From 50123887ba0f33cf47520bee7c419d68742af2d1 Mon Sep 17 00:00:00 2001 From: Qt by Nokia Date: Wed, 27 Apr 2011 12:05:43 +0200 Subject: [PATCH 1/1] Initial import from the monolithic Qt. This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12 --- 3rdparty/clucene/APACHE.license | 201 + 3rdparty/clucene/AUTHORS | 22 + 3rdparty/clucene/COPYING | 30 + 3rdparty/clucene/ChangeLog | 0 3rdparty/clucene/LGPL.license | 475 + 3rdparty/clucene/README | 92 + 3rdparty/clucene/src/CLucene.h | 38 + 3rdparty/clucene/src/CLucene/CLBackwards.h | 87 + 3rdparty/clucene/src/CLucene/CLConfig.h | 304 + 3rdparty/clucene/src/CLucene/CLMonolithic.cpp | 115 + 3rdparty/clucene/src/CLucene/LuceneThreads.h | 72 + 3rdparty/clucene/src/CLucene/StdHeader.cpp | 134 + 3rdparty/clucene/src/CLucene/StdHeader.h | 501 + .../src/CLucene/analysis/AnalysisHeader.cpp | 200 + .../clucene/src/CLucene/analysis/AnalysisHeader.h | 234 + .../clucene/src/CLucene/analysis/Analyzers.cpp | 389 + 3rdparty/clucene/src/CLucene/analysis/Analyzers.h | 309 + .../CLucene/analysis/standard/StandardAnalyzer.cpp | 46 + .../CLucene/analysis/standard/StandardAnalyzer.h | 47 + .../CLucene/analysis/standard/StandardFilter.cpp | 58 + .../src/CLucene/analysis/standard/StandardFilter.h | 37 + .../analysis/standard/StandardTokenizer.cpp | 446 + .../CLucene/analysis/standard/StandardTokenizer.h | 88 + .../analysis/standard/StandardTokenizerConstants.h | 30 + 3rdparty/clucene/src/CLucene/config/CompilerAcc.h | 166 + 3rdparty/clucene/src/CLucene/config/CompilerBcb.h | 68 + 3rdparty/clucene/src/CLucene/config/CompilerGcc.h | 175 + 3rdparty/clucene/src/CLucene/config/CompilerMsvc.h | 136 + 3rdparty/clucene/src/CLucene/config/PlatformMac.h | 19 + 3rdparty/clucene/src/CLucene/config/PlatformUnix.h | 12 + .../clucene/src/CLucene/config/PlatformWin32.h | 11 + 3rdparty/clucene/src/CLucene/config/compiler.h | 259 + 3rdparty/clucene/src/CLucene/config/define_std.h | 113 + .../clucene/src/CLucene/config/gunichartables.cpp | 386 + .../clucene/src/CLucene/config/gunichartables.h | 11264 +++++++++++++++++++ 3rdparty/clucene/src/CLucene/config/repl_lltot.cpp | 47 + 3rdparty/clucene/src/CLucene/config/repl_tchar.h | 126 + .../clucene/src/CLucene/config/repl_tcscasecmp.cpp | 21 + .../clucene/src/CLucene/config/repl_tcslwr.cpp | 15 + .../clucene/src/CLucene/config/repl_tcstod.cpp | 23 + .../clucene/src/CLucene/config/repl_tcstoll.cpp | 46 + .../clucene/src/CLucene/config/repl_tprintf.cpp | 149 + 3rdparty/clucene/src/CLucene/config/repl_wchar.h | 121 + .../clucene/src/CLucene/config/threadCSection.h | 71 + .../clucene/src/CLucene/config/threadPthread.h | 59 + 3rdparty/clucene/src/CLucene/config/threads.cpp | 162 + 3rdparty/clucene/src/CLucene/config/utf8.cpp | 237 + 3rdparty/clucene/src/CLucene/debug/condition.cpp | 80 + 3rdparty/clucene/src/CLucene/debug/condition.h | 64 + 3rdparty/clucene/src/CLucene/debug/error.cpp | 73 + 3rdparty/clucene/src/CLucene/debug/error.h | 74 + 3rdparty/clucene/src/CLucene/debug/lucenebase.h | 75 + 3rdparty/clucene/src/CLucene/debug/mem.h | 130 + 3rdparty/clucene/src/CLucene/debug/memtracking.cpp | 371 + .../clucene/src/CLucene/document/DateField.cpp | 60 + 3rdparty/clucene/src/CLucene/document/DateField.h | 64 + 3rdparty/clucene/src/CLucene/document/Document.cpp | 237 + 3rdparty/clucene/src/CLucene/document/Document.h | 158 + 3rdparty/clucene/src/CLucene/document/Field.cpp | 315 + 3rdparty/clucene/src/CLucene/document/Field.h | 261 + .../clucene/src/CLucene/index/CompoundFile.cpp | 380 + 3rdparty/clucene/src/CLucene/index/CompoundFile.h | 219 + .../clucene/src/CLucene/index/DocumentWriter.cpp | 571 + .../clucene/src/CLucene/index/DocumentWriter.h | 107 + 3rdparty/clucene/src/CLucene/index/FieldInfo.h | 16 + 3rdparty/clucene/src/CLucene/index/FieldInfos.cpp | 236 + 3rdparty/clucene/src/CLucene/index/FieldInfos.h | 171 + .../clucene/src/CLucene/index/FieldsReader.cpp | 231 + 3rdparty/clucene/src/CLucene/index/FieldsReader.h | 60 + .../clucene/src/CLucene/index/FieldsWriter.cpp | 186 + 3rdparty/clucene/src/CLucene/index/FieldsWriter.h | 49 + .../clucene/src/CLucene/index/IndexModifier.cpp | 254 + 3rdparty/clucene/src/CLucene/index/IndexModifier.h | 316 + 3rdparty/clucene/src/CLucene/index/IndexReader.cpp | 668 ++ 3rdparty/clucene/src/CLucene/index/IndexReader.h | 485 + 3rdparty/clucene/src/CLucene/index/IndexWriter.cpp | 697 ++ 3rdparty/clucene/src/CLucene/index/IndexWriter.h | 425 + 3rdparty/clucene/src/CLucene/index/MultiReader.cpp | 722 ++ 3rdparty/clucene/src/CLucene/index/MultiReader.h | 202 + 3rdparty/clucene/src/CLucene/index/SegmentHeader.h | 314 + .../clucene/src/CLucene/index/SegmentInfos.cpp | 259 + 3rdparty/clucene/src/CLucene/index/SegmentInfos.h | 128 + .../clucene/src/CLucene/index/SegmentMergeInfo.cpp | 104 + .../clucene/src/CLucene/index/SegmentMergeInfo.h | 47 + .../src/CLucene/index/SegmentMergeQueue.cpp | 74 + .../clucene/src/CLucene/index/SegmentMergeQueue.h | 38 + .../clucene/src/CLucene/index/SegmentMerger.cpp | 723 ++ 3rdparty/clucene/src/CLucene/index/SegmentMerger.h | 169 + .../clucene/src/CLucene/index/SegmentReader.cpp | 816 ++ .../clucene/src/CLucene/index/SegmentTermDocs.cpp | 216 + .../clucene/src/CLucene/index/SegmentTermEnum.cpp | 389 + .../clucene/src/CLucene/index/SegmentTermEnum.h | 138 + .../src/CLucene/index/SegmentTermPositions.cpp | 101 + .../src/CLucene/index/SegmentTermVector.cpp | 188 + 3rdparty/clucene/src/CLucene/index/Term.cpp | 182 + 3rdparty/clucene/src/CLucene/index/Term.h | 146 + 3rdparty/clucene/src/CLucene/index/TermInfo.cpp | 53 + 3rdparty/clucene/src/CLucene/index/TermInfo.h | 61 + .../clucene/src/CLucene/index/TermInfosReader.cpp | 443 + .../clucene/src/CLucene/index/TermInfosReader.h | 106 + .../clucene/src/CLucene/index/TermInfosWriter.cpp | 185 + .../clucene/src/CLucene/index/TermInfosWriter.h | 89 + 3rdparty/clucene/src/CLucene/index/TermVector.h | 418 + .../clucene/src/CLucene/index/TermVectorReader.cpp | 393 + .../clucene/src/CLucene/index/TermVectorWriter.cpp | 349 + 3rdparty/clucene/src/CLucene/index/Terms.h | 174 + 3rdparty/clucene/src/CLucene/queryParser/Lexer.cpp | 371 + 3rdparty/clucene/src/CLucene/queryParser/Lexer.h | 67 + .../CLucene/queryParser/MultiFieldQueryParser.cpp | 215 + .../CLucene/queryParser/MultiFieldQueryParser.h | 136 + .../src/CLucene/queryParser/QueryParser.cpp | 509 + .../clucene/src/CLucene/queryParser/QueryParser.h | 165 + .../src/CLucene/queryParser/QueryParserBase.cpp | 369 + .../src/CLucene/queryParser/QueryParserBase.h | 204 + .../clucene/src/CLucene/queryParser/QueryToken.cpp | 73 + .../clucene/src/CLucene/queryParser/QueryToken.h | 76 + .../clucene/src/CLucene/queryParser/TokenList.cpp | 79 + .../clucene/src/CLucene/queryParser/TokenList.h | 38 + .../clucene/src/CLucene/search/BooleanClause.h | 90 + .../clucene/src/CLucene/search/BooleanQuery.cpp | 363 + 3rdparty/clucene/src/CLucene/search/BooleanQuery.h | 126 + .../clucene/src/CLucene/search/BooleanScorer.cpp | 248 + .../clucene/src/CLucene/search/BooleanScorer.h | 99 + .../src/CLucene/search/CachingWrapperFilter.cpp | 86 + .../src/CLucene/search/CachingWrapperFilter.h | 80 + .../clucene/src/CLucene/search/ChainedFilter.cpp | 213 + .../clucene/src/CLucene/search/ChainedFilter.h | 86 + 3rdparty/clucene/src/CLucene/search/Compare.h | 161 + .../src/CLucene/search/ConjunctionScorer.cpp | 144 + .../clucene/src/CLucene/search/ConjunctionScorer.h | 50 + 3rdparty/clucene/src/CLucene/search/DateFilter.cpp | 93 + 3rdparty/clucene/src/CLucene/search/DateFilter.h | 59 + .../src/CLucene/search/ExactPhraseScorer.cpp | 85 + .../clucene/src/CLucene/search/ExactPhraseScorer.h | 31 + .../clucene/src/CLucene/search/Explanation.cpp | 133 + 3rdparty/clucene/src/CLucene/search/Explanation.h | 66 + 3rdparty/clucene/src/CLucene/search/FieldCache.cpp | 55 + 3rdparty/clucene/src/CLucene/search/FieldCache.h | 182 + .../clucene/src/CLucene/search/FieldCacheImpl.cpp | 529 + .../clucene/src/CLucene/search/FieldCacheImpl.h | 144 + 3rdparty/clucene/src/CLucene/search/FieldDoc.h | 70 + .../src/CLucene/search/FieldDocSortedHitQueue.cpp | 171 + .../src/CLucene/search/FieldDocSortedHitQueue.h | 159 + .../src/CLucene/search/FieldSortedHitQueue.cpp | 212 + .../src/CLucene/search/FieldSortedHitQueue.h | 216 + 3rdparty/clucene/src/CLucene/search/Filter.h | 46 + .../src/CLucene/search/FilteredTermEnum.cpp | 136 + .../clucene/src/CLucene/search/FilteredTermEnum.h | 61 + 3rdparty/clucene/src/CLucene/search/FuzzyQuery.cpp | 357 + 3rdparty/clucene/src/CLucene/search/FuzzyQuery.h | 156 + 3rdparty/clucene/src/CLucene/search/HitQueue.cpp | 107 + 3rdparty/clucene/src/CLucene/search/HitQueue.h | 55 + 3rdparty/clucene/src/CLucene/search/Hits.cpp | 174 + .../clucene/src/CLucene/search/IndexSearcher.cpp | 362 + .../clucene/src/CLucene/search/IndexSearcher.h | 73 + .../clucene/src/CLucene/search/MultiSearcher.cpp | 227 + .../clucene/src/CLucene/search/MultiSearcher.h | 95 + .../clucene/src/CLucene/search/MultiTermQuery.cpp | 98 + .../clucene/src/CLucene/search/MultiTermQuery.h | 62 + .../clucene/src/CLucene/search/PhrasePositions.cpp | 116 + .../clucene/src/CLucene/search/PhrasePositions.h | 41 + .../clucene/src/CLucene/search/PhraseQuery.cpp | 463 + 3rdparty/clucene/src/CLucene/search/PhraseQuery.h | 127 + 3rdparty/clucene/src/CLucene/search/PhraseQueue.h | 36 + .../clucene/src/CLucene/search/PhraseScorer.cpp | 225 + 3rdparty/clucene/src/CLucene/search/PhraseScorer.h | 65 + .../clucene/src/CLucene/search/PrefixQuery.cpp | 273 + 3rdparty/clucene/src/CLucene/search/PrefixQuery.h | 75 + .../clucene/src/CLucene/search/QueryFilter.cpp | 73 + 3rdparty/clucene/src/CLucene/search/QueryFilter.h | 44 + .../clucene/src/CLucene/search/RangeFilter.cpp | 150 + 3rdparty/clucene/src/CLucene/search/RangeFilter.h | 51 + 3rdparty/clucene/src/CLucene/search/RangeQuery.cpp | 204 + 3rdparty/clucene/src/CLucene/search/RangeQuery.h | 71 + 3rdparty/clucene/src/CLucene/search/Scorer.h | 80 + .../clucene/src/CLucene/search/SearchHeader.cpp | 141 + 3rdparty/clucene/src/CLucene/search/SearchHeader.h | 456 + 3rdparty/clucene/src/CLucene/search/Similarity.cpp | 233 + 3rdparty/clucene/src/CLucene/search/Similarity.h | 268 + .../src/CLucene/search/SloppyPhraseScorer.cpp | 106 + .../src/CLucene/search/SloppyPhraseScorer.h | 34 + 3rdparty/clucene/src/CLucene/search/Sort.cpp | 345 + 3rdparty/clucene/src/CLucene/search/Sort.h | 356 + 3rdparty/clucene/src/CLucene/search/TermQuery.cpp | 213 + 3rdparty/clucene/src/CLucene/search/TermQuery.h | 81 + 3rdparty/clucene/src/CLucene/search/TermScorer.cpp | 120 + 3rdparty/clucene/src/CLucene/search/TermScorer.h | 53 + .../clucene/src/CLucene/search/WildcardQuery.cpp | 147 + .../clucene/src/CLucene/search/WildcardQuery.h | 69 + .../src/CLucene/search/WildcardTermEnum.cpp | 150 + .../clucene/src/CLucene/search/WildcardTermEnum.h | 67 + 3rdparty/clucene/src/CLucene/store/Directory.h | 108 + 3rdparty/clucene/src/CLucene/store/FSDirectory.cpp | 662 ++ 3rdparty/clucene/src/CLucene/store/FSDirectory.h | 216 + 3rdparty/clucene/src/CLucene/store/IndexInput.cpp | 233 + 3rdparty/clucene/src/CLucene/store/IndexInput.h | 190 + 3rdparty/clucene/src/CLucene/store/IndexOutput.cpp | 163 + 3rdparty/clucene/src/CLucene/store/IndexOutput.h | 152 + 3rdparty/clucene/src/CLucene/store/InputStream.h | 21 + 3rdparty/clucene/src/CLucene/store/Lock.cpp | 27 + 3rdparty/clucene/src/CLucene/store/Lock.h | 106 + 3rdparty/clucene/src/CLucene/store/MMapInput.cpp | 203 + 3rdparty/clucene/src/CLucene/store/OutputStream.h | 23 + .../clucene/src/CLucene/store/RAMDirectory.cpp | 446 + 3rdparty/clucene/src/CLucene/store/RAMDirectory.h | 195 + .../CLucene/store/TransactionalRAMDirectory.cpp | 212 + .../src/CLucene/store/TransactionalRAMDirectory.h | 76 + 3rdparty/clucene/src/CLucene/util/Arrays.h | 164 + 3rdparty/clucene/src/CLucene/util/BitSet.cpp | 119 + 3rdparty/clucene/src/CLucene/util/BitSet.h | 62 + 3rdparty/clucene/src/CLucene/util/Equators.cpp | 180 + 3rdparty/clucene/src/CLucene/util/Equators.h | 274 + .../clucene/src/CLucene/util/FastCharStream.cpp | 107 + 3rdparty/clucene/src/CLucene/util/FastCharStream.h | 55 + 3rdparty/clucene/src/CLucene/util/Misc.cpp | 295 + 3rdparty/clucene/src/CLucene/util/Misc.h | 75 + 3rdparty/clucene/src/CLucene/util/PriorityQueue.h | 177 + 3rdparty/clucene/src/CLucene/util/Reader.cpp | 186 + 3rdparty/clucene/src/CLucene/util/Reader.h | 138 + 3rdparty/clucene/src/CLucene/util/StringBuffer.cpp | 335 + 3rdparty/clucene/src/CLucene/util/StringBuffer.h | 77 + 3rdparty/clucene/src/CLucene/util/StringIntern.cpp | 158 + 3rdparty/clucene/src/CLucene/util/StringIntern.h | 61 + 3rdparty/clucene/src/CLucene/util/ThreadLocal.cpp | 55 + 3rdparty/clucene/src/CLucene/util/ThreadLocal.h | 143 + 3rdparty/clucene/src/CLucene/util/VoidList.h | 175 + 3rdparty/clucene/src/CLucene/util/VoidMap.h | 270 + 3rdparty/clucene/src/CLucene/util/bufferedstream.h | 157 + 3rdparty/clucene/src/CLucene/util/dirent.cpp | 221 + 3rdparty/clucene/src/CLucene/util/dirent.h | 105 + .../clucene/src/CLucene/util/fileinputstream.cpp | 103 + .../clucene/src/CLucene/util/fileinputstream.h | 38 + .../clucene/src/CLucene/util/inputstreambuffer.h | 126 + 3rdparty/clucene/src/CLucene/util/jstreamsconfig.h | 9 + 3rdparty/clucene/src/CLucene/util/streambase.h | 148 + 3rdparty/clucene/src/CLucene/util/stringreader.h | 124 + 3rdparty/clucene/src/CLucene/util/subinputstream.h | 141 + demos/arthurplugin/arthur_plugin.qrc | 7 + demos/arthurplugin/arthurplugin.pro | 54 + demos/arthurplugin/bg1.jpg | Bin 0 -> 23771 bytes demos/arthurplugin/flower.jpg | Bin 0 -> 49616 bytes demos/arthurplugin/flower_alpha.jpg | Bin 0 -> 67326 bytes demos/arthurplugin/plugin.cpp | 296 + demos/shared/arthurstyle.cpp | 452 + demos/shared/arthurstyle.h | 79 + demos/shared/arthurwidgets.cpp | 371 + demos/shared/arthurwidgets.h | 137 + demos/shared/hoverpoints.cpp | 415 + demos/shared/hoverpoints.h | 162 + demos/shared/images/bg_pattern.png | Bin 0 -> 104 bytes demos/shared/images/button_normal_cap_left.png | Bin 0 -> 654 bytes demos/shared/images/button_normal_cap_right.png | Bin 0 -> 674 bytes demos/shared/images/button_normal_stretch.png | Bin 0 -> 185 bytes demos/shared/images/button_pressed_cap_left.png | Bin 0 -> 710 bytes demos/shared/images/button_pressed_cap_right.png | Bin 0 -> 785 bytes demos/shared/images/button_pressed_stretch.png | Bin 0 -> 217 bytes demos/shared/images/curve_thing_edit-6.png | Bin 0 -> 58097 bytes demos/shared/images/frame_bottom.png | Bin 0 -> 166 bytes demos/shared/images/frame_bottomleft.png | Bin 0 -> 602 bytes demos/shared/images/frame_bottomright.png | Bin 0 -> 553 bytes demos/shared/images/frame_left.png | Bin 0 -> 182 bytes demos/shared/images/frame_right.png | Bin 0 -> 175 bytes demos/shared/images/frame_top.png | Bin 0 -> 188 bytes demos/shared/images/frame_topleft.png | Bin 0 -> 801 bytes demos/shared/images/frame_topright.png | Bin 0 -> 851 bytes demos/shared/images/groupframe_bottom_left.png | Bin 0 -> 397 bytes demos/shared/images/groupframe_bottom_right.png | Bin 0 -> 383 bytes demos/shared/images/groupframe_bottom_stretch.png | Bin 0 -> 141 bytes demos/shared/images/groupframe_left_stretch.png | Bin 0 -> 132 bytes demos/shared/images/groupframe_right_stretch.png | Bin 0 -> 113 bytes demos/shared/images/groupframe_top_stretch.png | Bin 0 -> 115 bytes demos/shared/images/groupframe_topleft.png | Bin 0 -> 412 bytes demos/shared/images/groupframe_topright.png | Bin 0 -> 449 bytes demos/shared/images/line_dash_dot.png | Bin 0 -> 151 bytes demos/shared/images/line_dash_dot_dot.png | Bin 0 -> 155 bytes demos/shared/images/line_dashed.png | Bin 0 -> 121 bytes demos/shared/images/line_dotted.png | Bin 0 -> 116 bytes demos/shared/images/line_solid.png | Bin 0 -> 110 bytes demos/shared/images/radiobutton-off.png | Bin 0 -> 442 bytes demos/shared/images/radiobutton-on.png | Bin 0 -> 474 bytes demos/shared/images/radiobutton_off.png | Bin 0 -> 442 bytes demos/shared/images/radiobutton_on.png | Bin 0 -> 499 bytes demos/shared/images/slider_bar.png | Bin 0 -> 748 bytes demos/shared/images/slider_thumb_off.png | Bin 0 -> 823 bytes demos/shared/images/slider_thumb_on.png | Bin 0 -> 798 bytes demos/shared/images/title_cap_left.png | Bin 0 -> 179 bytes demos/shared/images/title_cap_right.png | Bin 0 -> 184 bytes demos/shared/images/title_stretch.png | Bin 0 -> 106 bytes demos/shared/shared.pri | 21 + demos/shared/shared.pro | 38 + demos/shared/shared.qrc | 39 + examples/designer/README | 37 + .../calculatorbuilder/calculatorbuilder.pro | 16 + .../calculatorbuilder/calculatorbuilder.qrc | 5 + .../designer/calculatorbuilder/calculatorform.cpp | 91 + .../designer/calculatorbuilder/calculatorform.h | 70 + .../designer/calculatorbuilder/calculatorform.ui | 303 + examples/designer/calculatorbuilder/main.cpp | 53 + .../designer/calculatorform/calculatorform.cpp | 65 + examples/designer/calculatorform/calculatorform.h | 65 + .../designer/calculatorform/calculatorform.pro | 15 + examples/designer/calculatorform/calculatorform.ui | 284 + examples/designer/calculatorform/main.cpp | 52 + .../containerextension/containerextension.pro | 28 + .../containerextension/multipagewidget.cpp | 130 + .../designer/containerextension/multipagewidget.h | 87 + .../multipagewidgetcontainerextension.cpp | 100 + .../multipagewidgetcontainerextension.h | 74 + .../multipagewidgetextensionfactory.cpp | 64 + .../multipagewidgetextensionfactory.h | 63 + .../containerextension/multipagewidgetplugin.cpp | 196 + .../containerextension/multipagewidgetplugin.h | 80 + .../designer/customwidgetplugin/analogclock.cpp | 110 + examples/designer/customwidgetplugin/analogclock.h | 58 + .../customwidgetplugin/customwidgetplugin.cpp | 155 + .../customwidgetplugin/customwidgetplugin.h | 72 + .../customwidgetplugin/customwidgetplugin.pro | 23 + examples/designer/designer.pro | 21 + .../taskmenuextension/taskmenuextension.pro | 27 + examples/designer/taskmenuextension/tictactoe.cpp | 175 + examples/designer/taskmenuextension/tictactoe.h | 82 + .../designer/taskmenuextension/tictactoedialog.cpp | 98 + .../designer/taskmenuextension/tictactoedialog.h | 72 + .../designer/taskmenuextension/tictactoeplugin.cpp | 141 + .../designer/taskmenuextension/tictactoeplugin.h | 77 + .../taskmenuextension/tictactoetaskmenu.cpp | 103 + .../designer/taskmenuextension/tictactoetaskmenu.h | 87 + examples/designer/worldtimeclockbuilder/form.ui | 162 + examples/designer/worldtimeclockbuilder/main.cpp | 69 + .../worldtimeclockbuilder.pro | 13 + .../worldtimeclockbuilder.qrc | 5 + .../worldtimeclockplugin/worldtimeclock.cpp | 121 + .../designer/worldtimeclockplugin/worldtimeclock.h | 72 + .../worldtimeclockplugin/worldtimeclockplugin.cpp | 123 + .../worldtimeclockplugin/worldtimeclockplugin.h | 73 + .../worldtimeclockplugin/worldtimeclockplugin.pro | 23 + examples/examples.pro | 2 + examples/help/README | 38 + .../contextsensitivehelp/contextsensitivehelp.pro | 20 + examples/help/contextsensitivehelp/doc/amount.html | 11 + examples/help/contextsensitivehelp/doc/filter.html | 12 + examples/help/contextsensitivehelp/doc/plants.html | 44 + examples/help/contextsensitivehelp/doc/rain.html | 11 + examples/help/contextsensitivehelp/doc/source.html | 33 + .../help/contextsensitivehelp/doc/temperature.html | 13 + examples/help/contextsensitivehelp/doc/time.html | 11 + .../contextsensitivehelp/doc/wateringmachine.qch | Bin 0 -> 25600 bytes .../contextsensitivehelp/doc/wateringmachine.qhc | Bin 0 -> 8192 bytes .../contextsensitivehelp/doc/wateringmachine.qhcp | 14 + .../contextsensitivehelp/doc/wateringmachine.qhp | 25 + examples/help/contextsensitivehelp/helpbrowser.cpp | 80 + examples/help/contextsensitivehelp/helpbrowser.h | 64 + examples/help/contextsensitivehelp/main.cpp | 50 + .../contextsensitivehelp/wateringconfigdialog.cpp | 68 + .../contextsensitivehelp/wateringconfigdialog.h | 61 + .../contextsensitivehelp/wateringconfigdialog.ui | 446 + examples/help/help.pro | 13 + examples/help/remotecontrol/enter.png | Bin 0 -> 315 bytes examples/help/remotecontrol/main.cpp | 53 + examples/help/remotecontrol/remotecontrol.cpp | 174 + examples/help/remotecontrol/remotecontrol.h | 78 + examples/help/remotecontrol/remotecontrol.pro | 15 + examples/help/remotecontrol/remotecontrol.qrc | 5 + examples/help/remotecontrol/remotecontrol.ui | 228 + examples/help/simpletextviewer/assistant.cpp | 109 + examples/help/simpletextviewer/assistant.h | 62 + .../help/simpletextviewer/documentation/about.txt | 9 + .../simpletextviewer/documentation/browse.html | 34 + .../simpletextviewer/documentation/filedialog.html | 48 + .../simpletextviewer/documentation/findfile.html | 32 + .../documentation/images/browse.png | Bin 0 -> 21553 bytes .../documentation/images/fadedfilemenu.png | Bin 0 -> 9589 bytes .../documentation/images/filedialog.png | Bin 0 -> 12318 bytes .../documentation/images/handbook.png | Bin 0 -> 1060 bytes .../simpletextviewer/documentation/images/icon.png | Bin 0 -> 5513 bytes .../documentation/images/mainwindow.png | Bin 0 -> 12769 bytes .../simpletextviewer/documentation/images/open.png | Bin 0 -> 11697 bytes .../documentation/images/wildcard.png | Bin 0 -> 11266 bytes .../help/simpletextviewer/documentation/index.html | 41 + .../help/simpletextviewer/documentation/intro.html | 28 + .../simpletextviewer/documentation/openfile.html | 36 + .../documentation/simpletextviewer.qch | Bin 0 -> 108544 bytes .../documentation/simpletextviewer.qhc | Bin 0 -> 18432 bytes .../documentation/simpletextviewer.qhcp | 30 + .../documentation/simpletextviewer.qhp | 49 + .../documentation/wildcardmatching.html | 57 + examples/help/simpletextviewer/findfiledialog.cpp | 221 + examples/help/simpletextviewer/findfiledialog.h | 98 + examples/help/simpletextviewer/main.cpp | 51 + examples/help/simpletextviewer/mainwindow.cpp | 146 + examples/help/simpletextviewer/mainwindow.h | 83 + .../help/simpletextviewer/simpletextviewer.pro | 18 + examples/help/simpletextviewer/textedit.cpp | 74 + examples/help/simpletextviewer/textedit.h | 60 + qttools.pro | 12 + src/assistant/assistant.pro | 6 + .../lib/fulltextsearch/fulltextsearch.pri | 161 + .../lib/fulltextsearch/fulltextsearch.pro | 50 + src/assistant/lib/fulltextsearch/license.txt | 503 + src/assistant/lib/fulltextsearch/qanalyzer.cpp | 219 + src/assistant/lib/fulltextsearch/qanalyzer_p.h | 152 + .../lib/fulltextsearch/qclucene-config_p.h | 557 + .../lib/fulltextsearch/qclucene_global_p.h | 134 + src/assistant/lib/fulltextsearch/qdocument.cpp | 180 + src/assistant/lib/fulltextsearch/qdocument_p.h | 100 + src/assistant/lib/fulltextsearch/qfield.cpp | 171 + src/assistant/lib/fulltextsearch/qfield_p.h | 119 + src/assistant/lib/fulltextsearch/qfilter.cpp | 57 + src/assistant/lib/fulltextsearch/qfilter_p.h | 75 + src/assistant/lib/fulltextsearch/qhits.cpp | 94 + src/assistant/lib/fulltextsearch/qhits_p.h | 86 + src/assistant/lib/fulltextsearch/qindexreader.cpp | 169 + src/assistant/lib/fulltextsearch/qindexreader_p.h | 115 + src/assistant/lib/fulltextsearch/qindexwriter.cpp | 191 + src/assistant/lib/fulltextsearch/qindexwriter_p.h | 124 + src/assistant/lib/fulltextsearch/qquery.cpp | 358 + src/assistant/lib/fulltextsearch/qquery_p.h | 188 + src/assistant/lib/fulltextsearch/qqueryparser.cpp | 176 + src/assistant/lib/fulltextsearch/qqueryparser_p.h | 109 + src/assistant/lib/fulltextsearch/qreader.cpp | 101 + src/assistant/lib/fulltextsearch/qreader_p.h | 104 + src/assistant/lib/fulltextsearch/qsearchable.cpp | 203 + src/assistant/lib/fulltextsearch/qsearchable_p.h | 135 + src/assistant/lib/fulltextsearch/qsort.cpp | 97 + src/assistant/lib/fulltextsearch/qsort_p.h | 84 + src/assistant/lib/fulltextsearch/qterm.cpp | 134 + src/assistant/lib/fulltextsearch/qterm_p.h | 100 + src/assistant/lib/fulltextsearch/qtoken.cpp | 150 + src/assistant/lib/fulltextsearch/qtoken_p.h | 112 + src/assistant/lib/fulltextsearch/qtokenizer.cpp | 117 + src/assistant/lib/fulltextsearch/qtokenizer_p.h | 97 + src/assistant/lib/fulltextsearch/qtokenstream.cpp | 67 + src/assistant/lib/fulltextsearch/qtokenstream_p.h | 95 + src/assistant/lib/helpsystem.qrc | 8 + src/assistant/lib/images/1leftarrow.png | Bin 0 -> 669 bytes src/assistant/lib/images/1rightarrow.png | Bin 0 -> 706 bytes src/assistant/lib/images/3leftarrow.png | Bin 0 -> 832 bytes src/assistant/lib/images/3rightarrow.png | Bin 0 -> 820 bytes src/assistant/lib/lib.pro | 71 + src/assistant/lib/qclucenefieldnames.cpp | 57 + src/assistant/lib/qclucenefieldnames_p.h | 63 + src/assistant/lib/qhelp_global.cpp | 114 + src/assistant/lib/qhelp_global.h | 78 + src/assistant/lib/qhelpcollectionhandler.cpp | 603 + src/assistant/lib/qhelpcollectionhandler_p.h | 124 + src/assistant/lib/qhelpcontentwidget.cpp | 586 + src/assistant/lib/qhelpcontentwidget.h | 146 + src/assistant/lib/qhelpdatainterface.cpp | 273 + src/assistant/lib/qhelpdatainterface_p.h | 155 + src/assistant/lib/qhelpdbreader.cpp | 583 + src/assistant/lib/qhelpdbreader_p.h | 128 + src/assistant/lib/qhelpengine.cpp | 213 + src/assistant/lib/qhelpengine.h | 84 + src/assistant/lib/qhelpengine_p.h | 144 + src/assistant/lib/qhelpenginecore.cpp | 737 ++ src/assistant/lib/qhelpenginecore.h | 136 + src/assistant/lib/qhelpgenerator.cpp | 909 ++ src/assistant/lib/qhelpgenerator_p.h | 118 + src/assistant/lib/qhelpindexwidget.cpp | 444 + src/assistant/lib/qhelpindexwidget.h | 114 + src/assistant/lib/qhelpprojectdata.cpp | 450 + src/assistant/lib/qhelpprojectdata_p.h | 89 + src/assistant/lib/qhelpsearchengine.cpp | 450 + src/assistant/lib/qhelpsearchengine.h | 125 + src/assistant/lib/qhelpsearchindex_default.cpp | 60 + src/assistant/lib/qhelpsearchindex_default_p.h | 149 + src/assistant/lib/qhelpsearchindexreader.cpp | 104 + .../lib/qhelpsearchindexreader_clucene.cpp | 481 + .../lib/qhelpsearchindexreader_clucene_p.h | 114 + .../lib/qhelpsearchindexreader_default.cpp | 612 + .../lib/qhelpsearchindexreader_default_p.h | 131 + src/assistant/lib/qhelpsearchindexreader_p.h | 106 + .../lib/qhelpsearchindexwriter_clucene.cpp | 898 ++ .../lib/qhelpsearchindexwriter_clucene_p.h | 124 + .../lib/qhelpsearchindexwriter_default.cpp | 384 + .../lib/qhelpsearchindexwriter_default_p.h | 130 + src/assistant/lib/qhelpsearchquerywidget.cpp | 587 + src/assistant/lib/qhelpsearchquerywidget.h | 92 + src/assistant/lib/qhelpsearchresultwidget.cpp | 447 + src/assistant/lib/qhelpsearchresultwidget.h | 85 + src/assistant/tools/assistant/Info_mac.plist | 18 + src/assistant/tools/assistant/aboutdialog.cpp | 184 + src/assistant/tools/assistant/aboutdialog.h | 91 + src/assistant/tools/assistant/assistant.icns | Bin 0 -> 162568 bytes src/assistant/tools/assistant/assistant.ico | Bin 0 -> 355574 bytes src/assistant/tools/assistant/assistant.pro | 118 + src/assistant/tools/assistant/assistant.qch | Bin 0 -> 364544 bytes src/assistant/tools/assistant/assistant.qrc | 5 + src/assistant/tools/assistant/assistant.rc | 32 + src/assistant/tools/assistant/assistant_images.qrc | 37 + src/assistant/tools/assistant/bookmarkdialog.cpp | 237 + src/assistant/tools/assistant/bookmarkdialog.h | 89 + src/assistant/tools/assistant/bookmarkdialog.ui | 156 + .../tools/assistant/bookmarkfiltermodel.cpp | 321 + .../tools/assistant/bookmarkfiltermodel.h | 118 + src/assistant/tools/assistant/bookmarkitem.cpp | 184 + src/assistant/tools/assistant/bookmarkitem.h | 91 + src/assistant/tools/assistant/bookmarkmanager.cpp | 559 + src/assistant/tools/assistant/bookmarkmanager.h | 160 + .../tools/assistant/bookmarkmanagerwidget.cpp | 321 + .../tools/assistant/bookmarkmanagerwidget.h | 103 + .../tools/assistant/bookmarkmanagerwidget.ui | 137 + src/assistant/tools/assistant/bookmarkmodel.cpp | 461 + src/assistant/tools/assistant/bookmarkmodel.h | 117 + src/assistant/tools/assistant/bookmarkwidget.ui | 85 + src/assistant/tools/assistant/centralwidget.cpp | 636 ++ src/assistant/tools/assistant/centralwidget.h | 172 + src/assistant/tools/assistant/cmdlineparser.cpp | 376 + src/assistant/tools/assistant/cmdlineparser.h | 117 + src/assistant/tools/assistant/contentwindow.cpp | 204 + src/assistant/tools/assistant/contentwindow.h | 86 + src/assistant/tools/assistant/doc/HOWTO | 16 + src/assistant/tools/assistant/doc/assistant.qdoc | 461 + .../tools/assistant/doc/assistant.qdocconf | 16 + src/assistant/tools/assistant/doc/assistant.qhp | 22 + src/assistant/tools/assistant/doc/classic.css | 92 + .../doc/images/assistant-address-toolbar.png | Bin 0 -> 2899 bytes .../assistant/doc/images/assistant-assistant.png | Bin 0 -> 205326 bytes .../assistant/doc/images/assistant-dockwidgets.png | Bin 0 -> 50554 bytes .../assistant/doc/images/assistant-docwindow.png | Bin 0 -> 55582 bytes .../assistant/doc/images/assistant-examples.png | Bin 0 -> 9799 bytes .../doc/images/assistant-filter-toolbar.png | Bin 0 -> 1767 bytes .../images/assistant-preferences-documentation.png | Bin 0 -> 13417 bytes .../doc/images/assistant-preferences-filters.png | Bin 0 -> 15561 bytes .../doc/images/assistant-preferences-fonts.png | Bin 0 -> 13139 bytes .../doc/images/assistant-preferences-options.png | Bin 0 -> 14255 bytes .../assistant/doc/images/assistant-search.png | Bin 0 -> 59254 bytes .../assistant/doc/images/assistant-toolbar.png | Bin 0 -> 6532 bytes src/assistant/tools/assistant/filternamedialog.cpp | 77 + src/assistant/tools/assistant/filternamedialog.h | 67 + src/assistant/tools/assistant/filternamedialog.ui | 67 + src/assistant/tools/assistant/findwidget.cpp | 234 + src/assistant/tools/assistant/findwidget.h | 100 + src/assistant/tools/assistant/globalactions.cpp | 246 + src/assistant/tools/assistant/globalactions.h | 105 + .../tools/assistant/helpenginewrapper.cpp | 844 ++ src/assistant/tools/assistant/helpenginewrapper.h | 218 + src/assistant/tools/assistant/helpviewer.cpp | 221 + src/assistant/tools/assistant/helpviewer.h | 158 + src/assistant/tools/assistant/helpviewer_p.h | 123 + src/assistant/tools/assistant/helpviewer_qtb.cpp | 384 + src/assistant/tools/assistant/helpviewer_qwv.cpp | 495 + .../tools/assistant/images/assistant-128.png | Bin 0 -> 6448 bytes src/assistant/tools/assistant/images/assistant.png | Bin 0 -> 2034 bytes src/assistant/tools/assistant/images/bookmark.png | Bin 0 -> 1266 bytes .../tools/assistant/images/closebutton.png | Bin 0 -> 288 bytes .../tools/assistant/images/darkclosebutton.png | Bin 0 -> 319 bytes .../tools/assistant/images/mac/addtab.png | Bin 0 -> 469 bytes src/assistant/tools/assistant/images/mac/book.png | Bin 0 -> 1477 bytes .../tools/assistant/images/mac/closetab.png | Bin 0 -> 516 bytes .../tools/assistant/images/mac/editcopy.png | Bin 0 -> 1468 bytes src/assistant/tools/assistant/images/mac/find.png | Bin 0 -> 1836 bytes src/assistant/tools/assistant/images/mac/home.png | Bin 0 -> 1807 bytes src/assistant/tools/assistant/images/mac/next.png | Bin 0 -> 1310 bytes .../tools/assistant/images/mac/previous.png | Bin 0 -> 1080 bytes src/assistant/tools/assistant/images/mac/print.png | Bin 0 -> 2087 bytes .../tools/assistant/images/mac/resetzoom.png | Bin 0 -> 1567 bytes .../tools/assistant/images/mac/synctoc.png | Bin 0 -> 1838 bytes .../tools/assistant/images/mac/zoomin.png | Bin 0 -> 1696 bytes .../tools/assistant/images/mac/zoomout.png | Bin 0 -> 1662 bytes .../tools/assistant/images/trolltech-logo.png | Bin 0 -> 10096 bytes .../tools/assistant/images/win/addtab.png | Bin 0 -> 314 bytes src/assistant/tools/assistant/images/win/book.png | Bin 0 -> 1109 bytes .../tools/assistant/images/win/closetab.png | Bin 0 -> 375 bytes .../tools/assistant/images/win/editcopy.png | Bin 0 -> 1325 bytes src/assistant/tools/assistant/images/win/find.png | Bin 0 -> 1944 bytes src/assistant/tools/assistant/images/win/home.png | Bin 0 -> 1414 bytes src/assistant/tools/assistant/images/win/next.png | Bin 0 -> 1038 bytes .../tools/assistant/images/win/previous.png | Bin 0 -> 898 bytes src/assistant/tools/assistant/images/win/print.png | Bin 0 -> 1456 bytes .../tools/assistant/images/win/resetzoom.png | Bin 0 -> 1134 bytes .../tools/assistant/images/win/synctoc.png | Bin 0 -> 1235 bytes .../tools/assistant/images/win/zoomin.png | Bin 0 -> 1208 bytes .../tools/assistant/images/win/zoomout.png | Bin 0 -> 1226 bytes src/assistant/tools/assistant/images/wrap.png | Bin 0 -> 500 bytes src/assistant/tools/assistant/indexwindow.cpp | 231 + src/assistant/tools/assistant/indexwindow.h | 90 + src/assistant/tools/assistant/installdialog.cpp | 355 + src/assistant/tools/assistant/installdialog.h | 105 + src/assistant/tools/assistant/installdialog.ui | 118 + src/assistant/tools/assistant/main.cpp | 440 + src/assistant/tools/assistant/mainwindow.cpp | 1099 ++ src/assistant/tools/assistant/mainwindow.h | 172 + src/assistant/tools/assistant/openpagesmanager.cpp | 378 + src/assistant/tools/assistant/openpagesmanager.h | 115 + src/assistant/tools/assistant/openpagesmodel.cpp | 119 + src/assistant/tools/assistant/openpagesmodel.h | 76 + .../tools/assistant/openpagesswitcher.cpp | 194 + src/assistant/tools/assistant/openpagesswitcher.h | 85 + src/assistant/tools/assistant/openpageswidget.cpp | 237 + src/assistant/tools/assistant/openpageswidget.h | 92 + .../tools/assistant/preferencesdialog.cpp | 507 + src/assistant/tools/assistant/preferencesdialog.h | 110 + src/assistant/tools/assistant/preferencesdialog.ui | 400 + src/assistant/tools/assistant/qtdocinstaller.cpp | 128 + src/assistant/tools/assistant/qtdocinstaller.h | 84 + src/assistant/tools/assistant/remotecontrol.cpp | 388 + src/assistant/tools/assistant/remotecontrol.h | 96 + src/assistant/tools/assistant/remotecontrol_win.h | 68 + src/assistant/tools/assistant/searchwidget.cpp | 237 + src/assistant/tools/assistant/searchwidget.h | 90 + src/assistant/tools/assistant/topicchooser.cpp | 87 + src/assistant/tools/assistant/topicchooser.h | 73 + src/assistant/tools/assistant/topicchooser.ui | 116 + src/assistant/tools/assistant/tracer.h | 75 + src/assistant/tools/assistant/xbelsupport.cpp | 233 + src/assistant/tools/assistant/xbelsupport.h | 87 + src/assistant/tools/qcollectiongenerator/main.cpp | 615 + .../qcollectiongenerator/qcollectiongenerator.pro | 17 + src/assistant/tools/qhelpconverter/adpreader.cpp | 179 + src/assistant/tools/qhelpconverter/adpreader.h | 90 + .../tools/qhelpconverter/assistant-128.png | Bin 0 -> 6448 bytes src/assistant/tools/qhelpconverter/assistant.png | Bin 0 -> 2034 bytes .../tools/qhelpconverter/conversionwizard.cpp | 265 + .../tools/qhelpconverter/conversionwizard.h | 96 + .../tools/qhelpconverter/doc/filespage.html | 8 + .../tools/qhelpconverter/doc/filterpage.html | 13 + .../tools/qhelpconverter/doc/generalpage.html | 10 + .../tools/qhelpconverter/doc/identifierpage.html | 17 + .../tools/qhelpconverter/doc/inputpage.html | 7 + .../tools/qhelpconverter/doc/outputpage.html | 7 + .../tools/qhelpconverter/doc/pathpage.html | 8 + src/assistant/tools/qhelpconverter/filespage.cpp | 112 + src/assistant/tools/qhelpconverter/filespage.h | 73 + src/assistant/tools/qhelpconverter/filespage.ui | 79 + src/assistant/tools/qhelpconverter/filterpage.cpp | 147 + src/assistant/tools/qhelpconverter/filterpage.h | 79 + src/assistant/tools/qhelpconverter/filterpage.ui | 125 + src/assistant/tools/qhelpconverter/finishpage.cpp | 75 + src/assistant/tools/qhelpconverter/finishpage.h | 65 + src/assistant/tools/qhelpconverter/generalpage.cpp | 92 + src/assistant/tools/qhelpconverter/generalpage.h | 66 + src/assistant/tools/qhelpconverter/generalpage.ui | 69 + src/assistant/tools/qhelpconverter/helpwindow.cpp | 84 + src/assistant/tools/qhelpconverter/helpwindow.h | 65 + .../tools/qhelpconverter/identifierpage.cpp | 71 + .../tools/qhelpconverter/identifierpage.h | 66 + .../tools/qhelpconverter/identifierpage.ui | 132 + src/assistant/tools/qhelpconverter/inputpage.cpp | 103 + src/assistant/tools/qhelpconverter/inputpage.h | 71 + src/assistant/tools/qhelpconverter/inputpage.ui | 79 + src/assistant/tools/qhelpconverter/main.cpp | 77 + src/assistant/tools/qhelpconverter/outputpage.cpp | 110 + src/assistant/tools/qhelpconverter/outputpage.h | 71 + src/assistant/tools/qhelpconverter/outputpage.ui | 95 + src/assistant/tools/qhelpconverter/pathpage.cpp | 112 + src/assistant/tools/qhelpconverter/pathpage.h | 71 + src/assistant/tools/qhelpconverter/pathpage.ui | 114 + src/assistant/tools/qhelpconverter/qhcpwriter.cpp | 145 + src/assistant/tools/qhelpconverter/qhcpwriter.h | 70 + .../tools/qhelpconverter/qhelpconverter.pro | 47 + .../tools/qhelpconverter/qhelpconverter.qrc | 13 + src/assistant/tools/qhelpconverter/qhpwriter.cpp | 184 + src/assistant/tools/qhelpconverter/qhpwriter.h | 85 + src/assistant/tools/qhelpgenerator/main.cpp | 178 + .../tools/qhelpgenerator/qhelpgenerator.pro | 14 + .../tools/shared/collectionconfiguration.cpp | 327 + .../tools/shared/collectionconfiguration.h | 149 + src/assistant/tools/shared/helpgenerator.cpp | 84 + src/assistant/tools/shared/helpgenerator.h | 73 + src/assistant/tools/tools.pro | 8 + src/checksdk/README | 3 + src/checksdk/cesdkhandler.cpp | 132 + src/checksdk/cesdkhandler.h | 111 + src/checksdk/checksdk.pro | 36 + src/checksdk/main.cpp | 165 + src/designer/data/generate_header.xsl | 465 + src/designer/data/generate_impl.xsl | 1161 ++ src/designer/data/generate_shared.xsl | 331 + src/designer/data/ui3.xsd | 353 + src/designer/data/ui4.xsd | 589 + src/designer/designer.pro | 5 + .../src/components/buddyeditor/buddyeditor.cpp | 446 + .../src/components/buddyeditor/buddyeditor.h | 92 + .../src/components/buddyeditor/buddyeditor.pri | 16 + .../components/buddyeditor/buddyeditor_global.h | 57 + .../buddyeditor/buddyeditor_instance.cpp | 50 + .../components/buddyeditor/buddyeditor_plugin.cpp | 133 + .../components/buddyeditor/buddyeditor_plugin.h | 93 + .../components/buddyeditor/buddyeditor_tool.cpp | 111 + .../src/components/buddyeditor/buddyeditor_tool.h | 89 + src/designer/src/components/component.pri | 2 + src/designer/src/components/components.pro | 3 + .../components/formeditor/brushmanagerproxy.cpp | 303 + .../src/components/formeditor/brushmanagerproxy.h | 77 + .../formeditor/default_actionprovider.cpp | 207 + .../components/formeditor/default_actionprovider.h | 131 + .../components/formeditor/default_container.cpp | 173 + .../src/components/formeditor/default_container.h | 213 + .../formeditor/default_layoutdecoration.cpp | 79 + .../formeditor/default_layoutdecoration.h | 69 + .../src/components/formeditor/defaultbrushes.xml | 542 + .../components/formeditor/deviceprofiledialog.cpp | 203 + .../components/formeditor/deviceprofiledialog.h | 104 + .../components/formeditor/deviceprofiledialog.ui | 108 + .../src/components/formeditor/dpi_chooser.cpp | 207 + .../src/components/formeditor/dpi_chooser.h | 94 + .../components/formeditor/embeddedoptionspage.cpp | 453 + .../components/formeditor/embeddedoptionspage.h | 103 + .../src/components/formeditor/formeditor.cpp | 203 + .../src/components/formeditor/formeditor.h | 69 + .../src/components/formeditor/formeditor.pri | 77 + .../src/components/formeditor/formeditor.qrc | 175 + .../src/components/formeditor/formeditor_global.h | 57 + .../formeditor/formeditor_optionspage.cpp | 191 + .../components/formeditor/formeditor_optionspage.h | 79 + .../src/components/formeditor/formwindow.cpp | 2981 +++++ .../src/components/formeditor/formwindow.h | 374 + .../components/formeditor/formwindow_dnditem.cpp | 116 + .../src/components/formeditor/formwindow_dnditem.h | 65 + .../formeditor/formwindow_widgetstack.cpp | 217 + .../components/formeditor/formwindow_widgetstack.h | 102 + .../src/components/formeditor/formwindowcursor.cpp | 211 + .../src/components/formeditor/formwindowcursor.h | 93 + .../components/formeditor/formwindowmanager.cpp | 1036 ++ .../src/components/formeditor/formwindowmanager.h | 200 + .../components/formeditor/formwindowsettings.cpp | 282 + .../src/components/formeditor/formwindowsettings.h | 85 + .../components/formeditor/formwindowsettings.ui | 328 + .../src/components/formeditor/iconcache.cpp | 121 + src/designer/src/components/formeditor/iconcache.h | 78 + .../src/components/formeditor/images/cleartext.png | Bin 0 -> 760 bytes .../src/components/formeditor/images/color.png | Bin 0 -> 117 bytes .../src/components/formeditor/images/configure.png | Bin 0 -> 1016 bytes .../components/formeditor/images/cursors/arrow.png | Bin 0 -> 171 bytes .../components/formeditor/images/cursors/busy.png | Bin 0 -> 201 bytes .../formeditor/images/cursors/closedhand.png | Bin 0 -> 147 bytes .../components/formeditor/images/cursors/cross.png | Bin 0 -> 130 bytes .../components/formeditor/images/cursors/hand.png | Bin 0 -> 159 bytes .../formeditor/images/cursors/hsplit.png | Bin 0 -> 155 bytes .../components/formeditor/images/cursors/ibeam.png | Bin 0 -> 124 bytes .../components/formeditor/images/cursors/no.png | Bin 0 -> 199 bytes .../formeditor/images/cursors/openhand.png | Bin 0 -> 160 bytes .../formeditor/images/cursors/sizeall.png | Bin 0 -> 174 bytes .../components/formeditor/images/cursors/sizeb.png | Bin 0 -> 161 bytes .../components/formeditor/images/cursors/sizef.png | Bin 0 -> 161 bytes .../components/formeditor/images/cursors/sizeh.png | Bin 0 -> 145 bytes .../components/formeditor/images/cursors/sizev.png | Bin 0 -> 141 bytes .../formeditor/images/cursors/uparrow.png | Bin 0 -> 132 bytes .../formeditor/images/cursors/vsplit.png | Bin 0 -> 161 bytes .../components/formeditor/images/cursors/wait.png | Bin 0 -> 172 bytes .../formeditor/images/cursors/whatsthis.png | Bin 0 -> 191 bytes .../src/components/formeditor/images/downplus.png | Bin 0 -> 562 bytes .../formeditor/images/dropdownbutton.png | Bin 0 -> 527 bytes .../src/components/formeditor/images/edit.png | Bin 0 -> 929 bytes .../components/formeditor/images/editdelete-16.png | Bin 0 -> 553 bytes .../src/components/formeditor/images/emptyicon.png | Bin 0 -> 108 bytes .../components/formeditor/images/filenew-16.png | Bin 0 -> 454 bytes .../components/formeditor/images/fileopen-16.png | Bin 0 -> 549 bytes .../src/components/formeditor/images/leveldown.png | Bin 0 -> 557 bytes .../src/components/formeditor/images/levelup.png | Bin 0 -> 564 bytes .../formeditor/images/mac/adjustsize.png | Bin 0 -> 1929 bytes .../src/components/formeditor/images/mac/back.png | Bin 0 -> 678 bytes .../components/formeditor/images/mac/buddytool.png | Bin 0 -> 2046 bytes .../src/components/formeditor/images/mac/down.png | Bin 0 -> 594 bytes .../formeditor/images/mac/editbreaklayout.png | Bin 0 -> 2067 bytes .../components/formeditor/images/mac/editcopy.png | Bin 0 -> 1468 bytes .../components/formeditor/images/mac/editcut.png | Bin 0 -> 1512 bytes .../formeditor/images/mac/editdelete.png | Bin 0 -> 1097 bytes .../components/formeditor/images/mac/editform.png | Bin 0 -> 621 bytes .../components/formeditor/images/mac/editgrid.png | Bin 0 -> 751 bytes .../formeditor/images/mac/edithlayout.png | Bin 0 -> 1395 bytes .../formeditor/images/mac/edithlayoutsplit.png | Bin 0 -> 1188 bytes .../components/formeditor/images/mac/editlower.png | Bin 0 -> 595 bytes .../components/formeditor/images/mac/editpaste.png | Bin 0 -> 1906 bytes .../components/formeditor/images/mac/editraise.png | Bin 0 -> 1213 bytes .../formeditor/images/mac/editvlayout.png | Bin 0 -> 586 bytes .../formeditor/images/mac/editvlayoutsplit.png | Bin 0 -> 872 bytes .../components/formeditor/images/mac/filenew.png | Bin 0 -> 772 bytes .../components/formeditor/images/mac/fileopen.png | Bin 0 -> 904 bytes .../components/formeditor/images/mac/filesave.png | Bin 0 -> 1206 bytes .../components/formeditor/images/mac/forward.png | Bin 0 -> 655 bytes .../formeditor/images/mac/insertimage.png | Bin 0 -> 1280 bytes .../src/components/formeditor/images/mac/minus.png | Bin 0 -> 488 bytes .../src/components/formeditor/images/mac/plus.png | Bin 0 -> 810 bytes .../src/components/formeditor/images/mac/redo.png | Bin 0 -> 1752 bytes .../formeditor/images/mac/resetproperty.png | Bin 0 -> 169 bytes .../formeditor/images/mac/resourceeditortool.png | Bin 0 -> 2171 bytes .../formeditor/images/mac/signalslottool.png | Bin 0 -> 1989 bytes .../formeditor/images/mac/simplifyrichtext.png | Bin 0 -> 1988 bytes .../formeditor/images/mac/tabordertool.png | Bin 0 -> 1963 bytes .../formeditor/images/mac/textanchor.png | Bin 0 -> 2543 bytes .../components/formeditor/images/mac/textbold.png | Bin 0 -> 1611 bytes .../formeditor/images/mac/textcenter.png | Bin 0 -> 1404 bytes .../formeditor/images/mac/textitalic.png | Bin 0 -> 1164 bytes .../formeditor/images/mac/textjustify.png | Bin 0 -> 1257 bytes .../components/formeditor/images/mac/textleft.png | Bin 0 -> 1235 bytes .../components/formeditor/images/mac/textright.png | Bin 0 -> 1406 bytes .../formeditor/images/mac/textsubscript.png | Bin 0 -> 1054 bytes .../formeditor/images/mac/textsuperscript.png | Bin 0 -> 1109 bytes .../components/formeditor/images/mac/textunder.png | Bin 0 -> 1183 bytes .../src/components/formeditor/images/mac/undo.png | Bin 0 -> 1746 bytes .../src/components/formeditor/images/mac/up.png | Bin 0 -> 692 bytes .../formeditor/images/mac/widgettool.png | Bin 0 -> 1874 bytes .../src/components/formeditor/images/minus-16.png | Bin 0 -> 296 bytes .../src/components/formeditor/images/plus-16.png | Bin 0 -> 383 bytes .../components/formeditor/images/prefix-add.png | Bin 0 -> 411 bytes .../src/components/formeditor/images/qt3logo.png | Bin 0 -> 1101 bytes .../src/components/formeditor/images/qtlogo.png | Bin 0 -> 825 bytes .../src/components/formeditor/images/reload.png | Bin 0 -> 1363 bytes .../components/formeditor/images/resetproperty.png | Bin 0 -> 169 bytes .../src/components/formeditor/images/sort.png | Bin 0 -> 563 bytes .../src/components/formeditor/images/submenu.png | Bin 0 -> 179 bytes .../formeditor/images/widgets/calendarwidget.png | Bin 0 -> 968 bytes .../formeditor/images/widgets/checkbox.png | Bin 0 -> 817 bytes .../formeditor/images/widgets/columnview.png | Bin 0 -> 518 bytes .../formeditor/images/widgets/combobox.png | Bin 0 -> 853 bytes .../images/widgets/commandlinkbutton.png | Bin 0 -> 1208 bytes .../formeditor/images/widgets/dateedit.png | Bin 0 -> 672 bytes .../formeditor/images/widgets/datetimeedit.png | Bin 0 -> 1132 bytes .../components/formeditor/images/widgets/dial.png | Bin 0 -> 978 bytes .../formeditor/images/widgets/dialogbuttonbox.png | Bin 0 -> 1003 bytes .../formeditor/images/widgets/dockwidget.png | Bin 0 -> 638 bytes .../formeditor/images/widgets/doublespinbox.png | Bin 0 -> 749 bytes .../formeditor/images/widgets/fontcombobox.png | Bin 0 -> 966 bytes .../components/formeditor/images/widgets/frame.png | Bin 0 -> 721 bytes .../formeditor/images/widgets/graphicsview.png | Bin 0 -> 1182 bytes .../formeditor/images/widgets/groupbox.png | Bin 0 -> 439 bytes .../images/widgets/groupboxcollapsible.png | Bin 0 -> 702 bytes .../formeditor/images/widgets/hscrollbar.png | Bin 0 -> 408 bytes .../formeditor/images/widgets/hslider.png | Bin 0 -> 729 bytes .../formeditor/images/widgets/hsplit.png | Bin 0 -> 164 bytes .../components/formeditor/images/widgets/label.png | Bin 0 -> 953 bytes .../formeditor/images/widgets/lcdnumber.png | Bin 0 -> 555 bytes .../components/formeditor/images/widgets/line.png | Bin 0 -> 287 bytes .../formeditor/images/widgets/lineedit.png | Bin 0 -> 405 bytes .../formeditor/images/widgets/listbox.png | Bin 0 -> 797 bytes .../formeditor/images/widgets/listview.png | Bin 0 -> 756 bytes .../formeditor/images/widgets/mdiarea.png | Bin 0 -> 643 bytes .../formeditor/images/widgets/plaintextedit.png | Bin 0 -> 807 bytes .../formeditor/images/widgets/progress.png | Bin 0 -> 559 bytes .../formeditor/images/widgets/pushbutton.png | Bin 0 -> 408 bytes .../formeditor/images/widgets/radiobutton.png | Bin 0 -> 586 bytes .../formeditor/images/widgets/scrollarea.png | Bin 0 -> 548 bytes .../formeditor/images/widgets/spacer.png | Bin 0 -> 686 bytes .../formeditor/images/widgets/spinbox.png | Bin 0 -> 680 bytes .../formeditor/images/widgets/tabbar.png | Bin 0 -> 623 bytes .../components/formeditor/images/widgets/table.png | Bin 0 -> 483 bytes .../formeditor/images/widgets/tabwidget.png | Bin 0 -> 572 bytes .../formeditor/images/widgets/textedit.png | Bin 0 -> 823 bytes .../formeditor/images/widgets/timeedit.png | Bin 0 -> 1353 bytes .../formeditor/images/widgets/toolbox.png | Bin 0 -> 783 bytes .../formeditor/images/widgets/toolbutton.png | Bin 0 -> 1167 bytes .../components/formeditor/images/widgets/vline.png | Bin 0 -> 314 bytes .../formeditor/images/widgets/vscrollbar.png | Bin 0 -> 415 bytes .../formeditor/images/widgets/vslider.png | Bin 0 -> 726 bytes .../formeditor/images/widgets/vspacer.png | Bin 0 -> 677 bytes .../formeditor/images/widgets/widget.png | Bin 0 -> 716 bytes .../formeditor/images/widgets/widgetstack.png | Bin 0 -> 828 bytes .../formeditor/images/widgets/wizard.png | Bin 0 -> 898 bytes .../formeditor/images/win/adjustsize.png | Bin 0 -> 1262 bytes .../src/components/formeditor/images/win/back.png | Bin 0 -> 678 bytes .../components/formeditor/images/win/buddytool.png | Bin 0 -> 997 bytes .../src/components/formeditor/images/win/down.png | Bin 0 -> 594 bytes .../formeditor/images/win/editbreaklayout.png | Bin 0 -> 1321 bytes .../components/formeditor/images/win/editcopy.png | Bin 0 -> 1325 bytes .../components/formeditor/images/win/editcut.png | Bin 0 -> 1384 bytes .../formeditor/images/win/editdelete.png | Bin 0 -> 850 bytes .../components/formeditor/images/win/editform.png | Bin 0 -> 349 bytes .../components/formeditor/images/win/editgrid.png | Bin 0 -> 349 bytes .../formeditor/images/win/edithlayout.png | Bin 0 -> 455 bytes .../formeditor/images/win/edithlayoutsplit.png | Bin 0 -> 860 bytes .../components/formeditor/images/win/editlower.png | Bin 0 -> 1038 bytes .../components/formeditor/images/win/editpaste.png | Bin 0 -> 1482 bytes .../components/formeditor/images/win/editraise.png | Bin 0 -> 1045 bytes .../formeditor/images/win/editvlayout.png | Bin 0 -> 340 bytes .../formeditor/images/win/editvlayoutsplit.png | Bin 0 -> 740 bytes .../components/formeditor/images/win/filenew.png | Bin 0 -> 768 bytes .../components/formeditor/images/win/fileopen.png | Bin 0 -> 1662 bytes .../components/formeditor/images/win/filesave.png | Bin 0 -> 1205 bytes .../components/formeditor/images/win/forward.png | Bin 0 -> 655 bytes .../formeditor/images/win/insertimage.png | Bin 0 -> 885 bytes .../src/components/formeditor/images/win/minus.png | Bin 0 -> 429 bytes .../src/components/formeditor/images/win/plus.png | Bin 0 -> 709 bytes .../src/components/formeditor/images/win/redo.png | Bin 0 -> 1212 bytes .../formeditor/images/win/resourceeditortool.png | Bin 0 -> 1429 bytes .../formeditor/images/win/signalslottool.png | Bin 0 -> 1128 bytes .../formeditor/images/win/simplifyrichtext.png | Bin 0 -> 1933 bytes .../formeditor/images/win/tabordertool.png | Bin 0 -> 1205 bytes .../formeditor/images/win/textanchor.png | Bin 0 -> 1581 bytes .../components/formeditor/images/win/textbold.png | Bin 0 -> 1134 bytes .../formeditor/images/win/textcenter.png | Bin 0 -> 627 bytes .../formeditor/images/win/textitalic.png | Bin 0 -> 829 bytes .../formeditor/images/win/textjustify.png | Bin 0 -> 695 bytes .../components/formeditor/images/win/textleft.png | Bin 0 -> 673 bytes .../components/formeditor/images/win/textright.png | Bin 0 -> 677 bytes .../formeditor/images/win/textsubscript.png | Bin 0 -> 897 bytes .../formeditor/images/win/textsuperscript.png | Bin 0 -> 864 bytes .../components/formeditor/images/win/textunder.png | Bin 0 -> 971 bytes .../src/components/formeditor/images/win/undo.png | Bin 0 -> 1181 bytes .../src/components/formeditor/images/win/up.png | Bin 0 -> 692 bytes .../formeditor/images/win/widgettool.png | Bin 0 -> 1039 bytes .../formeditor/itemview_propertysheet.cpp | 270 + .../components/formeditor/itemview_propertysheet.h | 92 + .../components/formeditor/layout_propertysheet.cpp | 546 + .../components/formeditor/layout_propertysheet.h | 82 + .../components/formeditor/line_propertysheet.cpp | 86 + .../src/components/formeditor/line_propertysheet.h | 71 + .../components/formeditor/previewactiongroup.cpp | 149 + .../src/components/formeditor/previewactiongroup.h | 90 + .../components/formeditor/qdesigner_resource.cpp | 2475 ++++ .../src/components/formeditor/qdesigner_resource.h | 178 + .../components/formeditor/qdesignerundostack.cpp | 112 + .../src/components/formeditor/qdesignerundostack.h | 90 + .../formeditor/qlayoutwidget_propertysheet.cpp | 83 + .../formeditor/qlayoutwidget_propertysheet.h | 72 + .../formeditor/qmainwindow_container.cpp | 199 + .../components/formeditor/qmainwindow_container.h | 81 + .../components/formeditor/qmdiarea_container.cpp | 281 + .../src/components/formeditor/qmdiarea_container.h | 119 + .../src/components/formeditor/qtbrushmanager.cpp | 140 + .../src/components/formeditor/qtbrushmanager.h | 85 + .../components/formeditor/qwizard_container.cpp | 226 + .../src/components/formeditor/qwizard_container.h | 123 + .../components/formeditor/qworkspace_container.cpp | 100 + .../components/formeditor/qworkspace_container.h | 79 + .../components/formeditor/spacer_propertysheet.cpp | 82 + .../components/formeditor/spacer_propertysheet.h | 72 + .../components/formeditor/templateoptionspage.cpp | 183 + .../components/formeditor/templateoptionspage.h | 110 + .../components/formeditor/templateoptionspage.ui | 59 + .../components/formeditor/tool_widgeteditor.cpp | 363 + .../src/components/formeditor/tool_widgeteditor.h | 107 + .../src/components/formeditor/widgetselection.cpp | 746 ++ .../src/components/formeditor/widgetselection.h | 145 + src/designer/src/components/lib/lib.pro | 77 + src/designer/src/components/lib/lib_pch.h | 43 + .../src/components/lib/qdesigner_components.cpp | 277 + .../components/objectinspector/objectinspector.cpp | 835 ++ .../components/objectinspector/objectinspector.h | 95 + .../components/objectinspector/objectinspector.pri | 16 + .../objectinspector/objectinspector_global.h | 61 + .../objectinspector/objectinspectormodel.cpp | 516 + .../objectinspector/objectinspectormodel_p.h | 168 + .../propertyeditor/brushpropertymanager.cpp | 298 + .../propertyeditor/brushpropertymanager.h | 105 + .../propertyeditor/designerpropertymanager.cpp | 2836 +++++ .../propertyeditor/designerpropertymanager.h | 315 + .../src/components/propertyeditor/fontmapping.xml | 73 + .../propertyeditor/fontpropertymanager.cpp | 377 + .../propertyeditor/fontpropertymanager.h | 124 + .../propertyeditor/newdynamicpropertydialog.cpp | 170 + .../propertyeditor/newdynamicpropertydialog.h | 104 + .../propertyeditor/newdynamicpropertydialog.ui | 106 + .../components/propertyeditor/paletteeditor.cpp | 616 + .../src/components/propertyeditor/paletteeditor.h | 204 + .../src/components/propertyeditor/paletteeditor.ui | 264 + .../propertyeditor/paletteeditorbutton.cpp | 88 + .../propertyeditor/paletteeditorbutton.h | 86 + .../src/components/propertyeditor/previewframe.cpp | 119 + .../src/components/propertyeditor/previewframe.h | 76 + .../components/propertyeditor/previewwidget.cpp | 59 + .../src/components/propertyeditor/previewwidget.h | 66 + .../src/components/propertyeditor/previewwidget.ui | 238 + .../components/propertyeditor/propertyeditor.cpp | 1294 +++ .../src/components/propertyeditor/propertyeditor.h | 207 + .../components/propertyeditor/propertyeditor.pri | 52 + .../components/propertyeditor/propertyeditor.qrc | 5 + .../propertyeditor/propertyeditor_global.h | 61 + .../propertyeditor/qlonglongvalidator.cpp | 153 + .../components/propertyeditor/qlonglongvalidator.h | 110 + .../components/propertyeditor/stringlisteditor.cpp | 212 + .../components/propertyeditor/stringlisteditor.h | 92 + .../components/propertyeditor/stringlisteditor.ui | 265 + .../propertyeditor/stringlisteditorbutton.cpp | 81 + .../propertyeditor/stringlisteditorbutton.h | 81 + .../components/signalsloteditor/connectdialog.cpp | 335 + .../components/signalsloteditor/connectdialog.ui | 150 + .../components/signalsloteditor/connectdialog_p.h | 109 + .../signalsloteditor/signalslot_utils.cpp | 334 + .../signalsloteditor/signalslot_utils_p.h | 104 + .../signalsloteditor/signalsloteditor.cpp | 528 + .../components/signalsloteditor/signalsloteditor.h | 98 + .../signalsloteditor/signalsloteditor.pri | 21 + .../signalsloteditor/signalsloteditor_global.h | 57 + .../signalsloteditor/signalsloteditor_instance.cpp | 50 + .../signalsloteditor/signalsloteditor_p.h | 138 + .../signalsloteditor/signalsloteditor_plugin.cpp | 133 + .../signalsloteditor/signalsloteditor_plugin.h | 92 + .../signalsloteditor/signalsloteditor_tool.cpp | 123 + .../signalsloteditor/signalsloteditor_tool.h | 93 + .../signalsloteditor/signalsloteditorwindow.cpp | 864 ++ .../signalsloteditor/signalsloteditorwindow.h | 96 + .../components/tabordereditor/tabordereditor.cpp | 433 + .../src/components/tabordereditor/tabordereditor.h | 109 + .../components/tabordereditor/tabordereditor.pri | 16 + .../tabordereditor/tabordereditor_global.h | 57 + .../tabordereditor/tabordereditor_instance.cpp | 49 + .../tabordereditor/tabordereditor_plugin.cpp | 133 + .../tabordereditor/tabordereditor_plugin.h | 93 + .../tabordereditor/tabordereditor_tool.cpp | 114 + .../tabordereditor/tabordereditor_tool.h | 89 + .../src/components/taskmenu/button_taskmenu.cpp | 709 ++ .../src/components/taskmenu/button_taskmenu.h | 170 + .../src/components/taskmenu/combobox_taskmenu.cpp | 133 + .../src/components/taskmenu/combobox_taskmenu.h | 94 + .../taskmenu/containerwidget_taskmenu.cpp | 348 + .../components/taskmenu/containerwidget_taskmenu.h | 157 + .../src/components/taskmenu/groupbox_taskmenu.cpp | 105 + .../src/components/taskmenu/groupbox_taskmenu.h | 77 + .../src/components/taskmenu/inplace_editor.cpp | 136 + .../src/components/taskmenu/inplace_editor.h | 110 + .../components/taskmenu/inplace_widget_helper.cpp | 120 + .../components/taskmenu/inplace_widget_helper.h | 88 + .../src/components/taskmenu/itemlisteditor.cpp | 478 + .../src/components/taskmenu/itemlisteditor.h | 165 + .../src/components/taskmenu/itemlisteditor.ui | 156 + .../src/components/taskmenu/label_taskmenu.cpp | 117 + .../src/components/taskmenu/label_taskmenu.h | 81 + .../src/components/taskmenu/layouttaskmenu.cpp | 93 + .../src/components/taskmenu/layouttaskmenu.h | 93 + .../src/components/taskmenu/lineedit_taskmenu.cpp | 103 + .../src/components/taskmenu/lineedit_taskmenu.h | 74 + .../components/taskmenu/listwidget_taskmenu.cpp | 117 + .../src/components/taskmenu/listwidget_taskmenu.h | 85 + .../src/components/taskmenu/listwidgeteditor.cpp | 138 + .../src/components/taskmenu/listwidgeteditor.h | 78 + .../src/components/taskmenu/menutaskmenu.cpp | 107 + .../src/components/taskmenu/menutaskmenu.h | 106 + .../components/taskmenu/tablewidget_taskmenu.cpp | 115 + .../src/components/taskmenu/tablewidget_taskmenu.h | 85 + .../src/components/taskmenu/tablewidgeteditor.cpp | 450 + .../src/components/taskmenu/tablewidgeteditor.h | 130 + .../src/components/taskmenu/tablewidgeteditor.ui | 157 + src/designer/src/components/taskmenu/taskmenu.pri | 50 + .../src/components/taskmenu/taskmenu_component.cpp | 106 + .../src/components/taskmenu/taskmenu_component.h | 73 + .../src/components/taskmenu/taskmenu_global.h | 57 + .../src/components/taskmenu/textedit_taskmenu.cpp | 105 + .../src/components/taskmenu/textedit_taskmenu.h | 89 + .../src/components/taskmenu/toolbar_taskmenu.cpp | 111 + .../src/components/taskmenu/toolbar_taskmenu.h | 99 + .../components/taskmenu/treewidget_taskmenu.cpp | 114 + .../src/components/taskmenu/treewidget_taskmenu.h | 85 + .../src/components/taskmenu/treewidgeteditor.cpp | 642 ++ .../src/components/taskmenu/treewidgeteditor.h | 129 + .../src/components/taskmenu/treewidgeteditor.ui | 257 + .../src/components/widgetbox/widgetbox.cpp | 235 + src/designer/src/components/widgetbox/widgetbox.h | 103 + .../src/components/widgetbox/widgetbox.pri | 14 + .../src/components/widgetbox/widgetbox.qrc | 5 + .../src/components/widgetbox/widgetbox.xml | 932 ++ .../src/components/widgetbox/widgetbox_dnditem.cpp | 225 + .../src/components/widgetbox/widgetbox_dnditem.h | 67 + .../src/components/widgetbox/widgetbox_global.h | 57 + .../widgetbox/widgetboxcategorylistview.cpp | 510 + .../widgetbox/widgetboxcategorylistview.h | 118 + .../components/widgetbox/widgetboxtreewidget.cpp | 1001 ++ .../src/components/widgetbox/widgetboxtreewidget.h | 150 + src/designer/src/designer/Info_mac.plist | 35 + src/designer/src/designer/appfontdialog.cpp | 429 + src/designer/src/designer/appfontdialog.h | 101 + src/designer/src/designer/assistantclient.cpp | 175 + src/designer/src/designer/assistantclient.h | 83 + src/designer/src/designer/designer.icns | Bin 0 -> 154893 bytes src/designer/src/designer/designer.ico | Bin 0 -> 355574 bytes src/designer/src/designer/designer.pro | 90 + src/designer/src/designer/designer.qrc | 5 + src/designer/src/designer/designer.rc | 32 + src/designer/src/designer/designer_enums.h | 52 + src/designer/src/designer/images/designer.png | Bin 0 -> 4205 bytes src/designer/src/designer/images/mdi.png | Bin 0 -> 59505 bytes src/designer/src/designer/images/sdi.png | Bin 0 -> 61037 bytes src/designer/src/designer/images/workbench.png | Bin 0 -> 2085 bytes src/designer/src/designer/main.cpp | 58 + src/designer/src/designer/mainwindow.cpp | 419 + src/designer/src/designer/mainwindow.h | 187 + src/designer/src/designer/newform.cpp | 227 + src/designer/src/designer/newform.h | 104 + src/designer/src/designer/preferencesdialog.cpp | 118 + src/designer/src/designer/preferencesdialog.h | 82 + src/designer/src/designer/preferencesdialog.ui | 91 + src/designer/src/designer/qdesigner.cpp | 320 + src/designer/src/designer/qdesigner.h | 102 + src/designer/src/designer/qdesigner_actions.cpp | 1437 +++ src/designer/src/designer/qdesigner_actions.h | 231 + .../src/designer/qdesigner_appearanceoptions.cpp | 167 + .../src/designer/qdesigner_appearanceoptions.h | 136 + .../src/designer/qdesigner_appearanceoptions.ui | 57 + src/designer/src/designer/qdesigner_formwindow.cpp | 290 + src/designer/src/designer/qdesigner_formwindow.h | 97 + src/designer/src/designer/qdesigner_pch.h | 59 + src/designer/src/designer/qdesigner_server.cpp | 156 + src/designer/src/designer/qdesigner_server.h | 89 + src/designer/src/designer/qdesigner_settings.cpp | 250 + src/designer/src/designer/qdesigner_settings.h | 94 + src/designer/src/designer/qdesigner_toolwindow.cpp | 438 + src/designer/src/designer/qdesigner_toolwindow.h | 123 + src/designer/src/designer/qdesigner_workbench.cpp | 1100 ++ src/designer/src/designer/qdesigner_workbench.h | 215 + src/designer/src/designer/saveformastemplate.cpp | 173 + src/designer/src/designer/saveformastemplate.h | 77 + src/designer/src/designer/saveformastemplate.ui | 166 + src/designer/src/designer/uifile.icns | Bin 0 -> 123696 bytes src/designer/src/designer/versiondialog.cpp | 191 + src/designer/src/designer/versiondialog.h | 58 + .../src/lib/components/qdesigner_components.h | 82 + .../lib/components/qdesigner_components_global.h | 66 + .../src/lib/extension/default_extensionfactory.cpp | 178 + .../src/lib/extension/default_extensionfactory.h | 86 + src/designer/src/lib/extension/extension.cpp | 186 + src/designer/src/lib/extension/extension.h | 109 + src/designer/src/lib/extension/extension.pri | 12 + src/designer/src/lib/extension/extension_global.h | 64 + .../src/lib/extension/qextensionmanager.cpp | 174 + src/designer/src/lib/extension/qextensionmanager.h | 79 + src/designer/src/lib/lib.pro | 78 + src/designer/src/lib/lib_pch.h | 65 + src/designer/src/lib/sdk/abstractactioneditor.cpp | 123 + src/designer/src/lib/sdk/abstractactioneditor.h | 76 + src/designer/src/lib/sdk/abstractbrushmanager.h | 83 + src/designer/src/lib/sdk/abstractdialoggui.cpp | 161 + src/designer/src/lib/sdk/abstractdialoggui_p.h | 107 + src/designer/src/lib/sdk/abstractdnditem.h | 75 + src/designer/src/lib/sdk/abstractdnditem.qdoc | 98 + src/designer/src/lib/sdk/abstractformeditor.cpp | 630 ++ src/designer/src/lib/sdk/abstractformeditor.h | 159 + .../src/lib/sdk/abstractformeditorplugin.cpp | 86 + .../src/lib/sdk/abstractformeditorplugin.h | 73 + src/designer/src/lib/sdk/abstractformwindow.cpp | 814 ++ src/designer/src/lib/sdk/abstractformwindow.h | 183 + .../src/lib/sdk/abstractformwindowcursor.cpp | 252 + .../src/lib/sdk/abstractformwindowcursor.h | 109 + .../src/lib/sdk/abstractformwindowmanager.cpp | 502 + .../src/lib/sdk/abstractformwindowmanager.h | 122 + .../src/lib/sdk/abstractformwindowtool.cpp | 106 + src/designer/src/lib/sdk/abstractformwindowtool.h | 85 + src/designer/src/lib/sdk/abstracticoncache.h | 83 + src/designer/src/lib/sdk/abstracticoncache.qdoc | 116 + src/designer/src/lib/sdk/abstractintegration.cpp | 105 + src/designer/src/lib/sdk/abstractintegration.h | 86 + src/designer/src/lib/sdk/abstractintrospection.cpp | 548 + src/designer/src/lib/sdk/abstractintrospection_p.h | 174 + src/designer/src/lib/sdk/abstractlanguage.h | 100 + src/designer/src/lib/sdk/abstractmetadatabase.cpp | 170 + src/designer/src/lib/sdk/abstractmetadatabase.h | 99 + src/designer/src/lib/sdk/abstractnewformwidget.cpp | 117 + src/designer/src/lib/sdk/abstractnewformwidget_p.h | 88 + .../src/lib/sdk/abstractobjectinspector.cpp | 110 + src/designer/src/lib/sdk/abstractobjectinspector.h | 73 + src/designer/src/lib/sdk/abstractoptionspage_p.h | 79 + .../src/lib/sdk/abstractpromotioninterface.cpp | 113 + .../src/lib/sdk/abstractpromotioninterface.h | 91 + .../src/lib/sdk/abstractpropertyeditor.cpp | 193 + src/designer/src/lib/sdk/abstractpropertyeditor.h | 84 + .../src/lib/sdk/abstractresourcebrowser.cpp | 57 + src/designer/src/lib/sdk/abstractresourcebrowser.h | 75 + src/designer/src/lib/sdk/abstractsettings_p.h | 87 + src/designer/src/lib/sdk/abstractwidgetbox.cpp | 340 + src/designer/src/lib/sdk/abstractwidgetbox.h | 142 + .../src/lib/sdk/abstractwidgetdatabase.cpp | 360 + src/designer/src/lib/sdk/abstractwidgetdatabase.h | 137 + src/designer/src/lib/sdk/abstractwidgetfactory.cpp | 112 + src/designer/src/lib/sdk/abstractwidgetfactory.h | 79 + src/designer/src/lib/sdk/dynamicpropertysheet.h | 81 + src/designer/src/lib/sdk/dynamicpropertysheet.qdoc | 80 + src/designer/src/lib/sdk/extrainfo.cpp | 116 + src/designer/src/lib/sdk/extrainfo.h | 84 + src/designer/src/lib/sdk/layoutdecoration.h | 99 + src/designer/src/lib/sdk/layoutdecoration.qdoc | 149 + src/designer/src/lib/sdk/membersheet.h | 89 + src/designer/src/lib/sdk/membersheet.qdoc | 249 + src/designer/src/lib/sdk/propertysheet.h | 90 + src/designer/src/lib/sdk/propertysheet.qdoc | 288 + src/designer/src/lib/sdk/script.cpp | 109 + src/designer/src/lib/sdk/script_p.h | 83 + src/designer/src/lib/sdk/sdk.pri | 58 + src/designer/src/lib/sdk/sdk_global.h | 64 + src/designer/src/lib/sdk/taskmenu.h | 72 + src/designer/src/lib/sdk/taskmenu.qdoc | 138 + src/designer/src/lib/shared/actioneditor.cpp | 823 ++ src/designer/src/lib/shared/actioneditor_p.h | 168 + src/designer/src/lib/shared/actionprovider_p.h | 108 + src/designer/src/lib/shared/actionrepository.cpp | 665 ++ src/designer/src/lib/shared/actionrepository_p.h | 269 + src/designer/src/lib/shared/addlinkdialog.ui | 112 + src/designer/src/lib/shared/codedialog.cpp | 262 + src/designer/src/lib/shared/codedialog_p.h | 100 + src/designer/src/lib/shared/connectionedit.cpp | 1612 +++ src/designer/src/lib/shared/connectionedit_p.h | 324 + src/designer/src/lib/shared/csshighlighter.cpp | 188 + src/designer/src/lib/shared/csshighlighter_p.h | 82 + src/designer/src/lib/shared/defaultgradients.xml | 498 + src/designer/src/lib/shared/deviceprofile.cpp | 467 + src/designer/src/lib/shared/deviceprofile_p.h | 152 + src/designer/src/lib/shared/dialoggui.cpp | 265 + src/designer/src/lib/shared/dialoggui_p.h | 107 + src/designer/src/lib/shared/extensionfactory_p.h | 120 + src/designer/src/lib/shared/filterwidget.cpp | 252 + src/designer/src/lib/shared/filterwidget_p.h | 151 + src/designer/src/lib/shared/formlayoutmenu.cpp | 534 + src/designer/src/lib/shared/formlayoutmenu_p.h | 100 + src/designer/src/lib/shared/formlayoutrowdialog.ui | 166 + src/designer/src/lib/shared/formwindowbase.cpp | 502 + src/designer/src/lib/shared/formwindowbase_p.h | 205 + src/designer/src/lib/shared/grid.cpp | 194 + src/designer/src/lib/shared/grid_p.h | 118 + src/designer/src/lib/shared/gridpanel.cpp | 121 + src/designer/src/lib/shared/gridpanel.ui | 144 + src/designer/src/lib/shared/gridpanel_p.h | 101 + src/designer/src/lib/shared/htmlhighlighter.cpp | 198 + src/designer/src/lib/shared/htmlhighlighter_p.h | 101 + src/designer/src/lib/shared/iconloader.cpp | 79 + src/designer/src/lib/shared/iconloader_p.h | 72 + src/designer/src/lib/shared/iconselector.cpp | 655 ++ src/designer/src/lib/shared/iconselector_p.h | 172 + src/designer/src/lib/shared/invisible_widget.cpp | 57 + src/designer/src/lib/shared/invisible_widget_p.h | 75 + src/designer/src/lib/shared/layout.cpp | 1332 +++ src/designer/src/lib/shared/layout_p.h | 152 + src/designer/src/lib/shared/layoutinfo.cpp | 312 + src/designer/src/lib/shared/layoutinfo_p.h | 114 + src/designer/src/lib/shared/metadatabase.cpp | 295 + src/designer/src/lib/shared/metadatabase_p.h | 142 + src/designer/src/lib/shared/morphmenu.cpp | 635 ++ src/designer/src/lib/shared/morphmenu_p.h | 97 + src/designer/src/lib/shared/newactiondialog.cpp | 199 + src/designer/src/lib/shared/newactiondialog.ui | 313 + src/designer/src/lib/shared/newactiondialog_p.h | 124 + src/designer/src/lib/shared/newformwidget.cpp | 586 + src/designer/src/lib/shared/newformwidget.ui | 192 + src/designer/src/lib/shared/newformwidget_p.h | 143 + src/designer/src/lib/shared/orderdialog.cpp | 188 + src/designer/src/lib/shared/orderdialog.ui | 198 + src/designer/src/lib/shared/orderdialog_p.h | 114 + src/designer/src/lib/shared/plaintexteditor.cpp | 119 + src/designer/src/lib/shared/plaintexteditor_p.h | 89 + src/designer/src/lib/shared/plugindialog.cpp | 207 + src/designer/src/lib/shared/plugindialog.ui | 136 + src/designer/src/lib/shared/plugindialog_p.h | 92 + src/designer/src/lib/shared/pluginmanager.cpp | 786 ++ src/designer/src/lib/shared/pluginmanager_p.h | 159 + .../src/lib/shared/previewconfigurationwidget.cpp | 366 + .../src/lib/shared/previewconfigurationwidget.ui | 91 + .../src/lib/shared/previewconfigurationwidget_p.h | 96 + src/designer/src/lib/shared/previewmanager.cpp | 943 ++ src/designer/src/lib/shared/previewmanager_p.h | 184 + src/designer/src/lib/shared/promotionmodel.cpp | 220 + src/designer/src/lib/shared/promotionmodel_p.h | 98 + src/designer/src/lib/shared/promotiontaskmenu.cpp | 361 + src/designer/src/lib/shared/promotiontaskmenu_p.h | 151 + src/designer/src/lib/shared/propertylineedit.cpp | 96 + src/designer/src/lib/shared/propertylineedit_p.h | 85 + src/designer/src/lib/shared/qdesigner_command.cpp | 2968 +++++ src/designer/src/lib/shared/qdesigner_command2.cpp | 221 + src/designer/src/lib/shared/qdesigner_command2_p.h | 123 + src/designer/src/lib/shared/qdesigner_command_p.h | 1136 ++ src/designer/src/lib/shared/qdesigner_dnditem.cpp | 300 + src/designer/src/lib/shared/qdesigner_dnditem_p.h | 147 + .../src/lib/shared/qdesigner_dockwidget.cpp | 140 + .../src/lib/shared/qdesigner_dockwidget_p.h | 87 + .../src/lib/shared/qdesigner_formbuilder.cpp | 498 + .../src/lib/shared/qdesigner_formbuilder_p.h | 181 + .../src/lib/shared/qdesigner_formeditorcommand.cpp | 64 + .../src/lib/shared/qdesigner_formeditorcommand_p.h | 83 + .../src/lib/shared/qdesigner_formwindowcommand.cpp | 151 + .../src/lib/shared/qdesigner_formwindowcommand_p.h | 98 + .../src/lib/shared/qdesigner_formwindowmanager.cpp | 167 + .../src/lib/shared/qdesigner_formwindowmanager_p.h | 99 + .../src/lib/shared/qdesigner_integration.cpp | 496 + .../src/lib/shared/qdesigner_integration_p.h | 152 + .../src/lib/shared/qdesigner_introspection.cpp | 372 + .../src/lib/shared/qdesigner_introspection_p.h | 84 + .../src/lib/shared/qdesigner_membersheet.cpp | 371 + .../src/lib/shared/qdesigner_membersheet_p.h | 120 + src/designer/src/lib/shared/qdesigner_menu.cpp | 1390 +++ src/designer/src/lib/shared/qdesigner_menu_p.h | 208 + src/designer/src/lib/shared/qdesigner_menubar.cpp | 979 ++ src/designer/src/lib/shared/qdesigner_menubar_p.h | 179 + .../src/lib/shared/qdesigner_objectinspector.cpp | 80 + .../src/lib/shared/qdesigner_objectinspector_p.h | 103 + .../src/lib/shared/qdesigner_promotion.cpp | 373 + .../src/lib/shared/qdesigner_promotion_p.h | 98 + .../src/lib/shared/qdesigner_promotiondialog.cpp | 456 + .../src/lib/shared/qdesigner_promotiondialog_p.h | 170 + .../src/lib/shared/qdesigner_propertycommand.cpp | 1503 +++ .../src/lib/shared/qdesigner_propertycommand_p.h | 313 + .../src/lib/shared/qdesigner_propertyeditor.cpp | 169 + .../src/lib/shared/qdesigner_propertyeditor_p.h | 112 + .../src/lib/shared/qdesigner_propertysheet.cpp | 1657 +++ .../src/lib/shared/qdesigner_propertysheet_p.h | 266 + .../src/lib/shared/qdesigner_qsettings.cpp | 94 + .../src/lib/shared/qdesigner_qsettings_p.h | 88 + .../src/lib/shared/qdesigner_stackedbox.cpp | 399 + .../src/lib/shared/qdesigner_stackedbox_p.h | 164 + .../src/lib/shared/qdesigner_tabwidget.cpp | 572 + .../src/lib/shared/qdesigner_tabwidget_p.h | 153 + src/designer/src/lib/shared/qdesigner_taskmenu.cpp | 912 ++ src/designer/src/lib/shared/qdesigner_taskmenu_p.h | 133 + src/designer/src/lib/shared/qdesigner_toolbar.cpp | 488 + src/designer/src/lib/shared/qdesigner_toolbar_p.h | 135 + src/designer/src/lib/shared/qdesigner_toolbox.cpp | 437 + src/designer/src/lib/shared/qdesigner_toolbox_p.h | 140 + src/designer/src/lib/shared/qdesigner_utils.cpp | 848 ++ src/designer/src/lib/shared/qdesigner_utils_p.h | 499 + src/designer/src/lib/shared/qdesigner_widget.cpp | 108 + src/designer/src/lib/shared/qdesigner_widget_p.h | 122 + .../src/lib/shared/qdesigner_widgetbox.cpp | 181 + .../src/lib/shared/qdesigner_widgetbox_p.h | 101 + .../src/lib/shared/qdesigner_widgetitem.cpp | 345 + .../src/lib/shared/qdesigner_widgetitem_p.h | 147 + src/designer/src/lib/shared/qlayout_widget.cpp | 2107 ++++ src/designer/src/lib/shared/qlayout_widget_p.h | 292 + src/designer/src/lib/shared/qscripthighlighter.cpp | 468 + src/designer/src/lib/shared/qscripthighlighter_p.h | 84 + src/designer/src/lib/shared/qsimpleresource.cpp | 418 + src/designer/src/lib/shared/qsimpleresource_p.h | 164 + .../src/lib/shared/qtresourceeditordialog.cpp | 2223 ++++ .../src/lib/shared/qtresourceeditordialog.ui | 177 + .../src/lib/shared/qtresourceeditordialog_p.h | 130 + src/designer/src/lib/shared/qtresourcemodel.cpp | 650 ++ src/designer/src/lib/shared/qtresourcemodel_p.h | 145 + src/designer/src/lib/shared/qtresourceview.cpp | 906 ++ src/designer/src/lib/shared/qtresourceview_p.h | 141 + src/designer/src/lib/shared/richtexteditor.cpp | 906 ++ src/designer/src/lib/shared/richtexteditor_p.h | 103 + src/designer/src/lib/shared/scriptcommand.cpp | 103 + src/designer/src/lib/shared/scriptcommand_p.h | 93 + src/designer/src/lib/shared/scriptdialog.cpp | 130 + src/designer/src/lib/shared/scriptdialog_p.h | 90 + src/designer/src/lib/shared/scripterrordialog.cpp | 108 + src/designer/src/lib/shared/scripterrordialog_p.h | 83 + src/designer/src/lib/shared/selectsignaldialog.ui | 93 + src/designer/src/lib/shared/shared.pri | 189 + src/designer/src/lib/shared/shared.qrc | 20 + src/designer/src/lib/shared/shared_enums_p.h | 99 + src/designer/src/lib/shared/shared_global_p.h | 76 + src/designer/src/lib/shared/shared_settings.cpp | 321 + src/designer/src/lib/shared/shared_settings_p.h | 142 + src/designer/src/lib/shared/sheet_delegate.cpp | 112 + src/designer/src/lib/shared/sheet_delegate_p.h | 85 + src/designer/src/lib/shared/signalslotdialog.cpp | 526 + src/designer/src/lib/shared/signalslotdialog.ui | 129 + src/designer/src/lib/shared/signalslotdialog_p.h | 173 + src/designer/src/lib/shared/spacer_widget.cpp | 280 + src/designer/src/lib/shared/spacer_widget_p.h | 117 + src/designer/src/lib/shared/stylesheeteditor.cpp | 409 + src/designer/src/lib/shared/stylesheeteditor_p.h | 144 + .../forms/240x320/Dialog_with_Buttons_Bottom.ui | 67 + .../forms/240x320/Dialog_with_Buttons_Right.ui | 67 + .../forms/320x240/Dialog_with_Buttons_Bottom.ui | 67 + .../forms/320x240/Dialog_with_Buttons_Right.ui | 67 + .../forms/480x640/Dialog_with_Buttons_Bottom.ui | 67 + .../forms/480x640/Dialog_with_Buttons_Right.ui | 67 + .../forms/640x480/Dialog_with_Buttons_Bottom.ui | 67 + .../forms/640x480/Dialog_with_Buttons_Right.ui | 67 + .../templates/forms/Dialog_with_Buttons_Bottom.ui | 71 + .../templates/forms/Dialog_with_Buttons_Right.ui | 71 + .../templates/forms/Dialog_without_Buttons.ui | 18 + .../src/lib/shared/templates/forms/Main_Window.ui | 24 + .../src/lib/shared/templates/forms/Widget.ui | 21 + src/designer/src/lib/shared/textpropertyeditor.cpp | 430 + src/designer/src/lib/shared/textpropertyeditor_p.h | 156 + src/designer/src/lib/shared/widgetdatabase.cpp | 865 ++ src/designer/src/lib/shared/widgetdatabase_p.h | 210 + src/designer/src/lib/shared/widgetfactory.cpp | 899 ++ src/designer/src/lib/shared/widgetfactory_p.h | 191 + src/designer/src/lib/shared/zoomwidget.cpp | 570 + src/designer/src/lib/shared/zoomwidget_p.h | 231 + src/designer/src/plugins/activeqt/activeqt.pro | 32 + .../src/plugins/activeqt/qaxwidgetextrainfo.cpp | 117 + .../src/plugins/activeqt/qaxwidgetextrainfo.h | 91 + .../src/plugins/activeqt/qaxwidgetplugin.cpp | 146 + .../src/plugins/activeqt/qaxwidgetplugin.h | 77 + .../plugins/activeqt/qaxwidgetpropertysheet.cpp | 189 + .../src/plugins/activeqt/qaxwidgetpropertysheet.h | 99 + .../src/plugins/activeqt/qaxwidgettaskmenu.cpp | 186 + .../src/plugins/activeqt/qaxwidgettaskmenu.h | 76 + .../src/plugins/activeqt/qdesigneraxwidget.cpp | 272 + .../src/plugins/activeqt/qdesigneraxwidget.h | 142 + .../plugins/phononwidgets/images/seekslider.png | Bin 0 -> 444 bytes .../plugins/phononwidgets/images/videoplayer.png | Bin 0 -> 644 bytes .../plugins/phononwidgets/images/videowidget.png | Bin 0 -> 794 bytes .../plugins/phononwidgets/images/volumeslider.png | Bin 0 -> 470 bytes .../src/plugins/phononwidgets/phononcollection.cpp | 82 + .../src/plugins/phononwidgets/phononwidgets.pro | 24 + .../src/plugins/phononwidgets/phononwidgets.qrc | 8 + .../src/plugins/phononwidgets/seeksliderplugin.cpp | 117 + .../src/plugins/phononwidgets/seeksliderplugin.h | 75 + .../plugins/phononwidgets/videoplayerplugin.cpp | 135 + .../src/plugins/phononwidgets/videoplayerplugin.h | 75 + .../plugins/phononwidgets/videoplayertaskmenu.cpp | 154 + .../plugins/phononwidgets/videoplayertaskmenu.h | 83 + .../plugins/phononwidgets/volumesliderplugin.cpp | 117 + .../src/plugins/phononwidgets/volumesliderplugin.h | 75 + src/designer/src/plugins/plugins.pri | 8 + src/designer/src/plugins/plugins.pro | 10 + .../plugins/qdeclarativeview/qdeclarativeview.pro | 13 + .../qdeclarativeview/qdeclarativeview_plugin.cpp | 132 + .../qdeclarativeview/qdeclarativeview_plugin.h | 74 + .../src/plugins/qwebview/images/qwebview.png | Bin 0 -> 1473 bytes src/designer/src/plugins/qwebview/qwebview.pro | 15 + .../src/plugins/qwebview/qwebview_plugin.cpp | 137 + .../src/plugins/qwebview/qwebview_plugin.h | 74 + .../src/plugins/qwebview/qwebview_plugin.qrc | 5 + src/designer/src/plugins/tools/view3d/view3d.cpp | 492 + src/designer/src/plugins/tools/view3d/view3d.h | 77 + src/designer/src/plugins/tools/view3d/view3d.pro | 17 + .../src/plugins/tools/view3d/view3d_global.h | 61 + .../src/plugins/tools/view3d/view3d_plugin.cpp | 115 + .../src/plugins/tools/view3d/view3d_plugin.h | 82 + .../src/plugins/tools/view3d/view3d_tool.cpp | 88 + .../src/plugins/tools/view3d/view3d_tool.h | 76 + .../widgets/q3iconview/q3iconview_extrainfo.cpp | 183 + .../widgets/q3iconview/q3iconview_extrainfo.h | 95 + .../widgets/q3iconview/q3iconview_plugin.cpp | 120 + .../plugins/widgets/q3iconview/q3iconview_plugin.h | 76 + .../widgets/q3listbox/q3listbox_extrainfo.cpp | 151 + .../widgets/q3listbox/q3listbox_extrainfo.h | 93 + .../plugins/widgets/q3listbox/q3listbox_plugin.cpp | 121 + .../plugins/widgets/q3listbox/q3listbox_plugin.h | 76 + .../widgets/q3listview/q3listview_extrainfo.cpp | 249 + .../widgets/q3listview/q3listview_extrainfo.h | 96 + .../widgets/q3listview/q3listview_plugin.cpp | 121 + .../plugins/widgets/q3listview/q3listview_plugin.h | 76 + .../q3mainwindow/q3mainwindow_container.cpp | 130 + .../widgets/q3mainwindow/q3mainwindow_container.h | 84 + .../widgets/q3mainwindow/q3mainwindow_plugin.cpp | 118 + .../widgets/q3mainwindow/q3mainwindow_plugin.h | 76 + .../plugins/widgets/q3table/q3table_extrainfo.cpp | 196 + .../plugins/widgets/q3table/q3table_extrainfo.h | 93 + .../src/plugins/widgets/q3table/q3table_plugin.cpp | 121 + .../src/plugins/widgets/q3table/q3table_plugin.h | 76 + .../widgets/q3textedit/q3textedit_extrainfo.cpp | 116 + .../widgets/q3textedit/q3textedit_extrainfo.h | 93 + .../widgets/q3textedit/q3textedit_plugin.cpp | 122 + .../plugins/widgets/q3textedit/q3textedit_plugin.h | 76 + .../widgets/q3toolbar/q3toolbar_extrainfo.cpp | 108 + .../widgets/q3toolbar/q3toolbar_extrainfo.h | 92 + .../plugins/widgets/q3toolbar/q3toolbar_plugin.cpp | 128 + .../plugins/widgets/q3toolbar/q3toolbar_plugin.h | 76 + .../plugins/widgets/q3widgets/q3widget_plugins.cpp | 601 + .../plugins/widgets/q3widgets/q3widget_plugins.h | 287 + .../q3widgetstack/q3widgetstack_container.cpp | 115 + .../q3widgetstack/q3widgetstack_container.h | 84 + .../widgets/q3widgetstack/q3widgetstack_plugin.cpp | 118 + .../widgets/q3widgetstack/q3widgetstack_plugin.h | 76 + .../q3widgetstack/qdesigner_q3widgetstack.cpp | 217 + .../q3widgetstack/qdesigner_q3widgetstack_p.h | 108 + .../widgets/q3wizard/q3wizard_container.cpp | 235 + .../plugins/widgets/q3wizard/q3wizard_container.h | 149 + .../plugins/widgets/q3wizard/q3wizard_plugin.cpp | 128 + .../src/plugins/widgets/q3wizard/q3wizard_plugin.h | 76 + .../src/plugins/widgets/qt3supportwidgets.cpp | 107 + src/designer/src/plugins/widgets/widgets.pro | 82 + src/designer/src/sharedcomponents.pri | 30 + src/designer/src/src.pro | 12 + src/doxygen/config/footer.html | 8 + src/doxygen/config/header.html | 30 + src/doxygen/config/phonon.css | 114 + src/doxygen/config/phonon.doxyfile | 220 + src/kmap2qmap/kmap2qmap.pro | 12 + src/kmap2qmap/main.cpp | 991 ++ src/linguist/lconvert/lconvert.pro | 22 + src/linguist/lconvert/main.cpp | 301 + src/linguist/linguist.pro | 6 + src/linguist/linguist/Info_mac.plist | 18 + src/linguist/linguist/batchtranslation.ui | 260 + src/linguist/linguist/batchtranslationdialog.cpp | 194 + src/linguist/linguist/batchtranslationdialog.h | 87 + src/linguist/linguist/errorsview.cpp | 118 + src/linguist/linguist/errorsview.h | 78 + src/linguist/linguist/finddialog.cpp | 94 + src/linguist/linguist/finddialog.h | 69 + src/linguist/linguist/finddialog.ui | 266 + src/linguist/linguist/formpreviewview.cpp | 537 + src/linguist/linguist/formpreviewview.h | 128 + src/linguist/linguist/globals.cpp | 55 + src/linguist/linguist/globals.h | 50 + src/linguist/linguist/images/appicon.png | Bin 0 -> 1382 bytes src/linguist/linguist/images/down.png | Bin 0 -> 594 bytes src/linguist/linguist/images/editdelete.png | Bin 0 -> 831 bytes .../linguist/images/icons/linguist-128-32.png | Bin 0 -> 5960 bytes .../linguist/images/icons/linguist-128-8.png | Bin 0 -> 5947 bytes .../linguist/images/icons/linguist-16-32.png | Bin 0 -> 537 bytes .../linguist/images/icons/linguist-16-8.png | Bin 0 -> 608 bytes .../linguist/images/icons/linguist-32-32.png | Bin 0 -> 1382 bytes .../linguist/images/icons/linguist-32-8.png | Bin 0 -> 1369 bytes .../linguist/images/icons/linguist-48-32.png | Bin 0 -> 2017 bytes .../linguist/images/icons/linguist-48-8.png | Bin 0 -> 1972 bytes .../linguist/images/icons/linguist-64-32.png | Bin 0 -> 2773 bytes .../linguist/images/icons/linguist-64-8.png | Bin 0 -> 2664 bytes src/linguist/linguist/images/mac/accelerator.png | Bin 0 -> 1921 bytes src/linguist/linguist/images/mac/book.png | Bin 0 -> 1477 bytes src/linguist/linguist/images/mac/doneandnext.png | Bin 0 -> 1590 bytes src/linguist/linguist/images/mac/editcopy.png | Bin 0 -> 1468 bytes src/linguist/linguist/images/mac/editcut.png | Bin 0 -> 1512 bytes src/linguist/linguist/images/mac/editpaste.png | Bin 0 -> 1906 bytes src/linguist/linguist/images/mac/filenew.png | Bin 0 -> 1172 bytes src/linguist/linguist/images/mac/fileopen.png | Bin 0 -> 2168 bytes src/linguist/linguist/images/mac/fileprint.png | Bin 0 -> 741 bytes src/linguist/linguist/images/mac/filesave.png | Bin 0 -> 1206 bytes src/linguist/linguist/images/mac/next.png | Bin 0 -> 1056 bytes .../linguist/images/mac/nextunfinished.png | Bin 0 -> 1756 bytes src/linguist/linguist/images/mac/phrase.png | Bin 0 -> 1932 bytes src/linguist/linguist/images/mac/prev.png | Bin 0 -> 1080 bytes .../linguist/images/mac/prevunfinished.png | Bin 0 -> 1682 bytes src/linguist/linguist/images/mac/print.png | Bin 0 -> 2087 bytes src/linguist/linguist/images/mac/punctuation.png | Bin 0 -> 1593 bytes src/linguist/linguist/images/mac/redo.png | Bin 0 -> 1752 bytes src/linguist/linguist/images/mac/searchfind.png | Bin 0 -> 1836 bytes src/linguist/linguist/images/mac/undo.png | Bin 0 -> 1746 bytes .../linguist/images/mac/validateplacemarkers.png | Bin 0 -> 1452 bytes src/linguist/linguist/images/mac/whatsthis.png | Bin 0 -> 1586 bytes src/linguist/linguist/images/minus.png | Bin 0 -> 296 bytes src/linguist/linguist/images/plus.png | Bin 0 -> 383 bytes src/linguist/linguist/images/s_check_danger.png | Bin 0 -> 304 bytes src/linguist/linguist/images/s_check_empty.png | Bin 0 -> 404 bytes src/linguist/linguist/images/s_check_obsolete.png | Bin 0 -> 192 bytes src/linguist/linguist/images/s_check_off.png | Bin 0 -> 434 bytes src/linguist/linguist/images/s_check_on.png | Bin 0 -> 192 bytes src/linguist/linguist/images/s_check_warning.png | Bin 0 -> 192 bytes src/linguist/linguist/images/splash.png | Bin 0 -> 15637 bytes src/linguist/linguist/images/up.png | Bin 0 -> 692 bytes src/linguist/linguist/images/win/accelerator.png | Bin 0 -> 1335 bytes src/linguist/linguist/images/win/book.png | Bin 0 -> 1109 bytes src/linguist/linguist/images/win/doneandnext.png | Bin 0 -> 1233 bytes src/linguist/linguist/images/win/editcopy.png | Bin 0 -> 1325 bytes src/linguist/linguist/images/win/editcut.png | Bin 0 -> 1384 bytes src/linguist/linguist/images/win/editpaste.png | Bin 0 -> 1482 bytes src/linguist/linguist/images/win/filenew.png | Bin 0 -> 768 bytes src/linguist/linguist/images/win/fileopen.png | Bin 0 -> 1662 bytes src/linguist/linguist/images/win/filesave.png | Bin 0 -> 1205 bytes src/linguist/linguist/images/win/next.png | Bin 0 -> 1038 bytes .../linguist/images/win/nextunfinished.png | Bin 0 -> 1257 bytes src/linguist/linguist/images/win/phrase.png | Bin 0 -> 1371 bytes src/linguist/linguist/images/win/prev.png | Bin 0 -> 898 bytes .../linguist/images/win/prevunfinished.png | Bin 0 -> 1260 bytes src/linguist/linguist/images/win/print.png | Bin 0 -> 1456 bytes src/linguist/linguist/images/win/punctuation.png | Bin 0 -> 1508 bytes src/linguist/linguist/images/win/redo.png | Bin 0 -> 1212 bytes src/linguist/linguist/images/win/searchfind.png | Bin 0 -> 1944 bytes src/linguist/linguist/images/win/undo.png | Bin 0 -> 1181 bytes .../linguist/images/win/validateplacemarkers.png | Bin 0 -> 1994 bytes src/linguist/linguist/images/win/whatsthis.png | Bin 0 -> 1040 bytes src/linguist/linguist/linguist.icns | Bin 0 -> 152596 bytes src/linguist/linguist/linguist.ico | Bin 0 -> 355574 bytes src/linguist/linguist/linguist.pro | 96 + src/linguist/linguist/linguist.qrc | 57 + src/linguist/linguist/linguist.rc | 32 + src/linguist/linguist/main.cpp | 121 + src/linguist/linguist/mainwindow.cpp | 2724 +++++ src/linguist/linguist/mainwindow.h | 267 + src/linguist/linguist/mainwindow.ui | 892 ++ src/linguist/linguist/messageeditor.cpp | 880 ++ src/linguist/linguist/messageeditor.h | 180 + src/linguist/linguist/messageeditorwidgets.cpp | 456 + src/linguist/linguist/messageeditorwidgets.h | 184 + src/linguist/linguist/messagehighlighter.cpp | 210 + src/linguist/linguist/messagehighlighter.h | 83 + src/linguist/linguist/messagemodel.cpp | 1426 +++ src/linguist/linguist/messagemodel.h | 535 + src/linguist/linguist/phrase.cpp | 355 + src/linguist/linguist/phrase.h | 138 + src/linguist/linguist/phrasebookbox.cpp | 242 + src/linguist/linguist/phrasebookbox.h | 89 + src/linguist/linguist/phrasebookbox.ui | 236 + src/linguist/linguist/phrasemodel.cpp | 200 + src/linguist/linguist/phrasemodel.h | 94 + src/linguist/linguist/phraseview.cpp | 272 + src/linguist/linguist/phraseview.h | 120 + src/linguist/linguist/printout.cpp | 210 + src/linguist/linguist/printout.h | 120 + src/linguist/linguist/recentfiles.cpp | 146 + src/linguist/linguist/recentfiles.h | 83 + src/linguist/linguist/sourcecodeview.cpp | 145 + src/linguist/linguist/sourcecodeview.h | 74 + src/linguist/linguist/statistics.cpp | 67 + src/linguist/linguist/statistics.h | 67 + src/linguist/linguist/statistics.ui | 211 + src/linguist/linguist/translatedialog.cpp | 90 + src/linguist/linguist/translatedialog.h | 89 + src/linguist/linguist/translatedialog.ui | 260 + src/linguist/linguist/translationsettings.ui | 137 + .../linguist/translationsettingsdialog.cpp | 166 + src/linguist/linguist/translationsettingsdialog.h | 81 + src/linguist/lrelease/lrelease.1 | 118 + src/linguist/lrelease/lrelease.pro | 23 + src/linguist/lrelease/main.cpp | 391 + src/linguist/lupdate/cpp.cpp | 2245 ++++ src/linguist/lupdate/java.cpp | 645 ++ src/linguist/lupdate/lupdate.1 | 153 + src/linguist/lupdate/lupdate.exe.manifest | 14 + src/linguist/lupdate/lupdate.h | 86 + src/linguist/lupdate/lupdate.pro | 49 + src/linguist/lupdate/main.cpp | 730 ++ src/linguist/lupdate/merge.cpp | 515 + src/linguist/lupdate/qdeclarative.cpp | 433 + src/linguist/lupdate/qscript.cpp | 2612 +++++ src/linguist/lupdate/qscript.g | 2261 ++++ src/linguist/lupdate/ui.cpp | 208 + src/linguist/lupdate/winmanifest.rc | 4 + src/linguist/phrasebooks/danish.qph | 1018 ++ src/linguist/phrasebooks/dutch.qph | 1044 ++ src/linguist/phrasebooks/finnish.qph | 1033 ++ src/linguist/phrasebooks/french.qph | 1493 +++ src/linguist/phrasebooks/german.qph | 1075 ++ src/linguist/phrasebooks/hungarian.qph | 752 ++ src/linguist/phrasebooks/italian.qph | 1105 ++ src/linguist/phrasebooks/japanese.qph | 1021 ++ src/linguist/phrasebooks/norwegian.qph | 1004 ++ src/linguist/phrasebooks/polish.qph | 527 + src/linguist/phrasebooks/russian.qph | 1219 ++ src/linguist/phrasebooks/spanish.qph | 1086 ++ src/linguist/phrasebooks/swedish.qph | 1010 ++ src/linguist/qdoc.conf | 15 + src/linguist/shared/abstractproitemvisitor.h | 74 + src/linguist/shared/formats.pri | 22 + src/linguist/shared/numerus.cpp | 404 + src/linguist/shared/po.cpp | 902 ++ src/linguist/shared/profileevaluator.cpp | 2627 +++++ src/linguist/shared/profileevaluator.h | 116 + src/linguist/shared/proitems.cpp | 358 + src/linguist/shared/proitems.h | 248 + src/linguist/shared/proparser.pri | 12 + src/linguist/shared/proparserutils.h | 324 + src/linguist/shared/qm.cpp | 803 ++ src/linguist/shared/qph.cpp | 207 + src/linguist/shared/simtexth.cpp | 277 + src/linguist/shared/simtexth.h | 100 + src/linguist/shared/translator.cpp | 759 ++ src/linguist/shared/translator.h | 246 + src/linguist/shared/translatormessage.cpp | 187 + src/linguist/shared/translatormessage.h | 181 + src/linguist/shared/ts.cpp | 781 ++ src/linguist/shared/ts.dtd | 100 + src/linguist/shared/xliff.cpp | 851 ++ src/linguist/tests/data/main.cpp | 75 + src/linguist/tests/data/test.pro | 9 + src/linguist/tests/tests.pro | 16 + src/linguist/tests/tst_linguist.cpp | 45 + src/linguist/tests/tst_linguist.h | 63 + src/linguist/tests/tst_lupdate.cpp | 195 + src/linguist/tests/tst_simtexth.cpp | 73 + src/macdeployqt/macchangeqt/macchangeqt.pro | 9 + src/macdeployqt/macchangeqt/main.cpp | 76 + src/macdeployqt/macdeployqt.pro | 7 + src/macdeployqt/macdeployqt/macdeployqt.pro | 13 + src/macdeployqt/macdeployqt/main.cpp | 135 + src/macdeployqt/shared/shared.cpp | 586 + src/macdeployqt/shared/shared.h | 110 + src/macdeployqt/tests/deployment_mac.pro | 10 + src/macdeployqt/tests/tst_deployment_mac.cpp | 233 + src/makeqpf/Blocks.txt | 185 + src/makeqpf/README | 1 + src/makeqpf/main.cpp | 183 + src/makeqpf/mainwindow.cpp | 322 + src/makeqpf/mainwindow.h | 80 + src/makeqpf/mainwindow.ui | 502 + src/makeqpf/makeqpf.pro | 20 + src/makeqpf/makeqpf.qrc | 5 + src/makeqpf/qpf2.cpp | 767 ++ src/makeqpf/qpf2.h | 119 + src/pixeltool/Info_mac.plist | 18 + src/pixeltool/main.cpp | 65 + src/pixeltool/pixeltool.pro | 25 + src/pixeltool/qpixeltool.cpp | 536 + src/pixeltool/qpixeltool.h | 118 + src/qconfig/feature.cpp | 240 + src/qconfig/feature.h | 125 + src/qconfig/featuretreemodel.cpp | 451 + src/qconfig/featuretreemodel.h | 104 + src/qconfig/graphics.h | 195 + src/qconfig/main.cpp | 544 + src/qconfig/qconfig.pro | 9 + src/qdbus/qdbus.pro | 3 + src/qdbus/qdbus/qdbus.cpp | 528 + src/qdbus/qdbus/qdbus.pro | 10 + src/qdbus/qdbuscpp2xml/qdbuscpp2xml.cpp | 446 + src/qdbus/qdbuscpp2xml/qdbuscpp2xml.pro | 10 + src/qdbus/qdbusviewer/Info_mac.plist | 18 + src/qdbus/qdbusviewer/images/qdbusviewer-128.png | Bin 0 -> 9850 bytes src/qdbus/qdbusviewer/images/qdbusviewer.icns | Bin 0 -> 146951 bytes src/qdbus/qdbusviewer/images/qdbusviewer.ico | Bin 0 -> 355574 bytes src/qdbus/qdbusviewer/images/qdbusviewer.png | Bin 0 -> 1231 bytes src/qdbus/qdbusviewer/main.cpp | 85 + src/qdbus/qdbusviewer/propertydialog.cpp | 114 + src/qdbus/qdbusviewer/propertydialog.h | 70 + src/qdbus/qdbusviewer/qdbusmodel.cpp | 350 + src/qdbus/qdbusviewer/qdbusmodel.h | 95 + src/qdbus/qdbusviewer/qdbusviewer.cpp | 521 + src/qdbus/qdbusviewer/qdbusviewer.h | 103 + src/qdbus/qdbusviewer/qdbusviewer.pro | 30 + src/qdbus/qdbusviewer/qdbusviewer.qrc | 6 + src/qdbus/qdbusviewer/qdbusviewer.rc | 1 + src/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp | 1144 ++ src/qdbus/qdbusxml2cpp/qdbusxml2cpp.pro | 10 + src/qev/README | 2 + src/qev/qev.cpp | 66 + src/qev/qev.pro | 11 + src/qmeegographicssystemhelper/qmeegofencesync.cpp | 79 + src/qmeegographicssystemhelper/qmeegofencesync.h | 101 + src/qmeegographicssystemhelper/qmeegofencesync_p.h | 60 + .../qmeegographicssystemhelper.cpp | 147 + .../qmeegographicssystemhelper.h | 235 + .../qmeegographicssystemhelper.pro | 10 + .../qmeegolivepixmap.cpp | 117 + src/qmeegographicssystemhelper/qmeegolivepixmap.h | 112 + .../qmeegolivepixmap_p.h | 57 + .../qmeegooverlaywidget.cpp | 102 + .../qmeegooverlaywidget.h | 86 + src/qmeegographicssystemhelper/qmeegoruntime.cpp | 302 + src/qmeegographicssystemhelper/qmeegoruntime.h | 76 + .../qmeegoswitchevent.cpp | 68 + src/qmeegographicssystemhelper/qmeegoswitchevent.h | 91 + src/qtconcurrent/codegenerator/codegenerator.pri | 5 + src/qtconcurrent/codegenerator/example/example.pro | 9 + src/qtconcurrent/codegenerator/example/main.cpp | 83 + .../codegenerator/src/codegenerator.cpp | 140 + src/qtconcurrent/codegenerator/src/codegenerator.h | 204 + src/qtconcurrent/generaterun/main.cpp | 418 + src/qtconcurrent/generaterun/run.pro | 9 + src/qtconfig/colorbutton.cpp | 207 + src/qtconfig/colorbutton.h | 90 + src/qtconfig/images/appicon.png | Bin 0 -> 2238 bytes src/qtconfig/main.cpp | 69 + src/qtconfig/mainwindow.cpp | 956 ++ src/qtconfig/mainwindow.h | 109 + src/qtconfig/mainwindow.ui | 1388 +++ src/qtconfig/paletteeditoradvanced.cpp | 401 + src/qtconfig/paletteeditoradvanced.h | 106 + src/qtconfig/paletteeditoradvanced.ui | 416 + src/qtconfig/previewframe.cpp | 104 + src/qtconfig/previewframe.h | 83 + src/qtconfig/previewwidget.cpp | 89 + src/qtconfig/previewwidget.h | 70 + src/qtconfig/previewwidget.ui | 252 + src/qtconfig/qtconfig.pro | 28 + src/qtconfig/qtconfig.qrc | 5 + src/qtestlib/qtestlib.pro | 4 + src/qtestlib/updater/main.cpp | 178 + src/qtestlib/updater/updater.pro | 10 + src/qtestlib/wince/cetcpsync/cetcpsync.pro | 22 + src/qtestlib/wince/cetcpsync/main.cpp | 191 + .../wince/cetcpsync/qtcesterconnection.cpp | 552 + src/qtestlib/wince/cetcpsync/qtcesterconnection.h | 86 + src/qtestlib/wince/cetcpsync/remoteconnection.cpp | 65 + src/qtestlib/wince/cetcpsync/remoteconnection.h | 81 + .../wince/cetcpsyncserver/cetcpsyncserver.pro | 17 + src/qtestlib/wince/cetcpsyncserver/commands.cpp | 686 ++ src/qtestlib/wince/cetcpsyncserver/commands.h | 292 + .../wince/cetcpsyncserver/connectionmanager.cpp | 138 + .../wince/cetcpsyncserver/connectionmanager.h | 83 + src/qtestlib/wince/cetcpsyncserver/main.cpp | 63 + .../wince/cetcpsyncserver/transfer_global.h | 159 + src/qtestlib/wince/cetest/activesyncconnection.cpp | 640 ++ src/qtestlib/wince/cetest/activesyncconnection.h | 89 + src/qtestlib/wince/cetest/bootstrapped.pri | 45 + src/qtestlib/wince/cetest/cetcpsyncconnection.cpp | 221 + src/qtestlib/wince/cetest/cetcpsyncconnection.h | 85 + src/qtestlib/wince/cetest/cetest.pro | 56 + src/qtestlib/wince/cetest/deployment.cpp | 293 + src/qtestlib/wince/cetest/deployment.h | 75 + src/qtestlib/wince/cetest/main.cpp | 445 + src/qtestlib/wince/cetest/qmake_include.pri | 13 + src/qtestlib/wince/cetest/remoteconnection.cpp | 100 + src/qtestlib/wince/cetest/remoteconnection.h | 84 + src/qtestlib/wince/remotelib/commands.cpp | 212 + src/qtestlib/wince/remotelib/commands.h | 54 + src/qtestlib/wince/remotelib/remotelib.pro | 15 + src/qtestlib/wince/wince.pro | 2 + src/qttracereplay/main.cpp | 351 + src/qttracereplay/qttracereplay.pro | 15 + src/qvfb/README | 51 + src/qvfb/config.ui | 2472 ++++ src/qvfb/gammaview.h | 59 + src/qvfb/images/logo-nt.png | Bin 0 -> 1965 bytes src/qvfb/images/logo.png | Bin 0 -> 2238 bytes src/qvfb/main.cpp | 168 + src/qvfb/qanimationwriter.cpp | 453 + src/qvfb/qanimationwriter.h | 71 + src/qvfb/qtopiakeysym.h | 68 + src/qvfb/qvfb.cpp | 1147 ++ src/qvfb/qvfb.h | 159 + src/qvfb/qvfb.pro | 64 + src/qvfb/qvfb.qrc | 7 + src/qvfb/qvfbmmap.cpp | 222 + src/qvfb/qvfbmmap.h | 91 + src/qvfb/qvfbprotocol.cpp | 195 + src/qvfb/qvfbprotocol.h | 173 + src/qvfb/qvfbratedlg.cpp | 103 + src/qvfb/qvfbratedlg.h | 74 + src/qvfb/qvfbshmem.cpp | 314 + src/qvfb/qvfbshmem.h | 90 + src/qvfb/qvfbview.cpp | 888 ++ src/qvfb/qvfbview.h | 214 + src/qvfb/qvfbx11view.cpp | 389 + src/qvfb/qvfbx11view.h | 122 + src/qvfb/x11keyfaker.cpp | 627 ++ src/qvfb/x11keyfaker.h | 81 + src/runonphone/main.cpp | 277 + src/runonphone/ossignalconverter.cpp | 121 + src/runonphone/ossignalconverter.h | 63 + src/runonphone/ossignalconverter_p.h | 71 + src/runonphone/runonphone.pro | 35 + src/runonphone/serenum.h | 56 + src/runonphone/serenum_stub.cpp | 53 + src/runonphone/serenum_unix.cpp | 224 + src/runonphone/serenum_win.cpp | 105 + src/runonphone/symbianutils/bluetoothlistener.cpp | 224 + src/runonphone/symbianutils/bluetoothlistener.h | 103 + .../symbianutils/bluetoothlistener_gui.cpp | 111 + .../symbianutils/bluetoothlistener_gui.h | 89 + src/runonphone/symbianutils/callback.h | 160 + .../symbianutils/communicationstarter.cpp | 251 + src/runonphone/symbianutils/communicationstarter.h | 160 + src/runonphone/symbianutils/json.cpp | 490 + src/runonphone/symbianutils/json.h | 149 + src/runonphone/symbianutils/launcher.cpp | 1036 ++ src/runonphone/symbianutils/launcher.h | 212 + .../symbianutils/symbiandevicemanager.cpp | 489 + src/runonphone/symbianutils/symbiandevicemanager.h | 178 + src/runonphone/symbianutils/symbianutils.pri | 35 + src/runonphone/symbianutils/symbianutils_global.h | 55 + src/runonphone/symbianutils/tcftrkdevice.cpp | 929 ++ src/runonphone/symbianutils/tcftrkdevice.h | 295 + src/runonphone/symbianutils/tcftrkmessage.cpp | 562 + src/runonphone/symbianutils/tcftrkmessage.h | 296 + src/runonphone/symbianutils/trkdevice.cpp | 1184 ++ src/runonphone/symbianutils/trkdevice.h | 143 + src/runonphone/symbianutils/trkutils.cpp | 603 + src/runonphone/symbianutils/trkutils.h | 261 + src/runonphone/symbianutils/trkutils_p.h | 62 + src/runonphone/trksignalhandler.cpp | 368 + src/runonphone/trksignalhandler.h | 88 + src/shared/deviceskin/deviceskin.cpp | 857 ++ src/shared/deviceskin/deviceskin.h | 174 + src/shared/deviceskin/deviceskin.pri | 12 + src/shared/deviceskin/skins/ClamshellPhone.qrc | 5 + .../skins/ClamshellPhone.skin/ClamshellPhone.skin | 30 + .../ClamshellPhone1-5-closed.png | Bin 0 -> 68200 bytes .../ClamshellPhone1-5-pressed.png | Bin 0 -> 113907 bytes .../ClamshellPhone.skin/ClamshellPhone1-5.png | Bin 0 -> 113450 bytes .../skins/ClamshellPhone.skin/defaultbuttons.conf | 78 + src/shared/deviceskin/skins/PortableMedia.qrc | 5 + .../skins/PortableMedia.skin/PortableMedia.skin | 14 + .../skins/PortableMedia.skin/defaultbuttons.conf | 23 + .../PortableMedia.skin/portablemedia-pressed.png | Bin 0 -> 6183 bytes .../skins/PortableMedia.skin/portablemedia.png | Bin 0 -> 6182 bytes .../skins/PortableMedia.skin/portablemedia.xcf | Bin 0 -> 41592 bytes src/shared/deviceskin/skins/S60-QVGA-Candybar.qrc | 5 + .../S60-QVGA-Candybar-down.png | Bin 0 -> 161184 bytes .../S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png | Bin 0 -> 156789 bytes .../S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin | 15 + .../S60-QVGA-Candybar.skin/defaultbuttons.conf | 78 + .../deviceskin/skins/S60-nHD-Touchscreen.qrc | 5 + .../S60-nHD-Touchscreen-down.png | Bin 0 -> 241501 bytes .../S60-nHD-Touchscreen.png | Bin 0 -> 240615 bytes .../S60-nHD-Touchscreen.skin | 10 + .../S60-nHD-Touchscreen.skin/defaultbuttons.conf | 53 + src/shared/deviceskin/skins/SmartPhone.qrc | 5 + .../skins/SmartPhone.skin/SmartPhone-pressed.png | Bin 0 -> 111515 bytes .../skins/SmartPhone.skin/SmartPhone.png | Bin 0 -> 101750 bytes .../skins/SmartPhone.skin/SmartPhone.skin | 28 + .../skins/SmartPhone.skin/defaultbuttons.conf | 78 + src/shared/deviceskin/skins/SmartPhone2.qrc | 5 + .../skins/SmartPhone2.skin/SmartPhone2-pressed.png | Bin 0 -> 134749 bytes .../skins/SmartPhone2.skin/SmartPhone2.png | Bin 0 -> 121915 bytes .../skins/SmartPhone2.skin/SmartPhone2.skin | 25 + .../skins/SmartPhone2.skin/defaultbuttons.conf | 52 + .../deviceskin/skins/SmartPhoneWithButtons.qrc | 5 + .../SmartPhoneWithButtons-pressed.png | Bin 0 -> 103838 bytes .../SmartPhoneWithButtons.png | Bin 0 -> 88470 bytes .../SmartPhoneWithButtons.skin | 31 + .../SmartPhoneWithButtons.skin/defaultbuttons.conf | 103 + src/shared/deviceskin/skins/TouchscreenPhone.qrc | 5 + .../TouchscreenPhone-pressed.png | Bin 0 -> 88599 bytes .../TouchscreenPhone.skin/TouchscreenPhone.png | Bin 0 -> 61809 bytes .../TouchscreenPhone.skin/TouchscreenPhone.skin | 16 + .../TouchscreenPhone.skin/defaultbuttons.conf | 45 + src/shared/findwidget/abstractfindwidget.cpp | 295 + src/shared/findwidget/abstractfindwidget.h | 115 + src/shared/findwidget/findwidget.pri | 4 + src/shared/findwidget/findwidget.qrc | 14 + src/shared/findwidget/images/mac/closetab.png | Bin 0 -> 516 bytes src/shared/findwidget/images/mac/next.png | Bin 0 -> 1310 bytes src/shared/findwidget/images/mac/previous.png | Bin 0 -> 1080 bytes src/shared/findwidget/images/mac/searchfind.png | Bin 0 -> 1836 bytes src/shared/findwidget/images/win/closetab.png | Bin 0 -> 375 bytes src/shared/findwidget/images/win/next.png | Bin 0 -> 1038 bytes src/shared/findwidget/images/win/previous.png | Bin 0 -> 898 bytes src/shared/findwidget/images/win/searchfind.png | Bin 0 -> 1944 bytes src/shared/findwidget/images/wrap.png | Bin 0 -> 500 bytes src/shared/findwidget/itemviewfindwidget.cpp | 317 + src/shared/findwidget/itemviewfindwidget.h | 78 + src/shared/findwidget/texteditfindwidget.cpp | 169 + src/shared/findwidget/texteditfindwidget.h | 73 + src/shared/fontpanel/fontpanel.cpp | 308 + src/shared/fontpanel/fontpanel.h | 108 + src/shared/fontpanel/fontpanel.pri | 3 + src/shared/qtgradienteditor/images/down.png | Bin 0 -> 594 bytes src/shared/qtgradienteditor/images/edit.png | Bin 0 -> 503 bytes src/shared/qtgradienteditor/images/editdelete.png | Bin 0 -> 831 bytes src/shared/qtgradienteditor/images/minus.png | Bin 0 -> 250 bytes src/shared/qtgradienteditor/images/plus.png | Bin 0 -> 462 bytes src/shared/qtgradienteditor/images/spreadpad.png | Bin 0 -> 151 bytes .../qtgradienteditor/images/spreadreflect.png | Bin 0 -> 165 bytes .../qtgradienteditor/images/spreadrepeat.png | Bin 0 -> 156 bytes src/shared/qtgradienteditor/images/typeconical.png | Bin 0 -> 937 bytes src/shared/qtgradienteditor/images/typelinear.png | Bin 0 -> 145 bytes src/shared/qtgradienteditor/images/typeradial.png | Bin 0 -> 583 bytes src/shared/qtgradienteditor/images/up.png | Bin 0 -> 692 bytes src/shared/qtgradienteditor/images/zoomin.png | Bin 0 -> 1208 bytes src/shared/qtgradienteditor/images/zoomout.png | Bin 0 -> 1226 bytes src/shared/qtgradienteditor/qtcolorbutton.cpp | 272 + src/shared/qtgradienteditor/qtcolorbutton.h | 86 + src/shared/qtgradienteditor/qtcolorbutton.pri | 4 + src/shared/qtgradienteditor/qtcolorline.cpp | 1122 ++ src/shared/qtgradienteditor/qtcolorline.h | 124 + src/shared/qtgradienteditor/qtgradientdialog.cpp | 353 + src/shared/qtgradienteditor/qtgradientdialog.h | 87 + src/shared/qtgradienteditor/qtgradientdialog.ui | 121 + src/shared/qtgradienteditor/qtgradienteditor.cpp | 952 ++ src/shared/qtgradienteditor/qtgradienteditor.h | 111 + src/shared/qtgradienteditor/qtgradienteditor.pri | 33 + src/shared/qtgradienteditor/qtgradienteditor.qrc | 18 + src/shared/qtgradienteditor/qtgradienteditor.ui | 1377 +++ src/shared/qtgradienteditor/qtgradientmanager.cpp | 135 + src/shared/qtgradienteditor/qtgradientmanager.h | 92 + .../qtgradienteditor/qtgradientstopscontroller.cpp | 724 ++ .../qtgradienteditor/qtgradientstopscontroller.h | 106 + .../qtgradienteditor/qtgradientstopsmodel.cpp | 477 + src/shared/qtgradienteditor/qtgradientstopsmodel.h | 121 + .../qtgradienteditor/qtgradientstopswidget.cpp | 1154 ++ .../qtgradienteditor/qtgradientstopswidget.h | 115 + src/shared/qtgradienteditor/qtgradientutils.cpp | 420 + src/shared/qtgradienteditor/qtgradientutils.h | 66 + src/shared/qtgradienteditor/qtgradientview.cpp | 292 + src/shared/qtgradienteditor/qtgradientview.h | 99 + src/shared/qtgradienteditor/qtgradientview.ui | 135 + .../qtgradienteditor/qtgradientviewdialog.cpp | 89 + src/shared/qtgradienteditor/qtgradientviewdialog.h | 75 + .../qtgradienteditor/qtgradientviewdialog.ui | 121 + src/shared/qtgradienteditor/qtgradientwidget.cpp | 815 ++ src/shared/qtgradienteditor/qtgradientwidget.h | 120 + .../qtpropertybrowser/images/cursor-arrow.png | Bin 0 -> 171 bytes .../qtpropertybrowser/images/cursor-busy.png | Bin 0 -> 201 bytes .../qtpropertybrowser/images/cursor-closedhand.png | Bin 0 -> 147 bytes .../qtpropertybrowser/images/cursor-cross.png | Bin 0 -> 130 bytes .../qtpropertybrowser/images/cursor-forbidden.png | Bin 0 -> 199 bytes .../qtpropertybrowser/images/cursor-hand.png | Bin 0 -> 159 bytes .../qtpropertybrowser/images/cursor-hsplit.png | Bin 0 -> 155 bytes .../qtpropertybrowser/images/cursor-ibeam.png | Bin 0 -> 124 bytes .../qtpropertybrowser/images/cursor-openhand.png | Bin 0 -> 160 bytes .../qtpropertybrowser/images/cursor-sizeall.png | Bin 0 -> 174 bytes .../qtpropertybrowser/images/cursor-sizeb.png | Bin 0 -> 161 bytes .../qtpropertybrowser/images/cursor-sizef.png | Bin 0 -> 161 bytes .../qtpropertybrowser/images/cursor-sizeh.png | Bin 0 -> 145 bytes .../qtpropertybrowser/images/cursor-sizev.png | Bin 0 -> 141 bytes .../qtpropertybrowser/images/cursor-uparrow.png | Bin 0 -> 132 bytes .../qtpropertybrowser/images/cursor-vsplit.png | Bin 0 -> 161 bytes .../qtpropertybrowser/images/cursor-wait.png | Bin 0 -> 172 bytes .../qtpropertybrowser/images/cursor-whatsthis.png | Bin 0 -> 191 bytes .../qtpropertybrowser/qtbuttonpropertybrowser.cpp | 627 ++ .../qtpropertybrowser/qtbuttonpropertybrowser.h | 85 + src/shared/qtpropertybrowser/qteditorfactory.cpp | 2560 +++++ src/shared/qtpropertybrowser/qteditorfactory.h | 397 + .../qtgroupboxpropertybrowser.cpp | 529 + .../qtpropertybrowser/qtgroupboxpropertybrowser.h | 76 + src/shared/qtpropertybrowser/qtpropertybrowser.cpp | 1955 ++++ src/shared/qtpropertybrowser/qtpropertybrowser.h | 309 + src/shared/qtpropertybrowser/qtpropertybrowser.pri | 19 + src/shared/qtpropertybrowser/qtpropertybrowser.qrc | 23 + .../qtpropertybrowser/qtpropertybrowserutils.cpp | 456 + .../qtpropertybrowser/qtpropertybrowserutils.pri | 4 + .../qtpropertybrowser/qtpropertybrowserutils_p.h | 161 + src/shared/qtpropertybrowser/qtpropertymanager.cpp | 6451 +++++++++++ src/shared/qtpropertybrowser/qtpropertymanager.h | 746 ++ .../qtpropertybrowser/qttreepropertybrowser.cpp | 1042 ++ .../qtpropertybrowser/qttreepropertybrowser.h | 134 + src/shared/qtpropertybrowser/qtvariantproperty.cpp | 2268 ++++ src/shared/qtpropertybrowser/qtvariantproperty.h | 177 + src/shared/qttoolbardialog/images/back.png | Bin 0 -> 678 bytes src/shared/qttoolbardialog/images/down.png | Bin 0 -> 594 bytes src/shared/qttoolbardialog/images/forward.png | Bin 0 -> 655 bytes src/shared/qttoolbardialog/images/minus.png | Bin 0 -> 250 bytes src/shared/qttoolbardialog/images/plus.png | Bin 0 -> 462 bytes src/shared/qttoolbardialog/images/up.png | Bin 0 -> 692 bytes src/shared/qttoolbardialog/qttoolbardialog.cpp | 1871 +++ src/shared/qttoolbardialog/qttoolbardialog.h | 138 + src/shared/qttoolbardialog/qttoolbardialog.pri | 6 + src/shared/qttoolbardialog/qttoolbardialog.qrc | 10 + src/shared/qttoolbardialog/qttoolbardialog.ui | 207 + src/tools.pro | 49 + tests/README | 18 + tests/auto/auto.pro | 9 + tests/auto/bic/.gitignore | 2 + .../bic/data/QtDesigner.4.2.0.linux-gcc-ia32.txt | 1985 ++++ .../bic/data/QtDesigner.4.3.0.linux-gcc-ia32.txt | 2169 ++++ .../bic/data/QtDesigner.4.4.0.linux-gcc-ia32.txt | 4431 ++++++++ .../bic/data/QtDesigner.4.5.0.linux-gcc-amd64.txt | 4460 ++++++++ .../bic/data/QtDesigner.4.5.0.linux-gcc-ia32.txt | 4460 ++++++++ .../bic/data/QtDesigner.4.6.0.linux-gcc-amd64.txt | 4741 ++++++++ .../bic/data/QtDesigner.4.6.0.linux-gcc-ia32.txt | 4741 ++++++++ .../bic/data/QtDesigner.4.7.0.linux-gcc-ia32.txt | 4746 ++++++++ .../auto/bic/data/QtHelp.4.5.0.linux-gcc-amd64.txt | 6357 +++++++++++ .../auto/bic/data/QtHelp.4.5.0.linux-gcc-ia32.txt | 6357 +++++++++++ .../auto/bic/data/QtHelp.4.6.0.linux-gcc-amd64.txt | 5492 +++++++++ .../auto/bic/data/QtHelp.4.6.0.linux-gcc-ia32.txt | 5492 +++++++++ .../auto/bic/data/QtHelp.4.7.0.linux-gcc-ia32.txt | 5497 +++++++++ tests/auto/linguist/lconvert/.gitignore | 2 + tests/auto/linguist/lconvert/data/codec-cp1252.ts | 28 + tests/auto/linguist/lconvert/data/codec-utf8.ts | 28 + tests/auto/linguist/lconvert/data/dual-encoding.ts | 11 + .../auto/linguist/lconvert/data/endless-po-loop.ts | 16 + tests/auto/linguist/lconvert/data/makeplurals.pl | 86 + tests/auto/linguist/lconvert/data/msgid.ts | 27 + tests/auto/linguist/lconvert/data/phrasebook.qph | 21 + tests/auto/linguist/lconvert/data/plurals-cn.ts | 17 + tests/auto/linguist/lconvert/data/plurals-de.ts | 18 + tests/auto/linguist/lconvert/data/relative.ts | 74 + tests/auto/linguist/lconvert/data/singular.po | 42 + .../linguist/lconvert/data/test-broken-utf8.po | 9 + .../linguist/lconvert/data/test-broken-utf8.po.out | 12 + .../lconvert/data/test-developer-comment.po | 23 + .../linguist/lconvert/data/test-empty-comment.po | 24 + tests/auto/linguist/lconvert/data/test-escapes.po | 11 + .../linguist/lconvert/data/test-escapes.po.out | 16 + tests/auto/linguist/lconvert/data/test-kde-ctxt.po | 25 + .../auto/linguist/lconvert/data/test-kde-fuzzy.po | 31 + .../linguist/lconvert/data/test-kde-multiline.po | 32 + .../linguist/lconvert/data/test-kde-plurals.po | 27 + tests/auto/linguist/lconvert/data/test-refs.po | 23 + tests/auto/linguist/lconvert/data/test-slurp.po | 19 + .../auto/linguist/lconvert/data/test-slurp.po.out | 22 + .../lconvert/data/test-translator-comment.po | 41 + tests/auto/linguist/lconvert/data/test1-cn.po | 67 + tests/auto/linguist/lconvert/data/test1-de.po | 75 + tests/auto/linguist/lconvert/data/test11.ts | 32 + tests/auto/linguist/lconvert/data/test20.ts | 171 + tests/auto/linguist/lconvert/data/variants.ts | 24 + tests/auto/linguist/lconvert/data/wrapping.po | 57 + tests/auto/linguist/lconvert/lconvert.pro | 8 + tests/auto/linguist/lconvert/tst_lconvert.cpp | 347 + tests/auto/linguist/linguist.pro | 2 + tests/auto/linguist/lrelease/.gitignore | 2 + tests/auto/linguist/lrelease/lrelease.pro | 5 + .../auto/linguist/lrelease/testdata/compressed.ts | 46 + tests/auto/linguist/lrelease/testdata/dupes.errors | 4 + tests/auto/linguist/lrelease/testdata/dupes.ts | 25 + tests/auto/linguist/lrelease/testdata/idbased.ts | 28 + .../linguist/lrelease/testdata/mixedcodecs-ts11.ts | 18 + .../linguist/lrelease/testdata/mixedcodecs-ts20.ts | 18 + tests/auto/linguist/lrelease/testdata/translate.ts | 136 + tests/auto/linguist/lrelease/tst_lrelease.cpp | 241 + tests/auto/linguist/lupdate/.gitignore | 4 + tests/auto/linguist/lupdate/lupdate.pro | 6 + .../lupdate/testdata/good/backslashes/lupdatecmd | 1 + .../lupdate/testdata/good/backslashes/project.pro | 3 + .../lupdate/testdata/good/backslashes/src/main.cpp | 56 + .../testdata/good/backslashes/ts/project.ts.result | 13 + .../testdata/good/cmdline_deeppath/lupdatecmd | 2 + .../good/cmdline_deeppath/project.ts.result | 27 + .../lupdate/testdata/good/cmdline_order/a.h | 42 + .../lupdate/testdata/good/cmdline_order/b.h | 44 + .../lupdate/testdata/good/cmdline_order/lupdatecmd | 1 + .../testdata/good/cmdline_order/project.ts.result | 20 + .../testdata/good/cmdline_recurse/lupdatecmd | 2 + .../good/cmdline_recurse/project.ts.result | 115 + .../lupdate/testdata/good/codecforsrc/main.cpp | 68 + .../lupdate/testdata/good/codecforsrc/project.pro | 7 + .../testdata/good/codecforsrc/project.ts.result | 38 + .../lupdate/testdata/good/codecfortr/main.cpp | 65 + .../lupdate/testdata/good/codecfortr/project.pro | 6 + .../testdata/good/codecfortr/project.ts.result | 13 + .../lupdate/testdata/good/codecfortr1/main.cpp | 63 + .../lupdate/testdata/good/codecfortr1/project.pro | 6 + .../testdata/good/codecfortr1/project.ts.result | 38 + .../lupdate/testdata/good/codecfortr2/main.cpp | 62 + .../lupdate/testdata/good/codecfortr2/project.pro | 7 + .../testdata/good/codecfortr2/project.ts.result | 33 + .../testdata/good/codecfortr3/expectedoutput.txt | 1 + .../lupdate/testdata/good/codecfortr3/main.cpp | 45 + .../lupdate/testdata/good/codecfortr3/project.pro | 4 + .../testdata/good/codecfortr3/project.ts.before | 13 + .../testdata/good/codecfortr3/project.ts.result | 12 + .../testdata/good/codecfortr4/expectedoutput.txt | 0 .../lupdate/testdata/good/codecfortr4/main.cpp | 45 + .../lupdate/testdata/good/codecfortr4/project.pro | 4 + .../testdata/good/codecfortr4/project.ts.before | 13 + .../testdata/good/codecfortr4/project.ts.result | 13 + .../lupdate/testdata/good/from_subdir/lupdatecmd | 1 + .../testdata/good/from_subdir/project.ts.result | 17 + .../lupdate/testdata/good/from_subdir/src/main.cpp | 50 + .../lupdate/testdata/good/from_subdir/src/main.h | 45 + .../good/from_subdir/translations/translations.pro | 7 + .../testdata/good/heuristics/expectedoutput.txt | 5 + .../lupdate/testdata/good/heuristics/lupdatecmd | 2 + .../lupdate/testdata/good/heuristics/main.cpp | 62 + .../lupdate/testdata/good/heuristics/project.pro | 3 + .../testdata/good/heuristics/project.ts.before | 38 + .../testdata/good/heuristics/project.ts.result | 22 + .../testdata/good/lacksqobject/expectedoutput.txt | 4 + .../lupdate/testdata/good/lacksqobject/main.cpp | 88 + .../lupdate/testdata/good/lacksqobject/project.pro | 3 + .../testdata/good/lacksqobject/project.ts.result | 40 + .../lupdate/testdata/good/merge_ordering/foo.cpp | 69 + .../testdata/good/merge_ordering/lupdatecmd | 1 + .../testdata/good/merge_ordering/project.pro | 3 + .../testdata/good/merge_ordering/project.ts.before | 74 + .../testdata/good/merge_ordering/project.ts.result | 82 + .../testdata/good/merge_versions/project.pro | 3 + .../testdata/good/merge_versions/project.ts.before | 14 + .../testdata/good/merge_versions/project.ts.result | 15 + .../testdata/good/merge_versions/project.ui | 72 + .../testdata/good/merge_whitespace/main.cpp | 64 + .../testdata/good/merge_whitespace/project.pro | 3 + .../good/merge_whitespace/project.ts.before | 70 + .../good/merge_whitespace/project.ts.result | 71 + .../lupdate/testdata/good/mergecpp/finddialog.cpp | 82 + .../lupdate/testdata/good/mergecpp/project.pro | 3 + .../testdata/good/mergecpp/project.ts.before | 70 + .../testdata/good/mergecpp/project.ts.result | 74 + .../good/mergecpp_noobsolete/finddialog.cpp | 154 + .../testdata/good/mergecpp_noobsolete/lupdatecmd | 1 + .../testdata/good/mergecpp_noobsolete/project.pro | 3 + .../good/mergecpp_noobsolete/project.ts.before | 44 + .../good/mergecpp_noobsolete/project.ts.result | 35 + .../testdata/good/mergecpp_obsolete/finddialog.cpp | 177 + .../testdata/good/mergecpp_obsolete/project.pro | 3 + .../good/mergecpp_obsolete/project.ts.before | 39 + .../good/mergecpp_obsolete/project.ts.result | 43 + .../lupdate/testdata/good/mergeui/project.pro | 3 + .../testdata/good/mergeui/project.ts.before | 22 + .../testdata/good/mergeui/project.ts.result | 23 + .../lupdate/testdata/good/mergeui/project.ui | 77 + .../testdata/good/mergeui_obsolete/project.pro | 3 + .../good/mergeui_obsolete/project.ts.before | 16 + .../good/mergeui_obsolete/project.ts.result | 22 + .../testdata/good/mergeui_obsolete/project.ui | 26 + .../good/multiple_locations/finddialog.cpp | 47 + .../testdata/good/multiple_locations/main.cpp | 53 + .../testdata/good/multiple_locations/project.pro | 4 + .../good/multiple_locations/project.ts.result | 17 + .../lupdate/testdata/good/namespaces/main.cpp | 198 + .../lupdate/testdata/good/namespaces/project.pro | 3 + .../testdata/good/namespaces/project.ts.result | 106 + .../testdata/good/parse_special_chars/main.cpp | 59 + .../testdata/good/parse_special_chars/project.pro | 3 + .../good/parse_special_chars/project.ts.result | 17 + .../lupdate/testdata/good/parsecontexts/main.cpp | 279 + .../testdata/good/parsecontexts/project.pro | 3 + .../testdata/good/parsecontexts/project.ts.result | 201 + .../lupdate/testdata/good/parsecpp/finddialog.cpp | 184 + .../lupdate/testdata/good/parsecpp/main.cpp | 345 + .../lupdate/testdata/good/parsecpp/project.pro | 4 + .../testdata/good/parsecpp/project.ts.result | 370 + .../testdata/good/parsecpp2/expectedoutput.txt | 7 + .../lupdate/testdata/good/parsecpp2/main.cpp | 127 + .../lupdate/testdata/good/parsecpp2/main.h | 51 + .../lupdate/testdata/good/parsecpp2/main2.cpp | 69 + .../lupdate/testdata/good/parsecpp2/main3.cpp | 83 + .../lupdate/testdata/good/parsecpp2/project.pro | 3 + .../testdata/good/parsecpp2/project.ts.result | 40 + .../lupdate/testdata/good/parsejava/main.java | 95 + .../lupdate/testdata/good/parsejava/project.pro | 3 + .../testdata/good/parsejava/project.ts.result | 115 + .../linguist/lupdate/testdata/good/parsejs/main.js | 91 + .../lupdate/testdata/good/parsejs/project.pro | 3 + .../testdata/good/parsejs/project.ts.result | 195 + .../testdata/good/parsejs2/expectedoutput.txt | 29 + .../lupdate/testdata/good/parsejs2/main.js | 56 + .../lupdate/testdata/good/parsejs2/project.pro | 3 + .../testdata/good/parsejs2/project.ts.result | 30 + .../lupdate/testdata/good/parsejscontexts/main.js | 29 + .../testdata/good/parsejscontexts/project.pro | 3 + .../good/parsejscontexts/project.ts.result | 81 + .../lupdate/testdata/good/parseqml/main.qml | 100 + .../lupdate/testdata/good/parseqml/project.pro | 3 + .../testdata/good/parseqml/project.ts.result | 200 + .../lupdate/testdata/good/parseui/project.pro | 3 + .../testdata/good/parseui/project.ts.result | 17 + .../lupdate/testdata/good/parseui/project.ui | 72 + .../linguist/lupdate/testdata/good/prefix/main.cpp | 56 + .../lupdate/testdata/good/prefix/project.pro | 3 + .../lupdate/testdata/good/prefix/project.ts.result | 23 + .../lupdate/testdata/good/preprocess/main.cpp | 78 + .../lupdate/testdata/good/preprocess/project.pro | 3 + .../testdata/good/preprocess/project.ts.result | 35 + .../lupdate/testdata/good/proparsing/main.cpp | 50 + .../lupdate/testdata/good/proparsing/main_mac.cpp | 51 + .../lupdate/testdata/good/proparsing/main_unix.cpp | 51 + .../lupdate/testdata/good/proparsing/main_win.cpp | 51 + .../lupdate/testdata/good/proparsing/project.pro | 31 + .../testdata/good/proparsing/project.ts.result | 64 + .../vpaths/dependpath/main_dependpath.cpp | 51 + .../testdata/good/proparsing/wildcard/main1.cpp | 50 + .../testdata/good/proparsing/wildcard/mainfile.cpp | 50 + .../lupdate/testdata/good/proparsing/wildcard1.cpp | 50 + .../testdata/good/proparsing/wildcard99.cpp | 50 + .../linguist/lupdate/testdata/good/proparsing2/a | 45 + .../lupdate/testdata/good/proparsing2/a.cpp | 45 + .../linguist/lupdate/testdata/good/proparsing2/b | 45 + .../lupdate/testdata/good/proparsing2/b.cpp | 45 + .../linguist/lupdate/testdata/good/proparsing2/e | 45 + .../lupdate/testdata/good/proparsing2/f/g.cpp | 45 + .../lupdate/testdata/good/proparsing2/files-cc.txt | 1 + .../lupdate/testdata/good/proparsing2/project.pro | 33 + .../testdata/good/proparsing2/project.ts.result | 62 + .../lupdate/testdata/good/proparsing2/spaces/z | 45 + .../testdata/good/proparsing2/variable_with_spaces | 45 + .../lupdate/testdata/good/proparsing2/with | 45 + .../linguist/lupdate/testdata/good/proparsing2/x/d | 45 + .../lupdate/testdata/good/proparsing2/x/variable | 45 + .../testdata/good/proparsingpaths/file1.cpp | 50 + .../testdata/good/proparsingpaths/filter.cpp | 50 + .../testdata/good/proparsingpaths/project.pro | 5 + .../good/proparsingpaths/project.ts.result | 31 + .../testdata/good/proparsingpaths/sub/sub.pri | 3 + .../testdata/good/proparsingpaths/sub/subfile1.cpp | 50 + .../good/proparsingpaths/sub/subfilter.cpp | 50 + .../testdata/good/proparsingpri/common/common.pri | 1 + .../testdata/good/proparsingpri/common/main.cpp | 50 + .../testdata/good/proparsingpri/common/main.pri | 5 + .../testdata/good/proparsingpri/mac/mac.pri | 5 + .../testdata/good/proparsingpri/mac/main_mac.cpp | 51 + .../testdata/good/proparsingpri/project.pro | 9 + .../testdata/good/proparsingpri/project.ts.result | 37 + .../good/proparsingpri/relativity/relativity.cpp | 50 + .../good/proparsingpri/relativity/relativity.pri | 3 + .../good/proparsingpri/relativity/sub/sub.pri | 1 + .../good/proparsingpri/relativity/sub2/sub2.pri | 2 + .../testdata/good/proparsingpri/unix/main_unix.cpp | 51 + .../testdata/good/proparsingpri/unix/unix.pri | 5 + .../testdata/good/proparsingpri/win/main_win.cpp | 51 + .../testdata/good/proparsingpri/win/win.pri | 5 + .../testdata/good/proparsingsubdirs/project.pro | 2 + .../good/proparsingsubdirs/project.ts.result | 13 + .../testdata/good/proparsingsubdirs/sub1/main.cpp | 50 + .../testdata/good/proparsingsubdirs/sub1/sub1.pro | 3 + .../testdata/good/proparsingsubs/common/common.pro | 2 + .../testdata/good/proparsingsubs/common/main.cpp | 50 + .../testdata/good/proparsingsubs/lupdatecmd | 1 + .../testdata/good/proparsingsubs/mac/mac.pro | 1 + .../testdata/good/proparsingsubs/mac/main_mac.cpp | 51 + .../testdata/good/proparsingsubs/project.pro | 2 + .../testdata/good/proparsingsubs/project.ts.result | 31 + .../good/proparsingsubs/unix/main_unix.cpp | 51 + .../testdata/good/proparsingsubs/unix/unix.pro | 1 + .../testdata/good/proparsingsubs/win/main_win.cpp | 51 + .../testdata/good/proparsingsubs/win/win.pro | 1 + .../testdata/good/recurse_full/expectedoutput.txt | 0 .../lupdate/testdata/good/recurse_full/lupdatecmd | 2 + .../testdata/good/recurse_full/project.ts.result | 20 + .../good/recurse_full/project_sub.ts.result | 13 + .../good/recurse_full_ts/expectedoutput.txt | 2 + .../testdata/good/recurse_full_ts/lupdatecmd | 3 + .../good/recurse_full_ts/project.ts.result | 20 + .../good/recurse_full_ts/project_sub.ts.before | 0 .../good/recurse_full_ts/project_sub.ts.result | 0 .../good/recurse_full_ts_join/expectedoutput.txt | 0 .../testdata/good/recurse_full_ts_join/lupdatecmd | 2 + .../good/recurse_full_ts_join/project.ts.result | 20 + .../testdata/good/recurse_part/expectedoutput.txt | 1 + .../lupdate/testdata/good/recurse_part/lupdatecmd | 2 + .../testdata/good/recurse_part/project.ts.before | 0 .../testdata/good/recurse_part/project.ts.result | 0 .../good/recurse_part/project_sub.ts.result | 13 + .../good/recurse_part_ts/expectedoutput.txt | 1 + .../testdata/good/recurse_part_ts/lupdatecmd | 3 + .../good/recurse_part_ts/project.ts.result | 20 + .../good/recurse_part_ts/project_sub.ts.before | 0 .../good/recurse_part_ts/project_sub.ts.result | 0 .../lupdate/testdata/good/reloutput/lupdatecmd | 1 + .../lupdate/testdata/good/reloutput/main.cpp | 50 + .../lupdate/testdata/good/reloutput/project.pro | 3 + .../good/reloutput/translations/project.ts.result | 12 + .../lupdate/testdata/good/respfile/lupdatecmd | 2 + .../testdata/good/respfile/project.ts.result | 17 + .../lupdate/testdata/good/respfile/source1.cpp | 49 + .../lupdate/testdata/good/respfile/source2.cpp | 49 + .../lupdate/testdata/good/respfile/sources.lst | 2 + .../lupdate/testdata/good/respfile/tsfiles.lst | 1 + .../testdata/good/textsimilarity/project.pro | 3 + .../testdata/good/textsimilarity/project.ts.before | 16 + .../testdata/good/textsimilarity/project.ts.result | 22 + .../testdata/good/textsimilarity/project.ui | 26 + .../lupdate/testdata/recursivescan/main.cpp | 63 + .../lupdate/testdata/recursivescan/project.ui | 74 + .../testdata/recursivescan/sub/filetypes/main.c++ | 49 + .../testdata/recursivescan/sub/filetypes/main.cpp | 49 + .../testdata/recursivescan/sub/filetypes/main.cxx | 49 + .../testdata/recursivescan/sub/finddialog.cpp | 73 + .../lupdate/testdata/subdirs_full/project.pro | 4 + .../lupdate/testdata/subdirs_full/subdir1/main.cpp | 46 + .../testdata/subdirs_full/subdir1/subdir1.pro | 1 + .../testdata/subdirs_full/subdir2/subdir2.pro | 2 + .../testdata/subdirs_full/subdir2/subsub1/main.cpp | 46 + .../subdirs_full/subdir2/subsub1/subsub1.pro | 1 + .../testdata/subdirs_full/subdir2/subsub2/main.cpp | 46 + .../subdirs_full/subdir2/subsub2/subsub2.pro | 4 + .../lupdate/testdata/subdirs_part/project.pro | 2 + .../lupdate/testdata/subdirs_part/subdir1/main.cpp | 46 + .../testdata/subdirs_part/subdir1/subdir1.pro | 1 + .../testdata/subdirs_part/subdir2/subdir2.pro | 2 + .../testdata/subdirs_part/subdir2/subsub1/main.cpp | 46 + .../subdirs_part/subdir2/subsub1/subsub1.pro | 1 + .../testdata/subdirs_part/subdir2/subsub2/main.cpp | 46 + .../subdirs_part/subdir2/subsub2/subsub2.pro | 4 + tests/auto/linguist/lupdate/tst_lupdate.cpp | 350 + tests/auto/qhelpcontentmodel/.gitignore | 2 + tests/auto/qhelpcontentmodel/data/collection.qhc | Bin 0 -> 10240 bytes tests/auto/qhelpcontentmodel/data/qmake-3.3.8.qch | Bin 0 -> 61440 bytes tests/auto/qhelpcontentmodel/data/qmake-4.3.0.qch | Bin 0 -> 93184 bytes tests/auto/qhelpcontentmodel/data/test.qch | Bin 0 -> 22528 bytes tests/auto/qhelpcontentmodel/qhelpcontentmodel.pro | 22 + .../qhelpcontentmodel/tst_qhelpcontentmodel.cpp | 182 + tests/auto/qhelpenginecore/.gitignore | 3 + tests/auto/qhelpenginecore/data/collection.qhc | Bin 0 -> 10240 bytes tests/auto/qhelpenginecore/data/collection1.qhc | Bin 0 -> 10240 bytes tests/auto/qhelpenginecore/data/linguist-3.3.8.qch | Bin 0 -> 131072 bytes tests/auto/qhelpenginecore/data/qmake-3.3.8.qch | Bin 0 -> 61440 bytes tests/auto/qhelpenginecore/data/qmake-4.3.0.qch | Bin 0 -> 93184 bytes tests/auto/qhelpenginecore/data/test.html | 11 + tests/auto/qhelpenginecore/data/test.qch | Bin 0 -> 22528 bytes tests/auto/qhelpenginecore/qhelpenginecore.pro | 23 + tests/auto/qhelpenginecore/tst_qhelpenginecore.cpp | 462 + tests/auto/qhelpgenerator/.gitignore | 1 + tests/auto/qhelpgenerator/data/cars.html | 11 + tests/auto/qhelpgenerator/data/classic.css | 92 + tests/auto/qhelpgenerator/data/fancy.html | 11 + tests/auto/qhelpgenerator/data/people.html | 11 + tests/auto/qhelpgenerator/data/sub/about.html | 11 + tests/auto/qhelpgenerator/data/test.html | 11 + tests/auto/qhelpgenerator/data/test.qhp | 71 + tests/auto/qhelpgenerator/qhelpgenerator.pro | 9 + tests/auto/qhelpgenerator/tst_qhelpgenerator.cpp | 218 + tests/auto/qhelpindexmodel/.gitignore | 2 + tests/auto/qhelpindexmodel/data/collection.qhc | Bin 0 -> 10240 bytes tests/auto/qhelpindexmodel/data/collection1.qhc | Bin 0 -> 10240 bytes tests/auto/qhelpindexmodel/data/linguist-3.3.8.qch | Bin 0 -> 131072 bytes tests/auto/qhelpindexmodel/data/qmake-3.3.8.qch | Bin 0 -> 61440 bytes tests/auto/qhelpindexmodel/data/qmake-4.3.0.qch | Bin 0 -> 93184 bytes tests/auto/qhelpindexmodel/data/test.html | 11 + tests/auto/qhelpindexmodel/data/test.qch | Bin 0 -> 22528 bytes tests/auto/qhelpindexmodel/qhelpindexmodel.pro | 9 + tests/auto/qhelpindexmodel/tst_qhelpindexmodel.cpp | 219 + tests/auto/qhelpprojectdata/.gitignore | 1 + tests/auto/qhelpprojectdata/data/test.qhp | 72 + tests/auto/qhelpprojectdata/qhelpprojectdata.pro | 9 + .../auto/qhelpprojectdata/tst_qhelpprojectdata.cpp | 193 + tests/global/.gitignore | 2 + tests/tests.pro | 2 + 2343 files changed, 431332 insertions(+) create mode 100644 3rdparty/clucene/APACHE.license create mode 100644 3rdparty/clucene/AUTHORS create mode 100644 3rdparty/clucene/COPYING create mode 100644 3rdparty/clucene/ChangeLog create mode 100644 3rdparty/clucene/LGPL.license create mode 100644 3rdparty/clucene/README create mode 100644 3rdparty/clucene/src/CLucene.h create mode 100644 3rdparty/clucene/src/CLucene/CLBackwards.h create mode 100644 3rdparty/clucene/src/CLucene/CLConfig.h create mode 100644 3rdparty/clucene/src/CLucene/CLMonolithic.cpp create mode 100644 3rdparty/clucene/src/CLucene/LuceneThreads.h create mode 100644 3rdparty/clucene/src/CLucene/StdHeader.cpp create mode 100644 3rdparty/clucene/src/CLucene/StdHeader.h create mode 100644 3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.cpp create mode 100644 3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.h create mode 100644 3rdparty/clucene/src/CLucene/analysis/Analyzers.cpp create mode 100644 3rdparty/clucene/src/CLucene/analysis/Analyzers.h create mode 100644 3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.cpp create mode 100644 3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.h create mode 100644 3rdparty/clucene/src/CLucene/analysis/standard/StandardFilter.cpp create mode 100644 3rdparty/clucene/src/CLucene/analysis/standard/StandardFilter.h create mode 100644 3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.cpp create mode 100644 3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.h create mode 100644 3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizerConstants.h create mode 100644 3rdparty/clucene/src/CLucene/config/CompilerAcc.h create mode 100644 3rdparty/clucene/src/CLucene/config/CompilerBcb.h create mode 100644 3rdparty/clucene/src/CLucene/config/CompilerGcc.h create mode 100644 3rdparty/clucene/src/CLucene/config/CompilerMsvc.h create mode 100644 3rdparty/clucene/src/CLucene/config/PlatformMac.h create mode 100644 3rdparty/clucene/src/CLucene/config/PlatformUnix.h create mode 100644 3rdparty/clucene/src/CLucene/config/PlatformWin32.h create mode 100644 3rdparty/clucene/src/CLucene/config/compiler.h create mode 100644 3rdparty/clucene/src/CLucene/config/define_std.h create mode 100644 3rdparty/clucene/src/CLucene/config/gunichartables.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/gunichartables.h create mode 100644 3rdparty/clucene/src/CLucene/config/repl_lltot.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/repl_tchar.h create mode 100644 3rdparty/clucene/src/CLucene/config/repl_tcscasecmp.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/repl_tcslwr.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/repl_tcstod.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/repl_tcstoll.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/repl_tprintf.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/repl_wchar.h create mode 100644 3rdparty/clucene/src/CLucene/config/threadCSection.h create mode 100644 3rdparty/clucene/src/CLucene/config/threadPthread.h create mode 100644 3rdparty/clucene/src/CLucene/config/threads.cpp create mode 100644 3rdparty/clucene/src/CLucene/config/utf8.cpp create mode 100644 3rdparty/clucene/src/CLucene/debug/condition.cpp create mode 100644 3rdparty/clucene/src/CLucene/debug/condition.h create mode 100644 3rdparty/clucene/src/CLucene/debug/error.cpp create mode 100644 3rdparty/clucene/src/CLucene/debug/error.h create mode 100644 3rdparty/clucene/src/CLucene/debug/lucenebase.h create mode 100644 3rdparty/clucene/src/CLucene/debug/mem.h create mode 100644 3rdparty/clucene/src/CLucene/debug/memtracking.cpp create mode 100644 3rdparty/clucene/src/CLucene/document/DateField.cpp create mode 100644 3rdparty/clucene/src/CLucene/document/DateField.h create mode 100644 3rdparty/clucene/src/CLucene/document/Document.cpp create mode 100644 3rdparty/clucene/src/CLucene/document/Document.h create mode 100644 3rdparty/clucene/src/CLucene/document/Field.cpp create mode 100644 3rdparty/clucene/src/CLucene/document/Field.h create mode 100644 3rdparty/clucene/src/CLucene/index/CompoundFile.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/CompoundFile.h create mode 100644 3rdparty/clucene/src/CLucene/index/DocumentWriter.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/DocumentWriter.h create mode 100644 3rdparty/clucene/src/CLucene/index/FieldInfo.h create mode 100644 3rdparty/clucene/src/CLucene/index/FieldInfos.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/FieldInfos.h create mode 100644 3rdparty/clucene/src/CLucene/index/FieldsReader.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/FieldsReader.h create mode 100644 3rdparty/clucene/src/CLucene/index/FieldsWriter.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/FieldsWriter.h create mode 100644 3rdparty/clucene/src/CLucene/index/IndexModifier.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/IndexModifier.h create mode 100644 3rdparty/clucene/src/CLucene/index/IndexReader.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/IndexReader.h create mode 100644 3rdparty/clucene/src/CLucene/index/IndexWriter.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/IndexWriter.h create mode 100644 3rdparty/clucene/src/CLucene/index/MultiReader.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/MultiReader.h create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentHeader.h create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentInfos.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentInfos.h create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.h create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.h create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentMerger.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentMerger.h create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentReader.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentTermDocs.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentTermEnum.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentTermEnum.h create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentTermPositions.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/SegmentTermVector.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/Term.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/Term.h create mode 100644 3rdparty/clucene/src/CLucene/index/TermInfo.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/TermInfo.h create mode 100644 3rdparty/clucene/src/CLucene/index/TermInfosReader.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/TermInfosReader.h create mode 100644 3rdparty/clucene/src/CLucene/index/TermInfosWriter.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/TermInfosWriter.h create mode 100644 3rdparty/clucene/src/CLucene/index/TermVector.h create mode 100644 3rdparty/clucene/src/CLucene/index/TermVectorReader.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/TermVectorWriter.cpp create mode 100644 3rdparty/clucene/src/CLucene/index/Terms.h create mode 100644 3rdparty/clucene/src/CLucene/queryParser/Lexer.cpp create mode 100644 3rdparty/clucene/src/CLucene/queryParser/Lexer.h create mode 100644 3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.cpp create mode 100644 3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.h create mode 100644 3rdparty/clucene/src/CLucene/queryParser/QueryParser.cpp create mode 100644 3rdparty/clucene/src/CLucene/queryParser/QueryParser.h create mode 100644 3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.cpp create mode 100644 3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.h create mode 100644 3rdparty/clucene/src/CLucene/queryParser/QueryToken.cpp create mode 100644 3rdparty/clucene/src/CLucene/queryParser/QueryToken.h create mode 100644 3rdparty/clucene/src/CLucene/queryParser/TokenList.cpp create mode 100644 3rdparty/clucene/src/CLucene/queryParser/TokenList.h create mode 100644 3rdparty/clucene/src/CLucene/search/BooleanClause.h create mode 100644 3rdparty/clucene/src/CLucene/search/BooleanQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/BooleanQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/BooleanScorer.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/BooleanScorer.h create mode 100644 3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.h create mode 100644 3rdparty/clucene/src/CLucene/search/ChainedFilter.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/ChainedFilter.h create mode 100644 3rdparty/clucene/src/CLucene/search/Compare.h create mode 100644 3rdparty/clucene/src/CLucene/search/ConjunctionScorer.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/ConjunctionScorer.h create mode 100644 3rdparty/clucene/src/CLucene/search/DateFilter.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/DateFilter.h create mode 100644 3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.h create mode 100644 3rdparty/clucene/src/CLucene/search/Explanation.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/Explanation.h create mode 100644 3rdparty/clucene/src/CLucene/search/FieldCache.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/FieldCache.h create mode 100644 3rdparty/clucene/src/CLucene/search/FieldCacheImpl.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/FieldCacheImpl.h create mode 100644 3rdparty/clucene/src/CLucene/search/FieldDoc.h create mode 100644 3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.h create mode 100644 3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.h create mode 100644 3rdparty/clucene/src/CLucene/search/Filter.h create mode 100644 3rdparty/clucene/src/CLucene/search/FilteredTermEnum.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/FilteredTermEnum.h create mode 100644 3rdparty/clucene/src/CLucene/search/FuzzyQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/FuzzyQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/HitQueue.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/HitQueue.h create mode 100644 3rdparty/clucene/src/CLucene/search/Hits.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/IndexSearcher.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/IndexSearcher.h create mode 100644 3rdparty/clucene/src/CLucene/search/MultiSearcher.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/MultiSearcher.h create mode 100644 3rdparty/clucene/src/CLucene/search/MultiTermQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/MultiTermQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/PhrasePositions.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/PhrasePositions.h create mode 100644 3rdparty/clucene/src/CLucene/search/PhraseQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/PhraseQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/PhraseQueue.h create mode 100644 3rdparty/clucene/src/CLucene/search/PhraseScorer.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/PhraseScorer.h create mode 100644 3rdparty/clucene/src/CLucene/search/PrefixQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/PrefixQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/QueryFilter.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/QueryFilter.h create mode 100644 3rdparty/clucene/src/CLucene/search/RangeFilter.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/RangeFilter.h create mode 100644 3rdparty/clucene/src/CLucene/search/RangeQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/RangeQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/Scorer.h create mode 100644 3rdparty/clucene/src/CLucene/search/SearchHeader.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/SearchHeader.h create mode 100644 3rdparty/clucene/src/CLucene/search/Similarity.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/Similarity.h create mode 100644 3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.h create mode 100644 3rdparty/clucene/src/CLucene/search/Sort.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/Sort.h create mode 100644 3rdparty/clucene/src/CLucene/search/TermQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/TermQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/TermScorer.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/TermScorer.h create mode 100644 3rdparty/clucene/src/CLucene/search/WildcardQuery.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/WildcardQuery.h create mode 100644 3rdparty/clucene/src/CLucene/search/WildcardTermEnum.cpp create mode 100644 3rdparty/clucene/src/CLucene/search/WildcardTermEnum.h create mode 100644 3rdparty/clucene/src/CLucene/store/Directory.h create mode 100644 3rdparty/clucene/src/CLucene/store/FSDirectory.cpp create mode 100644 3rdparty/clucene/src/CLucene/store/FSDirectory.h create mode 100644 3rdparty/clucene/src/CLucene/store/IndexInput.cpp create mode 100644 3rdparty/clucene/src/CLucene/store/IndexInput.h create mode 100644 3rdparty/clucene/src/CLucene/store/IndexOutput.cpp create mode 100644 3rdparty/clucene/src/CLucene/store/IndexOutput.h create mode 100644 3rdparty/clucene/src/CLucene/store/InputStream.h create mode 100644 3rdparty/clucene/src/CLucene/store/Lock.cpp create mode 100644 3rdparty/clucene/src/CLucene/store/Lock.h create mode 100644 3rdparty/clucene/src/CLucene/store/MMapInput.cpp create mode 100644 3rdparty/clucene/src/CLucene/store/OutputStream.h create mode 100644 3rdparty/clucene/src/CLucene/store/RAMDirectory.cpp create mode 100644 3rdparty/clucene/src/CLucene/store/RAMDirectory.h create mode 100644 3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.cpp create mode 100644 3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.h create mode 100644 3rdparty/clucene/src/CLucene/util/Arrays.h create mode 100644 3rdparty/clucene/src/CLucene/util/BitSet.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/BitSet.h create mode 100644 3rdparty/clucene/src/CLucene/util/Equators.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/Equators.h create mode 100644 3rdparty/clucene/src/CLucene/util/FastCharStream.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/FastCharStream.h create mode 100644 3rdparty/clucene/src/CLucene/util/Misc.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/Misc.h create mode 100644 3rdparty/clucene/src/CLucene/util/PriorityQueue.h create mode 100644 3rdparty/clucene/src/CLucene/util/Reader.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/Reader.h create mode 100644 3rdparty/clucene/src/CLucene/util/StringBuffer.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/StringBuffer.h create mode 100644 3rdparty/clucene/src/CLucene/util/StringIntern.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/StringIntern.h create mode 100644 3rdparty/clucene/src/CLucene/util/ThreadLocal.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/ThreadLocal.h create mode 100644 3rdparty/clucene/src/CLucene/util/VoidList.h create mode 100644 3rdparty/clucene/src/CLucene/util/VoidMap.h create mode 100644 3rdparty/clucene/src/CLucene/util/bufferedstream.h create mode 100644 3rdparty/clucene/src/CLucene/util/dirent.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/dirent.h create mode 100644 3rdparty/clucene/src/CLucene/util/fileinputstream.cpp create mode 100644 3rdparty/clucene/src/CLucene/util/fileinputstream.h create mode 100644 3rdparty/clucene/src/CLucene/util/inputstreambuffer.h create mode 100644 3rdparty/clucene/src/CLucene/util/jstreamsconfig.h create mode 100644 3rdparty/clucene/src/CLucene/util/streambase.h create mode 100644 3rdparty/clucene/src/CLucene/util/stringreader.h create mode 100644 3rdparty/clucene/src/CLucene/util/subinputstream.h create mode 100644 demos/arthurplugin/arthur_plugin.qrc create mode 100644 demos/arthurplugin/arthurplugin.pro create mode 100644 demos/arthurplugin/bg1.jpg create mode 100644 demos/arthurplugin/flower.jpg create mode 100644 demos/arthurplugin/flower_alpha.jpg create mode 100644 demos/arthurplugin/plugin.cpp create mode 100644 demos/shared/arthurstyle.cpp create mode 100644 demos/shared/arthurstyle.h create mode 100644 demos/shared/arthurwidgets.cpp create mode 100644 demos/shared/arthurwidgets.h create mode 100644 demos/shared/hoverpoints.cpp create mode 100644 demos/shared/hoverpoints.h create mode 100644 demos/shared/images/bg_pattern.png create mode 100644 demos/shared/images/button_normal_cap_left.png create mode 100644 demos/shared/images/button_normal_cap_right.png create mode 100644 demos/shared/images/button_normal_stretch.png create mode 100644 demos/shared/images/button_pressed_cap_left.png create mode 100644 demos/shared/images/button_pressed_cap_right.png create mode 100644 demos/shared/images/button_pressed_stretch.png create mode 100644 demos/shared/images/curve_thing_edit-6.png create mode 100644 demos/shared/images/frame_bottom.png create mode 100644 demos/shared/images/frame_bottomleft.png create mode 100644 demos/shared/images/frame_bottomright.png create mode 100644 demos/shared/images/frame_left.png create mode 100644 demos/shared/images/frame_right.png create mode 100644 demos/shared/images/frame_top.png create mode 100644 demos/shared/images/frame_topleft.png create mode 100644 demos/shared/images/frame_topright.png create mode 100644 demos/shared/images/groupframe_bottom_left.png create mode 100644 demos/shared/images/groupframe_bottom_right.png create mode 100644 demos/shared/images/groupframe_bottom_stretch.png create mode 100644 demos/shared/images/groupframe_left_stretch.png create mode 100644 demos/shared/images/groupframe_right_stretch.png create mode 100644 demos/shared/images/groupframe_top_stretch.png create mode 100644 demos/shared/images/groupframe_topleft.png create mode 100644 demos/shared/images/groupframe_topright.png create mode 100644 demos/shared/images/line_dash_dot.png create mode 100644 demos/shared/images/line_dash_dot_dot.png create mode 100644 demos/shared/images/line_dashed.png create mode 100644 demos/shared/images/line_dotted.png create mode 100644 demos/shared/images/line_solid.png create mode 100644 demos/shared/images/radiobutton-off.png create mode 100644 demos/shared/images/radiobutton-on.png create mode 100644 demos/shared/images/radiobutton_off.png create mode 100644 demos/shared/images/radiobutton_on.png create mode 100644 demos/shared/images/slider_bar.png create mode 100644 demos/shared/images/slider_thumb_off.png create mode 100644 demos/shared/images/slider_thumb_on.png create mode 100644 demos/shared/images/title_cap_left.png create mode 100644 demos/shared/images/title_cap_right.png create mode 100644 demos/shared/images/title_stretch.png create mode 100644 demos/shared/shared.pri create mode 100644 demos/shared/shared.pro create mode 100644 demos/shared/shared.qrc create mode 100644 examples/designer/README create mode 100644 examples/designer/calculatorbuilder/calculatorbuilder.pro create mode 100644 examples/designer/calculatorbuilder/calculatorbuilder.qrc create mode 100644 examples/designer/calculatorbuilder/calculatorform.cpp create mode 100644 examples/designer/calculatorbuilder/calculatorform.h create mode 100644 examples/designer/calculatorbuilder/calculatorform.ui create mode 100644 examples/designer/calculatorbuilder/main.cpp create mode 100644 examples/designer/calculatorform/calculatorform.cpp create mode 100644 examples/designer/calculatorform/calculatorform.h create mode 100644 examples/designer/calculatorform/calculatorform.pro create mode 100644 examples/designer/calculatorform/calculatorform.ui create mode 100644 examples/designer/calculatorform/main.cpp create mode 100644 examples/designer/containerextension/containerextension.pro create mode 100644 examples/designer/containerextension/multipagewidget.cpp create mode 100644 examples/designer/containerextension/multipagewidget.h create mode 100644 examples/designer/containerextension/multipagewidgetcontainerextension.cpp create mode 100644 examples/designer/containerextension/multipagewidgetcontainerextension.h create mode 100644 examples/designer/containerextension/multipagewidgetextensionfactory.cpp create mode 100644 examples/designer/containerextension/multipagewidgetextensionfactory.h create mode 100644 examples/designer/containerextension/multipagewidgetplugin.cpp create mode 100644 examples/designer/containerextension/multipagewidgetplugin.h create mode 100644 examples/designer/customwidgetplugin/analogclock.cpp create mode 100644 examples/designer/customwidgetplugin/analogclock.h create mode 100644 examples/designer/customwidgetplugin/customwidgetplugin.cpp create mode 100644 examples/designer/customwidgetplugin/customwidgetplugin.h create mode 100644 examples/designer/customwidgetplugin/customwidgetplugin.pro create mode 100644 examples/designer/designer.pro create mode 100644 examples/designer/taskmenuextension/taskmenuextension.pro create mode 100644 examples/designer/taskmenuextension/tictactoe.cpp create mode 100644 examples/designer/taskmenuextension/tictactoe.h create mode 100644 examples/designer/taskmenuextension/tictactoedialog.cpp create mode 100644 examples/designer/taskmenuextension/tictactoedialog.h create mode 100644 examples/designer/taskmenuextension/tictactoeplugin.cpp create mode 100644 examples/designer/taskmenuextension/tictactoeplugin.h create mode 100644 examples/designer/taskmenuextension/tictactoetaskmenu.cpp create mode 100644 examples/designer/taskmenuextension/tictactoetaskmenu.h create mode 100644 examples/designer/worldtimeclockbuilder/form.ui create mode 100644 examples/designer/worldtimeclockbuilder/main.cpp create mode 100644 examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.pro create mode 100644 examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.qrc create mode 100644 examples/designer/worldtimeclockplugin/worldtimeclock.cpp create mode 100644 examples/designer/worldtimeclockplugin/worldtimeclock.h create mode 100644 examples/designer/worldtimeclockplugin/worldtimeclockplugin.cpp create mode 100644 examples/designer/worldtimeclockplugin/worldtimeclockplugin.h create mode 100644 examples/designer/worldtimeclockplugin/worldtimeclockplugin.pro create mode 100644 examples/examples.pro create mode 100644 examples/help/README create mode 100644 examples/help/contextsensitivehelp/contextsensitivehelp.pro create mode 100644 examples/help/contextsensitivehelp/doc/amount.html create mode 100644 examples/help/contextsensitivehelp/doc/filter.html create mode 100644 examples/help/contextsensitivehelp/doc/plants.html create mode 100644 examples/help/contextsensitivehelp/doc/rain.html create mode 100644 examples/help/contextsensitivehelp/doc/source.html create mode 100644 examples/help/contextsensitivehelp/doc/temperature.html create mode 100644 examples/help/contextsensitivehelp/doc/time.html create mode 100644 examples/help/contextsensitivehelp/doc/wateringmachine.qch create mode 100644 examples/help/contextsensitivehelp/doc/wateringmachine.qhc create mode 100644 examples/help/contextsensitivehelp/doc/wateringmachine.qhcp create mode 100644 examples/help/contextsensitivehelp/doc/wateringmachine.qhp create mode 100644 examples/help/contextsensitivehelp/helpbrowser.cpp create mode 100644 examples/help/contextsensitivehelp/helpbrowser.h create mode 100644 examples/help/contextsensitivehelp/main.cpp create mode 100644 examples/help/contextsensitivehelp/wateringconfigdialog.cpp create mode 100644 examples/help/contextsensitivehelp/wateringconfigdialog.h create mode 100644 examples/help/contextsensitivehelp/wateringconfigdialog.ui create mode 100644 examples/help/help.pro create mode 100644 examples/help/remotecontrol/enter.png create mode 100644 examples/help/remotecontrol/main.cpp create mode 100644 examples/help/remotecontrol/remotecontrol.cpp create mode 100644 examples/help/remotecontrol/remotecontrol.h create mode 100644 examples/help/remotecontrol/remotecontrol.pro create mode 100644 examples/help/remotecontrol/remotecontrol.qrc create mode 100644 examples/help/remotecontrol/remotecontrol.ui create mode 100644 examples/help/simpletextviewer/assistant.cpp create mode 100644 examples/help/simpletextviewer/assistant.h create mode 100644 examples/help/simpletextviewer/documentation/about.txt create mode 100644 examples/help/simpletextviewer/documentation/browse.html create mode 100644 examples/help/simpletextviewer/documentation/filedialog.html create mode 100644 examples/help/simpletextviewer/documentation/findfile.html create mode 100644 examples/help/simpletextviewer/documentation/images/browse.png create mode 100644 examples/help/simpletextviewer/documentation/images/fadedfilemenu.png create mode 100644 examples/help/simpletextviewer/documentation/images/filedialog.png create mode 100644 examples/help/simpletextviewer/documentation/images/handbook.png create mode 100644 examples/help/simpletextviewer/documentation/images/icon.png create mode 100644 examples/help/simpletextviewer/documentation/images/mainwindow.png create mode 100644 examples/help/simpletextviewer/documentation/images/open.png create mode 100644 examples/help/simpletextviewer/documentation/images/wildcard.png create mode 100644 examples/help/simpletextviewer/documentation/index.html create mode 100644 examples/help/simpletextviewer/documentation/intro.html create mode 100644 examples/help/simpletextviewer/documentation/openfile.html create mode 100644 examples/help/simpletextviewer/documentation/simpletextviewer.qch create mode 100644 examples/help/simpletextviewer/documentation/simpletextviewer.qhc create mode 100644 examples/help/simpletextviewer/documentation/simpletextviewer.qhcp create mode 100644 examples/help/simpletextviewer/documentation/simpletextviewer.qhp create mode 100644 examples/help/simpletextviewer/documentation/wildcardmatching.html create mode 100644 examples/help/simpletextviewer/findfiledialog.cpp create mode 100644 examples/help/simpletextviewer/findfiledialog.h create mode 100644 examples/help/simpletextviewer/main.cpp create mode 100644 examples/help/simpletextviewer/mainwindow.cpp create mode 100644 examples/help/simpletextviewer/mainwindow.h create mode 100644 examples/help/simpletextviewer/simpletextviewer.pro create mode 100644 examples/help/simpletextviewer/textedit.cpp create mode 100644 examples/help/simpletextviewer/textedit.h create mode 100644 qttools.pro create mode 100644 src/assistant/assistant.pro create mode 100644 src/assistant/lib/fulltextsearch/fulltextsearch.pri create mode 100644 src/assistant/lib/fulltextsearch/fulltextsearch.pro create mode 100644 src/assistant/lib/fulltextsearch/license.txt create mode 100644 src/assistant/lib/fulltextsearch/qanalyzer.cpp create mode 100644 src/assistant/lib/fulltextsearch/qanalyzer_p.h create mode 100644 src/assistant/lib/fulltextsearch/qclucene-config_p.h create mode 100644 src/assistant/lib/fulltextsearch/qclucene_global_p.h create mode 100644 src/assistant/lib/fulltextsearch/qdocument.cpp create mode 100644 src/assistant/lib/fulltextsearch/qdocument_p.h create mode 100644 src/assistant/lib/fulltextsearch/qfield.cpp create mode 100644 src/assistant/lib/fulltextsearch/qfield_p.h create mode 100644 src/assistant/lib/fulltextsearch/qfilter.cpp create mode 100644 src/assistant/lib/fulltextsearch/qfilter_p.h create mode 100644 src/assistant/lib/fulltextsearch/qhits.cpp create mode 100644 src/assistant/lib/fulltextsearch/qhits_p.h create mode 100644 src/assistant/lib/fulltextsearch/qindexreader.cpp create mode 100644 src/assistant/lib/fulltextsearch/qindexreader_p.h create mode 100644 src/assistant/lib/fulltextsearch/qindexwriter.cpp create mode 100644 src/assistant/lib/fulltextsearch/qindexwriter_p.h create mode 100644 src/assistant/lib/fulltextsearch/qquery.cpp create mode 100644 src/assistant/lib/fulltextsearch/qquery_p.h create mode 100644 src/assistant/lib/fulltextsearch/qqueryparser.cpp create mode 100644 src/assistant/lib/fulltextsearch/qqueryparser_p.h create mode 100644 src/assistant/lib/fulltextsearch/qreader.cpp create mode 100644 src/assistant/lib/fulltextsearch/qreader_p.h create mode 100644 src/assistant/lib/fulltextsearch/qsearchable.cpp create mode 100644 src/assistant/lib/fulltextsearch/qsearchable_p.h create mode 100644 src/assistant/lib/fulltextsearch/qsort.cpp create mode 100644 src/assistant/lib/fulltextsearch/qsort_p.h create mode 100644 src/assistant/lib/fulltextsearch/qterm.cpp create mode 100644 src/assistant/lib/fulltextsearch/qterm_p.h create mode 100644 src/assistant/lib/fulltextsearch/qtoken.cpp create mode 100644 src/assistant/lib/fulltextsearch/qtoken_p.h create mode 100644 src/assistant/lib/fulltextsearch/qtokenizer.cpp create mode 100644 src/assistant/lib/fulltextsearch/qtokenizer_p.h create mode 100644 src/assistant/lib/fulltextsearch/qtokenstream.cpp create mode 100644 src/assistant/lib/fulltextsearch/qtokenstream_p.h create mode 100644 src/assistant/lib/helpsystem.qrc create mode 100644 src/assistant/lib/images/1leftarrow.png create mode 100644 src/assistant/lib/images/1rightarrow.png create mode 100644 src/assistant/lib/images/3leftarrow.png create mode 100644 src/assistant/lib/images/3rightarrow.png create mode 100644 src/assistant/lib/lib.pro create mode 100644 src/assistant/lib/qclucenefieldnames.cpp create mode 100644 src/assistant/lib/qclucenefieldnames_p.h create mode 100644 src/assistant/lib/qhelp_global.cpp create mode 100644 src/assistant/lib/qhelp_global.h create mode 100644 src/assistant/lib/qhelpcollectionhandler.cpp create mode 100644 src/assistant/lib/qhelpcollectionhandler_p.h create mode 100644 src/assistant/lib/qhelpcontentwidget.cpp create mode 100644 src/assistant/lib/qhelpcontentwidget.h create mode 100644 src/assistant/lib/qhelpdatainterface.cpp create mode 100644 src/assistant/lib/qhelpdatainterface_p.h create mode 100644 src/assistant/lib/qhelpdbreader.cpp create mode 100644 src/assistant/lib/qhelpdbreader_p.h create mode 100644 src/assistant/lib/qhelpengine.cpp create mode 100644 src/assistant/lib/qhelpengine.h create mode 100644 src/assistant/lib/qhelpengine_p.h create mode 100644 src/assistant/lib/qhelpenginecore.cpp create mode 100644 src/assistant/lib/qhelpenginecore.h create mode 100644 src/assistant/lib/qhelpgenerator.cpp create mode 100644 src/assistant/lib/qhelpgenerator_p.h create mode 100644 src/assistant/lib/qhelpindexwidget.cpp create mode 100644 src/assistant/lib/qhelpindexwidget.h create mode 100644 src/assistant/lib/qhelpprojectdata.cpp create mode 100644 src/assistant/lib/qhelpprojectdata_p.h create mode 100644 src/assistant/lib/qhelpsearchengine.cpp create mode 100644 src/assistant/lib/qhelpsearchengine.h create mode 100644 src/assistant/lib/qhelpsearchindex_default.cpp create mode 100644 src/assistant/lib/qhelpsearchindex_default_p.h create mode 100644 src/assistant/lib/qhelpsearchindexreader.cpp create mode 100644 src/assistant/lib/qhelpsearchindexreader_clucene.cpp create mode 100644 src/assistant/lib/qhelpsearchindexreader_clucene_p.h create mode 100644 src/assistant/lib/qhelpsearchindexreader_default.cpp create mode 100644 src/assistant/lib/qhelpsearchindexreader_default_p.h create mode 100644 src/assistant/lib/qhelpsearchindexreader_p.h create mode 100644 src/assistant/lib/qhelpsearchindexwriter_clucene.cpp create mode 100644 src/assistant/lib/qhelpsearchindexwriter_clucene_p.h create mode 100644 src/assistant/lib/qhelpsearchindexwriter_default.cpp create mode 100644 src/assistant/lib/qhelpsearchindexwriter_default_p.h create mode 100644 src/assistant/lib/qhelpsearchquerywidget.cpp create mode 100644 src/assistant/lib/qhelpsearchquerywidget.h create mode 100644 src/assistant/lib/qhelpsearchresultwidget.cpp create mode 100644 src/assistant/lib/qhelpsearchresultwidget.h create mode 100644 src/assistant/tools/assistant/Info_mac.plist create mode 100644 src/assistant/tools/assistant/aboutdialog.cpp create mode 100644 src/assistant/tools/assistant/aboutdialog.h create mode 100644 src/assistant/tools/assistant/assistant.icns create mode 100644 src/assistant/tools/assistant/assistant.ico create mode 100644 src/assistant/tools/assistant/assistant.pro create mode 100644 src/assistant/tools/assistant/assistant.qch create mode 100644 src/assistant/tools/assistant/assistant.qrc create mode 100644 src/assistant/tools/assistant/assistant.rc create mode 100644 src/assistant/tools/assistant/assistant_images.qrc create mode 100644 src/assistant/tools/assistant/bookmarkdialog.cpp create mode 100644 src/assistant/tools/assistant/bookmarkdialog.h create mode 100644 src/assistant/tools/assistant/bookmarkdialog.ui create mode 100644 src/assistant/tools/assistant/bookmarkfiltermodel.cpp create mode 100644 src/assistant/tools/assistant/bookmarkfiltermodel.h create mode 100644 src/assistant/tools/assistant/bookmarkitem.cpp create mode 100644 src/assistant/tools/assistant/bookmarkitem.h create mode 100644 src/assistant/tools/assistant/bookmarkmanager.cpp create mode 100644 src/assistant/tools/assistant/bookmarkmanager.h create mode 100644 src/assistant/tools/assistant/bookmarkmanagerwidget.cpp create mode 100644 src/assistant/tools/assistant/bookmarkmanagerwidget.h create mode 100644 src/assistant/tools/assistant/bookmarkmanagerwidget.ui create mode 100644 src/assistant/tools/assistant/bookmarkmodel.cpp create mode 100644 src/assistant/tools/assistant/bookmarkmodel.h create mode 100644 src/assistant/tools/assistant/bookmarkwidget.ui create mode 100644 src/assistant/tools/assistant/centralwidget.cpp create mode 100644 src/assistant/tools/assistant/centralwidget.h create mode 100644 src/assistant/tools/assistant/cmdlineparser.cpp create mode 100644 src/assistant/tools/assistant/cmdlineparser.h create mode 100644 src/assistant/tools/assistant/contentwindow.cpp create mode 100644 src/assistant/tools/assistant/contentwindow.h create mode 100644 src/assistant/tools/assistant/doc/HOWTO create mode 100644 src/assistant/tools/assistant/doc/assistant.qdoc create mode 100644 src/assistant/tools/assistant/doc/assistant.qdocconf create mode 100644 src/assistant/tools/assistant/doc/assistant.qhp create mode 100644 src/assistant/tools/assistant/doc/classic.css create mode 100644 src/assistant/tools/assistant/doc/images/assistant-address-toolbar.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-assistant.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-dockwidgets.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-docwindow.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-examples.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-filter-toolbar.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-preferences-documentation.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-preferences-filters.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-preferences-fonts.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-preferences-options.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-search.png create mode 100644 src/assistant/tools/assistant/doc/images/assistant-toolbar.png create mode 100644 src/assistant/tools/assistant/filternamedialog.cpp create mode 100644 src/assistant/tools/assistant/filternamedialog.h create mode 100644 src/assistant/tools/assistant/filternamedialog.ui create mode 100644 src/assistant/tools/assistant/findwidget.cpp create mode 100644 src/assistant/tools/assistant/findwidget.h create mode 100644 src/assistant/tools/assistant/globalactions.cpp create mode 100644 src/assistant/tools/assistant/globalactions.h create mode 100644 src/assistant/tools/assistant/helpenginewrapper.cpp create mode 100644 src/assistant/tools/assistant/helpenginewrapper.h create mode 100644 src/assistant/tools/assistant/helpviewer.cpp create mode 100644 src/assistant/tools/assistant/helpviewer.h create mode 100644 src/assistant/tools/assistant/helpviewer_p.h create mode 100644 src/assistant/tools/assistant/helpviewer_qtb.cpp create mode 100644 src/assistant/tools/assistant/helpviewer_qwv.cpp create mode 100644 src/assistant/tools/assistant/images/assistant-128.png create mode 100644 src/assistant/tools/assistant/images/assistant.png create mode 100644 src/assistant/tools/assistant/images/bookmark.png create mode 100644 src/assistant/tools/assistant/images/closebutton.png create mode 100644 src/assistant/tools/assistant/images/darkclosebutton.png create mode 100644 src/assistant/tools/assistant/images/mac/addtab.png create mode 100644 src/assistant/tools/assistant/images/mac/book.png create mode 100644 src/assistant/tools/assistant/images/mac/closetab.png create mode 100644 src/assistant/tools/assistant/images/mac/editcopy.png create mode 100644 src/assistant/tools/assistant/images/mac/find.png create mode 100644 src/assistant/tools/assistant/images/mac/home.png create mode 100644 src/assistant/tools/assistant/images/mac/next.png create mode 100644 src/assistant/tools/assistant/images/mac/previous.png create mode 100644 src/assistant/tools/assistant/images/mac/print.png create mode 100644 src/assistant/tools/assistant/images/mac/resetzoom.png create mode 100644 src/assistant/tools/assistant/images/mac/synctoc.png create mode 100644 src/assistant/tools/assistant/images/mac/zoomin.png create mode 100644 src/assistant/tools/assistant/images/mac/zoomout.png create mode 100644 src/assistant/tools/assistant/images/trolltech-logo.png create mode 100644 src/assistant/tools/assistant/images/win/addtab.png create mode 100644 src/assistant/tools/assistant/images/win/book.png create mode 100644 src/assistant/tools/assistant/images/win/closetab.png create mode 100644 src/assistant/tools/assistant/images/win/editcopy.png create mode 100644 src/assistant/tools/assistant/images/win/find.png create mode 100644 src/assistant/tools/assistant/images/win/home.png create mode 100644 src/assistant/tools/assistant/images/win/next.png create mode 100644 src/assistant/tools/assistant/images/win/previous.png create mode 100644 src/assistant/tools/assistant/images/win/print.png create mode 100644 src/assistant/tools/assistant/images/win/resetzoom.png create mode 100644 src/assistant/tools/assistant/images/win/synctoc.png create mode 100644 src/assistant/tools/assistant/images/win/zoomin.png create mode 100644 src/assistant/tools/assistant/images/win/zoomout.png create mode 100644 src/assistant/tools/assistant/images/wrap.png create mode 100644 src/assistant/tools/assistant/indexwindow.cpp create mode 100644 src/assistant/tools/assistant/indexwindow.h create mode 100644 src/assistant/tools/assistant/installdialog.cpp create mode 100644 src/assistant/tools/assistant/installdialog.h create mode 100644 src/assistant/tools/assistant/installdialog.ui create mode 100644 src/assistant/tools/assistant/main.cpp create mode 100644 src/assistant/tools/assistant/mainwindow.cpp create mode 100644 src/assistant/tools/assistant/mainwindow.h create mode 100644 src/assistant/tools/assistant/openpagesmanager.cpp create mode 100644 src/assistant/tools/assistant/openpagesmanager.h create mode 100644 src/assistant/tools/assistant/openpagesmodel.cpp create mode 100644 src/assistant/tools/assistant/openpagesmodel.h create mode 100644 src/assistant/tools/assistant/openpagesswitcher.cpp create mode 100644 src/assistant/tools/assistant/openpagesswitcher.h create mode 100644 src/assistant/tools/assistant/openpageswidget.cpp create mode 100644 src/assistant/tools/assistant/openpageswidget.h create mode 100644 src/assistant/tools/assistant/preferencesdialog.cpp create mode 100644 src/assistant/tools/assistant/preferencesdialog.h create mode 100644 src/assistant/tools/assistant/preferencesdialog.ui create mode 100644 src/assistant/tools/assistant/qtdocinstaller.cpp create mode 100644 src/assistant/tools/assistant/qtdocinstaller.h create mode 100644 src/assistant/tools/assistant/remotecontrol.cpp create mode 100644 src/assistant/tools/assistant/remotecontrol.h create mode 100644 src/assistant/tools/assistant/remotecontrol_win.h create mode 100644 src/assistant/tools/assistant/searchwidget.cpp create mode 100644 src/assistant/tools/assistant/searchwidget.h create mode 100644 src/assistant/tools/assistant/topicchooser.cpp create mode 100644 src/assistant/tools/assistant/topicchooser.h create mode 100644 src/assistant/tools/assistant/topicchooser.ui create mode 100644 src/assistant/tools/assistant/tracer.h create mode 100644 src/assistant/tools/assistant/xbelsupport.cpp create mode 100644 src/assistant/tools/assistant/xbelsupport.h create mode 100644 src/assistant/tools/qcollectiongenerator/main.cpp create mode 100644 src/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro create mode 100644 src/assistant/tools/qhelpconverter/adpreader.cpp create mode 100644 src/assistant/tools/qhelpconverter/adpreader.h create mode 100644 src/assistant/tools/qhelpconverter/assistant-128.png create mode 100644 src/assistant/tools/qhelpconverter/assistant.png create mode 100644 src/assistant/tools/qhelpconverter/conversionwizard.cpp create mode 100644 src/assistant/tools/qhelpconverter/conversionwizard.h create mode 100644 src/assistant/tools/qhelpconverter/doc/filespage.html create mode 100644 src/assistant/tools/qhelpconverter/doc/filterpage.html create mode 100644 src/assistant/tools/qhelpconverter/doc/generalpage.html create mode 100644 src/assistant/tools/qhelpconverter/doc/identifierpage.html create mode 100644 src/assistant/tools/qhelpconverter/doc/inputpage.html create mode 100644 src/assistant/tools/qhelpconverter/doc/outputpage.html create mode 100644 src/assistant/tools/qhelpconverter/doc/pathpage.html create mode 100644 src/assistant/tools/qhelpconverter/filespage.cpp create mode 100644 src/assistant/tools/qhelpconverter/filespage.h create mode 100644 src/assistant/tools/qhelpconverter/filespage.ui create mode 100644 src/assistant/tools/qhelpconverter/filterpage.cpp create mode 100644 src/assistant/tools/qhelpconverter/filterpage.h create mode 100644 src/assistant/tools/qhelpconverter/filterpage.ui create mode 100644 src/assistant/tools/qhelpconverter/finishpage.cpp create mode 100644 src/assistant/tools/qhelpconverter/finishpage.h create mode 100644 src/assistant/tools/qhelpconverter/generalpage.cpp create mode 100644 src/assistant/tools/qhelpconverter/generalpage.h create mode 100644 src/assistant/tools/qhelpconverter/generalpage.ui create mode 100644 src/assistant/tools/qhelpconverter/helpwindow.cpp create mode 100644 src/assistant/tools/qhelpconverter/helpwindow.h create mode 100644 src/assistant/tools/qhelpconverter/identifierpage.cpp create mode 100644 src/assistant/tools/qhelpconverter/identifierpage.h create mode 100644 src/assistant/tools/qhelpconverter/identifierpage.ui create mode 100644 src/assistant/tools/qhelpconverter/inputpage.cpp create mode 100644 src/assistant/tools/qhelpconverter/inputpage.h create mode 100644 src/assistant/tools/qhelpconverter/inputpage.ui create mode 100644 src/assistant/tools/qhelpconverter/main.cpp create mode 100644 src/assistant/tools/qhelpconverter/outputpage.cpp create mode 100644 src/assistant/tools/qhelpconverter/outputpage.h create mode 100644 src/assistant/tools/qhelpconverter/outputpage.ui create mode 100644 src/assistant/tools/qhelpconverter/pathpage.cpp create mode 100644 src/assistant/tools/qhelpconverter/pathpage.h create mode 100644 src/assistant/tools/qhelpconverter/pathpage.ui create mode 100644 src/assistant/tools/qhelpconverter/qhcpwriter.cpp create mode 100644 src/assistant/tools/qhelpconverter/qhcpwriter.h create mode 100644 src/assistant/tools/qhelpconverter/qhelpconverter.pro create mode 100644 src/assistant/tools/qhelpconverter/qhelpconverter.qrc create mode 100644 src/assistant/tools/qhelpconverter/qhpwriter.cpp create mode 100644 src/assistant/tools/qhelpconverter/qhpwriter.h create mode 100644 src/assistant/tools/qhelpgenerator/main.cpp create mode 100644 src/assistant/tools/qhelpgenerator/qhelpgenerator.pro create mode 100644 src/assistant/tools/shared/collectionconfiguration.cpp create mode 100644 src/assistant/tools/shared/collectionconfiguration.h create mode 100644 src/assistant/tools/shared/helpgenerator.cpp create mode 100644 src/assistant/tools/shared/helpgenerator.h create mode 100644 src/assistant/tools/tools.pro create mode 100644 src/checksdk/README create mode 100644 src/checksdk/cesdkhandler.cpp create mode 100644 src/checksdk/cesdkhandler.h create mode 100644 src/checksdk/checksdk.pro create mode 100644 src/checksdk/main.cpp create mode 100644 src/designer/data/generate_header.xsl create mode 100644 src/designer/data/generate_impl.xsl create mode 100644 src/designer/data/generate_shared.xsl create mode 100644 src/designer/data/ui3.xsd create mode 100644 src/designer/data/ui4.xsd create mode 100644 src/designer/designer.pro create mode 100644 src/designer/src/components/buddyeditor/buddyeditor.cpp create mode 100644 src/designer/src/components/buddyeditor/buddyeditor.h create mode 100644 src/designer/src/components/buddyeditor/buddyeditor.pri create mode 100644 src/designer/src/components/buddyeditor/buddyeditor_global.h create mode 100644 src/designer/src/components/buddyeditor/buddyeditor_instance.cpp create mode 100644 src/designer/src/components/buddyeditor/buddyeditor_plugin.cpp create mode 100644 src/designer/src/components/buddyeditor/buddyeditor_plugin.h create mode 100644 src/designer/src/components/buddyeditor/buddyeditor_tool.cpp create mode 100644 src/designer/src/components/buddyeditor/buddyeditor_tool.h create mode 100644 src/designer/src/components/component.pri create mode 100644 src/designer/src/components/components.pro create mode 100644 src/designer/src/components/formeditor/brushmanagerproxy.cpp create mode 100644 src/designer/src/components/formeditor/brushmanagerproxy.h create mode 100644 src/designer/src/components/formeditor/default_actionprovider.cpp create mode 100644 src/designer/src/components/formeditor/default_actionprovider.h create mode 100644 src/designer/src/components/formeditor/default_container.cpp create mode 100644 src/designer/src/components/formeditor/default_container.h create mode 100644 src/designer/src/components/formeditor/default_layoutdecoration.cpp create mode 100644 src/designer/src/components/formeditor/default_layoutdecoration.h create mode 100644 src/designer/src/components/formeditor/defaultbrushes.xml create mode 100644 src/designer/src/components/formeditor/deviceprofiledialog.cpp create mode 100644 src/designer/src/components/formeditor/deviceprofiledialog.h create mode 100644 src/designer/src/components/formeditor/deviceprofiledialog.ui create mode 100644 src/designer/src/components/formeditor/dpi_chooser.cpp create mode 100644 src/designer/src/components/formeditor/dpi_chooser.h create mode 100644 src/designer/src/components/formeditor/embeddedoptionspage.cpp create mode 100644 src/designer/src/components/formeditor/embeddedoptionspage.h create mode 100644 src/designer/src/components/formeditor/formeditor.cpp create mode 100644 src/designer/src/components/formeditor/formeditor.h create mode 100644 src/designer/src/components/formeditor/formeditor.pri create mode 100644 src/designer/src/components/formeditor/formeditor.qrc create mode 100644 src/designer/src/components/formeditor/formeditor_global.h create mode 100644 src/designer/src/components/formeditor/formeditor_optionspage.cpp create mode 100644 src/designer/src/components/formeditor/formeditor_optionspage.h create mode 100644 src/designer/src/components/formeditor/formwindow.cpp create mode 100644 src/designer/src/components/formeditor/formwindow.h create mode 100644 src/designer/src/components/formeditor/formwindow_dnditem.cpp create mode 100644 src/designer/src/components/formeditor/formwindow_dnditem.h create mode 100644 src/designer/src/components/formeditor/formwindow_widgetstack.cpp create mode 100644 src/designer/src/components/formeditor/formwindow_widgetstack.h create mode 100644 src/designer/src/components/formeditor/formwindowcursor.cpp create mode 100644 src/designer/src/components/formeditor/formwindowcursor.h create mode 100644 src/designer/src/components/formeditor/formwindowmanager.cpp create mode 100644 src/designer/src/components/formeditor/formwindowmanager.h create mode 100644 src/designer/src/components/formeditor/formwindowsettings.cpp create mode 100644 src/designer/src/components/formeditor/formwindowsettings.h create mode 100644 src/designer/src/components/formeditor/formwindowsettings.ui create mode 100644 src/designer/src/components/formeditor/iconcache.cpp create mode 100644 src/designer/src/components/formeditor/iconcache.h create mode 100644 src/designer/src/components/formeditor/images/cleartext.png create mode 100644 src/designer/src/components/formeditor/images/color.png create mode 100644 src/designer/src/components/formeditor/images/configure.png create mode 100644 src/designer/src/components/formeditor/images/cursors/arrow.png create mode 100644 src/designer/src/components/formeditor/images/cursors/busy.png create mode 100644 src/designer/src/components/formeditor/images/cursors/closedhand.png create mode 100644 src/designer/src/components/formeditor/images/cursors/cross.png create mode 100644 src/designer/src/components/formeditor/images/cursors/hand.png create mode 100644 src/designer/src/components/formeditor/images/cursors/hsplit.png create mode 100644 src/designer/src/components/formeditor/images/cursors/ibeam.png create mode 100644 src/designer/src/components/formeditor/images/cursors/no.png create mode 100644 src/designer/src/components/formeditor/images/cursors/openhand.png create mode 100644 src/designer/src/components/formeditor/images/cursors/sizeall.png create mode 100644 src/designer/src/components/formeditor/images/cursors/sizeb.png create mode 100644 src/designer/src/components/formeditor/images/cursors/sizef.png create mode 100644 src/designer/src/components/formeditor/images/cursors/sizeh.png create mode 100644 src/designer/src/components/formeditor/images/cursors/sizev.png create mode 100644 src/designer/src/components/formeditor/images/cursors/uparrow.png create mode 100644 src/designer/src/components/formeditor/images/cursors/vsplit.png create mode 100644 src/designer/src/components/formeditor/images/cursors/wait.png create mode 100644 src/designer/src/components/formeditor/images/cursors/whatsthis.png create mode 100644 src/designer/src/components/formeditor/images/downplus.png create mode 100644 src/designer/src/components/formeditor/images/dropdownbutton.png create mode 100644 src/designer/src/components/formeditor/images/edit.png create mode 100644 src/designer/src/components/formeditor/images/editdelete-16.png create mode 100644 src/designer/src/components/formeditor/images/emptyicon.png create mode 100644 src/designer/src/components/formeditor/images/filenew-16.png create mode 100644 src/designer/src/components/formeditor/images/fileopen-16.png create mode 100644 src/designer/src/components/formeditor/images/leveldown.png create mode 100644 src/designer/src/components/formeditor/images/levelup.png create mode 100644 src/designer/src/components/formeditor/images/mac/adjustsize.png create mode 100644 src/designer/src/components/formeditor/images/mac/back.png create mode 100644 src/designer/src/components/formeditor/images/mac/buddytool.png create mode 100644 src/designer/src/components/formeditor/images/mac/down.png create mode 100644 src/designer/src/components/formeditor/images/mac/editbreaklayout.png create mode 100644 src/designer/src/components/formeditor/images/mac/editcopy.png create mode 100644 src/designer/src/components/formeditor/images/mac/editcut.png create mode 100644 src/designer/src/components/formeditor/images/mac/editdelete.png create mode 100644 src/designer/src/components/formeditor/images/mac/editform.png create mode 100644 src/designer/src/components/formeditor/images/mac/editgrid.png create mode 100644 src/designer/src/components/formeditor/images/mac/edithlayout.png create mode 100644 src/designer/src/components/formeditor/images/mac/edithlayoutsplit.png create mode 100644 src/designer/src/components/formeditor/images/mac/editlower.png create mode 100644 src/designer/src/components/formeditor/images/mac/editpaste.png create mode 100644 src/designer/src/components/formeditor/images/mac/editraise.png create mode 100644 src/designer/src/components/formeditor/images/mac/editvlayout.png create mode 100644 src/designer/src/components/formeditor/images/mac/editvlayoutsplit.png create mode 100644 src/designer/src/components/formeditor/images/mac/filenew.png create mode 100644 src/designer/src/components/formeditor/images/mac/fileopen.png create mode 100644 src/designer/src/components/formeditor/images/mac/filesave.png create mode 100644 src/designer/src/components/formeditor/images/mac/forward.png create mode 100644 src/designer/src/components/formeditor/images/mac/insertimage.png create mode 100644 src/designer/src/components/formeditor/images/mac/minus.png create mode 100644 src/designer/src/components/formeditor/images/mac/plus.png create mode 100644 src/designer/src/components/formeditor/images/mac/redo.png create mode 100644 src/designer/src/components/formeditor/images/mac/resetproperty.png create mode 100644 src/designer/src/components/formeditor/images/mac/resourceeditortool.png create mode 100644 src/designer/src/components/formeditor/images/mac/signalslottool.png create mode 100644 src/designer/src/components/formeditor/images/mac/simplifyrichtext.png create mode 100644 src/designer/src/components/formeditor/images/mac/tabordertool.png create mode 100644 src/designer/src/components/formeditor/images/mac/textanchor.png create mode 100644 src/designer/src/components/formeditor/images/mac/textbold.png create mode 100644 src/designer/src/components/formeditor/images/mac/textcenter.png create mode 100644 src/designer/src/components/formeditor/images/mac/textitalic.png create mode 100644 src/designer/src/components/formeditor/images/mac/textjustify.png create mode 100644 src/designer/src/components/formeditor/images/mac/textleft.png create mode 100644 src/designer/src/components/formeditor/images/mac/textright.png create mode 100644 src/designer/src/components/formeditor/images/mac/textsubscript.png create mode 100644 src/designer/src/components/formeditor/images/mac/textsuperscript.png create mode 100644 src/designer/src/components/formeditor/images/mac/textunder.png create mode 100644 src/designer/src/components/formeditor/images/mac/undo.png create mode 100644 src/designer/src/components/formeditor/images/mac/up.png create mode 100644 src/designer/src/components/formeditor/images/mac/widgettool.png create mode 100644 src/designer/src/components/formeditor/images/minus-16.png create mode 100644 src/designer/src/components/formeditor/images/plus-16.png create mode 100644 src/designer/src/components/formeditor/images/prefix-add.png create mode 100644 src/designer/src/components/formeditor/images/qt3logo.png create mode 100644 src/designer/src/components/formeditor/images/qtlogo.png create mode 100644 src/designer/src/components/formeditor/images/reload.png create mode 100644 src/designer/src/components/formeditor/images/resetproperty.png create mode 100644 src/designer/src/components/formeditor/images/sort.png create mode 100644 src/designer/src/components/formeditor/images/submenu.png create mode 100644 src/designer/src/components/formeditor/images/widgets/calendarwidget.png create mode 100644 src/designer/src/components/formeditor/images/widgets/checkbox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/columnview.png create mode 100644 src/designer/src/components/formeditor/images/widgets/combobox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/commandlinkbutton.png create mode 100644 src/designer/src/components/formeditor/images/widgets/dateedit.png create mode 100644 src/designer/src/components/formeditor/images/widgets/datetimeedit.png create mode 100644 src/designer/src/components/formeditor/images/widgets/dial.png create mode 100644 src/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/dockwidget.png create mode 100644 src/designer/src/components/formeditor/images/widgets/doublespinbox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/fontcombobox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/frame.png create mode 100644 src/designer/src/components/formeditor/images/widgets/graphicsview.png create mode 100644 src/designer/src/components/formeditor/images/widgets/groupbox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png create mode 100644 src/designer/src/components/formeditor/images/widgets/hscrollbar.png create mode 100644 src/designer/src/components/formeditor/images/widgets/hslider.png create mode 100644 src/designer/src/components/formeditor/images/widgets/hsplit.png create mode 100644 src/designer/src/components/formeditor/images/widgets/label.png create mode 100644 src/designer/src/components/formeditor/images/widgets/lcdnumber.png create mode 100644 src/designer/src/components/formeditor/images/widgets/line.png create mode 100644 src/designer/src/components/formeditor/images/widgets/lineedit.png create mode 100644 src/designer/src/components/formeditor/images/widgets/listbox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/listview.png create mode 100644 src/designer/src/components/formeditor/images/widgets/mdiarea.png create mode 100644 src/designer/src/components/formeditor/images/widgets/plaintextedit.png create mode 100644 src/designer/src/components/formeditor/images/widgets/progress.png create mode 100644 src/designer/src/components/formeditor/images/widgets/pushbutton.png create mode 100644 src/designer/src/components/formeditor/images/widgets/radiobutton.png create mode 100644 src/designer/src/components/formeditor/images/widgets/scrollarea.png create mode 100644 src/designer/src/components/formeditor/images/widgets/spacer.png create mode 100644 src/designer/src/components/formeditor/images/widgets/spinbox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/tabbar.png create mode 100644 src/designer/src/components/formeditor/images/widgets/table.png create mode 100644 src/designer/src/components/formeditor/images/widgets/tabwidget.png create mode 100644 src/designer/src/components/formeditor/images/widgets/textedit.png create mode 100644 src/designer/src/components/formeditor/images/widgets/timeedit.png create mode 100644 src/designer/src/components/formeditor/images/widgets/toolbox.png create mode 100644 src/designer/src/components/formeditor/images/widgets/toolbutton.png create mode 100644 src/designer/src/components/formeditor/images/widgets/vline.png create mode 100644 src/designer/src/components/formeditor/images/widgets/vscrollbar.png create mode 100644 src/designer/src/components/formeditor/images/widgets/vslider.png create mode 100644 src/designer/src/components/formeditor/images/widgets/vspacer.png create mode 100644 src/designer/src/components/formeditor/images/widgets/widget.png create mode 100644 src/designer/src/components/formeditor/images/widgets/widgetstack.png create mode 100644 src/designer/src/components/formeditor/images/widgets/wizard.png create mode 100644 src/designer/src/components/formeditor/images/win/adjustsize.png create mode 100644 src/designer/src/components/formeditor/images/win/back.png create mode 100644 src/designer/src/components/formeditor/images/win/buddytool.png create mode 100644 src/designer/src/components/formeditor/images/win/down.png create mode 100644 src/designer/src/components/formeditor/images/win/editbreaklayout.png create mode 100644 src/designer/src/components/formeditor/images/win/editcopy.png create mode 100644 src/designer/src/components/formeditor/images/win/editcut.png create mode 100644 src/designer/src/components/formeditor/images/win/editdelete.png create mode 100644 src/designer/src/components/formeditor/images/win/editform.png create mode 100644 src/designer/src/components/formeditor/images/win/editgrid.png create mode 100644 src/designer/src/components/formeditor/images/win/edithlayout.png create mode 100644 src/designer/src/components/formeditor/images/win/edithlayoutsplit.png create mode 100644 src/designer/src/components/formeditor/images/win/editlower.png create mode 100644 src/designer/src/components/formeditor/images/win/editpaste.png create mode 100644 src/designer/src/components/formeditor/images/win/editraise.png create mode 100644 src/designer/src/components/formeditor/images/win/editvlayout.png create mode 100644 src/designer/src/components/formeditor/images/win/editvlayoutsplit.png create mode 100644 src/designer/src/components/formeditor/images/win/filenew.png create mode 100644 src/designer/src/components/formeditor/images/win/fileopen.png create mode 100644 src/designer/src/components/formeditor/images/win/filesave.png create mode 100644 src/designer/src/components/formeditor/images/win/forward.png create mode 100644 src/designer/src/components/formeditor/images/win/insertimage.png create mode 100644 src/designer/src/components/formeditor/images/win/minus.png create mode 100644 src/designer/src/components/formeditor/images/win/plus.png create mode 100644 src/designer/src/components/formeditor/images/win/redo.png create mode 100644 src/designer/src/components/formeditor/images/win/resourceeditortool.png create mode 100644 src/designer/src/components/formeditor/images/win/signalslottool.png create mode 100644 src/designer/src/components/formeditor/images/win/simplifyrichtext.png create mode 100644 src/designer/src/components/formeditor/images/win/tabordertool.png create mode 100644 src/designer/src/components/formeditor/images/win/textanchor.png create mode 100644 src/designer/src/components/formeditor/images/win/textbold.png create mode 100644 src/designer/src/components/formeditor/images/win/textcenter.png create mode 100644 src/designer/src/components/formeditor/images/win/textitalic.png create mode 100644 src/designer/src/components/formeditor/images/win/textjustify.png create mode 100644 src/designer/src/components/formeditor/images/win/textleft.png create mode 100644 src/designer/src/components/formeditor/images/win/textright.png create mode 100644 src/designer/src/components/formeditor/images/win/textsubscript.png create mode 100644 src/designer/src/components/formeditor/images/win/textsuperscript.png create mode 100644 src/designer/src/components/formeditor/images/win/textunder.png create mode 100644 src/designer/src/components/formeditor/images/win/undo.png create mode 100644 src/designer/src/components/formeditor/images/win/up.png create mode 100644 src/designer/src/components/formeditor/images/win/widgettool.png create mode 100644 src/designer/src/components/formeditor/itemview_propertysheet.cpp create mode 100644 src/designer/src/components/formeditor/itemview_propertysheet.h create mode 100644 src/designer/src/components/formeditor/layout_propertysheet.cpp create mode 100644 src/designer/src/components/formeditor/layout_propertysheet.h create mode 100644 src/designer/src/components/formeditor/line_propertysheet.cpp create mode 100644 src/designer/src/components/formeditor/line_propertysheet.h create mode 100644 src/designer/src/components/formeditor/previewactiongroup.cpp create mode 100644 src/designer/src/components/formeditor/previewactiongroup.h create mode 100644 src/designer/src/components/formeditor/qdesigner_resource.cpp create mode 100644 src/designer/src/components/formeditor/qdesigner_resource.h create mode 100644 src/designer/src/components/formeditor/qdesignerundostack.cpp create mode 100644 src/designer/src/components/formeditor/qdesignerundostack.h create mode 100644 src/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp create mode 100644 src/designer/src/components/formeditor/qlayoutwidget_propertysheet.h create mode 100644 src/designer/src/components/formeditor/qmainwindow_container.cpp create mode 100644 src/designer/src/components/formeditor/qmainwindow_container.h create mode 100644 src/designer/src/components/formeditor/qmdiarea_container.cpp create mode 100644 src/designer/src/components/formeditor/qmdiarea_container.h create mode 100644 src/designer/src/components/formeditor/qtbrushmanager.cpp create mode 100644 src/designer/src/components/formeditor/qtbrushmanager.h create mode 100644 src/designer/src/components/formeditor/qwizard_container.cpp create mode 100644 src/designer/src/components/formeditor/qwizard_container.h create mode 100644 src/designer/src/components/formeditor/qworkspace_container.cpp create mode 100644 src/designer/src/components/formeditor/qworkspace_container.h create mode 100644 src/designer/src/components/formeditor/spacer_propertysheet.cpp create mode 100644 src/designer/src/components/formeditor/spacer_propertysheet.h create mode 100644 src/designer/src/components/formeditor/templateoptionspage.cpp create mode 100644 src/designer/src/components/formeditor/templateoptionspage.h create mode 100644 src/designer/src/components/formeditor/templateoptionspage.ui create mode 100644 src/designer/src/components/formeditor/tool_widgeteditor.cpp create mode 100644 src/designer/src/components/formeditor/tool_widgeteditor.h create mode 100644 src/designer/src/components/formeditor/widgetselection.cpp create mode 100644 src/designer/src/components/formeditor/widgetselection.h create mode 100644 src/designer/src/components/lib/lib.pro create mode 100644 src/designer/src/components/lib/lib_pch.h create mode 100644 src/designer/src/components/lib/qdesigner_components.cpp create mode 100644 src/designer/src/components/objectinspector/objectinspector.cpp create mode 100644 src/designer/src/components/objectinspector/objectinspector.h create mode 100644 src/designer/src/components/objectinspector/objectinspector.pri create mode 100644 src/designer/src/components/objectinspector/objectinspector_global.h create mode 100644 src/designer/src/components/objectinspector/objectinspectormodel.cpp create mode 100644 src/designer/src/components/objectinspector/objectinspectormodel_p.h create mode 100644 src/designer/src/components/propertyeditor/brushpropertymanager.cpp create mode 100644 src/designer/src/components/propertyeditor/brushpropertymanager.h create mode 100644 src/designer/src/components/propertyeditor/designerpropertymanager.cpp create mode 100644 src/designer/src/components/propertyeditor/designerpropertymanager.h create mode 100644 src/designer/src/components/propertyeditor/fontmapping.xml create mode 100644 src/designer/src/components/propertyeditor/fontpropertymanager.cpp create mode 100644 src/designer/src/components/propertyeditor/fontpropertymanager.h create mode 100644 src/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp create mode 100644 src/designer/src/components/propertyeditor/newdynamicpropertydialog.h create mode 100644 src/designer/src/components/propertyeditor/newdynamicpropertydialog.ui create mode 100644 src/designer/src/components/propertyeditor/paletteeditor.cpp create mode 100644 src/designer/src/components/propertyeditor/paletteeditor.h create mode 100644 src/designer/src/components/propertyeditor/paletteeditor.ui create mode 100644 src/designer/src/components/propertyeditor/paletteeditorbutton.cpp create mode 100644 src/designer/src/components/propertyeditor/paletteeditorbutton.h create mode 100644 src/designer/src/components/propertyeditor/previewframe.cpp create mode 100644 src/designer/src/components/propertyeditor/previewframe.h create mode 100644 src/designer/src/components/propertyeditor/previewwidget.cpp create mode 100644 src/designer/src/components/propertyeditor/previewwidget.h create mode 100644 src/designer/src/components/propertyeditor/previewwidget.ui create mode 100644 src/designer/src/components/propertyeditor/propertyeditor.cpp create mode 100644 src/designer/src/components/propertyeditor/propertyeditor.h create mode 100644 src/designer/src/components/propertyeditor/propertyeditor.pri create mode 100644 src/designer/src/components/propertyeditor/propertyeditor.qrc create mode 100644 src/designer/src/components/propertyeditor/propertyeditor_global.h create mode 100644 src/designer/src/components/propertyeditor/qlonglongvalidator.cpp create mode 100644 src/designer/src/components/propertyeditor/qlonglongvalidator.h create mode 100644 src/designer/src/components/propertyeditor/stringlisteditor.cpp create mode 100644 src/designer/src/components/propertyeditor/stringlisteditor.h create mode 100644 src/designer/src/components/propertyeditor/stringlisteditor.ui create mode 100644 src/designer/src/components/propertyeditor/stringlisteditorbutton.cpp create mode 100644 src/designer/src/components/propertyeditor/stringlisteditorbutton.h create mode 100644 src/designer/src/components/signalsloteditor/connectdialog.cpp create mode 100644 src/designer/src/components/signalsloteditor/connectdialog.ui create mode 100644 src/designer/src/components/signalsloteditor/connectdialog_p.h create mode 100644 src/designer/src/components/signalsloteditor/signalslot_utils.cpp create mode 100644 src/designer/src/components/signalsloteditor/signalslot_utils_p.h create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor.cpp create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor.h create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor.pri create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor_global.h create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor_p.h create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor_plugin.h create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditor_tool.h create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp create mode 100644 src/designer/src/components/signalsloteditor/signalsloteditorwindow.h create mode 100644 src/designer/src/components/tabordereditor/tabordereditor.cpp create mode 100644 src/designer/src/components/tabordereditor/tabordereditor.h create mode 100644 src/designer/src/components/tabordereditor/tabordereditor.pri create mode 100644 src/designer/src/components/tabordereditor/tabordereditor_global.h create mode 100644 src/designer/src/components/tabordereditor/tabordereditor_instance.cpp create mode 100644 src/designer/src/components/tabordereditor/tabordereditor_plugin.cpp create mode 100644 src/designer/src/components/tabordereditor/tabordereditor_plugin.h create mode 100644 src/designer/src/components/tabordereditor/tabordereditor_tool.cpp create mode 100644 src/designer/src/components/tabordereditor/tabordereditor_tool.h create mode 100644 src/designer/src/components/taskmenu/button_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/button_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/combobox_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/combobox_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/containerwidget_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/containerwidget_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/groupbox_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/groupbox_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/inplace_editor.cpp create mode 100644 src/designer/src/components/taskmenu/inplace_editor.h create mode 100644 src/designer/src/components/taskmenu/inplace_widget_helper.cpp create mode 100644 src/designer/src/components/taskmenu/inplace_widget_helper.h create mode 100644 src/designer/src/components/taskmenu/itemlisteditor.cpp create mode 100644 src/designer/src/components/taskmenu/itemlisteditor.h create mode 100644 src/designer/src/components/taskmenu/itemlisteditor.ui create mode 100644 src/designer/src/components/taskmenu/label_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/label_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/layouttaskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/layouttaskmenu.h create mode 100644 src/designer/src/components/taskmenu/lineedit_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/lineedit_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/listwidget_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/listwidget_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/listwidgeteditor.cpp create mode 100644 src/designer/src/components/taskmenu/listwidgeteditor.h create mode 100644 src/designer/src/components/taskmenu/menutaskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/menutaskmenu.h create mode 100644 src/designer/src/components/taskmenu/tablewidget_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/tablewidget_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/tablewidgeteditor.cpp create mode 100644 src/designer/src/components/taskmenu/tablewidgeteditor.h create mode 100644 src/designer/src/components/taskmenu/tablewidgeteditor.ui create mode 100644 src/designer/src/components/taskmenu/taskmenu.pri create mode 100644 src/designer/src/components/taskmenu/taskmenu_component.cpp create mode 100644 src/designer/src/components/taskmenu/taskmenu_component.h create mode 100644 src/designer/src/components/taskmenu/taskmenu_global.h create mode 100644 src/designer/src/components/taskmenu/textedit_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/textedit_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/toolbar_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/toolbar_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/treewidget_taskmenu.cpp create mode 100644 src/designer/src/components/taskmenu/treewidget_taskmenu.h create mode 100644 src/designer/src/components/taskmenu/treewidgeteditor.cpp create mode 100644 src/designer/src/components/taskmenu/treewidgeteditor.h create mode 100644 src/designer/src/components/taskmenu/treewidgeteditor.ui create mode 100644 src/designer/src/components/widgetbox/widgetbox.cpp create mode 100644 src/designer/src/components/widgetbox/widgetbox.h create mode 100644 src/designer/src/components/widgetbox/widgetbox.pri create mode 100644 src/designer/src/components/widgetbox/widgetbox.qrc create mode 100644 src/designer/src/components/widgetbox/widgetbox.xml create mode 100644 src/designer/src/components/widgetbox/widgetbox_dnditem.cpp create mode 100644 src/designer/src/components/widgetbox/widgetbox_dnditem.h create mode 100644 src/designer/src/components/widgetbox/widgetbox_global.h create mode 100644 src/designer/src/components/widgetbox/widgetboxcategorylistview.cpp create mode 100644 src/designer/src/components/widgetbox/widgetboxcategorylistview.h create mode 100644 src/designer/src/components/widgetbox/widgetboxtreewidget.cpp create mode 100644 src/designer/src/components/widgetbox/widgetboxtreewidget.h create mode 100644 src/designer/src/designer/Info_mac.plist create mode 100644 src/designer/src/designer/appfontdialog.cpp create mode 100644 src/designer/src/designer/appfontdialog.h create mode 100644 src/designer/src/designer/assistantclient.cpp create mode 100644 src/designer/src/designer/assistantclient.h create mode 100644 src/designer/src/designer/designer.icns create mode 100644 src/designer/src/designer/designer.ico create mode 100644 src/designer/src/designer/designer.pro create mode 100644 src/designer/src/designer/designer.qrc create mode 100644 src/designer/src/designer/designer.rc create mode 100644 src/designer/src/designer/designer_enums.h create mode 100644 src/designer/src/designer/images/designer.png create mode 100644 src/designer/src/designer/images/mdi.png create mode 100644 src/designer/src/designer/images/sdi.png create mode 100644 src/designer/src/designer/images/workbench.png create mode 100644 src/designer/src/designer/main.cpp create mode 100644 src/designer/src/designer/mainwindow.cpp create mode 100644 src/designer/src/designer/mainwindow.h create mode 100644 src/designer/src/designer/newform.cpp create mode 100644 src/designer/src/designer/newform.h create mode 100644 src/designer/src/designer/preferencesdialog.cpp create mode 100644 src/designer/src/designer/preferencesdialog.h create mode 100644 src/designer/src/designer/preferencesdialog.ui create mode 100644 src/designer/src/designer/qdesigner.cpp create mode 100644 src/designer/src/designer/qdesigner.h create mode 100644 src/designer/src/designer/qdesigner_actions.cpp create mode 100644 src/designer/src/designer/qdesigner_actions.h create mode 100644 src/designer/src/designer/qdesigner_appearanceoptions.cpp create mode 100644 src/designer/src/designer/qdesigner_appearanceoptions.h create mode 100644 src/designer/src/designer/qdesigner_appearanceoptions.ui create mode 100644 src/designer/src/designer/qdesigner_formwindow.cpp create mode 100644 src/designer/src/designer/qdesigner_formwindow.h create mode 100644 src/designer/src/designer/qdesigner_pch.h create mode 100644 src/designer/src/designer/qdesigner_server.cpp create mode 100644 src/designer/src/designer/qdesigner_server.h create mode 100644 src/designer/src/designer/qdesigner_settings.cpp create mode 100644 src/designer/src/designer/qdesigner_settings.h create mode 100644 src/designer/src/designer/qdesigner_toolwindow.cpp create mode 100644 src/designer/src/designer/qdesigner_toolwindow.h create mode 100644 src/designer/src/designer/qdesigner_workbench.cpp create mode 100644 src/designer/src/designer/qdesigner_workbench.h create mode 100644 src/designer/src/designer/saveformastemplate.cpp create mode 100644 src/designer/src/designer/saveformastemplate.h create mode 100644 src/designer/src/designer/saveformastemplate.ui create mode 100644 src/designer/src/designer/uifile.icns create mode 100644 src/designer/src/designer/versiondialog.cpp create mode 100644 src/designer/src/designer/versiondialog.h create mode 100644 src/designer/src/lib/components/qdesigner_components.h create mode 100644 src/designer/src/lib/components/qdesigner_components_global.h create mode 100644 src/designer/src/lib/extension/default_extensionfactory.cpp create mode 100644 src/designer/src/lib/extension/default_extensionfactory.h create mode 100644 src/designer/src/lib/extension/extension.cpp create mode 100644 src/designer/src/lib/extension/extension.h create mode 100644 src/designer/src/lib/extension/extension.pri create mode 100644 src/designer/src/lib/extension/extension_global.h create mode 100644 src/designer/src/lib/extension/qextensionmanager.cpp create mode 100644 src/designer/src/lib/extension/qextensionmanager.h create mode 100644 src/designer/src/lib/lib.pro create mode 100644 src/designer/src/lib/lib_pch.h create mode 100644 src/designer/src/lib/sdk/abstractactioneditor.cpp create mode 100644 src/designer/src/lib/sdk/abstractactioneditor.h create mode 100644 src/designer/src/lib/sdk/abstractbrushmanager.h create mode 100644 src/designer/src/lib/sdk/abstractdialoggui.cpp create mode 100644 src/designer/src/lib/sdk/abstractdialoggui_p.h create mode 100644 src/designer/src/lib/sdk/abstractdnditem.h create mode 100644 src/designer/src/lib/sdk/abstractdnditem.qdoc create mode 100644 src/designer/src/lib/sdk/abstractformeditor.cpp create mode 100644 src/designer/src/lib/sdk/abstractformeditor.h create mode 100644 src/designer/src/lib/sdk/abstractformeditorplugin.cpp create mode 100644 src/designer/src/lib/sdk/abstractformeditorplugin.h create mode 100644 src/designer/src/lib/sdk/abstractformwindow.cpp create mode 100644 src/designer/src/lib/sdk/abstractformwindow.h create mode 100644 src/designer/src/lib/sdk/abstractformwindowcursor.cpp create mode 100644 src/designer/src/lib/sdk/abstractformwindowcursor.h create mode 100644 src/designer/src/lib/sdk/abstractformwindowmanager.cpp create mode 100644 src/designer/src/lib/sdk/abstractformwindowmanager.h create mode 100644 src/designer/src/lib/sdk/abstractformwindowtool.cpp create mode 100644 src/designer/src/lib/sdk/abstractformwindowtool.h create mode 100644 src/designer/src/lib/sdk/abstracticoncache.h create mode 100644 src/designer/src/lib/sdk/abstracticoncache.qdoc create mode 100644 src/designer/src/lib/sdk/abstractintegration.cpp create mode 100644 src/designer/src/lib/sdk/abstractintegration.h create mode 100644 src/designer/src/lib/sdk/abstractintrospection.cpp create mode 100644 src/designer/src/lib/sdk/abstractintrospection_p.h create mode 100644 src/designer/src/lib/sdk/abstractlanguage.h create mode 100644 src/designer/src/lib/sdk/abstractmetadatabase.cpp create mode 100644 src/designer/src/lib/sdk/abstractmetadatabase.h create mode 100644 src/designer/src/lib/sdk/abstractnewformwidget.cpp create mode 100644 src/designer/src/lib/sdk/abstractnewformwidget_p.h create mode 100644 src/designer/src/lib/sdk/abstractobjectinspector.cpp create mode 100644 src/designer/src/lib/sdk/abstractobjectinspector.h create mode 100644 src/designer/src/lib/sdk/abstractoptionspage_p.h create mode 100644 src/designer/src/lib/sdk/abstractpromotioninterface.cpp create mode 100644 src/designer/src/lib/sdk/abstractpromotioninterface.h create mode 100644 src/designer/src/lib/sdk/abstractpropertyeditor.cpp create mode 100644 src/designer/src/lib/sdk/abstractpropertyeditor.h create mode 100644 src/designer/src/lib/sdk/abstractresourcebrowser.cpp create mode 100644 src/designer/src/lib/sdk/abstractresourcebrowser.h create mode 100644 src/designer/src/lib/sdk/abstractsettings_p.h create mode 100644 src/designer/src/lib/sdk/abstractwidgetbox.cpp create mode 100644 src/designer/src/lib/sdk/abstractwidgetbox.h create mode 100644 src/designer/src/lib/sdk/abstractwidgetdatabase.cpp create mode 100644 src/designer/src/lib/sdk/abstractwidgetdatabase.h create mode 100644 src/designer/src/lib/sdk/abstractwidgetfactory.cpp create mode 100644 src/designer/src/lib/sdk/abstractwidgetfactory.h create mode 100644 src/designer/src/lib/sdk/dynamicpropertysheet.h create mode 100644 src/designer/src/lib/sdk/dynamicpropertysheet.qdoc create mode 100644 src/designer/src/lib/sdk/extrainfo.cpp create mode 100644 src/designer/src/lib/sdk/extrainfo.h create mode 100644 src/designer/src/lib/sdk/layoutdecoration.h create mode 100644 src/designer/src/lib/sdk/layoutdecoration.qdoc create mode 100644 src/designer/src/lib/sdk/membersheet.h create mode 100644 src/designer/src/lib/sdk/membersheet.qdoc create mode 100644 src/designer/src/lib/sdk/propertysheet.h create mode 100644 src/designer/src/lib/sdk/propertysheet.qdoc create mode 100644 src/designer/src/lib/sdk/script.cpp create mode 100644 src/designer/src/lib/sdk/script_p.h create mode 100644 src/designer/src/lib/sdk/sdk.pri create mode 100644 src/designer/src/lib/sdk/sdk_global.h create mode 100644 src/designer/src/lib/sdk/taskmenu.h create mode 100644 src/designer/src/lib/sdk/taskmenu.qdoc create mode 100644 src/designer/src/lib/shared/actioneditor.cpp create mode 100644 src/designer/src/lib/shared/actioneditor_p.h create mode 100644 src/designer/src/lib/shared/actionprovider_p.h create mode 100644 src/designer/src/lib/shared/actionrepository.cpp create mode 100644 src/designer/src/lib/shared/actionrepository_p.h create mode 100644 src/designer/src/lib/shared/addlinkdialog.ui create mode 100644 src/designer/src/lib/shared/codedialog.cpp create mode 100644 src/designer/src/lib/shared/codedialog_p.h create mode 100644 src/designer/src/lib/shared/connectionedit.cpp create mode 100644 src/designer/src/lib/shared/connectionedit_p.h create mode 100644 src/designer/src/lib/shared/csshighlighter.cpp create mode 100644 src/designer/src/lib/shared/csshighlighter_p.h create mode 100644 src/designer/src/lib/shared/defaultgradients.xml create mode 100644 src/designer/src/lib/shared/deviceprofile.cpp create mode 100644 src/designer/src/lib/shared/deviceprofile_p.h create mode 100644 src/designer/src/lib/shared/dialoggui.cpp create mode 100644 src/designer/src/lib/shared/dialoggui_p.h create mode 100644 src/designer/src/lib/shared/extensionfactory_p.h create mode 100644 src/designer/src/lib/shared/filterwidget.cpp create mode 100644 src/designer/src/lib/shared/filterwidget_p.h create mode 100644 src/designer/src/lib/shared/formlayoutmenu.cpp create mode 100644 src/designer/src/lib/shared/formlayoutmenu_p.h create mode 100644 src/designer/src/lib/shared/formlayoutrowdialog.ui create mode 100644 src/designer/src/lib/shared/formwindowbase.cpp create mode 100644 src/designer/src/lib/shared/formwindowbase_p.h create mode 100644 src/designer/src/lib/shared/grid.cpp create mode 100644 src/designer/src/lib/shared/grid_p.h create mode 100644 src/designer/src/lib/shared/gridpanel.cpp create mode 100644 src/designer/src/lib/shared/gridpanel.ui create mode 100644 src/designer/src/lib/shared/gridpanel_p.h create mode 100644 src/designer/src/lib/shared/htmlhighlighter.cpp create mode 100644 src/designer/src/lib/shared/htmlhighlighter_p.h create mode 100644 src/designer/src/lib/shared/iconloader.cpp create mode 100644 src/designer/src/lib/shared/iconloader_p.h create mode 100644 src/designer/src/lib/shared/iconselector.cpp create mode 100644 src/designer/src/lib/shared/iconselector_p.h create mode 100644 src/designer/src/lib/shared/invisible_widget.cpp create mode 100644 src/designer/src/lib/shared/invisible_widget_p.h create mode 100644 src/designer/src/lib/shared/layout.cpp create mode 100644 src/designer/src/lib/shared/layout_p.h create mode 100644 src/designer/src/lib/shared/layoutinfo.cpp create mode 100644 src/designer/src/lib/shared/layoutinfo_p.h create mode 100644 src/designer/src/lib/shared/metadatabase.cpp create mode 100644 src/designer/src/lib/shared/metadatabase_p.h create mode 100644 src/designer/src/lib/shared/morphmenu.cpp create mode 100644 src/designer/src/lib/shared/morphmenu_p.h create mode 100644 src/designer/src/lib/shared/newactiondialog.cpp create mode 100644 src/designer/src/lib/shared/newactiondialog.ui create mode 100644 src/designer/src/lib/shared/newactiondialog_p.h create mode 100644 src/designer/src/lib/shared/newformwidget.cpp create mode 100644 src/designer/src/lib/shared/newformwidget.ui create mode 100644 src/designer/src/lib/shared/newformwidget_p.h create mode 100644 src/designer/src/lib/shared/orderdialog.cpp create mode 100644 src/designer/src/lib/shared/orderdialog.ui create mode 100644 src/designer/src/lib/shared/orderdialog_p.h create mode 100644 src/designer/src/lib/shared/plaintexteditor.cpp create mode 100644 src/designer/src/lib/shared/plaintexteditor_p.h create mode 100644 src/designer/src/lib/shared/plugindialog.cpp create mode 100644 src/designer/src/lib/shared/plugindialog.ui create mode 100644 src/designer/src/lib/shared/plugindialog_p.h create mode 100644 src/designer/src/lib/shared/pluginmanager.cpp create mode 100644 src/designer/src/lib/shared/pluginmanager_p.h create mode 100644 src/designer/src/lib/shared/previewconfigurationwidget.cpp create mode 100644 src/designer/src/lib/shared/previewconfigurationwidget.ui create mode 100644 src/designer/src/lib/shared/previewconfigurationwidget_p.h create mode 100644 src/designer/src/lib/shared/previewmanager.cpp create mode 100644 src/designer/src/lib/shared/previewmanager_p.h create mode 100644 src/designer/src/lib/shared/promotionmodel.cpp create mode 100644 src/designer/src/lib/shared/promotionmodel_p.h create mode 100644 src/designer/src/lib/shared/promotiontaskmenu.cpp create mode 100644 src/designer/src/lib/shared/promotiontaskmenu_p.h create mode 100644 src/designer/src/lib/shared/propertylineedit.cpp create mode 100644 src/designer/src/lib/shared/propertylineedit_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_command.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_command2.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_command2_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_command_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_dnditem.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_dnditem_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_dockwidget.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_dockwidget_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_formbuilder.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_formbuilder_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_formeditorcommand.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_formeditorcommand_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_formwindowcommand.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_formwindowcommand_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_formwindowmanager.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_formwindowmanager_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_integration.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_integration_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_introspection.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_introspection_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_membersheet.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_membersheet_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_menu.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_menu_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_menubar.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_menubar_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_objectinspector.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_objectinspector_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_promotion.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_promotion_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_promotiondialog.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_promotiondialog_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_propertycommand.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_propertycommand_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_propertyeditor.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_propertyeditor_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_propertysheet.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_propertysheet_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_qsettings.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_qsettings_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_stackedbox.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_stackedbox_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_tabwidget.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_tabwidget_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_taskmenu.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_taskmenu_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_toolbar.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_toolbar_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_toolbox.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_toolbox_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_utils.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_utils_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_widget.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_widget_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_widgetbox.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_widgetbox_p.h create mode 100644 src/designer/src/lib/shared/qdesigner_widgetitem.cpp create mode 100644 src/designer/src/lib/shared/qdesigner_widgetitem_p.h create mode 100644 src/designer/src/lib/shared/qlayout_widget.cpp create mode 100644 src/designer/src/lib/shared/qlayout_widget_p.h create mode 100644 src/designer/src/lib/shared/qscripthighlighter.cpp create mode 100644 src/designer/src/lib/shared/qscripthighlighter_p.h create mode 100644 src/designer/src/lib/shared/qsimpleresource.cpp create mode 100644 src/designer/src/lib/shared/qsimpleresource_p.h create mode 100644 src/designer/src/lib/shared/qtresourceeditordialog.cpp create mode 100644 src/designer/src/lib/shared/qtresourceeditordialog.ui create mode 100644 src/designer/src/lib/shared/qtresourceeditordialog_p.h create mode 100644 src/designer/src/lib/shared/qtresourcemodel.cpp create mode 100644 src/designer/src/lib/shared/qtresourcemodel_p.h create mode 100644 src/designer/src/lib/shared/qtresourceview.cpp create mode 100644 src/designer/src/lib/shared/qtresourceview_p.h create mode 100644 src/designer/src/lib/shared/richtexteditor.cpp create mode 100644 src/designer/src/lib/shared/richtexteditor_p.h create mode 100644 src/designer/src/lib/shared/scriptcommand.cpp create mode 100644 src/designer/src/lib/shared/scriptcommand_p.h create mode 100644 src/designer/src/lib/shared/scriptdialog.cpp create mode 100644 src/designer/src/lib/shared/scriptdialog_p.h create mode 100644 src/designer/src/lib/shared/scripterrordialog.cpp create mode 100644 src/designer/src/lib/shared/scripterrordialog_p.h create mode 100644 src/designer/src/lib/shared/selectsignaldialog.ui create mode 100644 src/designer/src/lib/shared/shared.pri create mode 100644 src/designer/src/lib/shared/shared.qrc create mode 100644 src/designer/src/lib/shared/shared_enums_p.h create mode 100644 src/designer/src/lib/shared/shared_global_p.h create mode 100644 src/designer/src/lib/shared/shared_settings.cpp create mode 100644 src/designer/src/lib/shared/shared_settings_p.h create mode 100644 src/designer/src/lib/shared/sheet_delegate.cpp create mode 100644 src/designer/src/lib/shared/sheet_delegate_p.h create mode 100644 src/designer/src/lib/shared/signalslotdialog.cpp create mode 100644 src/designer/src/lib/shared/signalslotdialog.ui create mode 100644 src/designer/src/lib/shared/signalslotdialog_p.h create mode 100644 src/designer/src/lib/shared/spacer_widget.cpp create mode 100644 src/designer/src/lib/shared/spacer_widget_p.h create mode 100644 src/designer/src/lib/shared/stylesheeteditor.cpp create mode 100644 src/designer/src/lib/shared/stylesheeteditor_p.h create mode 100644 src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui create mode 100644 src/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui create mode 100644 src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui create mode 100644 src/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui create mode 100644 src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui create mode 100644 src/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui create mode 100644 src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui create mode 100644 src/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui create mode 100644 src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui create mode 100644 src/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui create mode 100644 src/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui create mode 100644 src/designer/src/lib/shared/templates/forms/Main_Window.ui create mode 100644 src/designer/src/lib/shared/templates/forms/Widget.ui create mode 100644 src/designer/src/lib/shared/textpropertyeditor.cpp create mode 100644 src/designer/src/lib/shared/textpropertyeditor_p.h create mode 100644 src/designer/src/lib/shared/widgetdatabase.cpp create mode 100644 src/designer/src/lib/shared/widgetdatabase_p.h create mode 100644 src/designer/src/lib/shared/widgetfactory.cpp create mode 100644 src/designer/src/lib/shared/widgetfactory_p.h create mode 100644 src/designer/src/lib/shared/zoomwidget.cpp create mode 100644 src/designer/src/lib/shared/zoomwidget_p.h create mode 100644 src/designer/src/plugins/activeqt/activeqt.pro create mode 100644 src/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp create mode 100644 src/designer/src/plugins/activeqt/qaxwidgetextrainfo.h create mode 100644 src/designer/src/plugins/activeqt/qaxwidgetplugin.cpp create mode 100644 src/designer/src/plugins/activeqt/qaxwidgetplugin.h create mode 100644 src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp create mode 100644 src/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h create mode 100644 src/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp create mode 100644 src/designer/src/plugins/activeqt/qaxwidgettaskmenu.h create mode 100644 src/designer/src/plugins/activeqt/qdesigneraxwidget.cpp create mode 100644 src/designer/src/plugins/activeqt/qdesigneraxwidget.h create mode 100644 src/designer/src/plugins/phononwidgets/images/seekslider.png create mode 100644 src/designer/src/plugins/phononwidgets/images/videoplayer.png create mode 100644 src/designer/src/plugins/phononwidgets/images/videowidget.png create mode 100644 src/designer/src/plugins/phononwidgets/images/volumeslider.png create mode 100644 src/designer/src/plugins/phononwidgets/phononcollection.cpp create mode 100644 src/designer/src/plugins/phononwidgets/phononwidgets.pro create mode 100644 src/designer/src/plugins/phononwidgets/phononwidgets.qrc create mode 100644 src/designer/src/plugins/phononwidgets/seeksliderplugin.cpp create mode 100644 src/designer/src/plugins/phononwidgets/seeksliderplugin.h create mode 100644 src/designer/src/plugins/phononwidgets/videoplayerplugin.cpp create mode 100644 src/designer/src/plugins/phononwidgets/videoplayerplugin.h create mode 100644 src/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp create mode 100644 src/designer/src/plugins/phononwidgets/videoplayertaskmenu.h create mode 100644 src/designer/src/plugins/phononwidgets/volumesliderplugin.cpp create mode 100644 src/designer/src/plugins/phononwidgets/volumesliderplugin.h create mode 100644 src/designer/src/plugins/plugins.pri create mode 100644 src/designer/src/plugins/plugins.pro create mode 100644 src/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro create mode 100644 src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp create mode 100644 src/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h create mode 100644 src/designer/src/plugins/qwebview/images/qwebview.png create mode 100644 src/designer/src/plugins/qwebview/qwebview.pro create mode 100644 src/designer/src/plugins/qwebview/qwebview_plugin.cpp create mode 100644 src/designer/src/plugins/qwebview/qwebview_plugin.h create mode 100644 src/designer/src/plugins/qwebview/qwebview_plugin.qrc create mode 100644 src/designer/src/plugins/tools/view3d/view3d.cpp create mode 100644 src/designer/src/plugins/tools/view3d/view3d.h create mode 100644 src/designer/src/plugins/tools/view3d/view3d.pro create mode 100644 src/designer/src/plugins/tools/view3d/view3d_global.h create mode 100644 src/designer/src/plugins/tools/view3d/view3d_plugin.cpp create mode 100644 src/designer/src/plugins/tools/view3d/view3d_plugin.h create mode 100644 src/designer/src/plugins/tools/view3d/view3d_tool.cpp create mode 100644 src/designer/src/plugins/tools/view3d/view3d_tool.h create mode 100644 src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp create mode 100644 src/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h create mode 100644 src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp create mode 100644 src/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h create mode 100644 src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp create mode 100644 src/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h create mode 100644 src/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3listview/q3listview_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp create mode 100644 src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h create mode 100644 src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp create mode 100644 src/designer/src/plugins/widgets/q3table/q3table_extrainfo.h create mode 100644 src/designer/src/plugins/widgets/q3table/q3table_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3table/q3table_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp create mode 100644 src/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h create mode 100644 src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp create mode 100644 src/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h create mode 100644 src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp create mode 100644 src/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h create mode 100644 src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp create mode 100644 src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h create mode 100644 src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h create mode 100644 src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp create mode 100644 src/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h create mode 100644 src/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp create mode 100644 src/designer/src/plugins/widgets/q3wizard/q3wizard_container.h create mode 100644 src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp create mode 100644 src/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h create mode 100644 src/designer/src/plugins/widgets/qt3supportwidgets.cpp create mode 100644 src/designer/src/plugins/widgets/widgets.pro create mode 100644 src/designer/src/sharedcomponents.pri create mode 100644 src/designer/src/src.pro create mode 100644 src/doxygen/config/footer.html create mode 100644 src/doxygen/config/header.html create mode 100644 src/doxygen/config/phonon.css create mode 100644 src/doxygen/config/phonon.doxyfile create mode 100644 src/kmap2qmap/kmap2qmap.pro create mode 100644 src/kmap2qmap/main.cpp create mode 100644 src/linguist/lconvert/lconvert.pro create mode 100644 src/linguist/lconvert/main.cpp create mode 100644 src/linguist/linguist.pro create mode 100644 src/linguist/linguist/Info_mac.plist create mode 100644 src/linguist/linguist/batchtranslation.ui create mode 100644 src/linguist/linguist/batchtranslationdialog.cpp create mode 100644 src/linguist/linguist/batchtranslationdialog.h create mode 100644 src/linguist/linguist/errorsview.cpp create mode 100644 src/linguist/linguist/errorsview.h create mode 100644 src/linguist/linguist/finddialog.cpp create mode 100644 src/linguist/linguist/finddialog.h create mode 100644 src/linguist/linguist/finddialog.ui create mode 100644 src/linguist/linguist/formpreviewview.cpp create mode 100644 src/linguist/linguist/formpreviewview.h create mode 100644 src/linguist/linguist/globals.cpp create mode 100644 src/linguist/linguist/globals.h create mode 100644 src/linguist/linguist/images/appicon.png create mode 100644 src/linguist/linguist/images/down.png create mode 100644 src/linguist/linguist/images/editdelete.png create mode 100644 src/linguist/linguist/images/icons/linguist-128-32.png create mode 100644 src/linguist/linguist/images/icons/linguist-128-8.png create mode 100644 src/linguist/linguist/images/icons/linguist-16-32.png create mode 100644 src/linguist/linguist/images/icons/linguist-16-8.png create mode 100644 src/linguist/linguist/images/icons/linguist-32-32.png create mode 100644 src/linguist/linguist/images/icons/linguist-32-8.png create mode 100644 src/linguist/linguist/images/icons/linguist-48-32.png create mode 100644 src/linguist/linguist/images/icons/linguist-48-8.png create mode 100644 src/linguist/linguist/images/icons/linguist-64-32.png create mode 100644 src/linguist/linguist/images/icons/linguist-64-8.png create mode 100644 src/linguist/linguist/images/mac/accelerator.png create mode 100644 src/linguist/linguist/images/mac/book.png create mode 100644 src/linguist/linguist/images/mac/doneandnext.png create mode 100644 src/linguist/linguist/images/mac/editcopy.png create mode 100644 src/linguist/linguist/images/mac/editcut.png create mode 100644 src/linguist/linguist/images/mac/editpaste.png create mode 100644 src/linguist/linguist/images/mac/filenew.png create mode 100644 src/linguist/linguist/images/mac/fileopen.png create mode 100644 src/linguist/linguist/images/mac/fileprint.png create mode 100644 src/linguist/linguist/images/mac/filesave.png create mode 100644 src/linguist/linguist/images/mac/next.png create mode 100644 src/linguist/linguist/images/mac/nextunfinished.png create mode 100644 src/linguist/linguist/images/mac/phrase.png create mode 100644 src/linguist/linguist/images/mac/prev.png create mode 100644 src/linguist/linguist/images/mac/prevunfinished.png create mode 100644 src/linguist/linguist/images/mac/print.png create mode 100644 src/linguist/linguist/images/mac/punctuation.png create mode 100644 src/linguist/linguist/images/mac/redo.png create mode 100644 src/linguist/linguist/images/mac/searchfind.png create mode 100644 src/linguist/linguist/images/mac/undo.png create mode 100644 src/linguist/linguist/images/mac/validateplacemarkers.png create mode 100644 src/linguist/linguist/images/mac/whatsthis.png create mode 100644 src/linguist/linguist/images/minus.png create mode 100644 src/linguist/linguist/images/plus.png create mode 100644 src/linguist/linguist/images/s_check_danger.png create mode 100644 src/linguist/linguist/images/s_check_empty.png create mode 100644 src/linguist/linguist/images/s_check_obsolete.png create mode 100644 src/linguist/linguist/images/s_check_off.png create mode 100644 src/linguist/linguist/images/s_check_on.png create mode 100644 src/linguist/linguist/images/s_check_warning.png create mode 100644 src/linguist/linguist/images/splash.png create mode 100644 src/linguist/linguist/images/up.png create mode 100644 src/linguist/linguist/images/win/accelerator.png create mode 100644 src/linguist/linguist/images/win/book.png create mode 100644 src/linguist/linguist/images/win/doneandnext.png create mode 100644 src/linguist/linguist/images/win/editcopy.png create mode 100644 src/linguist/linguist/images/win/editcut.png create mode 100644 src/linguist/linguist/images/win/editpaste.png create mode 100644 src/linguist/linguist/images/win/filenew.png create mode 100644 src/linguist/linguist/images/win/fileopen.png create mode 100644 src/linguist/linguist/images/win/filesave.png create mode 100644 src/linguist/linguist/images/win/next.png create mode 100644 src/linguist/linguist/images/win/nextunfinished.png create mode 100644 src/linguist/linguist/images/win/phrase.png create mode 100644 src/linguist/linguist/images/win/prev.png create mode 100644 src/linguist/linguist/images/win/prevunfinished.png create mode 100644 src/linguist/linguist/images/win/print.png create mode 100644 src/linguist/linguist/images/win/punctuation.png create mode 100644 src/linguist/linguist/images/win/redo.png create mode 100644 src/linguist/linguist/images/win/searchfind.png create mode 100644 src/linguist/linguist/images/win/undo.png create mode 100644 src/linguist/linguist/images/win/validateplacemarkers.png create mode 100644 src/linguist/linguist/images/win/whatsthis.png create mode 100644 src/linguist/linguist/linguist.icns create mode 100644 src/linguist/linguist/linguist.ico create mode 100644 src/linguist/linguist/linguist.pro create mode 100644 src/linguist/linguist/linguist.qrc create mode 100644 src/linguist/linguist/linguist.rc create mode 100644 src/linguist/linguist/main.cpp create mode 100644 src/linguist/linguist/mainwindow.cpp create mode 100644 src/linguist/linguist/mainwindow.h create mode 100644 src/linguist/linguist/mainwindow.ui create mode 100644 src/linguist/linguist/messageeditor.cpp create mode 100644 src/linguist/linguist/messageeditor.h create mode 100644 src/linguist/linguist/messageeditorwidgets.cpp create mode 100644 src/linguist/linguist/messageeditorwidgets.h create mode 100644 src/linguist/linguist/messagehighlighter.cpp create mode 100644 src/linguist/linguist/messagehighlighter.h create mode 100644 src/linguist/linguist/messagemodel.cpp create mode 100644 src/linguist/linguist/messagemodel.h create mode 100644 src/linguist/linguist/phrase.cpp create mode 100644 src/linguist/linguist/phrase.h create mode 100644 src/linguist/linguist/phrasebookbox.cpp create mode 100644 src/linguist/linguist/phrasebookbox.h create mode 100644 src/linguist/linguist/phrasebookbox.ui create mode 100644 src/linguist/linguist/phrasemodel.cpp create mode 100644 src/linguist/linguist/phrasemodel.h create mode 100644 src/linguist/linguist/phraseview.cpp create mode 100644 src/linguist/linguist/phraseview.h create mode 100644 src/linguist/linguist/printout.cpp create mode 100644 src/linguist/linguist/printout.h create mode 100644 src/linguist/linguist/recentfiles.cpp create mode 100644 src/linguist/linguist/recentfiles.h create mode 100644 src/linguist/linguist/sourcecodeview.cpp create mode 100644 src/linguist/linguist/sourcecodeview.h create mode 100644 src/linguist/linguist/statistics.cpp create mode 100644 src/linguist/linguist/statistics.h create mode 100644 src/linguist/linguist/statistics.ui create mode 100644 src/linguist/linguist/translatedialog.cpp create mode 100644 src/linguist/linguist/translatedialog.h create mode 100644 src/linguist/linguist/translatedialog.ui create mode 100644 src/linguist/linguist/translationsettings.ui create mode 100644 src/linguist/linguist/translationsettingsdialog.cpp create mode 100644 src/linguist/linguist/translationsettingsdialog.h create mode 100644 src/linguist/lrelease/lrelease.1 create mode 100644 src/linguist/lrelease/lrelease.pro create mode 100644 src/linguist/lrelease/main.cpp create mode 100644 src/linguist/lupdate/cpp.cpp create mode 100644 src/linguist/lupdate/java.cpp create mode 100644 src/linguist/lupdate/lupdate.1 create mode 100644 src/linguist/lupdate/lupdate.exe.manifest create mode 100644 src/linguist/lupdate/lupdate.h create mode 100644 src/linguist/lupdate/lupdate.pro create mode 100644 src/linguist/lupdate/main.cpp create mode 100644 src/linguist/lupdate/merge.cpp create mode 100644 src/linguist/lupdate/qdeclarative.cpp create mode 100644 src/linguist/lupdate/qscript.cpp create mode 100644 src/linguist/lupdate/qscript.g create mode 100644 src/linguist/lupdate/ui.cpp create mode 100644 src/linguist/lupdate/winmanifest.rc create mode 100644 src/linguist/phrasebooks/danish.qph create mode 100644 src/linguist/phrasebooks/dutch.qph create mode 100644 src/linguist/phrasebooks/finnish.qph create mode 100644 src/linguist/phrasebooks/french.qph create mode 100644 src/linguist/phrasebooks/german.qph create mode 100644 src/linguist/phrasebooks/hungarian.qph create mode 100644 src/linguist/phrasebooks/italian.qph create mode 100644 src/linguist/phrasebooks/japanese.qph create mode 100644 src/linguist/phrasebooks/norwegian.qph create mode 100644 src/linguist/phrasebooks/polish.qph create mode 100644 src/linguist/phrasebooks/russian.qph create mode 100644 src/linguist/phrasebooks/spanish.qph create mode 100644 src/linguist/phrasebooks/swedish.qph create mode 100644 src/linguist/qdoc.conf create mode 100644 src/linguist/shared/abstractproitemvisitor.h create mode 100644 src/linguist/shared/formats.pri create mode 100644 src/linguist/shared/numerus.cpp create mode 100644 src/linguist/shared/po.cpp create mode 100644 src/linguist/shared/profileevaluator.cpp create mode 100644 src/linguist/shared/profileevaluator.h create mode 100644 src/linguist/shared/proitems.cpp create mode 100644 src/linguist/shared/proitems.h create mode 100644 src/linguist/shared/proparser.pri create mode 100644 src/linguist/shared/proparserutils.h create mode 100644 src/linguist/shared/qm.cpp create mode 100644 src/linguist/shared/qph.cpp create mode 100644 src/linguist/shared/simtexth.cpp create mode 100644 src/linguist/shared/simtexth.h create mode 100644 src/linguist/shared/translator.cpp create mode 100644 src/linguist/shared/translator.h create mode 100644 src/linguist/shared/translatormessage.cpp create mode 100644 src/linguist/shared/translatormessage.h create mode 100644 src/linguist/shared/ts.cpp create mode 100644 src/linguist/shared/ts.dtd create mode 100644 src/linguist/shared/xliff.cpp create mode 100644 src/linguist/tests/data/main.cpp create mode 100644 src/linguist/tests/data/test.pro create mode 100644 src/linguist/tests/tests.pro create mode 100644 src/linguist/tests/tst_linguist.cpp create mode 100644 src/linguist/tests/tst_linguist.h create mode 100644 src/linguist/tests/tst_lupdate.cpp create mode 100644 src/linguist/tests/tst_simtexth.cpp create mode 100644 src/macdeployqt/macchangeqt/macchangeqt.pro create mode 100644 src/macdeployqt/macchangeqt/main.cpp create mode 100644 src/macdeployqt/macdeployqt.pro create mode 100644 src/macdeployqt/macdeployqt/macdeployqt.pro create mode 100644 src/macdeployqt/macdeployqt/main.cpp create mode 100644 src/macdeployqt/shared/shared.cpp create mode 100644 src/macdeployqt/shared/shared.h create mode 100644 src/macdeployqt/tests/deployment_mac.pro create mode 100644 src/macdeployqt/tests/tst_deployment_mac.cpp create mode 100644 src/makeqpf/Blocks.txt create mode 100644 src/makeqpf/README create mode 100644 src/makeqpf/main.cpp create mode 100644 src/makeqpf/mainwindow.cpp create mode 100644 src/makeqpf/mainwindow.h create mode 100644 src/makeqpf/mainwindow.ui create mode 100644 src/makeqpf/makeqpf.pro create mode 100644 src/makeqpf/makeqpf.qrc create mode 100644 src/makeqpf/qpf2.cpp create mode 100644 src/makeqpf/qpf2.h create mode 100644 src/pixeltool/Info_mac.plist create mode 100644 src/pixeltool/main.cpp create mode 100644 src/pixeltool/pixeltool.pro create mode 100644 src/pixeltool/qpixeltool.cpp create mode 100644 src/pixeltool/qpixeltool.h create mode 100644 src/qconfig/feature.cpp create mode 100644 src/qconfig/feature.h create mode 100644 src/qconfig/featuretreemodel.cpp create mode 100644 src/qconfig/featuretreemodel.h create mode 100644 src/qconfig/graphics.h create mode 100644 src/qconfig/main.cpp create mode 100644 src/qconfig/qconfig.pro create mode 100644 src/qdbus/qdbus.pro create mode 100644 src/qdbus/qdbus/qdbus.cpp create mode 100644 src/qdbus/qdbus/qdbus.pro create mode 100644 src/qdbus/qdbuscpp2xml/qdbuscpp2xml.cpp create mode 100644 src/qdbus/qdbuscpp2xml/qdbuscpp2xml.pro create mode 100644 src/qdbus/qdbusviewer/Info_mac.plist create mode 100644 src/qdbus/qdbusviewer/images/qdbusviewer-128.png create mode 100644 src/qdbus/qdbusviewer/images/qdbusviewer.icns create mode 100644 src/qdbus/qdbusviewer/images/qdbusviewer.ico create mode 100644 src/qdbus/qdbusviewer/images/qdbusviewer.png create mode 100644 src/qdbus/qdbusviewer/main.cpp create mode 100644 src/qdbus/qdbusviewer/propertydialog.cpp create mode 100644 src/qdbus/qdbusviewer/propertydialog.h create mode 100644 src/qdbus/qdbusviewer/qdbusmodel.cpp create mode 100644 src/qdbus/qdbusviewer/qdbusmodel.h create mode 100644 src/qdbus/qdbusviewer/qdbusviewer.cpp create mode 100644 src/qdbus/qdbusviewer/qdbusviewer.h create mode 100644 src/qdbus/qdbusviewer/qdbusviewer.pro create mode 100644 src/qdbus/qdbusviewer/qdbusviewer.qrc create mode 100644 src/qdbus/qdbusviewer/qdbusviewer.rc create mode 100644 src/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp create mode 100644 src/qdbus/qdbusxml2cpp/qdbusxml2cpp.pro create mode 100644 src/qev/README create mode 100644 src/qev/qev.cpp create mode 100644 src/qev/qev.pro create mode 100644 src/qmeegographicssystemhelper/qmeegofencesync.cpp create mode 100644 src/qmeegographicssystemhelper/qmeegofencesync.h create mode 100644 src/qmeegographicssystemhelper/qmeegofencesync_p.h create mode 100644 src/qmeegographicssystemhelper/qmeegographicssystemhelper.cpp create mode 100644 src/qmeegographicssystemhelper/qmeegographicssystemhelper.h create mode 100644 src/qmeegographicssystemhelper/qmeegographicssystemhelper.pro create mode 100644 src/qmeegographicssystemhelper/qmeegolivepixmap.cpp create mode 100644 src/qmeegographicssystemhelper/qmeegolivepixmap.h create mode 100644 src/qmeegographicssystemhelper/qmeegolivepixmap_p.h create mode 100644 src/qmeegographicssystemhelper/qmeegooverlaywidget.cpp create mode 100644 src/qmeegographicssystemhelper/qmeegooverlaywidget.h create mode 100644 src/qmeegographicssystemhelper/qmeegoruntime.cpp create mode 100644 src/qmeegographicssystemhelper/qmeegoruntime.h create mode 100644 src/qmeegographicssystemhelper/qmeegoswitchevent.cpp create mode 100644 src/qmeegographicssystemhelper/qmeegoswitchevent.h create mode 100644 src/qtconcurrent/codegenerator/codegenerator.pri create mode 100644 src/qtconcurrent/codegenerator/example/example.pro create mode 100644 src/qtconcurrent/codegenerator/example/main.cpp create mode 100644 src/qtconcurrent/codegenerator/src/codegenerator.cpp create mode 100644 src/qtconcurrent/codegenerator/src/codegenerator.h create mode 100644 src/qtconcurrent/generaterun/main.cpp create mode 100644 src/qtconcurrent/generaterun/run.pro create mode 100644 src/qtconfig/colorbutton.cpp create mode 100644 src/qtconfig/colorbutton.h create mode 100644 src/qtconfig/images/appicon.png create mode 100644 src/qtconfig/main.cpp create mode 100644 src/qtconfig/mainwindow.cpp create mode 100644 src/qtconfig/mainwindow.h create mode 100644 src/qtconfig/mainwindow.ui create mode 100644 src/qtconfig/paletteeditoradvanced.cpp create mode 100644 src/qtconfig/paletteeditoradvanced.h create mode 100644 src/qtconfig/paletteeditoradvanced.ui create mode 100644 src/qtconfig/previewframe.cpp create mode 100644 src/qtconfig/previewframe.h create mode 100644 src/qtconfig/previewwidget.cpp create mode 100644 src/qtconfig/previewwidget.h create mode 100644 src/qtconfig/previewwidget.ui create mode 100644 src/qtconfig/qtconfig.pro create mode 100644 src/qtconfig/qtconfig.qrc create mode 100644 src/qtestlib/qtestlib.pro create mode 100644 src/qtestlib/updater/main.cpp create mode 100644 src/qtestlib/updater/updater.pro create mode 100644 src/qtestlib/wince/cetcpsync/cetcpsync.pro create mode 100644 src/qtestlib/wince/cetcpsync/main.cpp create mode 100644 src/qtestlib/wince/cetcpsync/qtcesterconnection.cpp create mode 100644 src/qtestlib/wince/cetcpsync/qtcesterconnection.h create mode 100644 src/qtestlib/wince/cetcpsync/remoteconnection.cpp create mode 100644 src/qtestlib/wince/cetcpsync/remoteconnection.h create mode 100644 src/qtestlib/wince/cetcpsyncserver/cetcpsyncserver.pro create mode 100644 src/qtestlib/wince/cetcpsyncserver/commands.cpp create mode 100644 src/qtestlib/wince/cetcpsyncserver/commands.h create mode 100644 src/qtestlib/wince/cetcpsyncserver/connectionmanager.cpp create mode 100644 src/qtestlib/wince/cetcpsyncserver/connectionmanager.h create mode 100644 src/qtestlib/wince/cetcpsyncserver/main.cpp create mode 100644 src/qtestlib/wince/cetcpsyncserver/transfer_global.h create mode 100644 src/qtestlib/wince/cetest/activesyncconnection.cpp create mode 100644 src/qtestlib/wince/cetest/activesyncconnection.h create mode 100644 src/qtestlib/wince/cetest/bootstrapped.pri create mode 100644 src/qtestlib/wince/cetest/cetcpsyncconnection.cpp create mode 100644 src/qtestlib/wince/cetest/cetcpsyncconnection.h create mode 100644 src/qtestlib/wince/cetest/cetest.pro create mode 100644 src/qtestlib/wince/cetest/deployment.cpp create mode 100644 src/qtestlib/wince/cetest/deployment.h create mode 100644 src/qtestlib/wince/cetest/main.cpp create mode 100644 src/qtestlib/wince/cetest/qmake_include.pri create mode 100644 src/qtestlib/wince/cetest/remoteconnection.cpp create mode 100644 src/qtestlib/wince/cetest/remoteconnection.h create mode 100644 src/qtestlib/wince/remotelib/commands.cpp create mode 100644 src/qtestlib/wince/remotelib/commands.h create mode 100644 src/qtestlib/wince/remotelib/remotelib.pro create mode 100644 src/qtestlib/wince/wince.pro create mode 100644 src/qttracereplay/main.cpp create mode 100644 src/qttracereplay/qttracereplay.pro create mode 100644 src/qvfb/README create mode 100644 src/qvfb/config.ui create mode 100644 src/qvfb/gammaview.h create mode 100644 src/qvfb/images/logo-nt.png create mode 100644 src/qvfb/images/logo.png create mode 100644 src/qvfb/main.cpp create mode 100644 src/qvfb/qanimationwriter.cpp create mode 100644 src/qvfb/qanimationwriter.h create mode 100644 src/qvfb/qtopiakeysym.h create mode 100644 src/qvfb/qvfb.cpp create mode 100644 src/qvfb/qvfb.h create mode 100644 src/qvfb/qvfb.pro create mode 100644 src/qvfb/qvfb.qrc create mode 100644 src/qvfb/qvfbmmap.cpp create mode 100644 src/qvfb/qvfbmmap.h create mode 100644 src/qvfb/qvfbprotocol.cpp create mode 100644 src/qvfb/qvfbprotocol.h create mode 100644 src/qvfb/qvfbratedlg.cpp create mode 100644 src/qvfb/qvfbratedlg.h create mode 100644 src/qvfb/qvfbshmem.cpp create mode 100644 src/qvfb/qvfbshmem.h create mode 100644 src/qvfb/qvfbview.cpp create mode 100644 src/qvfb/qvfbview.h create mode 100644 src/qvfb/qvfbx11view.cpp create mode 100644 src/qvfb/qvfbx11view.h create mode 100644 src/qvfb/x11keyfaker.cpp create mode 100644 src/qvfb/x11keyfaker.h create mode 100644 src/runonphone/main.cpp create mode 100644 src/runonphone/ossignalconverter.cpp create mode 100644 src/runonphone/ossignalconverter.h create mode 100644 src/runonphone/ossignalconverter_p.h create mode 100644 src/runonphone/runonphone.pro create mode 100644 src/runonphone/serenum.h create mode 100644 src/runonphone/serenum_stub.cpp create mode 100644 src/runonphone/serenum_unix.cpp create mode 100644 src/runonphone/serenum_win.cpp create mode 100644 src/runonphone/symbianutils/bluetoothlistener.cpp create mode 100644 src/runonphone/symbianutils/bluetoothlistener.h create mode 100644 src/runonphone/symbianutils/bluetoothlistener_gui.cpp create mode 100644 src/runonphone/symbianutils/bluetoothlistener_gui.h create mode 100644 src/runonphone/symbianutils/callback.h create mode 100644 src/runonphone/symbianutils/communicationstarter.cpp create mode 100644 src/runonphone/symbianutils/communicationstarter.h create mode 100644 src/runonphone/symbianutils/json.cpp create mode 100644 src/runonphone/symbianutils/json.h create mode 100644 src/runonphone/symbianutils/launcher.cpp create mode 100644 src/runonphone/symbianutils/launcher.h create mode 100644 src/runonphone/symbianutils/symbiandevicemanager.cpp create mode 100644 src/runonphone/symbianutils/symbiandevicemanager.h create mode 100644 src/runonphone/symbianutils/symbianutils.pri create mode 100644 src/runonphone/symbianutils/symbianutils_global.h create mode 100644 src/runonphone/symbianutils/tcftrkdevice.cpp create mode 100644 src/runonphone/symbianutils/tcftrkdevice.h create mode 100644 src/runonphone/symbianutils/tcftrkmessage.cpp create mode 100644 src/runonphone/symbianutils/tcftrkmessage.h create mode 100644 src/runonphone/symbianutils/trkdevice.cpp create mode 100644 src/runonphone/symbianutils/trkdevice.h create mode 100644 src/runonphone/symbianutils/trkutils.cpp create mode 100644 src/runonphone/symbianutils/trkutils.h create mode 100644 src/runonphone/symbianutils/trkutils_p.h create mode 100644 src/runonphone/trksignalhandler.cpp create mode 100644 src/runonphone/trksignalhandler.h create mode 100644 src/shared/deviceskin/deviceskin.cpp create mode 100644 src/shared/deviceskin/deviceskin.h create mode 100644 src/shared/deviceskin/deviceskin.pri create mode 100644 src/shared/deviceskin/skins/ClamshellPhone.qrc create mode 100644 src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone.skin create mode 100644 src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-closed.png create mode 100644 src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png create mode 100644 src/shared/deviceskin/skins/ClamshellPhone.skin/ClamshellPhone1-5.png create mode 100644 src/shared/deviceskin/skins/ClamshellPhone.skin/defaultbuttons.conf create mode 100644 src/shared/deviceskin/skins/PortableMedia.qrc create mode 100644 src/shared/deviceskin/skins/PortableMedia.skin/PortableMedia.skin create mode 100644 src/shared/deviceskin/skins/PortableMedia.skin/defaultbuttons.conf create mode 100644 src/shared/deviceskin/skins/PortableMedia.skin/portablemedia-pressed.png create mode 100644 src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.png create mode 100644 src/shared/deviceskin/skins/PortableMedia.skin/portablemedia.xcf create mode 100644 src/shared/deviceskin/skins/S60-QVGA-Candybar.qrc create mode 100644 src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png create mode 100644 src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png create mode 100644 src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin create mode 100644 src/shared/deviceskin/skins/S60-QVGA-Candybar.skin/defaultbuttons.conf create mode 100644 src/shared/deviceskin/skins/S60-nHD-Touchscreen.qrc create mode 100644 src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png create mode 100644 src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png create mode 100644 src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin create mode 100644 src/shared/deviceskin/skins/S60-nHD-Touchscreen.skin/defaultbuttons.conf create mode 100644 src/shared/deviceskin/skins/SmartPhone.qrc create mode 100644 src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone-pressed.png create mode 100644 src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.png create mode 100644 src/shared/deviceskin/skins/SmartPhone.skin/SmartPhone.skin create mode 100644 src/shared/deviceskin/skins/SmartPhone.skin/defaultbuttons.conf create mode 100644 src/shared/deviceskin/skins/SmartPhone2.qrc create mode 100644 src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2-pressed.png create mode 100644 src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.png create mode 100644 src/shared/deviceskin/skins/SmartPhone2.skin/SmartPhone2.skin create mode 100644 src/shared/deviceskin/skins/SmartPhone2.skin/defaultbuttons.conf create mode 100644 src/shared/deviceskin/skins/SmartPhoneWithButtons.qrc create mode 100644 src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png create mode 100644 src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png create mode 100644 src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin create mode 100644 src/shared/deviceskin/skins/SmartPhoneWithButtons.skin/defaultbuttons.conf create mode 100644 src/shared/deviceskin/skins/TouchscreenPhone.qrc create mode 100644 src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone-pressed.png create mode 100644 src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.png create mode 100644 src/shared/deviceskin/skins/TouchscreenPhone.skin/TouchscreenPhone.skin create mode 100644 src/shared/deviceskin/skins/TouchscreenPhone.skin/defaultbuttons.conf create mode 100644 src/shared/findwidget/abstractfindwidget.cpp create mode 100644 src/shared/findwidget/abstractfindwidget.h create mode 100644 src/shared/findwidget/findwidget.pri create mode 100644 src/shared/findwidget/findwidget.qrc create mode 100644 src/shared/findwidget/images/mac/closetab.png create mode 100644 src/shared/findwidget/images/mac/next.png create mode 100644 src/shared/findwidget/images/mac/previous.png create mode 100644 src/shared/findwidget/images/mac/searchfind.png create mode 100644 src/shared/findwidget/images/win/closetab.png create mode 100644 src/shared/findwidget/images/win/next.png create mode 100644 src/shared/findwidget/images/win/previous.png create mode 100644 src/shared/findwidget/images/win/searchfind.png create mode 100644 src/shared/findwidget/images/wrap.png create mode 100644 src/shared/findwidget/itemviewfindwidget.cpp create mode 100644 src/shared/findwidget/itemviewfindwidget.h create mode 100644 src/shared/findwidget/texteditfindwidget.cpp create mode 100644 src/shared/findwidget/texteditfindwidget.h create mode 100644 src/shared/fontpanel/fontpanel.cpp create mode 100644 src/shared/fontpanel/fontpanel.h create mode 100644 src/shared/fontpanel/fontpanel.pri create mode 100644 src/shared/qtgradienteditor/images/down.png create mode 100644 src/shared/qtgradienteditor/images/edit.png create mode 100644 src/shared/qtgradienteditor/images/editdelete.png create mode 100644 src/shared/qtgradienteditor/images/minus.png create mode 100644 src/shared/qtgradienteditor/images/plus.png create mode 100644 src/shared/qtgradienteditor/images/spreadpad.png create mode 100644 src/shared/qtgradienteditor/images/spreadreflect.png create mode 100644 src/shared/qtgradienteditor/images/spreadrepeat.png create mode 100644 src/shared/qtgradienteditor/images/typeconical.png create mode 100644 src/shared/qtgradienteditor/images/typelinear.png create mode 100644 src/shared/qtgradienteditor/images/typeradial.png create mode 100644 src/shared/qtgradienteditor/images/up.png create mode 100644 src/shared/qtgradienteditor/images/zoomin.png create mode 100644 src/shared/qtgradienteditor/images/zoomout.png create mode 100644 src/shared/qtgradienteditor/qtcolorbutton.cpp create mode 100644 src/shared/qtgradienteditor/qtcolorbutton.h create mode 100644 src/shared/qtgradienteditor/qtcolorbutton.pri create mode 100644 src/shared/qtgradienteditor/qtcolorline.cpp create mode 100644 src/shared/qtgradienteditor/qtcolorline.h create mode 100644 src/shared/qtgradienteditor/qtgradientdialog.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientdialog.h create mode 100644 src/shared/qtgradienteditor/qtgradientdialog.ui create mode 100644 src/shared/qtgradienteditor/qtgradienteditor.cpp create mode 100644 src/shared/qtgradienteditor/qtgradienteditor.h create mode 100644 src/shared/qtgradienteditor/qtgradienteditor.pri create mode 100644 src/shared/qtgradienteditor/qtgradienteditor.qrc create mode 100644 src/shared/qtgradienteditor/qtgradienteditor.ui create mode 100644 src/shared/qtgradienteditor/qtgradientmanager.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientmanager.h create mode 100644 src/shared/qtgradienteditor/qtgradientstopscontroller.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientstopscontroller.h create mode 100644 src/shared/qtgradienteditor/qtgradientstopsmodel.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientstopsmodel.h create mode 100644 src/shared/qtgradienteditor/qtgradientstopswidget.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientstopswidget.h create mode 100644 src/shared/qtgradienteditor/qtgradientutils.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientutils.h create mode 100644 src/shared/qtgradienteditor/qtgradientview.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientview.h create mode 100644 src/shared/qtgradienteditor/qtgradientview.ui create mode 100644 src/shared/qtgradienteditor/qtgradientviewdialog.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientviewdialog.h create mode 100644 src/shared/qtgradienteditor/qtgradientviewdialog.ui create mode 100644 src/shared/qtgradienteditor/qtgradientwidget.cpp create mode 100644 src/shared/qtgradienteditor/qtgradientwidget.h create mode 100644 src/shared/qtpropertybrowser/images/cursor-arrow.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-busy.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-closedhand.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-cross.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-forbidden.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-hand.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-hsplit.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-ibeam.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-openhand.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-sizeall.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-sizeb.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-sizef.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-sizeh.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-sizev.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-uparrow.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-vsplit.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-wait.png create mode 100644 src/shared/qtpropertybrowser/images/cursor-whatsthis.png create mode 100644 src/shared/qtpropertybrowser/qtbuttonpropertybrowser.cpp create mode 100644 src/shared/qtpropertybrowser/qtbuttonpropertybrowser.h create mode 100644 src/shared/qtpropertybrowser/qteditorfactory.cpp create mode 100644 src/shared/qtpropertybrowser/qteditorfactory.h create mode 100644 src/shared/qtpropertybrowser/qtgroupboxpropertybrowser.cpp create mode 100644 src/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h create mode 100644 src/shared/qtpropertybrowser/qtpropertybrowser.cpp create mode 100644 src/shared/qtpropertybrowser/qtpropertybrowser.h create mode 100644 src/shared/qtpropertybrowser/qtpropertybrowser.pri create mode 100644 src/shared/qtpropertybrowser/qtpropertybrowser.qrc create mode 100644 src/shared/qtpropertybrowser/qtpropertybrowserutils.cpp create mode 100644 src/shared/qtpropertybrowser/qtpropertybrowserutils.pri create mode 100644 src/shared/qtpropertybrowser/qtpropertybrowserutils_p.h create mode 100644 src/shared/qtpropertybrowser/qtpropertymanager.cpp create mode 100644 src/shared/qtpropertybrowser/qtpropertymanager.h create mode 100644 src/shared/qtpropertybrowser/qttreepropertybrowser.cpp create mode 100644 src/shared/qtpropertybrowser/qttreepropertybrowser.h create mode 100644 src/shared/qtpropertybrowser/qtvariantproperty.cpp create mode 100644 src/shared/qtpropertybrowser/qtvariantproperty.h create mode 100644 src/shared/qttoolbardialog/images/back.png create mode 100644 src/shared/qttoolbardialog/images/down.png create mode 100644 src/shared/qttoolbardialog/images/forward.png create mode 100644 src/shared/qttoolbardialog/images/minus.png create mode 100644 src/shared/qttoolbardialog/images/plus.png create mode 100644 src/shared/qttoolbardialog/images/up.png create mode 100644 src/shared/qttoolbardialog/qttoolbardialog.cpp create mode 100644 src/shared/qttoolbardialog/qttoolbardialog.h create mode 100644 src/shared/qttoolbardialog/qttoolbardialog.pri create mode 100644 src/shared/qttoolbardialog/qttoolbardialog.qrc create mode 100644 src/shared/qttoolbardialog/qttoolbardialog.ui create mode 100644 src/tools.pro create mode 100644 tests/README create mode 100644 tests/auto/auto.pro create mode 100644 tests/auto/bic/.gitignore create mode 100644 tests/auto/bic/data/QtDesigner.4.2.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtDesigner.4.3.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtDesigner.4.4.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtDesigner.4.5.0.linux-gcc-amd64.txt create mode 100644 tests/auto/bic/data/QtDesigner.4.5.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtDesigner.4.6.0.linux-gcc-amd64.txt create mode 100644 tests/auto/bic/data/QtDesigner.4.6.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtDesigner.4.7.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtHelp.4.5.0.linux-gcc-amd64.txt create mode 100644 tests/auto/bic/data/QtHelp.4.5.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtHelp.4.6.0.linux-gcc-amd64.txt create mode 100644 tests/auto/bic/data/QtHelp.4.6.0.linux-gcc-ia32.txt create mode 100644 tests/auto/bic/data/QtHelp.4.7.0.linux-gcc-ia32.txt create mode 100644 tests/auto/linguist/lconvert/.gitignore create mode 100644 tests/auto/linguist/lconvert/data/codec-cp1252.ts create mode 100644 tests/auto/linguist/lconvert/data/codec-utf8.ts create mode 100644 tests/auto/linguist/lconvert/data/dual-encoding.ts create mode 100644 tests/auto/linguist/lconvert/data/endless-po-loop.ts create mode 100755 tests/auto/linguist/lconvert/data/makeplurals.pl create mode 100644 tests/auto/linguist/lconvert/data/msgid.ts create mode 100644 tests/auto/linguist/lconvert/data/phrasebook.qph create mode 100644 tests/auto/linguist/lconvert/data/plurals-cn.ts create mode 100644 tests/auto/linguist/lconvert/data/plurals-de.ts create mode 100644 tests/auto/linguist/lconvert/data/relative.ts create mode 100644 tests/auto/linguist/lconvert/data/singular.po create mode 100644 tests/auto/linguist/lconvert/data/test-broken-utf8.po create mode 100644 tests/auto/linguist/lconvert/data/test-broken-utf8.po.out create mode 100644 tests/auto/linguist/lconvert/data/test-developer-comment.po create mode 100644 tests/auto/linguist/lconvert/data/test-empty-comment.po create mode 100644 tests/auto/linguist/lconvert/data/test-escapes.po create mode 100644 tests/auto/linguist/lconvert/data/test-escapes.po.out create mode 100644 tests/auto/linguist/lconvert/data/test-kde-ctxt.po create mode 100644 tests/auto/linguist/lconvert/data/test-kde-fuzzy.po create mode 100644 tests/auto/linguist/lconvert/data/test-kde-multiline.po create mode 100644 tests/auto/linguist/lconvert/data/test-kde-plurals.po create mode 100644 tests/auto/linguist/lconvert/data/test-refs.po create mode 100644 tests/auto/linguist/lconvert/data/test-slurp.po create mode 100644 tests/auto/linguist/lconvert/data/test-slurp.po.out create mode 100644 tests/auto/linguist/lconvert/data/test-translator-comment.po create mode 100644 tests/auto/linguist/lconvert/data/test1-cn.po create mode 100644 tests/auto/linguist/lconvert/data/test1-de.po create mode 100644 tests/auto/linguist/lconvert/data/test11.ts create mode 100644 tests/auto/linguist/lconvert/data/test20.ts create mode 100644 tests/auto/linguist/lconvert/data/variants.ts create mode 100644 tests/auto/linguist/lconvert/data/wrapping.po create mode 100644 tests/auto/linguist/lconvert/lconvert.pro create mode 100644 tests/auto/linguist/lconvert/tst_lconvert.cpp create mode 100644 tests/auto/linguist/linguist.pro create mode 100644 tests/auto/linguist/lrelease/.gitignore create mode 100644 tests/auto/linguist/lrelease/lrelease.pro create mode 100644 tests/auto/linguist/lrelease/testdata/compressed.ts create mode 100644 tests/auto/linguist/lrelease/testdata/dupes.errors create mode 100644 tests/auto/linguist/lrelease/testdata/dupes.ts create mode 100644 tests/auto/linguist/lrelease/testdata/idbased.ts create mode 100644 tests/auto/linguist/lrelease/testdata/mixedcodecs-ts11.ts create mode 100644 tests/auto/linguist/lrelease/testdata/mixedcodecs-ts20.ts create mode 100644 tests/auto/linguist/lrelease/testdata/translate.ts create mode 100644 tests/auto/linguist/lrelease/tst_lrelease.cpp create mode 100644 tests/auto/linguist/lupdate/.gitignore create mode 100644 tests/auto/linguist/lupdate/lupdate.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/backslashes/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/backslashes/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/backslashes/src/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/backslashes/ts/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_deeppath/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_deeppath/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_order/a.h create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_order/b.h create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_order/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_order/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_recurse/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/cmdline_recurse/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecforsrc/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecforsrc/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecforsrc/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr1/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr1/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr1/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr2/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr2/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr2/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr3/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr3/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr3/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr3/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr3/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr4/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr4/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr4/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr4/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/codecfortr4/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/from_subdir/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/from_subdir/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/from_subdir/src/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/from_subdir/src/main.h create mode 100644 tests/auto/linguist/lupdate/testdata/good/from_subdir/translations/translations.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/heuristics/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/heuristics/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/heuristics/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/heuristics/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/heuristics/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/heuristics/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/lacksqobject/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/lacksqobject/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/lacksqobject/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/lacksqobject/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_ordering/foo.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_ordering/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_ordering/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_ordering/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_ordering/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_versions/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_versions/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_versions/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_versions/project.ui create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_whitespace/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_whitespace/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_whitespace/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/merge_whitespace/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp/finddialog.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_noobsolete/finddialog.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_noobsolete/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_noobsolete/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_noobsolete/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_noobsolete/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_obsolete/finddialog.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_obsolete/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_obsolete/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergecpp_obsolete/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui/project.ui create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui_obsolete/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui_obsolete/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui_obsolete/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/mergeui_obsolete/project.ui create mode 100644 tests/auto/linguist/lupdate/testdata/good/multiple_locations/finddialog.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/multiple_locations/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/multiple_locations/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/multiple_locations/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/namespaces/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/namespaces/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/namespaces/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parse_special_chars/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parse_special_chars/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parse_special_chars/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecontexts/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecontexts/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecontexts/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp/finddialog.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.h create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/main2.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/main3.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejava/main.java create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejava/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejava/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejs/main.js create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejs/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejs/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejs2/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejs2/main.js create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejs2/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejs2/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejscontexts/main.js create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsejscontexts/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml create mode 100644 tests/auto/linguist/lupdate/testdata/good/parseqml/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parseui/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parseui/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/parseui/project.ui create mode 100644 tests/auto/linguist/lupdate/testdata/good/prefix/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/prefix/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/prefix/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/preprocess/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/preprocess/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/preprocess/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/main_mac.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/main_unix.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/main_win.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/vpaths/dependpath/main_dependpath.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/wildcard/main1.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/wildcard/mainfile.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/wildcard1.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing/wildcard99.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/a create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/a.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/b create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/b.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/e create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/f/g.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/files-cc.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/spaces/z create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/variable_with_spaces create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/with create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/x/d create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsing2/x/variable create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpaths/file1.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpaths/filter.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpaths/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/sub.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfile1.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpaths/sub/subfilter.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/common/common.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/common/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/common/main.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/mac/mac.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/mac/main_mac.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/relativity/relativity.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/relativity/relativity.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/relativity/sub/sub.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/relativity/sub2/sub2.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/unix/main_unix.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/unix/unix.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/win/main_win.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingpri/win/win.pri create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubdirs/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubdirs/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubdirs/sub1/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubdirs/sub1/sub1.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/common/common.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/common/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/mac/mac.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/mac/main_mac.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/unix/main_unix.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/unix/unix.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/win/main_win.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/proparsingsubs/win/win.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full/project_sub.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts/project_sub.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts/project_sub.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts_join/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts_join/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_full_ts_join/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part/project_sub.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part_ts/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part_ts/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part_ts/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part_ts/project_sub.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/recurse_part_ts/project_sub.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/reloutput/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/reloutput/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/reloutput/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/reloutput/translations/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/lupdatecmd create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/source1.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/source2.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/sources.lst create mode 100644 tests/auto/linguist/lupdate/testdata/good/respfile/tsfiles.lst create mode 100644 tests/auto/linguist/lupdate/testdata/good/textsimilarity/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/textsimilarity/project.ts.before create mode 100644 tests/auto/linguist/lupdate/testdata/good/textsimilarity/project.ts.result create mode 100644 tests/auto/linguist/lupdate/testdata/good/textsimilarity/project.ui create mode 100644 tests/auto/linguist/lupdate/testdata/recursivescan/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/recursivescan/project.ui create mode 100644 tests/auto/linguist/lupdate/testdata/recursivescan/sub/filetypes/main.c++ create mode 100644 tests/auto/linguist/lupdate/testdata/recursivescan/sub/filetypes/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/recursivescan/sub/filetypes/main.cxx create mode 100644 tests/auto/linguist/lupdate/testdata/recursivescan/sub/finddialog.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/subdir1/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/subdir1/subdir1.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/subdir2/subdir2.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/subdir2/subsub1/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/subdir2/subsub1/subsub1.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/subdir2/subsub2/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_full/subdir2/subsub2/subsub2.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/subdir1/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/subdir1/subdir1.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/subdir2/subdir2.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/subdir2/subsub1/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/subdir2/subsub1/subsub1.pro create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/subdir2/subsub2/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/subdirs_part/subdir2/subsub2/subsub2.pro create mode 100644 tests/auto/linguist/lupdate/tst_lupdate.cpp create mode 100644 tests/auto/qhelpcontentmodel/.gitignore create mode 100644 tests/auto/qhelpcontentmodel/data/collection.qhc create mode 100644 tests/auto/qhelpcontentmodel/data/qmake-3.3.8.qch create mode 100644 tests/auto/qhelpcontentmodel/data/qmake-4.3.0.qch create mode 100644 tests/auto/qhelpcontentmodel/data/test.qch create mode 100644 tests/auto/qhelpcontentmodel/qhelpcontentmodel.pro create mode 100644 tests/auto/qhelpcontentmodel/tst_qhelpcontentmodel.cpp create mode 100644 tests/auto/qhelpenginecore/.gitignore create mode 100644 tests/auto/qhelpenginecore/data/collection.qhc create mode 100644 tests/auto/qhelpenginecore/data/collection1.qhc create mode 100644 tests/auto/qhelpenginecore/data/linguist-3.3.8.qch create mode 100644 tests/auto/qhelpenginecore/data/qmake-3.3.8.qch create mode 100644 tests/auto/qhelpenginecore/data/qmake-4.3.0.qch create mode 100644 tests/auto/qhelpenginecore/data/test.html create mode 100644 tests/auto/qhelpenginecore/data/test.qch create mode 100644 tests/auto/qhelpenginecore/qhelpenginecore.pro create mode 100644 tests/auto/qhelpenginecore/tst_qhelpenginecore.cpp create mode 100644 tests/auto/qhelpgenerator/.gitignore create mode 100644 tests/auto/qhelpgenerator/data/cars.html create mode 100644 tests/auto/qhelpgenerator/data/classic.css create mode 100644 tests/auto/qhelpgenerator/data/fancy.html create mode 100644 tests/auto/qhelpgenerator/data/people.html create mode 100644 tests/auto/qhelpgenerator/data/sub/about.html create mode 100644 tests/auto/qhelpgenerator/data/test.html create mode 100644 tests/auto/qhelpgenerator/data/test.qhp create mode 100644 tests/auto/qhelpgenerator/qhelpgenerator.pro create mode 100644 tests/auto/qhelpgenerator/tst_qhelpgenerator.cpp create mode 100644 tests/auto/qhelpindexmodel/.gitignore create mode 100644 tests/auto/qhelpindexmodel/data/collection.qhc create mode 100644 tests/auto/qhelpindexmodel/data/collection1.qhc create mode 100644 tests/auto/qhelpindexmodel/data/linguist-3.3.8.qch create mode 100644 tests/auto/qhelpindexmodel/data/qmake-3.3.8.qch create mode 100644 tests/auto/qhelpindexmodel/data/qmake-4.3.0.qch create mode 100644 tests/auto/qhelpindexmodel/data/test.html create mode 100644 tests/auto/qhelpindexmodel/data/test.qch create mode 100644 tests/auto/qhelpindexmodel/qhelpindexmodel.pro create mode 100644 tests/auto/qhelpindexmodel/tst_qhelpindexmodel.cpp create mode 100644 tests/auto/qhelpprojectdata/.gitignore create mode 100644 tests/auto/qhelpprojectdata/data/test.qhp create mode 100644 tests/auto/qhelpprojectdata/qhelpprojectdata.pro create mode 100644 tests/auto/qhelpprojectdata/tst_qhelpprojectdata.cpp create mode 100644 tests/global/.gitignore create mode 100644 tests/tests.pro diff --git a/3rdparty/clucene/APACHE.license b/3rdparty/clucene/APACHE.license new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/3rdparty/clucene/APACHE.license @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/3rdparty/clucene/AUTHORS b/3rdparty/clucene/AUTHORS new file mode 100644 index 0000000..4a7904b --- /dev/null +++ b/3rdparty/clucene/AUTHORS @@ -0,0 +1,22 @@ +As with most development projects, contributions come from many people and in +many forms. The CLucene project would like to thank it's many contributors. +Omissions are merely accidental, please e-mail ustramooner@users.sourceforge.net +if you have been left out or a contribution is not mentioned. + +CLucene was originally ported to C++ by Ben van Klinken (ustramooner@users.sourceforge.net) +from Doug Cutting's popular java search engine, Lucene (see http://lucene.apache.org). + +Here is a list of contributors. Please send me an email at ustramooner@users.sourceforge.net +if I have left you out. + +Doug Cutting cutting@users.sourceforge.net +John Wheeler j_wheeler@users.sourceforge.net +Robert G. Ristroph rgristroph@users.sourceforge.net +David Rushby woodsplitter@users.sourceforge.net +Jimmy Pritts jpritts@sdf.lonestar.org +Peter Edwards peter@dragonstaff.co.uk +Jorge Sabater Redondo jsabater@elderecho.com +Daniel Glassey danglassey@ntlworld.com +Peter Gladkikh batyi@mail.ru +Pedja amigo@max3d.com +Peter Hodges hodges.peter@gmail.com diff --git a/3rdparty/clucene/COPYING b/3rdparty/clucene/COPYING new file mode 100644 index 0000000..0e32bb4 --- /dev/null +++ b/3rdparty/clucene/COPYING @@ -0,0 +1,30 @@ +License + +The CLucene Core Library uses a dual license strategy for the source code. +These licenses are the GNU Lesser General Public License (LGPL) and the Apache +License (Version 2.0). Users can choose the license they wish to distribute +their software under. This means that you do not need to abide by *both* +licenses, but rather than you can choose the license which most suits your +needs. + +To rephrase this and to make it perfectly clear: +CLucene is distributed under the GNU Lesser General Public License (LGPL) + *or* +the Apache License, Version 2.0 + +However, we are an open source project, and we encourage users to use the LGPL +license and participate fully in the free software community. Dual licensing +of the CLucene source code provides open and free access to the technology both +for the GPL community and for other developers or companies that cannot use the +GPL. + +You can freely modify, extend, and improve the CLucene source code. The only +question is whether or not you must provide the source code and contribute +modifications to the community. The GNU and Apache licenses allow different +ranges of flexibility in this regard, but in the end, regardless of the license +used, we highly recommend that you submit any bugs, incompatibilities or +added features. + +Note that this same license does *not* apply to the CLucene Contributions +package. You should read the COPYING file in that directory or package for +more information. \ No newline at end of file diff --git a/3rdparty/clucene/ChangeLog b/3rdparty/clucene/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/3rdparty/clucene/LGPL.license b/3rdparty/clucene/LGPL.license new file mode 100644 index 0000000..422c760 --- /dev/null +++ b/3rdparty/clucene/LGPL.license @@ -0,0 +1,475 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + +------------------------------------------------------------------------------- + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + +------------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + +------------------------------------------------------------------------------- + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + +------------------------------------------------------------------------------- + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + +------------------------------------------------------------------------------- + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + +------------------------------------------------------------------------------- + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + +------------------------------------------------------------------------------- + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + diff --git a/3rdparty/clucene/README b/3rdparty/clucene/README new file mode 100644 index 0000000..ee4f493 --- /dev/null +++ b/3rdparty/clucene/README @@ -0,0 +1,92 @@ +CLucene README +============== + +------------------------------------------------------ +CLucene is a C++ port of Lucene. +It is a high-performance, full-featured text search +engine written in C++. CLucene is faster than lucene +as it is written in C++. +------------------------------------------------------ + +CLucene has contributions from many, see AUTHORS + +CLucene is distributed under the GNU Lesser General Public License (LGPL) + *or* +the Apache License, Version 2.0 +See the LGPL.license and APACHE.license for the respective license information. +Read COPYING for more about the license. + +Installation +------------ +* For Linux, MacOSX, cygwin and MinGW build information, read INSTALL. +* Boost.Jam files are provided in the root directory and subdirectories. +* Microsoft Visual Studio (6&7) are provided in the win32 folder. + +Mailing List +------------ +Questions and discussion should be directed to the CLucene mailing list + at clucene-developers@lists.sourceforge.net +Find subscription instructions at + http://lists.sourceforge.net/lists/listinfo/clucene-developers +Suggestions and bug reports can be made on our bug tracking database + (http://sourceforge.net/tracker/?group_id=80013&atid=558446) + +The latest version +------------------ +Details of the latest version can be found on the CLucene sourceforge project +web site: http://www.sourceforge.net/projects/clucene + +Documentation +------------- +Documentation is provided at http://clucene.sourceforge.net/doc/doxygen/html/ +You can also build your own documentation by running doxygen from the root directory +of clucene. +CLucene is a very close port of Java Lucene, so you can also try looking at the +Java Docs on http://lucene.apache.org/java/ + + +Performance +----------- +Very little benchmarking has been done on clucene. Andi Vajda posted some +limited statistics on the clucene list a while ago with the following results. + +There are 250 HTML files under $JAVA_HOME/docs/api/java/util for about +6108kb of HTML text. +org.apache.lucene.demo.IndexFiles with java and gcj: +on mac os x 10.3.1 (panther) powerbook g4 1ghz 1gb: + . running with java 1.4.1_01-99 : 20379 ms + . running with gcj 3.3.2 -O2 : 17842 ms + . running clucene 0.8.9's demo : 9930 ms + +I recently did some more tests and came up with these rough tests: +663mb (797 files) of Guttenberg texts +on a Pentium 4 running Windows XP with 1 GB of RAM. Indexing max 100,000 fields +• Jlucene: 646453ms. peak mem usage ~72mb, avg ~14mb ram +• Clucene: 232141. peak mem usage ~60, avg ~4mb ram + +Searching indexing using 10,000 single word queries +• Jlucene: ~60078ms and used ~13mb ram +• Clucene: ~48359ms and used ~4.2mb ram + +Platform notes +-------------- + +'Too many open files' +Some platforms don't provide enough file handles to run CLucene properly. +To solve this, increase the open file limit: + +On Solaris: +ulimit -n 1024 +set rlim_fd_cur=1024 + +Acknowledgments +---------------- + +The Apache Lucene project is the basis for this software, so the biggest +acknoledgment goes to that project. + +We wish to acknowledge the following copyrighted works that +make up portions of the CLucene software: + +CLucene relies heavily on the use of autoconf and libtool to provide +a build environment. diff --git a/3rdparty/clucene/src/CLucene.h b/3rdparty/clucene/src/CLucene.h new file mode 100644 index 0000000..1eac800 --- /dev/null +++ b/3rdparty/clucene/src/CLucene.h @@ -0,0 +1,38 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +//Includes some standard headers for searching and indexing. +#ifndef _lucene_CLucene_ +#define _lucene_CLucene_ + +#include "CLucene/StdHeader.h" +#include "CLucene/debug/condition.h" +#include "CLucene/debug/mem.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/IndexWriter.h" +#include "CLucene/index/MultiReader.h" +#include "CLucene/index/Term.h" +#include "CLucene/search/IndexSearcher.h" +#include "CLucene/search/MultiSearcher.h" +#include "CLucene/search/DateFilter.h" +#include "CLucene/search/WildcardQuery.h" +#include "CLucene/search/FuzzyQuery.h" +#include "CLucene/search/PhraseQuery.h" +#include "CLucene/search/PrefixQuery.h" +#include "CLucene/search/RangeQuery.h" +#include "CLucene/search/BooleanQuery.h" +#include "CLucene/document/Document.h" +#include "CLucene/document/Field.h" +#include "CLucene/document/DateField.h" +#include "CLucene/store/Directory.h" +#include "CLucene/store/FSDirectory.h" +#include "CLucene/queryParser/QueryParser.h" +#include "CLucene/queryParser/MultiFieldQueryParser.h" +#include "CLucene/analysis/standard/StandardAnalyzer.h" +#include "CLucene/analysis/Analyzers.h" +#include "CLucene/util/Reader.h" + +#endif diff --git a/3rdparty/clucene/src/CLucene/CLBackwards.h b/3rdparty/clucene/src/CLucene/CLBackwards.h new file mode 100644 index 0000000..ffaf428 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/CLBackwards.h @@ -0,0 +1,87 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _clucene_backwards_h +#define _clucene_backwards_h + +//In light of the recent major changes to clucene, +//this file should help to maintain some backwards compatibility +//include it after including StdHeader.h +// +//Note: I haven't tested this much, so please send me your changes + +//dirent is one of the most major changes that won't easily port. +//you can use the TCHAR copying macros, STRCPY_TtoA and STRCPY_AtoT +//to copy between different character types. + +//If you use stringPrintF, you will need to add the target string +//size parameter, because it is using _sntprintf... Change this if you +//want, but _sntprintf is much safer + +#define char_t TCHAR +#define uchar_t TCHAR +#define l_byte_t byte_t + +//#define stringSpn _tcsspn //not used in clucene anymore +#define stringCSpn _tcscspn +#define stringLength _tcslen +//#define stringToInteger _ttoi //not used in clucene anymore, use integer w/ base +#define stringFind _tcsstr +#define stringFindChar _tcschr +#define stringCompare _tcscmp +#define stringNCopy _tcsncpy +#define stringCopy _tcscpy +#define stringCat _tcscat +//#define stringToken _tcstok //not used in clucene anymore +#define stringPrintF _sntprintf //you will have errors, because now we used printf w/ bufferlen count +#define printFormatted _tprintf + +//conversion functions +#define integerToString _i64tot +#define stringToIntegerBase _tcstoi64 +#define stringToFloat _tcstod + +//file find structures +#define Cmd_Stat fileStat +#define Struct_Stat fileStat +#define stringICompare _tcsicmp +#define stringNCompare _tcsncmp +#define stringDifference _tcscmp + +//character conversion functions +#define isSpace _istspace +#define isDigit _istwdigit +#define isAlNum _istwalnum +#define toLower _totlower +#define stringUpper _tcsupr +//#define stringLower _tcslwr //not used in clucene anymore + +#define _THROWX(y) _THROWT(y) +#define _THROWC(y) _THROWA(y) + +//file naming stuff - remember we have changed all names to file naming lower case +#define fileRename _rename +#define fileFullName(abs,rel) _realpath(rel,abs) +#define makeDirectory _tmkdir +#define unlinkFile _unlink + +//no longer supported definitions +#ifdef _UNICODE + #define TO_CHAR_T STRDUP_AtoT + #define _cout wcout + #define _cin wcin + #define _cerr wcerr +#else + #define TO_CHAR_T STRDUP_WtoT + #define _cout cout + #define _cin cin + #define _cerr cerr +#endif + +//some headers that used to be automatically included: +#include "CLucene/util/dirent.h" //if we have dirent, then the native one will be used + +#endif diff --git a/3rdparty/clucene/src/CLucene/CLConfig.h b/3rdparty/clucene/src/CLucene/CLConfig.h new file mode 100644 index 0000000..c63c083 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/CLConfig.h @@ -0,0 +1,304 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_Config_ +#define _lucene_Config_ + + +//////////////////////////////////////////////////////////////////// +// this settings should be set up in the compiler, +// but are put here for reference as to what could be defined +//////////////////////////////////////////////////////////////////// +// +//define this if you want debugging code to be enabled +//#define _DEBUG +// +//define this if you want condition debugging to be enabled +#if defined(_DEBUG) && !defined(_CL__CND_DEBUG) + #define _CL__CND_DEBUG +#endif +// +//define this to print out lots of information about merges, etc +//requires __CL__CND_DEBUG to be defined +//#define _CL_DEBUG_INFO stdout +// +//to disable namespaces define this +//#define DISABLE_NAMESPACE +// +//This is mostly for windows. If you have put the google sparse +//map code in your include path somewhere, then define this +//to use it. +//However, for msvc, there are no significant gains since there +//is already a compatible hashmap available. +//#define _CL_HAVE_GOOGLE_DENSE_HASH_MAP +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// These options can be set depending on the particular needs of +// Your application +//////////////////////////////////////////////////////////////////// +// +//define this to force the build into ascii mode +//#define _ASCII +// +//define this to force the build into ucs2 mode +//#define _UCS2 +// +//if a wide character is being converted to a ascii character and it +//cannot fit, this character is used instead. Required. +#define LUCENE_OOR_CHAR(c) ((char)(((unsigned short)c)&0xFF)) +// +//define if you would like to force clucene to use the internal +//character functions. +//Tests may display unpredictable behaviour if this is not defined. +#define LUCENE_USE_INTERNAL_CHAR_FUNCTIONS +// +//define this to enable mmap support in the fsdirectory IndexInput +//todo: only available for windows so far...need to add MMapInput.cpp to project +//EXPERIMENTAL +//#define LUCENE_FS_MMAP +// +//LOCK_DIR implementation: +//define this to set an exact directory for the lock dir (not recommended) +//all other methods of getting the temporary directory will be ignored +//#define LUCENE_LOCK_DIR "/tmp" +// +//define this to try and load the lock dir from this specified environment variable +#define LUCENE_LOCK_DIR_ENV_1 "TEMP" +//define this if you want to have look up this environment variable if the first one fails +#define LUCENE_LOCK_DIR_ENV_2 "TMP" +//define this if you want to have a fallback directory, if not defined then +//the lockdirectory will be the index directory +#define LUCENE_LOCK_DIR_ENV_FALLBACK "/tmp" +// +//////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////// +// The following are search query options +// THe NO_* options can make CLucene faster and/or smaller +// special queries sometime require longer search times or may +// not be required +//////////////////////////////////////////////////////////////////// +// +//Define this to remove fuzzy query and sloppy scoring +//#define NO_FUZZY_QUERY +// +//Define to remove wildcard t*m or te?m to match term +//#define NO_WILDCARD_QUERY +// +//Define to remove prefix term query - ter* to match term or terms +//#define NO_PREFIX_QUERY +// +//Define to remove range (exlusive and inclusive) +//#define NO_RANGE_QUERY +// +//This must always be defined. They can be adjusted if required. But +//general Wildcard string would be '*' and Wildcard Char would be '?' +//Both are Required. +#define LUCENE_WILDCARDTERMENUM_WILDCARD_STRING '*' +#define LUCENE_WILDCARDTERMENUM_WILDCARD_CHAR '?' +// +//////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// memory handling configurations +//////////////////////////////////////////////////////////////////// +// +//If this is defined, lucene's configurations are changed +//to use less memory, but may run slower. +//todo: i dont think this actualy changes speed much, just memory +#define LUCENE_OPTIMIZE_FOR_MEMORY +// +//define this if you want the pointer tracking to be enabled +//this is a useful tool for memory leak tracking +//The LuceneBase can slow down the code a *lot* +#if defined(_DEBUG) + #if !defined(LUCENE_DISABLE_MEMTRACKING) && !defined(LUCENE_ENABLE_MEMLEAKTRACKING) + #define LUCENE_ENABLE_MEMLEAKTRACKING + #endif +#endif +// +//enable use of rich file/line tracking. use CL_FILELINE to pass +//to functions like stringDuplicate (or use CL_STRDUP* functions instead) and +//CLStringIntern::x. +#if defined(LUCENE_ENABLE_MEMLEAKTRACKING) + #define LUCENE_ENABLE_FILELINEINFO +#endif +// +//enable creation of clucene.log file. Logs every +//call to new operator. Must have LUCENE_ENABLE_MEMLEAKTRACKING enabled. +//writes log in this format. +//action,file name,file line,allocation size +//logging can be disabled by setting _lucene_disable_debuglogging to true +#if defined(LUCENE_ENABLE_MEMLEAKTRACKING) && defined(_DEBUG) +//#define LUCENE_ENABLE_CONSTRUCTOR_LOG +#endif +// +// +//enable this if you want to enable reference counting. This is +//not necessary or useful in most cases except when implementing wrappers +//which have reference counting. If the wrapper wraps a StringReader, +//for example, it should expect that the wrapped StringReader should not +//be deleted. However, when the stringreader is added into a Field, +//the Field usually takes over the stringReader and deletes it on completion. +//If reference counting is enabled, the wrapper can add a reference to any class +//and when _CLDECDELETE is called, the reference is decremented and only deleted +//if the refcount is zero. +#define LUCENE_ENABLE_REFCOUNT + + +//////////////////////////////////////////////////////////////////// +// These options allow you to remove certain implementations +// out of clucene so that they can be implemented in the client +// application +//////////////////////////////////////////////////////////////////// +// +//define this to your own setting if you would like to implement your own +//threading locking code. it should have the same sort of functions as +//mutex_default. If not defined, clucene will try and use posix,win32 critical +//sections, or a timer based mutex hack. +//#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_default +// +//define this if you want to implement the _Cnd_OutDebug routine yourself +//you can then easily customise in your own application how to handle debug messages +//#define _CND_DEBUG_DONTIMPLEMENT_OUTDEBUG +// +//define this if you want to implement your own namespace macros +//#define _LUCENE_DONTIMPLEMENT_NS_MACROS +// +//define this if you do not want clucene to include any standard libraries. +//this could be useful if you want to use alternate libraries +//#define LUCENE_DISABLE_INCLUDES +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// These options will be changed depending on your compiler/platform +// but can also be changed here if required +//////////////////////////////////////////////////////////////////// +// +//define this if multi-threading support is not required +//if not defined, multi-thread locking will +//occur (and its related processing overhead) +//note: it is recommended to disable multithreading if you do not need it +//there is a lot of overhead that can be avoided. +//#define _CL_DISABLE_MULTITHREADING +// +//if you want to define your own default file encoding. specify it +//here - normally defined in the platform specific headers +//#define PLATFORM_DEFAULT_READER_ENCODING CL_NS(util)::FileReader::ENCODING_ASCII +// +//disable hash implementations (if available) +//#define LUCENE_DISABLE_HASHING +//////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////// +// These options should not be changed. But you can experiment with +// them to optimize performance +//////////////////////////////////////////////////////////////////// +// +//some defaults, wouldn't usually need to be changed +//Buffer size for input/output streams. Required. +#define LUCENE_STREAM_BUFFER_SIZE 1024 +// +// DSR:2004.08.19: +// Formerly, StringBuffer used 1024 as the default size of its internal buffer. +// However, StringBuffer is used primarily for token- and term-oriented +// processing, e.g. in StandardTokenizer. I've calculated that the average +// token (as produced by StandardTokenizer) in all .txt files distributed in +// the Project Gutenberg CD Image (August 2003 release) has only 6 characters. +// Although most languages are likely to have a longer average word length than +// English due to the popularity of "non-atomized" conjugation and declension +// mechanisms, 1024 is still vastly excessive. +// I made two changes intended to deliver better overall performance: +// a) Switched to a default StringBuffer character capacity of 32. Though 32 +// is longer than the average token, the high cost of realloc makes a +// slightly liberal default size optimal. I chose the default size of 32 +// after fairly extensive experimentation on the Gutenberg e-texts. The +// results are summarized in the following table: +// ------------------------------------------------------------------------ +// LUCENE_DEFAULT_TOKEN_BUFFER_SIZE value | % faster than default size 1024 +// ------------------------------------------------------------------------ +// 8 : 4% +// 16 : 7% +// 32 : 6% +// 64 : 3% +// A default size of 32 is actually slightly slower than 16, but I was +// experimenting on English text; I expect that 32 will maintain decent +// performance in languages such as German, and in technical documents +// with long tokens. +// +// b) To offset the switch to a smaller default buffer size, I implemented a +// more aggressive growth strategy. A StringBuffer now [at least] doubles +// the size of its internal buffer every time it needs to grow, rather +// than [at least] increasing by LUCENE_DEFAULT_TOKEN_BUFFER_SIZE no +// matter how many times it has already grown. +//Required. +#define LUCENE_DEFAULT_TOKEN_BUFFER_SIZE 32 +//todo: should implement a similar strategy in analysis/token +// +//Expert: The fraction of {@link TermDocs} entries stored in skip tables, +//used to accellerate {@link TermDocs#skipTo(int)}. Larger values result in +//smaller indices, greater acceleration, but fewer accelerable cases, while +//smaller values result in bigger indices, less acceleration and more +//accelerable cases. More detailed experiments would be useful here. */ +#define LUCENE_DEFAULT_TERMDOCS_SKIP_INTERVAL 16 +// +//Size of TermScore cache. Required. +#define LUCENE_SCORE_CACHE_SIZE 32 +// +//analysis options +//maximum length that the CharTokenizer uses. Required. +//By adjusting this value, you can greatly improve the performance of searching +//and especially indexing. Default is 255, but smaller numbers will decrease +//the amount of memory used as well as increasing the speed. +#define LUCENE_MAX_WORD_LEN 255 +//Maximum length of a token word. +//Should be the same or more than LUCENE_MAX_WORD_LEN +//if not defined, then no token limit, but may be slower +//if defined will be faster (up to 15% in some cases), but will use more memory +#ifndef LUCENE_OPTIMIZE_FOR_MEMORY + #define LUCENE_TOKEN_WORD_LENGTH LUCENE_MAX_WORD_LEN +#endif +// +//maximum field length. some optimisation can be done if a maximum field +//length is given... The smaller the better +#define LUCENE_MAX_FIELD_LEN 100 +// +//The initial value set to BooleanQuery::maxClauseCount. Default is 1024 +#define LUCENE_BOOLEANQUERY_MAXCLAUSECOUNT 1024 +// +//bvk: 12.3.2005 +//============================================================================== +//Previously the way the tokenizer has worked has been changed to optionally +//use a a fixed word length. I have implemented this in the Term class as well. +//It seems that by predefining the text length instead of using new TCHAR[x] +//in the constructor greatly improves the performance by 20-30% for certain +//operations. +//Maximum length of a term text. +//Should be the same or more than LUCENE_MAX_WORD_LEN +//if not defined, then no term text limit, but may be slower +//if defined will be faster (up to 30% in some cases), but will use more memory +#ifndef LUCENE_OPTIMIZE_FOR_MEMORY + #define LUCENE_TERM_TEXT_LENGTH LUCENE_MAX_WORD_LEN +#endif +// +//Size of the CharTokenizer buffersize. Required. +#define LUCENE_IO_BUFFER_SIZE 1024 +// +//the minimum amount the segment term enum should grow by. Must be at least 1 +#define LUCENE_SEGMENTTERMENUM_GROWSIZE 8 +// +//////////////////////////////////////////////////////////////////// + +#endif + diff --git a/3rdparty/clucene/src/CLucene/CLMonolithic.cpp b/3rdparty/clucene/src/CLucene/CLMonolithic.cpp new file mode 100644 index 0000000..e3c2798 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/CLMonolithic.cpp @@ -0,0 +1,115 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +/* +* this is a monolithic file that can be used to compile clucene using one source file. +* it simplifies some build processes by avoiding static & dynamic compalation pitfalls. +* +* note: when creating a project add either this file, or all the other .cpp files, not both! +*/ +#include "CLucene/StdHeader.cpp" +#include "CLucene/analysis/Analyzers.cpp" +#include "CLucene/analysis/AnalysisHeader.cpp" +#include "CLucene/analysis/standard/StandardAnalyzer.cpp" +#include "CLucene/analysis/standard/StandardFilter.cpp" +#include "CLucene/analysis/standard/StandardTokenizer.cpp" +#include "CLucene/config/gunichartables.cpp" +#include "CLucene/config/repl_tcscasecmp.cpp" +#include "CLucene/config/repl_tcslwr.cpp" +#include "CLucene/config/repl_tcstod.cpp" +#include "CLucene/config/repl_lltot.cpp" +#include "CLucene/config/repl_tcstoll.cpp" +#include "CLucene/config/repl_tprintf.cpp" +#include "CLucene/config/threads.cpp" +#include "CLucene/config/utf8.cpp" +#include "CLucene/debug/condition.cpp" +#include "CLucene/debug/error.cpp" +#include "CLucene/debug/memtracking.cpp" +#include "CLucene/document/DateField.cpp" +#include "CLucene/document/Document.cpp" +#include "CLucene/document/Field.cpp" +#include "CLucene/index/CompoundFile.cpp" +#include "CLucene/index/DocumentWriter.cpp" +#include "CLucene/index/FieldInfos.cpp" +#include "CLucene/index/FieldsReader.cpp" +#include "CLucene/index/FieldsWriter.cpp" +#include "CLucene/index/IndexWriter.cpp" +#include "CLucene/index/IndexReader.cpp" +#include "CLucene/index/MultiReader.cpp" +#include "CLucene/index/SegmentInfos.cpp" +#include "CLucene/index/SegmentMergeInfo.cpp" +#include "CLucene/index/SegmentMergeQueue.cpp" +#include "CLucene/index/SegmentMerger.cpp" +#include "CLucene/index/SegmentReader.cpp" +#include "CLucene/index/SegmentTermDocs.cpp" +#include "CLucene/index/SegmentTermEnum.cpp" +#include "CLucene/index/SegmentTermPositions.cpp" +#include "CLucene/index/SegmentTermVector.cpp" +#include "CLucene/index/Term.cpp" +#include "CLucene/index/TermInfo.cpp" +#include "CLucene/index/TermInfosReader.cpp" +#include "CLucene/index/TermInfosWriter.cpp" +#include "CLucene/index/TermVectorReader.cpp" +#include "CLucene/index/TermVectorWriter.cpp" +#include "CLucene/queryParser/Lexer.cpp" +#include "CLucene/queryParser/MultiFieldQueryParser.cpp" +#include "CLucene/queryParser/QueryParser.cpp" +#include "CLucene/queryParser/QueryParserBase.cpp" +#include "CLucene/queryParser/QueryToken.cpp" +#include "CLucene/queryParser/TokenList.cpp" +#include "CLucene/search/BooleanQuery.cpp" +#include "CLucene/search/BooleanScorer.cpp" +#include "CLucene/search/CachingWrapperFilter.cpp" +#include "CLucene/search/ChainedFilter.cpp" +#include "CLucene/search/DateFilter.cpp" +#include "CLucene/search/ConjunctionScorer.cpp" +#include "CLucene/search/ExactPhraseScorer.cpp" +#include "CLucene/search/Explanation.cpp" +#include "CLucene/search/FieldCache.cpp" +#include "CLucene/search/FieldCacheImpl.cpp" +#include "CLucene/search/FieldDocSortedHitQueue.cpp" +#include "CLucene/search/FieldSortedHitQueue.cpp" +#include "CLucene/search/FilteredTermEnum.cpp" +#include "CLucene/search/FuzzyQuery.cpp" +#include "CLucene/search/Hits.cpp" +#include "CLucene/search/HitQueue.cpp" +#include "CLucene/search/IndexSearcher.cpp" +#include "CLucene/search/MultiSearcher.cpp" +#include "CLucene/search/MultiTermQuery.cpp" +#include "CLucene/search/PhrasePositions.cpp" +#include "CLucene/search/PhraseQuery.cpp" +#include "CLucene/search/PhraseScorer.cpp" +#include "CLucene/search/PrefixQuery.cpp" +#include "CLucene/search/QueryFilter.cpp" +#include "CLucene/search/RangeQuery.cpp" +#include "CLucene/search/RangeFilter.cpp" +#include "CLucene/search/SearchHeader.cpp" +#include "CLucene/search/Similarity.cpp" +#include "CLucene/search/SloppyPhraseScorer.cpp" +#include "CLucene/search/Sort.cpp" +#include "CLucene/search/TermQuery.cpp" +#include "CLucene/search/TermScorer.cpp" +#include "CLucene/search/WildcardQuery.cpp" +#include "CLucene/search/WildcardTermEnum.cpp" +#include "CLucene/store/FSDirectory.cpp" +#include "CLucene/store/IndexInput.cpp" +#include "CLucene/store/Lock.cpp" +#include "CLucene/store/MMapInput.cpp" +#include "CLucene/store/IndexOutput.cpp" +#include "CLucene/store/RAMDirectory.cpp" +#include "CLucene/store/TransactionalRAMDirectory.cpp" +#include "CLucene/util/BitSet.cpp" +#include "CLucene/util/Equators.cpp" +#include "CLucene/util/FastCharStream.cpp" +#include "CLucene/util/fileinputstream.cpp" +#include "CLucene/util/Misc.cpp" +#include "CLucene/util/Reader.cpp" +#include "CLucene/util/StringBuffer.cpp" +#include "CLucene/util/StringIntern.cpp" +#include "CLucene/util/dirent.cpp" +#include "CLucene/util/ThreadLocal.cpp" diff --git a/3rdparty/clucene/src/CLucene/LuceneThreads.h b/3rdparty/clucene/src/CLucene/LuceneThreads.h new file mode 100644 index 0000000..cad0786 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/LuceneThreads.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _LuceneThreads_h +#define _LuceneThreads_h +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#if defined(_CL_DISABLE_MULTITHREADING) + #define SCOPED_LOCK_MUTEX(theMutex) + #define DEFINE_MUTEX(x) + #define STATIC_DEFINE_MUTEX(x) + #define _LUCENE_SLEEP(x) + #define _LUCENE_CURRTHREADID 1 + #define _LUCENE_THREADID_TYPE char + + CL_NS_DEF(util) + class CLuceneThreadIdCompare + { + public: + enum + { // parameters for hash table + bucket_size = 4, // 0 < bucket_size + min_buckets = 8 + }; // min_buckets = 2 ^^ N, 0 < N + + bool operator()( char t1, char t2 ) const{ + return t1 < t2; + } + }; + CL_NS_END +#else + + #if defined(_LUCENE_DONTIMPLEMENT_THREADMUTEX) + //do nothing + #elif defined(_CL_HAVE_PTHREAD) + #include "CLucene/config/threadPthread.h" + #elif defined(_CL_HAVE_WIN32_THREADS) || defined(_CLCOMPILER_MSVC) || defined(__MINGW32__) //note that mingw32 could have pthreads, so put this after. + #if !defined(_CL_HAVE_WIN32_THREADS) + #define _CL_HAVE_WIN32_THREADS + #endif + #include "CLucene/config/threadCSection.h" + #else + #error A valid thread library was not found + #endif //mutex types + + CL_NS_DEF(util) + /** @internal */ + class mutexGuard + { + private: + _LUCENE_THREADMUTEX* mrMutex; + mutexGuard(const mutexGuard& clone); + public: + mutexGuard( _LUCENE_THREADMUTEX& rMutex ); + ~mutexGuard(); + }; + CL_NS_END + + #define SCOPED_LOCK_MUTEX(theMutex) CL_NS(util)::mutexGuard theMutexGuard(theMutex); + #define DEFINE_MUTEX(theMutex) _LUCENE_THREADMUTEX theMutex; + #define STATIC_DEFINE_MUTEX(theMutex) static _LUCENE_THREADMUTEX theMutex; + +#endif //_CL_DISABLE_MULTITHREADING + + + +#endif diff --git a/3rdparty/clucene/src/CLucene/StdHeader.cpp b/3rdparty/clucene/src/CLucene/StdHeader.cpp new file mode 100644 index 0000000..d64c51f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/StdHeader.cpp @@ -0,0 +1,134 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CLucene/util/Misc.h" + +#include "CLucene/search/Sort.h" +#include "CLucene/search/Similarity.h" +#include "CLucene/search/FieldCache.h" +#include "CLucene/search/FieldSortedHitQueue.h" + +#if defined(_CLCOMPILER_MSVC) && defined(_DEBUG) +# define CRTDBG_MAP_ALLOC +# include +#ifndef UNDER_CE +# include +#endif +#endif + +CL_NS_USE(util) + +TCHAR* _LUCENE_BLANK_STRING = _T(""); +char* _LUCENE_BLANK_ASTRING = ""; + +#ifndef Q_CC_MIPS +#if defined(_LUCENE_THREADMUTEX_USINGDEFAULT) +# if defined(_LUCENE_PRAGMA_WARNINGS) +# pragma message ("==================Using clunky thread mutex!!!==================") +# else +# if !defined(Q_OS_SOLARIS) +# warning "==================Using clunky thread mutex!!!==================" +# endif +# endif +#endif + +#if defined(_ASCII) +# if defined(_LUCENE_PRAGMA_WARNINGS) +# pragma message ("==================Using ascii mode!!!==================") +# else +# if !defined(Q_OS_SOLARIS) +# warning "==================Using ascii mode!!!==================" +# endif +# endif +#endif + +//This causes confusion, because CLucene doesn't really need hashed maps/sets. My experience with the +//hash maps on linux are that there are no significant improvements in using them (infact it adversely +//affected performance... therefore we'll just silently ignore +/*#if defined(LUCENE_DISABLE_HASHING) +# if defined(_LUCENE_PRAGMA_WARNINGS) +# pragma message ("==================Hashing not available or is disabled! CLucene may run slower than optimal ==================") +# else +# if !defined(Q_OS_SOLARIS) +# warning "==================Hashing not available or is disabled! CLucene may run slower than optimal ==================" +# endif +# endif +#endif*/ +#endif + +//clears all static memory. do not attempt to do anything else +//in clucene after calling this function +void _lucene_shutdown(){ + CL_NS(search)::FieldSortedHitQueue::Comparators.clear(); + _CLDELETE(CL_NS(search)::Sort::RELEVANCE); + _CLDELETE(CL_NS(search)::Sort::INDEXORDER); + _CLDELETE(CL_NS(search)::ScoreDocComparator::INDEXORDER); + _CLDELETE(CL_NS(search)::ScoreDocComparator::RELEVANCE); + _CLDELETE(CL_NS(search)::SortField::FIELD_SCORE); + _CLDELETE(CL_NS(search)::SortField::FIELD_DOC); + _CLDELETE(CL_NS(search)::FieldCache::DEFAULT); + + _CLLDELETE(CL_NS(search)::Similarity::getDefault()); + + CL_NS(util)::CLStringIntern::shutdown(); +} + +void CLDebugBreak(){ + //can be used for debug breaking... +#if defined(_CLCOMPILER_MSVC) && defined(_DEBUG) + _CrtDbgBreak(); +#else + int i=0; //a line to put breakpoint on +#endif +} + +//these are functions that lucene uses which +//are not replacement functions +char* lucenestrdup(const char* v CL_FILELINEPARAM){ + size_t len = strlen(v); + char* ret = new char[len+1]; + strncpy(ret,v,len+1); +#if defined(LUCENE_ENABLE_MEMLEAKTRACKING) +# if defined(LUCENE_ENABLE_FILELINEINFO) + CL_NS(debug)::LuceneBase::__cl_voidpadd((void*)ret,file,line,len); +# else + CL_NS(debug)::LuceneBase::__cl_voidpadd((void*)ret,__FILE__,__LINE__,len); +# endif +#endif + return ret; +} + +#ifdef _UCS2 +wchar_t* lucenewcsdup(const wchar_t* v CL_FILELINEPARAM){ + size_t len = _tcslen(v); + wchar_t* ret = new wchar_t[len+1]; + _tcsncpy(ret,v,len+1); +#if defined(LUCENE_ENABLE_MEMLEAKTRACKING) +# if defined(LUCENE_ENABLE_FILELINEINFO) + CL_NS(debug)::LuceneBase::__cl_voidpadd((void*)ret,file,line,len); +# else + CL_NS(debug)::LuceneBase::__cl_voidpadd((void*)ret,__FILE__,__LINE__,len); +# endif +#endif + return ret; +} +#endif //ucs2 + + +//ok, these are the exceptions, but these never +//exist on non-msvc platform, so lets put it here +#ifndef _CL_HAVE_FILELENGTH +int64_t lucene_filelength(int filehandle) +{ + struct fileStat info; + if (fileHandleStat(filehandle, &info) == -1) + _CLTHROWA( CL_ERR_IO,"fileStat error" ); + return info.st_size; +} +#endif diff --git a/3rdparty/clucene/src/CLucene/StdHeader.h b/3rdparty/clucene/src/CLucene/StdHeader.h new file mode 100644 index 0000000..fbb3fd9 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/StdHeader.h @@ -0,0 +1,501 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#ifndef lucene_stdheader_h +#define lucene_stdheader_h + +#if defined(OVERRIDE_DEFAULT_CLCONFIG) + #include "AltCLConfig.h" +#else + #include "CLucene/CLConfig.h" +#endif + +//first inclusion of compiler.h (it will be called again later) +#include "CLucene/config/compiler.h" + +extern void _lucene_shutdown(); +extern int _lucene_counter_break; //can set a watch on this +#if defined(LUCENE_ENABLE_MEMLEAKTRACKING) + extern bool _lucene_disable_debuglogging; //if LUCENE_ENABLE_CONSTRUCTOR_LOG is on, dont do log if this is true +#endif + +//////////////////////////////////////////////////////// +// default includes +//////////////////////////////////////////////////////// +#ifndef LUCENE_DISABLE_INCLUDES + +#include + +#if defined(_CL_STDC_HEADERS) + #include + #include +#else + #if defined(_CL_HAVE_STDLIB_H) + #include + #endif +#endif + +#if defined(_CL_HAVE_STRING_H) + #if !defined(_CL_STDC_HEADERS) && defined(_CL_HAVE_MEMORY_H) + #include + #endif + #include +#elif defined(_CL_HAVE_STRINGS_H) + //note: as a side note, strtok is not thread-safe.. so be careful where you use it! + #error "strtok replacement for BSD has not been implemented" + #include + #if !defined(_CL_HAVE_STRCHR) + #define strchr index + #define strrchr rindex + #endif +#endif + +#if defined(_CL_HAVE_UNISTD_H) + #include +#elif defined(_CL_HAVE_IO_H) && defined(_CL_HAVE_DIRECT_H) +#ifndef UNDER_CE + #include + #include +#endif +#else + #error "Neither unistd.h or (io.h & direct.h) were available" +#endif + +#ifndef _CL_DISABLE_NATIVE_EXCEPTIONS + #ifdef _CL_HAVE_STDEXCEPT + #include + #else + #error "CLucene can't compile with exception handling on because header is not available" + #endif +#endif + +#if defined(_CL_STAT_MACROS_BROKEN) + #error "Haven't implemented STAT_MACROS_BROKEN fix yet" +#elif defined(_CL_HAVE_SYS_STAT_H) +#ifdef UNDER_CE + #include +#else + #include +#endif +#else + #error "Haven't implemented platforms with no sys/stat.h" +#endif + +#if defined(_CL_HAVE_STDARG_H) + #include +#else + #error "CLucene can compile, but some extras may not work" +#endif + +#if defined(_CL_HAVE_MATH_H) + #include +#else + #error "CLucene can't compile without " +#endif + +#if defined(_CL_HAVE_MAP) + #include +#else + #error "CLucene can't compile without the map header" +#endif + +#if defined(_CL_HAVE_LIST) + #include +#else + #error "CLucene can't compile without the list header" +#endif + +#if defined(_CL_HAVE_SET) + #include +#else + #error "CLucene can't compile without the set header" +#endif + +#if defined(_CL_HAVE_VECTOR) + #include +#else + #error "CLucene can't compile without the vector header" +#endif + +#if !defined(LUCENE_DISABLE_HASHING) && defined(_CL_HAVE_HASH_MAP) && defined(_CL_HAVE_HASH_SET) + //hashing is all or nothing! + #include + #include +#elif !defined(LUCENE_DISABLE_HASHING) && defined(_CL_HAVE_EXT_HASH_MAP) && defined(_CL_HAVE_EXT_HASH_SET) + #include + #include +#elif !defined(LUCENE_DISABLE_HASHING) + #define LUCENE_DISABLE_HASHING +#endif +#if !defined(LUCENE_DISABLE_HASHING) && !defined(CL_NS_HASHING) + #define CL_NS_HASHING(func) std::func +#endif + +#if defined(_CL_HAVE_ALGORITHM) +# include +#else +# error "Can't compile clucene without " +#endif + +#if defined(_CL_HAVE_FUNCTIONAL) +# include +#else +# error "Can't compile clucene without " +#endif + +#if !defined(_CL_HAVE_PRINTF) + #error "CLucene can't compile without printf, replacements have not been implemented" +#endif + +#if !defined(_CL_HAVE_SNPRINTF) && !defined(_CL_HAVE__SNPRINTF) + #error "CLucene can't compile without snprintf, replacements have not been implemented" +#elif !defined(_CL_HAVE__SNPRINTF)&& defined(_CL_HAVE_SVNPRINTF) + #define _snprintf snprintf +#endif + +#if defined(_UCS2) + #if defined(_CL_HAVE_WCHAR_H) + #include + #else + //actually the repl_wchar.h replacements header will + //always be included. It replaces some functions + //that are missing in some wchar.h headers. + #endif +#endif + +#if defined(_UCS2) && defined(_CL_HAVE_WCTYPE_H) + #include +#elif defined(_ASCII) && defined(_CL_HAVE_CTYPE_H) + #include + #undef LUCENE_USE_INTERNAL_CHAR_FUNCTIONS +#elif defined(_UCS2) + //must be in _UCS2 to use internal char functions + #undef LUCENE_USE_INTERNAL_CHAR_FUNCTIONS + #define LUCENE_USE_INTERNAL_CHAR_FUNCTIONS +#else + #error "Cannot compile in _ASCII without ctype.h" +#endif + +//always include replacement, some missing tchar defines +#include "CLucene/config/repl_tchar.h" + +#if defined(_CL_HAVE_ERRNO_H) +#ifndef UNDER_CE + #include +#endif +#else + #error "Haven't implemented platforms with no errno.h" +#endif + +#if defined(_CL_HAVE_FCNTL_H) +#ifndef UNDER_CE + #include +#endif +#else + #error "Haven't implemented platforms with no fcntl.h" +#endif + +#if defined(_CL_HAVE_WINDOWS_H) + #include +#endif + +#endif //LUCENE_DISABLE_INCLUDES +// +//////////////////////////////////////////////////////// + +//second inclusion of compiler.h +//this gives CompilerXXX.h a chance to include other headers +#include "CLucene/config/compiler.h" +// +//////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////// +// Character functions. +// Here we decide whose character functions to use +//////////////////////////////////////////////////////// +#if defined(LUCENE_USE_INTERNAL_CHAR_FUNCTIONS) + #define stringCaseFold cl_tcscasefold + #define stringCaseFoldCmp cl_tcscasefoldcmp + + #undef _istspace + #undef _istdigit + #undef _istalnum + #undef _istalpha + #undef _totlower + #undef _totupper + #define _istalnum cl_isalnum + #define _istalpha cl_isletter + #define _istspace cl_isspace + #define _istdigit cl_isdigit + #define _totlower cl_tolower + #define _totupper cl_toupper + + //here are some functions to help deal with utf8/ucs2 conversions + //lets let the user decide what mb functions to use... we provide pure utf8 ones no matter what. + /*#undef _mbtowc + #undef _mbstowcs + #undef _wctomb + #undef _wcstombs + #define _mbtowc lucene_mbstowc + #define _mbsstowcs lucene_mbstowcs + #define _wctomb lucene_wcto_mb + #define _wcstombs lucene_wcstombs*/ +#else + //we are using native functions + //here are some functions to help deal with utf8/ucs2 conversions + /*#define _mbtowc mbtowc + #define _wctomb wctomb + #define _mbstowcs mbstowcs + #define _wcstombs wcstombs*/ + + //we are using native character functions + #if defined(_ASCII) + #undef _istspace + #undef _istdigit + #undef _istalnum + #undef _istalpha + #undef _totlower + #undef _totupper + #define _istspace(x) isspace((unsigned char)x) + #define _istdigit(x) isdigit((unsigned char)x) + #define _istalnum(x) isalnum((unsigned char)x) + #define _istalpha(x) isalpha((unsigned char)x) + #define _totlower(x) tolower((unsigned char)x) + #define _totupper(x) toupper((unsigned char)x) + #endif +#endif + +//the methods contained in gunichartables.h +typedef unsigned long clunichar; +bool cl_isletter(clunichar c); +bool cl_isalnum(clunichar c); +bool cl_isdigit(clunichar c); +bool cl_isspace (clunichar c); +TCHAR cl_tolower (TCHAR c); +TCHAR cl_toupper (TCHAR c); + +int cl_tcscasefoldcmp(const TCHAR * dst, const TCHAR * src); +TCHAR* cl_tcscasefold( TCHAR * str, int len=-1 ); + +//we provide utf8 conversion functions +size_t lucene_utf8towc (wchar_t *ret, const char *s, size_t n); +size_t lucene_utf8towcs(wchar_t *, const char *, size_t maxslen); +size_t lucene_wctoutf8 (char * ret, const wchar_t str); +size_t lucene_wcstoutf8 (char *, const wchar_t *, size_t maxslen); +size_t lucene_utf8charlen(const char *p); + +///a blank string... +extern TCHAR* _LUCENE_BLANK_STRING; +#define LUCENE_BLANK_STRING _LUCENE_BLANK_STRING +extern char* _LUCENE_BLANK_ASTRING; +#define LUCENE_BLANK_ASTRING _LUCENE_BLANK_ASTRING + +/* Converts a string into a form that is independent of case. The + * result will not correspond to any particular case, but can be + * compared for equality or ordered with the results of calling + * stringCaseFold() on other strings. + * + * If we did not define this elsewhere, then just convert to lower case + */ +#ifndef stringCaseFold + #define stringCaseFold _tcslwr +#endif +/* Compares 2 strings using case folding (if available) + * If we did not define this elsewhere, then just compare + * using normal method + */ +#ifndef stringCaseFoldCmp + #define stringCaseFoldCmp _tcsicmp +#endif + +//now that all the character routines are completed, include the +//wchar.h replacements. +#include "CLucene/config/repl_wchar.h" //always include replacements + +//a replacement for _tcsdup. This uses new TCHAR[] instead of malloc, so that we can use delete[] to free +#if defined(LUCENE_ENABLE_FILELINEINFO) + #define CL_FILELINE ,__FILE__,__LINE__ + #define CL_FILELINEREF ,file,line /// StringArray; +typedef CL_NS(util)::CLVector StringArrayWithDeletor; +typedef CL_NS(util)::CLVector StringArrayConst; +typedef CL_NS(util)::CLVector StringArrayConstWithDeletor; + +typedef CL_NS(util)::CLVector AStringArray; +typedef CL_NS(util)::CLVector AStringArrayWithDeletor; +typedef CL_NS(util)::CLVector AStringArrayConst; +typedef CL_NS(util)::CLVector AStringArrayConstWithDeletor; +CL_NS_END + +// +//////////////////////////////////////////////////////// + +#endif // STDHEADER_H diff --git a/3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.cpp b/3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.cpp new file mode 100644 index 0000000..03f61a0 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.cpp @@ -0,0 +1,200 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "AnalysisHeader.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(util) +CL_NS_DEF(analysis) + +const TCHAR* Token::defaultType=_T("word"); + +Token::Token(): + _startOffset (0), + _endOffset (0), + _type ( defaultType ), + positionIncrement (1) +{ + _termTextLen = 0; +#ifndef LUCENE_TOKEN_WORD_LENGTH + _termText = NULL; + bufferTextLen = 0; +#else + _termText[0] = 0; //make sure null terminated + bufferTextLen = LUCENE_TOKEN_WORD_LENGTH+1; +#endif +} + +Token::~Token(){ +#ifndef LUCENE_TOKEN_WORD_LENGTH + free(_termText); +#endif +} + +Token::Token(const TCHAR* text, const int32_t start, const int32_t end, const TCHAR* typ): + _startOffset (start), + _endOffset (end), + _type ( typ ), + positionIncrement (1) +{ + _termTextLen = 0; +#ifndef LUCENE_TOKEN_WORD_LENGTH + _termText = NULL; + bufferTextLen = 0; +#else + _termText[0] = 0; //make sure null terminated + bufferTextLen = LUCENE_TOKEN_WORD_LENGTH+1; +#endif + setText(text); +} + +void Token::set(const TCHAR* text, const int32_t start, const int32_t end, const TCHAR* typ){ + _startOffset = start; + _endOffset = end; + _type = typ; + positionIncrement = 1; + setText(text); +} + +void Token::setText(const TCHAR* text){ + _termTextLen = _tcslen(text); + +#ifndef LUCENE_TOKEN_WORD_LENGTH + growBuffer(_termTextLen+1); + _tcsncpy(_termText,text,_termTextLen+1); +#else + if ( _termTextLen > LUCENE_TOKEN_WORD_LENGTH ){ + //in the case where this occurs, we will leave the endOffset as it is + //since the actual word still occupies that space. + _termTextLen=LUCENE_TOKEN_WORD_LENGTH; + } + _tcsncpy(_termText,text,_termTextLen+1); +#endif + _termText[_termTextLen] = 0; //make sure null terminated +} + +void Token::growBuffer(size_t size){ + if(bufferTextLen>=size) + return; +#ifndef LUCENE_TOKEN_WORD_LENGTH + if ( _termText == NULL ) + _termText = (TCHAR*)malloc( size * sizeof(TCHAR) ); + else + _termText = (TCHAR*)realloc( _termText, size * sizeof(TCHAR) ); + bufferTextLen = size; +#else + _CLTHROWA(CL_ERR_TokenMgr,"Couldn't grow Token buffer"); +#endif +} + +void Token::setPositionIncrement(int32_t posIncr) { + if (posIncr < 0) { + _CLTHROWA(CL_ERR_IllegalArgument,"positionIncrement must be >= 0"); + } + positionIncrement = posIncr; +} + +int32_t Token::getPositionIncrement() const { return positionIncrement; } + +// Returns the Token's term text. +const TCHAR* Token::termText() const{ + return (const TCHAR*) _termText; +} +size_t Token::termTextLength() { + if ( _termTextLen == -1 ) //it was invalidated by growBuffer + _termTextLen = _tcslen(_termText); + return _termTextLen; +} +void Token::resetTermTextLen(){ + _termTextLen=-1; +} +bool Token::OrderCompare::operator()( Token* t1, Token* t2 ) const{ + if(t1->startOffset()>t2->startOffset()) + return false; + if(t1->startOffset()startOffset()) + return true; + return true; +} +TCHAR* Token::toString() const{ + StringBuffer sb; + sb.append(_T("(")); + sb.append( _termText ); + sb.append(_T(",")); + sb.appendInt( _startOffset ); + sb.append(_T(",")); + sb.appendInt( _endOffset ); + + if (!_tcscmp( _type, _T("word")) == 0 ){ + sb.append(_T(",type=")); + sb.append(_type); + } + if (positionIncrement != 1){ + sb.append(_T(",posIncr=")); + sb.appendInt(positionIncrement); + } + sb.append(_T(")")); + + return sb.toString(); +} + + +Token* TokenStream::next(){ + Token* t = _CLNEW Token; //deprecated + if ( !next(t) ) + _CLDELETE(t); + return t; +} + + +TokenFilter::TokenFilter(TokenStream* in, bool deleteTS): + input(in), + deleteTokenStream(deleteTS) +{ +} +TokenFilter::~TokenFilter(){ + close(); +} + +// Close the input TokenStream. +void TokenFilter::close() { + if ( input != NULL ){ + input->close(); + if ( deleteTokenStream ) + _CLDELETE( input ); + } + input = NULL; +} + + + +Tokenizer::Tokenizer() { + input = NULL; +} + +Tokenizer::Tokenizer(CL_NS(util)::Reader* _input): + input(_input) +{ +} + +void Tokenizer::close(){ + if (input != NULL) { + // ? delete input; + input = NULL; + } +} + +Tokenizer::~Tokenizer(){ + close(); +} + + +int32_t Analyzer::getPositionIncrementGap(const TCHAR* fieldName) +{ + return 0; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.h b/3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.h new file mode 100644 index 0000000..0cfd9c6 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/AnalysisHeader.h @@ -0,0 +1,234 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_analysis_AnalysisHeader_ +#define _lucene_analysis_AnalysisHeader_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/Reader.h" + +CL_NS_DEF(analysis) + + +/** A Token is an occurence of a term from the text of a field. It consists of +* a term's text, the start and end offset of the term in the text of the field, +* and a type string. +* +* The start and end offsets permit applications to re-associate a token with +* its source text, e.g., to display highlighted query terms in a document +* browser, or to show matching text fragments in a KWIC (KeyWord In Context) +* display, etc. +* +* The type is an interned string, assigned by a lexical analyzer +* (a.k.a. tokenizer), naming the lexical or syntactic class that the token +* belongs to. For example an end of sentence marker token might be implemented +* with type "eos". The default token type is "word". +*/ +class Token:LUCENE_BASE{ +private: + int32_t _startOffset; // start in source text + int32_t _endOffset; // end in source text + const TCHAR* _type; // lexical type + int32_t positionIncrement; + size_t bufferTextLen; + +public: + #ifndef LUCENE_TOKEN_WORD_LENGTH + TCHAR* _termText; // the text of the term + #else + TCHAR _termText[LUCENE_TOKEN_WORD_LENGTH+1]; // the text of the term + #endif + int32_t _termTextLen; + static const TCHAR* defaultType; + + Token(); + ~Token(); + // Constructs a Token with the given text, start and end offsets, & type. + Token(const TCHAR* text, const int32_t start, const int32_t end, const TCHAR* typ=defaultType); + void set(const TCHAR* text, const int32_t start, const int32_t end, const TCHAR* typ=defaultType); + + size_t bufferLength(){ return bufferTextLen; } + void growBuffer(size_t size); + + /* Set the position increment. This determines the position of this + * token relative to the previous Token in a TokenStream, used in + * phrase searching. + * + * The default value is 1. + * + * Some common uses for this are: + * + * - Set it to zero to put multiple terms in the same position. This is + * useful if, e.g., a word has multiple stems. Searches for phrases + * including either stem will match. In this case, all but the first stem's + * increment should be set to zero: the increment of the first instance + * should be one. Repeating a token with an increment of zero can also be + * used to boost the scores of matches on that token. + * + * - Set it to values greater than one to inhibit exact phrase matches. + * If, for example, one does not want phrases to match across removed stop + * words, then one could build a stop word filter that removes stop words and + * also sets the increment to the number of stop words removed before each + * non-stop word. Then exact phrase queries will only match when the terms + * occur with no intervening stop words. + */ + void setPositionIncrement(int32_t posIncr); + int32_t getPositionIncrement() const; + const TCHAR* termText() const; + size_t termTextLength(); + void resetTermTextLen(); + void setText(const TCHAR* txt); + + /** + * Returns this Token's starting offset, the position of the first character + * corresponding to this token in the source text. + * + * Note that the difference between endOffset() and startOffset() may not be + * equal to termText.length(), as the term text may have been altered by a + * stemmer or some other filter. + */ + int32_t startOffset() const { return _startOffset; } + void setStartOffset(int32_t val){ _startOffset =val; } + + /** + * Returns this Token's ending offset, one greater than the position of the + * last character corresponding to this token in the source text. + */ + int32_t endOffset() const { return _endOffset; } + void setEndOffset(int32_t val){ _endOffset =val; } + + // Returns this Token's lexical type. Defaults to "word". + const TCHAR* type() const { return _type; } /// + { + public: + bool operator()( Token* t1, Token* t2 ) const; + }; +}; + +/** +* A TokenStream enumerates the sequence of tokens, either from +* fields of a document or from query text. +*

+* This is an abstract class. Concrete subclasses are: +*

    +*
  • {@link Tokenizer}, a TokenStream +* whose input is a Reader; and +*
  • {@link TokenFilter}, a TokenStream +* whose input is another TokenStream. +*
+*/ +class TokenStream:LUCENE_BASE { +public: + /** Sets token to the next token in the stream, returns false at the EOS. */ + virtual bool next(Token* token) = 0; + + /** Releases resources associated with this stream. */ + virtual void close() = 0; + + virtual ~TokenStream(){ + } + + /* This is for backwards compatibility only. You should pass the token you want to fill + * to next(), this will save a lot of object construction and destructions. + * @deprecated. use next(token). Kept only to avoid breaking existing code. + */ + _CL_DEPRECATED(next(Token)) Token* next(); +}; + + +/** An Analyzer builds TokenStreams, which analyze text. It thus represents a + * policy for extracting index terms from text. + *

+ * Typical implementations first build a Tokenizer, which breaks the stream of + * characters from the Reader into raw Tokens. One or more TokenFilters may + * then be applied to the output of the Tokenizer. + *

+ * WARNING: You must override one of the methods defined by this class in your + * subclass or the Analyzer will enter an infinite loop. + */ +class Analyzer:LUCENE_BASE{ +public: + /** Creates a TokenStream which tokenizes all the text in the provided + Reader. Default implementation forwards to tokenStream(Reader) for + compatibility with older version. Override to allow Analyzer to choose + strategy based on document and/or field. Must be able to handle null + field name for backward compatibility. */ + virtual TokenStream* tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader)=0; + + virtual ~Analyzer(){ + } + + /** + * Invoked before indexing a Field instance if + * terms have already been added to that field. This allows custom + * analyzers to place an automatic position increment gap between + * Field instances using the same field name. The default value + * position increment gap is 0. With a 0 position increment gap and + * the typical default token position increment of 1, all terms in a field, + * including across Field instances, are in successive positions, allowing + * exact PhraseQuery matches, for instance, across Field instance boundaries. + * + * @param fieldName Field name being indexed. + * @return position increment gap, added to the next token emitted from {@link #tokenStream(TCHAR*, Reader*)} + */ + virtual int32_t getPositionIncrementGap(const TCHAR* fieldName); +}; + + +/** A Tokenizer is a TokenStream whose input is a Reader. +

+This is an abstract class. +*/ +class Tokenizer:public TokenStream { +protected: + /** The text source for this Tokenizer. */ + CL_NS(util)::Reader* input; + +public: + /** Construct a tokenizer with null input. */ + Tokenizer(); + /** Construct a token stream processing the given input. */ + Tokenizer(CL_NS(util)::Reader* _input); + + // ** By default, closes the input Reader. */ + virtual void close(); + virtual ~Tokenizer(); +}; + +/** A TokenFilter is a TokenStream whose input is another token stream. +

+This is an abstract class. +*/ +class TokenFilter:public TokenStream { +protected: + /** The source of tokens for this filter. */ + TokenStream* input; + /** If true then input will be deleted in the destructor */ + bool deleteTokenStream; + + /** Construct a token stream filtering the given input. + * + * @param in The TokenStream to filter from + * @param deleteTS If true, input will be deleted in the destructor + */ + TokenFilter(TokenStream* in, bool deleteTS=false); + virtual ~TokenFilter(); +public: + /** Close the input TokenStream. */ + void close(); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/analysis/Analyzers.cpp b/3rdparty/clucene/src/CLucene/analysis/Analyzers.cpp new file mode 100644 index 0000000..142bbfb --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/Analyzers.cpp @@ -0,0 +1,389 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Analyzers.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(util) +CL_NS_DEF(analysis) + +CharTokenizer::CharTokenizer(Reader* in) : + Tokenizer(in), + offset(0), + bufferIndex(0), + dataLen(0), + ioBuffer(NULL) +{ + buffer[0]=0; +} + +TCHAR CharTokenizer::normalize(const TCHAR c) const +{ + return c; +} +bool CharTokenizer::next(Token* token){ + int32_t length = 0; + int32_t start = offset; + while (true) { + TCHAR c; + offset++; + if (bufferIndex >= dataLen) { + dataLen = input->read(ioBuffer, LUCENE_IO_BUFFER_SIZE); + if (dataLen == -1) + dataLen = 0; + bufferIndex = 0; + } + if (dataLen <= 0 ) { + if (length > 0) + break; + else + return false; + }else + c = ioBuffer[bufferIndex++]; + if (isTokenChar(c)) { // if it's a token TCHAR + + if (length == 0) // start of token + start = offset-1; + + buffer[length++] = normalize(c); // buffer it, normalized + + if (length == LUCENE_MAX_WORD_LEN) // buffer overflow! + break; + + } else if (length > 0) // at non-Letter w/ chars + break; // return 'em + + } + buffer[length]=0; + token->set( buffer, start, start+length); + return true; +} + +bool LetterTokenizer::isTokenChar(const TCHAR c) const { + return _istalpha(c)!=0; +} + + +TCHAR LowerCaseTokenizer::normalize(const TCHAR chr) const { + return _totlower(chr); +} + +bool WhitespaceTokenizer::isTokenChar(const TCHAR c) const{ + return _istspace(c)==0; //(return true if NOT a space) +} + +TokenStream* WhitespaceAnalyzer::tokenStream(const TCHAR* fieldName, Reader* reader) { + return _CLNEW WhitespaceTokenizer(reader); +} + +TokenStream* SimpleAnalyzer::tokenStream(const TCHAR* fieldName, Reader* reader) { + return _CLNEW LowerCaseTokenizer(reader); +} + +bool LowerCaseFilter::next(Token* t){ + if (!input->next(t)) + return false; + stringCaseFold( t->_termText ); + return true; +} + +StopFilter::StopFilter(TokenStream* in, bool deleteTokenStream, const TCHAR** stopWords): + TokenFilter(in, deleteTokenStream), + table(_CLNEW CLSetList(false)) +{ + fillStopTable( table,stopWords ); +} + +void StopFilter::fillStopTable(CLSetList* stopTable, + const TCHAR** stopWords) { + for (int32_t i = 0; stopWords[i]!=NULL; i++) + stopTable->insert(stopWords[i]); +} + +bool StopFilter::next(Token* token) { + // return the first non-stop word found + while (input->next(token)){ + if (table->find(token->_termText)==table->end()){ + return true; + } + } + + // reached EOS -- return nothing + return false; +} + +StopAnalyzer::StopAnalyzer():stopTable(false) +{ + StopFilter::fillStopTable(&stopTable,ENGLISH_STOP_WORDS); +} +StopAnalyzer::~StopAnalyzer() +{ +} +StopAnalyzer::StopAnalyzer( const TCHAR** stopWords) { + StopFilter::fillStopTable(&stopTable,stopWords); +} +TokenStream* StopAnalyzer::tokenStream(const TCHAR* fieldName, Reader* reader) { + return _CLNEW StopFilter(_CLNEW LowerCaseTokenizer(reader),true, &stopTable); +} + +const TCHAR* StopAnalyzer::ENGLISH_STOP_WORDS[] = +{ + _T("a"), _T("an"), _T("and"), _T("are"), _T("as"), _T("at"), _T("be"), _T("but"), _T("by"), + _T("for"), _T("if"), _T("in"), _T("into"), _T("is"), _T("it"), + _T("no"), _T("not"), _T("of"), _T("on"), _T("or"), _T("s"), _T("such"), + _T("t"), _T("that"), _T("the"), _T("their"), _T("then"), _T("there"), _T("these"), + _T("they"), _T("this"), _T("to"), _T("was"), _T("will"), _T("with"), NULL +}; + +PerFieldAnalyzerWrapper::PerFieldAnalyzerWrapper(Analyzer* defaultAnalyzer): + analyzerMap(true,true) +{ + this->defaultAnalyzer = defaultAnalyzer; +} +PerFieldAnalyzerWrapper::~PerFieldAnalyzerWrapper(){ + analyzerMap.clear(); + _CLDELETE(defaultAnalyzer); +} + +void PerFieldAnalyzerWrapper::addAnalyzer(const TCHAR* fieldName, Analyzer* analyzer) { + analyzerMap.put(STRDUP_TtoT(fieldName), analyzer); +} + +TokenStream* PerFieldAnalyzerWrapper::tokenStream(const TCHAR* fieldName, Reader* reader) { + Analyzer* analyzer = (fieldName==NULL?defaultAnalyzer:analyzerMap.get(fieldName)); + if (analyzer == NULL) { + analyzer = defaultAnalyzer; + } + + return analyzer->tokenStream(fieldName, reader); +} + + + +bool ISOLatin1AccentFilter::next(Token* token){ + if ( input->next(token) ){ + int32_t l = token->termTextLength(); + const TCHAR* chars = token->termText(); + bool doProcess = false; + for (int32_t i = 0; i < l; ++i) { +#ifdef _UCS2 + if ( chars[i] >= 0xC0 && chars[i] <= 0x178 ) { +#else + if ( (chars[i] >= 0xC0 && chars[i] <= 0xFF) || chars[i] < 0 ) { +#endif + doProcess = true; + break; + } + } + if ( !doProcess ) { + return true; + } + + StringBuffer output(l*2); + for (int32_t j = 0; j < l; j++) { + #ifdef _UCS2 + TCHAR c = chars[j]; + #else + unsigned char c = chars[j]; + #endif + switch (c) { + case 0xC0 : + case 0xC1 : + case 0xC2 : + case 0xC3 : + case 0xC4 : + case 0xC5 : + output.appendChar('A'); + break; + case 0xC6 : + output.append(_T("AE")); + break; + case 0xC7 : + output.appendChar('C'); + break; + case 0xC8 : + case 0xC9 : + case 0xCA : + case 0xCB : + output.appendChar('E'); + break; + case 0xCC : + case 0xCD : + case 0xCE : + case 0xCF : + output.appendChar('I'); + break; + case 0xD0 : + output.appendChar('D'); + break; + case 0xD1 : + output.appendChar('N'); + break; + case 0xD2 : + case 0xD3 : + case 0xD4 : + case 0xD5 : + case 0xD6 : + case 0xD8 : + output.appendChar('O'); + break; + case 0xDE : + output.append(_T("TH")); + break; + case 0xD9 : + case 0xDA : + case 0xDB : + case 0xDC : + output.appendChar('U'); + break; + case 0xDD : + output.appendChar('Y'); + break; + case 0xE0 : + case 0xE1 : + case 0xE2 : + case 0xE3 : + case 0xE4 : + case 0xE5 : + output.appendChar('a'); + break; + case 0xE6 : + output.append(_T("ae")); + break; + case 0xE7 : + output.appendChar('c'); + break; + case 0xE8 : + case 0xE9 : + case 0xEA : + case 0xEB : + output.appendChar('e'); + break; + case 0xEC : + case 0xED : + case 0xEE : + case 0xEF : + output.appendChar('i'); + break; + case 0xF0 : + output.appendChar('d'); + break; + case 0xF1 : + output.appendChar('n'); + break; + case 0xF2 : + case 0xF3 : + case 0xF4 : + case 0xF5 : + case 0xF6 : + case 0xF8 : + output.appendChar('o'); + break; + case 0xDF : + output.append(_T("ss")); + break; + case 0xFE : + output.append(_T("th")); + break; + case 0xF9 : + case 0xFA : + case 0xFB : + case 0xFC : + output.appendChar('u'); + break; + case 0xFD : + case 0xFF : + output.appendChar('y'); + break; + + #ifdef _UCS2 + case 0x152 : + output.append(_T("OE")); + break; + case 0x153 : + output.append(_T("oe")); + break; + case 0x178 : + output.appendChar('Y'); + break; + #endif + default : + output.appendChar(c); + break; + } + } + token->setText(output.getBuffer()); + return true; + } + return false; +} + + +TokenStream* KeywordAnalyzer::tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader){ + return _CLNEW KeywordTokenizer(reader); +} + +KeywordTokenizer::KeywordTokenizer(CL_NS(util)::Reader* input, int bufferSize): + Tokenizer(input) +{ + this->done = false; + if ( bufferSize < 0 ) + this->bufferSize = DEFAULT_BUFFER_SIZE; +} +KeywordTokenizer::~KeywordTokenizer(){ +} + +bool KeywordTokenizer::next(Token* token){ + if (!done) { + done = true; + int32_t rd; + const TCHAR* buffer=0; + while (true) { + rd = input->read(buffer, bufferSize); + if (rd == -1) + break; + token->growBuffer(token->_termTextLen +rd+1); + + int32_t cp = rd; + if ( token->_termTextLen + cp > token->bufferLength() ) + cp = token->bufferLength() - token->_termTextLen; + _tcsncpy(token->_termText+token->_termTextLen,buffer,cp); + token->_termTextLen+=rd; + } + token->_termText[token->_termTextLen]=0; + token->set(token->_termText,0,token->_termTextLen); + return true; + } + return false; +} + + +LengthFilter::LengthFilter(TokenStream* in, int _min, int _max): + TokenFilter(in) +{ + this->_min = _min; + this->_max = _max; +} + +bool LengthFilter::next(Token* token) +{ + // return the first non-stop word found + while ( input->next(token) ) + { + size_t len = token->termTextLength(); + if (len >= _min && len <= _max) + return true; + // note: else we ignore it but should we index each part of it? + } + // reached EOS -- return null + return false; +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/analysis/Analyzers.h b/3rdparty/clucene/src/CLucene/analysis/Analyzers.h new file mode 100644 index 0000000..a12bd65 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/Analyzers.h @@ -0,0 +1,309 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_analysis_Analyzers_ +#define _lucene_analysis_Analyzers_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/Reader.h" +#include "AnalysisHeader.h" +#include "CLucene/util/Misc.h" + +CL_NS_DEF(analysis) + +/** An abstract base class for simple, character-oriented tokenizers.*/ +class CharTokenizer:public Tokenizer { +private: + int32_t offset, bufferIndex, dataLen; + TCHAR buffer[LUCENE_MAX_WORD_LEN+1]; + const TCHAR* ioBuffer; +protected: + + /** Returns true iff a character should be included in a token. This + * tokenizer generates as tokens adjacent sequences of characters which + * satisfy this predicate. Characters for which this is false are used to + * define token boundaries and are not included in tokens. */ + virtual bool isTokenChar(const TCHAR c) const = 0; + + /** Called on each token character to normalize it before it is added to the + * token. The default implementation does nothing. Subclasses may use this + * to, e.g., lowercase tokens. */ + virtual TCHAR normalize(const TCHAR c) const; + +public: + CharTokenizer(CL_NS(util)::Reader* in); + virtual ~CharTokenizer(){ + } + bool next(Token* token); +}; + + +/** A LetterTokenizer is a tokenizer that divides text at non-letters. That's +to say, it defines tokens as maximal strings of adjacent letters, as defined +by java.lang.Character.isLetter() predicate. + +Note: this does a decent job for most European languages, but does a terrible +job for some Asian languages, where words are not separated by spaces. */ +class LetterTokenizer:public CharTokenizer { +public: + // Construct a new LetterTokenizer. + LetterTokenizer(CL_NS(util)::Reader* in): + CharTokenizer(in) {} + + ~LetterTokenizer(){} +protected: + /** Collects only characters which satisfy _istalpha.*/ + bool isTokenChar(const TCHAR c) const; +}; + + + +/** +* LowerCaseTokenizer performs the function of LetterTokenizer +* and LowerCaseFilter together. It divides text at non-letters and converts +* them to lower case. While it is functionally equivalent to the combination +* of LetterTokenizer and LowerCaseFilter, there is a performance advantage +* to doing the two tasks at once, hence this (redundant) implementation. +*

+* Note: this does a decent job for most European languages, but does a terrible +* job for some Asian languages, where words are not separated by spaces. +*/ +class LowerCaseTokenizer:public LetterTokenizer { +public: + /** Construct a new LowerCaseTokenizer. */ + LowerCaseTokenizer(CL_NS(util)::Reader* in): + LetterTokenizer(in) {} + + ~LowerCaseTokenizer(){} +protected: + /** Collects only characters which satisfy _totlower. */ + TCHAR normalize(const TCHAR chr) const; +}; + + +/** A WhitespaceTokenizer is a tokenizer that divides text at whitespace. + * Adjacent sequences of non-Whitespace characters form tokens. */ +class WhitespaceTokenizer: public CharTokenizer { +public: + /** Construct a new WhitespaceTokenizer. */ + WhitespaceTokenizer(CL_NS(util)::Reader* in):CharTokenizer(in) {} + ~WhitespaceTokenizer(){} +protected: + /** Collects only characters which do not satisfy _istspace. + */ + bool isTokenChar(const TCHAR c) const; +}; + + +/** An Analyzer that uses WhitespaceTokenizer. */ +class WhitespaceAnalyzer: public Analyzer { + public: + TokenStream* tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader); + ~WhitespaceAnalyzer(){} +}; + +/** An Analyzer that filters LetterTokenizer with LowerCaseFilter. */ +class SimpleAnalyzer: public Analyzer { +public: + TokenStream* tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader); + ~SimpleAnalyzer(){} +}; + + + +/** +* Normalizes token text to lower case. +*/ +class LowerCaseFilter: public TokenFilter { +public: + LowerCaseFilter(TokenStream* in, bool deleteTokenStream):TokenFilter(in,deleteTokenStream) {} + ~LowerCaseFilter(){} + bool next(Token* token); +}; + + +/** + * Removes stop words from a token stream. + */ +class StopFilter: public TokenFilter { +private: + //bvk: i found this to work faster with a non-hash table. the number of items + //in the stop table is not like to make it worth having hashing. + CL_NS(util)::CLSetList* table; +public: + // Constructs a filter which removes words from the input + // TokenStream that are named in the array of words. + StopFilter(TokenStream* in, bool deleteTokenStream, const TCHAR** stopWords); + + ~StopFilter(){} + + /** Constructs a filter which removes words from the input + * TokenStream that are named in the CLSetList. + */ + StopFilter(TokenStream* in, bool deleteTokenStream, CL_NS(util)::CLSetList* stopTable): + TokenFilter(in, deleteTokenStream), + table(stopTable) + {} + + + /** + * Builds a Hashtable from an array of stop words, appropriate for passing + * into the StopFilter constructor. This permits this table construction to + * be cached once when an Analyzer is constructed. + * Note: the stopWords list must be a static list because the strings are not copied + */ + static void fillStopTable(CL_NS(util)::CLSetList* stopTable, + const TCHAR** stopWords); + + /** + * Returns the next input Token whose termText() is not a stop word. + */ + bool next(Token* token); +}; + + + + +/** Filters LetterTokenizer with LowerCaseFilter and StopFilter. */ +class StopAnalyzer: public Analyzer { + CL_NS(util)::CLSetList stopTable; + +public: + /** Builds an analyzer which removes words in ENGLISH_STOP_WORDS. */ + StopAnalyzer(); + ~StopAnalyzer(); + + /** Builds an analyzer which removes words in the provided array. */ + StopAnalyzer( const TCHAR** stopWords ); + /** Filters LowerCaseTokenizer with StopFilter. */ + TokenStream* tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader); + + /** An array containing some common English words that are not usually useful + for searching. */ + static const TCHAR* ENGLISH_STOP_WORDS[]; +}; + + + +/** + * This analyzer is used to facilitate scenarios where different + * fields require different analysis techniques. Use {@link #addAnalyzer} + * to add a non-default analyzer on a field name basis. + * + *

Example usage: + * + *

+ *   PerFieldAnalyzerWrapper aWrapper =
+ *      new PerFieldAnalyzerWrapper(new StandardAnalyzer());
+ *   aWrapper.addAnalyzer("firstname", new KeywordAnalyzer());
+ *   aWrapper.addAnalyzer("lastname", new KeywordAnalyzer());
+ * 
+ * + *

In this example, StandardAnalyzer will be used for all fields except "firstname" + * and "lastname", for which KeywordAnalyzer will be used. + * + *

A PerFieldAnalyzerWrapper can be used like any other analyzer, for both indexing + * and query parsing. + */ +class PerFieldAnalyzerWrapper : public Analyzer { +private: + Analyzer* defaultAnalyzer; + CL_NS(util)::CLHashMap > analyzerMap; +public: + /** + * Constructs with default analyzer. + * + * @param defaultAnalyzer Any fields not specifically + * defined to use a different analyzer will use the one provided here. + */ + PerFieldAnalyzerWrapper(Analyzer* defaultAnalyzer); + ~PerFieldAnalyzerWrapper(); + + /** + * Defines an analyzer to use for the specified field. + * + * @param fieldName field name requiring a non-default analyzer + * @param analyzer non-default analyzer to use for field + */ + void addAnalyzer(const TCHAR* fieldName, Analyzer* analyzer); + TokenStream* tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader); +}; + + +/** + * A filter that replaces accented characters in the ISO Latin 1 character set + * (ISO-8859-1) by their unaccented equivalent. The case will not be altered. + *

+ * For instance, 'à' will be replaced by 'a'. + *

+ */ +class ISOLatin1AccentFilter: public TokenFilter { +public: + ISOLatin1AccentFilter(TokenStream* input, bool deleteTs): + TokenFilter(input,deleteTs) + { + } + + /** + * To replace accented characters in a String by unaccented equivalents. + */ + bool next(Token* token); +}; + + +/** + * Emits the entire input as a single token. + */ +class KeywordTokenizer: public Tokenizer { +private: + LUCENE_STATIC_CONSTANT(int, DEFAULT_BUFFER_SIZE = 256); + bool done; + int bufferSize; +public: + KeywordTokenizer(CL_NS(util)::Reader* input, int bufferSize=-1); + virtual ~KeywordTokenizer(); + bool next(Token* token); +}; + +/** + * "Tokenizes" the entire stream as a single token. This is useful + * for data like zip codes, ids, and some product names. + */ +class KeywordAnalyzer: public Analyzer { +public: + TokenStream* tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader); + virtual ~KeywordAnalyzer(){} +}; + + +/** + * Removes words that are too long and too short from the stream. + * + */ +class LengthFilter: public TokenFilter { +private: + int _min; + int _max; +public: + /** + * Build a filter that removes words that are too long or too + * short from the text. + */ + LengthFilter(TokenStream* in, int _min, int _max); + + /** + * Returns the next input Token whose termText() is the right len + */ + bool next(Token* token); +}; + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.cpp b/3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.cpp new file mode 100644 index 0000000..e0994c4 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.cpp @@ -0,0 +1,46 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "StandardAnalyzer.h" + +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/Reader.h" +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/analysis/Analyzers.h" +#include "StandardFilter.h" +#include "StandardTokenizer.h" + +CL_NS_USE(util) +CL_NS_USE(analysis) + +CL_NS_DEF2(analysis,standard) + + StandardAnalyzer::StandardAnalyzer(): + stopSet(false) + { + StopFilter::fillStopTable( &stopSet,CL_NS(analysis)::StopAnalyzer::ENGLISH_STOP_WORDS); + } + + StandardAnalyzer::StandardAnalyzer( const TCHAR** stopWords): + stopSet(false) + { + StopFilter::fillStopTable( &stopSet,stopWords ); + } + + StandardAnalyzer::~StandardAnalyzer(){ + } + + + TokenStream* StandardAnalyzer::tokenStream(const TCHAR* fieldName, Reader* reader) + { + TokenStream* ret = _CLNEW StandardTokenizer(reader); + ret = _CLNEW StandardFilter(ret,true); + ret = _CLNEW LowerCaseFilter(ret,true); + ret = _CLNEW StopFilter(ret,true, &stopSet); + return ret; + } +CL_NS_END2 diff --git a/3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.h b/3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.h new file mode 100644 index 0000000..9cce041 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/standard/StandardAnalyzer.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_analysis_standard_StandardAnalyzer +#define _lucene_analysis_standard_StandardAnalyzer + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/Reader.h" +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/analysis/Analyzers.h" +#include "StandardFilter.h" +#include "StandardTokenizer.h" + + +CL_NS_DEF2(analysis,standard) + + /** Represents a standard analyzer. */ + class StandardAnalyzer : public Analyzer + { + private: + CL_NS(util)::CLSetList stopSet; + public: + /** Builds an analyzer.*/ + StandardAnalyzer(); + + /** Builds an analyzer with the given stop words. */ + StandardAnalyzer( const TCHAR** stopWords); + + ~StandardAnalyzer(); + + + /** + * Constructs a StandardTokenizer filtered by a + * StandardFilter, a LowerCaseFilter and a StopFilter. + */ + TokenStream* tokenStream(const TCHAR* fieldName, CL_NS(util)::Reader* reader) + ; + }; +CL_NS_END2 +#endif diff --git a/3rdparty/clucene/src/CLucene/analysis/standard/StandardFilter.cpp b/3rdparty/clucene/src/CLucene/analysis/standard/StandardFilter.cpp new file mode 100644 index 0000000..9869d25 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/standard/StandardFilter.cpp @@ -0,0 +1,58 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "StandardFilter.h" + +#include "../AnalysisHeader.h" +#include "../Analyzers.h" +#include "StandardTokenizerConstants.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(analysis) +CL_NS_USE(util) +CL_NS_DEF2(analysis,standard) + + StandardFilter::StandardFilter(TokenStream* in, bool deleteTokenStream): + TokenFilter(in, deleteTokenStream) + { + } + + StandardFilter::~StandardFilter(){ + } + + bool StandardFilter::next(Token* t) { + if (!input->next(t)) + return false; + + TCHAR* text = t->_termText; + const int32_t textLength = t->termTextLength(); + const TCHAR* type = t->type(); + + if ( type == tokenImage[APOSTROPHE] && //we can compare the type directy since the type should always come from the tokenImage + ( textLength >= 2 && _tcsicmp(text+textLength-2, _T("'s"))==0 ) ) + { + // remove 's + text[textLength-2]=0; + t->resetTermTextLen(); + + return true; + + } else if ( type == tokenImage[ACRONYM] ) { // remove dots + int32_t j = 0; + for ( int32_t i=0;iin. + StandardFilter(TokenStream* in, bool deleteTokenStream); + + ~StandardFilter(); + + + /** Returns the next token in the stream, or NULL at EOS. + *

Removes 's from the end of words. + *

Removes dots from acronyms. + */ + bool next(Token* token); + }; +CL_NS_END2 +#endif diff --git a/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.cpp b/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.cpp new file mode 100644 index 0000000..60f9a44 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.cpp @@ -0,0 +1,446 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "StandardTokenizer.h" + +CL_NS_USE(analysis) +CL_NS_USE(util) +CL_NS_DEF2(analysis,standard) + + const static TCHAR* tokenImageArray[] = { + _T(""), + _T(""), + _T(""), + _T(""), + _T(""), + _T(""), + _T(""), + _T(""), + _T(""), + _T("") + }; + const TCHAR** tokenImage = tokenImageArray; + + /* A bunch of shortcut macros, many of which make assumptions about variable + ** names. These macros enhance readability, not just convenience! */ + #define EOS (ch==-1 || rd->Eos()) + #define SPACE (_istspace((TCHAR)ch) != 0) + #define ALPHA (_istalpha((TCHAR)ch) != 0) + #define ALNUM (_istalnum(ch) != 0) + #define DIGIT (_istdigit(ch) != 0) + #define UNDERSCORE (ch == '_') + + #define _CJK ( (ch>=0x3040 && ch<=0x318f) || \ + (ch>=0x3300 && ch<=0x337f) || \ + (ch>=0x3400 && ch<=0x3d2d) || \ + (ch>=0x4e00 && ch<=0x9fff) || \ + (ch>=0xf900 && ch<=0xfaff) || \ + (ch>=0xac00 && ch<=0xd7af) ) //korean + + + #define DASH (ch == '-') + #define NEGATIVE_SIGN_ DASH + //#define POSITIVE_SIGN_ (ch == '+') + //#define SIGN (NEGATIVE_SIGN_ || POSITIVE_SIGN_) + + #define DOT (ch == '.') + #define DECIMAL DOT + + + //freebsd seems to have a problem with defines over multiple lines, so this has to be one long line + #define _CONSUME_AS_LONG_AS(conditionFails) while (true) { ch = readChar(); if (ch==-1 || (!(conditionFails) || str.len >= LUCENE_MAX_WORD_LEN)) { break; } str.appendChar(ch);} + + #define CONSUME_ALPHAS _CONSUME_AS_LONG_AS(ALPHA) + + #define CONSUME_DIGITS _CONSUME_AS_LONG_AS(DIGIT) + + /* otherMatches is a condition (possibly compound) under which a character + ** that's not an ALNUM or UNDERSCORE can be considered not to break the + ** span. Callers should pass false if only ALNUM/UNDERSCORE are acceptable. */ + #define CONSUME_WORD _CONSUME_AS_LONG_AS(ALNUM || UNDERSCORE) + + /* + ** Consume CJK characters + */ + #define CONSUME_CJK _CONSUME_AS_LONG_AS(_CJK) + + + /* It is considered that "nothing of value" has been read if: + ** a) The "read head" hasn't moved since specialCharPos was established. + ** or + ** b) The "read head" has moved by one character, but that character was + ** either whitespace or not among the characters found in the body of + ** a token (deliberately doesn't include the likes of '@'/'&'). */ + #define CONSUMED_NOTHING_OF_VALUE (rdPos == specialCharPos || (rdPos == specialCharPos+1 && ( SPACE || !(ALNUM || DOT || DASH || UNDERSCORE) ))) + + #define RIGHTMOST(sb) (sb.getBuffer()[sb.len-1]) + #define RIGHTMOST_IS(sb, c) (RIGHTMOST(sb) == c) + /* To discard the last character in a StringBuffer, we decrement the buffer's + ** length indicator and move the terminator back by one character. */ + #define SHAVE_RIGHTMOST(sb) (sb.getBuffer()[--sb.len] = '\0') + + //#define REMOVE_TRAILING_CHARS(sb, charMatchesCondition) { TCHAR* sbBuf = sb.getBuffer(); for (int32_t i = sb.len-1; i >= 0; i--) { TCHAR c = sbBuf[i]; if (charMatchesCondition) { sbBuf[--sb.len] = '\0'; } else {break;}}} + + /* Does StringBuffer sb contain any of the characters in string ofThese? */ + #define CONTAINS_ANY(sb, ofThese) (_tcscspn(sb.getBuffer(), _T(ofThese)) != static_cast(sb.len)) + + + StandardTokenizer::StandardTokenizer(Reader* reader): + rd(_CLNEW FastCharStream(reader)), + /* rdPos is zero-based. It starts at -1, and will advance to the first + ** position when readChar() is first called. */ + rdPos(-1), + tokenStart(-1) + { + } + + StandardTokenizer::~StandardTokenizer() { + _CLDELETE(rd); + } + + int StandardTokenizer::readChar() { + /* Increment by 1 because we're speaking in terms of characters, not + ** necessarily bytes: */ + rdPos++; + return rd->GetNext(); + } + + void StandardTokenizer::unReadChar() { + rd->UnGet(); + rdPos--; + } + + inline bool StandardTokenizer::setToken(Token* t, StringBuffer* sb, TokenTypes tokenCode) { + t->setStartOffset(tokenStart); + t->setEndOffset(tokenStart+sb->length()); + t->setType(tokenImage[tokenCode]); + sb->getBuffer(); //null terminates the buffer + t->resetTermTextLen(); + return true; + } + + bool StandardTokenizer::next(Token* t) { + int ch=0; + while (!EOS) { + ch = readChar(); + + if ( ch == 0 || ch == -1 ){ + continue; + } else if (SPACE) { + continue; + } else if (ALPHA || UNDERSCORE) { + tokenStart = rdPos; + return ReadAlphaNum(ch,t); + } else if (DIGIT || NEGATIVE_SIGN_ || DECIMAL) { + tokenStart = rdPos; + /* ReadNumber returns NULL if it fails to extract a valid number; in + ** that case, we just continue. */ + if (ReadNumber(NULL, ch,t)) + return true; + } else if ( _CJK ){ + if ( ReadCJK(ch,t) ) + return true; + } + } + return false; + } + + bool StandardTokenizer::ReadNumber(const TCHAR* previousNumber, const TCHAR prev,Token* t) { + /* previousNumber is only non-NULL if this function already read a complete + ** number in a previous recursion, yet has been asked to read additional + ** numeric segments. For example, in the HOST "192.168.1.3", "192.168" is + ** a complete number, but this function will recurse to read the "1.3", + ** generating a single HOST token "192.168.1.3". */ + t->growBuffer(LUCENE_MAX_WORD_LEN+1);//make sure token can hold the next word + StringBuffer str(t->_termText,t->bufferLength(),true); //use stringbuffer to read data onto the termText + TokenTypes tokenType; + bool decExhausted; + if (previousNumber != NULL) { + str.prepend(previousNumber); + tokenType = CL_NS2(analysis,standard)::HOST; + decExhausted = false; + } else { + tokenType = CL_NS2(analysis,standard)::NUM; + decExhausted = (prev == '.'); + } + if ( str.len >= LUCENE_MAX_WORD_LEN ){ + //if a number is too long, i would say there is no point + //storing it, because its going to be the wrong number anyway? + //what do people think? + return false; + } + str.appendChar(prev); + + const bool signExhausted = (prev == '-'); + int ch = prev; + + CONSUME_DIGITS; + + if (str.len < 2 /* CONSUME_DIGITS didn't find any digits. */ + && ( + (signExhausted && !DECIMAL) + || (decExhausted /* && !DIGIT is implied, since CONSUME_DIGITS stopped on a non-digit. */) + ) + ) + { + /* We have either: + ** a) a negative sign that's not followed by either digit(s) or a decimal + ** b) a decimal that's not followed by digit(s) + ** so this is not a valid number. */ + if (!EOS) { + /* Unread the character that stopped CONSUME_DIGITS: */ + unReadChar(); + } + return false; + } + + /* We just read a group of digits. Is it followed by a decimal symbol, + ** implying that there might be another group of digits available? */ + if (!EOS) { + if (DECIMAL) { + if ( str.len >= LUCENE_MAX_WORD_LEN ) + return false; //read above for rationale + str.appendChar(ch); + } else { + unReadChar(); + goto SUCCESSFULLY_EXTRACTED_NUMBER; + } + + CONSUME_DIGITS; + if (!DIGIT && !DECIMAL) { + unReadChar(); + } else if (!EOS && DECIMAL && _istdigit(rd->Peek())) { + /* We just read the fractional digit group, but it's also followed by + ** a decimal symbol and at least one more digit, so this must be a + ** HOST rather than a real number. */ + return ReadNumber(str.getBuffer(), '.',t); + } + } + + SUCCESSFULLY_EXTRACTED_NUMBER: + TCHAR rightmost = RIGHTMOST(str); + /* Don't including a trailing decimal point. */ + if (rightmost == '.') { + SHAVE_RIGHTMOST(str); + unReadChar(); + rightmost = RIGHTMOST(str); + } + /* If all we have left is a negative sign, it's not a valid number. */ + if (rightmost == '-') { + CND_PRECONDITION (str.len == 1, "Number is invalid"); + return false; + } + + return setToken(t,&str,tokenType); + } + + bool StandardTokenizer::ReadAlphaNum(const TCHAR prev, Token* t) { + t->growBuffer(LUCENE_MAX_WORD_LEN+1);//make sure token can hold the next word + StringBuffer str(t->_termText,t->bufferLength(),true); //use stringbuffer to read data onto the termText + if ( str.len < LUCENE_MAX_WORD_LEN ){ + str.appendChar(prev); + int ch = prev; + + CONSUME_WORD; + if (!EOS && str.len < LUCENE_MAX_WORD_LEN-1 ) { //still have space for 1 more character? + switch(ch) { /* What follows the first alphanum segment? */ + case '.': + str.appendChar('.'); + return ReadDotted(&str, CL_NS2(analysis,standard)::UNKNOWN,t); + case '\'': + str.appendChar('\''); + return ReadApostrophe(&str,t); + case '@': + str.appendChar('@'); + return ReadAt(&str,t); + case '&': + str.appendChar('&'); + return ReadCompany(&str,t); + /* default: fall through to end of this function. */ + } + } + } + return setToken(t,&str,CL_NS2(analysis,standard)::ALPHANUM); + } + + bool StandardTokenizer::ReadCJK(const TCHAR prev, Token* t) { + t->growBuffer(LUCENE_MAX_WORD_LEN+1);//make sure token can hold the next word + StringBuffer str(t->_termText,t->bufferLength(),true); //use stringbuffer to read data onto the termText + if ( str.len < LUCENE_MAX_WORD_LEN ){ + str.appendChar(prev); + int ch = prev; + + CONSUME_CJK; + } + return setToken(t,&str,CL_NS2(analysis,standard)::CJK); + } + + + bool StandardTokenizer::ReadDotted(StringBuffer* _str, TokenTypes forcedType, Token* t) { + const int32_t specialCharPos = rdPos; + StringBuffer& str=*_str; + + /* A segment of a "dotted" is not allowed to begin with another dot or a dash. + ** Even though hosts, e-mail addresses, etc., could have a dotted-segment + ** that begins with a dot or a dash, it's far more common in source text + ** for a pattern like "abc.--def" to be intended as two tokens. */ + int ch = rd->Peek(); + if (!(DOT || DASH)) { + bool prevWasDot; + bool prevWasDash; + if (str.len == 0) { + prevWasDot = false; + prevWasDash = false; + } else { + prevWasDot = RIGHTMOST(str) == '.'; + prevWasDash = RIGHTMOST(str) == '-'; + } + while (!EOS && str.len < LUCENE_MAX_WORD_LEN-1 ) { + ch = readChar(); + const bool dot = ch == '.'; + const bool dash = ch == '-'; + + if (!(ALNUM || UNDERSCORE || dot || dash)) { + break; + } + /* Multiple dots or dashes in succession end the token. + ** Consider the following inputs: + ** "Visit windowsupdate.microsoft.com--update today!" + ** "In the U.S.A.--yes, even there!" */ + if ((dot || dash) && (prevWasDot || prevWasDash)) { + /* We're not going to append the character we just read, in any case. + ** As to the character before it (which is currently RIGHTMOST(str)): + ** Unless RIGHTMOST(str) is a dot, in which we need to save it so the + ** acronym-versus-host detection can work, we want to get rid of it. */ + if (!prevWasDot) { + SHAVE_RIGHTMOST(str); + } + break; + } + + str.appendChar(ch); + + prevWasDot = dot; + prevWasDash = dash; + } + } + + /* There's a potential StringBuffer.append call in the code above, which + ** could cause str to reallocate its internal buffer. We must wait to + ** obtain the optimization-oriented strBuf pointer until after the initial + ** potentially realloc-triggering operations on str. + ** Because there can be other such ops much later in this function, strBuf + ** is guarded within a block to prevent its use during or after the calls + ** that would potentially invalidate it. */ + { /* Begin block-guard of strBuf */ + TCHAR* strBuf = str.getBuffer(); + + bool rightmostIsDot = RIGHTMOST_IS(str, '.'); + if (CONSUMED_NOTHING_OF_VALUE) { + /* No more alphanums available for this token; shave trailing dot, if any. */ + if (rightmostIsDot) { + SHAVE_RIGHTMOST(str); + } + /* If there are no dots remaining, this is a generic ALPHANUM. */ + if (_tcschr(strBuf, '.') == NULL) { + forcedType = CL_NS2(analysis,standard)::ALPHANUM; + } + + /* Check the token to see if it's an acronym. An acronym must have a + ** letter in every even slot and a dot in every odd slot, including the + ** last slot (for example, "U.S.A."). */ + } else if (rightmostIsDot) { + bool isAcronym = true; + const int32_t upperCheckLimit = str.len - 1; /* -1 b/c we already checked the last slot. */ + + for (int32_t i = 0; i < upperCheckLimit; i++) { + const bool even = (i % 2 == 0); + ch = strBuf[i]; + if ( (even && !ALPHA) || (!even && !DOT) ) { + isAcronym = false; + break; + } + } + if (isAcronym) { + forcedType = CL_NS2(analysis,standard)::ACRONYM; + } else { + /* If it's not an acronym, we don't want the trailing dot. */ + SHAVE_RIGHTMOST(str); + /* If there are no dots remaining, this is a generic ALPHANUM. */ + if (_tcschr(strBuf, '.') == NULL) { + forcedType = CL_NS2(analysis,standard)::ALPHANUM; + } + } + } + } /* End block-guard of strBuf */ + + if (!EOS) { + if (ch == '@' && str.len < LUCENE_MAX_WORD_LEN-1) { + str.appendChar('@'); + return ReadAt(&str,t); + } else { + unReadChar(); + } + } + + return setToken(t,&str,CL_NS2(analysis,standard)::UNKNOWN + ? forcedType : CL_NS2(analysis,standard)::HOST); + } + + bool StandardTokenizer::ReadApostrophe(StringBuffer* _str, Token* t) { + StringBuffer& str=*_str; + + TokenTypes tokenType = CL_NS2(analysis,standard)::APOSTROPHE; + const int32_t specialCharPos = rdPos; + int ch=0; + + CONSUME_ALPHAS; + if (RIGHTMOST_IS(str, '\'') || CONSUMED_NOTHING_OF_VALUE) { + /* After the apostrophe, no more alphanums were available within this + ** token; shave trailing apostrophe and revert to generic ALPHANUM. */ + SHAVE_RIGHTMOST(str); + tokenType = CL_NS2(analysis,standard)::ALPHANUM; + } + if (!EOS) { + unReadChar(); + } + + return setToken(t,&str,tokenType); + } + + bool StandardTokenizer::ReadAt(StringBuffer* str, Token* t) { + ReadDotted(str, CL_NS2(analysis,standard)::EMAIL,t); + /* JLucene grammar indicates dots/digits not allowed in company name: */ + if (!CONTAINS_ANY((*str), ".0123456789")) { + setToken(t,str,CL_NS2(analysis,standard)::COMPANY); + } + return true; + } + + bool StandardTokenizer::ReadCompany(StringBuffer* _str, Token* t) { + StringBuffer& str = *_str; + const int32_t specialCharPos = rdPos; + int ch=0; + + CONSUME_WORD; + if (CONSUMED_NOTHING_OF_VALUE) { + /* After the ampersand, no more alphanums were available within this + ** token; shave trailing ampersand and revert to ALPHANUM. */ + CND_PRECONDITION(RIGHTMOST_IS(str, '&'),"ReadCompany failed"); + SHAVE_RIGHTMOST(str); + + + return setToken(t,&str,CL_NS2(analysis,standard)::ALPHANUM); + } + if (!EOS) { + unReadChar(); + } + + return setToken(t,&str,CL_NS2(analysis,standard)::COMPANY); + } + +CL_NS_END2 diff --git a/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.h b/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.h new file mode 100644 index 0000000..d4195be --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizer.h @@ -0,0 +1,88 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_analysis_standard_StandardTokenizer +#define _lucene_analysis_standard_StandardTokenizer + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "../AnalysisHeader.h" +#include "../Analyzers.h" +#include "StandardTokenizerConstants.h" +#include "CLucene/util/StringBuffer.h" +#include "CLucene/util/FastCharStream.h" +#include "CLucene/util/Reader.h" + + +CL_NS_DEF2(analysis,standard) + +/** A grammar-based tokenizer constructed with JavaCC. + * + *

This should be a good tokenizer for most European-language documents: + * + *

    + *
  • Splits words at punctuation characters, removing punctuation. However, a + * dot that's not followed by whitespace is considered part of a token. + *
  • Splits words at hyphens, unless there's a number in the token, in which case + * the whole token is interpreted as a product number and is not split. + *
  • Recognizes email addresses and internet hostnames as one token. + *
+ * + *

Many applications have specific tokenizer needs. If this tokenizer does + * not suit your application, please consider copying this source code + * directory to your project and maintaining your own grammar-based tokenizer. + */ + class StandardTokenizer: public Tokenizer { + private: + int32_t rdPos; + int32_t tokenStart; + + // Advance by one character, incrementing rdPos and returning the character. + int readChar(); + // Retreat by one character, decrementing rdPos. + void unReadChar(); + + // createToken centralizes token creation for auditing purposes. + //Token* createToken(CL_NS(util)::StringBuffer* sb, TokenTypes tokenCode); + inline bool setToken(Token* t, CL_NS(util)::StringBuffer* sb, TokenTypes tokenCode); + + bool ReadDotted(CL_NS(util)::StringBuffer* str, TokenTypes forcedType,Token* t); + + public: + CL_NS(util)::FastCharStream* rd; + + // Constructs a tokenizer for this Reader. + StandardTokenizer(CL_NS(util)::Reader* reader); + + ~StandardTokenizer(); + + /** Returns the next token in the stream, or false at end-of-stream. + * The returned token's type is set to an element of + * StandardTokenizerConstants::tokenImage. */ + bool next(Token* token); + + // Reads for number like "1"/"1234.567", or IP address like "192.168.1.2". + bool ReadNumber(const TCHAR* previousNumber, const TCHAR prev, Token* t); + + bool ReadAlphaNum(const TCHAR prev, Token* t); + + // Reads for apostrophe-containing word. + bool ReadApostrophe(CL_NS(util)::StringBuffer* str, Token* t); + + // Reads for something@... it may be a COMPANY name or a EMAIL address + bool ReadAt(CL_NS(util)::StringBuffer* str, Token* t); + + // Reads for COMPANY name like AT&T. + bool ReadCompany(CL_NS(util)::StringBuffer* str, Token* t); + + // Reads CJK characters + bool ReadCJK(const TCHAR prev, Token* t); + }; + +CL_NS_END2 +#endif diff --git a/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizerConstants.h b/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizerConstants.h new file mode 100644 index 0000000..3c95af4 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/analysis/standard/StandardTokenizerConstants.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_analysis_standard_StandardTokenizerConstants +#define _lucene_analysis_standard_StandardTokenizerConstants + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF2(analysis,standard) + enum TokenTypes { + _EOF, + UNKNOWN, + ALPHANUM, + APOSTROPHE, + ACRONYM, + COMPANY, + EMAIL, + HOST, + NUM, + CJK + }; + extern const TCHAR** tokenImage; + + CL_NS_END2 +#endif diff --git a/3rdparty/clucene/src/CLucene/config/CompilerAcc.h b/3rdparty/clucene/src/CLucene/config/CompilerAcc.h new file mode 100644 index 0000000..6ecd142 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/CompilerAcc.h @@ -0,0 +1,166 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#if !defined(_lucene_COMPILER_ACC) +#define _lucene_COMPILER_ACC + +// It is internal CLucene header - DO NOT include it directly +#if !defined(_SUPPRESS_MAKE_BASED_CONFIG) +#if defined(_BUILD_FOR_QT_) +#include "fulltextsearch/qclucene-config_p.h" +#else +#include "CLucene/clucene-config.h" //make clucene-config.h file +#endif +#endif + +#if defined(_ASCII) +#undef _UCS2 +#elif defined(_UCS2) +// +#else +#define CL_CHARSET_GUESS +#endif + +//dont allow FS_MMAP if mmap is not available +#if defined(LUCENE_FS_MMAP) && !defined(_CL_HAVE_MMAP) +#error "LUCENE_FS_MMAP is defined and MMap doesn't appear to be available" +#endif + +#ifdef _CL_HAVE_NO_FUNCTION_TRY_BLOCKS +#undef _LUCENE_DISABLE_EXCEPTIONS +#define _LUCENE_DISABLE_EXCEPTIONS + +#error "this is bad if you made it here... your compiler seems not to have try/catch blocks." +#error "maybe you could implement an alternative solution for us? :)" +#endif + +#ifndef _CL_HAVE_NAMESPACES +#define DISABLE_NAMESPACE +#endif + +#define LUCENE_DISABLE_HASHING //we could enable this, but so far test show that the hashing is slower :( + +//define the file functions +#define fileSeek lseek +#define fileSize _filelength +#define fileStat stat +#define fileHandleStat fstat +#ifdef _CL_HAVE_TELL +#define fileTell tell +#else +//ftell (and probably soon ftell64) are POSIX standard functions, but tell and +//tell64 are not, so we define fileTell in terms of fileSeek. +#define fileTell(fhandle) fileSeek(fhandle, 0, SEEK_CUR) +#endif + +//this is needed early on so that CL_MAX_PATH can be correctly determined +//in the StdHeader.h. This was earlier causing problems with macosx. +//:: crash was due to realpath() that expects an output arguments that +//has at least the size of PATH_MAX (even if the result has a lower size) +#include + +#ifndef _CL_HAVE_WCHAR_T + typedef unsigned short wchar_t; +#endif + +#if defined(__CYGWIN__) +//cygwin seems to incorrectly define that it has wprintf??? +#undef _CL_HAVE_WPRINTF +#elif defined(__MINGW32__) +# ifndef _CL_HAVE_WINDOWS_H +# define _CL_HAVE_WINDOWS_H +# endif +#endif + + +/////////////////////////////////////////////////////////////////////////////// +//end _lucene_COMPILER_ACC +#elif !defined(_lucene_COMPILER_ACC2) +#define _lucene_COMPILER_ACC2 +//second inclusion + + //types + #if defined(_CL_HAVE_SYS_TYPES_H) + #include + #endif + #if defined(_CL_HAVE_INTTYPES_H) + #include + #elif defined(_CL_HAVE_STDINT_H) + #include + #else + #if _CL_SIZEOF_UNSIGNED_LONG_LONG==8 + typedef unsigned long long uint64_t; + typedef long long int64_t; + #elif _CL_SIZEOF_UNSIGNED_LONG==8 + typedef unsigned long uint64_t; + typedef long int64_t; + #else + #error I do not know what to use for a uint64_t. + #endif + + /* Give us an unsigned 32-bit data type. */ + #if _CL_SIZEOF_UNSIGNED_LONG==4 + typedef unsigned long uint32_t; + typedef long int32_t; + #elif _CL_SIZEOF_UNSIGNED_INT==4 + typedef unsigned int uint32_t; + typedef int int32_t; + #else + #error I do not know what to use for a uint32_t. + #endif + + /* An unsigned 8-bit data type */ + #if _CL_SIZEOF_UNSIGNED_CHAR==1 + typedef unsigned char uint8_t; + #else + #error I do not know what to use for a uint8_t. + #endif + #endif + + //second chance to fix default settings + //this must be defined later, otherwise it messes up + //the standard libraries + #if !defined(__MINGW32__) + #define _close ::close + #define _read ::read + #endif + + //now that int64_t is defined, we can define this... + #ifndef _CL_HAVE_FILELENGTH + #undef fileSize + #define fileSize lucene_filelength + int64_t lucene_filelength(int handle); + #endif + +#elif !defined(_lucene_COMPILER_ACC3) +#define _lucene_COMPILER_ACC3 + //third inclusion + + #if !defined(__MINGW32__) + //define replacements + #define O_RANDOM 0 + #undef O_BINARY + #define O_BINARY 0 + #define _S_IREAD 0444 + #define _S_IWRITE 0333 // write and execute permissions + + //some functions that are needed - not charset dependent and not tchar type functions + #define _open open + #define _write write + #define _snprintf snprintf + + //clucene uses ascii for filename interactions + #define _realpath(rel,abs) realpath(rel,abs) + #define _mkdir(x) mkdir(x,0777) + #define _unlink unlink + #else + #define _realpath(rel,abs) _fullpath(abs,rel,CL_MAX_PATH) + #endif + //also required by mingw + #define _rename rename +#endif diff --git a/3rdparty/clucene/src/CLucene/config/CompilerBcb.h b/3rdparty/clucene/src/CLucene/config/CompilerBcb.h new file mode 100644 index 0000000..f1b423b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/CompilerBcb.h @@ -0,0 +1,68 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#if !defined(_lucene_COMPILER_BCB) +#define _lucene_COMPILER_BCB + +// It is internal CLucene header - DO NOT include it directly + +#include "CLucene/config/define_std.h" +#undef _CL_HAVE_STRTOLL +#undef _CL_HAVE_WCSTOLL + +#define _LUCENE_PRAGMA_ONCE +#define _LUCENE_PRAGMA_WARNINGS //tell lucene to display warnings using pragmas instead of #warning +#define LUCENE_DISABLE_HASHING +#define LUCENE_STATIC_CONSTANT(type, assignment) enum { assignment } + +#undef LUCENE_ENABLE_MEMLEAKTRACKING //it has been reported that this causes problems + +#define fileSize filelength +#define fileSeek lseek +#define fileTell tell +#define fileStat stat +#define fileHandleStat fstat + +#define O_RANDOM 0 + +//java long type +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +//java int type +typedef int int32_t; +typedef unsigned int uint32_t; + +//java byte type +typedef unsigned char uint8_t; + +//floating point type +//we are going to use qreal now +//typedef double float_t; + +//required type +typedef int intptr_t; + +#define _CL_ILONG(x) x ## L +#define _ILONGLONG(x) x ## i64 + + +#elif !defined(_lucene_COMPILER_BCB2) +#define _lucene_COMPILER_BCB2 + //second inclusion + + #define _open open + #define _timeb timeb + #define _ftime ::ftime + #define _rename rename + + #define _realpath(rel,abs) _fullpath(abs,rel,CL_MAX_PATH) + +#elif !defined(_lucene_COMPILER_BCB3) +#define _lucene_COMPILER_BCB3 + //third inclusion + +#endif diff --git a/3rdparty/clucene/src/CLucene/config/CompilerGcc.h b/3rdparty/clucene/src/CLucene/config/CompilerGcc.h new file mode 100644 index 0000000..a912098 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/CompilerGcc.h @@ -0,0 +1,175 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#if !defined(_lucene_COMPILER_GCC) +#define _lucene_COMPILER_GCC + +// It is internal CLucene header - DO NOT include it directly +#if !defined(_SUPPRESS_MAKE_BASED_CONFIG) + #if defined(_BUILD_FOR_QT_) + #include "fulltextsearch/qclucene-config_p.h" + #else + #include "CLucene/clucene-config.h" //make clucene-config.h file + #endif +#endif + +#if defined(_ASCII) + #undef _UCS2 +#elif defined(_UCS2) +// +#else + #define CL_CHARSET_GUESS +#endif + +//dont allow FS_MMAP if mmap is not available +#if defined(LUCENE_FS_MMAP) && !defined(_CL_HAVE_MMAP) + #error "LUCENE_FS_MMAP is defined and MMap doesn't appear to be available" +#endif + +#ifdef _CL_HAVE_NO_FUNCTION_TRY_BLOCKS + #undef _LUCENE_DISABLE_EXCEPTIONS + #define _LUCENE_DISABLE_EXCEPTIONS + + #error "this is bad if you made it here... your compiler seems not to have try/catch blocks." + #error "maybe you could implement an alternative solution for us? :)" +#endif + +#ifndef _CL_HAVE_NAMESPACES + #define DISABLE_NAMESPACE +#endif + +#define CL_NS_HASHING(func) __gnu_cxx::func +#define LUCENE_DISABLE_HASHING //we could enable this, but so far test show that the hashing is slower :( + +//define the file functions +#define fileSeek lseek +#define fileSize _filelength +#define fileStat stat +#define fileHandleStat fstat +#ifdef _CL_HAVE_TELL + #define fileTell tell +#else + //ftell (and probably soon ftell64) are POSIX standard functions, but tell and + //tell64 are not, so we define fileTell in terms of fileSeek. + #define fileTell(fhandle) fileSeek(fhandle, 0, SEEK_CUR) +#endif + +//this is needed early on so that CL_MAX_PATH can be correctly determined +//in the StdHeader.h. This was earlier causing problems with macosx. +//:: crash was due to realpath() that expects an output arguments that +//has at least the size of PATH_MAX (even if the result has a lower size) +#include + +#ifndef _CL_HAVE_WCHAR_T + typedef unsigned short wchar_t; +#endif + +#if defined(__CYGWIN__) + //cygwin seems to incorrectly define that it has wprintf??? + #undef _CL_HAVE_WPRINTF +#elif defined(__MINGW32__) + #ifndef _CL_HAVE_WINDOWS_H + #define _CL_HAVE_WINDOWS_H + #endif +#endif + + +/////////////////////////////////////////////////////////////////////////////// +//end _lucene_COMPILER_GCC1 +#elif !defined(_lucene_COMPILER_GCC2) +#define _lucene_COMPILER_GCC2 + //second inclusion + + //types + #if defined(_CL_HAVE_SYS_TYPES_H) + #include + #endif + #if defined(_CL_HAVE_INTTYPES_H) + #include + #elif defined(_CL_HAVE_STDINT_H) + #include + #else + #if _CL_SIZEOF_UNSIGNED_LONG_LONG==8 + typedef unsigned long long uint64_t; + typedef long long int64_t; + #elif _CL_SIZEOF_UNSIGNED_LONG==8 + typedef unsigned long uint64_t; + typedef long int64_t; + #else + #error I do not know what to use for a uint64_t. + #endif + + /* Give us an unsigned 32-bit data type. */ + #if _CL_SIZEOF_UNSIGNED_LONG==4 + typedef unsigned long uint32_t; + typedef long int32_t; + #elif _CL_SIZEOF_UNSIGNED_INT==4 + typedef unsigned int uint32_t; + typedef int int32_t; + #else + #error I do not know what to use for a uint32_t. + #endif + + /* An unsigned 8-bit data type */ + #if _CL_SIZEOF_UNSIGNED_CHAR==1 + typedef unsigned char uint8_t; + #else + #error I do not know what to use for a uint8_t. + #endif + #endif + + //second chance to fix default settings + //this must be defined later, otherwise it messes up + //the standard libraries + #if !defined(__MINGW32__) + #define _close ::close + #define _read ::read + #endif + + //now that int64_t is defined, we can define this... + #ifndef _CL_HAVE_FILELENGTH + #undef fileSize + #define fileSize lucene_filelength + int64_t lucene_filelength(int handle); + #endif + +#elif !defined(_lucene_COMPILER_GCC3) +#define _lucene_COMPILER_GCC3 + //third inclusion + + #if !defined(__MINGW32__) + //define replacements + #define O_RANDOM 0 + #undef O_BINARY + #define O_BINARY 0 + #define _S_IREAD 0444 + #define _S_IWRITE 0333 // write and execute permissions + + //some functions that are needed - not charset dependent and not tchar type functions + #define _open open + #define _write write + #define _snprintf snprintf + + //clucene uses ascii for filename interactions + #define _realpath(rel,abs) realpath(rel,abs) + #define _mkdir(x) mkdir(x,0777) + #define _unlink unlink + #else + #define _realpath(rel,abs) _fullpath(abs,rel,CL_MAX_PATH) + #endif + //also required by mingw + #define _rename rename +#endif + +#if defined(__GNUC__) && (defined(__sgi) || (defined(Q_OS_SOLARIS) && Q_SOLARIS_VERSION < 10)) + #undef _CL_HAVE_FLOAT_T +#endif + +#if defined(__GNUC__) && defined(Q_OS_SOLARIS) && Q_SOLARIS_VERSION < 10 + #undef _CL_HAVE_WCSTOLL +#endif diff --git a/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h b/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h new file mode 100644 index 0000000..0021ea3 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/CompilerMsvc.h @@ -0,0 +1,136 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#if !defined(_lucene_COMPILER_MSVC) +#define _lucene_COMPILER_MSVC + +// It is internal CLucene header - DO NOT include it directly + +#include "CLucene/config/define_std.h" + +#if (_MSC_VER >= 1300) +//>= 7.0 + #if defined(_BUILD_FOR_QT_) + # pragma warning(disable: 4100) // disable unreferenced formal parameter + # pragma warning(disable: 4189) // disable local variable is initialized but not referenced + #endif + # pragma warning(disable: 4512) // This would be very annoying + # pragma warning(disable: 4290) // Ignore exception specification warning + # pragma warning(disable: 4250) // Ignore 'class1' : inherits 'class2::member' via dominance (e.g. in MultiReader) + // Check for STLport presence + #include + #if (_MSC_VER < 1310) || defined(_STLPORT_VERSION) + #define CL_NS_HASHING(func) std::func //the namespace is different on VC 7.0 + #else + #define CL_NS_HASHING(func) stdext::func + #endif + #define LUCENE_STATIC_CONSTANT_SYNTAX 1 + + #if _MSC_FULL_VER >= 140050320 + #define _CL_DEPRECATE_TEXT(_Text) __declspec(deprecated(_Text)) + #else + #define _CL_DEPRECATE_TEXT(_Text) __declspec(deprecated) + #endif + +#elif (_MSC_VER >= 1200) +//6.0 +#ifdef LUCENE_ENABLE_MEMLEAKTRACKING + #define _CLDELETE_CARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((void*)x,__FILE__,__LINE__);delete[] __CONST_CAST(TCHAR*,x); x=NULL;} + #define _CLDELETE_CaARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((void*)x,__FILE__,__LINE__);delete[] __CONST_CAST(char*,x); x=NULL;} + #define _CLDELETE_LCARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((void*)x,__FILE__,__LINE__);delete[] __CONST_CAST(TCHAR*,x);} + #define _CLDELETE_LCaARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((void*)x,__FILE__,__LINE__);delete[] __CONST_CAST(char*,x);} +#else + #define _CLDELETE_CARRAY(x) if (x!=NULL){delete[] __CONST_CAST(TCHAR*,x); x=NULL;} + #define _CLDELETE_CaARRAY(x) if (x!=NULL){delete[] __CONST_CAST(char*,x); x=NULL;} + #define _CLDELETE_LCARRAY(x) if (x!=NULL){delete[] __CONST_CAST(TCHAR*,x);} + #define _CLDELETE_LCaARRAY(x) if (x!=NULL){delete[] __CONST_CAST(char*,x);} + +#endif + #define LUCENE_STATIC_CONSTANT_SYNTAX 2 + + # pragma warning(disable: 4786) // This would be very annoying + namespace std{ + # undef min // just in case + # undef max // just in case + + #define min(a,b) (a>b?b:a) + #define max(a,b) (a>b?a:b) + } + + //only 7.0+ has these function + #undef _CL_HAVE_LLTOA + #undef _CL_HAVE_LLTOAW + #undef _CL_HAVE_INTPTR_T + #undef _CL_HAVE_WCSTOLL + #undef _CL_HAVE_STRTOLL + #undef _CL_HAVE_HASH_MAP + #undef _CL_HAVE_HASH_SET + +#else +# error "This version of MSVC has not been tested. Please uncomment this line to try anyway. Please send a report to the Clucene's administration if successful" +#endif + +#if _MSC_VER >= 1020 + #define _LUCENE_PRAGMA_ONCE +#endif +#define _LUCENE_PRAGMA_WARNINGS //tell lucene to display warnings using pragmas instead of #warning + +//if we are compiling using single-threaded libraries, we can disable multi-threading stuff +#if !defined(_MT) && !defined(_CL_DISABLE_MULTITHREADING) + #define _CL_DISABLE_MULTITHREADING +#endif + +//msvc supports large files +#ifdef _LARGE_FILES +# define fileSize _filelengthi64 +# define fileSeek _lseeki64 +# define fileTell _telli64 +# define fileStat _stati64 +# define fileHandleStat _fstati64 +#else +# define fileSize _filelength +# define fileSeek _lseek +# define fileTell _tell +# define fileStat _stat +# define fileHandleStat _fstat +#endif + +//_rename is not defined??? +#define _rename rename + +#define CL_MAX_PATH 260 //give the windef.h value for this... +#define _realpath(rel,abs) _fullpath(abs,rel,CL_MAX_PATH) + +//java long type +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +//java int type +typedef int int32_t; +typedef unsigned int uint32_t; + +//java byte type +typedef unsigned char uint8_t; + +//floating point type +//we are going to use qreal now +//typedef double float_t; + +#define _CL_ILONG(x) x ## L +#define _ILONGLONG(x) x ## i64 + + +#elif !defined(_lucene_COMPILER_MSVC2) +#define _lucene_COMPILER_MSVC2 + //second inclusion + + +#elif !defined(_lucene_COMPILER_MSVC3) +#define _lucene_COMPILER_MSVC3 + //third inclusion +#endif diff --git a/3rdparty/clucene/src/CLucene/config/PlatformMac.h b/3rdparty/clucene/src/CLucene/config/PlatformMac.h new file mode 100644 index 0000000..9f6d6f4 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/PlatformMac.h @@ -0,0 +1,19 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +// It is internal CLucene header - DO NOT include it directly + +# define PATH_DELIMITER _T("/") +# define PATH_DELIMITERA "/" +# define PATH_DELIMITERC '/' + +# if (__GNUC__ < 3) && !defined( __APPLE_CC__) +// GCC strange "ignore std" mode works better if you pretend everything +// is in the std namespace, for the most part. +# define LUCENE_NO_STDC_NAMESPACE +# endif + +#undef _T //apple has something else strange here... diff --git a/3rdparty/clucene/src/CLucene/config/PlatformUnix.h b/3rdparty/clucene/src/CLucene/config/PlatformUnix.h new file mode 100644 index 0000000..202a894 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/PlatformUnix.h @@ -0,0 +1,12 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +// It is internal CLucene header - DO NOT include it directly + +# define PATH_DELIMITER _T("/") +# define PATH_DELIMITERA "/" +# define PATH_DELIMITERC '/' + diff --git a/3rdparty/clucene/src/CLucene/config/PlatformWin32.h b/3rdparty/clucene/src/CLucene/config/PlatformWin32.h new file mode 100644 index 0000000..8b8a113 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/PlatformWin32.h @@ -0,0 +1,11 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +// It is internal CLucene header - DO NOT include it directly + +# define PATH_DELIMITER _T("\\") +# define PATH_DELIMITERA "\\" +# define PATH_DELIMITERC '\\' diff --git a/3rdparty/clucene/src/CLucene/config/compiler.h b/3rdparty/clucene/src/CLucene/config/compiler.h new file mode 100644 index 0000000..68f93b6 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/compiler.h @@ -0,0 +1,259 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#if !defined(lucene_compiler_h) +#define lucene_compiler_h + +#if defined(_MBCS) || defined(_ASCII) +#undef _ASCII +#undef _UCS2 +#define _ASCII +#elif defined(_UNICODE) +#define _UCS2 +#elif !defined(_UCS2) +#define _UCS2 +#endif + +//msvc needs unicode define so that it uses unicode library +#ifdef _UCS2 +#undef _UNICODE +#define _UNICODE +#undef _ASCII +#else +#undef _UNICODE +#undef _UCS2 +#endif + + +//////////////////////////////////////////////////////////////////// +// Figure out what compiler we are using +//////////////////////////////////////////////////////////////////// + +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined (__COMO__) +#define _CLCOMPILER_MSVC _MSC_VER +#endif + +#if defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__xlC__) || defined(__sgi) && defined(__EDG__) +#include "CLucene/config/CompilerGcc.h" + +#elif defined(_CLCOMPILER_MSVC) +/* Microsoft Visual C++ */ +#include "CLucene/config/CompilerMsvc.h" + +#elif defined (__BORLANDC__) +#include "CLucene/config/CompilerBcb.h" + +#elif defined (__HP_aCC) +#include "CLucene/config/CompilerAcc.h" + +#else + //Unable to identify the compiler, issue error diagnostic. + //Edit to set STLport up for your compiler. + //Uncomment this next line +#error "Unable to identify the compiler, issue error diagnostic. Edit to set Lucene up for your compiler." +#include "CLucene/config/LuceneMycomp.h" +#endif /* end of compiler choice */ +//////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////// +// Now include platform specific definitions +//////////////////////////////////////////////////////////////////// + +/* Operating system recognition (basic) */ +#if defined (__unix) || defined (__linux__) || defined (__QNX__) || defined (_AIX) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__Lynx__) || defined(hpux) || defined(__hpux) +#undef _UNIX +#define _UNIX 1 +#include "CLucene/config/PlatformUnix.h" + +#elif defined(macintosh) || defined (_MAC) || defined(__APPLE__) +#undef _MAC +#define _MAC 1 +#include "CLucene/config/PlatformMac.h" + +#elif defined (_WIN32) || defined (__WIN32) || defined (WIN32) || defined (__WIN32__) +#undef _WIN32 +#define _WIN32 +#include "CLucene/config/PlatformWin32.h" + +#elif defined (__WIN16) || defined (WIN16) || defined (_WIN16) +#undef _WIN16 +#define _WIN16 +#error "CLucene has not been tested on this platform. Please send a report to the lucene administrators if you are able to successfully compile" +#else +#error "CLucene could not identify the platform." +#endif /* platforms */ + + + +//////////////////////////////////////////////////////////////////// +// Now we take all that we have learnt, and define some things +//////////////////////////////////////////////////////////////////// + +//lets just say that we can always do unicode! :) +#ifdef CL_CHARSET_GUESS +#define _UCS2 +#endif + +#if defined(_ASCII) +#undef _UCS2 +#elif defined(_UCS2) +#undef _ASCII +#endif + +#ifndef _LUCENE_NO_NEW_STYLE_CASTS +#define __CONST_CAST(typ,var) const_cast(var) +#define __REINTERPRET_CAST(typ,var) reinterpret_cast(var) +#else +#define __CONST_CAST(typ,var) ((typ)(var)) +#define __REINTERPRET_CAST,var) ((typ)(var)) +#endif + +#ifndef _CL_DEPRECATE_TEXT +#define _CL_DEPRECATE_TEXT(_Text) +#endif +#define _CL_DEPRECATED(_NewItem) _CL_DEPRECATE_TEXT("This function or variable has been superceded by newer library or operating system functionality. Consider using" #_NewItem "instead. See online help for details.") + + +//cnd-debug exit command +#ifndef debugFatalExit +#define debugFatalExit(ret) exit(ret) +#endif + +#ifndef _CL_ILONG +#define _CL_ILONG(x) x ## L +#endif +#ifndef _ILONGLONG +#define _ILONGLONG(x) x ## LL +#endif + +//define whats the values of item intergers *should* be. we can check this in a test +#define LUCENE_INT64_MAX_SHOULDBE _ILONGLONG(0x7FFFFFFFFFFFFFFF) +#define LUCENE_INT32_MAX_SHOULDBE 0x7FFFFFFFL +#define LUCENE_UINT8_MAX_SHOULDBE 0xff + +//maximum path length. only used for buffers that use fullpath. +//anything else should use a dynamic length. +#if defined(CL_MAX_PATH) +//do nothing... +#elif defined(PATH_MAX) +#define CL_MAX_PATH PATH_MAX +#elif defined(MAX_PATH) +#define CL_MAX_PATH MAX_PATH +#elif defined(_MAX_PATH) +#define CL_MAX_PATH _MAX_PATH +#else + #error "CL_MAX_PATH could not be determined" +#endif + +//this is the max filename... for now its just the same, +//but this could change, so we use a different name +#define CL_MAX_NAME CL_MAX_PATH +//this used to be CL_MAX_NAME * 32, but as Alex Hudson points out, this could come to be 128kb. +//the above logic for CL_MAX_NAME should be correct enough to handle all file names +#define CL_MAX_DIR CL_MAX_PATH + +#ifdef _LARGE_FILES +#define LUCENE_MAX_FILELENGTH LUCENE_INT64_MAX_SHOULDBE +#else +#define LUCENE_MAX_FILELENGTH LUCENE_INT32_MAX_SHOULDBE +#endif + +//use the LUCENE_STATIC_CONSTANT_SYNTAX to determine LUCENE_STATIC_CONSTANT +#ifndef LUCENE_STATIC_CONSTANT + //autoconf is not properly detecting the correct method for this, and since there's no real big + //harm in always using an enum, we'll probably just make this the default. + /*#if LUCENE_STATIC_CONSTANT_SYNTAX == 1 + #define LUCENE_STATIC_CONSTANT(type, assignment) static const type assignment + #elif LUCENE_STATIC_CONSTANT_SYNTAX == 2*/ + #define LUCENE_STATIC_CONSTANT(type, assignment) enum { assignment } + /*#else + #error "LUCENE_STATIC_CONSTANT not defined, and/or LUCENE_STATIC_CONSTANT_SYNTAX is not defined to a valid value" + #endif*/ +#endif + +//end of lucene_compiler_h +#elif !defined(lucene_compiler_h2) +#define lucene_compiler_h2 +//here we include the compiler header again, this gives the header a +//second chance at including stuff, after the main inclusions are complete + +#if defined (__GNUC__) || defined(__SUNPRO_CC) || defined(__xlC__) || defined(__sgi) && defined(__EDG__) +#include "CLucene/config/CompilerGcc.h" + +#elif defined(_CLCOMPILER_MSVC) +/* Microsoft Visual C++ */ +#include "CLucene/config/CompilerMsvc.h" + +#elif defined __BORLANDC__ +#include "CLucene/config/CompilerBcb.h" + +#elif defined (__HP_aCC) +#include "CLucene/config/CompilerAcc.h" + +#else +//Unable to identify the compiler, issue error diagnostic. +//Edit to set STLport up for your compiler. +//Uncomment this next line +#error "Unable to identify the compiler, issue error diagnostic. Edit to set Lucene up for your compiler." +#include "CLucene/config/LuceneMycomp.h" +#endif /* end of compiler choice */ + +#ifndef _CL_HAVE_FLOAT_T +//#ifdef _CL_HAVE_LONG_DOUBLE +// long double's are not working (reported by Mark Ashworth on Solaris 64) +// typedef long double float_t; /* `float' expressions are evaluated as `long double'. */ +//#else +// we are going to use qreal now +// typedef double float_t; +//#endif +#endif + +/*todo: but need to define SIZEOF_VOID_P #if (SIZEOF_VOID_P > 4 && SIZEOF_VOID_P <= 8) +#ifndef _CL_HAVE_INTPTR_T + typedef int64_t intptr_t; +#endif +#elif (SIZEOF_VOID_P > 2 && SIZEOF_VOID_P <= 4) +# ifndef _CL_HAVE_INTPTR_T + typedef int32_t intptr_t; +# endif +#else +#error "void * is either >8 bytes or <= 2. In either case, I am confused." +#endif*/ + +#ifndef _CL_HAVE_INTPTR_T + typedef int intptr_t; +#endif + +//end of lucene_compiler_h2 +#elif !defined(lucene_compiler_h3) +#define lucene_compiler_h3 +//here we include the compiler header again, this gives the header a +//third chance at including stuff, after the main inclusions are complete + +#if defined (__GNUC__ ) || defined(__SUNPRO_CC) || defined(__xlC__) || defined(__sgi) && defined(__EDG__) +#include "CLucene/config/CompilerGcc.h" + +#elif defined(_CLCOMPILER_MSVC) +/* Microsoft Visual C++ */ +#include "CLucene/config/CompilerMsvc.h" + +#elif defined __BORLANDC__ +#include "CLucene/config/CompilerBcb.h" + +#elif defined (__HP_aCC) +#include "CLucene/config/CompilerAcc.h" + +#else +//Unable to identify the compiler, issue error diagnostic. +//Edit to set STLport up for your compiler. +//Uncomment this next line +#error "Unable to identify the compiler, issue error diagnostic. Edit to set Lucene up for your compiler." +#include "CLucene/config/LuceneMycomp.h" +#endif /* end of compiler choice */ + +#endif diff --git a/3rdparty/clucene/src/CLucene/config/define_std.h b/3rdparty/clucene/src/CLucene/config/define_std.h new file mode 100644 index 0000000..22a0790 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/define_std.h @@ -0,0 +1,113 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef lucene_define_std +#define lucene_define_std +//define a standard list of defines. +//These defines represents a fairly complete compiler. +//Of course it is preferable to use the autoconf generated +//list, but then not all systems can do this :) + +//we support long files - 64 bit file functions +#define _LARGE_FILES + +//support namespaces +#define _CL_HAVE_NAMESPACES + +//support try/catch blocks +#define _CL_HAVE_FUNCTION_TRY_BLOCKS + +//the normal headers +#define _CL_STDC_HEADERS +#define _CL_HAVE_STDARG_H +#define _CL_HAVE_ALGORITHM +#define _CL_HAVE_FUNCTIONAL +#define _CL_HAVE_MATH_H +#define _CL_HAVE_STL +#define _CL_HAVE_HASH_MAP +#define _CL_HAVE_HASH_SET +#define _CL_HAVE_MAP +#define _CL_HAVE_SET +#define _CL_HAVE_LIST +#define _CL_HAVE_VECTOR +#define _CL_HAVE_STDEXCEPT +#define _CL_HAVE_ERRNO_H +#define _CL_HAVE_SYS_STAT_H +#define _CL_HAVE_FCNTL_H + +//character & std tchar support +#define _CL_HAVE_TCHAR_H +#ifdef _UCS2 + #define _CL_HAVE_WCTYPE_H + + #define _CL_HAVE_WCSCPY + #define _CL_HAVE_WCSNCPY + #define _CL_HAVE_WCSCAT + #define _CL_HAVE_WCSCHR + #define _CL_HAVE_WCSSTR + #define _CL_HAVE_WCSLEN + #define _CL_HAVE_WCSCMP + #define _CL_HAVE_WCSNCMP + #define _CL_HAVE_WCSCSPN +#else + #define _CL_HAVE_CTYPE_H +#endif + +//already have the normal structures +#define _CL_HAVE_FLOAT_T +#define _CL_HAVE_INTPTR_T + +//system dependant: +#define _CL_HAVE_STRING_H //could be HAVE_STRINGS_H && HAVE_STRCHR +#define _CL_HAVE_SYS_TIMEB_H +#define _CL_HAVE_TIME_H + +#if defined (_WIN32) || defined (__WIN32) || defined (WIN32) || defined (__WIN32__) + #define _CL_HAVE_IO_H + #define _CL_HAVE_DIRECT_H + #define _CL_HAVE_WINDOWS_H +#else + #define _CL_HAVE_UNISTD_H +#endif +#ifdef UNDER_CE +#undef _CL_HAVE_SYS_TIMEB_H +#endif + +//////////////////////////////////////////////// +//now for individual functions. some compilers +//miss these, so must individually define what +//we have +//////////////////////////////////////////////// + +//string functions +#define _CL_HAVE_STRLWR +#define _CL_HAVE_WCSLWR +#define _CL_HAVE_WCSCASECMP +#define _CL_HAVE_STRCASECMP + +//formatting functions +#define _CL_HAVE_SNWPRINTF +#define _CL_HAVE_VSNWPRINTF +#define _CL_HAVE_WPRINTF +#define _CL_HAVE_SNPRINTF +#define _CL_HAVE_PRINTF + + +//conversion functions +#define _CL_HAVE_STRTOLL +#define _CL_HAVE_WCSTOLL +#define _CL_HAVE_WCSTOD +#define _CL_HAVE_LLTOA +#define _CL_HAVE_LLTOW +#define _CL_HAVE_INTPTR_T + +//these ones are not standard (msvc) +//so you will probably need to undefine +//if you are not using msvc +#define _CL_HAVE_FILELENGTH + + +#endif diff --git a/3rdparty/clucene/src/CLucene/config/gunichartables.cpp b/3rdparty/clucene/src/CLucene/config/gunichartables.cpp new file mode 100644 index 0000000..5463936 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/gunichartables.cpp @@ -0,0 +1,386 @@ +/* + * Copyright (C) 1999 Tom Tromey + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * + ************************************************ + * Also licensed with permission from Tom Tromey + * and Owen Taylor under the Apache license. + * Original location: + * http://cvs.gnome.org/viewcvs/glib/glib/guniprop.c?view=log + ************************************************ + * + * Copyright 2003-2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ + +#include "CLucene/StdHeader.h" + +typedef unsigned long gunichar; +typedef unsigned short guint16; +typedef short gint16; +typedef char gchar; +typedef unsigned char guchar; + +/* These are the possible character classifications. + * See http://www.unicode.org/Public/UNIDATA/UnicodeData.txt + or http://www.unicode.org/Public/UNIDATA/UCD.html. + + todo: i think there is a new version of the unicode, which we should use. + data is licensed like this: http://www.unicode.org/copyright.html... not sure but looks apache compatible + */ +typedef enum +{ + G_UNICODE_CONTROL, + G_UNICODE_FORMAT, + G_UNICODE_UNASSIGNED, + G_UNICODE_PRIVATE_USE, + G_UNICODE_SURROGATE, + G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER, + G_UNICODE_TITLECASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_COMBINING_MARK, + G_UNICODE_ENCLOSING_MARK, + G_UNICODE_NON_SPACING_MARK, + G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_LETTER_NUMBER, + G_UNICODE_OTHER_NUMBER, + G_UNICODE_CONNECT_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_FINAL_PUNCTUATION, + G_UNICODE_INITIAL_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, + G_UNICODE_LINE_SEPARATOR, + G_UNICODE_PARAGRAPH_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR +} GUnicodeType; + + +#include "gunichartables.h" + +#define ATTR_TABLE(Page) (((Page) <= G_UNICODE_LAST_PAGE_PART1) \ + ? attr_table_part1[Page] \ + : attr_table_part2[(Page) - 0xe00]) + +#define ATTTABLE(Page, Char) \ + ((ATTR_TABLE(Page) == G_UNICODE_MAX_TABLE_INDEX) ? 0 : (attr_data[ATTR_TABLE(Page)][Char])) + + +#define TTYPE_PART1(Page, Char) \ + ((type_table_part1[Page] >= G_UNICODE_MAX_TABLE_INDEX) \ + ? (type_table_part1[Page] - G_UNICODE_MAX_TABLE_INDEX) \ + : (type_data[type_table_part1[Page]][Char])) + +#define TTYPE_PART2(Page, Char) \ + ((type_table_part2[Page] >= G_UNICODE_MAX_TABLE_INDEX) \ + ? (type_table_part2[Page] - G_UNICODE_MAX_TABLE_INDEX) \ + : (type_data[type_table_part2[Page]][Char])) + +#define TYPE(Char) \ + (((Char) <= G_UNICODE_LAST_CHAR_PART1) \ + ? TTYPE_PART1 ((Char) >> 8, (Char) & 0xff) \ + : (((Char) >= 0xe0000 && (Char) <= G_UNICODE_LAST_CHAR) \ + ? TTYPE_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \ + : G_UNICODE_UNASSIGNED)) + +/* Count the number of elements in an array. The array must be defined + * as such; using this with a dynamically allocated array will give + * incorrect results. + */ +#define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) + + + + +#if defined(LUCENE_USE_INTERNAL_CHAR_FUNCTIONS) +#ifdef _LUCENE_PRAGMA_WARNINGS + #pragma message ("===== Using internal character function =====") +#else +#if !(defined(Q_OS_SOLARIS) || defined(Q_CC_MIPS)) +#warning "===== Using internal character function =====" +#endif +#endif + +bool cl_isletter(gunichar c) +{ + int t = TYPE (c); + switch(t) + { + case G_UNICODE_LOWERCASE_LETTER: return true; + case G_UNICODE_TITLECASE_LETTER: return true; + case G_UNICODE_UPPERCASE_LETTER: return true; + case G_UNICODE_MODIFIER_LETTER: return true; + case G_UNICODE_OTHER_LETTER: return true; + default: return false; + } +} + +bool cl_isalnum(gunichar c) +{ + int t = TYPE (c); + switch(t) + { + case G_UNICODE_LOWERCASE_LETTER: return true; + case G_UNICODE_TITLECASE_LETTER: return true; + case G_UNICODE_UPPERCASE_LETTER: return true; + case G_UNICODE_MODIFIER_LETTER: return true; + case G_UNICODE_OTHER_LETTER: return true; + case G_UNICODE_DECIMAL_NUMBER: return true; + case G_UNICODE_LETTER_NUMBER: return true; + case G_UNICODE_OTHER_NUMBER: return true; + default: return false; + } +} + +bool cl_isdigit(gunichar c) +{ + int t = TYPE (c); + switch(t) + { + case G_UNICODE_DECIMAL_NUMBER: return true; + case G_UNICODE_LETTER_NUMBER: return true; + case G_UNICODE_OTHER_NUMBER: return true; + default: return false; + } +} + +/** + * cl_isspace: + * @c: a Unicode character + * + * Determines whether a character is a space, tab, or line separator + * (newline, carriage return, etc.). Given some UTF-8 text, obtain a + * character value with lucene_utf8towc(). + * + * (Note: don't use this to do word breaking; you have to use + * Pango or equivalent to get word breaking right, the algorithm + * is fairly complex.) + * + * Return value: %TRUE if @c is a punctuation character + **/ +bool cl_isspace (gunichar c) +{ + switch (c) + { + /* special-case these since Unicode thinks they are not spaces */ + case '\t': + case '\n': + case '\r': + case '\f': + return true; + + default: + { + int t = TYPE ((gunichar)c); + return (t == G_UNICODE_SPACE_SEPARATOR || t == G_UNICODE_LINE_SEPARATOR + || t == G_UNICODE_PARAGRAPH_SEPARATOR); + } + } +} + + + +/** + * cl_tolower: + * @c: a Unicode character. + * + * Converts a character to lower case. + * + * Return value: the result of converting @c to lower case. + * If @c is not an upperlower or titlecase character, + * or has no lowercase equivalent @c is returned unchanged. + **/ +TCHAR cl_tolower (TCHAR ch) +{ + gunichar c=ch; + int t = TYPE ((gunichar)c); + if (t == G_UNICODE_UPPERCASE_LETTER) + { + gunichar val = ATTTABLE (c >> 8, c & 0xff); + if (val >= 0x1000000) + { + const gchar *p = special_case_table + val - 0x1000000; + int len=0; + wchar_t ret=0; + lucene_utf8towc(&ret,p,6); +#ifdef _UCS2 + return ret; +#else + return LUCENE_OOR_CHAR(ret); +#endif + //return cl_utf8_get_char (p, &len); + }else + return val ? val : c; + }else if (t == G_UNICODE_TITLECASE_LETTER){ + unsigned int i; + for (i = 0; i < G_N_ELEMENTS (title_table); ++i) + { + if (title_table[i][0] == c) + return title_table[i][2]; + } + } + return c; +} + +/** + * cl_toupper: + * @c: a Unicode character + * + * Converts a character to uppercase. + * + * Return value: the result of converting @c to uppercase. + * If @c is not an lowercase or titlecase character, + * or has no upper case equivalent @c is returned unchanged. + **/ +TCHAR cl_toupper (TCHAR ch) +{ + gunichar c=ch; + int t = TYPE (c); + if (t == G_UNICODE_LOWERCASE_LETTER) + { + gunichar val = ATTTABLE (c >> 8, c & 0xff); + if (val >= 0x1000000) + { + const gchar *p = special_case_table + val - 0x1000000; + + wchar_t ret=0; + lucene_utf8towc(&ret,p,6); +#ifdef _UCS2 + return ret; +#else + return LUCENE_OOR_CHAR(ret); +#endif + //return lucene_utf8towc (p); + } + else + return val ? val : c; + } + else if (t == G_UNICODE_TITLECASE_LETTER) + { + unsigned int i; + for (i = 0; i < G_N_ELEMENTS (title_table); ++i) + { + if (title_table[i][0] == c) + return title_table[i][1]; + } + } + return c; +} + + + +/** + * cl_tcasefold: + * @str: a unicode string + * + * Converts a string into a form that is independent of case. The + * result will not correspond to any particular case, but can be + * compared for equality or ordered with the results of calling + * cl_tcasefold() on other strings. + * + * Note that calling cl_tcasefold() followed by g_utf8_collate() is + * only an approximation to the correct linguistic case insensitive + * ordering, though it is a fairly good one. Getting this exactly + * right would require a more sophisticated collation function that + * takes case sensitivity into account. GLib does not currently + * provide such a function. + * + * Return value: a newly allocated string, that is a + * case independent form of @str. + **/ +TCHAR cl_tcasefold(const TCHAR ch){ + int start = 0; + int end = G_N_ELEMENTS (casefold_table); + + if (ch >= casefold_table[start].ch && + ch <= casefold_table[end - 1].ch) + { + while (1) + { + int half = (start + end) / 2; + if (ch == casefold_table[half].ch) + { + wchar_t ret=0; + lucene_utf8towc(&ret,casefold_table[half].data,6); + + #ifdef _UCS2 + return ret; + #else + LUCENE_OOR_CHAR(ret) + #endif + }else if (half == start){ + break; + }else if (ch > casefold_table[half].ch){ + start = half; + }else{ + end = half; + } + } + } + return cl_tolower(ch); + +} + + +//this function was not taken from gnome +TCHAR* cl_tcscasefold( TCHAR * str, int len ) //len default is -1 +{ + TCHAR *p = str; + while ((len < 0 || p < str + len) && *p) + { + *p = cl_tcasefold(*p); + p++; + } + return str; +} +//this function was not taken from gnome +int cl_tcscasefoldcmp(const TCHAR * dst, const TCHAR * src){ + TCHAR f,l; + + do{ + f = cl_tcasefold( (*(dst++)) ); + l = cl_tcasefold( (*(src++)) ); + } while ( (f) && (f == l) ); + + return (int)(f - l); +} + +#endif diff --git a/3rdparty/clucene/src/CLucene/config/gunichartables.h b/3rdparty/clucene/src/CLucene/config/gunichartables.h new file mode 100644 index 0000000..182a870 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/gunichartables.h @@ -0,0 +1,11264 @@ +/* This file is automatically generated. DO NOT EDIT! + Instead, edit gen-unicode-tables.pl and re-run. */ + +#ifndef CHARTABLES_H +#define CHARTABLES_H + +#define G_UNICODE_DATA_VERSION "4.0" + +#define G_UNICODE_LAST_CHAR 0x10ffff + +#define G_UNICODE_MAX_TABLE_INDEX 10000 + +#define G_UNICODE_LAST_CHAR_PART1 0x2FAFF + +#define G_UNICODE_LAST_PAGE_PART1 762 + +static const char type_data[][256] = { + { /* page 0, index 0 */ + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_SPACE_SEPARATOR, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_MATH_SYMBOL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_CONTROL, + G_UNICODE_CONTROL, G_UNICODE_CONTROL, G_UNICODE_SPACE_SEPARATOR, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_INITIAL_PUNCTUATION, G_UNICODE_MATH_SYMBOL, G_UNICODE_FORMAT, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_OTHER_NUMBER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_FINAL_PUNCTUATION, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER + }, + { /* page 1, index 1 */ + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER + }, + { /* page 2, index 2 */ + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL + }, + { /* page 3, index 3 */ + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 4, index 4 */ + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_ENCLOSING_MARK, G_UNICODE_ENCLOSING_MARK, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 5, index 5 */ + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 6, index 6 */ + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_MODIFIER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_FORMAT, G_UNICODE_ENCLOSING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_LETTER + }, + { /* page 7, index 7 */ + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_FORMAT, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 9, index 8 */ + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_LETTER, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 10, index 9 */ + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 11, index 10 */ + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 12, index 11 */ + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 13, index 12 */ + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 14, index 13 */ + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_MODIFIER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 15, index 14 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 16, index 15 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 17, index 16 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 18, index 17 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER + }, + { /* page 19, index 18 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 20, index 19 */ + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER + }, + { /* page 22, index 20 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_SPACE_SEPARATOR, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 23, index 21 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_OTHER_LETTER, G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 24, index 22 */ + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_UNASSIGNED, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 25, index 23 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL + }, + { /* page 29, index 24 */ + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 30, index 25 */ + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 31, index 26 */ + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_TITLECASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_TITLECASE_LETTER, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_UNASSIGNED + }, + { /* page 32, index 27 */ + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_SPACE_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_SPACE_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_SPACE_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_SPACE_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_SPACE_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_SPACE_SEPARATOR, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_INITIAL_PUNCTUATION, G_UNICODE_FINAL_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_INITIAL_PUNCTUATION, + G_UNICODE_INITIAL_PUNCTUATION, G_UNICODE_FINAL_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_INITIAL_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_LINE_SEPARATOR, G_UNICODE_PARAGRAPH_SEPARATOR, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_SPACE_SEPARATOR, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_INITIAL_PUNCTUATION, G_UNICODE_FINAL_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_CONNECT_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_CONNECT_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_SPACE_SEPARATOR, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_OTHER_NUMBER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_ENCLOSING_MARK, G_UNICODE_ENCLOSING_MARK, + G_UNICODE_ENCLOSING_MARK, G_UNICODE_ENCLOSING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_ENCLOSING_MARK, + G_UNICODE_ENCLOSING_MARK, G_UNICODE_ENCLOSING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 33, index 28 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL + }, + { /* page 35, index 29 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 36, index 30 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER + }, + { /* page 37, index 31 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL + }, + { /* page 38, index 32 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 39, index 33 */ + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL + }, + { /* page 41, index 34 */ + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL + }, + { /* page 43, index 35 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 46, index 36 */ + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 47, index 37 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 48, index 38 */ + G_UNICODE_SPACE_SEPARATOR, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_LETTER_NUMBER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_LETTER_NUMBER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER + }, + { /* page 49, index 39 */ + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER + }, + { /* page 50, index 40 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED + }, + { /* page 77, index 41 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL + }, + { /* page 159, index 42 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 164, index 43 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 215, index 44 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 250, index 45 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 251, index 46 */ + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER + }, + { /* page 253, index 47 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 254, index 48 */ + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_CONNECT_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_CONNECT_PUNCTUATION, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_DASH_PUNCTUATION, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_FORMAT + }, + { /* page 255, index 49 */ + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OPEN_PUNCTUATION, G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_CONNECT_PUNCTUATION, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_MODIFIER_LETTER, G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_CURRENCY_SYMBOL, G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 256, index 50 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 257, index 51 */ + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 259, index 52 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_NUMBER, + G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, G_UNICODE_OTHER_NUMBER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_LETTER_NUMBER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_PUNCTUATION, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 260, index 53 */ + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 264, index 54 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 464, index 55 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 465, index 56 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, + G_UNICODE_COMBINING_MARK, G_UNICODE_COMBINING_MARK, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 467, index 57 */ + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, G_UNICODE_OTHER_SYMBOL, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 468, index 58 */ + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER + }, + { /* page 469, index 59 */ + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER + }, + { /* page 470, index 60 */ + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_MATH_SYMBOL, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER + }, + { /* page 471, index 61 */ + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_MATH_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_MATH_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_MATH_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_MATH_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_MATH_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, G_UNICODE_MATH_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_MATH_SYMBOL, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_LOWERCASE_LETTER, G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_DECIMAL_NUMBER, G_UNICODE_DECIMAL_NUMBER + }, + { /* page 678, index 62 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 762, index 63 */ + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, G_UNICODE_OTHER_LETTER, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 3584, index 64 */ + G_UNICODE_UNASSIGNED, G_UNICODE_FORMAT, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_FORMAT, G_UNICODE_FORMAT, G_UNICODE_FORMAT, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED + }, + { /* page 3585, index 65 */ + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_NON_SPACING_MARK, G_UNICODE_NON_SPACING_MARK, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 4095, index 66 */ + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + }, + { /* page 4351, index 67 */ + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, + G_UNICODE_PRIVATE_USE, G_UNICODE_PRIVATE_USE, G_UNICODE_UNASSIGNED, + G_UNICODE_UNASSIGNED + } +}; + +/* U+0000 through U+2FAFF */ +static const gint16 type_table_part1[763] = { + 0 /* page 0 */, + 1 /* page 1 */, + 2 /* page 2 */, + 3 /* page 3 */, + 4 /* page 4 */, + 5 /* page 5 */, + 6 /* page 6 */, + 7 /* page 7 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + 8 /* page 9 */, + 9 /* page 10 */, + 10 /* page 11 */, + 11 /* page 12 */, + 12 /* page 13 */, + 13 /* page 14 */, + 14 /* page 15 */, + 15 /* page 16 */, + 16 /* page 17 */, + 17 /* page 18 */, + 18 /* page 19 */, + 19 /* page 20 */, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 20 /* page 22 */, + 21 /* page 23 */, + 22 /* page 24 */, + 23 /* page 25 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + 24 /* page 29 */, + 25 /* page 30 */, + 26 /* page 31 */, + 27 /* page 32 */, + 28 /* page 33 */, + G_UNICODE_MATH_SYMBOL + G_UNICODE_MAX_TABLE_INDEX, + 29 /* page 35 */, + 30 /* page 36 */, + 31 /* page 37 */, + 32 /* page 38 */, + 33 /* page 39 */, + G_UNICODE_OTHER_SYMBOL + G_UNICODE_MAX_TABLE_INDEX, + 34 /* page 41 */, + G_UNICODE_MATH_SYMBOL + G_UNICODE_MAX_TABLE_INDEX, + 35 /* page 43 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + 36 /* page 46 */, + 37 /* page 47 */, + 38 /* page 48 */, + 39 /* page 49 */, + 40 /* page 50 */, + G_UNICODE_OTHER_SYMBOL + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 41 /* page 77 */, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 42 /* page 159 */, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 43 /* page 164 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 44 /* page 215 */, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_SURROGATE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 45 /* page 250 */, + 46 /* page 251 */, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 47 /* page 253 */, + 48 /* page 254 */, + 49 /* page 255 */, + 50 /* page 256 */, + 51 /* page 257 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + 52 /* page 259 */, + 53 /* page 260 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + 54 /* page 264 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + 55 /* page 464 */, + 56 /* page 465 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + 57 /* page 467 */, + 58 /* page 468 */, + 59 /* page 469 */, + 60 /* page 470 */, + 61 /* page 471 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 62 /* page 678 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_OTHER_LETTER + G_UNICODE_MAX_TABLE_INDEX, + 63 /* page 762 */ +}; + +/* U+E0000 through U+10FFFF */ +static const gint16 type_table_part2[768] = { + 64 /* page 3584 */, + 65 /* page 3585 */, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_UNASSIGNED + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + 66 /* page 4095 */, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + G_UNICODE_PRIVATE_USE + G_UNICODE_MAX_TABLE_INDEX, + 67 /* page 4351 */ +}; + +static const gunichar attr_data[][256] = { + { /* page 0, index 0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, + 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, + 0x007a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0041, 0x0042, + 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, + 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, + 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x039c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, + 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, + 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0000, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x1000000, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, + 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x00d0, 0x00d1, + 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0000, 0x00d8, 0x00d9, 0x00da, + 0x00db, 0x00dc, 0x00dd, 0x00de, 0x0178 + }, + { /* page 1, index 1 */ + 0x0101, 0x0100, 0x0103, 0x0102, 0x0105, 0x0104, 0x0107, 0x0106, 0x0109, + 0x0108, 0x010b, 0x010a, 0x010d, 0x010c, 0x010f, 0x010e, 0x0111, 0x0110, + 0x0113, 0x0112, 0x0115, 0x0114, 0x0117, 0x0116, 0x0119, 0x0118, 0x011b, + 0x011a, 0x011d, 0x011c, 0x011f, 0x011e, 0x0121, 0x0120, 0x0123, 0x0122, + 0x0125, 0x0124, 0x0127, 0x0126, 0x0129, 0x0128, 0x012b, 0x012a, 0x012d, + 0x012c, 0x012f, 0x012e, 0x1000007, 0x0049, 0x0133, 0x0132, 0x0135, + 0x0134, 0x0137, 0x0136, 0x0000, 0x013a, 0x0139, 0x013c, 0x013b, 0x013e, + 0x013d, 0x0140, 0x013f, 0x0142, 0x0141, 0x0144, 0x0143, 0x0146, 0x0145, + 0x0148, 0x0147, 0x1000086, 0x014b, 0x014a, 0x014d, 0x014c, 0x014f, + 0x014e, 0x0151, 0x0150, 0x0153, 0x0152, 0x0155, 0x0154, 0x0157, 0x0156, + 0x0159, 0x0158, 0x015b, 0x015a, 0x015d, 0x015c, 0x015f, 0x015e, 0x0161, + 0x0160, 0x0163, 0x0162, 0x0165, 0x0164, 0x0167, 0x0166, 0x0169, 0x0168, + 0x016b, 0x016a, 0x016d, 0x016c, 0x016f, 0x016e, 0x0171, 0x0170, 0x0173, + 0x0172, 0x0175, 0x0174, 0x0177, 0x0176, 0x00ff, 0x017a, 0x0179, 0x017c, + 0x017b, 0x017e, 0x017d, 0x0053, 0x0000, 0x0253, 0x0183, 0x0182, 0x0185, + 0x0184, 0x0254, 0x0188, 0x0187, 0x0256, 0x0257, 0x018c, 0x018b, 0x0000, + 0x01dd, 0x0259, 0x025b, 0x0192, 0x0191, 0x0260, 0x0263, 0x01f6, 0x0269, + 0x0268, 0x0199, 0x0198, 0x0000, 0x0000, 0x026f, 0x0272, 0x0220, 0x0275, + 0x01a1, 0x01a0, 0x01a3, 0x01a2, 0x01a5, 0x01a4, 0x0280, 0x01a8, 0x01a7, + 0x0283, 0x0000, 0x0000, 0x01ad, 0x01ac, 0x0288, 0x01b0, 0x01af, 0x028a, + 0x028b, 0x01b4, 0x01b3, 0x01b6, 0x01b5, 0x0292, 0x01b9, 0x01b8, 0x0000, + 0x0000, 0x01bd, 0x01bc, 0x0000, 0x01f7, 0x0000, 0x0000, 0x0000, 0x0000, + 0x01c6, 0x0000, 0x01c4, 0x01c9, 0x0000, 0x01c7, 0x01cc, 0x0000, 0x01ca, + 0x01ce, 0x01cd, 0x01d0, 0x01cf, 0x01d2, 0x01d1, 0x01d4, 0x01d3, 0x01d6, + 0x01d5, 0x01d8, 0x01d7, 0x01da, 0x01d9, 0x01dc, 0x01db, 0x018e, 0x01df, + 0x01de, 0x01e1, 0x01e0, 0x01e3, 0x01e2, 0x01e5, 0x01e4, 0x01e7, 0x01e6, + 0x01e9, 0x01e8, 0x01eb, 0x01ea, 0x01ed, 0x01ec, 0x01ef, 0x01ee, + 0x10000ad, 0x01f3, 0x0000, 0x01f1, 0x01f5, 0x01f4, 0x0195, 0x01bf, + 0x01f9, 0x01f8, 0x01fb, 0x01fa, 0x01fd, 0x01fc, 0x01ff, 0x01fe + }, + { /* page 2, index 2 */ + 0x0201, 0x0200, 0x0203, 0x0202, 0x0205, 0x0204, 0x0207, 0x0206, 0x0209, + 0x0208, 0x020b, 0x020a, 0x020d, 0x020c, 0x020f, 0x020e, 0x0211, 0x0210, + 0x0213, 0x0212, 0x0215, 0x0214, 0x0217, 0x0216, 0x0219, 0x0218, 0x021b, + 0x021a, 0x021d, 0x021c, 0x021f, 0x021e, 0x019e, 0x0000, 0x0223, 0x0222, + 0x0225, 0x0224, 0x0227, 0x0226, 0x0229, 0x0228, 0x022b, 0x022a, 0x022d, + 0x022c, 0x022f, 0x022e, 0x0231, 0x0230, 0x0233, 0x0232, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0181, 0x0186, 0x0000, 0x0189, 0x018a, 0x0000, 0x018f, + 0x0000, 0x0190, 0x0000, 0x0000, 0x0000, 0x0000, 0x0193, 0x0000, 0x0000, + 0x0194, 0x0000, 0x0000, 0x0000, 0x0000, 0x0197, 0x0196, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x019c, 0x0000, 0x0000, 0x019d, 0x0000, 0x0000, + 0x019f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x01a6, 0x0000, 0x0000, 0x01a9, 0x0000, 0x0000, 0x0000, + 0x0000, 0x01ae, 0x0000, 0x01b1, 0x01b2, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x01b7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 3, index 3 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03ac, + 0x0000, 0x03ad, 0x03ae, 0x03af, 0x0000, 0x03cc, 0x0000, 0x03cd, 0x03ce, + 0x100008f, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, + 0x03c1, 0x0000, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, + 0x03ca, 0x03cb, 0x0386, 0x0388, 0x0389, 0x038a, 0x100009e, 0x0391, + 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, + 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a3, 0x03a3, + 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x038c, + 0x038e, 0x038f, 0x0000, 0x0392, 0x0398, 0x0000, 0x0000, 0x0000, 0x03a6, + 0x03a0, 0x0000, 0x03d9, 0x03d8, 0x03db, 0x03da, 0x03dd, 0x03dc, 0x03df, + 0x03de, 0x03e1, 0x03e0, 0x03e3, 0x03e2, 0x03e5, 0x03e4, 0x03e7, 0x03e6, + 0x03e9, 0x03e8, 0x03eb, 0x03ea, 0x03ed, 0x03ec, 0x03ef, 0x03ee, 0x039a, + 0x03a1, 0x03f9, 0x0000, 0x03b8, 0x0395, 0x0000, 0x03f8, 0x03f7, 0x03f2, + 0x03fb, 0x03fa, 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 4, index 4 */ + 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, + 0x0459, 0x045a, 0x045b, 0x045c, 0x045d, 0x045e, 0x045f, 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, 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, 0x0400, + 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, + 0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f, 0x0461, 0x0460, 0x0463, + 0x0462, 0x0465, 0x0464, 0x0467, 0x0466, 0x0469, 0x0468, 0x046b, 0x046a, + 0x046d, 0x046c, 0x046f, 0x046e, 0x0471, 0x0470, 0x0473, 0x0472, 0x0475, + 0x0474, 0x0477, 0x0476, 0x0479, 0x0478, 0x047b, 0x047a, 0x047d, 0x047c, + 0x047f, 0x047e, 0x0481, 0x0480, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x048b, 0x048a, 0x048d, 0x048c, 0x048f, 0x048e, + 0x0491, 0x0490, 0x0493, 0x0492, 0x0495, 0x0494, 0x0497, 0x0496, 0x0499, + 0x0498, 0x049b, 0x049a, 0x049d, 0x049c, 0x049f, 0x049e, 0x04a1, 0x04a0, + 0x04a3, 0x04a2, 0x04a5, 0x04a4, 0x04a7, 0x04a6, 0x04a9, 0x04a8, 0x04ab, + 0x04aa, 0x04ad, 0x04ac, 0x04af, 0x04ae, 0x04b1, 0x04b0, 0x04b3, 0x04b2, + 0x04b5, 0x04b4, 0x04b7, 0x04b6, 0x04b9, 0x04b8, 0x04bb, 0x04ba, 0x04bd, + 0x04bc, 0x04bf, 0x04be, 0x0000, 0x04c2, 0x04c1, 0x04c4, 0x04c3, 0x04c6, + 0x04c5, 0x04c8, 0x04c7, 0x04ca, 0x04c9, 0x04cc, 0x04cb, 0x04ce, 0x04cd, + 0x0000, 0x04d1, 0x04d0, 0x04d3, 0x04d2, 0x04d5, 0x04d4, 0x04d7, 0x04d6, + 0x04d9, 0x04d8, 0x04db, 0x04da, 0x04dd, 0x04dc, 0x04df, 0x04de, 0x04e1, + 0x04e0, 0x04e3, 0x04e2, 0x04e5, 0x04e4, 0x04e7, 0x04e6, 0x04e9, 0x04e8, + 0x04eb, 0x04ea, 0x04ed, 0x04ec, 0x04ef, 0x04ee, 0x04f1, 0x04f0, 0x04f3, + 0x04f2, 0x04f5, 0x04f4, 0x0000, 0x0000, 0x04f9, 0x04f8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 5, index 5 */ + 0x0501, 0x0500, 0x0503, 0x0502, 0x0505, 0x0504, 0x0507, 0x0506, 0x0509, + 0x0508, 0x050b, 0x050a, 0x050d, 0x050c, 0x050f, 0x050e, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, + 0x0566, 0x0567, 0x0568, 0x0569, 0x056a, 0x056b, 0x056c, 0x056d, 0x056e, + 0x056f, 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057a, 0x057b, 0x057c, 0x057d, 0x057e, 0x057f, 0x0580, + 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0531, 0x0532, + 0x0533, 0x0534, 0x0535, 0x0536, 0x0537, 0x0538, 0x0539, 0x053a, 0x053b, + 0x053c, 0x053d, 0x053e, 0x053f, 0x0540, 0x0541, 0x0542, 0x0543, 0x0544, + 0x0545, 0x0546, 0x0547, 0x0548, 0x0549, 0x054a, 0x054b, 0x054c, 0x054d, + 0x054e, 0x054f, 0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, + 0x1000044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 6, index 6 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 9, index 7 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 10, index 8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 11, index 9 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 12, index 10 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 13, index 11 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 14, index 12 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 15, index 13 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 16, index 14 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 19, index 15 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 23, index 16 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 24, index 17 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, + 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 25, index 18 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, + 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 30, index 19 */ + 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, 0x10000b6, 0x10000bf, + 0x10000c8, 0x10000d1, 0x10000da, 0x1e60, 0x0000, 0x0000, 0x0000, 0x0000, + 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, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 31, index 20 */ + 0x1f08, 0x1f09, 0x1f0a, 0x1f0b, 0x1f0c, 0x1f0d, 0x1f0e, 0x1f0f, 0x1f00, + 0x1f01, 0x1f02, 0x1f03, 0x1f04, 0x1f05, 0x1f06, 0x1f07, 0x1f18, 0x1f19, + 0x1f1a, 0x1f1b, 0x1f1c, 0x1f1d, 0x0000, 0x0000, 0x1f10, 0x1f11, 0x1f12, + 0x1f13, 0x1f14, 0x1f15, 0x0000, 0x0000, 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, 0x0000, 0x0000, + 0x1f40, 0x1f41, 0x1f42, 0x1f43, 0x1f44, 0x1f45, 0x0000, 0x0000, + 0x10000e3, 0x1f59, 0x10000ee, 0x1f5b, 0x10000fd, 0x1f5d, 0x100010c, + 0x1f5f, 0x0000, 0x1f51, 0x0000, 0x1f53, 0x0000, 0x1f55, 0x0000, 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, 0x0000, 0x0000, 0x10001b7, 0x10001c4, 0x10001d1, + 0x10001de, 0x10001eb, 0x10001f8, 0x1000205, 0x1000212, 0x100021f, + 0x1000229, 0x1000233, 0x100023d, 0x1000247, 0x1000251, 0x100025b, + 0x1000265, 0x100026f, 0x100027c, 0x1000289, 0x1000296, 0x10002a3, + 0x10002b0, 0x10002bd, 0x10002ca, 0x10002d7, 0x10002e1, 0x10002eb, + 0x10002f5, 0x10002ff, 0x1000309, 0x1000313, 0x100031d, 0x1000327, + 0x1000334, 0x1000341, 0x100034e, 0x100035b, 0x1000368, 0x1000375, + 0x1000382, 0x100038f, 0x1000399, 0x10003a3, 0x10003ad, 0x10003b7, + 0x10003c1, 0x10003cb, 0x10003d5, 0x1fb8, 0x1fb9, 0x100041e, 0x10003df, + 0x100042b, 0x0000, 0x100011b, 0x1000466, 0x1fb0, 0x1fb1, 0x1f70, 0x1f71, + 0x10003eb, 0x0000, 0x0399, 0x0000, 0x0000, 0x0000, 0x1000436, 0x10003f4, + 0x1000443, 0x0000, 0x1000126, 0x1000475, 0x1f72, 0x1f73, 0x1f74, 0x1f75, + 0x1000400, 0x0000, 0x0000, 0x0000, 0x1fd8, 0x1fd9, 0x1000131, 0x1000140, + 0x0000, 0x0000, 0x100014f, 0x100015a, 0x1fd0, 0x1fd1, 0x1f76, 0x1f77, + 0x0000, 0x0000, 0x0000, 0x0000, 0x1fe8, 0x1fe9, 0x1000169, 0x1000178, + 0x1000187, 0x1fec, 0x1000192, 0x100019d, 0x1fe0, 0x1fe1, 0x1f7a, 0x1f7b, + 0x1fe5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x100044e, 0x1000409, + 0x100045b, 0x0000, 0x10001ac, 0x1000484, 0x1f78, 0x1f79, 0x1f7c, 0x1f7d, + 0x1000415, 0x0000, 0x0000, 0x0000 + }, + { /* page 33, index 21 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x03c9, 0x0000, 0x0000, 0x0000, 0x006b, 0x00e5, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 251, index 22 */ + 0x100000f, 0x1000016, 0x100001d, 0x1000024, 0x100002d, 0x1000036, + 0x100003d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x100004f, 0x100005a, 0x1000065, + 0x1000070, 0x100007b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000 + }, + { /* page 255, index 23 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, + 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 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, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 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, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 260, index 24 */ + 0x10428, 0x10429, 0x1042a, 0x1042b, 0x1042c, 0x1042d, 0x1042e, 0x1042f, + 0x10430, 0x10431, 0x10432, 0x10433, 0x10434, 0x10435, 0x10436, 0x10437, + 0x10438, 0x10439, 0x1043a, 0x1043b, 0x1043c, 0x1043d, 0x1043e, 0x1043f, + 0x10440, 0x10441, 0x10442, 0x10443, 0x10444, 0x10445, 0x10446, 0x10447, + 0x10448, 0x10449, 0x1044a, 0x1044b, 0x1044c, 0x1044d, 0x1044e, 0x1044f, + 0x10400, 0x10401, 0x10402, 0x10403, 0x10404, 0x10405, 0x10406, 0x10407, + 0x10408, 0x10409, 0x1040a, 0x1040b, 0x1040c, 0x1040d, 0x1040e, 0x1040f, + 0x10410, 0x10411, 0x10412, 0x10413, 0x10414, 0x10415, 0x10416, 0x10417, + 0x10418, 0x10419, 0x1041a, 0x1041b, 0x1041c, 0x1041d, 0x1041e, 0x1041f, + 0x10420, 0x10421, 0x10422, 0x10423, 0x10424, 0x10425, 0x10426, 0x10427, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 + }, + { /* page 471, index 25 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, + 0x0009, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, + 0x0007, 0x0008, 0x0009, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x0006, 0x0007, 0x0008, 0x0009 + } +}; + +/* U+0000 through U+2FAFF */ +static const gint16 attr_table_part1[763] = { + 0 /* page 0 */, + 1 /* page 1 */, + 2 /* page 2 */, + 3 /* page 3 */, + 4 /* page 4 */, + 5 /* page 5 */, + 6 /* page 6 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 7 /* page 9 */, + 8 /* page 10 */, + 9 /* page 11 */, + 10 /* page 12 */, + 11 /* page 13 */, + 12 /* page 14 */, + 13 /* page 15 */, + 14 /* page 16 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 15 /* page 19 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 16 /* page 23 */, + 17 /* page 24 */, + 18 /* page 25 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 19 /* page 30 */, + 20 /* page 31 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 21 /* page 33 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 22 /* page 251 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 23 /* page 255 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 24 /* page 260 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 25 /* page 471 */, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX +}; + +/* U+E0000 through U+10FFFF */ +static const gint16 attr_table_part2[768] = { + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX, + 0x0000 + G_UNICODE_MAX_TABLE_INDEX +}; + +static const gunichar title_table[][3] = { + { 0x01c5, 0x01c4, 0x01c6 }, + { 0x01c8, 0x01c7, 0x01c9 }, + { 0x01cb, 0x01ca, 0x01cc }, + { 0x01f2, 0x01f1, 0x01f3 }, + { 0x1f88, 0x0000, 0x1f80 }, + { 0x1f89, 0x0000, 0x1f81 }, + { 0x1f8a, 0x0000, 0x1f82 }, + { 0x1f8b, 0x0000, 0x1f83 }, + { 0x1f8c, 0x0000, 0x1f84 }, + { 0x1f8d, 0x0000, 0x1f85 }, + { 0x1f8e, 0x0000, 0x1f86 }, + { 0x1f8f, 0x0000, 0x1f87 }, + { 0x1f98, 0x0000, 0x1f90 }, + { 0x1f99, 0x0000, 0x1f91 }, + { 0x1f9a, 0x0000, 0x1f92 }, + { 0x1f9b, 0x0000, 0x1f93 }, + { 0x1f9c, 0x0000, 0x1f94 }, + { 0x1f9d, 0x0000, 0x1f95 }, + { 0x1f9e, 0x0000, 0x1f96 }, + { 0x1f9f, 0x0000, 0x1f97 }, + { 0x1fa8, 0x0000, 0x1fa0 }, + { 0x1fa9, 0x0000, 0x1fa1 }, + { 0x1faa, 0x0000, 0x1fa2 }, + { 0x1fab, 0x0000, 0x1fa3 }, + { 0x1fac, 0x0000, 0x1fa4 }, + { 0x1fad, 0x0000, 0x1fa5 }, + { 0x1fae, 0x0000, 0x1fa6 }, + { 0x1faf, 0x0000, 0x1fa7 }, + { 0x1fbc, 0x0000, 0x1fb3 }, + { 0x1fcc, 0x0000, 0x1fc3 }, + { 0x1ffc, 0x0000, 0x1ff3 } +}; + + +/* Table of special cases for case conversion; each record contains + * First, the best single character mapping to lowercase if Lu, + * and to uppercase if Ll, followed by the output mapping for the two cases + * other than the case of the codepoint, in the order [Ll],[Lu],[Lt], + * encoded in UTF-8, separated and terminated by a null character. + */ +static const gchar special_case_table[] = { + "\x00\x53\x53\x00\x53\x73\0" /* offset 0 */ + "\x69\x69\xcc\x87\x00\xc4\xb0\0" /* offset 7 */ + "\x00\x46\x46\x00\x46\x66\0" /* offset 15 */ + "\x00\x46\x49\x00\x46\x69\0" /* offset 22 */ + "\x00\x46\x4c\x00\x46\x6c\0" /* offset 29 */ + "\x00\x46\x46\x49\x00\x46\x66\x69\0" /* offset 36 */ + "\x00\x46\x46\x4c\x00\x46\x66\x6c\0" /* offset 45 */ + "\x00\x53\x54\x00\x53\x74\0" /* offset 54 */ + "\x00\x53\x54\x00\x53\x74\0" /* offset 61 */ + "\x00\xd4\xb5\xd5\x92\x00\xd4\xb5\xd6\x82\0" /* offset 68 */ + "\x00\xd5\x84\xd5\x86\x00\xd5\x84\xd5\xb6\0" /* offset 79 */ + "\x00\xd5\x84\xd4\xb5\x00\xd5\x84\xd5\xa5\0" /* offset 90 */ + "\x00\xd5\x84\xd4\xbb\x00\xd5\x84\xd5\xab\0" /* offset 101 */ + "\x00\xd5\x8e\xd5\x86\x00\xd5\x8e\xd5\xb6\0" /* offset 112 */ + "\x00\xd5\x84\xd4\xbd\x00\xd5\x84\xd5\xad\0" /* offset 123 */ + "\x00\xca\xbc\x4e\x00\xca\xbc\x4e\0" /* offset 134 */ + "\x00\xce\x99\xcc\x88\xcc\x81\x00\xce\x99\xcc\x88\xcc\x81\0" /* offset 143 */ + "\x00\xce\xa5\xcc\x88\xcc\x81\x00\xce\xa5\xcc\x88\xcc\x81\0" /* offset 158 */ + "\x00\x4a\xcc\x8c\x00\x4a\xcc\x8c\0" /* offset 173 */ + "\x00\x48\xcc\xb1\x00\x48\xcc\xb1\0" /* offset 182 */ + "\x00\x54\xcc\x88\x00\x54\xcc\x88\0" /* offset 191 */ + "\x00\x57\xcc\x8a\x00\x57\xcc\x8a\0" /* offset 200 */ + "\x00\x59\xcc\x8a\x00\x59\xcc\x8a\0" /* offset 209 */ + "\x00\x41\xca\xbe\x00\x41\xca\xbe\0" /* offset 218 */ + "\x00\xce\xa5\xcc\x93\x00\xce\xa5\xcc\x93\0" /* offset 227 */ + "\x00\xce\xa5\xcc\x93\xcc\x80\x00\xce\xa5\xcc\x93\xcc\x80\0" /* offset 238 */ + "\x00\xce\xa5\xcc\x93\xcc\x81\x00\xce\xa5\xcc\x93\xcc\x81\0" /* offset 253 */ + "\x00\xce\xa5\xcc\x93\xcd\x82\x00\xce\xa5\xcc\x93\xcd\x82\0" /* offset 268 */ + "\x00\xce\x91\xcd\x82\x00\xce\x91\xcd\x82\0" /* offset 283 */ + "\x00\xce\x97\xcd\x82\x00\xce\x97\xcd\x82\0" /* offset 294 */ + "\x00\xce\x99\xcc\x88\xcc\x80\x00\xce\x99\xcc\x88\xcc\x80\0" /* offset 305 */ + "\x00\xce\x99\xcc\x88\xcc\x81\x00\xce\x99\xcc\x88\xcc\x81\0" /* offset 320 */ + "\x00\xce\x99\xcd\x82\x00\xce\x99\xcd\x82\0" /* offset 335 */ + "\x00\xce\x99\xcc\x88\xcd\x82\x00\xce\x99\xcc\x88\xcd\x82\0" /* offset 346 */ + "\x00\xce\xa5\xcc\x88\xcc\x80\x00\xce\xa5\xcc\x88\xcc\x80\0" /* offset 361 */ + "\x00\xce\xa5\xcc\x88\xcc\x81\x00\xce\xa5\xcc\x88\xcc\x81\0" /* offset 376 */ + "\x00\xce\xa1\xcc\x93\x00\xce\xa1\xcc\x93\0" /* offset 391 */ + "\x00\xce\xa5\xcd\x82\x00\xce\xa5\xcd\x82\0" /* offset 402 */ + "\x00\xce\xa5\xcc\x88\xcd\x82\x00\xce\xa5\xcc\x88\xcd\x82\0" /* offset 413 */ + "\x00\xce\xa9\xcd\x82\x00\xce\xa9\xcd\x82\0" /* offset 428 */ + "\xe1\xbe\x88\xe1\xbc\x88\xce\x99\x00\xe1\xbe\x88\0" /* offset 439 */ + "\xe1\xbe\x89\xe1\xbc\x89\xce\x99\x00\xe1\xbe\x89\0" /* offset 452 */ + "\xe1\xbe\x8a\xe1\xbc\x8a\xce\x99\x00\xe1\xbe\x8a\0" /* offset 465 */ + "\xe1\xbe\x8b\xe1\xbc\x8b\xce\x99\x00\xe1\xbe\x8b\0" /* offset 478 */ + "\xe1\xbe\x8c\xe1\xbc\x8c\xce\x99\x00\xe1\xbe\x8c\0" /* offset 491 */ + "\xe1\xbe\x8d\xe1\xbc\x8d\xce\x99\x00\xe1\xbe\x8d\0" /* offset 504 */ + "\xe1\xbe\x8e\xe1\xbc\x8e\xce\x99\x00\xe1\xbe\x8e\0" /* offset 517 */ + "\xe1\xbe\x8f\xe1\xbc\x8f\xce\x99\x00\xe1\xbe\x8f\0" /* offset 530 */ + "\xe1\xbe\x80\x00\xe1\xbc\x88\xce\x99\0" /* offset 543 */ + "\xe1\xbe\x81\x00\xe1\xbc\x89\xce\x99\0" /* offset 553 */ + "\xe1\xbe\x82\x00\xe1\xbc\x8a\xce\x99\0" /* offset 563 */ + "\xe1\xbe\x83\x00\xe1\xbc\x8b\xce\x99\0" /* offset 573 */ + "\xe1\xbe\x84\x00\xe1\xbc\x8c\xce\x99\0" /* offset 583 */ + "\xe1\xbe\x85\x00\xe1\xbc\x8d\xce\x99\0" /* offset 593 */ + "\xe1\xbe\x86\x00\xe1\xbc\x8e\xce\x99\0" /* offset 603 */ + "\xe1\xbe\x87\x00\xe1\xbc\x8f\xce\x99\0" /* offset 613 */ + "\xe1\xbe\x98\xe1\xbc\xa8\xce\x99\x00\xe1\xbe\x98\0" /* offset 623 */ + "\xe1\xbe\x99\xe1\xbc\xa9\xce\x99\x00\xe1\xbe\x99\0" /* offset 636 */ + "\xe1\xbe\x9a\xe1\xbc\xaa\xce\x99\x00\xe1\xbe\x9a\0" /* offset 649 */ + "\xe1\xbe\x9b\xe1\xbc\xab\xce\x99\x00\xe1\xbe\x9b\0" /* offset 662 */ + "\xe1\xbe\x9c\xe1\xbc\xac\xce\x99\x00\xe1\xbe\x9c\0" /* offset 675 */ + "\xe1\xbe\x9d\xe1\xbc\xad\xce\x99\x00\xe1\xbe\x9d\0" /* offset 688 */ + "\xe1\xbe\x9e\xe1\xbc\xae\xce\x99\x00\xe1\xbe\x9e\0" /* offset 701 */ + "\xe1\xbe\x9f\xe1\xbc\xaf\xce\x99\x00\xe1\xbe\x9f\0" /* offset 714 */ + "\xe1\xbe\x90\x00\xe1\xbc\xa8\xce\x99\0" /* offset 727 */ + "\xe1\xbe\x91\x00\xe1\xbc\xa9\xce\x99\0" /* offset 737 */ + "\xe1\xbe\x92\x00\xe1\xbc\xaa\xce\x99\0" /* offset 747 */ + "\xe1\xbe\x93\x00\xe1\xbc\xab\xce\x99\0" /* offset 757 */ + "\xe1\xbe\x94\x00\xe1\xbc\xac\xce\x99\0" /* offset 767 */ + "\xe1\xbe\x95\x00\xe1\xbc\xad\xce\x99\0" /* offset 777 */ + "\xe1\xbe\x96\x00\xe1\xbc\xae\xce\x99\0" /* offset 787 */ + "\xe1\xbe\x97\x00\xe1\xbc\xaf\xce\x99\0" /* offset 797 */ + "\xe1\xbe\xa8\xe1\xbd\xa8\xce\x99\x00\xe1\xbe\xa8\0" /* offset 807 */ + "\xe1\xbe\xa9\xe1\xbd\xa9\xce\x99\x00\xe1\xbe\xa9\0" /* offset 820 */ + "\xe1\xbe\xaa\xe1\xbd\xaa\xce\x99\x00\xe1\xbe\xaa\0" /* offset 833 */ + "\xe1\xbe\xab\xe1\xbd\xab\xce\x99\x00\xe1\xbe\xab\0" /* offset 846 */ + "\xe1\xbe\xac\xe1\xbd\xac\xce\x99\x00\xe1\xbe\xac\0" /* offset 859 */ + "\xe1\xbe\xad\xe1\xbd\xad\xce\x99\x00\xe1\xbe\xad\0" /* offset 872 */ + "\xe1\xbe\xae\xe1\xbd\xae\xce\x99\x00\xe1\xbe\xae\0" /* offset 885 */ + "\xe1\xbe\xaf\xe1\xbd\xaf\xce\x99\x00\xe1\xbe\xaf\0" /* offset 898 */ + "\xe1\xbe\xa0\x00\xe1\xbd\xa8\xce\x99\0" /* offset 911 */ + "\xe1\xbe\xa1\x00\xe1\xbd\xa9\xce\x99\0" /* offset 921 */ + "\xe1\xbe\xa2\x00\xe1\xbd\xaa\xce\x99\0" /* offset 931 */ + "\xe1\xbe\xa3\x00\xe1\xbd\xab\xce\x99\0" /* offset 941 */ + "\xe1\xbe\xa4\x00\xe1\xbd\xac\xce\x99\0" /* offset 951 */ + "\xe1\xbe\xa5\x00\xe1\xbd\xad\xce\x99\0" /* offset 961 */ + "\xe1\xbe\xa6\x00\xe1\xbd\xae\xce\x99\0" /* offset 971 */ + "\xe1\xbe\xa7\x00\xe1\xbd\xaf\xce\x99\0" /* offset 981 */ + "\xe1\xbe\xbc\xce\x91\xce\x99\x00\xe1\xbe\xbc\0" /* offset 991 */ + "\xe1\xbe\xb3\x00\xce\x91\xce\x99\0" /* offset 1003 */ + "\xe1\xbf\x8c\xce\x97\xce\x99\x00\xe1\xbf\x8c\0" /* offset 1012 */ + "\xe1\xbf\x83\x00\xce\x97\xce\x99\0" /* offset 1024 */ + "\xe1\xbf\xbc\xce\xa9\xce\x99\x00\xe1\xbf\xbc\0" /* offset 1033 */ + "\xe1\xbf\xb3\x00\xce\xa9\xce\x99\0" /* offset 1045 */ + "\x00\xe1\xbe\xba\xce\x99\x00\xe1\xbe\xba\xcd\x85\0" /* offset 1054 */ + "\x00\xce\x86\xce\x99\x00\xce\x86\xcd\x85\0" /* offset 1067 */ + "\x00\xe1\xbf\x8a\xce\x99\x00\xe1\xbf\x8a\xcd\x85\0" /* offset 1078 */ + "\x00\xce\x89\xce\x99\x00\xce\x89\xcd\x85\0" /* offset 1091 */ + "\x00\xe1\xbf\xba\xce\x99\x00\xe1\xbf\xba\xcd\x85\0" /* offset 1102 */ + "\x00\xce\x8f\xce\x99\x00\xce\x8f\xcd\x85\0" /* offset 1115 */ + "\x00\xce\x91\xcd\x82\xce\x99\x00\xce\x91\xcd\x82\xcd\x85\0" /* offset 1126 */ + "\x00\xce\x97\xcd\x82\xce\x99\x00\xce\x97\xcd\x82\xcd\x85\0" /* offset 1141 */ + "\x00\xce\xa9\xcd\x82\xce\x99\x00\xce\xa9\xcd\x82\xcd\x85\0" /* offset 1156 */ +}; + + +/* Table of casefolding cases that can't be derived by lowercasing + */ +static const struct { + guint16 ch; + gchar data[7]; +} casefold_table[] = { + { 0x00b5, "\xce\xbc" }, + { 0x00df, "\x73\x73" }, + { 0x0130, "\x69\xcc\x87" }, + { 0x0149, "\xca\xbc\x6e" }, + { 0x017f, "\x73" }, + { 0x01f0, "\x6a\xcc\x8c" }, + { 0x0345, "\xce\xb9" }, + { 0x0390, "\xce\xb9\xcc\x88\xcc\x81" }, + { 0x03b0, "\xcf\x85\xcc\x88\xcc\x81" }, + { 0x03c2, "\xcf\x83" }, + { 0x03d0, "\xce\xb2" }, + { 0x03d1, "\xce\xb8" }, + { 0x03d5, "\xcf\x86" }, + { 0x03d6, "\xcf\x80" }, + { 0x03f0, "\xce\xba" }, + { 0x03f1, "\xcf\x81" }, + { 0x03f5, "\xce\xb5" }, + { 0x0587, "\xd5\xa5\xd6\x82" }, + { 0x1e96, "\x68\xcc\xb1" }, + { 0x1e97, "\x74\xcc\x88" }, + { 0x1e98, "\x77\xcc\x8a" }, + { 0x1e99, "\x79\xcc\x8a" }, + { 0x1e9a, "\x61\xca\xbe" }, + { 0x1e9b, "\xe1\xb9\xa1" }, + { 0x1f50, "\xcf\x85\xcc\x93" }, + { 0x1f52, "\xcf\x85\xcc\x93\xcc\x80" }, + { 0x1f54, "\xcf\x85\xcc\x93\xcc\x81" }, + { 0x1f56, "\xcf\x85\xcc\x93\xcd\x82" }, + { 0x1f80, "\xe1\xbc\x80\xce\xb9" }, + { 0x1f81, "\xe1\xbc\x81\xce\xb9" }, + { 0x1f82, "\xe1\xbc\x82\xce\xb9" }, + { 0x1f83, "\xe1\xbc\x83\xce\xb9" }, + { 0x1f84, "\xe1\xbc\x84\xce\xb9" }, + { 0x1f85, "\xe1\xbc\x85\xce\xb9" }, + { 0x1f86, "\xe1\xbc\x86\xce\xb9" }, + { 0x1f87, "\xe1\xbc\x87\xce\xb9" }, + { 0x1f88, "\xe1\xbc\x80\xce\xb9" }, + { 0x1f89, "\xe1\xbc\x81\xce\xb9" }, + { 0x1f8a, "\xe1\xbc\x82\xce\xb9" }, + { 0x1f8b, "\xe1\xbc\x83\xce\xb9" }, + { 0x1f8c, "\xe1\xbc\x84\xce\xb9" }, + { 0x1f8d, "\xe1\xbc\x85\xce\xb9" }, + { 0x1f8e, "\xe1\xbc\x86\xce\xb9" }, + { 0x1f8f, "\xe1\xbc\x87\xce\xb9" }, + { 0x1f90, "\xe1\xbc\xa0\xce\xb9" }, + { 0x1f91, "\xe1\xbc\xa1\xce\xb9" }, + { 0x1f92, "\xe1\xbc\xa2\xce\xb9" }, + { 0x1f93, "\xe1\xbc\xa3\xce\xb9" }, + { 0x1f94, "\xe1\xbc\xa4\xce\xb9" }, + { 0x1f95, "\xe1\xbc\xa5\xce\xb9" }, + { 0x1f96, "\xe1\xbc\xa6\xce\xb9" }, + { 0x1f97, "\xe1\xbc\xa7\xce\xb9" }, + { 0x1f98, "\xe1\xbc\xa0\xce\xb9" }, + { 0x1f99, "\xe1\xbc\xa1\xce\xb9" }, + { 0x1f9a, "\xe1\xbc\xa2\xce\xb9" }, + { 0x1f9b, "\xe1\xbc\xa3\xce\xb9" }, + { 0x1f9c, "\xe1\xbc\xa4\xce\xb9" }, + { 0x1f9d, "\xe1\xbc\xa5\xce\xb9" }, + { 0x1f9e, "\xe1\xbc\xa6\xce\xb9" }, + { 0x1f9f, "\xe1\xbc\xa7\xce\xb9" }, + { 0x1fa0, "\xe1\xbd\xa0\xce\xb9" }, + { 0x1fa1, "\xe1\xbd\xa1\xce\xb9" }, + { 0x1fa2, "\xe1\xbd\xa2\xce\xb9" }, + { 0x1fa3, "\xe1\xbd\xa3\xce\xb9" }, + { 0x1fa4, "\xe1\xbd\xa4\xce\xb9" }, + { 0x1fa5, "\xe1\xbd\xa5\xce\xb9" }, + { 0x1fa6, "\xe1\xbd\xa6\xce\xb9" }, + { 0x1fa7, "\xe1\xbd\xa7\xce\xb9" }, + { 0x1fa8, "\xe1\xbd\xa0\xce\xb9" }, + { 0x1fa9, "\xe1\xbd\xa1\xce\xb9" }, + { 0x1faa, "\xe1\xbd\xa2\xce\xb9" }, + { 0x1fab, "\xe1\xbd\xa3\xce\xb9" }, + { 0x1fac, "\xe1\xbd\xa4\xce\xb9" }, + { 0x1fad, "\xe1\xbd\xa5\xce\xb9" }, + { 0x1fae, "\xe1\xbd\xa6\xce\xb9" }, + { 0x1faf, "\xe1\xbd\xa7\xce\xb9" }, + { 0x1fb2, "\xe1\xbd\xb0\xce\xb9" }, + { 0x1fb3, "\xce\xb1\xce\xb9" }, + { 0x1fb4, "\xce\xac\xce\xb9" }, + { 0x1fb6, "\xce\xb1\xcd\x82" }, + { 0x1fb7, "\xce\xb1\xcd\x82\xce\xb9" }, + { 0x1fbc, "\xce\xb1\xce\xb9" }, + { 0x1fbe, "\xce\xb9" }, + { 0x1fc2, "\xe1\xbd\xb4\xce\xb9" }, + { 0x1fc3, "\xce\xb7\xce\xb9" }, + { 0x1fc4, "\xce\xae\xce\xb9" }, + { 0x1fc6, "\xce\xb7\xcd\x82" }, + { 0x1fc7, "\xce\xb7\xcd\x82\xce\xb9" }, + { 0x1fcc, "\xce\xb7\xce\xb9" }, + { 0x1fd2, "\xce\xb9\xcc\x88\xcc\x80" }, + { 0x1fd3, "\xce\xb9\xcc\x88\xcc\x81" }, + { 0x1fd6, "\xce\xb9\xcd\x82" }, + { 0x1fd7, "\xce\xb9\xcc\x88\xcd\x82" }, + { 0x1fe2, "\xcf\x85\xcc\x88\xcc\x80" }, + { 0x1fe3, "\xcf\x85\xcc\x88\xcc\x81" }, + { 0x1fe4, "\xcf\x81\xcc\x93" }, + { 0x1fe6, "\xcf\x85\xcd\x82" }, + { 0x1fe7, "\xcf\x85\xcc\x88\xcd\x82" }, + { 0x1ff2, "\xe1\xbd\xbc\xce\xb9" }, + { 0x1ff3, "\xcf\x89\xce\xb9" }, + { 0x1ff4, "\xcf\x8e\xce\xb9" }, + { 0x1ff6, "\xcf\x89\xcd\x82" }, + { 0x1ff7, "\xcf\x89\xcd\x82\xce\xb9" }, + { 0x1ffc, "\xcf\x89\xce\xb9" }, + { 0x2160, "\xe2\x85\xb0" }, + { 0x2161, "\xe2\x85\xb1" }, + { 0x2162, "\xe2\x85\xb2" }, + { 0x2163, "\xe2\x85\xb3" }, + { 0x2164, "\xe2\x85\xb4" }, + { 0x2165, "\xe2\x85\xb5" }, + { 0x2166, "\xe2\x85\xb6" }, + { 0x2167, "\xe2\x85\xb7" }, + { 0x2168, "\xe2\x85\xb8" }, + { 0x2169, "\xe2\x85\xb9" }, + { 0x216a, "\xe2\x85\xba" }, + { 0x216b, "\xe2\x85\xbb" }, + { 0x216c, "\xe2\x85\xbc" }, + { 0x216d, "\xe2\x85\xbd" }, + { 0x216e, "\xe2\x85\xbe" }, + { 0x216f, "\xe2\x85\xbf" }, + { 0x24b6, "\xe2\x93\x90" }, + { 0x24b7, "\xe2\x93\x91" }, + { 0x24b8, "\xe2\x93\x92" }, + { 0x24b9, "\xe2\x93\x93" }, + { 0x24ba, "\xe2\x93\x94" }, + { 0x24bb, "\xe2\x93\x95" }, + { 0x24bc, "\xe2\x93\x96" }, + { 0x24bd, "\xe2\x93\x97" }, + { 0x24be, "\xe2\x93\x98" }, + { 0x24bf, "\xe2\x93\x99" }, + { 0x24c0, "\xe2\x93\x9a" }, + { 0x24c1, "\xe2\x93\x9b" }, + { 0x24c2, "\xe2\x93\x9c" }, + { 0x24c3, "\xe2\x93\x9d" }, + { 0x24c4, "\xe2\x93\x9e" }, + { 0x24c5, "\xe2\x93\x9f" }, + { 0x24c6, "\xe2\x93\xa0" }, + { 0x24c7, "\xe2\x93\xa1" }, + { 0x24c8, "\xe2\x93\xa2" }, + { 0x24c9, "\xe2\x93\xa3" }, + { 0x24ca, "\xe2\x93\xa4" }, + { 0x24cb, "\xe2\x93\xa5" }, + { 0x24cc, "\xe2\x93\xa6" }, + { 0x24cd, "\xe2\x93\xa7" }, + { 0x24ce, "\xe2\x93\xa8" }, + { 0x24cf, "\xe2\x93\xa9" }, + { 0xfb00, "\x66\x66" }, + { 0xfb01, "\x66\x69" }, + { 0xfb02, "\x66\x6c" }, + { 0xfb03, "\x66\x66\x69" }, + { 0xfb04, "\x66\x66\x6c" }, + { 0xfb05, "\x73\x74" }, + { 0xfb06, "\x73\x74" }, + { 0xfb13, "\xd5\xb4\xd5\xb6" }, + { 0xfb14, "\xd5\xb4\xd5\xa5" }, + { 0xfb15, "\xd5\xb4\xd5\xab" }, + { 0xfb16, "\xd5\xbe\xd5\xb6" }, + { 0xfb17, "\xd5\xb4\xd5\xad" }, +}; + +static const struct { + gunichar ch; + gunichar mirrored_ch; +} bidi_mirroring_table[] = +{ + { 0x0028, 0x0029 }, + { 0x0029, 0x0028 }, + { 0x003c, 0x003e }, + { 0x003e, 0x003c }, + { 0x005b, 0x005d }, + { 0x005d, 0x005b }, + { 0x007b, 0x007d }, + { 0x007d, 0x007b }, + { 0x00ab, 0x00bb }, + { 0x00bb, 0x00ab }, + { 0x2039, 0x203a }, + { 0x203a, 0x2039 }, + { 0x2045, 0x2046 }, + { 0x2046, 0x2045 }, + { 0x207d, 0x207e }, + { 0x207e, 0x207d }, + { 0x208d, 0x208e }, + { 0x208e, 0x208d }, + { 0x2208, 0x220b }, + { 0x2209, 0x220c }, + { 0x220a, 0x220d }, + { 0x220b, 0x2208 }, + { 0x220c, 0x2209 }, + { 0x220d, 0x220a }, + { 0x2215, 0x29f5 }, + { 0x223c, 0x223d }, + { 0x223d, 0x223c }, + { 0x2243, 0x22cd }, + { 0x2252, 0x2253 }, + { 0x2253, 0x2252 }, + { 0x2254, 0x2255 }, + { 0x2255, 0x2254 }, + { 0x2264, 0x2265 }, + { 0x2265, 0x2264 }, + { 0x2266, 0x2267 }, + { 0x2267, 0x2266 }, + { 0x2268, 0x2269 }, + { 0x2269, 0x2268 }, + { 0x226a, 0x226b }, + { 0x226b, 0x226a }, + { 0x226e, 0x226f }, + { 0x226f, 0x226e }, + { 0x2270, 0x2271 }, + { 0x2271, 0x2270 }, + { 0x2272, 0x2273 }, + { 0x2273, 0x2272 }, + { 0x2274, 0x2275 }, + { 0x2275, 0x2274 }, + { 0x2276, 0x2277 }, + { 0x2277, 0x2276 }, + { 0x2278, 0x2279 }, + { 0x2279, 0x2278 }, + { 0x227a, 0x227b }, + { 0x227b, 0x227a }, + { 0x227c, 0x227d }, + { 0x227d, 0x227c }, + { 0x227e, 0x227f }, + { 0x227f, 0x227e }, + { 0x2280, 0x2281 }, + { 0x2281, 0x2280 }, + { 0x2282, 0x2283 }, + { 0x2283, 0x2282 }, + { 0x2284, 0x2285 }, + { 0x2285, 0x2284 }, + { 0x2286, 0x2287 }, + { 0x2287, 0x2286 }, + { 0x2288, 0x2289 }, + { 0x2289, 0x2288 }, + { 0x228a, 0x228b }, + { 0x228b, 0x228a }, + { 0x228f, 0x2290 }, + { 0x2290, 0x228f }, + { 0x2291, 0x2292 }, + { 0x2292, 0x2291 }, + { 0x2298, 0x29b8 }, + { 0x22a2, 0x22a3 }, + { 0x22a3, 0x22a2 }, + { 0x22a6, 0x2ade }, + { 0x22a8, 0x2ae4 }, + { 0x22a9, 0x2ae3 }, + { 0x22ab, 0x2ae5 }, + { 0x22b0, 0x22b1 }, + { 0x22b1, 0x22b0 }, + { 0x22b2, 0x22b3 }, + { 0x22b3, 0x22b2 }, + { 0x22b4, 0x22b5 }, + { 0x22b5, 0x22b4 }, + { 0x22b6, 0x22b7 }, + { 0x22b7, 0x22b6 }, + { 0x22c9, 0x22ca }, + { 0x22ca, 0x22c9 }, + { 0x22cb, 0x22cc }, + { 0x22cc, 0x22cb }, + { 0x22cd, 0x2243 }, + { 0x22d0, 0x22d1 }, + { 0x22d1, 0x22d0 }, + { 0x22d6, 0x22d7 }, + { 0x22d7, 0x22d6 }, + { 0x22d8, 0x22d9 }, + { 0x22d9, 0x22d8 }, + { 0x22da, 0x22db }, + { 0x22db, 0x22da }, + { 0x22dc, 0x22dd }, + { 0x22dd, 0x22dc }, + { 0x22de, 0x22df }, + { 0x22df, 0x22de }, + { 0x22e0, 0x22e1 }, + { 0x22e1, 0x22e0 }, + { 0x22e2, 0x22e3 }, + { 0x22e3, 0x22e2 }, + { 0x22e4, 0x22e5 }, + { 0x22e5, 0x22e4 }, + { 0x22e6, 0x22e7 }, + { 0x22e7, 0x22e6 }, + { 0x22e8, 0x22e9 }, + { 0x22e9, 0x22e8 }, + { 0x22ea, 0x22eb }, + { 0x22eb, 0x22ea }, + { 0x22ec, 0x22ed }, + { 0x22ed, 0x22ec }, + { 0x22f0, 0x22f1 }, + { 0x22f1, 0x22f0 }, + { 0x22f2, 0x22fa }, + { 0x22f3, 0x22fb }, + { 0x22f4, 0x22fc }, + { 0x22f6, 0x22fd }, + { 0x22f7, 0x22fe }, + { 0x22fa, 0x22f2 }, + { 0x22fb, 0x22f3 }, + { 0x22fc, 0x22f4 }, + { 0x22fd, 0x22f6 }, + { 0x22fe, 0x22f7 }, + { 0x2308, 0x2309 }, + { 0x2309, 0x2308 }, + { 0x230a, 0x230b }, + { 0x230b, 0x230a }, + { 0x2329, 0x232a }, + { 0x232a, 0x2329 }, + { 0x2768, 0x2769 }, + { 0x2769, 0x2768 }, + { 0x276a, 0x276b }, + { 0x276b, 0x276a }, + { 0x276c, 0x276d }, + { 0x276d, 0x276c }, + { 0x276e, 0x276f }, + { 0x276f, 0x276e }, + { 0x2770, 0x2771 }, + { 0x2771, 0x2770 }, + { 0x2772, 0x2773 }, + { 0x2773, 0x2772 }, + { 0x2774, 0x2775 }, + { 0x2775, 0x2774 }, + { 0x27d5, 0x27d6 }, + { 0x27d6, 0x27d5 }, + { 0x27dd, 0x27de }, + { 0x27de, 0x27dd }, + { 0x27e2, 0x27e3 }, + { 0x27e3, 0x27e2 }, + { 0x27e4, 0x27e5 }, + { 0x27e5, 0x27e4 }, + { 0x27e6, 0x27e7 }, + { 0x27e7, 0x27e6 }, + { 0x27e8, 0x27e9 }, + { 0x27e9, 0x27e8 }, + { 0x27ea, 0x27eb }, + { 0x27eb, 0x27ea }, + { 0x2983, 0x2984 }, + { 0x2984, 0x2983 }, + { 0x2985, 0x2986 }, + { 0x2986, 0x2985 }, + { 0x2987, 0x2988 }, + { 0x2988, 0x2987 }, + { 0x2989, 0x298a }, + { 0x298a, 0x2989 }, + { 0x298b, 0x298c }, + { 0x298c, 0x298b }, + { 0x298d, 0x2990 }, + { 0x298e, 0x298f }, + { 0x298f, 0x298e }, + { 0x2990, 0x298d }, + { 0x2991, 0x2992 }, + { 0x2992, 0x2991 }, + { 0x2993, 0x2994 }, + { 0x2994, 0x2993 }, + { 0x2995, 0x2996 }, + { 0x2996, 0x2995 }, + { 0x2997, 0x2998 }, + { 0x2998, 0x2997 }, + { 0x29b8, 0x2298 }, + { 0x29c0, 0x29c1 }, + { 0x29c1, 0x29c0 }, + { 0x29c4, 0x29c5 }, + { 0x29c5, 0x29c4 }, + { 0x29cf, 0x29d0 }, + { 0x29d0, 0x29cf }, + { 0x29d1, 0x29d2 }, + { 0x29d2, 0x29d1 }, + { 0x29d4, 0x29d5 }, + { 0x29d5, 0x29d4 }, + { 0x29d8, 0x29d9 }, + { 0x29d9, 0x29d8 }, + { 0x29da, 0x29db }, + { 0x29db, 0x29da }, + { 0x29f5, 0x2215 }, + { 0x29f8, 0x29f9 }, + { 0x29f9, 0x29f8 }, + { 0x29fc, 0x29fd }, + { 0x29fd, 0x29fc }, + { 0x2a2b, 0x2a2c }, + { 0x2a2c, 0x2a2b }, + { 0x2a2d, 0x2a2c }, + { 0x2a2e, 0x2a2d }, + { 0x2a34, 0x2a35 }, + { 0x2a35, 0x2a34 }, + { 0x2a3c, 0x2a3d }, + { 0x2a3d, 0x2a3c }, + { 0x2a64, 0x2a65 }, + { 0x2a65, 0x2a64 }, + { 0x2a79, 0x2a7a }, + { 0x2a7a, 0x2a79 }, + { 0x2a7d, 0x2a7e }, + { 0x2a7e, 0x2a7d }, + { 0x2a7f, 0x2a80 }, + { 0x2a80, 0x2a7f }, + { 0x2a81, 0x2a82 }, + { 0x2a82, 0x2a81 }, + { 0x2a83, 0x2a84 }, + { 0x2a84, 0x2a83 }, + { 0x2a8b, 0x2a8c }, + { 0x2a8c, 0x2a8b }, + { 0x2a91, 0x2a92 }, + { 0x2a92, 0x2a91 }, + { 0x2a93, 0x2a94 }, + { 0x2a94, 0x2a93 }, + { 0x2a95, 0x2a96 }, + { 0x2a96, 0x2a95 }, + { 0x2a97, 0x2a98 }, + { 0x2a98, 0x2a97 }, + { 0x2a99, 0x2a9a }, + { 0x2a9a, 0x2a99 }, + { 0x2a9b, 0x2a9c }, + { 0x2a9c, 0x2a9b }, + { 0x2aa1, 0x2aa2 }, + { 0x2aa2, 0x2aa1 }, + { 0x2aa6, 0x2aa7 }, + { 0x2aa7, 0x2aa6 }, + { 0x2aa8, 0x2aa9 }, + { 0x2aa9, 0x2aa8 }, + { 0x2aaa, 0x2aab }, + { 0x2aab, 0x2aaa }, + { 0x2aac, 0x2aad }, + { 0x2aad, 0x2aac }, + { 0x2aaf, 0x2ab0 }, + { 0x2ab0, 0x2aaf }, + { 0x2ab3, 0x2ab4 }, + { 0x2ab4, 0x2ab3 }, + { 0x2abb, 0x2abc }, + { 0x2abc, 0x2abb }, + { 0x2abd, 0x2abe }, + { 0x2abe, 0x2abd }, + { 0x2abf, 0x2ac0 }, + { 0x2ac0, 0x2abf }, + { 0x2ac1, 0x2ac2 }, + { 0x2ac2, 0x2ac1 }, + { 0x2ac3, 0x2ac4 }, + { 0x2ac4, 0x2ac3 }, + { 0x2ac5, 0x2ac6 }, + { 0x2ac6, 0x2ac5 }, + { 0x2acd, 0x2ace }, + { 0x2ace, 0x2acd }, + { 0x2acf, 0x2ad0 }, + { 0x2ad0, 0x2acf }, + { 0x2ad1, 0x2ad2 }, + { 0x2ad2, 0x2ad1 }, + { 0x2ad3, 0x2ad4 }, + { 0x2ad4, 0x2ad3 }, + { 0x2ad5, 0x2ad6 }, + { 0x2ad6, 0x2ad5 }, + { 0x2ade, 0x22a6 }, + { 0x2ae3, 0x22a9 }, + { 0x2ae4, 0x22a8 }, + { 0x2ae5, 0x22ab }, + { 0x2aec, 0x2aed }, + { 0x2aed, 0x2aec }, + { 0x2af7, 0x2af8 }, + { 0x2af8, 0x2af7 }, + { 0x2af9, 0x2afa }, + { 0x2afa, 0x2af9 }, + { 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 }, + { 0xff08, 0xff09 }, + { 0xff09, 0xff08 }, + { 0xff1c, 0xff1e }, + { 0xff1e, 0xff1c }, + { 0xff3b, 0xff3d }, + { 0xff3d, 0xff3b }, + { 0xff5b, 0xff5d }, + { 0xff5d, 0xff5b }, + { 0xff5f, 0xff60 }, + { 0xff60, 0xff5f }, + { 0xff62, 0xff63 }, + { 0xff63, 0xff62 } +}; + +#endif /* CHARTABLES_H */ diff --git a/3rdparty/clucene/src/CLucene/config/repl_lltot.cpp b/3rdparty/clucene/src/CLucene/config/repl_lltot.cpp new file mode 100644 index 0000000..05a63b8 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_lltot.cpp @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" + +TCHAR* lucene_i64tot( + int64_t value, /* [I] Value to be converted */ + TCHAR* str, /* [O] Destination for the converted value */ + int radix) /* [I] Number base for conversion */ +{ + uint64_t val; + int negative; + TCHAR buffer[65]; + TCHAR* pos; + int digit; + + if (value < 0 && radix == 10) { + negative = 1; + val = -value; + } else { + negative = 0; + val = value; + } /* if */ + + pos = &buffer[64]; + *pos = '\0'; + + do { + digit = val % radix; + val = val / radix; + if (digit < 10) { + *--pos = '0' + digit; + } else { + *--pos = 'a' + digit - 10; + } /* if */ + } while (val != 0L); + + if (negative) { + *--pos = '-'; + } /* if */ + + _tcsncpy(str,pos,&buffer[64] - pos + 1); //needed for unicode to work + return str; +} diff --git a/3rdparty/clucene/src/CLucene/config/repl_tchar.h b/3rdparty/clucene/src/CLucene/config/repl_tchar.h new file mode 100644 index 0000000..ba8aef5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_tchar.h @@ -0,0 +1,126 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _CL_HAVE_TCHAR_H +#if defined(_UCS2) + #define TCHAR wchar_t + + //note: descriptions with * in front have replacement functions + + //formatting functions + #define _sntprintf swprintf //* make a formatted a string + #define _tprintf wprintf //* print a formatted string + + //this one has no replacement functions yet, but it is only used in the tests + #define _vsntprintf vsnwprintf //* print a formatted string using variable arguments + + //we are using the internal functions of the compiler here + //if LUCENE_USE_INTERNAL_CHAR_FUNCTIONS is defined, thesse + //will be replaced by internal functions + #define _istalnum iswalnum //* alpha/numeric char check + #define _istalpha iswalpha //* alpha char check + #define _istspace iswspace //* space char check + #define _istdigit iswdigit //* digit char check + #define _totlower towlower //* convert char to lower case + #define _totupper towupper //* convert char to lower case + #define _tcslwr wcslwr //* convert string to lower case + + //these are the string handling functions + //we may need to create wide-character/multi-byte replacements for these + #define _tcscpy wcscpy //copy a string to another string + #define _tcsncpy wcsncpy //copy a specified amount of one string to another string. + #define _tcscat wcscat //copy a string onto the end of the other string + #define _tcschr wcschr //find location of one character + #define _tcsstr wcsstr //find location of a string + #define _tcslen wcslen //get length of a string + #define _tcscmp wcscmp //case sensitive compare two strings + #define _tcsncmp wcsncmp //case sensitive compare two strings + #define _tcscspn wcscspn //location of any of a set of character in a string + + #ifdef _CL_HAVE_WCSICMP + #define _tcsicmp wcsicmp //* case insensitive compare two string + #else + #define _tcsicmp wcscasecmp //* case insensitive compare two string + #endif + + //conversion functions + #define _tcstod wcstod //convert a string to a double + #ifdef _PA_RISC + #define _tcstoi64 __wcstoll //* convers a string to an 64bit bit integer + #else + #define _tcstoi64 wcstoll //* convers a string to an 64bit bit integer + #endif + #define _i64tot lltow //* converts a 64 bit integer to a string (with base) + +#else //if defined(_ASCII) + #define TCHAR char + + //formatting functions + #define _sntprintf snprintf + #define _tprintf printf + #define _vsntprintf vsnprintf + + //we are using the internal functions of the compiler here + //if LUCENE_USE_INTERNAL_CHAR_FUNCTIONS is defined, thesse + //will be replaced by internal functions + #define _istalnum isalnum + #define _istalpha isalpha + #define _istspace isspace + #define _istdigit isdigit + #define _totlower tolower + #define _totupper toupper + #define _tcslwr strlwr + + //these are the string handling functions + #define _tcscpy strcpy + #define _tcsncpy strncpy + #define _tcscat strcat + #define _tcschr strchr + #define _tcsstr strstr + #define _tcslen strlen + #define _tcscmp strcmp + #define _tcsncmp strncmp + #define _tcsicmp strcasecmp + #define _tcscspn strcspn + + //converstion methods + #define _tcstod strtod + #define _tcstoi64 strtoll + #define _i64tot lltoa +#endif +#else //HAVE_TCHAR_H + #include + +#ifdef UNDER_CE +#include +#define _i64tot i64tot +inline TCHAR* i64tot(__int64 value, TCHAR* str, int radix) +{ + QT_USE_NAMESPACE + _tcscpy(str, (TCHAR *) QString::number(value, radix).utf16()); + return str; +} + +#define _tcstoi64 tcstoi64 +inline __int64 tcstoi64(const TCHAR *nptr, TCHAR **endptr, int base) +{ + QT_USE_NAMESPACE + bool ok; + return QString::fromUtf16((ushort*) nptr).toInt(&ok, base); +} + +#endif + + //some tchar headers miss these... + #ifndef _tcstoi64 + #if defined(_UCS2) + #define _tcstoi64 wcstoll //* convers a string to an 64bit bit integer + #else + #define _tcstoi64 strtoll + #endif + #endif + +#endif //HAVE_TCHAR_H diff --git a/3rdparty/clucene/src/CLucene/config/repl_tcscasecmp.cpp b/3rdparty/clucene/src/CLucene/config/repl_tcscasecmp.cpp new file mode 100644 index 0000000..1bee7b7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_tcscasecmp.cpp @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ + +#include "CLucene/StdHeader.h" + +int lucene_tcscasecmp(const TCHAR * sa, const TCHAR * sb){ + TCHAR ca,cb; + if (sa == sb) + return 0; + + do{ + ca = _totlower( (*(sa++)) ); + cb = _totlower( (*(sb++)) ); + } while ( ca != L'\0' && (ca == cb) ); + + return (int)(ca - cb); +} diff --git a/3rdparty/clucene/src/CLucene/config/repl_tcslwr.cpp b/3rdparty/clucene/src/CLucene/config/repl_tcslwr.cpp new file mode 100644 index 0000000..2ae6abc --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_tcslwr.cpp @@ -0,0 +1,15 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ + +#include "CLucene/StdHeader.h" + +TCHAR* lucene_tcslwr( TCHAR* str ) +{ + TCHAR* ret = str; + for ( ; *str; str++) *str = _totlower(*str); + return ret; +} diff --git a/3rdparty/clucene/src/CLucene/config/repl_tcstod.cpp b/3rdparty/clucene/src/CLucene/config/repl_tcstod.cpp new file mode 100644 index 0000000..1fd4ca7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_tcstod.cpp @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ + +#include "CLucene/StdHeader.h" + +#ifndef _ASCII +double lucene_tcstod(const TCHAR *value, TCHAR **end){ + int32_t len = _tcslen(value)+1; + char* avalue=_CL_NEWARRAY(char,len); + char* aend=NULL; + STRCPY_TtoA(avalue,value,len); + + double ret = strtod(avalue,&aend); + *end=(TCHAR*)value+(aend-avalue); + _CLDELETE_CaARRAY(avalue); + + return ret; +} +#endif diff --git a/3rdparty/clucene/src/CLucene/config/repl_tcstoll.cpp b/3rdparty/clucene/src/CLucene/config/repl_tcstoll.cpp new file mode 100644 index 0000000..246d66c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_tcstoll.cpp @@ -0,0 +1,46 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ + +#include "CLucene/StdHeader.h" + +int64_t lucene_tcstoi64(const TCHAR* str, TCHAR**end, int radix){ + #define LUCENE_TCSTOI64_RADIX(x,r) ((x>=_T('0') && x<=_T('9'))?x-_T('0'):((x>=_T('a') && x<=_T('z'))?x-_T('a')+10:((x>=_T('A') && x<=_T('Z'))?x-_T('A')+10:1000))) + + if (radix < 2 || radix > 36) + return 0; + + /* Skip white space. */ + while (_istspace (*str)) + ++str; + + int sign=1; + if ( str[0] == _T('+') ) + str++; + else if ( str[0] == _T('-') ){ + sign = -1; + str++; + } + + *end=(TCHAR*)str; + long r = -1; + while ( (r=LUCENE_TCSTOI64_RADIX(*end[0],radix)) >=0 && r=str;p-- ){ + int i=LUCENE_TCSTOI64_RADIX(p[0],radix); + if ( pos == 0 ) + ret=i; + else + ret += (int64_t)pow((qreal)radix,(qreal)pos) * i; //todo: might be quicker with a different pow overload + + pos++; + } + return sign*ret; +} diff --git a/3rdparty/clucene/src/CLucene/config/repl_tprintf.cpp b/3rdparty/clucene/src/CLucene/config/repl_tprintf.cpp new file mode 100644 index 0000000..62cecb7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_tprintf.cpp @@ -0,0 +1,149 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CLucene/util/StringBuffer.h" + +#ifdef __CL_INCLUDE_TPRINTF + +CL_NS_USE(util) + +//print a variable argument to a stream +//currently special number formatting is not supported. it is very minimalistic +void lucene_vfnwprintf(StringBuffer* buffer, size_t count, const wchar_t * format, va_list& valist){ + const wchar_t *iter = format; + StringBuffer* tmp = NULL; + if ( buffer == NULL ) + tmp = _CLNEW StringBuffer; + else + tmp = buffer; + + while (*iter) + { + while (*iter && *iter != '%') + { + tmp->appendChar(*iter++); + } + if (*iter == '%') + { + if (iter[1] == '%') + { + //just print a % + tmp->appendChar('%'); + iter += 2; + continue; + } + + iter++; + switch (*iter) + { + case 's': + { + //todo: this is faulty. it doesn't heed count + + //print a string or null + TCHAR *wstr = va_arg(valist, TCHAR *); + if ( !wstr ) + wstr = _T("(null)"); + + tmp->append(wstr); + iter++; + break; + } + + case 'c': + tmp->appendChar((TCHAR)va_arg(valist, int)); + iter++; + break; + + default: + { + //todo: this is faulty. it doesn't heed count + + if (*iter == 'p') + tmp->appendInt((int32_t)va_arg(valist, long)); + else + { + if (*iter == 'a' || *iter == 'A' || + *iter == 'e' || *iter == 'E' || + *iter == 'f' || *iter == 'F' || + *iter == 'g' || *iter == 'G') + tmp->appendFloat((qreal)va_arg(valist, double),8); + else if (*iter == 'd' || *iter == 'i' ){ + tmp->appendInt((int32_t)va_arg(valist, int)); + }else if (*iter == 'l' ){ + TCHAR b[100]; + _i64tot((int64_t)va_arg(valist, int64_t),b,10); + tmp->append(b); + }/*else{ + TCHAR b[100]; + _i64tot((int64_t)va_arg(valist, void*),b,10); + tmp->append(b); + }*/ + } + iter++; + break; + } + } + } + } + + + if ( buffer == NULL ){ + //we are supposed to be writing to the console +#ifdef _UCS2 + TCHAR* pointer = tmp->getBuffer(); + char ob[MB_LEN_MAX]; + size_t v; + size_t len = tmp->length(); + for (size_t i=0;i 0 ){ + ob[v]='\0'; + fputs(ob,stdout); + } + pointer++; + } + + +#else + fputs(tmp->getBuffer(),stdout); +#endif + _CLDELETE(tmp); + } +} + +//print a list of arguments to a string +int lucene_snwprintf(wchar_t* strbuf, size_t count, const wchar_t * format, ...){ + va_list ap; + va_start(ap, format); + StringBuffer buffer; + lucene_vfnwprintf(&buffer,count,format,ap); + va_end(ap); + + size_t ret = min(count,(size_t)(buffer.length()+1)); + _tcsncpy(strbuf,buffer.getBuffer(),ret); + return ret; +} + +//print a list of arguments to the stdout +void lucene_wprintf(const wchar_t * format, ...){ + va_list ap; + va_start(ap, format); + lucene_vfnwprintf(NULL,LUCENE_INT32_MAX_SHOULDBE,format,ap); + va_end(ap); +} + +//print a variable argument to a string +int lucene_vsnwprintf(wchar_t * strbuf, size_t count, const wchar_t * format, va_list& ap){ + StringBuffer buffer; + lucene_vfnwprintf(&buffer,count,format,ap); + int ret = min((int32_t)count,buffer.length()+1); + _tcsncpy(strbuf,buffer.getBuffer(),ret); + return ret; +} + +#endif //__CL_INCLUDE_TPRINTF diff --git a/3rdparty/clucene/src/CLucene/config/repl_wchar.h b/3rdparty/clucene/src/CLucene/config/repl_wchar.h new file mode 100644 index 0000000..3e05c31 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/repl_wchar.h @@ -0,0 +1,121 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_repl_wchar_h +#define _lucene_repl_wchar_h + +#ifdef _UCS2 + +#ifndef _CL_HAVE_WCSCPY + //copy a string to another string + #error wcscpy is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSNCPY + //copy a specified amount of one string to another string. + #error wcsncpy is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSCAT + //copy a string onto the end of the other string + #error wcscat is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSCHR + //find location of one character + #error wcschr is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSSTR + //find location of a string + #error wcspy is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSLEN + //get length of a string + #error wcslen is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSCMP + //case sensitive compare two strings + #error wcscmp is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSNCMP + //case sensitive compare two strings of a specified length + #error wcsncmp is not defined, and a licensed replacement has not been written yet +#endif + +#ifndef _CL_HAVE_WCSCSPN + //Return the length of the maximum initial segment + //of WCS which contains only wide-characters not in REJECT. + #error wcscspn is not defined, and a licensed replacement has not been written yet +#endif + +#endif //_UCS2 + +//string function replacements +#if defined(LUCENE_USE_INTERNAL_CHAR_FUNCTIONS) || (defined(_UCS2) && !defined(_CL_HAVE_WCSCASECMP)) || (defined(_ASCII) && !defined(_CL_HAVE_STRCASECMP)) + int lucene_tcscasecmp(const TCHAR *, const TCHAR *); + #undef _tcsicmp + #define _tcsicmp lucene_tcscasecmp +#endif +#if defined(LUCENE_USE_INTERNAL_CHAR_FUNCTIONS) || (defined(_UCS2) && !defined(_CL_HAVE_WCSLWR)) || (defined(_ASCII) && !defined(_CL_HAVE_STRLWR)) + TCHAR* lucene_tcslwr( TCHAR* str ); + #undef _tcslwr + #define _tcslwr lucene_tcslwr +#endif + +//conversion functions +#if (defined(_ASCII) && !defined(_CL_HAVE_LLTOA)) || (defined(_UCS2) && !defined(_CL_HAVE_LLTOW)) + TCHAR* lucene_i64tot( int64_t value, TCHAR* str, int radix); + #undef _i64tot + #define _i64tot lucene_i64tot +#endif +#if (defined(_UCS2) && !defined(_CL_HAVE_WCSTOLL)) || (defined(_ASCII) && !defined(_CL_HAVE_STRTOLL)) + int64_t lucene_tcstoi64(const TCHAR* str, TCHAR**end, int radix); + #undef _tcstoi64 + #define _tcstoi64 lucene_tcstoi64 +#endif +#if defined(_UCS2) && !defined(_CL_HAVE_WCSTOD) + double lucene_tcstod(const TCHAR *value, TCHAR **end); + #undef _tcstod + #define _tcstod lucene_tcstod +#endif + +//printf functions +#if defined(_UCS2) && (!defined(_CL_HAVE_SNWPRINTF) || defined(_CL_HAVE_SWPRINTF_BUG) ) + #undef _sntprintf + #define _sntprintf lucene_snwprintf + int lucene_snwprintf(wchar_t* strbuf, size_t count, const wchar_t * format, ...); + + #ifndef __CL_INCLUDE_TPRINTF + #define __CL_INCLUDE_TPRINTF + #endif +#endif +#if defined(_UCS2) && !defined(_CL_HAVE_WPRINTF) + #undef _tprintf + #define _tprintf lucene_wprintf + void lucene_wprintf(const wchar_t * format, ...); + + #ifndef __CL_INCLUDE_TPRINTF + #define __CL_INCLUDE_TPRINTF + #endif +#endif +#if defined(_UCS2) && (!defined(_CL_HAVE_VSNWPRINTF) || defined(_CL_HAVE_SWPRINTF_BUG) ) + #undef _vsntprintf + #define _vsntprintf lucene_vsnwprintf + int lucene_vsnwprintf(wchar_t * strbuf, size_t count, const wchar_t * format, va_list& ap); + + #ifndef __CL_INCLUDE_TPRINTF + #define __CL_INCLUDE_TPRINTF + #endif +#endif + +//todo: if _CL_HAVE_SNPRINTF_BUG fails(snprintf overflow),we should use our own +//function. but we don't have it currently, and our functions are dubious anyway... + +#endif //end of _lucene_repl_wchar_h diff --git a/3rdparty/clucene/src/CLucene/config/threadCSection.h b/3rdparty/clucene/src/CLucene/config/threadCSection.h new file mode 100644 index 0000000..ab18420 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/threadCSection.h @@ -0,0 +1,71 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +//NOTE: do not include this file directly, it is included from lucene internally. + +#ifndef lucene_config_threadCSection_h +#define lucene_config_threadCSection_h +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(util) + + #if !defined(LUCENE_USE_WINDOWS_H) && !defined(_WINDOWS_) && !defined(__MINGW32__) + //we have not explicity included windows.h and windows.h has + //not been included (check _WINDOWS_), then we must define + //our own definitions to the thread locking functions: + struct CRITICAL_SECTION + { + struct critical_section_debug * DebugInfo; + long LockCount; + long RecursionCount; + void * OwningThread; + void * LockSemaphore; + #if defined(_WIN64) + unsigned __int64 SpinCount; + #else + unsigned long SpinCount; + #endif + }; + #endif + + ///a windows implementation of the lock mutex + ///todo: boost has a InterlockedExchange way of locking too. More backwards compatible/faster??? + class mutex_win32 + { + private: + CRITICAL_SECTION mtx; + public: + mutex_win32(const mutex_win32& clone); + mutex_win32(); + ~mutex_win32(); + void lock(); + void unlock(); + }; + + class CLuceneThreadIdCompare + { + public: + + enum + { // parameters for hash table + bucket_size = 4, // 0 < bucket_size + min_buckets = 8 + }; // min_buckets = 2 ^^ N, 0 < N + + bool operator()( DWORD t1, DWORD t2 ) const{ + return t1 < t2; + } + }; + + #define _LUCENE_SLEEP(x) Sleep(x) + #define _LUCENE_THREADMUTEX CL_NS(util)::mutex_win32 + #define _LUCENE_CURRTHREADID GetCurrentThreadId() + #define _LUCENE_THREADID_TYPE DWORD +CL_NS_END + +#endif //lucene_config_threadCSection_h diff --git a/3rdparty/clucene/src/CLucene/config/threadPthread.h b/3rdparty/clucene/src/CLucene/config/threadPthread.h new file mode 100644 index 0000000..d0ed9c4 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/threadPthread.h @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +//NOTE: do not include this file directly, it is included from lucene internally. + +#ifndef lucene_config_threadPthread_h +#define lucene_config_threadPthread_h + +#include + +CL_NS_DEF(util) + +///a posix implementation of the lock mutex +///todo: we need a spinlock implemenation for usage in reference counting +class mutex_pthread +{ +private: + pthread_mutex_t mtx; + +public: + mutex_pthread(const mutex_pthread& clone); + mutex_pthread(); + ~mutex_pthread(); + void lock(); + void unlock(); + +private: + #ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE + pthread_t lockOwner; + unsigned int lockCount; + #endif +}; + +#define _LUCENE_SLEEP(x) usleep(x*1000) //_LUCENE_SLEEP should be in millis, usleep is in micros +#define _LUCENE_THREADMUTEX CL_NS(util)::mutex_pthread +#define _LUCENE_CURRTHREADID pthread_self() +#define _LUCENE_THREADID_TYPE pthread_t + +class CLuceneThreadIdCompare +{ +public: + enum + { // parameters for hash table + bucket_size = 4, // 0 < bucket_size + min_buckets = 8 + }; // min_buckets = 2 ^^ N, 0 < N + + bool operator()( pthread_t t1, pthread_t t2 ) const{ + return t1 < t2; + } +}; + + +CL_NS_END + +#endif //lucene_config_threadPthread_h diff --git a/3rdparty/clucene/src/CLucene/config/threads.cpp b/3rdparty/clucene/src/CLucene/config/threads.cpp new file mode 100644 index 0000000..427e580 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/threads.cpp @@ -0,0 +1,162 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" + +#ifndef _CL_DISABLE_MULTITHREADING +CL_NS_DEF(util) + + +mutexGuard::mutexGuard(const mutexGuard& clone){ + //no autoclone + mrMutex = NULL; +} +mutexGuard::mutexGuard( _LUCENE_THREADMUTEX& rMutex ) : + mrMutex(&rMutex) +{ + mrMutex->lock(); +} +mutexGuard::~mutexGuard() +{ + mrMutex->unlock(); +} + +#if defined(_LUCENE_DONTIMPLEMENT_THREADMUTEX) + //do nothing + #if defined(_LUCENE_PRAGMA_WARNINGS) + #pragma message ("==================Not implementing any thread mutex==================") + #else + #warning "==================Not implementing any thread mutex==================" + #endif + + + +#elif defined(_CL_HAVE_WIN32_THREADS) + #include "CLucene/config/threadCSection.h" + + #if !defined(LUCENE_USE_WINDOWS_H) && !defined(_WINDOWS_) + //we have not explicity included windows.h and windows.h has + //not been included (check _WINDOWS_), then we must define + //our own definitions to the thread locking functions: + extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *); + extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *); + extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); + extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); + extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); + #endif + + mutex_win32::mutex_win32(const mutex_win32& clone){ + InitializeCriticalSection(&mtx); + } + mutex_win32::mutex_win32() + { + InitializeCriticalSection(&mtx); + } + + mutex_win32::~mutex_win32() + { + DeleteCriticalSection(&mtx); + } + + void mutex_win32::lock() + { + EnterCriticalSection(&mtx); + } + + void mutex_win32::unlock() + { + LeaveCriticalSection(&mtx); + } + + + +#elif defined(_CL_HAVE_PTHREAD) + #include "CLucene/config/threadPthread.h" + + #ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE + bool mutex_pthread_attr_initd=false; + pthread_mutexattr_t mutex_pthread_attr; + #endif + + #ifdef _CL__CND_DEBUG + #define _CLPTHREAD_CHECK(c,m) CND_PRECONDITION(c==0,m) + #else + #define _CLPTHREAD_CHECK(c,m) c; + #endif + + mutex_pthread::mutex_pthread(const mutex_pthread& clone){ + #ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE + _CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed") + #else + #if defined(__hpux) && defined(_DECTHREADS_) + _CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed") + #else + _CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed") + #endif + lockCount=0; + lockOwner=0; + #endif + } + mutex_pthread::mutex_pthread() + { + #ifdef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE + if ( mutex_pthread_attr_initd == false ){ + pthread_mutexattr_init(&mutex_pthread_attr); + pthread_mutexattr_settype(&mutex_pthread_attr, PTHREAD_MUTEX_RECURSIVE); + mutex_pthread_attr_initd = true; + } + _CLPTHREAD_CHECK(pthread_mutex_init(&mtx, &mutex_pthread_attr), "mutex_pthread(clone) constructor failed") + #else + #if defined(__hpux) && defined(_DECTHREADS_) + _CLPTHREAD_CHECK(pthread_mutex_init(&mtx, pthread_mutexattr_default), "mutex_pthread(clone) constructor failed") + #else + _CLPTHREAD_CHECK(pthread_mutex_init(&mtx, 0), "mutex_pthread(clone) constructor failed") + #endif + lockCount=0; + lockOwner=0; + #endif + } + + mutex_pthread::~mutex_pthread() + { + _CLPTHREAD_CHECK(pthread_mutex_destroy(&mtx), "~mutex_pthread destructor failed") + } + + void mutex_pthread::lock() + { + #ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE + pthread_t currentThread = pthread_self(); + if( pthread_equal( lockOwner, currentThread ) ) { + ++lockCount; + } else { + _CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock") + lockOwner = currentThread; + lockCount = 1; + } + #else + _CLPTHREAD_CHECK(pthread_mutex_lock(&mtx), "mutex_pthread::lock") + #endif + } + + void mutex_pthread::unlock() + { + #ifndef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE + --lockCount; + if( lockCount == 0 ) + { + lockOwner = 0; + _CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock") + } + #else + _CLPTHREAD_CHECK(pthread_mutex_unlock(&mtx), "mutex_pthread::unlock") + #endif + } + +#endif //thread impl choice + + +CL_NS_END +#endif //!_CL_DISABLE_MULTITHREADING diff --git a/3rdparty/clucene/src/CLucene/config/utf8.cpp b/3rdparty/clucene/src/CLucene/config/utf8.cpp new file mode 100644 index 0000000..14ccf5a --- /dev/null +++ b/3rdparty/clucene/src/CLucene/config/utf8.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (C) 1999 Tom Tromey + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * + ************************************************ + * Also licensed with permission from Tom Tromey + * and Owen Taylor under the Apache license. + * Original location: + * http://cvs.gnome.org/viewcvs/glib/glib/gutf8.c?rev=1.50&view=log + ************************************************ + * + * Copyright 2003-2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "CLucene/StdHeader.h" + +typedef unsigned long gunichar; +typedef unsigned char guchar; + +#define UTF8_COMPUTE(Char, Mask, Len) \ + if (Char < 128) \ + { \ + Len = 1; \ + Mask = 0x7f; \ + } \ + else if ((Char & 0xe0) == 0xc0) \ + { \ + Len = 2; \ + Mask = 0x1f; \ + } \ + else if ((Char & 0xf0) == 0xe0) \ + { \ + Len = 3; \ + Mask = 0x0f; \ + } \ + else if ((Char & 0xf8) == 0xf0) \ + { \ + Len = 4; \ + Mask = 0x07; \ + } \ + else if ((Char & 0xfc) == 0xf8) \ + { \ + Len = 5; \ + Mask = 0x03; \ + } \ + else if ((Char & 0xfe) == 0xfc) \ + { \ + Len = 6; \ + Mask = 0x01; \ + } \ + else \ + Len = -1; + +/*#define UTF8_LENGTH(Char) \ + ((Char) < 0x80 ? 1 : \ + ((Char) < 0x800 ? 2 : \ + ((Char) < 0x10000 ? 3 : \ + ((Char) < 0x200000 ? 4 : \ + ((Char) < 0x4000000 ? 5 : 6)))))*/ + + +#define UTF8_GET(Result, Chars, Count, Mask, Len) \ + (Result) = (Chars)[0] & (Mask); \ + for ((Count) = 1; (Count) < (Len); ++(Count)) \ + { \ + if (((Chars)[(Count)] & 0xc0) != 0x80) \ + { \ + (Result) = -1; \ + break; \ + } \ + (Result) <<= 6; \ + (Result) |= ((Chars)[(Count)] & 0x3f); \ + } + + +/** + * lucene_wctoutf8: + * @c: a ISO10646 character code + * @outbuf: output buffer, must have at least 6 bytes of space. + * If %NULL, the length will be computed and returned + * and nothing will be written to @outbuf. + * + * Converts a single character to UTF-8. + * + * Return value: number of bytes written + **/ +size_t lucene_wctoutf8(char * outbuf, const wchar_t ch) +{ + gunichar c = ch; + guchar len = 0; + int first; + int i; + + if (c < 0x80) + { + first = 0; + len = 1; + } + else if (c < 0x800) + { + first = 0xc0; + len = 2; + } + else if (c < 0x10000) + { + first = 0xe0; + len = 3; + } + else if (c < 0x200000) + { + first = 0xf0; + len = 4; + } + else if (c < 0x4000000) + { + first = 0xf8; + len = 5; + } + else + { + first = 0xfc; + len = 6; + } + + if (outbuf) + { + for (i = len - 1; i > 0; --i) + { + outbuf[i] = (char)((c & 0x3f) | 0x80); + c >>= 6; + } + outbuf[0] = c | first; + } + + return len; +} + + +/** + * lucene_utf8towc: + * @p: a pointer to Unicode character encoded as UTF-8 + * + * Converts a sequence of bytes encoded as UTF-8 to a Unicode character. + * If @p does not point to a valid UTF-8 encoded character, results are + * undefined. If you are not sure that the bytes are complete + * valid Unicode characters, you should use lucene_utf8towc_validated() + * instead. + * + * Return value: the resulting character + **/ +size_t lucene_utf8towc(wchar_t *pwc, const char *p, size_t n) +{ + int i, mask = 0; + int result; + unsigned char c = (unsigned char) *p; + int len=0; + + UTF8_COMPUTE (c, mask, len); + if (len == -1) + return 0; + UTF8_GET (result, p, i, mask, len); + + *pwc = result; + return len; +} + + +//this function was not taken from gnome +size_t lucene_wcstoutf8(char * result, const wchar_t * str, size_t result_length){ + char *p=result; + int i = 0; + + while (p < result + result_length-1 && str[i] != 0) + p += lucene_wctoutf8(p,str[i++]); + + *p = '\0'; + + return p-result; +} +//this function was not taken from gnome +size_t lucene_utf8towcs(wchar_t * result, const char * str, size_t result_length){ + char *sp = (char*)str; + wchar_t *rp = result; + int i = 0; + + while (rp < result + result_length && *sp!=0){ + size_t r = lucene_utf8towc(rp,sp,6); + if ( r == -1 ) + return 0; + sp += r; + rp++; + } + + if ( sp-str < result_length ) + *rp = '\0'; + + size_t ret = sp-str; + return ret; +} +//get the number of bytes that make up the utf8 character. +//this function was not taken from gnome +size_t lucene_utf8charlen(const char *p) +{ + int mask = 0; + int len=0; + unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len); + return len; +} diff --git a/3rdparty/clucene/src/CLucene/debug/condition.cpp b/3rdparty/clucene/src/CLucene/debug/condition.cpp new file mode 100644 index 0000000..8554194 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/debug/condition.cpp @@ -0,0 +1,80 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "condition.h" +#include "CLucene/util/Misc.h" +#ifdef _CL__CND_DEBUG + +#define __CND_STR_PRECONDITION "PRECONDITION" +#define __CND_STR_CONDITION "CONDITION" +#define __CND_STR_WARNING "WARNING" +#define __CND_STR_MESSAGE "MESSAGE" +#define __CND_STR_DEBUGMESSAGE "DEBUG MESSAGE" +#define __CND_STR_EXIT "EXIT" + +#ifndef _CND_DEBUG_DONTIMPLEMENT_OUTDEBUG +void _Cnd_OutDebug( const char* FormattedMsg, const char* StrTitle, const char* File, int32_t Line, int32_t Title, const char* Mes2, int32_t fatal ){ + #ifdef __WINDOWS_H + /*Display a standard messagebox*/ + MessageBox(NULL, FormattedMsg, StrTitle, (fatal==1 ? MB_ICONSTOP:MB_ICONEXCLAMATION) | MB_OK | MB_TASKMODAL); + #else + printf("%s\n",FormattedMsg); + #endif + + #if defined(_CND_DEBUG_WARN_DEBUGGER) /*attempt to signal windows debugger*/ + OutputDebugString(FormattedMsg); + DebugBreak(); /*Position debugger just before exit program*/ + #endif + + if ( fatal ) + debugFatalExit(1); +} +#endif + +void __cnd_FormatDebug( const char* File, int32_t Line, int32_t Title, const char* Mes2, int32_t fatal ) { + char M[512]; + char* StrTitle = NULL; + + if( Mes2 ) + _snprintf(M,512,"file:%s line:%d\n%s",File,Line,Mes2); + else + _snprintf(M,512,"file:%s line:%d",File,Line); + + /*Determine which title to use*/ + switch( Title ) { + case CND_STR_PRECONDITION: { + StrTitle = __CND_STR_PRECONDITION; + break; + } + case CND_STR_CONDITION: { + StrTitle = __CND_STR_CONDITION; + break; + } + case CND_STR_WARNING: { + StrTitle = __CND_STR_WARNING; + break; + } + case CND_STR_MESSAGE: { + StrTitle = __CND_STR_MESSAGE; + break; + } + case CND_STR_DEBUGMESSAGE: { + StrTitle = __CND_STR_DEBUGMESSAGE; + break; + } + case CND_STR_EXIT: { + StrTitle = __CND_STR_EXIT; + break; + } + default: + break; + }/*switch*/ + + _Cnd_OutDebug(M, StrTitle, File, Line, Title, Mes2, fatal); +} +#endif + diff --git a/3rdparty/clucene/src/CLucene/debug/condition.h b/3rdparty/clucene/src/CLucene/debug/condition.h new file mode 100644 index 0000000..ab227e5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/debug/condition.h @@ -0,0 +1,64 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef __CONDITION_H +#define __CONDITION_H + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +/* +To enable condition debugging uncomment _CND_DEBUG in CLConfig.h +*/ + +#ifdef _CL__CND_DEBUG /* Don't include the debug code */ + #ifndef CND_STR_DEFINES + #define CND_STR_DEFINES + #define CND_STR_PRECONDITION 1 + #define CND_STR_CONDITION 2 + #define CND_STR_WARNING 3 + #define CND_STR_MESSAGE 4 + #define CND_STR_DEBUGMESSAGE 5 + #define CND_STR_EXIT 6 + #endif + + /* _CL__CND_DEBUG defined, include debug code */ + + #ifdef _CND_NODEBUGTEXT + #define CND_PRECONDITION(cond,usermessage) CND__EXITCONDITION(cond,__FILE__,__LINE__,CND_STR_PRECONDITION,NULL) + #define CND_CONDITION(cond,usermessage) CND__EXITCONDITION(cond,__FILE__,__LINE__,CND_STR_CONDITION,NULL) + #define CND_WARNING(cond,usermessage) CND__CONDITION(cond,__FILE__,__LINE__,CND_STR_WARNING,NULL) + #define CND_MESSAGE(cond,usermessage) CND__CONDITION(cond,__FILE__,__LINE__,CND_STR_MESSAGE,NULL) + #define CND_DEBUGMESSAGE(usermessage) CND__MESSAGE(__FILE__,__LINE__,CND_STR_DEBUGMESSAGE,NULL) + #else + #define CND_PRECONDITION(cond,usermessage) CND__EXITCONDITION(cond,__FILE__,__LINE__,CND_STR_PRECONDITION,usermessage) + #define CND_CONDITION(cond,usermessage) CND__EXITCONDITION(cond,__FILE__,__LINE__,CND_STR_CONDITION,usermessage) + #define CND_WARNING(cond,usermessage) CND__CONDITION(cond,__FILE__,__LINE__,CND_STR_WARNING,usermessage) + #define CND_MESSAGE(cond,usermessage) CND__CONDITION(cond,__FILE__,__LINE__,CND_STR_MESSAGE,usermessage) + #define CND_DEBUGMESSAGE(usermessage) CND__MESSAGE(__FILE__,__LINE__,CND_STR_DEBUGMESSAGE,usermessage) + #endif + + //if _CND_DEBUG_DONTIMPLEMENT_OUTDEBUG is defined, then you must implement + //this routine in the client application. The debug callback can then + //be better customised to the host application. + //Here is the default implementation: + void _Cnd_OutDebug( const char* FormattedMsg, const char* StrTitle, const char* File, int32_t Line, int32_t Title, const char* Mes2, int32_t fatal ); + + void __cnd_FormatDebug( const char* File, int32_t Line, int32_t Title, const char* Mes2, int32_t fatal ); + #define CND__EXIT(file,line,title,mes2) {__cnd_FormatDebug(file,line,title,mes2,1);} + #define CND__EXITCONDITION(cond,file,line,title,mes2) {if(!(cond)){__cnd_FormatDebug(file,line,title,mes2,1);}} + #define CND__CONDITION(cond,file,line,title,mes2) {if(!(cond)){__cnd_FormatDebug(file,line,title,mes2,0);}} + #define CND__MESSAGE(file,line,title,mes2) {__cnd_FormatDebug(file,line,title,mes2,0);} +#else + #define CND_PRECONDITION(cond, usermessage) + #define CND_CONDITION(cond, usermessage) + #define CND_WARNING(cond,usermessage) + #define CND_MESSAGE(cond,usermessage) + #define CND_DEBUGMESSAGE(usermessage) +#endif + +#endif diff --git a/3rdparty/clucene/src/CLucene/debug/error.cpp b/3rdparty/clucene/src/CLucene/debug/error.cpp new file mode 100644 index 0000000..53ea0e9 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/debug/error.cpp @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" + +CL_NS_USE(util) + + +#ifdef _LUCENE_DISABLE_EXCEPTIONS + #ifdef _LUCENE_PRAGMA_WARNINGS + #pragma message ("==================Lucene exceptions are disabled==================") + #else + #warning "==================Lucene exceptions are disabled==================" + #endif +#else + CLuceneError::CLuceneError(int num, const char* str, bool ownstr) + { + error_number = num; + _awhat=STRDUP_AtoA(str); + _twhat=NULL; + if ( ownstr ) + _CLDELETE_CaARRAY(str); + } + + CLuceneError::CLuceneError(const CLuceneError& clone) + { + this->error_number = clone.error_number; + this->_awhat = NULL; + this->_twhat = NULL; + + if ( clone._awhat != NULL ) + this->_awhat = STRDUP_AtoA(clone._awhat); + if ( clone._twhat != NULL ) + this->_twhat = STRDUP_TtoT(clone._twhat); + } + CLuceneError::~CLuceneError() throw(){ + _CLDELETE_CARRAY(_twhat); + _CLDELETE_CaARRAY(_awhat); + } + char* CLuceneError::what(){ +#ifdef _ASCII + if ( _twhat != NULL ) + return _twhat; +#endif + if ( _awhat == NULL ) + _awhat = STRDUP_TtoA(_twhat); + return _awhat; + } + TCHAR* CLuceneError::twhat(){ +#ifdef _ASCII + if ( _awhat != NULL ) + return _awhat; +#endif + if ( _twhat == NULL ) + _twhat = STRDUP_AtoT(_awhat); + return _twhat; + } + +#ifndef _ASCII + CLuceneError::CLuceneError(int num, const TCHAR* str, bool ownstr) + { + error_number = 0; + _awhat=NULL; + _twhat=STRDUP_TtoT(str); + if ( ownstr ) + _CLDELETE_CARRAY(str); + } +#endif + +#endif //_LUCENE_DISABLE_EXCEPTIONS diff --git a/3rdparty/clucene/src/CLucene/debug/error.h b/3rdparty/clucene/src/CLucene/debug/error.h new file mode 100644 index 0000000..5abcc80 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/debug/error.h @@ -0,0 +1,74 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_debug_error_ +#define _lucene_debug_error_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#define CL_ERR_UNKNOWN -1 +#define CL_ERR_IO 1 +#define CL_ERR_NullPointer 2 +#define CL_ERR_Runtime 3 +#define CL_ERR_IllegalArgument 4 +#define CL_ERR_Parse 5 +#define CL_ERR_TokenMgr 6 +#define CL_ERR_UnsupportedOperation 7 +#define CL_ERR_InvalidState 8 +#define CL_ERR_IndexOutOfBounds 9 +#define CL_ERR_TooManyClauses 10 +#define CL_ERR_RAMTransaction 11 +#define CL_ERR_InvalidCast 12 +#define CL_ERR_IllegalState 13 + + + +//////////////////////////////////////////////////////// +//error try/throw/catch definitions +//////////////////////////////////////////////////////// +#ifdef _CL_DISABLE_NATIVE_EXCEPTIONS + /*#define try _jpr_Try + #define _CLCATCH _jpr_Catch + #define _CLFINALLY(x) xxxx + #define _CLTHROWA(y) _jpr_Throw + #define _THROWA_DEL(y) _jpr_Throw + #define _RETHROW(x) _jpr_Throw + #define _CLTHROWT(y) _jpr_Throw + + #define _THROWS ,_jpr_Throws*/ +#else + class CLuceneError + { + int error_number; + char* _awhat; + TCHAR* _twhat; + public: + CLuceneError(const CLuceneError& clone); + CLuceneError(int num, const char* str, bool ownstr); +#ifdef _UCS2 + CLuceneError(int num, const TCHAR* str, bool ownstr); +#endif + int number(){return error_number;} + char* what(); + TCHAR* twhat(); + ~CLuceneError() throw(); + }; + + //#define _THROWS //does nothing + #define _CLFINALLY(x) catch(...){ x; throw; } x //note: code x is not run if return is called + #define _CLTHROWA(number, str) throw CLuceneError(number, str,false) + #define _CLTHROWT(number, str) throw CLuceneError(number, str,false) + #define _CLTHROWA_DEL(number, str) throw CLuceneError(number, str,true) //throw a string ensures the value is deleted + #define _CLTHROWT_DEL(number, str) throw CLuceneError(number, str,true) //throw a string ensures the value is deleted + + +#endif //_LUCENE_DISABLE_EXCEPTIONS +// +//////////////////////////////////////////////////////// + +#endif diff --git a/3rdparty/clucene/src/CLucene/debug/lucenebase.h b/3rdparty/clucene/src/CLucene/debug/lucenebase.h new file mode 100644 index 0000000..86cdae1 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/debug/lucenebase.h @@ -0,0 +1,75 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_debug_lucenebase_ +#define _lucene_debug_lucenebase_ + +#ifdef _LUCENE_PRAGMA_ONCE +# pragma once +#endif + +CL_NS_DEF(debug) + +//Lucenebase is the superclass of all clucene objects. It provides +//memory debugging tracking and/or reference counting +class LuceneBase{ +public: +#ifdef LUCENE_ENABLE_MEMLEAKTRACKING + static void* operator new (size_t size); + static void operator delete (void *p); + int32_t __cl_initnum; ///< The order that the object was created at. This is then used to do a lookup in the objects list + + static void* operator new (size_t size, char const * file, int32_t line); + static void operator delete (void *p, char const * file, int32_t line); + + static void* __cl_voidpadd(void* data, const char* file, int line, size_t size); ///dummy__see_mem_h_for_details +#endif +#define _CL_POINTER(x) (x==NULL?NULL:(x->__cl_addref()>=0?x:x)) //return a add-ref'd object +#define LUCENE_REFBASE public CL_NS(debug)::LuceneBase //this is the base of classes who *always* need refcounting + +#if defined(_DEBUG) + #if !defined(LUCENE_BASE_CHECK) + #define LUCENE_BASE_CHECK(x) + #endif +#else + #undef LUCENE_BASE_CHECK + #define LUCENE_BASE_CHECK(x) +#endif + +//Macro for creating new arrays +#ifdef LUCENE_ENABLE_MEMLEAKTRACKING + #define _CL_NEWARRAY(type,size) (type*)CL_NS(debug)::LuceneBase::__cl_voidpadd(new type[(size_t)size],__FILE__,__LINE__,(size_t)size); + #define _CLDELETE_ARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((const void*)x,__FILE__,__LINE__); delete [] x; x=NULL;} + #define _CLDELETE_LARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((const void*)x,__FILE__,__LINE__);delete [] x;} + #ifndef _CLDELETE_CARRAY + #define _CLDELETE_CARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((const void*)x,__FILE__,__LINE__);delete [] x; x=NULL;} + #define _CLDELETE_LCARRAY(x) if (x!=NULL){CL_NS(debug)::LuceneBase::__cl_voidpremove((const void*)x,__FILE__,__LINE__);delete [] x;} + #endif +#else + #define _CL_NEWARRAY(type,size) new type[size] + #define _CLDELETE_ARRAY(x) if (x!=NULL){delete [] x; x=NULL;} + #define _CLDELETE_LARRAY(x) if (x!=NULL){delete [] x;} + #ifndef _CLDELETE_CARRAY + #define _CLDELETE_CARRAY(x) if (x!=NULL){delete [] x; x=NULL;} + #define _CLDELETE_LCARRAY(x) if (x!=NULL){delete [] x;} + #endif +#endif +//a shortcut for deleting a carray and all its contents +#define _CLDELETE_CARRAY_ALL(x) {if ( x!=NULL ){ for(int xcda=0;x[xcda]!=NULL;xcda++)_CLDELETE_CARRAY(x[xcda]);}_CLDELETE_ARRAY(x)}; +#define _CLDELETE_ARRAY_ALL(x) {if ( x!=NULL ){ for(int xcda=0;x[xcda]!=NULL;xcda++)_CLDELETE(x[xcda]);}_CLDELETE_ARRAY(x)}; +#ifndef _CLDELETE_CaARRAY + #define _CLDELETE_CaARRAY _CLDELETE_CARRAY + #define _CLDELETE_LCaARRAY _CLDELETE_LCARRAY +#endif + +//Macro for deleting +#ifdef LUCENE_ENABLE_REFCOUNT + #define _CLDELETE(x) if (x!=NULL){ CND_PRECONDITION((x)->__cl_refcount>=0,"__cl_refcount was < 0"); if ((x)->__cl_decref() <= 0)delete x; x=NULL; } + #define _CLLDELETE(x) if (x!=NULL){ CND_PRECONDITION((x)->__cl_refcount>=0,"__cl_refcount was < 0"); if ((x)->__cl_decref() <= 0)delete x; } +#else + #define _CLDELETE(x) if (x!=NULL){ LUCENE_BASE_CHECK(x); delete x; x=NULL; } + #define _CLLDELETE(x) if (x!=NULL){ LUCENE_BASE_CHECK(x); delete x; } +#endif + +//_CLDECDELETE deletes objects which are *always* refcounted +#define _CLDECDELETE(x) if (x!=NULL){ CND_PRECONDITION((x)->__cl_refcount>=0,"__cl_refcount was < 0"); if ((x)->__cl_decref() <= 0)delete x; x=NULL; } +#define _CLLDECDELETE(x) if (x!=NULL){ CND_PRECONDITION((x)->__cl_refcount>=0,"__cl_refcount was < 0"); if ((x)->__cl_decref() <= 0)delete x; } + +//_VDelete should be used for deleting non-clucene objects. +//when using reference counting, _CLDELETE casts the object +//into a LuceneBase*. +#define _CLVDELETE(x) if(x!=NULL){delete x; x=NULL;} + +template +class Array: LUCENE_BASE{ +public: + T* values; + size_t length; + + void deleteAll(){ + for (size_t i=0;ivalues = values; + this->length = length; + } + Array(size_t length){ + this->values = _CL_NEWARRAY(T,length); + this->length = length; + } + ~Array(){} + + const T operator[](size_t _Pos) const + { + if (length <= _Pos){ + _CLTHROWA(CL_ERR_IllegalArgument,"vector subscript out of range"); + } + return (*(values + _Pos)); + } + T operator[](size_t _Pos) + { + if (length <= _Pos){ + _CLTHROWA(CL_ERR_IllegalArgument,"vector subscript out of range"); + } + return (*(values + _Pos)); + } + +}; + +#endif //_lucene_debug_lucenebase_ diff --git a/3rdparty/clucene/src/CLucene/debug/memtracking.cpp b/3rdparty/clucene/src/CLucene/debug/memtracking.cpp new file mode 100644 index 0000000..544a125 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/debug/memtracking.cpp @@ -0,0 +1,371 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CLucene/util/Misc.h" + +bool _lucene_disable_debuglogging = true; //if LUCENE_ENABLE_CONSTRUCTOR_LOG is on, dont do log if this is true +bool _lucene_run_objectcheck = false; //run a memory check before deleting objects +int _lucene_counter_break = -1; //to break at this item, change this + //and put break points at points below + +CL_NS_USE(util) +CL_NS_DEF(debug) + +#ifdef LUCENE_ENABLE_MEMLEAKTRACKING +int32_t _instance_counter = 0; //counter for initnumber + +struct _file{ + int32_t refcount; ///times this has been used + char* value; ///reference to the the basefile +}; //structure for name counting +struct _pointers{ + _file* file; + int32_t initline; + int32_t initnumber; +};//structure for pointer-filename references + +typedef CL_NS(util)::CLSet > defFile; +typedef CL_NS(util)::CLSet,Deletor::Dummy,Deletor::Void<_pointers> > defPointer; +typedef CL_NS(util)::CLSet,Deletor::Dummy,Deletor::Void<_pointers> > defVoid; + +DEFINE_MUTEX(memleak_lock) +defFile LuceneBase_Files(false,true); //list of filenames used +defPointer LuceneBase_Pointers(false,true); //list of pointers counted +defVoid LuceneBase_Voids(false,true); //list of arbitary data added + +//variables to trim filenames to just the base names +char _files_trim_string[CL_MAX_DIR]; +int32_t _files_trim_start=-1; + +//trim the filename and return the refcounted _file* structure +_file* get_file(const char* file){ + if ( _files_trim_start == -1 ){ + //this trims the start of the name file name so + //that the whole of the filename is not stored - more asthetic :) + //need to find the base + _files_trim_start = strlen(__FILE__) - 21; //(length of debug/memtracking.cpp) + strcpy(_files_trim_string,__FILE__); + _files_trim_string[_files_trim_start] = 0; + } + if ( strncmp(file,_files_trim_string,_files_trim_start) == 0 ){ + //this file should be within the same directory area as we found lucenebase.cpp + //to be, lets trim the start + file+=_files_trim_start; + } + + //now return an existing files structure (with refcount++) or create a new one + defFile::iterator itr = LuceneBase_Files.find((const char*)file); + if ( itr != LuceneBase_Files.end() ){ + _file* bf = itr->second; + bf->refcount++; + return bf; + }else{ + _file* ref = new _file; + ref->value = new char[strlen(file)+1]; //cannot use _CL_NEWARRAY otherwise recursion + strcpy(ref->value,file); + + ref->refcount = 1; + LuceneBase_Files.insert(pair(ref->value,ref)); + return ref; + } +} + +void remove_file(_file* bf){ + bf->refcount--; + if ( bf->refcount <= 0 ){ + defFile::iterator fi = LuceneBase_Files.find(bf->value); + CND_PRECONDITION(fi!=LuceneBase_Files.end(),"fi==NULL"); + delete[] bf->value; + LuceneBase_Files.removeitr(fi); + } +} + +#ifdef LUCENE_ENABLE_CONSTRUCTOR_LOG + void constructor_log(const char* type,const char* file,const int line, const int size){ + if ( _lucene_disable_debuglogging ){ + FILE* f = fopen("clucene.log","a"); + char buf[CL_MAX_DIR+5]; + sprintf(buf,"%s,%s,%d,%d\n",type,file,line,size); + fwrite(buf,sizeof(char),strlen(buf),f); + fclose(f); + } + } + #define CONSTRUCTOR_LOG(type,file,line,size) constructor_log(type,file,line,size) +#else + #define CONSTRUCTOR_LOG(type,file,line,size) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// the _CLNEW&_CLDELETE new/delete operators +//////////////////////////////////////////////////////////////////////////////// +void* LuceneBase::operator new (size_t size, const char * file, int32_t line) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + void* p = malloc (size); + LuceneBase* lb = (LuceneBase*)p; + + //create the pointer struct + _file* br = get_file(file); + _pointers* bp = new _pointers; + bp->file = br; + bp->initnumber = _instance_counter++; + bp->initline = line; + + //associate this object with the pointer + lb->__cl_initnum = bp->initnumber; + + //break if necessary + if ( _lucene_counter_break == lb->__cl_initnum ) + CLDebugBreak(); //put break point here + + //add the pointer object + LuceneBase_Pointers.insert(pair(lb, bp)); + + CONSTRUCTOR_LOG("newobj",file,line,size); + return p; +} +void LuceneBase::operator delete (void *p, char const * file, int32_t line) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + LuceneBase* lb=(LuceneBase*)p; + + defPointer::iterator itr = LuceneBase_Pointers.find(lb); + if ( itr != LuceneBase_Pointers.end() ){ + _pointers* bp = itr->second; + remove_file(bp->file); + + LuceneBase_Pointers.removeitr(itr); + }else{ + //break + } + free(p); +} + +/////////////////////////////////////////////////////////////////////////// +// the generic new/delete operators +/////////////////////////////////////////////////////////////////////////// +void* LuceneBase::operator new (size_t size) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + void* p = malloc (size); + LuceneBase* lb = (LuceneBase*)p; + + //create the pointer struct + _file* br = get_file("undefined"); + _pointers* bp = new _pointers; + bp->file = br; + bp->initnumber = _instance_counter++; + bp->initline = -1; + + //associate this object with the pointer + lb->__cl_initnum = bp->initnumber; + + //break if necessary + if ( _lucene_counter_break == lb->__cl_initnum ) + CLDebugBreak(); + + //add the pointer object + LuceneBase_Pointers.insert(pair(lb,bp)); + + CONSTRUCTOR_LOG("newobj","unknown",-1,size); + return p; +} +void LuceneBase::operator delete (void *p) +{ + SCOPED_LOCK_MUTEX(memleak_lock) + + LuceneBase* lb=(LuceneBase*)p; + + defPointer::iterator itr = LuceneBase_Pointers.find(lb); + if ( itr != LuceneBase_Pointers.end() ){ + _pointers* bp = itr->second; + remove_file(bp->file); + LuceneBase_Pointers.removeitr(itr); + }else{ + CLDebugBreak(); + } + free(p); +} + +/////////////////////////////////////////////////////////////////////////// +// other memtracking functions +/////////////////////////////////////////////////////////////////////////// +void LuceneBase::__cl_unregister(const void* obj){ + SCOPED_LOCK_MUTEX(memleak_lock) + + LuceneBase* lb=(LuceneBase*)obj; + defPointer::iterator itr = LuceneBase_Pointers.find(lb); + CND_PRECONDITION(itr != LuceneBase_Pointers.end(),"__cl_unregister object not found"); + _pointers* bp = itr->second; + LuceneBase_Pointers.removeitr(itr); +} + +void* LuceneBase::__cl_voidpadd(void* data, const char* file, int line,size_t size){ + SCOPED_LOCK_MUTEX(memleak_lock) + + _file* br = get_file(file); + _pointers* bp = new _pointers; + bp->file = br; + bp->initnumber = _instance_counter++; + bp->initline = line; + + LuceneBase_Voids.insert(pair(data,bp)); + CONSTRUCTOR_LOG("newarr",file,line,size); + return data; +} +void LuceneBase::__cl_voidpremove(const void* data, const char* file, int line){ + SCOPED_LOCK_MUTEX(memleak_lock) + defVoid::iterator itr = LuceneBase_Voids.find(data); + if ( itr != LuceneBase_Voids.end() ){ + _pointers* bp = itr->second; + remove_file(bp->file); + LuceneBase_Voids.removeitr(itr); + }else{ + printf("Data deleted when not added with _CL_NEWARRAY in %s at %d\n",file,line); + } +} + + +//////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////// +//The lucene base memory leak printout functions +//////////////////////////////////////////////////////////// +//static +void __internalcl_PrintUnclosedObject(bool isObject, string& sb,_pointers* bp,_file* bf, bool print){ + TCHAR ttmp[100]; + char atmp[100]; + + sb.append(" "); + { + _i64tot(bp->initnumber,ttmp,10); + STRCPY_TtoA(atmp,ttmp,100); + sb.append(atmp); + } + if ( isObject ){ + sb.append("(obj). "); + }else{ + sb.append(". "); + } + sb.append(bf->value); + sb.append(", line "); + { + _i64tot(bp->initline,ttmp,10); + STRCPY_TtoA(atmp,ttmp,100); + sb.append(atmp); + } + sb.append("\n"); + + if ( print && sb.length() > 0 ){ + printf("%s\n", sb.c_str()); + sb = ""; + } +} +char* __internalcl_GetUnclosedObjects(bool print){ + TCHAR ttmp[100]; + char atmp[100]; + SCOPED_LOCK_MUTEX(memleak_lock) + + string sb; + bool unknowns = false; + if ( LuceneBase_Pointers.size() > 0 ){ + { + _i64tot(LuceneBase_Pointers.size(),ttmp,10); + STRCPY_TtoA(atmp,ttmp,100); + sb.append(atmp); + } + sb.append(" clucene objects are still open\n"); + + defPointer::iterator itr = LuceneBase_Pointers.begin(); + while ( itr != LuceneBase_Pointers.end() ){ + _pointers* bp = itr->second; + _file* bf = bp->file; + + if ( bp->initline == -1 ) + unknowns = true; + __internalcl_PrintUnclosedObject(true, sb,bp,bf,print); + + ++itr; + } + + defVoid::iterator itr2 = LuceneBase_Voids.begin(); + while ( itr2 != LuceneBase_Voids.end() ){ + _pointers* bp = itr2->second; + _file* bf = bp->file; + + if ( bp->initline == -1 ) + unknowns = true; + __internalcl_PrintUnclosedObject(false, sb,bp,bf,print); + + itr2++; + } + } + + if ( unknowns == true ){ + sb.append("*** Some memory was not created with _CLNEW and was not tracked... ***\n"); + sb.append("*** Use _CLNEW instead of new when creating CLucene objects ***\n"); + sb.append("*** Memory may also have not been freed in the current context ***\n"); + } + + if ( print ){ + if ( sb.length() > 0 ){ + printf("%s\n", sb.c_str()); + sb = ""; + } + return NULL; + }else{ + if ( sb.length() > 0 ) + return STRDUP_AtoA(sb.c_str()); + else + return NULL; + } +} + +void LuceneBase::__cl_ClearMemory(){ + SCOPED_LOCK_MUTEX(memleak_lock) + + while ( LuceneBase_Files.size() > 0 ){ + defFile::iterator fi = LuceneBase_Files.begin(); + _file* f = fi->second; + delete[] f->value; + LuceneBase_Files.removeitr (fi); + } + LuceneBase_Pointers.clear(); + LuceneBase_Voids.clear(); +} +char* LuceneBase::__cl_GetUnclosedObjects(){ + return __internalcl_GetUnclosedObjects(false); +} +//static +int32_t LuceneBase::__cl_GetUnclosedObjectsCount(){ + return LuceneBase_Pointers.size(); +} + +const char* LuceneBase::__cl_GetUnclosedObject(int32_t item){ + SCOPED_LOCK_MUTEX(memleak_lock) + + defPointer::iterator itr=LuceneBase_Pointers.begin(); + int32_t i=0; + for ( ;itr!=LuceneBase_Pointers.end() && isecond->file->value; + else + return NULL; +} +void LuceneBase::__cl_PrintUnclosedObjects(){ + __internalcl_GetUnclosedObjects(true); +} +//////////////////////////////////////////////////////////// + +#endif //LUCENE_ENABLE_MEMLEAKTRACKING +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/document/DateField.cpp b/3rdparty/clucene/src/CLucene/document/DateField.cpp new file mode 100644 index 0000000..ff72b12 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/document/DateField.cpp @@ -0,0 +1,60 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" + +#include "DateField.h" +#include "CLucene/util/Misc.h" +CL_NS_USE(util) +CL_NS_DEF(document) + +DateField::~DateField(){ +} + +TCHAR* DateField::timeToString(const int64_t time) { + TCHAR* buf = _CL_NEWARRAY(TCHAR,DATEFIELD_DATE_LEN + 1); + timeToString(time,buf); + return buf; +} +void DateField::timeToString(const int64_t time, TCHAR* buf) { + CND_PRECONDITION (buf, "buf == NULL"); + *buf = '\0'; + if (time < 0) + _CLTHROWA (CL_ERR_IllegalArgument,"time too early"); //todo: make richer error + + if (time > DATEFIELD_DATE_MAX) + _CLTHROWA (CL_ERR_IllegalArgument, "time too late (past DATEFIELD_DATE_MAX"); //todo: make richer error + + _i64tot(time, buf, 36); + int32_t bufLen = _tcslen(buf); + + CND_PRECONDITION (bufLen <= DATEFIELD_DATE_LEN, "timeToString length is greater than 9"); + + /* Supply leading zeroes if necessary. */ + if (bufLen < DATEFIELD_DATE_LEN) { + const int32_t nMissingZeroes = DATEFIELD_DATE_LEN - bufLen; + /* Move buffer contents forward to make room for leading zeroes. */ + for (int32_t i = DATEFIELD_DATE_LEN - 1; i >= nMissingZeroes; i--) + buf[i] = buf[i - nMissingZeroes]; + + /* Insert leading zeroes. */ + {// MSVC6 scoping fix + for (int32_t i = 0; i < nMissingZeroes; i++) + buf[i] = '0'; + } + + buf[DATEFIELD_DATE_LEN] = 0; + } + + CND_PRECONDITION (_tcslen(buf) == DATEFIELD_DATE_LEN, "timeToString return is not equal to DATEFIELD_DATE_LEN"); +} + +int64_t DateField::stringToTime(const TCHAR* time) { + TCHAR* end; + return _tcstoi64(time, &end, 36); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/document/DateField.h b/3rdparty/clucene/src/CLucene/document/DateField.h new file mode 100644 index 0000000..712fe9b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/document/DateField.h @@ -0,0 +1,64 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_document_DateField_ +#define _lucene_document_DateField_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(document) + +//here are some constants used throughout clucene +//make date strings long enough to last a millenium +#define DATEFIELD_DATE_MAX _ILONGLONG(31536000000000) //1000L*365*24*60*60*1000 + +#define DATEFIELD_DATE_LEN 9 ////Long.toString(DATEFIELD_DATE_MAX, Character.MAX_RADIX).length() + +/** +* Provides support for converting dates to strings and vice-versa. +* The strings are structured so that lexicographic sorting orders by date, +* which makes them suitable for use as field values and search terms. +* +*

Note that this class saves dates with millisecond granularity, +* which is bad for {@link RangeQuery} and {@link PrefixQuery}, as those +* queries are expanded to a BooleanQuery with a potentially large number +* of terms when searching. Thus you might want to use +* {@link DateTools} instead. +* +*

+* Note: dates before 1970 cannot be used, and therefore cannot be +* indexed when using this class. See {@link DateTools} for an +* alternative without such a limitation. +* +* @deprecated If you build a new index, use {@link DateTools} instead. This class is included for use with existing +* indices and will be removed in a future release. +*/ +class DateField :LUCENE_BASE { +public: + ~DateField(); + + /** + * Converts a millisecond time to a string suitable for indexing. + * @throws RuntimeException if the time specified in the + * method argument is negative, that is, before 1970 + */ + static TCHAR* timeToString(const int64_t time); + + /** + * Converts a millisecond time to a string suitable for indexing. + * @throws CL_ERR_IllegalArgument if the time specified in the + * method argument is negative, that is, before 1970 + * @param str must be a character array DATEFIELD_DATE_LEN+1 or longer + */ + static void timeToString(const int64_t time, TCHAR* str); + + /** Converts a string-encoded date into a millisecond time. */ + static int64_t stringToTime(const TCHAR* s); +}; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/document/Document.cpp b/3rdparty/clucene/src/CLucene/document/Document.cpp new file mode 100644 index 0000000..a0ce039 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/document/Document.cpp @@ -0,0 +1,237 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Document.h" +#include "Field.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(util) +CL_NS_DEF(document) + + DocumentFieldEnumeration::DocumentFieldList::DocumentFieldList(Field* f, DocumentFieldList* n ) { + //Func - Constructor + //Pre - f != NULL + // n may be NULL + //Post - Instance has been created + CND_PRECONDITION(f != NULL, "f is NULL"); + + field = f; + next = n; + } + DocumentFieldEnumeration::DocumentFieldList::~DocumentFieldList(){ + //Func - Destructor + //Pre - true + //Post - Instance has been destroyed + + // Instead of recursively deleting the field list we do + // it iteratively to avoid stack overflows when + // dealing with several thousands of fields. + + if (!field) { + return; // nothing to do; deleted by different invocation of dtor + } + + DocumentFieldList* cur = next; + while (cur != NULL) + { + DocumentFieldList* temp = cur->next; + cur->next = NULL; + + _CLDELETE(cur); + cur = temp; + } + _CLDELETE(field); + } + + + DocumentFieldEnumeration::DocumentFieldEnumeration(const DocumentFieldList* fl){ + //Func - Constructor + //Pre - fl may be NULL + //Post - Instance has been created + + fields = fl; + } + + DocumentFieldEnumeration::~DocumentFieldEnumeration(){ + //Func - Destructor + //Pre - true + //Post - Instance has been destroyed + } + + bool DocumentFieldEnumeration::hasMoreElements() const { + return fields == NULL ? false : true; + } + + Field* DocumentFieldEnumeration::nextElement() { + //Func - Return the next element in the enumeration + //Pre - true + //Post - The next element is returned or NULL + + + Field* result = NULL; + //Check if fields is still valid + if (fields){ + result = fields->field; + fields = fields->next; + } + return result; + } + + /** Constructs a new document with no fields. */ + Document::Document(){ + //Func - Constructor + //Pre - true + //Post - Instance has been created + boost = 1.0f; + fieldList = NULL; + } + + Document::~Document(){ + //Func - Destructor + //Pre - true + //Post - Instance has been destroyed + boost = 1.0f; + _CLDELETE(fieldList); + } + + void Document::clear(){ + _CLDELETE(fieldList); + } + + void Document::add(Field& field) { + fieldList = _CLNEW DocumentFieldEnumeration::DocumentFieldList(&field, fieldList); + } + + void Document::setBoost(qreal boost) { + this->boost = boost; + } + + qreal Document::getBoost() const { + return boost; + } + + + Field* Document::getField(const TCHAR* name) const{ + CND_PRECONDITION(name != NULL, "name is NULL"); + + for (DocumentFieldEnumeration::DocumentFieldList* list = fieldList; list != NULL; list = list->next) + //cannot use interning here, because name is probably not interned + if ( _tcscmp(list->field->name(), name) == 0 ){ + return list->field; + } + + return NULL; + } + + const TCHAR* Document::get(const TCHAR* field) const { + CND_PRECONDITION(field != NULL, "field is NULL"); + Field *f = getField(field); + if (f!=NULL) + return f->stringValue(); //this returns null it is a binary(reader) + else + return NULL; + } + + DocumentFieldEnumeration* Document::fields() const { + return _CLNEW DocumentFieldEnumeration(fieldList); + } + + + TCHAR* Document::toString() const { + StringBuffer ret(_T("Document<")); + for (DocumentFieldEnumeration::DocumentFieldList* list = fieldList; list != NULL; list = list->next) { + TCHAR* tmp = list->field->toString(); + ret.append( tmp ); + if (list->next != NULL) + ret.append(_T(" ")); + _CLDELETE_ARRAY( tmp ); + } + ret.append(_T(">")); + return ret.toString(); + } + + + + void Document::removeField(const TCHAR* name) { + CND_PRECONDITION(name != NULL, "name is NULL"); + + DocumentFieldEnumeration::DocumentFieldList* previous = NULL; + DocumentFieldEnumeration::DocumentFieldList* current = fieldList; + while (current != NULL) { + //cannot use interning here, because name is probably not interned + if ( _tcscmp(current->field->name(),name) == 0 ){ + if (previous){ + previous->next = current->next; + }else + fieldList = current->next; + current->next=NULL; //ensure fieldlist destructor doesnt delete it + _CLDELETE(current); + return; + } + previous = current; + current = current->next; + } + } + + void Document::removeFields(const TCHAR* name) { + CND_PRECONDITION(name != NULL, "name is NULL"); + + DocumentFieldEnumeration::DocumentFieldList* previous = NULL; + DocumentFieldEnumeration::DocumentFieldList* current = fieldList; + while (current != NULL) { + //cannot use interning here, because name is probably not interned + if ( _tcscmp(current->field->name(),name) == 0 ){ + if (previous){ + previous->next = current->next; + }else + fieldList = current->next; + + current->next=NULL; //ensure fieldlist destructor doesnt delete it + _CLDELETE(current); + + if ( previous ) + current = previous->next; + else + current = fieldList; + }else{ + previous = current; + current = current->next; + } + } + } + + TCHAR** Document::getValues(const TCHAR* name) { + DocumentFieldEnumeration* it = fields(); + int32_t count = 0; + while ( it->hasMoreElements() ){ + Field* f = it->nextElement(); + //cannot use interning here, because name is probably not interned + if ( _tcscmp(f->name(),name) == 0 && f->stringValue() != NULL ) + count++; + } + _CLDELETE(it); + it = fields(); + + //todo: there must be a better way of doing this, we are doing two iterations of the fields + TCHAR** ret = NULL; + if ( count > 0 ){ + //start again + ret = _CL_NEWARRAY(TCHAR*,count+1); + int32_t i=0; + while ( it->hasMoreElements() ){ + Field* fld=it->nextElement(); + if ( _tcscmp(fld->name(),name)== 0 && fld->stringValue() != NULL ){ + ret[i] = stringDuplicate(fld->stringValue()); + i++; + } + } + ret[count]=NULL; + } + _CLDELETE(it); + return ret; + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/document/Document.h b/3rdparty/clucene/src/CLucene/document/Document.h new file mode 100644 index 0000000..ba7a283 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/document/Document.h @@ -0,0 +1,158 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_document_Document_ +#define _lucene_document_Document_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Field.h" + +///todo: jlucene has change from using DocumentFieldList/Enumeration +///to using a java List... do we want to do this too? +CL_NS_DEF(document) + +class Document; //predefine +class DocumentFieldEnumeration :LUCENE_BASE{ + class DocumentFieldList :LUCENE_BASE{ + public: + DocumentFieldList(Field* f, DocumentFieldList* n); + ~DocumentFieldList(); + Field* field; + DocumentFieldList* next; + }; + friend class Document; +private: + const DocumentFieldList* fields; +public: + DocumentFieldEnumeration(const DocumentFieldList* fl); + ~DocumentFieldEnumeration(); + bool hasMoreElements() const; + Field* nextElement(); +}; + +/** Documents are the unit of indexing and search. +* +* A Document is a set of fields. Each field has a name and a textual value. +* A field may be {@link Field#isStored() stored} with the document, in which +* case it is returned with search hits on the document. Thus each document +* should typically contain one or more stored fields which uniquely identify +* it. +* +*

Note that fields which are not {@link Field#isStored() stored} are +* not available in documents retrieved from the index, e.g. with {@link +* Hits#doc(int32_t, Document*)}, {@link Searcher#doc(int32_t, Document*)} or {@link +* IndexReader#document(int32_t, Document*)}. +*/ +class Document:LUCENE_BASE { +private: + DocumentFieldEnumeration::DocumentFieldList* fieldList; + qreal boost; +public: + Document(); + ~Document(); + + /** + *

Adds a field to a document. Several fields may be added with + * the same name. In this case, if the fields are indexed, their text is + * treated as though appended for the purposes of search.

+ *

Note that add like the removeField(s) methods only makes sense + * prior to adding a document to an index. These methods cannot + * be used to change the content of an existing index! In order to achieve this, + * a document has to be deleted from an index and a new changed version of that + * document has to be added.

+ * + */ + void add(Field& field); + /** Returns a field with the given name if any exist in this document, or + * null. If multiple fields exists with this name, this method returns the + * first value added. + * Note: name is case sensitive + */ + Field* getField(const TCHAR* name) const; + + /** Returns the string value of the field with the given name if any exist in + * this document, or null. If multiple fields exist with this name, this + * method returns the first value added. If only binary fields with this name + * exist, returns null. + * Note: name is case sensitive + */ + const TCHAR* get(const TCHAR* field) const; + + /** Returns an Enumeration of all the fields in a document. */ + DocumentFieldEnumeration* fields() const; + /** Prints the fields of a document for human consumption. */ + TCHAR* toString() const; + + /** Sets a boost factor for hits on any field of this document. This value + * will be multiplied into the score of all hits on this document. + * + *

Values are multiplied into the value of {@link Field#getBoost()} of + * each field in this document. Thus, this method in effect sets a default + * boost for the fields of this document. + * + * @see Field#setBoost(qreal) + */ + void setBoost(qreal boost); + + /** Returns the boost factor for hits on any field of this document. + * + *

The default value is 1.0. + * + *

Note: This value is not stored directly with the document in the index. + * Documents returned from {@link IndexReader#document(int32_t, Document*)} and + * {@link Hits#doc(int32_t, Document*)} may thus not have the same value present as when + * this document was indexed. + * + * @see #setBoost(qreal) + */ + qreal getBoost() const; + + + /** + *

Removes field with the specified name from the document. + * If multiple fields exist with this name, this method removes the first field that has been added. + * If there is no field with the specified name, the document remains unchanged.

+ *

Note that the removeField(s) methods like the add method only make sense + * prior to adding a document to an index. These methods cannot + * be used to change the content of an existing index! In order to achieve this, + * a document has to be deleted from an index and a new changed version of that + * document has to be added.

+ * Note: name is case sensitive + */ + void removeField(const TCHAR* name); + + /** + *

Removes all fields with the given name from the document. + * If there is no field with the specified name, the document remains unchanged.

+ *

Note that the removeField(s) methods like the add method only make sense + * prior to adding a document to an index. These methods cannot + * be used to change the content of an existing index! In order to achieve this, + * a document has to be deleted from an index and a new changed version of that + * document has to be added.

+ * Note: name is case sensitive + */ + void removeFields(const TCHAR* name); + + /** + * Returns an array of values of the field specified as the method parameter. + * This method can return null. + * Note: name is case sensitive + * + * @param name the name of the field + * @return a String[] of field values + */ + TCHAR** getValues(const TCHAR* name); + + /** + * Empties out the document so that it can be reused + */ + void clear(); +}; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/document/Field.cpp b/3rdparty/clucene/src/CLucene/document/Field.cpp new file mode 100644 index 0000000..8cd88a3 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/document/Field.cpp @@ -0,0 +1,315 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CLucene/util/Reader.h" +#include "Field.h" +#include "CLucene/util/Misc.h" +#include "CLucene/util/StringIntern.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(util) +CL_NS_DEF(document) + +Field::Field(const TCHAR* Name, const TCHAR* String, bool store, bool index, bool token, const bool storeTermVector) +{ +//Func - Constructor +//Pre - Name != NULL and contains the name of the field +// String != NULL and contains the value of the field +// store indicates if the field must be stored +// index indicates if the field must be indexed +// token indicates if the field must be tokenized +//Post - The instance has been created + + CND_PRECONDITION(Name != NULL, "Name is NULL"); + CND_PRECONDITION(String != NULL,"String is NULL"); + CND_PRECONDITION(!(!index && storeTermVector),"cannot store a term vector for fields that are not indexed."); + + _name = CLStringIntern::intern( Name CL_FILELINE); + _stringValue = stringDuplicate( String ); + _readerValue = NULL; + _streamValue = NULL; + boost=1.0f; + omitNorms = false; + + int cfg = 0; + if ( store ) + cfg |= STORE_YES; + if ( index && token ) + cfg |= INDEX_TOKENIZED; + else if ( index && !token ) + cfg |= INDEX_UNTOKENIZED; + + if ( storeTermVector ) + _CLTHROWA(CL_ERR_IllegalArgument,"Stored term vector is deprecated with using this constructor"); + + setConfig(cfg); +} + +Field::Field(const TCHAR* Name, Reader* reader, bool store, bool index, bool token, const bool storeTermVector) +{ +//Func - Constructor +//Pre - Name != NULL and contains the name of the field +// reader != NULL and contains a Reader +// store indicates if the field must be stored +// index indicates if the field must be indexed +// token indicates if the field must be tokenized +//Post - The instance has been created + + CND_PRECONDITION(Name != NULL, "Name is NULL"); + CND_PRECONDITION(reader != NULL, "reader is NULL"); + + _name = CLStringIntern::intern( Name CL_FILELINE); + _stringValue = NULL; + _readerValue = reader; + _streamValue = NULL; + boost=1.0f; + omitNorms = false; + + int cfg = 0; + if ( store ) + cfg |= STORE_YES; + if ( index && token ) + cfg |= INDEX_TOKENIZED; + else if ( index && !token ) + cfg |= INDEX_UNTOKENIZED; + + if ( storeTermVector ) + _CLTHROWA(CL_ERR_IllegalArgument,"Stored term vector is deprecated with using this constructor"); + + setConfig(cfg); +} + +Field::Field(const TCHAR* Name, Reader* reader, int config) +{ + CND_PRECONDITION(Name != NULL, "Name is NULL"); + CND_PRECONDITION(reader != NULL, "reader is NULL"); + + _name = CLStringIntern::intern( Name CL_FILELINE); + _stringValue = NULL; + _readerValue = reader; + _streamValue = NULL; + boost=1.0f; + omitNorms = false; + + setConfig(config); +} + + +Field::Field(const TCHAR* Name, const TCHAR* Value, int config) +{ + CND_PRECONDITION(Name != NULL, "Name is NULL"); + CND_PRECONDITION(Value != NULL, "value is NULL"); + + _name = CLStringIntern::intern( Name CL_FILELINE); + _stringValue = stringDuplicate( Value ); + _readerValue = NULL; + _streamValue = NULL; + boost=1.0f; + omitNorms = false; + + setConfig(config); +} + +Field::Field(const TCHAR* Name, jstreams::StreamBase* Value, int config) +{ + CND_PRECONDITION(Name != NULL, "Name is NULL"); + CND_PRECONDITION(Value != NULL, "value is NULL"); + + _name = CLStringIntern::intern( Name CL_FILELINE); + _stringValue = NULL; + _readerValue = NULL; + _streamValue = Value; + boost=1.0f; + omitNorms = false; + + setConfig(config); +} + +Field::~Field(){ +//Func - Destructor +//Pre - true +//Post - Instance has been destroyed + + CLStringIntern::unintern(_name); + _CLDELETE_CARRAY(_stringValue); + _CLDELETE(_readerValue); + _CLVDELETE( _streamValue ); +} + + +/*===============FIELDS=======================*/ +const TCHAR* Field::name() { return _name; } ///* Field::streamValue() { return _streamValue; } ///omitNorms=omitNorms; } + +void Field::setBoost(qreal boost) { this->boost = boost; } +qreal Field::getBoost() { return boost; } + +void Field::setConfig(int x){ + int newConfig=0; + + //set storage settings + if ( (x & STORE_YES) || (x & STORE_COMPRESS) ){ + newConfig |= STORE_YES; + if ( x & STORE_COMPRESS ) + newConfig |= STORE_COMPRESS; + }else + newConfig |= STORE_NO; + + if ( (x & INDEX_NO)==0 ){ + bool index=false; + + if ( x & INDEX_NONORMS ){ + newConfig |= INDEX_NONORMS; + index = true; + } + + if ( x & INDEX_TOKENIZED && x & INDEX_UNTOKENIZED ) + _CLTHROWA(CL_ERR_IllegalArgument,"it doesn't make sense to have an untokenised and tokenised field"); + if ( x & INDEX_TOKENIZED ){ + newConfig |= INDEX_TOKENIZED; + index = true; + } + if ( x & INDEX_UNTOKENIZED ){ + newConfig |= INDEX_UNTOKENIZED; + index = true; + } + if ( !index ) + newConfig |= INDEX_NO; + }else + newConfig |= INDEX_NO; + + if ( newConfig & INDEX_NO && newConfig & STORE_NO ) + _CLTHROWA(CL_ERR_IllegalArgument,"it doesn't make sense to have a field that is neither indexed nor stored"); + + //set termvector settings + if ( (x & TERMVECTOR_NO) == 0 ){ + bool termVector=false; + if ( x & TERMVECTOR_YES ){ + termVector=true; + } + if ( x & TERMVECTOR_WITH_OFFSETS ){ + newConfig |= TERMVECTOR_WITH_OFFSETS; + termVector=true; + } + if ( x & TERMVECTOR_WITH_POSITIONS ){ + newConfig |= TERMVECTOR_WITH_POSITIONS; + termVector=true; + } + if ( termVector ){ + if ( newConfig & INDEX_NO ) + _CLTHROWA(CL_ERR_IllegalArgument,"cannot store a term vector for fields that are not indexed."); + + newConfig |= TERMVECTOR_YES; + }else + newConfig |= TERMVECTOR_NO; + }else + newConfig |= TERMVECTOR_NO; + + config = newConfig; +} + +TCHAR* Field::toString() { + CL_NS(util)::StringBuffer result; + if (isStored()) { + result.append( _T("stored") ); + } + if (isIndexed()) { + if (result.length() > 0) + result.append( _T(",") ); + result.append( _T("indexed") ); + } + if (isTokenized()) { + if (result.length() > 0) + result.append( _T(",") ); + result.append( _T("tokenized") ); + } + if (isTermVectorStored()) { + if (result.length() > 0) + result.append( _T(",") ); + result.append( _T("termVector") ); + } + if (isStoreOffsetWithTermVector()) { + if (result.length() > 0) + result.appendChar( ',' ); + result.append( _T("termVectorOffsets") ); + } + if (isStorePositionWithTermVector()) { + if (result.length() > 0) + result.appendChar( ',' ); + result.append( _T("termVectorPosition") ); + } + if (isBinary()) { + if (result.length() > 0) + result.appendChar( ',' ); + result.append( _T("binary") ); + } + if (getOmitNorms()) { + result.append( _T(",omitNorms") ); + } + result.appendChar('<'); + result.append(name()); + result.appendChar(':'); + + if (_stringValue != NULL) + result.append(_stringValue); + else if ( _readerValue != NULL ) + result.append( _T("Reader") ); + else if ( _streamValue != NULL ) + result.append( _T("Stream") ); + else + result.append( _T("NULL") ); + + result.appendChar('>'); + return result.toString(); +} + + +Field* Field::Keyword(const TCHAR* Name, const TCHAR* Value) { + return _CLNEW Field(Name,Value,Field::STORE_YES | Field::INDEX_UNTOKENIZED); +} + +Field* Field::UnIndexed(const TCHAR* Name, const TCHAR* Value) { + return _CLNEW Field(Name,Value,Field::STORE_YES | Field::INDEX_NO); +} + +Field* Field::Text(const TCHAR* Name, const TCHAR* Value, const bool storeTermVector) { + if ( storeTermVector ) + return _CLNEW Field(Name,Value,Field::STORE_YES | Field::INDEX_TOKENIZED | Field::TERMVECTOR_YES); + else + return _CLNEW Field(Name,Value,Field::STORE_YES | Field::INDEX_TOKENIZED); +} + +Field* Field::UnStored(const TCHAR* Name, const TCHAR* Value, const bool storeTermVector) { + if ( storeTermVector ) + return _CLNEW Field(Name,Value,Field::STORE_NO | Field::INDEX_TOKENIZED | Field::TERMVECTOR_YES); + else + return _CLNEW Field(Name,Value,Field::STORE_NO | Field::INDEX_TOKENIZED); +} + +Field* Field::Text(const TCHAR* Name, Reader* Value, const bool storeTermVector) { + if ( storeTermVector ) + return _CLNEW Field(Name,Value,Field::INDEX_TOKENIZED | Field::TERMVECTOR_YES); + else + return _CLNEW Field(Name,Value,Field::INDEX_TOKENIZED); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/document/Field.h b/3rdparty/clucene/src/CLucene/document/Field.h new file mode 100644 index 0000000..771a138 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/document/Field.h @@ -0,0 +1,261 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_document_Field_ +#define _lucene_document_Field_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/Reader.h" +#include "CLucene/util/streambase.h" + +CL_NS_DEF(document) +/** +A field is a section of a Document. Each field has two parts, a name and a +value. Values may be free text, provided as a String or as a Reader, or they +may be atomic keywords, which are not further processed. Such keywords may +be used to represent dates, urls, etc. Fields are optionally stored in the +index, so that they may be returned with hits on the document. + +PORTING: CLucene doesn't directly support compressed fields. However, it is easy +to reproduce this functionality by using the GZip streams in the contrib package. +Also note that binary fields are not read immediately in CLucene, a substream +is pointed directly to the field's data, in affect creating a lazy load ability. +This means that large fields are best saved in binary format (even if they are +text), so that they can be loaded lazily. +*/ +class Field :LUCENE_BASE{ +private: + const TCHAR* _name; + TCHAR* _stringValue; + CL_NS(util)::Reader* _readerValue; + jstreams::StreamBase* _streamValue; + + int config; + qreal boost; + bool omitNorms; +public: + enum Store{ + /** Store the original field value in the index. This is useful for short texts + * like a document's title which should be displayed with the results. The + * value is stored in its original form, i.e. no analyzer is used before it is + * stored. + */ + STORE_YES=1, + /** Do not store the field value in the index. */ + STORE_NO=2, + + /** Store the original field value in the index in a compressed form. This is + * useful for long documents and for binary valued fields. + * NOTE: CLucene does not directly support compressed fields, to store a + * compressed field. + * //TODO: need better documentation on how to add a compressed field + * //because actually we still need to write a GZipOutputStream... + */ + STORE_COMPRESS=4 + }; + + enum Index{ + /** Do not index the field value. This field can thus not be searched, + * but one can still access its contents provided it is + * {@link Field::Store stored}. */ + INDEX_NO=16, + /** Index the field's value so it can be searched. An Analyzer will be used + * to tokenize and possibly further normalize the text before its + * terms will be stored in the index. This is useful for common text. + */ + INDEX_TOKENIZED=32, + /** Index the field's value without using an Analyzer, so it can be searched. + * As no analyzer is used the value will be stored as a single term. This is + * useful for unique Ids like product numbers. + */ + INDEX_UNTOKENIZED=64, + /** Index the field's value without an Analyzer, and disable + * the storing of norms. No norms means that index-time boosting + * and field length normalization will be disabled. The benefit is + * less memory usage as norms take up one byte per indexed field + * for every document in the index. + */ + INDEX_NONORMS=128 + }; + + enum TermVector{ + /** Do not store term vectors. */ + TERMVECTOR_NO=256, + /** Store the term vectors of each document. A term vector is a list + * of the document's terms and their number of occurences in that document. */ + TERMVECTOR_YES=512, + /** + * Store the term vector + token position information + * + * @see #YES + */ + TERMVECTOR_WITH_POSITIONS=1024, + /** + * Store the term vector + Token offset information + * + * @see #YES + */ + TERMVECTOR_WITH_OFFSETS=2048 + }; + + _CL_DEPRECATED( another overload ) Field(const TCHAR* name, const TCHAR* value, bool store, bool index, bool token, const bool storeTermVector=false); + _CL_DEPRECATED( another overload ) Field(const TCHAR* name, CL_NS(util)::Reader* reader, bool store, bool index, bool token, const bool storeTermVector=false); + + Field(const TCHAR* name, const TCHAR* value, int configs); + Field(const TCHAR* name, CL_NS(util)::Reader* reader, int configs); + Field(const TCHAR* name, jstreams::StreamBase* stream, int configs); + ~Field(); + + /** Constructs a String-valued Field that is not tokenized, but is indexed + * and stored. Useful for non-text fields, e.g. date or url. + * @deprecated Use new Field(name,value,Field::STORE_YES | Field::INDEX_UNTOKENIZED) + */ + _CL_DEPRECATED( new Field(*) ) static Field* Keyword(const TCHAR* name, const TCHAR* value); + + /** Constructs a String-valued Field that is not tokenized nor indexed, + * but is stored in the index, for return with hits. + * @deprecated Use new Field(name,value,Field::STORE_YES | Field::INDEX_NO) + */ + _CL_DEPRECATED( new Field(*) ) static Field* UnIndexed(const TCHAR* name, const TCHAR* value); + + /** Constructs a String-valued Field that is tokenized and indexed, + * and is stored in the index, for return with hits. Useful for short text + * fields, like "title" or "subject". + * @deprecated Use new Field(name,value,Field::STORE_YES | Field::INDEX_TOKENIZED) + */ + _CL_DEPRECATED( new Field(*) ) static Field* Text(const TCHAR* name, const TCHAR* value, const bool storeTermVector=false); + + /** Constructs a String-valued Field that is tokenized and indexed, + * but that is not stored in the index. + * @deprecated Use new Field(name,value,Field::STORE_NO | Field::INDEX_TOKENIZED) + */ + _CL_DEPRECATED( new Field(*) ) static Field* UnStored(const TCHAR* name, const TCHAR* value, const bool storeTermVector=false); + + /** Constructs a Reader-valued Field that is tokenized and indexed, but is + * *not* stored in the index verbatim. Useful for longer text fields, like + * "body". + * @deprecated Use new Field(name,value, Field::INDEX_TOKENIZED) + */ + _CL_DEPRECATED( new Field(*) ) static Field* Text(const TCHAR* name, CL_NS(util)::Reader* value, const bool storeTermVector=false); + + /** The name of the field (e.g., "date", "subject", "title", "body", etc.) + * as an interned string. */ + const TCHAR* name(); ///* streamValue(); + + // True iff the value of the field is to be stored in the index for return + // with search hits. It is an error for this to be true if a field is + // Reader-valued. + bool isStored(); + + // True iff the value of the field is to be indexed, so that it may be + // searched on. + bool isIndexed(); + + // True iff the value of the field should be tokenized as text prior to + // indexing. Un-tokenized fields are indexed as a single word and may not be + // Reader-valued. + bool isTokenized(); + + /** True if the value of the field is stored and compressed within the index + * NOTE: CLucene does not actually support compressed fields, Instead, a reader + * will be returned with a pointer to a SubIndexInputStream. A GZipInputStream + * and a UTF8 reader must be used to actually read the content. This flag + * will only be set if the index was created by another lucene implementation. + */ + bool isCompressed(); + + //Set configs using XOR. This resets all the settings + //For example, to use term vectors with positions and offsets do: + //object->setConfig(TERMVECTOR_WITH_POSITIONS | TERMVECTOR_WITH_OFFSETS); + void setConfig(int termVector); + + /** True iff the term or terms used to index this field are stored as a term + * vector, available from {@link IndexReader#getTermFreqVector(int32_t,TCHAR*)}. + * These methods do not provide access to the original content of the field, + * only to terms used to index it. If the original content must be + * preserved, use the stored attribute instead. + * + * @see IndexReader#getTermFreqVector(int32_t, String) + */ + bool isTermVectorStored(); + + /** + * True iff terms are stored as term vector together with their offsets + * (start and end positon in source text). + */ + bool isStoreOffsetWithTermVector(); + + /** + * True iff terms are stored as term vector together with their token positions. + */ + bool isStorePositionWithTermVector(); + + /** Returns the boost factor for hits for this field. + * + *

The default value is 1.0. + * + *

Note: this value is not stored directly with the document in the index. + * Documents returned from {@link IndexReader#document(int)} and + * {@link Hits#doc(int)} may thus not have the same value present as when + * this field was indexed. + * + * @see #setBoost(float) + */ + qreal getBoost(); + + /** Sets the boost factor hits on this field. This value will be + * multiplied into the score of all hits on this field of this document. + * + *

The boost is multiplied by {@link Document#getBoost()} of the document + * containing this field. If a document has multiple fields with the same + * name, all such values are multiplied together. This product is then + * multipled by the value {@link Similarity#lengthNorm(String,int)}, and + * rounded by {@link Similarity#encodeNorm(float)} before it is stored in the + * index. One should attempt to ensure that this product does not overflow + * the range of that encoding. + * + * @see Document#setBoost(float) + * @see Similarity#lengthNorm(String, int) + * @see Similarity#encodeNorm(float) + */ + void setBoost(qreal value); + + /** True iff the value of the filed is stored as binary */ + bool isBinary(); + + /** True if norms are omitted for this indexed field */ + bool getOmitNorms(); + + /** Expert: + * + * If set, omit normalization factors associated with this indexed field. + * This effectively disables indexing boosts and length normalization for this field. + */ + void setOmitNorms(bool omitNorms); + + // Prints a Field for human consumption. + TCHAR* toString(); +}; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/index/CompoundFile.cpp b/3rdparty/clucene/src/CLucene/index/CompoundFile.cpp new file mode 100644 index 0000000..efa0e25 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/CompoundFile.cpp @@ -0,0 +1,380 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CompoundFile.h" +#include "CLucene/util/Misc.h" + +CL_NS_USE(store) +CL_NS_USE(util) +CL_NS_DEF(index) + +CompoundFileReader::CSIndexInput::CSIndexInput(CL_NS(store)::IndexInput* base, + const int64_t fileOffset, const int64_t length) +{ + this->base = base; + this->fileOffset = fileOffset; + this->_length = length; +} + +void CompoundFileReader::CSIndexInput::readInternal(uint8_t* b, const int32_t len) +{ + SCOPED_LOCK_MUTEX(base->THIS_LOCK) + + int64_t start = getFilePointer(); + if(start + len > _length) + _CLTHROWA(CL_ERR_IO, "read past EOF"); + base->seek(fileOffset + start); + base->readBytes(b, len); +} + +CompoundFileReader::CSIndexInput::~CSIndexInput() +{ +} + +IndexInput* CompoundFileReader::CSIndexInput::clone() const +{ + return _CLNEW CSIndexInput(*this); +} + +CompoundFileReader::CSIndexInput::CSIndexInput(const CSIndexInput& clone) + : BufferedIndexInput(clone) +{ + this->base = clone.base; //no need to clone this.. + this->fileOffset = clone.fileOffset; + this->_length = clone._length; +} + +void CompoundFileReader::CSIndexInput::close() +{ +} + +CompoundFileReader::CompoundFileReader(Directory* dir, const QString& name) + : entries(false, true) +{ + directory = dir; + fileName = name; + + bool success = false; + try { + stream = dir->openInput(name); + + // read the directory and init files + int32_t count = stream->readVInt(); + FileEntry* entry = NULL; + TCHAR tid[CL_MAX_PATH]; + for (int32_t i = 0; i < count; i++) { + int64_t offset = stream->readLong(); + int32_t read = stream->readString(tid, CL_MAX_PATH); + QString aid(QString::fromWCharArray(tid, read)); + + // set length of the previous entry + if (entry != NULL) + entry->length = offset - entry->offset; + + entry = _CLNEW FileEntry(offset); + entries.put(aid, entry); + } + + // set the length of the final entry + if (entry != NULL) + entry->length = stream->length() - entry->offset; + success = true; + } _CLFINALLY ( + if (!success && (stream != NULL)) { + try { + stream->close(); + _CLDELETE(stream); + } catch (CLuceneError& err) { + if (err.number() != CL_ERR_IO) + throw err; + } + } + ) +} + +CompoundFileReader::~CompoundFileReader() +{ + close(); +} + +Directory* CompoundFileReader::getDirectory() +{ + return directory; +} + +QString CompoundFileReader::getName() const +{ + return fileName; +} + +void CompoundFileReader::close() +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + + if (stream != NULL) { + entries.clear(); + stream->close(); + _CLDELETE(stream); + } +} + +IndexInput* CompoundFileReader::openInput(const QString& id) +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + + if (stream == NULL) + _CLTHROWA(CL_ERR_IO, "Stream closed"); + + const FileEntry* entry = entries.get(id); + if (entry == NULL) { + char buf[CL_MAX_PATH + 30]; + strcpy(buf,"No sub-file with id "); + strncat(buf, id.toLocal8Bit().constData(), CL_MAX_PATH); + strcat(buf, " found"); + _CLTHROWA(CL_ERR_IO,buf); + } + return _CLNEW CSIndexInput(stream, entry->offset, entry->length); +} + +QStringList CompoundFileReader::list() const +{ + // for (EntriesType::const_iterator i=entries.begin();i!=entries.end();i++){ + // names->push_back(i->first); + // ++i; + // } + + QStringList names; + EntriesType::const_iterator itr; + // TODO: verify this, see old code above ??? + for (itr = entries.begin(); itr != entries.end(); ++itr) + names.push_back(itr->first); + + return names; +} + +bool CompoundFileReader::fileExists(const QString& name) const +{ + return entries.exists(name); +} + +int64_t CompoundFileReader::fileModified(const QString& name) const +{ + return directory->fileModified(fileName); +} + +void CompoundFileReader::touchFile(const QString& name) +{ + directory->touchFile(fileName); +} + +bool CompoundFileReader::doDeleteFile(const QString& name) +{ + _CLTHROWA(CL_ERR_UnsupportedOperation, + "UnsupportedOperationException: CompoundFileReader::doDeleteFile"); +} + +void CompoundFileReader::renameFile(const QString& from, const QString& to) +{ + _CLTHROWA(CL_ERR_UnsupportedOperation, + "UnsupportedOperationException: CompoundFileReader::renameFile"); +} + +int64_t CompoundFileReader::fileLength(const QString& name) const +{ + FileEntry* e = entries.get(name); + if (e == NULL) { + char buf[CL_MAX_PATH + 30]; + strcpy(buf,"File "); + strncat(buf, name.toLocal8Bit().constData(), CL_MAX_PATH); + strcat(buf," does not exist"); + _CLTHROWA(CL_ERR_IO,buf); + } + return e->length; +} + +IndexOutput* CompoundFileReader::createOutput(const QString& name) +{ + _CLTHROWA(CL_ERR_UnsupportedOperation, + "UnsupportedOperationException: CompoundFileReader::createOutput"); +} + +LuceneLock* CompoundFileReader::makeLock(const QString& name) +{ + _CLTHROWA(CL_ERR_UnsupportedOperation, + "UnsupportedOperationException: CompoundFileReader::makeLock"); +} + +QString CompoundFileReader::toString() const +{ + QString ret(QLatin1String("CompoundFileReader@")); + return ret.append(fileName); +} + +CompoundFileWriter::CompoundFileWriter(Directory* dir, const QString& name) + : ids(false) + , entries(true) +{ + if (dir == NULL) + _CLTHROWA(CL_ERR_NullPointer, "directory cannot be null"); + + if (name.isEmpty()) + _CLTHROWA(CL_ERR_NullPointer, "name cannot be null"); + + merged = false; + directory = dir; + fileName = name; +} + +CompoundFileWriter::~CompoundFileWriter() +{ +} + +Directory* CompoundFileWriter::getDirectory() +{ + return directory; +} + +/** Returns the name of the compound file. */ +QString CompoundFileWriter::getName() const +{ + return fileName; +} + +void CompoundFileWriter::addFile(const QString& file) +{ + if (merged) + _CLTHROWA(CL_ERR_IO, "Can't add extensions after merge has been called"); + + if (file.isEmpty()) + _CLTHROWA(CL_ERR_NullPointer, "file cannot be null"); + + if (ids.find(file) != ids.end()) { + char buf[CL_MAX_PATH + 30]; + strcpy(buf, "File "); + strncat(buf, file.toLocal8Bit().constData(), CL_MAX_PATH); + strcat(buf," already added"); + _CLTHROWA(CL_ERR_IO,buf); + } + ids.insert(file); + entries.push_back(_CLNEW WriterFileEntry(file)); +} + +void CompoundFileWriter::close() +{ + if (merged) + _CLTHROWA(CL_ERR_IO, "Merge already performed"); + + if (entries.size() == 0) // isEmpty() + _CLTHROWA(CL_ERR_IO, "No entries to merge have been defined"); + + merged = true; + + // open the compound stream + IndexOutput* os = NULL; + try { + os = directory->createOutput(fileName); + + // Write the number of entries + os->writeVInt(entries.size()); + + // Write the directory with all offsets at 0. + // Remember the positions of directory entries so that we can + // adjust the offsets later + { //msvc6 for scope fix + TCHAR tfile[CL_MAX_PATH]; + for (CLLinkedList::iterator i = entries.begin(); + i != entries.end(); i++) { + WriterFileEntry* fe = *i; + fe->directoryOffset = os->getFilePointer(); + os->writeLong(0); // for now + tfile[fe->file.toWCharArray(tfile)] = '\0'; + os->writeString(tfile, _tcslen(tfile)); + } + } + + // Open the files and copy their data into the stream. + // Remember the locations of each file's data section. + { //msvc6 for scope fix + int32_t bufferLength = 1024; + uint8_t buffer[1024]; + for (CLLinkedList::iterator i = entries.begin(); + i != entries.end(); i++) { + WriterFileEntry* fe = *i; + fe->dataOffset = os->getFilePointer(); + copyFile(fe, os, buffer, bufferLength); + } + } + + { //msvc6 for scope fix + // Write the data offsets into the directory of the compound stream + for (CLLinkedList::iterator i = entries.begin(); + i != entries.end(); i++) { + WriterFileEntry* fe = *i; + os->seek(fe->directoryOffset); + os->writeLong(fe->dataOffset); + } + } + + + } _CLFINALLY ( + if (os != NULL) { + try { + os->close(); + _CLDELETE(os); + } catch (...) { } + } + ); +} + +void CompoundFileWriter::copyFile(WriterFileEntry* source, IndexOutput* os, + uint8_t* buffer, int32_t bufferLength) +{ + IndexInput* is = NULL; + try { + int64_t startPtr = os->getFilePointer(); + + is = directory->openInput(source->file); + int64_t length = is->length(); + int64_t remainder = length; + int32_t chunk = bufferLength; + + while(remainder > 0) { + int32_t len = (int32_t)min((int64_t)chunk, remainder); + is->readBytes(buffer, len); + os->writeBytes(buffer, len); + remainder -= len; + } + + // Verify that remainder is 0 + if (remainder != 0) { + TCHAR buf[CL_MAX_PATH+100]; + _sntprintf(buf, CL_MAX_PATH + 100, _T("Non-zero remainder length ") + _T("after copying: %d (id: %s, length: %d, buffer size: %d)"), + remainder, source->file.toLocal8Bit().constData(), length, chunk); + _CLTHROWT(CL_ERR_IO, buf); + } + + // Verify that the output length diff is equal to original file + int64_t endPtr = os->getFilePointer(); + int64_t diff = endPtr - startPtr; + if (diff != length) { + TCHAR buf[100]; + _sntprintf(buf, 100, _T("Difference in the output file offsets %d ") + _T("does not match the original file length %d"), diff, length); + _CLTHROWT(CL_ERR_IO,buf); + } + } _CLFINALLY ( + if (is != NULL) { + is->close(); + _CLDELETE(is); + } + ); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/CompoundFile.h b/3rdparty/clucene/src/CLucene/index/CompoundFile.h new file mode 100644 index 0000000..84799a6 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/CompoundFile.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#ifndef _lucene_index_compoundfile_h +#define _lucene_index_compoundfile_h + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include "CLucene/store/IndexInput.h" +#include "CLucene/store/IndexOutput.h" +#include "CLucene/store/Directory.h" +#include "CLucene/store/Lock.h" +#include "CLucene/util/VoidList.h" +#include "CLucene/util/VoidMap.h" + +CL_NS_DEF(index) + +// Class for accessing a compound stream. +// This class implements a directory, but is limited to only read operations. +// Directory methods that would normally modify data throw an exception. +class CompoundFileReader : public CL_NS(store)::Directory +{ +private: + /** Implementation of an IndexInput that reads from a portion of the + * compound file. The visibility is left as "package" *only* because + * this helps with testing since JUnit test cases in a different class + * can then access package fields of this class. + */ + class CSIndexInput : public CL_NS(store)::BufferedIndexInput + { + private: + CL_NS(store)::IndexInput* base; + int64_t fileOffset; + int64_t _length; + protected: + /** Expert: implements buffer refill. Reads uint8_ts from the current + * position in the input. + * @param b the array to read uint8_ts into + * @param length the number of uint8_ts to read + */ + void readInternal(uint8_t* b, const int32_t len); + void seekInternal(const int64_t pos) {} + + public: + CSIndexInput(CL_NS(store)::IndexInput* base, const int64_t fileOffset, + const int64_t length); + CSIndexInput(const CSIndexInput& clone); + ~CSIndexInput(); + + /** Closes the stream to futher operations. */ + void close(); + CL_NS(store)::IndexInput* clone() const; + + int64_t length() { return _length; } + + QString getDirectoryType() const { + return CompoundFileReader::DirectoryType(); } + }; + + class FileEntry : LUCENE_BASE + { + public: + FileEntry() + : offset(0), length(0) {} + FileEntry(int64_t _offset) + : offset(_offset), length(0) {} + ~FileEntry() {} + + int64_t offset; + int64_t length; + }; + + // Base info + CL_NS(store)::Directory* directory; + QString fileName; + + CL_NS(store)::IndexInput* stream; + + typedef CL_NS(util)::CLHashMap > EntriesType; + EntriesType entries; +protected: + // Removes an existing file in the directory-> + bool doDeleteFile(const QString& name); + +public: + CompoundFileReader(CL_NS(store)::Directory* dir, const QString& name); + ~CompoundFileReader(); + CL_NS(store)::Directory* getDirectory(); + QString getName() const; + + void close(); + CL_NS(store)::IndexInput* openInput(const QString& id); + + /** Returns an array of strings, one for each file in the directory-> */ + QStringList list() const; + /** Returns true iff a file with the given name exists. */ + bool fileExists(const QString& name) const; + /** Returns the time the named file was last modified. */ + int64_t fileModified(const QString& name) const; + /** Set the modified time of an existing file to now. */ + void touchFile(const QString& name); + /** Renames an existing file in the directory-> + If a file already exists with the new name, then it is replaced. + This replacement should be atomic. */ + void renameFile(const QString& from, const QString& to); + /** Returns the length of a file in the directory. + * @throws IOException if the file does not exist */ + int64_t fileLength(const QString& name) const; + /** Not implemented + * @throws UnsupportedOperationException */ + CL_NS(store)::IndexOutput* createOutput(const QString& name); + /** Not implemented + * @throws UnsupportedOperationException */ + CL_NS(store)::LuceneLock* makeLock(const QString& name); + + QString toString() const; + + static QString DirectoryType() { return QLatin1String("CFS"); } + QString getDirectoryType() const { return DirectoryType(); } +}; + + + +// Combines multiple files into a single compound file. +// The file format:
+//

    +//
  • VInt fileCount
  • +//
  • {Directory} +// fileCount entries with the following structure:
  • +//
      +//
    • int64_t dataOffset
    • +//
    • UTFString extension
    • +//
    +//
  • {File Data} +// fileCount entries with the raw data of the corresponding file
  • +//
+// The fileCount integer indicates how many files are contained in this compound +// file. The {directory} that follows has that many entries. Each directory entry +// contains an encoding identifier, an int64_t pointer to the start of this file's +// data section, and a UTF String with that file's extension. +class CompoundFileWriter : LUCENE_BASE +{ + class WriterFileEntry : LUCENE_BASE { + public: + WriterFileEntry() + : dataOffset(0), directoryOffset(0) {} + WriterFileEntry(const QString& _file) + : file(_file), dataOffset(0), directoryOffset(0) {} + ~WriterFileEntry() {} + + QString file; + // temporary holder for the start of this file's data section + int64_t dataOffset; + // temporary holder for the start of directory entry for this file + int64_t directoryOffset; + }; + + bool merged; + QString fileName; + CL_NS(store)::Directory* directory; + + CL_NS(util)::CLHashSet ids; + + CL_NS(util)::CLLinkedList > entries; + + // Copy the contents of the file with specified extension into the + // provided output stream. Use the provided buffer for moving data + // to reduce memory allocation. + void copyFile(WriterFileEntry* source, CL_NS(store)::IndexOutput* os, + uint8_t* buffer, int32_t bufferLength); + +public: + // Create the compound stream in the specified file. The file name is the + // entire name (no extensions are added). + CompoundFileWriter(CL_NS(store)::Directory* dir, const QString& name); + ~CompoundFileWriter(); + + // Returns the directory of the compound file. + CL_NS(store)::Directory* getDirectory(); + + QString getName() const ; + /* Add a source stream. file is the string by which the + * sub-stream will be known in the compound stream. + * + * @throws IllegalStateException if this writer is closed + * @throws NullPointerException if file is null + * @throws IllegalArgumentException if a file with the same name + * has been added already + */ + void addFile(const QString& file); + /* Merge files with the extensions added up to now. + * All files with these extensions are combined sequentially into the + * compound stream. After successful merge, the source files + * @throws IllegalStateException if close() had been called before or + * if no file has been added to this object + * are deleted. + */ + void close(); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/DocumentWriter.cpp b/3rdparty/clucene/src/CLucene/index/DocumentWriter.cpp new file mode 100644 index 0000000..dcbc315 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/DocumentWriter.cpp @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" + +#include "DocumentWriter.h" +#include "FieldInfos.h" +#include "IndexWriter.h" +#include "FieldsWriter.h" +#include "Term.h" +#include "TermInfo.h" +#include "TermInfosWriter.h" + +#include "CLucene/analysis/AnalysisHeader.h" + +#include "CLucene/search/Similarity.h" +#include "TermInfosWriter.h" +#include "FieldsWriter.h" + +CL_NS_USE(util) +CL_NS_USE(store) +CL_NS_USE(analysis) +CL_NS_USE(document) +CL_NS_DEF(index) + +/*Posting*/ + +DocumentWriter::Posting::Posting(Term* t, const int32_t position, + TermVectorOffsetInfo* offset) +{ + //Func - Constructor + //Pre - t contains a valid reference to a Term + //Post - Instance has been created + freq = 1; + + term = _CL_POINTER(t); + positions.values = (int32_t*)malloc(sizeof(int32_t)); + positions.values[0] = position; + positions.length = 1; + + if ( offset != NULL ){ + this->offsets.values =(TermVectorOffsetInfo*)malloc(sizeof(TermVectorOffsetInfo)); + this->offsets.values[0] = *offset; + this->offsets.length = 1; + } +} + +DocumentWriter::Posting::~Posting() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + free(positions.values); + if ( this->offsets.values != NULL ) + free(this->offsets.values); + _CLDECDELETE(term); +} + +DocumentWriter::DocumentWriter(Directory* d, Analyzer* a, + CL_NS(search)::Similarity* sim, const int32_t mfl) + : analyzer(a) + , directory(d) + , maxFieldLength(mfl) + , fieldInfos(NULL) + , fieldLengths(NULL) + , similarity(sim) + , termIndexInterval(IndexWriter::DEFAULT_TERM_INDEX_INTERVAL) + , fieldPositions(NULL) + , fieldBoosts(NULL) + , termBuffer(_CLNEW Term) +{ + //Pre - d contains a valid reference to a Directory + // d contains a valid reference to a Analyzer + // mfl > 0 and contains the maximum field length + //Post - Instance has been created + + CND_PRECONDITION(((mfl > 0) || (mfl == IndexWriter::FIELD_TRUNC_POLICY__WARN)), + "mfl is 0 or smaller than IndexWriter::FIELD_TRUNC_POLICY__WARN") + + fieldInfos = NULL; + fieldLengths = NULL; +} + +DocumentWriter::DocumentWriter(CL_NS(store)::Directory* d, + CL_NS(analysis)::Analyzer* a, IndexWriter* writer) + : analyzer(a) + , directory(d) + , maxFieldLength(writer->getMaxFieldLength()) + , fieldInfos(NULL) + , fieldLengths(NULL) + , similarity(writer->getSimilarity()) + , termIndexInterval(writer->getTermIndexInterval()) + , fieldPositions(NULL) + , fieldBoosts(NULL) + , termBuffer(_CLNEW Term) +{ + //Pre - d contains a valid reference to a Directory + // d contains a valid reference to a Analyzer + // mfl > 0 and contains the maximum field length + //Post - Instance has been created + + CND_PRECONDITION(((maxFieldLength > 0) + || (maxFieldLength == IndexWriter::FIELD_TRUNC_POLICY__WARN)), + "mfl is 0 or smaller than IndexWriter::FIELD_TRUNC_POLICY__WARN") + + fieldInfos = NULL; + fieldLengths = NULL; + +} + +DocumentWriter::~DocumentWriter() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + clearPostingTable(); + _CLDELETE( fieldInfos ); + _CLDELETE_ARRAY(fieldLengths); + _CLDELETE_ARRAY(fieldPositions); + _CLDELETE_ARRAY(fieldBoosts); + _CLDELETE_ARRAY(fieldOffsets); + + _CLDECDELETE(termBuffer); +} + +void DocumentWriter::clearPostingTable() +{ + PostingTableType::iterator itr = postingTable.begin(); + while (itr != postingTable.end()){ + _CLDELETE(itr->second); + _CLLDECDELETE(itr->first); + ++itr; + } + postingTable.clear(); +} + +void DocumentWriter::addDocument(const QString& segment, Document* doc) +{ + CND_PRECONDITION(fieldInfos == NULL, "fieldInfos!=NULL") + + // write field names + fieldInfos = _CLNEW FieldInfos(); + fieldInfos->add(doc); + + QString buf = Misc::segmentname(segment, QLatin1String(".fnm")); + fieldInfos->write(directory, buf); + + // write field values + FieldsWriter fieldsWriter(directory, segment, fieldInfos); + try { + fieldsWriter.addDocument(doc); + } _CLFINALLY ( + fieldsWriter.close() + ); + + // clear postingTable + clearPostingTable(); + + int32_t fieldInfoSize = fieldInfos->size(); + fieldLengths = _CL_NEWARRAY(int32_t, fieldInfoSize); // init fieldLengths + fieldPositions = _CL_NEWARRAY(int32_t, fieldInfoSize); // init fieldPositions + fieldOffsets = _CL_NEWARRAY(int32_t, fieldInfoSize); // init fieldOffsets + fieldBoosts = _CL_NEWARRAY(qreal, fieldInfoSize); // init fieldBoosts + + qreal fbd = doc->getBoost(); + for (int32_t i = 0; i < fieldInfoSize; ++i) { + fieldLengths[i] = 0; + fieldPositions[i] = 0; + fieldOffsets[i] = 0; + //initialise fieldBoost array with default boost + fieldBoosts[i] = fbd; + } + + // invert doc into postingTable + invertDocument(doc); + + // sort postingTable into an array + Posting** postings = NULL; + int32_t postingsLength = 0; + sortPostingTable(postings, postingsLength); + + //DEBUG: + /*for (int32_t i = 0; i < postingsLength; i++) { + Posting* posting = postings[i]; + + TCHAR* b = posting->term->toString(); + _cout << b << " freq=" << posting->freq; + _CLDELETE(b); + + _cout << " pos=" << posting->positions[0]; + for (int32_t j = 1; j < posting->freq; j++) + _cout <<"," << posting->positions[j]; + + _cout << endl; + }*/ + + + // write postings + writePostings(postings, postingsLength, segment); + + // write norms of indexed fields + writeNorms(segment); + _CLDELETE_ARRAY(postings); +} + +void DocumentWriter::sortPostingTable(Posting**& array, int32_t& arraySize) +{ + // copy postingTable into an array + arraySize = postingTable.size(); + array = _CL_NEWARRAY(Posting*,arraySize); + PostingTableType::iterator postings = postingTable.begin(); + int32_t i=0; + while ( postings != postingTable.end() ){ + array[i] = (Posting*)postings->second; + postings++; + i++; + } + // sort the array + quickSort(array, 0, i - 1); +} + + +void DocumentWriter::invertDocument(const Document* doc) +{ + DocumentFieldEnumeration* fields = doc->fields(); + try { + while (fields->hasMoreElements()) { + Field* field = (Field*)fields->nextElement(); + const TCHAR* fieldName = field->name(); + const int32_t fieldNumber = fieldInfos->fieldNumber(fieldName); + + int32_t length = fieldLengths[fieldNumber]; // length of field + int32_t position = fieldPositions[fieldNumber]; // position in field + if (length>0) + position+=analyzer->getPositionIncrementGap(fieldName); + int32_t offset = fieldOffsets[fieldNumber]; // offset field + + if (field->isIndexed()) { + if (!field->isTokenized()) { // un-tokenized field + //FEATURE: this is bug in java: if using a Reader, then + //field value will not be added. With CLucene, an untokenized + //field with a reader will still be added (if it isn't stored, + //because if it's stored, then the reader has already been read. + const TCHAR* charBuf = NULL; + int64_t dataLen = 0; + + if (field->stringValue() == NULL && !field->isStored() ) { + CL_NS(util)::Reader* r = field->readerValue(); + // this call tries to read the entire stream + // this may invalidate the string for the further calls + // it may be better to do this via a FilterReader + // TODO make a better implementation of this + dataLen = r->read(charBuf, LUCENE_INT32_MAX_SHOULDBE); + if (dataLen == -1) + dataLen = 0; + //todo: would be better to pass the string length, in case + //a null char is passed, but then would need to test the output too. + } else { + charBuf = field->stringValue(); + dataLen = _tcslen(charBuf); + } + + if(field->isStoreOffsetWithTermVector()){ + TermVectorOffsetInfo tio; + tio.setStartOffset(offset); + tio.setEndOffset(offset + dataLen); + addPosition(fieldName, charBuf, position++, &tio ); + }else + addPosition(fieldName, charBuf, position++, NULL); + offset += dataLen; + length++; + } else { // field must be tokenized + CL_NS(util)::Reader* reader; // find or make Reader + bool delReader = false; + if (field->readerValue() != NULL) { + reader = field->readerValue(); + } else if (field->stringValue() != NULL) { + reader = _CLNEW CL_NS(util)::StringReader( + field->stringValue(),_tcslen(field->stringValue()), + false); + delReader = true; + } else { + _CLTHROWA(CL_ERR_IO,"field must have either String or Reader value"); + } + + try { + // Tokenize field and add to postingTable. + CL_NS(analysis)::TokenStream* stream = + analyzer->tokenStream(fieldName, reader); + + try { + CL_NS(analysis)::Token t; + int32_t lastTokenEndOffset = -1; + while (stream->next(&t)) { + position += (t.getPositionIncrement() - 1); + + if(field->isStoreOffsetWithTermVector()){ + TermVectorOffsetInfo tio; + tio.setStartOffset(offset + t.startOffset()); + tio.setEndOffset(offset + t.endOffset()); + addPosition(fieldName, t.termText(), position++, &tio); + } else + addPosition(fieldName, t.termText(), position++, NULL); + + lastTokenEndOffset = t.endOffset(); + length++; + // Apply field truncation policy. + if (maxFieldLength != IndexWriter::FIELD_TRUNC_POLICY__WARN) { + // The client programmer has explicitly authorized us to + // truncate the token stream after maxFieldLength tokens. + if ( length > maxFieldLength) + break; + } else if (length > IndexWriter::DEFAULT_MAX_FIELD_LENGTH) { + const TCHAR* errMsgBase = + _T("Indexing a huge number of tokens from a single") + _T(" field (\"%s\", in this case) can cause CLucene") + _T(" to use memory excessively.") + _T(" By default, CLucene will accept only %s tokens") + _T(" tokens from a single field before forcing the") + _T(" client programmer to specify a threshold at") + _T(" which to truncate the token stream.") + _T(" You should set this threshold via") + _T(" IndexReader::maxFieldLength (set to LUCENE_INT32_MAX") + _T(" to disable truncation, or a value to specify maximum number of fields)."); + + TCHAR defaultMaxAsChar[34]; + _i64tot(IndexWriter::DEFAULT_MAX_FIELD_LENGTH, + defaultMaxAsChar, 10 + ); + int32_t errMsgLen = _tcslen(errMsgBase) + + _tcslen(fieldName) + + _tcslen(defaultMaxAsChar); + TCHAR* errMsg = _CL_NEWARRAY(TCHAR,errMsgLen+1); + + _sntprintf(errMsg, errMsgLen,errMsgBase, fieldName, defaultMaxAsChar); + + _CLTHROWT_DEL(CL_ERR_Runtime,errMsg); + } + } // while token->next + + if(lastTokenEndOffset != -1 ) + offset += lastTokenEndOffset + 1; + } _CLFINALLY ( + stream->close(); + _CLDELETE(stream); + ); + } _CLFINALLY ( + if (delReader) { + _CLDELETE(reader); + } + ); + } // if/else field is to be tokenized + fieldLengths[fieldNumber] = length; // save field length + fieldPositions[fieldNumber] = position; // save field position + fieldBoosts[fieldNumber] *= field->getBoost(); + fieldOffsets[fieldNumber] = offset; + } // if field is to beindexed + } // while more fields available + } _CLFINALLY ( + _CLDELETE(fields); + ); +} + +void DocumentWriter::addPosition(const TCHAR* field, const TCHAR* text, + const int32_t position, TermVectorOffsetInfo* offset) +{ + termBuffer->set(field,text,false); + + Posting* ti = postingTable.get(termBuffer); + if (ti != NULL) { // word seen before + int32_t freq = ti->freq; + if (ti->positions.length == freq) { + // positions array is full, realloc its size + ti->positions.length = freq*2; + ti->positions.values = (int32_t*)realloc(ti->positions.values, ti->positions.length * sizeof(int32_t)); + } + ti->positions.values[freq] = position; // add new position + + if (offset != NULL) { + if (ti->offsets.length == freq){ + ti->offsets.length = freq*2; + ti->offsets.values = (TermVectorOffsetInfo*)realloc(ti->offsets.values, ti->offsets.length * sizeof(TermVectorOffsetInfo)); + } + ti->offsets[freq] = *offset; + } + + ti->freq = freq + 1; // update frequency + } else { // word not seen before + Term* term = _CLNEW Term( field, text, false); + postingTable.put(term, _CLNEW Posting(term, position, offset)); + } +} + +//static +void DocumentWriter::quickSort(Posting**& postings, const int32_t lo, const int32_t hi) +{ + if(lo >= hi) + return; + + int32_t mid = (lo + hi) / 2; + + if(postings[lo]->term->compareTo(postings[mid]->term) > 0) { + Posting* tmp = postings[lo]; + postings[lo] = postings[mid]; + postings[mid] = tmp; + } + + if(postings[mid]->term->compareTo(postings[hi]->term) > 0) { + Posting* tmp = postings[mid]; + postings[mid] = postings[hi]; + postings[hi] = tmp; + + if(postings[lo]->term->compareTo(postings[mid]->term) > 0) { + Posting* tmp2 = postings[lo]; + postings[lo] = postings[mid]; + postings[mid] = tmp2; + } + } + + int32_t left = lo + 1; + int32_t right = hi - 1; + + if (left >= right) + return; + + const Term* partition = postings[mid]->term; //not kept, so no need to finalize + + for( ;; ) { + while(postings[right]->term->compareTo(partition) > 0) + --right; + + while(left < right && postings[left]->term->compareTo(partition) <= 0) + ++left; + + if(left < right) { + Posting* tmp = postings[left]; + postings[left] = postings[right]; + postings[right] = tmp; + --right; + } else { + break; + } + } + + quickSort(postings, lo, left); + quickSort(postings, left + 1, hi); +} + +void DocumentWriter::writePostings(Posting** postings, + const int32_t postingsLength, const QString& segment) +{ + #define __DOCLOSE(obj) \ + if (obj!=NULL) { \ + try { \ + obj->close(); \ + _CLDELETE(obj); \ + } catch(CLuceneError &e) { \ + ierr = e.number(); \ + err = e.what(); \ + } catch(...) { \ + err = "Unknown error while closing posting tables"; \ + } \ + } + + IndexOutput* freq = NULL; + IndexOutput* prox = NULL; + TermInfosWriter* tis = NULL; + TermVectorsWriter* termVectorWriter = NULL; + try { + //open files for inverse index storage + QString buf = Misc::segmentname(segment, QLatin1String(".frq")); + freq = directory->createOutput(buf); + + buf = Misc::segmentname(segment, QLatin1String(".prx")); + prox = directory->createOutput(buf); + + tis = _CLNEW TermInfosWriter(directory, segment, fieldInfos, + termIndexInterval); + TermInfo* ti = _CLNEW TermInfo(); + const TCHAR* currentField = NULL; + for (int32_t i = 0; i < postingsLength; i++) { + Posting* posting = postings[i]; + + // add an entry to the dictionary with pointers to prox and freq files + ti->set(1, freq->getFilePointer(), prox->getFilePointer(), -1); + tis->add(posting->term, ti); + + // add an entry to the freq file + int32_t postingFreq = posting->freq; + if (postingFreq == 1) // optimize freq=1 + freq->writeVInt(1); // set low bit of doc num. + else { + freq->writeVInt(0); // the document number + freq->writeVInt(postingFreq); // frequency in doc + } + + int32_t lastPosition = 0; // write positions + for (int32_t j = 0; j < postingFreq; ++j) { // use delta-encoding + prox->writeVInt(posting->positions.values[j] - lastPosition); + lastPosition = posting->positions.values[j]; + } + + // check to see if we switched to a new field + const TCHAR* termField = posting->term->field(); + if ( currentField == NULL || _tcscmp(currentField,termField) != 0 ) { + //todo, can we do an intern'd check? + // changing field - see if there is something to save + currentField = termField; + FieldInfo* fi = fieldInfos->fieldInfo(currentField); + + if (fi->storeTermVector) { + if (termVectorWriter == NULL) { + termVectorWriter = _CLNEW TermVectorsWriter(directory, + segment, fieldInfos); + termVectorWriter->openDocument(); + } + termVectorWriter->openField(currentField); + } else if (termVectorWriter != NULL) { + termVectorWriter->closeField(); + } + } + if (termVectorWriter != NULL && termVectorWriter->isFieldOpen()) { + termVectorWriter->addTerm(posting->term->text(), postingFreq, + &posting->positions, &posting->offsets); + } + } + if (termVectorWriter != NULL) + termVectorWriter->closeDocument(); + _CLDELETE(ti); + } _CLFINALLY ( + const char* err = NULL; + int32_t ierr = 0; + + // make an effort to close all streams we can but remember and re-throw + // the first exception encountered in this process + __DOCLOSE(freq); + __DOCLOSE(prox); + __DOCLOSE(tis); + __DOCLOSE(termVectorWriter); + if (err != NULL) + _CLTHROWA(ierr,err); + ); +} + +void DocumentWriter::writeNorms(const QString& segment) +{ + for(int32_t n = 0; n < fieldInfos->size(); n++){ + FieldInfo* fi = fieldInfos->fieldInfo(n); + if(fi->isIndexed && !fi->omitNorms) { + qreal norm = fieldBoosts[n] * similarity->lengthNorm( + fi->name, fieldLengths[n]); + + QString fn(segment + QLatin1String(".f%1")); + IndexOutput* norms = directory->createOutput(fn.arg(n)); + try { + norms->writeByte(CL_NS(search)::Similarity::encodeNorm(norm)); + }_CLFINALLY ( + norms->close(); + _CLDELETE(norms); + ) + } + } +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/DocumentWriter.h b/3rdparty/clucene/src/CLucene/index/DocumentWriter.h new file mode 100644 index 0000000..7096ba3 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/DocumentWriter.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_DocumentWriter_ +#define _lucene_index_DocumentWriter_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/document/Document.h" +#include "CLucene/store/Directory.h" +#include "FieldInfos.h" +#include "IndexWriter.h" +#include "CLucene/util/VoidMap.h" +#include "CLucene/document/Field.h" +#include "TermInfo.h" +#include "CLucene/search/Similarity.h" +#include "TermInfosWriter.h" +#include "FieldsWriter.h" +#include "Term.h" + +CL_NS_DEF(index) + +class DocumentWriter : LUCENE_BASE +{ +public: + // info about a Term in a doc + class Posting : LUCENE_BASE + { + public: + Term* term; // the Term + int32_t freq; // its frequency in doc + Array positions; // positions it occurs at + Array offsets; + + Posting(Term* t, const int32_t position, TermVectorOffsetInfo* offset); + ~Posting(); + }; + +private: + CL_NS(analysis)::Analyzer* analyzer; + CL_NS(store)::Directory* directory; + FieldInfos* fieldInfos; //array + const int32_t maxFieldLength; + CL_NS(search)::Similarity* similarity; + int32_t termIndexInterval; + + // Keys are Terms, values are Postings. + // Used to buffer a document before it is written to the index. + typedef CL_NS(util)::CLHashtable PostingTableType; + PostingTableType postingTable; + int32_t* fieldLengths; //array + int32_t* fieldPositions; //array + int32_t* fieldOffsets; //array + qreal* fieldBoosts; //array + + Term* termBuffer; +public: + /** This ctor used by test code only. + * + * @param directory The directory to write the document information to + * @param analyzer The analyzer to use for the document + * @param similarity The Similarity function + * @param maxFieldLength The maximum number of tokens a field may have + */ + DocumentWriter(CL_NS(store)::Directory* d, CL_NS(analysis)::Analyzer* a, + CL_NS(search)::Similarity* similarity, const int32_t maxFieldLength); + + DocumentWriter(CL_NS(store)::Directory* directory, + CL_NS(analysis)::Analyzer* analyzer, IndexWriter* writer); + ~DocumentWriter(); + + void addDocument(const QString& segment, CL_NS(document)::Document* doc); + + +private: + // Tokenizes the fields of a document into Postings. + void invertDocument(const CL_NS(document)::Document* doc); + + void addPosition(const TCHAR* field, const TCHAR* text, + const int32_t position, TermVectorOffsetInfo* offset); + + void sortPostingTable(Posting**& array, int32_t& arraySize); + + static void quickSort(Posting**& postings, const int32_t lo, const int32_t hi); + + void writePostings(Posting** postings, const int32_t postingsLength, + const QString& segment); + + void writeNorms(const QString& segment); + + void clearPostingTable(); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/FieldInfo.h b/3rdparty/clucene/src/CLucene/index/FieldInfo.h new file mode 100644 index 0000000..387c4a6 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/FieldInfo.h @@ -0,0 +1,16 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_FieldInfo_ +#define _lucene_index_FieldInfo_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#error "This header is deprecated, use FieldInfos.h instead" + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/FieldInfos.cpp b/3rdparty/clucene/src/CLucene/index/FieldInfos.cpp new file mode 100644 index 0000000..0c66882 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/FieldInfos.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "FieldInfos.h" + +#include "CLucene/store/Directory.h" +#include "CLucene/document/Document.h" +#include "CLucene/document/Field.h" +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/Misc.h" +#include "CLucene/util/StringIntern.h" + +CL_NS_USE(store) +CL_NS_USE(document) +CL_NS_USE(util) +CL_NS_DEF(index) + +FieldInfo::FieldInfo(const TCHAR* _fieldName, bool _isIndexed, + int32_t _fieldNumber, bool _storeTermVector, bool _storeOffsetWithTermVector, + bool _storePositionWithTermVector, bool _omitNorms) + : name(CLStringIntern::intern(_fieldName CL_FILELINE)) + , isIndexed(_isIndexed) + , number(_fieldNumber) + , storeTermVector(_storeTermVector) + , storeOffsetWithTermVector(_storeOffsetWithTermVector) + , storePositionWithTermVector(_storeTermVector) + , omitNorms(_omitNorms) +{ +} + +FieldInfo::~FieldInfo() +{ + CL_NS(util)::CLStringIntern::unintern(name); +} + +// #pragma mark -- FieldInfos + +FieldInfos::FieldInfos() + : byName(false, false) + , byNumber(true) +{ +} + +FieldInfos::~FieldInfos() +{ + byName.clear(); + byNumber.clear(); +} + +FieldInfos::FieldInfos(Directory* d, const QString& name) + : byName(false, false) + , byNumber(true) +{ + IndexInput* input = d->openInput(name); + try { + read(input); + } _CLFINALLY ( + input->close(); + _CLDELETE(input); + ); +} + +void FieldInfos::add(const Document* doc) +{ + DocumentFieldEnumeration* fields = doc->fields(); + Field* field; + while (fields->hasMoreElements()) { + field = fields->nextElement(); + add(field->name(), field->isIndexed(), field->isTermVectorStored()); + } + _CLDELETE(fields); +} + +void FieldInfos::add(const TCHAR* name, bool isIndexed, bool storeTermVector, + bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms) +{ + FieldInfo* fi = fieldInfo(name); + if (fi == NULL) { + addInternal(name, isIndexed, storeTermVector, + storePositionWithTermVector, + storeOffsetWithTermVector, omitNorms); + } else { + if (fi->isIndexed != isIndexed) { + // once indexed, always index + fi->isIndexed = true; + } + + if (fi->storeTermVector != storeTermVector) { + // once vector, always vector + fi->storeTermVector = true; + } + + if (fi->storePositionWithTermVector != storePositionWithTermVector) { + // once vector, always vector + fi->storePositionWithTermVector = true; + } + + if (fi->storeOffsetWithTermVector != storeOffsetWithTermVector) { + // once vector, always vector + fi->storeOffsetWithTermVector = true; + } + + if (fi->omitNorms != omitNorms) { + // once norms are stored, always store + fi->omitNorms = false; + } + } +} + +void FieldInfos::add(const TCHAR** names, bool isIndexed, bool storeTermVectors, + bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms) +{ + int32_t i=0; + while (names[i] != NULL) { + add(names[i], isIndexed, storeTermVectors, storePositionWithTermVector, + storeOffsetWithTermVector, omitNorms); + ++i; + } +} + +int32_t FieldInfos::fieldNumber(const TCHAR* fieldName) const +{ + FieldInfo* fi = fieldInfo(fieldName); + return (fi != NULL) ? fi->number : -1; +} + +FieldInfo* FieldInfos::fieldInfo(const TCHAR* fieldName) const +{ + return byName.get(fieldName); +} + +const TCHAR* FieldInfos::fieldName(const int32_t fieldNumber) const +{ + FieldInfo* fi = fieldInfo(fieldNumber); + return (fi == NULL) ? LUCENE_BLANK_STRING : fi->name; +} + +FieldInfo* FieldInfos::fieldInfo(const int32_t fieldNumber) const +{ + if (fieldNumber < 0 || (size_t)fieldNumber >= byNumber.size()) + return NULL; + return byNumber[fieldNumber]; +} + +int32_t FieldInfos::size() const +{ + return byNumber.size(); +} + +void FieldInfos::write(Directory* d, const QString& name) const +{ + IndexOutput* output = d->createOutput(name); + try { + write(output); + } _CLFINALLY ( + output->close(); + _CLDELETE(output); + ); +} + +void FieldInfos::write(IndexOutput* output) const +{ + output->writeVInt(size()); + FieldInfo* fi; + uint8_t bits; + for (int32_t i = 0; i < size(); ++i) { + fi = fieldInfo(i); + bits = 0x0; + if (fi->isIndexed) + bits |= IS_INDEXED; + + if (fi->storeTermVector) + bits |= STORE_TERMVECTOR; + + if (fi->storePositionWithTermVector) + bits |= STORE_POSITIONS_WITH_TERMVECTOR; + + if (fi->storeOffsetWithTermVector) + bits |= STORE_OFFSET_WITH_TERMVECTOR; + + if (fi->omitNorms) + bits |= OMIT_NORMS; + + output->writeString(fi->name, _tcslen(fi->name)); + output->writeByte(bits); + } +} + +void FieldInfos::read(IndexInput* input) +{ + int32_t size = input->readVInt(); + for (int32_t i = 0; i < size; ++i) { + // we could read name into a string buffer, but we can't be sure what + // the maximum field length will be. + TCHAR* name = input->readString(); + uint8_t bits = input->readByte(); + bool isIndexed = (bits & IS_INDEXED) != 0; + bool storeTermVector = (bits & STORE_TERMVECTOR) != 0; + bool storePositionsWithTermVector = + (bits & STORE_POSITIONS_WITH_TERMVECTOR) != 0; + bool storeOffsetWithTermVector = (bits & STORE_OFFSET_WITH_TERMVECTOR) != 0; + bool omitNorms = (bits & OMIT_NORMS) != 0; + + addInternal(name, isIndexed, storeTermVector, + storePositionsWithTermVector, storeOffsetWithTermVector, omitNorms); + _CLDELETE_CARRAY(name); + } +} + +void FieldInfos::addInternal(const TCHAR* name, bool isIndexed, + bool storeTermVector, bool storePositionWithTermVector, + bool storeOffsetWithTermVector, bool omitNorms) +{ + FieldInfo* fi = _CLNEW FieldInfo(name, isIndexed, byNumber.size(), + storeTermVector, storePositionWithTermVector, storeOffsetWithTermVector, + omitNorms); + byNumber.push_back(fi); + byName.put(fi->name, fi); +} + +bool FieldInfos::hasVectors() const +{ + for (int32_t i = 0; i < size(); i++) { + if (fieldInfo(i)->storeTermVector) + return true; + } + return false; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/FieldInfos.h b/3rdparty/clucene/src/CLucene/index/FieldInfos.h new file mode 100644 index 0000000..7b6d0f5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/FieldInfos.h @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_FieldInfos_ +#define _lucene_index_FieldInfos_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" +#include "CLucene/document/Document.h" +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/VoidList.h" + +CL_NS_DEF(index) + +class FieldInfo : LUCENE_BASE +{ + public: + //name of the field + const TCHAR* name; + + //Is field indexed? true = yes false = no + bool isIndexed; + + //field number + const int32_t number; + + // true if term vector for this field should be stored + bool storeTermVector; + bool storeOffsetWithTermVector; + bool storePositionWithTermVector; + + bool omitNorms; // omit norms associated with indexed fields + + //Func - Constructor + // Initialises FieldInfo. + // na holds the name of the field + // tk indicates whether this field is indexed or not + // nu indicates its number + //Pre - na != NULL and holds the name of the field + // tk is true or false + // number >= 0 + //Post - The FieldInfo instance has been created and initialized. + // name holds the duplicated string of na + // isIndexed = tk + // number = nu + FieldInfo(const TCHAR* fieldName, bool isIndexed, int32_t fieldNumber, + bool storeTermVector, bool storeOffsetWithTermVector, + bool storePositionWithTermVector, bool omitNorms); + + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + ~FieldInfo(); +}; + +/* Access to the Field Info file that describes document fields and whether or + * not they are indexed. Each segment has a separate Field Info file. Objects + * of this class are thread-safe for multiple readers, but only one thread can + * be adding documents at a time, with no other reader or writer threads + * accessing this object. +*/ +class FieldInfos : LUCENE_BASE +{ +private: + // we now use internd field names, so we can use the voidCompare to + // directly compare the strings + typedef CL_NS(util)::CLHashMap defByName; + defByName byName; + + CL_NS(util)::CLArrayList > byNumber; + +public: + enum { + IS_INDEXED = 0x1, + STORE_TERMVECTOR = 0x2, + STORE_POSITIONS_WITH_TERMVECTOR = 0x4, + STORE_OFFSET_WITH_TERMVECTOR = 0x8, + OMIT_NORMS = 0x10 + }; + + FieldInfos(); + ~FieldInfos(); + + // Construct a FieldInfos object using the directory and the name of the + // file IndexInput + // @param d The directory to open the IndexInput from + // @param name Name of the file to open the IndexInput from in the Directory + // @throws IOException + // @see #read + FieldInfos(CL_NS(store)::Directory* d, const QString& name); + + int32_t fieldNumber(const TCHAR* fieldName)const; + + // Return the fieldinfo object referenced by the fieldNumber. + // @param fieldNumber + // @return the FieldInfo object or null when the given fieldNumber + // doesn't exist. + FieldInfo* fieldInfo(const TCHAR* fieldName) const; + + // Return the fieldName identified by its number. + // @param fieldNumber + // @return the fieldName or an empty string when the field + // with the given number doesn't exist. + const TCHAR* fieldName(const int32_t fieldNumber) const; + + FieldInfo* fieldInfo(const int32_t fieldNumber) const; + + int32_t size()const; + + bool hasVectors() const; + + // Adds field info for a Document. + void add(const CL_NS(document)::Document* doc); + + // Merges in information from another FieldInfos. + void add(FieldInfos* other); + + + /** If the field is not yet known, adds it. If it is known, checks to make + * sure that the isIndexed flag is the same as was given previously for this + * field. If not - marks it as being indexed. Same goes for the TermVector + * parameters. + * + * @param name The name of the field + * @param isIndexed true if the field is indexed + * @param storeTermVector true if the term vector should be stored + * @param storePositionWithTermVector true if the term vector with positions should be stored + * @param storeOffsetWithTermVector true if the term vector with offsets should be stored + */ + void add(const TCHAR* name, bool isIndexed, bool storeTermVector = false, + bool storePositionWithTermVector = false, + bool storeOffsetWithTermVector = false, bool omitNorms = false); + + /** + * Assumes the fields are not storing term vectors + * @param names The names of the fields + * @param isIndexed true if the field is indexed + * @param storeTermVector true if the term vector should be stored + * + * @see #add(String, boolean) + */ + void add(const TCHAR** names, bool isIndexed, bool storeTermVector = false, + bool storePositionWithTermVector = false, + bool storeOffsetWithTermVector = false, bool omitNorms = false); + + void write(CL_NS(store)::Directory* d, const QString& name) const; + void write(CL_NS(store)::IndexOutput* output) const; + +private: + void read(CL_NS(store)::IndexInput* input); + void addInternal(const TCHAR* name, bool isIndexed, bool storeTermVector, + bool storePositionWithTermVector, bool storeOffsetWithTermVector, + bool omitNorms); + +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/FieldsReader.cpp b/3rdparty/clucene/src/CLucene/index/FieldsReader.cpp new file mode 100644 index 0000000..e3f9d1c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/FieldsReader.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "FieldsReader.h" + +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/Misc.h" +#include "CLucene/store/Directory.h" +#include "CLucene/document/Document.h" +#include "CLucene/document/Field.h" +#include "FieldInfos.h" +#include "FieldsWriter.h" + +CL_NS_USE(store) +CL_NS_USE(document) +CL_NS_USE(util) +CL_NS_DEF(index) + +FieldsReader::FieldsReader(Directory* d, const QString& segment, FieldInfos* fn) + : fieldInfos(fn) +{ + //Func - Constructor + //Pre - d contains a valid reference to a Directory + // segment != NULL + // fn contains a valid reference to a FieldInfos + //Post - The instance has been created + + CND_PRECONDITION(!segment.isEmpty(), "segment != NULL"); + + QString buf = Misc::segmentname(segment, QLatin1String(".fdt")); + fieldsStream = d->openInput(buf); + + buf = Misc::segmentname(segment, QLatin1String(".fdx")); + indexStream = d->openInput(buf); + + _size = (int32_t)indexStream->length() / 8; +} + +FieldsReader::~FieldsReader() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + close(); +} + +void FieldsReader::close() +{ + //Func - Closes the FieldsReader + //Pre - true + //Post - The FieldsReader has been closed + if (fieldsStream) { + fieldsStream->close(); + _CLDELETE(fieldsStream); + } + + if(indexStream) { + indexStream->close(); + _CLDELETE(indexStream); + } +} + +int32_t FieldsReader::size() const +{ + return _size; +} + +bool FieldsReader::doc(int32_t n, Document* doc) +{ + if ( n * 8L > indexStream->length() ) + return false; + + indexStream->seek(n * 8L); + int64_t position = indexStream->readLong(); + fieldsStream->seek(position); + + int32_t numFields = fieldsStream->readVInt(); + for (int32_t i = 0; i < numFields; i++) { + int32_t fieldNumber = fieldsStream->readVInt(); + FieldInfo* fi = fieldInfos->fieldInfo(fieldNumber); + + if ( fi == NULL ) + _CLTHROWA(CL_ERR_IO, "Field stream is invalid"); + + uint8_t bits = fieldsStream->readByte(); + if ((bits & FieldsWriter::FIELD_IS_BINARY) != 0) { + int32_t fieldLen = fieldsStream->readVInt(); + FieldsReader::FieldsStreamHolder* subStream = new + FieldsReader::FieldsStreamHolder(fieldsStream, fieldLen); + uint8_t bits = Field::STORE_YES; + Field* f = _CLNEW Field( + fi->name, // name + subStream, // read value + bits); + + doc->add(*f); + + //now skip over the rest of the field + if (fieldsStream->getFilePointer() + fieldLen + == fieldsStream->length()) { + // set to eof + fieldsStream->seek(fieldsStream->getFilePointer() + fieldLen - 1); + fieldsStream->readByte(); + } else { + fieldsStream->seek(fieldsStream->getFilePointer() + fieldLen); + } + } else { + uint8_t bits = Field::STORE_YES; + if (fi->isIndexed && (bits & FieldsWriter::FIELD_IS_TOKENIZED)!=0 ) + bits |= Field::INDEX_TOKENIZED; + else if (fi->isIndexed && (bits & FieldsWriter::FIELD_IS_TOKENIZED) == 0) + bits |= Field::INDEX_UNTOKENIZED; + else + bits |= Field::INDEX_NO; + + if (fi->storeTermVector) { + if (fi->storeOffsetWithTermVector) { + if (fi->storePositionWithTermVector) { + bits |= Field::TERMVECTOR_WITH_OFFSETS; + bits |= Field::TERMVECTOR_WITH_POSITIONS; + } else { + bits |= Field::TERMVECTOR_WITH_OFFSETS; + } + } else if (fi->storePositionWithTermVector) { + bits |= Field::TERMVECTOR_WITH_POSITIONS; + } else { + bits |= Field::TERMVECTOR_YES; + } + } else { + bits |= Field::TERMVECTOR_NO; + } + + if ( (bits & FieldsWriter::FIELD_IS_COMPRESSED) != 0 ) { + bits |= Field::STORE_COMPRESS; + int32_t fieldLen = fieldsStream->readVInt(); + FieldsStreamHolder* subStream = new + FieldsStreamHolder(fieldsStream, fieldLen); + + // TODO: we dont have gzip inputstream available, must alert + // user to somehow use a gzip inputstream + Field* f = _CLNEW Field( + fi->name, // name + subStream, // read value + bits); + + f->setOmitNorms(fi->omitNorms); + doc->add(*f); + + // now skip over the rest of the field + if (fieldsStream->getFilePointer() + fieldLen + == fieldsStream->length()) { + //set to eof + fieldsStream->seek(fieldsStream->getFilePointer() + fieldLen - 1); + fieldsStream->readByte(); + } else { + fieldsStream->seek(fieldsStream->getFilePointer() + fieldLen); + } + } else { + TCHAR* fvalue = fieldsStream->readString(true); + Field* f = _CLNEW Field( + fi->name, // name + fvalue, // read value + bits); + // TODO: could optimise this + _CLDELETE_CARRAY(fvalue); + f->setOmitNorms(fi->omitNorms); + doc->add(*f); + } + } + } + return true; +} + +FieldsReader::FieldsStreamHolder::FieldsStreamHolder(IndexInput* indexInput, + int32_t subLength) +{ + this->indexInput = indexInput->clone(); + this->indexInputStream = new IndexInputStream(this->indexInput); + this->subStream = new jstreams::SubInputStream(indexInputStream, + subLength); + + this->size = subStream->getSize(); + this->position = subStream->getPosition(); + this->error = subStream->getError(); + this->status = subStream->getStatus(); +} + +FieldsReader::FieldsStreamHolder::~FieldsStreamHolder() +{ + delete subStream; + delete indexInputStream; + + indexInput->close(); + _CLDELETE(indexInput); +} + +int32_t FieldsReader::FieldsStreamHolder::read(const char*& start, int32_t _min, + int32_t _max) +{ + int32_t ret = subStream->read(start,_min,_max); + this->position = subStream->getPosition(); + this->error = subStream->getError(); + this->status = subStream->getStatus(); + return ret; +} + +int64_t FieldsReader::FieldsStreamHolder::skip(int64_t ntoskip) +{ + int64_t ret = subStream->skip(ntoskip); + this->position = subStream->getPosition(); + this->error = subStream->getError(); + this->status = subStream->getStatus(); + return ret; +} + +int64_t FieldsReader::FieldsStreamHolder::reset(int64_t pos) +{ + int64_t ret = subStream->reset(pos); + this->position = subStream->getPosition(); + this->error = subStream->getError(); + this->status = subStream->getStatus(); + return ret; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/FieldsReader.h b/3rdparty/clucene/src/CLucene/index/FieldsReader.h new file mode 100644 index 0000000..53589a5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/FieldsReader.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_FieldsReader_ +#define _lucene_index_FieldsReader_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" +#include "CLucene/document/Document.h" +#include "CLucene/util/subinputstream.h" +#include "CLucene/store/IndexInput.h" + +CL_NS_DEF(index) + +class FieldInfos; + +class FieldsReader : LUCENE_BASE +{ +private: + const FieldInfos* fieldInfos; + CL_NS(store)::IndexInput* fieldsStream; + CL_NS(store)::IndexInput* indexStream; + int32_t _size; + + class FieldsStreamHolder : public jstreams::StreamBase + { + CL_NS(store)::IndexInput* indexInput; + CL_NS(store)::IndexInputStream* indexInputStream; + jstreams::SubInputStream* subStream; + + public: + FieldsStreamHolder(CL_NS(store)::IndexInput* indexInput, int32_t subLength); + ~FieldsStreamHolder(); + int32_t read(const char*& start, int32_t _min, int32_t _max); + int64_t skip(int64_t ntoskip); + int64_t reset(int64_t pos); + }; + +public: + FieldsReader(CL_NS(store)::Directory* d, const QString& segment, FieldInfos* fn); + ~FieldsReader(); + void close(); + int32_t size() const; + // loads the fields from n'th document into doc. returns true on success. + bool doc(int32_t n, CL_NS(document)::Document* doc); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/FieldsWriter.cpp b/3rdparty/clucene/src/CLucene/index/FieldsWriter.cpp new file mode 100644 index 0000000..ceb6735 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/FieldsWriter.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "FieldsWriter.h" + +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/Reader.h" +#include "CLucene/util/Misc.h" +#include "CLucene/store/Directory.h" +#include "CLucene/store/IndexOutput.h" +#include "CLucene/document/Document.h" +#include "CLucene/document/Field.h" +#include "FieldInfos.h" + +CL_NS_USE(store) +CL_NS_USE(util) +CL_NS_USE(document) +CL_NS_DEF(index) + +FieldsWriter::FieldsWriter(Directory* d, const QString& segment, FieldInfos* fn) + : fieldInfos(fn) +{ + //Func - Constructor + //Pre - d contains a valid reference to a directory + // segment != NULL and contains the name of the segment + //Post - fn contains a valid reference toa a FieldInfos + + CND_PRECONDITION(!segment.isEmpty(), "segment is NULL"); + + QString buf = Misc::segmentname(segment, QLatin1String(".fdt")); + fieldsStream = d->createOutput(buf); + + buf = Misc::segmentname(segment, QLatin1String(".fdx")); + indexStream = d->createOutput(buf); + + CND_CONDITION(indexStream != NULL, "indexStream is NULL"); +} + +FieldsWriter::~FieldsWriter() +{ + //Func - Destructor + //Pre - true + //Post - Instance has been destroyed + + close(); +} + +void FieldsWriter::close() +{ + //Func - Closes all streams and frees all resources + //Pre - true + //Post - All streams have been closed all resources have been freed + + //Check if fieldsStream is valid + if (fieldsStream) { + //Close fieldsStream + fieldsStream->close(); + _CLDELETE(fieldsStream); + } + + //Check if indexStream is valid + if (indexStream) { + //Close indexStream + indexStream->close(); + _CLDELETE(indexStream); + } +} + +void FieldsWriter::addDocument(Document* doc) +{ + //Func - Adds a document + //Pre - doc contains a valid reference to a Document + // indexStream != NULL + // fieldsStream != NULL + //Post - The document doc has been added + + CND_PRECONDITION(indexStream != NULL, "indexStream is NULL"); + CND_PRECONDITION(fieldsStream != NULL, "fieldsStream is NULL"); + + indexStream->writeLong(fieldsStream->getFilePointer()); + + int32_t storedCount = 0; + DocumentFieldEnumeration* fields = doc->fields(); + while (fields->hasMoreElements()) { + Field* field = fields->nextElement(); + if (field->isStored()) + storedCount++; + } + _CLDELETE(fields); + fieldsStream->writeVInt(storedCount); + + fields = doc->fields(); + while (fields->hasMoreElements()) { + Field* field = fields->nextElement(); + if (field->isStored()) { + fieldsStream->writeVInt(fieldInfos->fieldNumber(field->name())); + + uint8_t bits = 0; + if (field->isTokenized()) + bits |= FieldsWriter::FIELD_IS_TOKENIZED; + if (field->isBinary()) + bits |= FieldsWriter::FIELD_IS_BINARY; + if (field->isCompressed()) + bits |= FieldsWriter::FIELD_IS_COMPRESSED; + + fieldsStream->writeByte(bits); + + if ( field->isCompressed()) { + _CLTHROWA(CL_ERR_Runtime, + "CLucene does not directly support compressed fields. " + "Write a compressed byte array instead"); + } else { + // FEATURE: this problem in Java Lucene too, if using Reader, + // data is not stored. + // + // TODO: this is a logic bug... + // if the field is stored, and indexed, and is using a reader + // the field wont get indexed + // + // if we could write zero prefixed vints (therefore static + // length), then we could write a reader directly to the field + // indexoutput and then go back and write the data length. + // however this is not supported in lucene yet... + // if this is ever implemented, then it would make sense to + // also be able to combine the FieldsWriter and + // DocumentWriter::invertDocument process, and use a + // streamfilter to write the field data while the documentwrite + // analyses the document! how cool would that be! it would cut + // out all these buffers!!! + + // compression is disabled for the current field + if (field->isBinary()) { + // TODO: since we currently don't support static length vints, + // we have to read the entire stream into memory first.... ugly! + jstreams::StreamBase* stream = field->streamValue(); + const char* sd; + // how do we make sure we read the entire index in now??? + // TODO: we need to have a max amount, and guarantee its all + // in or throw an error... + int32_t rl = stream->read(sd,10000000,0); + + if ( rl < 0 ) { + // TODO: could we detect this earlier and not actually + // write the field?? + fieldsStream->writeVInt(0); + } else { + // TODO: if this int could be written with a constant + // length, then the stream could be read and written a + // bit at a time then the length is re-written at the end. + fieldsStream->writeVInt(rl); + fieldsStream->writeBytes((uint8_t*)sd, rl); + } + } else if (field->stringValue() == NULL ) { + // we must be using readerValue + CND_PRECONDITION(!field->isIndexed(), + "Cannot store reader if it is indexed too") + Reader* r = field->readerValue(); + + //read the entire string + const TCHAR* rv; + int64_t rl = r->read(rv, LUCENE_INT32_MAX_SHOULDBE); + if ( rl > LUCENE_INT32_MAX_SHOULDBE ) + _CLTHROWA(CL_ERR_Runtime, "Field length too long"); + else if ( rl < 0 ) + rl = 0; + + fieldsStream->writeString( rv, (int32_t)rl); + } else if (field->stringValue() != NULL ) { + fieldsStream->writeString(field->stringValue(), + _tcslen(field->stringValue())); + } else { + _CLTHROWA(CL_ERR_Runtime, "No values are set for the field"); + } + } + } + } + _CLDELETE(fields); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/FieldsWriter.h b/3rdparty/clucene/src/CLucene/index/FieldsWriter.h new file mode 100644 index 0000000..7dde5f2 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/FieldsWriter.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_FieldsWriter_ +#define _lucene_index_FieldsWriter_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/document/Document.h" +#include "CLucene/store/Directory.h" +#include "CLucene/store/IndexOutput.h" + +CL_NS_DEF(index) + +class FieldInfos; + +class FieldsWriter : LUCENE_BASE +{ +private: + FieldInfos* fieldInfos; + + CL_NS(store)::IndexOutput* fieldsStream; + CL_NS(store)::IndexOutput* indexStream; + +public: + LUCENE_STATIC_CONSTANT(uint8_t, FIELD_IS_TOKENIZED = 0x1); + LUCENE_STATIC_CONSTANT(uint8_t, FIELD_IS_BINARY = 0x2); + LUCENE_STATIC_CONSTANT(uint8_t, FIELD_IS_COMPRESSED = 0x4); + + FieldsWriter(CL_NS(store)::Directory* d, const QString& segment, FieldInfos* fn); + ~FieldsWriter(); + + void close(); + + void addDocument(CL_NS(document)::Document* doc); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/IndexModifier.cpp b/3rdparty/clucene/src/CLucene/index/IndexModifier.cpp new file mode 100644 index 0000000..1423cc7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/IndexModifier.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "IndexModifier.h" + +#include "Term.h" +#include "IndexWriter.h" +#include "IndexReader.h" + +CL_NS_DEF(index) +CL_NS_USE(util) +CL_NS_USE(store) +CL_NS_USE(analysis) +CL_NS_USE(document) + +IndexModifier::IndexModifier(Directory* directory, Analyzer* analyzer, bool create) { + init(directory, analyzer, create); +} + +IndexModifier::IndexModifier(const QString& dirName, Analyzer* analyzer, bool create) { + Directory* dir = FSDirectory::getDirectory(dirName, create); + init(dir, analyzer, create); +} + +void IndexModifier::init(Directory* directory, Analyzer* analyzer, bool create) { + indexWriter = NULL; + indexReader = NULL; + this->analyzer = analyzer; + open = false; + + useCompoundFile = true; + int32_t maxBufferedDocs = IndexWriter::DEFAULT_MAX_BUFFERED_DOCS; + this->maxFieldLength = IndexWriter::DEFAULT_MAX_FIELD_LENGTH; + int32_t mergeFactor = IndexWriter::DEFAULT_MERGE_FACTOR; + + this->directory = _CL_POINTER(directory); + createIndexReader(); + open = true; +} + +IndexModifier::~IndexModifier(){ + close(); +} + +void IndexModifier::assureOpen() const{ + if (!open) { + _CLTHROWA(CL_ERR_IllegalState,"Index is closed"); + } +} + +void IndexModifier::createIndexWriter() { + if (indexWriter == NULL) { + if (indexReader != NULL) { + indexReader->close(); + _CLDELETE(indexReader); + } + indexWriter = _CLNEW IndexWriter(directory, analyzer, false); + indexWriter->setUseCompoundFile(useCompoundFile); + //indexWriter->setMaxBufferedDocs(maxBufferedDocs); + indexWriter->setMaxFieldLength(maxFieldLength); + //indexWriter->setMergeFactor(mergeFactor); + } +} + +void IndexModifier::createIndexReader() { + if (indexReader == NULL) { + if (indexWriter != NULL) { + indexWriter->close(); + _CLDELETE(indexWriter); + } + indexReader = IndexReader::open(directory); + } +} + +void IndexModifier::flush() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + if (indexWriter != NULL) { + indexWriter->close(); + _CLDELETE(indexWriter); + createIndexWriter(); + } else { + indexReader->close(); + _CLDELETE(indexReader); + createIndexReader(); + } +} + +void IndexModifier::addDocument(Document* doc, Analyzer* docAnalyzer) { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexWriter(); + if (docAnalyzer != NULL) + indexWriter->addDocument(doc, docAnalyzer); + else + indexWriter->addDocument(doc); +} + +int32_t IndexModifier::deleteDocuments(Term* term) { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexReader(); + return indexReader->deleteDocuments(term); +} + +void IndexModifier::deleteDocument(int32_t docNum) { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexReader(); + indexReader->deleteDocument(docNum); +} + +int32_t IndexModifier::docCount() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + if (indexWriter != NULL) + return indexWriter->docCount(); + else + return indexReader->numDocs(); +} + +void IndexModifier::optimize() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexWriter(); + indexWriter->optimize(); +} + +void IndexModifier::setUseCompoundFile(bool useCompoundFile) { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + if (indexWriter != NULL) + indexWriter->setUseCompoundFile(useCompoundFile); + this->useCompoundFile = useCompoundFile; +} + +bool IndexModifier::getUseCompoundFile() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexWriter(); + return indexWriter->getUseCompoundFile(); +} + +void IndexModifier::setMaxFieldLength(int32_t maxFieldLength) { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + if (indexWriter != NULL) + indexWriter->setMaxFieldLength(maxFieldLength); + this->maxFieldLength = maxFieldLength; +} + +int32_t IndexModifier::getMaxFieldLength() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexWriter(); + return indexWriter->getMaxFieldLength(); +} + +void IndexModifier::setMaxBufferedDocs(int32_t maxBufferedDocs) { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + if (indexWriter != NULL) + indexWriter->setMaxBufferedDocs(maxBufferedDocs); + this->maxBufferedDocs = maxBufferedDocs; +} + +int32_t IndexModifier::getMaxBufferedDocs() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexWriter(); + return indexWriter->getMaxBufferedDocs(); +} +void IndexModifier::setMergeFactor(int32_t mergeFactor) { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + if (indexWriter != NULL) + indexWriter->setMergeFactor(mergeFactor); + this->mergeFactor = mergeFactor; +} + +int32_t IndexModifier::getMergeFactor() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexWriter(); + return indexWriter->getMergeFactor(); +} + +void IndexModifier::close() { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + if (indexWriter != NULL) { + indexWriter->close(); + _CLDELETE(indexWriter); + } else { + indexReader->close(); + _CLDELETE(indexReader); + } + _CLDECDELETE(directory) + open = false; +} + +QString IndexModifier::toString() const +{ + QString ret(QLatin1String("Index@")); + return ret.append(directory->toString()); +} + + + +int64_t IndexModifier::getCurrentVersion() const{ + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + return IndexReader::getCurrentVersion(directory); +} + +TermDocs* IndexModifier::termDocs(Term* term){ + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexReader(); + return indexReader->termDocs(term); +} + +TermEnum* IndexModifier::terms(Term* term){ + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexReader(); + if ( term != NULL ) + return indexReader->terms(term); + else + return indexReader->terms(); +} + + + CL_NS(document)::Document* IndexModifier::document(const int32_t n){ + Document* ret = _CLNEW Document; + if (!document(n,ret) ) + _CLDELETE(ret); + return ret; + } +bool IndexModifier::document(int32_t n, CL_NS(document)::Document* doc){ + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + assureOpen(); + createIndexReader(); + return indexReader->document(n, doc); +} +CL_NS(store)::Directory* IndexModifier::getDirectory(){ + return directory; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/IndexModifier.h b/3rdparty/clucene/src/CLucene/index/IndexModifier.h new file mode 100644 index 0000000..4e9963f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/IndexModifier.h @@ -0,0 +1,316 @@ +/* +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_IndexModifier_ +#define _lucene_index_IndexModifier_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" +#include "CLucene/document/Document.h" +#include "CLucene/analysis/AnalysisHeader.h" + +CL_NS_DEF(index) + +class IndexReader; +class IndexWriter; +class Term; +class TermDocs; +class TermEnum; + +/** +* A class to modify an index, i.e. to delete and add documents. This +* class hides {@link IndexReader} and {@link IndexWriter} so that you +* do not need to care about implementation details such as that adding +* documents is done via IndexWriter and deletion is done via IndexReader. +* +*

Note that you cannot create more than one IndexModifier object +* on the same directory at the same time. +* +*

Example usage: +* +*

+* +* +* +* +*
+* +* //note this code will leak memory :) +* Analyzer* analyzer = new StandardAnalyzer();
+* // create an index in /tmp/index, overwriting an existing one:
+* IndexModifier* indexModifier = new IndexModifier("/tmp/index", analyzer, true);
+* Document* doc = new Document*();
+* doc->add(*new Field("id", "1", Field::STORE_YES| Field::INDEX_UNTOKENIZED));
+* doc->add(*new Field("body", "a simple test", Field::STORE_YES, Field::INDEX_TOKENIZED));
+* indexModifier->addDocument(doc);
+* int32_t deleted = indexModifier->deleteDocuments(new Term("id", "1"));
+* printf("Deleted %d document", deleted);
+* indexModifier->flush();
+* printf( "$d docs in index", indexModifier->docCount() );
+* indexModifier->close(); +*
+*
+* +*

Not all methods of IndexReader and IndexWriter are offered by this +* class. If you need access to additional methods, either use those classes +* directly or implement your own class that extends IndexModifier. +* +*

Although an instance of this class can be used from more than one +* thread, you will not get the best performance. You might want to use +* IndexReader and IndexWriter directly for that (but you will need to +* care about synchronization yourself then). +* +*

While you can freely mix calls to add() and delete() using this class, +* you should batch you calls for best performance. For example, if you +* want to update 20 documents, you should first delete all those documents, +* then add all the new documents. +* +*/ +class IndexModifier : LUCENE_BASE +{ +protected: + IndexWriter* indexWriter; + IndexReader* indexReader; + + CL_NS(store)::Directory* directory; + CL_NS(analysis)::Analyzer* analyzer; + bool open; + + // Lucene defaults: + bool useCompoundFile; + int32_t maxBufferedDocs; + int32_t maxFieldLength; + int32_t mergeFactor; + +public: + + /** + * Open an index with write access. + * + * @param directory the index directory + * @param analyzer the analyzer to use for adding new documents + * @param create true to create the index or overwrite + * the existing one; false to append to the existing index + */ + IndexModifier(CL_NS(store)::Directory* directory, + CL_NS(analysis)::Analyzer* analyzer, bool create); + + ~IndexModifier(); + + /** + * Open an index with write access. + * + * @param dirName the index directory + * @param analyzer the analyzer to use for adding new documents + * @param create true to create the index or overwrite + * the existing one; false to append to the existing index + */ + IndexModifier(const QString& dirName, CL_NS(analysis)::Analyzer* analyzer, + bool create); + +protected: + + // Initialize an IndexWriter. @throws IOException + void init(CL_NS(store)::Directory* directory, + CL_NS(analysis)::Analyzer* analyzer, bool create); + + // Throw an IllegalStateException if the index is closed. + // @throws IllegalStateException + void assureOpen() const; + + // Close the IndexReader and open an IndexWriter. @throws IOException + void createIndexWriter(); + + // Close the IndexWriter and open an IndexReader. @throws IOException + void createIndexReader(); + +public: + // Make sure all changes are written to disk. @throws IOException + void flush(); + + // Adds a document to this index, using the provided analyzer instead of + // the one specific in the constructor. If the document contains more than + // {@link #setMaxFieldLength(int32_t)} terms for a given field, the + // remainder are discarded. + // @see IndexWriter#addDocument(Document*, Analyzer*) + // @throws IllegalStateException if the index is closed + void addDocument(CL_NS(document)::Document* doc, CL_NS(analysis)::Analyzer* + docAnalyzer = NULL); + + + /** + * Deletes all documents containing term. + * This is useful if one uses a document field to hold a unique ID string for + * the document. Then to delete such a document, one merely constructs a + * term with the appropriate field and the unique ID string as its text and + * passes it to this method. Returns the number of documents deleted. + * @return the number of documents deleted + * @see IndexReader#deleteDocuments(Term*) + * @throws IllegalStateException if the index is closed + */ + int32_t deleteDocuments(Term* term); + + /** + * Deletes the document numbered docNum. + * @see IndexReader#deleteDocument(int32_t) + * @throws IllegalStateException if the index is closed + */ + void deleteDocument(int32_t docNum); + + /** + * Returns the number of documents currently in this index. + * @see IndexWriter#docCount() + * @see IndexReader#numDocs() + * @throws IllegalStateException if the index is closed + */ + int32_t docCount(); + + /** + * Merges all segments together into a single segment, optimizing an index + * for search. + * @see IndexWriter#optimize() + * @throws IllegalStateException if the index is closed + */ + void optimize(); + + /** + * Setting to turn on usage of a compound file. When on, multiple files + * for each segment are merged into a single file once the segment creation + * is finished. This is done regardless of what directory is in use. + * @see IndexWriter#setUseCompoundFile(bool) + * @throws IllegalStateException if the index is closed + */ + void setUseCompoundFile(bool useCompoundFile); + + /** + * @throws IOException + * @see IndexModifier#setUseCompoundFile(bool) + */ + bool getUseCompoundFile(); + + /** + * The maximum number of terms that will be indexed for a single field in a + * document. This limits the amount of memory required for indexing, so that + * collections with very large files will not crash the indexing process by + * running out of memory.

+ * Note that this effectively truncates large documents, excluding from the + * index terms that occur further in the document. If you know your source + * documents are large, be sure to set this value high enough to accomodate + * the expected size. If you set it to Integer.MAX_VALUE, then the only limit + * is your memory, but you should anticipate an OutOfMemoryError.

+ * By default, no more than 10,000 terms will be indexed for a field. + * @see IndexWriter#setMaxFieldLength(int32_t) + * @throws IllegalStateException if the index is closed + */ + void setMaxFieldLength(int32_t maxFieldLength); + + /** + * @throws IOException + * @see IndexModifier#setMaxFieldLength(int32_t) + */ + int32_t getMaxFieldLength(); + + /* + * The maximum number of terms that will be indexed for a single field in a + * document. This limits the amount of memory required for indexing, so that + * collections with very large files will not crash the indexing process by + * running out of memory.

+ * Note that this effectively truncates large documents, excluding from the + * index terms that occur further in the document. If you know your source + * documents are large, be sure to set this value high enough to accomodate + * the expected size. If you set it to Integer.MAX_VALUE, then the only limit + * is your memory, but you should anticipate an OutOfMemoryError.

+ * By default, no more than 10,000 terms will be indexed for a field. + * @see IndexWriter#setMaxBufferedDocs(int32_t) + * @throws IllegalStateException if the index is closed + */ + void setMaxBufferedDocs(int32_t maxBufferedDocs); + + // @see IndexModifier#setMaxBufferedDocs(int32_t) @throws IOException + int32_t getMaxBufferedDocs(); + + /* + * Determines how often segment indices are merged by addDocument(). With + * smaller values, less RAM is used while indexing, and searches on + * unoptimized indices are faster, but indexing speed is slower. With larger + * values, more RAM is used during indexing, and while searches on unoptimized + * indices are slower, indexing is faster. Thus larger values (> 10) are + * best for batch index creation, and smaller values (< 10) for indices + * that are interactively maintained. + *

This must never be less than 2. The default value is 10. + * + * @see IndexWriter#setMergeFactor(int32_t) + * @throws IllegalStateException if the index is closed + */ + void setMergeFactor(int32_t mergeFactor); + + /** + * @throws IOException + * @see IndexModifier#setMergeFactor(int32_t) + */ + int32_t getMergeFactor(); + + /** + * Close this index, writing all pending changes to disk. + * + * @throws IllegalStateException if the index has been closed before already + */ + void close(); + + QString toString() const; + + /** + * Gets the version number of the currently open index. + */ + int64_t getCurrentVersion() const; + + /** + * Returns an enumeration of all the documents which contain term. + * + * Warning: This is not threadsafe. Make sure you lock the modifier object + * while using the TermDocs. If the IndexReader that the modifier manages + * is closed, the TermDocs object will fail. + */ + TermDocs* termDocs(Term* term = NULL); + + /** + * Returns an enumeration of all terms after a given term. + * If no term is given, an enumeration of all the terms + * in the index is returned. + * The enumeration is ordered by Term.compareTo(). Each term + * is greater than all that precede it in the enumeration. + * + * Warning: This is not threadsafe. Make sure you lock the modifier object + * while using the TermDocs. If the IndexReader that the modifier manages + * is closed, the Document will be invalid + */ + TermEnum* terms(Term* term = NULL); + + /** + * Returns the stored fields of the n-th Document in this index. + * + * Warning: This is not threadsafe. Make sure you lock the modifier object + * while using the TermDocs. If the IndexReader that the modifier manages + * is closed, the Document will be invalid + */ + bool document(const int32_t n, CL_NS(document)::Document* doc); + _CL_DEPRECATED(document(i, document)) + CL_NS(document)::Document* document(const int32_t n); + + // Returns the directory used by this index. + CL_NS(store)::Directory* getDirectory(); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/IndexReader.cpp b/3rdparty/clucene/src/CLucene/index/IndexReader.cpp new file mode 100644 index 0000000..91c7356 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/IndexReader.cpp @@ -0,0 +1,668 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +# include +# include + +#include "CLucene/StdHeader.h" +#include "IndexReader.h" +#include "IndexWriter.h" + +#include "CLucene/store/Directory.h" +#include "CLucene/store/FSDirectory.h" +#include "CLucene/store/Lock.h" +#include "CLucene/document/Document.h" +#include "CLucene/search/Similarity.h" +#include "SegmentInfos.h" +#include "MultiReader.h" +#include "Terms.h" + +CL_NS_USE(util) +CL_NS_USE(store) +CL_NS_DEF(index) + +IndexReader::IndexReader(Directory* dir) + : stale(false) + , hasChanges(false) + , closeDirectory(false) + , directoryOwner(false) + , segmentInfos(NULL) + , directory(_CL_POINTER(dir)) + , writeLock(NULL) +{ +} + +IndexReader::IndexReader(Directory* dir, SegmentInfos* infos, bool close) + : stale(false) + , hasChanges(false) + , closeDirectory(close) + , directoryOwner(true) + , segmentInfos(infos) + , directory(_CL_POINTER(dir)) + , writeLock(NULL) +{ +} + +IndexReader::~IndexReader() +{ + if (writeLock != NULL) { + writeLock->release(); + _CLDELETE(writeLock); + } + _CLDELETE(segmentInfos); + _CLDECDELETE(directory); +} + +IndexReader* IndexReader::open(const QString& path) +{ + //Func - Static method. + // Returns an IndexReader reading the index in an FSDirectory in the named path. + //Pre - path != NULL and contains the path of the index for which an IndexReader must be + // instantiated + // closeDir indicates if the directory needs to be closed + //Post - An IndexReader has been returned that reads tnhe index located at path + + CND_PRECONDITION(!path.isEmpty(), "path is NULL"); + + Directory* dir = FSDirectory::getDirectory(path, false); + IndexReader* reader = open(dir, true); + //because fsdirectory will now have a refcount of 1 more than + //if the reader had been opened with a directory object, + //we need to do a refdec + _CLDECDELETE(dir); + return reader; +} + +IndexReader* IndexReader::open(Directory* directory, bool closeDirectory) +{ + //Func - Static method. + // Returns an IndexReader reading the index in an FSDirectory in the named path. + //Pre - directory represents a directory + // closeDir indicates if the directory needs to be closed + //Post - An IndexReader has been returned that reads the index located at directory + + // in- & inter-process sync + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + + //Instantiate an IndexReader::LockWith which can produce an IndexReader + LuceneLock* lock = directory->makeLock(QLatin1String("commit.lock")); + IndexReader::LockWith with(lock, directory); + + IndexReader* ret = NULL; + try { + //Create an IndexReader reading the index + ret = with.runAndReturn(); + } _CLFINALLY ( + _CLDELETE(lock); + ); + + CND_CONDITION(ret != NULL, "ret is NULL"); + ret->closeDirectory = closeDirectory; + + return ret; +} + +CL_NS(document)::Document* IndexReader::document(const int32_t n) +{ + CL_NS(document)::Document* ret = _CLNEW CL_NS(document)::Document; + if (!document(n, ret)) + _CLDELETE(ret); + return ret; +} + +IndexReader* IndexReader::LockWith::doBody() +{ + //Func - Reads the segmentinfo file and depending on the number of segments found + // it returns a SegmentsReader or a SegmentReader + //Pre - directory != NULL + //Post - Depending on the number of Segments present in directory this method + // returns an empty SegmentsReader when there are no segments, a SegmentReader when + // directory contains 1 segment and a nonempty SegmentsReader when directory + // contains multiple segements + + CND_PRECONDITION(directory != NULL, "directory is NULL"); + + //Instantiate SegmentInfos + SegmentInfos* infos = _CLNEW SegmentInfos; + try { + //Have SegmentInfos read the segments file in directory + infos->read(directory); + } catch(...) { + //make sure infos is cleaned up + _CLDELETE(infos); + throw; + } + + // If there is at least one segment (if infos.size() >= 1), the last + // SegmentReader object will close the directory when the SegmentReader + // object itself is closed (see SegmentReader::doClose). + // If there are no segments, there will be no "last SegmentReader object" + // to fulfill this responsibility, so we need to explicitly close the + // directory in the segmentsreader.close + + //Count the number segments in the directory + const uint32_t nSegs = infos->size(); + + if (nSegs == 1 ) { + // index is optimized + return _CLNEW SegmentReader(infos, infos->info(0)); + } else { + //Instantiate an array of pointers to SegmentReaders of size nSegs (The number of segments in the index) + IndexReader** readers = NULL; + + if (nSegs > 0){ + uint32_t infosize = infos->size(); + readers = _CL_NEWARRAY(IndexReader*,infosize+1); + for (uint32_t i = 0; i < infosize; ++i) { + //Instantiate a SegementReader responsible for reading the i-th segment and store it in + //the readers array + readers[i] = _CLNEW SegmentReader(infos->info(i)); + } + readers[infosize] = NULL; + } + + //return an instance of SegmentsReader which is a reader that manages all Segments + return _CLNEW MultiReader(directory, infos, readers); + }// end if +} + +uint64_t IndexReader::lastModified(const QString& directory) +{ + //Func - Static method + // Returns the time the index in the named directory was last modified. + //Pre - directory != NULL and contains the path name of the directory to check + //Post - The last modified time of the index has been returned + + CND_PRECONDITION(!directory.isEmpty(), "directory is NULL"); + + return FSDirectory::fileModified(directory, QLatin1String("segments")); +} + +int64_t IndexReader::getCurrentVersion(Directory* directory) +{ + // in- & inter-process sync + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + + int64_t ret = 0; + bool locked = false; + LuceneLock* commitLock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); + try { + locked = commitLock->obtain(IndexWriter::COMMIT_LOCK_TIMEOUT); + ret = SegmentInfos::readCurrentVersion(directory); + } _CLFINALLY ( + if (locked) + commitLock->release(); + _CLDELETE(commitLock); + ) + return ret; +} + +int64_t IndexReader::getCurrentVersion(const QString& directory) +{ + Directory* dir = FSDirectory::getDirectory(directory, false); + int64_t version = getCurrentVersion(dir); + dir->close(); + _CLDECDELETE(dir); + return version; +} + +int64_t IndexReader::getVersion() +{ + return segmentInfos->getVersion(); +} + +bool IndexReader::isCurrent() +{ + // in- & inter-process sync + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + + bool ret = false; + bool locked = false; + LuceneLock* commitLock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); + try { + locked = commitLock->obtain(IndexWriter::COMMIT_LOCK_TIMEOUT); + ret = SegmentInfos::readCurrentVersion(directory) + == segmentInfos->getVersion(); + } _CLFINALLY( + if (locked) + commitLock->release(); + _CLDELETE(commitLock); + ) + return ret; +} + +uint64_t IndexReader::lastModified(const Directory* directory) +{ + //Func - Static method + // Returns the time the index in this directory was last modified. + //Pre - directory contains a valid reference + //Post - The last modified time of the index has been returned + + return directory->fileModified(QLatin1String("segments")); +} + + +bool IndexReader::indexExists(const QString& directory) +{ + //Func - Static method + // Checks if an index exists in the named directory + //Pre - directory != NULL + //Post - Returns true if an index exists at the specified directory-> + // If the directory does not exist or if there is no index in it. + // false is returned. + + CND_PRECONDITION(!directory.isEmpty(), "directory is NULL"); + return QFile(directory + QLatin1String("/segments")).exists(); +} + + +void IndexReader::setNorm(int32_t doc, const TCHAR* field, uint8_t value) +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + if(directoryOwner) + aquireWriteLock(); + doSetNorm(doc, field, value); + hasChanges = true; +} + +void IndexReader::aquireWriteLock() +{ + if (stale) { + _CLTHROWA(CL_ERR_IO, + "IndexReader out of date and no longer valid for delete, " + "undelete, or setNorm operations"); + } + + if (writeLock == NULL) { + LuceneLock* writeLock = directory->makeLock(QLatin1String("write.lock")); + if (!writeLock->obtain(IndexWriter::WRITE_LOCK_TIMEOUT)) // obtain write lock + _CLTHROWA(CL_ERR_IO,"Index locked for write"); // + writeLock + this->writeLock = writeLock; + + // we have to check whether index has changed since this reader was opened. + // if so, this reader is no longer valid for deletion + if (SegmentInfos::readCurrentVersion(directory) > segmentInfos->getVersion()) { + stale = true; + this->writeLock->release(); + _CLDELETE(this->writeLock); + _CLTHROWA(CL_ERR_IO,"IndexReader out of date and no longer valid " + "for delete, undelete, or setNorm operations"); + } + } +} + + +void IndexReader::setNorm(int32_t doc, const TCHAR* field, qreal value) +{ + setNorm(doc, field, CL_NS(search)::Similarity::encodeNorm(value)); +} + +bool IndexReader::indexExists(const Directory* directory) +{ + //Func - Static method + // Checks if an index exists in the directory + //Pre - directory is a valid reference + //Post - Returns true if an index exists at the specified directory-> + // If the directory does not exist or if there is no index in it. + // false is returned. + + return directory->fileExists(QLatin1String("segments")); +} + +TermDocs* IndexReader::termDocs(Term* term) const +{ + //Func - Returns an enumeration of all the documents which contain + // term. For each document, the document number, the frequency of + // the term in that document is also provided, for use in search scoring. + // Thus, this method implements the mapping: + // + // Term => * + // The enumeration is ordered by document number. Each document number + // is greater than all that precede it in the enumeration. + //Pre - term != NULL + //Post - A reference to TermDocs containing an enumeration of all found documents + // has been returned + + CND_PRECONDITION(term != NULL, "term is NULL"); + + //Reference an instantiated TermDocs instance + TermDocs* _termDocs = termDocs(); + //Seek all documents containing term + _termDocs->seek(term); + //return the enumaration + return _termDocs; +} + +TermPositions* IndexReader::termPositions(Term* term) const +{ + //Func - Returns an enumeration of all the documents which contain term. For each + // document, in addition to the document number and frequency of the term in + // that document, a list of all of the ordinal positions of the term in the document + // is available. Thus, this method implements the mapping: + // + // Term => >* + // + // This positional information faciliates phrase and proximity searching. + // The enumeration is ordered by document number. Each document number is greater than + // all that precede it in the enumeration. + //Pre - term != NULL + //Post - A reference to TermPositions containing an enumeration of all found documents + // has been returned + + CND_PRECONDITION(term != NULL, "term is NULL"); + + //Reference an instantiated termPositions instance + TermPositions* _termPositions = termPositions(); + //Seek all documents containing term + _termPositions->seek(term); + //return the enumeration + return _termPositions; +} + +void IndexReader::deleteDocument(const int32_t docNum) +{ + //Func - Deletes the document numbered docNum. Once a document is deleted it will not appear + // in TermDocs or TermPostitions enumerations. Attempts to read its field with the document + // method will result in an error. The presence of this document may still be reflected in + // the docFreq statistic, though this will be corrected eventually as the index is further modified. + //Pre - docNum >= 0 + //Post - If successful the document identified by docNum has been deleted. If no writelock + // could be obtained an exception has been thrown stating that the index was locked or has no write access + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + CND_PRECONDITION(docNum >= 0, "docNum is negative"); + + if (directoryOwner) + aquireWriteLock(); + + //Have the document identified by docNum deleted + doDelete(docNum); + hasChanges = true; +} + +/** +* Commit changes resulting from delete, undeleteAll, or setNorm operations +* +* @throws IOException +*/ +void IndexReader::commit() +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + if(hasChanges){ + if(directoryOwner){ + { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) // in- & inter-process sync + + LuceneLock* commitLock = directory->makeLock(QLatin1String("commit.lock")); + IndexReader::CommitLockWith cl(commitLock,this); + cl.run(); + _CLDELETE(commitLock); + + } + if (writeLock != NULL) { + writeLock->release(); // release write lock + _CLDELETE(writeLock); + } + }else + doCommit(); + } + hasChanges = false; +} + + +void IndexReader::undeleteAll() +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + if(directoryOwner) + aquireWriteLock(); + doUndeleteAll(); + hasChanges = true; +} + +int32_t IndexReader::deleteDocuments(Term* term) +{ + //Func - Deletes all documents containing term. This is useful if one uses a + // document field to hold a unique ID string for the document. Then to delete such + // a document, one merely constructs a term with the appropriate field and the unique + // ID string as its text and passes it to this method. + //Pre - term != NULL + //Post - All documents containing term have been deleted. The number of deleted documents + // has been returned + + CND_PRECONDITION(term != NULL, "term is NULL"); + + //Search for the documents contain term + TermDocs* docs = termDocs(term); + + //Check if documents have been found + if ( docs == NULL ){ + return 0; + } + + //initialize + int32_t Counter = 0; + try { + //iterate through the found documents + while (docs->next()) { + //Delete the document + deleteDocument(docs->doc()); + ++Counter; + } + }_CLFINALLY( + //Close the enumeration + docs->close(); + ); + + //Delete the enumeration of found documents + _CLDELETE( docs ); + + //Return the number of deleted documents + return Counter; +} + +TCHAR** IndexReader::getFieldNames() +{ + CL_NS(util)::StringArrayWithDeletor array; + getFieldNames(IndexReader::ALL, array); + + array.setDoDelete(false); + TCHAR** ret = _CL_NEWARRAY(TCHAR*,array.size()+1); + int j=0; + CL_NS(util)::StringArrayWithDeletor::iterator itr = array.begin(); + while ( itr != array.end() ){ + ret[j]=*itr; + ++j;++itr; + } + ret[j]=NULL; + return ret; +} + +TCHAR** IndexReader::getFieldNames(bool indexed) +{ + CL_NS(util)::StringArrayWithDeletor array; + getFieldNames(indexed?IndexReader::INDEXED:IndexReader::UNINDEXED, array); + + array.setDoDelete(false); + TCHAR** ret = _CL_NEWARRAY(TCHAR*,array.size()+1); + int j=0; + CL_NS(util)::StringArrayWithDeletor::iterator itr = array.begin(); + while ( itr != array.end() ){ + ret[j]=*itr; + ++j;++itr; + } + ret[j]=NULL; + return ret; +} + +void IndexReader::close() +{ + //Func - Closes files associated with this index and also saves any new deletions to disk. + // No other methods should be called after this has been called. + //Pre - true + //Post - All files associated with this index have been deleted and new deletions have been + // saved to disk + SCOPED_LOCK_MUTEX(THIS_LOCK) + + CloseCallbackMap::iterator iter; + for (iter = closeCallbacks.begin(); iter != closeCallbacks.end(); iter++) { + CloseCallback callback = *iter->first; + callback(this, iter->second); + } + + commit(); + doClose(); + + if(closeDirectory) { + directory->close(); + _CLDECDELETE(directory); + } +} + +bool IndexReader::isLocked(Directory* directory) +{ + //Func - Static method + // Checks if the index in the directory is currently locked. + //Pre - directory is a valid reference to a directory to check for a lock + //Post - Returns true if the index in the named directory is locked otherwise false + + //Check the existence of the file write.lock and return true when it does and false + //when it doesn't + LuceneLock* l1 = directory->makeLock(QLatin1String("write.lock")); + LuceneLock* l2 = directory->makeLock(QLatin1String("commit.lock")); + + bool ret = l1->isLocked() || l2->isLocked(); + + _CLDELETE(l1); + _CLDELETE(l2); + return ret; +} + +bool IndexReader::isLocked(const QString& directory) +{ + //Func - Static method + // Checks if the index in the named directory is currently locked. + //Pre - directory != NULL and contains the directory to check for a lock + //Post - Returns true if the index in the named directory is locked otherwise false + + CND_PRECONDITION(!directory.isEmpty(), "directory is NULL"); + + Directory* dir = FSDirectory::getDirectory(directory, false); + bool ret = isLocked(dir); + dir->close(); + _CLDECDELETE(dir); + + return ret; +} + +/** Returns true if there are norms stored for this field. */ +bool IndexReader::hasNorms(const TCHAR* field) +{ + // backward compatible implementation. + // SegmentReader has an efficient implementation. + return norms(field) != NULL; +} + +void IndexReader::unlock(const QString& path) +{ + FSDirectory* dir = FSDirectory::getDirectory(path, false); + unlock(dir); + dir->close(); + _CLDECDELETE(dir); +} + +void IndexReader::unlock(Directory* directory) +{ + //Func - Static method + // Forcibly unlocks the index in the named directory-> + // Caution: this should only be used by failure recovery code, + // when it is known that no other process nor thread is in fact + // currently accessing this index. + //Pre - directory is a valid reference to a directory + //Post - The directory has been forcibly unlocked + LuceneLock* lock; + + lock = directory->makeLock(QLatin1String("write.lock")); + lock->release(); + _CLDELETE(lock); + + lock = directory->makeLock(QLatin1String("commit.lock")); + lock->release(); + _CLDELETE(lock); +} + +bool IndexReader::isLuceneFile(const QString& filename) +{ + if (filename.isNull() || filename.isEmpty()) + return false; + + size_t len = filename.length(); + if (len < 6) //need at least x.frx + return false; + + if (filename == QLatin1String("segments")) + return true; + + if (filename == QLatin1String("segments.new")) + return true; + + if (filename == QLatin1String("deletable")) + return true; + + QStringList extList; + extList << QLatin1String(".cfs") + << QLatin1String(".fnm") << QLatin1String(".fdx") << QLatin1String(".fdt") + << QLatin1String(".tii") << QLatin1String(".tis") << QLatin1String(".frq") + << QLatin1String(".prx") << QLatin1String(".del") << QLatin1String(".tvx") + << QLatin1String(".tvd") << QLatin1String(".tvf") << QLatin1String(".tvp"); + + QString suffix = filename.right(4); + if (extList.contains(suffix, Qt::CaseInsensitive)) + return true; + + if (suffix.leftRef(2) == QLatin1String(".f")) { + suffix = suffix.remove(0, 2); + if (suffix.length() > 0) { + for (int i = 0; i < suffix.length(); ++i) { + if (!suffix.at(i).isDigit()) + return false; + } + return true; + } + } + return false; +} + +void IndexReader::addCloseCallback(CloseCallback callback, void* parameter) +{ + closeCallbacks.put(callback, parameter); +} + +// #pragma mark -- IndexReader::LockWith + +IndexReader::LockWith::LockWith(CL_NS(store)::LuceneLock* lock, CL_NS(store)::Directory* dir) + : CL_NS(store)::LuceneLockWith(lock, IndexWriter::COMMIT_LOCK_TIMEOUT) +{ + this->directory = dir; +} + +// #pragma mark -- IndexReader::CommitLockWith + +IndexReader::CommitLockWith::CommitLockWith(CL_NS(store)::LuceneLock* lock, IndexReader* r) + : CL_NS(store)::LuceneLockWith(lock,IndexWriter::COMMIT_LOCK_TIMEOUT) + , reader(r) +{ +} + +void IndexReader::CommitLockWith::doBody() +{ + reader->doCommit(); + reader->segmentInfos->write(reader->getDirectory()); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/IndexReader.h b/3rdparty/clucene/src/CLucene/index/IndexReader.h new file mode 100644 index 0000000..352d16e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/IndexReader.h @@ -0,0 +1,485 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_IndexReader_ +#define _lucene_index_IndexReader_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" +#include "CLucene/store/FSDirectory.h" +#include "CLucene/store/Lock.h" +#include "CLucene/document/Document.h" +#include "CLucene/index/TermVector.h" +#include "SegmentInfos.h" +#include "Terms.h" + + +CL_NS_DEF(index) + + +/** IndexReader is an abstract class, providing an interface for accessing an + index. Search of an index is done entirely through this abstract interface, + so that any subclass which implements it is searchable. + +

Concrete subclasses of IndexReader are usually constructed with a call to + one of the static open() methods, e.g. {@link #open(String)}. + +

For efficiency, in this API documents are often referred to via + document numbers, non-negative integers which each name a unique + document in the index. These document numbers are ephemeral--they may change + as documents are added to and deleted from an index. Clients should thus not + rely on a given document having the same number between sessions. + +

An IndexReader can be opened on a directory for which an IndexWriter is + opened already, but it cannot be used to delete documents from the index then. +*/ +class IndexReader : LUCENE_BASE +{ +public: + //Callback for classes that need to know if IndexReader is closing. + typedef void (*CloseCallback)(IndexReader*, void*); + + class CloseCallbackCompare:public CL_NS(util)::Compare::_base{ + public: + bool operator()( CloseCallback t1, CloseCallback t2 ) const{ + return t1 > t2; + } + static void doDelete(CloseCallback dummy){ + } + }; + + + enum FieldOption { + // all fields + ALL = 1, + // all indexed fields + INDEXED = 2, + // all fields which are not indexed + UNINDEXED = 4, + // all fields which are indexed with termvectors enables + INDEXED_WITH_TERMVECTOR = 8, + // all fields which are indexed but don't have termvectors enabled + INDEXED_NO_TERMVECTOR = 16, + // all fields where termvectors are enabled. Please note that only standard termvector fields are returned + TERMVECTOR = 32, + // all field with termvectors wiht positions enabled + TERMVECTOR_WITH_POSITION = 64, + // all fields where termvectors with offset position are set + TERMVECTOR_WITH_OFFSET = 128, + // all fields where termvectors with offset and position values set + TERMVECTOR_WITH_POSITION_OFFSET = 256 + }; + + +private: + bool stale; + bool hasChanges; + bool closeDirectory; + bool directoryOwner; + + SegmentInfos* segmentInfos; + CL_NS(store)::Directory* directory; + CL_NS(store)::LuceneLock* writeLock; + + typedef CL_NS(util)::CLSet CloseCallbackMap; + CloseCallbackMap closeCallbacks; + + /** Internal use. Implements commit */ + virtual void doCommit() = 0; + + /** + * Tries to acquire the WriteLock on this directory. + * this method is only valid if this IndexReader is directory owner. + * + * @throws IOException If WriteLock cannot be acquired. + */ + void aquireWriteLock(); +protected: + /** + * Constructor used if IndexReader is not owner of its directory. + * This is used for IndexReaders that are used within other IndexReaders that take care or locking directories. + * + * @param directory Directory where IndexReader files reside. + */ + IndexReader(CL_NS(store)::Directory* dir); + + /** + * Constructor used if IndexReader is owner of its directory. + * If IndexReader is owner of its directory, it locks its directory in case of write operations. + * + * @param directory Directory where IndexReader files reside. + * @param segmentInfos Used for write-l + * @param closeDirectory + */ + IndexReader(CL_NS(store)::Directory* directory, SegmentInfos* segmentInfos, bool closeDirectory); + + + /// Implements close. + virtual void doClose() = 0; + + /** Implements setNorm in subclass.*/ + virtual void doSetNorm(int32_t doc, const TCHAR* field, uint8_t value) = 0; + + /** Implements actual undeleteAll() in subclass. */ + virtual void doUndeleteAll() = 0; + + + /** Implements deletion of the document numbered docNum. + * Applications should call {@link #deleteDocument(int32_t)} or {@link #deleteDocuments(Term*)}. + */ + virtual void doDelete(const int32_t docNum) = 0; + +public: + + DEFINE_MUTEX(THIS_LOCK) + + ///Do not access this directly, only public so that MultiReader can access it + virtual void commit(); + + + /** Undeletes all documents currently marked as deleted in this index.*/ + void undeleteAll(); + + /** + * Get a list of unique field names that exist in this index and have the specified + * field option information. + * @param fldOption specifies which field option should be available for the returned fields + * @return Collection of Strings indicating the names of the fields. + * @see IndexReader.FieldOption + */ + virtual void getFieldNames(FieldOption fldOption, CL_NS(util)::StringArrayWithDeletor& retarray) = 0; + + _CL_DEPRECATED( getFieldNames(FieldOption, StringArrayWithDeletor&) ) virtual TCHAR** getFieldNames(); + _CL_DEPRECATED( getFieldNames(FieldOption, StringArrayWithDeletor&) ) virtual TCHAR** getFieldNames(bool indexed); + + /** Returns the byte-encoded normalization factor for the named field of + * every document. This is used by the search code to score documents. + * + * The number of bytes returned is the size of the IndexReader->maxDoc() + * MEMORY: The values are cached, so don't delete the returned byte array. + * @see Field#setBoost(qreal) + */ + virtual uint8_t* norms(const TCHAR* field) = 0; + + + /** Reads the byte-encoded normalization factor for the named field of every + * document. This is used by the search code to score documents. + * + * @see Field#setBoost(qreal) + */ + virtual void norms(const TCHAR* field, uint8_t* bytes) = 0; + + /** Expert: Resets the normalization factor for the named field of the named + * document. + * + * @see #norms(TCHAR*) + * @see Similarity#decodeNorm(uint8_t) + */ + void setNorm(int32_t doc, const TCHAR* field, qreal value); + + /** Expert: Resets the normalization factor for the named field of the named + * document. The norm represents the product of the field's {@link + * Field#setBoost(qreal) boost} and its {@link Similarity#lengthNorm(TCHAR*, + * int32_t) length normalization}. Thus, to preserve the length normalization + * values when resetting this, one should base the new value upon the old. + * + * @see #norms(TCHAR*) + * @see Similarity#decodeNorm(uint8_t) + */ + void setNorm(int32_t doc, const TCHAR* field, uint8_t value); + + /// Release the write lock, if needed. + virtual ~IndexReader(); + + /// Returns an IndexReader reading the index in an FSDirectory in the named path. + static IndexReader* open(const QString& path); + + /// Returns an IndexReader reading the index in the given Directory. + static IndexReader* open( CL_NS(store)::Directory* directory, bool closeDirectory=false); + + /** + * Returns the time the index in the named directory was last modified. + * Do not use this to check whether the reader is still up-to-date, use + * {@link #isCurrent()} instead. + */ + static uint64_t lastModified(const QString& directory); + + /** + * Returns the time the index in the named directory was last modified. + * Do not use this to check whether the reader is still up-to-date, use + * {@link #isCurrent()} instead. + */ + static uint64_t lastModified(const CL_NS(store)::Directory* directory); + + + /** + * Reads version number from segments files. The version number is + * initialized with a timestamp and then increased by one for each change of + * the index. + * + * @param directory where the index resides. + * @return version number. + * @throws IOException if segments file cannot be read + */ + static int64_t getCurrentVersion(CL_NS(store)::Directory* directory); + + /** + * Reads version number from segments files. The version number is + * initialized with a timestamp and then increased by one for each change of + * the index. + * + * @param directory where the index resides. + * @return version number. + * @throws IOException if segments file cannot be read + */ + static int64_t getCurrentVersion(const QString& directory); + + /** + * Version number when this IndexReader was opened. + */ + int64_t getVersion(); + + /** + * Check whether this IndexReader still works on a current version of the index. + * If this is not the case you will need to re-open the IndexReader to + * make sure you see the latest changes made to the index. + * + * @throws IOException + */ + bool isCurrent(); + + + /** + * Return an array of term frequency vectors for the specified document. + * The array contains a vector for each vectorized field in the document. + * Each vector contains terms and frequencies for all terms in a given vectorized field. + * If no such fields existed, the method returns null. The term vectors that are + * returned my either be of type TermFreqVector or of type TermPositionsVector if + * positions or offsets have been stored. + * + * @param docNumber document for which term frequency vectors are returned + * @return array of term frequency vectors. May be null if no term vectors have been + * stored for the specified document. + * @throws IOException if index cannot be accessed + * @see org.apache.lucene.document.Field.TermVector + */ + virtual bool getTermFreqVectors(int32_t docNumber, Array& result) =0; + + /** + * Return a term frequency vector for the specified document and field. The + * returned vector contains terms and frequencies for the terms in + * the specified field of this document, if the field had the storeTermVector + * flag set. If termvectors had been stored with positions or offsets, a + * TermPositionsVector is returned. + * + * @param docNumber document for which the term frequency vector is returned + * @param field field for which the term frequency vector is returned. + * @return term frequency vector May be null if field does not exist in the specified + * document or term vector was not stored. + * @throws IOException if index cannot be accessed + * @see org.apache.lucene.document.Field.TermVector + */ + virtual TermFreqVector* getTermFreqVector(int32_t docNumber, const TCHAR* field) = 0; + + /** + * Returns true if an index exists at the specified directory. + * If the directory does not exist or if there is no index in it. + * @param directory the directory to check for an index + * @return true if an index exists; false otherwise + */ + static bool indexExists(const QString& directory); + + /** + * Returns true if an index exists at the specified directory. + * If the directory does not exist or if there is no index in it. + * @param directory the directory to check for an index + * @return true if an index exists; false otherwise + * @throws IOException if there is a problem with accessing the index + */ + static bool indexExists(const CL_NS(store)::Directory* directory); + + /** Returns the number of documents in this index. */ + virtual int32_t numDocs() = 0; + + /** Returns one greater than the largest possible document number. + * This may be used to, e.g., determine how big to allocate an array which + * will have an element for every document number in an index. + */ + virtual int32_t maxDoc() const = 0; + + /** Gets the stored fields of the nth + * Document in this index. + * The fields are not cleared before retrieving the document, so the + * object should be new or just cleared. + */ + virtual bool document(int32_t n, CL_NS(document)::Document*) =0; + + _CL_DEPRECATED( document(i, document) ) CL_NS(document)::Document* document(const int32_t n); + + /** Returns true if document n has been deleted */ + virtual bool isDeleted(const int32_t n) = 0; + + /** Returns true if any documents have been deleted */ + virtual bool hasDeletions() const = 0; + + /** Returns true if there are norms stored for this field. */ + virtual bool hasNorms(const TCHAR* field); + + /** Returns an enumeration of all the terms in the index. + * The enumeration is ordered by Term.compareTo(). Each term + * is greater than all that precede it in the enumeration. + * @memory Caller must clean up + */ + virtual TermEnum* terms() const =0; + + /** Returns an enumeration of all terms after a given term. + * The enumeration is ordered by Term.compareTo(). Each term + * is greater than all that precede it in the enumeration. + * @memory Caller must clean up + */ + virtual TermEnum* terms(const Term* t) const = 0; + + /** Returns the number of documents containing the term t. */ + virtual int32_t docFreq(const Term* t) const = 0; + + /* Returns an unpositioned TermPositions enumerator. + * @memory Caller must clean up + */ + virtual TermPositions* termPositions() const = 0; + + /** Returns an enumeration of all the documents which contain + * term. For each document, in addition to the document number + * and frequency of the term in that document, a list of all of the ordinal + * positions of the term in the document is available. Thus, this method + * implements the mapping: + * + *

    + * Term    =>    <docNum, freq, + * <pos1, pos2, ... + * posfreq-1> + * >* + *
+ *

This positional information faciliates phrase and proximity searching. + *

The enumeration is ordered by document number. Each document number is + * greater than all that precede it in the enumeration. + * @memory Caller must clean up + */ + TermPositions* termPositions(Term* term) const; + + /** Returns an unpositioned {@link TermDocs} enumerator. + * @memory Caller must clean up + */ + virtual TermDocs* termDocs() const = 0; + + /** Returns an enumeration of all the documents which contain + * term. For each document, the document number, the frequency of + * the term in that document is also provided, for use in search scoring. + * Thus, this method implements the mapping: + *

    Term    =>    <docNum, freq>*
+ *

The enumeration is ordered by document number. Each document number + * is greater than all that precede it in the enumeration. + * @memory Caller must clean up + */ + TermDocs* termDocs(Term* term) const; + + /** Deletes the document numbered docNum. Once a document is + * deleted it will not appear in TermDocs or TermPostitions enumerations. + * Attempts to read its field with the {@link #document} + * method will result in an error. The presence of this document may still be + * reflected in the {@link #docFreq} statistic, though + * this will be corrected eventually as the index is further modified. + */ + void deleteDocument(const int32_t docNum); + + ///@deprecated. Use deleteDocument instead. + _CL_DEPRECATED( deleteDocument ) void deleteDoc(const int32_t docNum) + { deleteDocument(docNum); } + + /** Deletes all documents containing term. + * This is useful if one uses a document field to hold a unique ID string for + * the document. Then to delete such a document, one merely constructs a + * term with the appropriate field and the unique ID string as its text and + * passes it to this method. + * See {@link #deleteDocument(int)} for information about when this deletion will + * become effective. + * @return the number of documents deleted + */ + int32_t deleteDocuments(Term* term); + + ///@deprecated. Use deleteDocuments instead. + _CL_DEPRECATED( deleteDocuments ) int32_t deleteTerm(Term* term){ return deleteDocuments(term); } + + /** + * Closes files associated with this index and also saves any new deletions to disk. + * No other methods should be called after this has been called. + */ + void close(); + + ///Checks if the index in the named directory is currently locked. + static bool isLocked(CL_NS(store)::Directory* directory); + + ///Checks if the index in the named directory is currently locked. + static bool isLocked(const QString& directory); + + + ///Forcibly unlocks the index in the named directory. + ///Caution: this should only be used by failure recovery code, + ///when it is known that no other process nor thread is in fact + ///currently accessing this index. + static void unlock(CL_NS(store)::Directory* directory); + static void unlock(const QString& path); + + /** Returns the directory this index resides in. */ + CL_NS(store)::Directory* getDirectory() { return directory; } + + /** Returns true if the file is a lucene filename (based on extension or filename) */ + static bool isLuceneFile(const QString& filename); + + /** + * For classes that need to know when the IndexReader closes (such as caches, etc), + * should pass their callback function to this. + */ + void addCloseCallback(CloseCallback callback, void* parameter); + +protected: + class LockWith : public CL_NS(store)::LuceneLockWith + { + public: + LockWith(CL_NS(store)::LuceneLock* lock, CL_NS(store)::Directory* dir); + + //Reads the segmentinfo file and depending on the number of segments found + //it returns a MultiReader or a SegmentReader + IndexReader* doBody(); + + private: + CL_NS(store)::Directory* directory; + }; + friend class IndexReader::LockWith; + + class CommitLockWith : public CL_NS(store)::LuceneLockWith + { + public: + CommitLockWith(CL_NS(store)::LuceneLock* lock, IndexReader* r); + void doBody(); + + private: + IndexReader* reader; + }; + friend class IndexReader::CommitLockWith; +}; + +CL_NS_END +#endif + + diff --git a/3rdparty/clucene/src/CLucene/index/IndexWriter.cpp b/3rdparty/clucene/src/CLucene/index/IndexWriter.cpp new file mode 100644 index 0000000..5504cf6 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/IndexWriter.cpp @@ -0,0 +1,697 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "IndexWriter.h" + +#include "CLucene/document/Document.h" +#include "CLucene/store/Directory.h" +#include "CLucene/store/Lock.h" +#include "CLucene/util/VoidList.h" +#include "DocumentWriter.h" +#include "SegmentInfos.h" +#include "SegmentMerger.h" + +CL_NS_USE(store) +CL_NS_USE(util) +CL_NS_USE(document) +CL_NS_USE(analysis) +CL_NS_DEF(index) + +const QLatin1String IndexWriter::WRITE_LOCK_NAME("write.lock"); +const QLatin1String IndexWriter::COMMIT_LOCK_NAME("commit.lock"); + +IndexWriter::IndexWriter(const QString& path, Analyzer* a, const bool create, + const bool _closeDir) + : directory(FSDirectory::getDirectory(path, create)) + , analyzer(a) + , segmentInfos(true) + , closeDir(_closeDir) +{ + //Func - Constructor + // Constructs an IndexWriter for the index in path. + //Pre - path != NULL and contains a named directory path + // a holds a valid reference to an analyzer and analyzes the text to + // be indexed create indicates if the indexWriter must create a new + // index located at path or just open it + //Post - If create is true, then a new, empty index has been created in + // path, replacing the index already there, if any. The named + // directory path is owned by this Instance + + CND_PRECONDITION(!path.isEmpty(), "path is NULL"); + + //Continue initializing the instance by _IndexWriter + _IndexWriter(create); +} + +IndexWriter::IndexWriter(Directory* d, Analyzer* a, const bool create, + const bool _closeDir) + : directory(_CL_POINTER(d)) + , analyzer(a) + , segmentInfos(true) + , closeDir(_closeDir) +{ + //Func - Constructor + // Constructs an IndexWriter for the index in path. + //Pre - d contains a valid reference to a directory + // a holds a valid reference to an analyzer and analyzes the text to + // be indexed create indicates if the indexWriter must create a new + // index located at path or just open it + //Post - If create is true, then a new, empty index has been created in + // path, replacing the index already there, if any. The directory d + // is not owned by this Instance + + //Continue initializing the instance by _IndexWriter + _IndexWriter ( create ); +} + +void IndexWriter::_IndexWriter(const bool create) +{ + //Func - Initialises the instances + //Pre - create indicates if the indexWriter must create a new index + // located at path or just open it + + similarity = CL_NS(search)::Similarity::getDefault(); + + useCompoundFile = true; + if ( directory->getDirectoryType() == RAMDirectory::DirectoryType() ) + useCompoundFile = false; + + //Create a ramDirectory + ramDirectory = _CLNEW TransactionalRAMDirectory; + + CND_CONDITION(ramDirectory != NULL, "ramDirectory is NULL"); + + //Initialize the writeLock to + writeLock = NULL; + + //initialise the settings... + maxFieldLength = DEFAULT_MAX_FIELD_LENGTH; + mergeFactor = DEFAULT_MERGE_FACTOR; + maxMergeDocs = DEFAULT_MAX_MERGE_DOCS; + writeLockTimeout = WRITE_LOCK_TIMEOUT; + commitLockTimeout = COMMIT_LOCK_TIMEOUT; + minMergeDocs = DEFAULT_MAX_BUFFERED_DOCS; + termIndexInterval = DEFAULT_TERM_INDEX_INTERVAL; + + //Create a new lock using the name "write.lock" + LuceneLock* newLock = directory->makeLock(IndexWriter::WRITE_LOCK_NAME); + + //Condition check to see if newLock has been allocated properly + CND_CONDITION(newLock != NULL, + "No memory could be allocated for LuceneLock newLock"); + + //Try to obtain a write lock + if (!newLock->obtain(writeLockTimeout)){ + //Write lock could not be obtained so delete it + _CLDELETE(newLock); + //Reset the instance + _finalize(); + //throw an exception because no writelock could be created or obtained + _CLTHROWA(CL_ERR_IO, "Index locked for write or no write access." ); + } + + //The Write Lock has been obtained so save it for later use + this->writeLock = newLock; + + //Create a new lock using the name "commit.lock" + LuceneLock* lock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); + + //Condition check to see if lock has been allocated properly + CND_CONDITION(lock != NULL, "No memory could be allocated for LuceneLock lock"); + + LockWith2 with(lock, commitLockTimeout, this, NULL, create); + { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) // in- & inter-process sync + with.run(); + } + + //Release the commit lock + _CLDELETE(lock); + + isOpen = true; +} + +IndexWriter::~IndexWriter() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + close(); + _finalize(); +} + +void IndexWriter::close() +{ + //Func - Flushes all changes to an index, closes all associated files, and + // closes the directory that the index is stored in. + //Pre - closeDir indicates if the directory must be closed or not + //Post - All the changes have been flushed to disk and the write lock has + // been released. The ramDirectory has also been closed. The + // directory has been closed if the reference count of the directory + // reaches zero + + SCOPED_LOCK_MUTEX(THIS_LOCK) + if (isOpen) { + //Flush the Ram Segments + flushRamSegments(); + //Close the ram directory + if (ramDirectory != NULL) { + ramDirectory->close(); + _CLDECDELETE(ramDirectory); + } + + //Check if this instance must close the directory + if (closeDir) + directory->close(); + _CLDECDELETE(directory); + + // release write lock + if (writeLock != NULL) { + writeLock->release(); + _CLDELETE(writeLock); + } + isOpen = false; + } +} + +void IndexWriter::_finalize() +{ + //Func - Releases all the resources of the instance + //Pre - true + //Post - All the releases have been released + + if(writeLock != NULL) { + //release write lock + writeLock->release(); + _CLDELETE( writeLock ); + } + + //Delete the ramDirectory + if (ramDirectory != NULL) { + ramDirectory->close(); + _CLDECDELETE(ramDirectory); + } +} + +int32_t IndexWriter::docCount() +{ + //Func - Counts the number of documents in the index + //Pre - true + //Post - The number of documents have been returned + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + //Initialize count + int32_t count = 0; + + //Iterate through all segmentInfos + for (int32_t i = 0; i < segmentInfos.size(); i++) { + //Get the i-th SegmentInfo + SegmentInfo* si = segmentInfos.info(i); + //Retrieve the number of documents of the segment and add it to count + count += si->docCount; + } + return count; +} + +void IndexWriter::addDocument(Document* doc, Analyzer* analyzer) +{ + //Func - Adds a document to the index + //Pre - doc contains a valid reference to a document + // ramDirectory != NULL + //Post - The document has been added to the index of this IndexWriter + CND_PRECONDITION(ramDirectory != NULL, "ramDirectory is NULL"); + + if (analyzer == NULL) + analyzer = this->analyzer; + + ramDirectory->transStart(); + try { + QString segmentName = newSegmentName(); + CND_CONDITION(!segmentName.isEmpty(), "segmentName is NULL"); + try { + //Create the DocumentWriter using a ramDirectory and analyzer + // supplied by the IndexWriter (this). + DocumentWriter* dw = _CLNEW DocumentWriter(ramDirectory, analyzer, + this ); + CND_CONDITION(dw != NULL, "dw is NULL"); + try { + //Add the client-supplied document to the new segment. + dw->addDocument(segmentName, doc); + } _CLFINALLY ( + _CLDELETE(dw); + ); + + //Create a new SegmentInfo instance about this new segment. + SegmentInfo* si = _CLNEW SegmentInfo(segmentName, 1, ramDirectory); + CND_CONDITION(si != NULL, "Si is NULL"); + { + SCOPED_LOCK_MUTEX(THIS_LOCK) + + //Add the info object for this particular segment to the list + // of all segmentInfos-> + segmentInfos.add(si); + + //Check to see if the segments must be merged + maybeMergeSegments(); + } + } _CLFINALLY() + } catch (...) { + ramDirectory->transAbort(); + throw; +} + ramDirectory->transCommit(); +} + +void IndexWriter::optimize() +{ + //Func - Optimizes the index for which this Instance is responsible + //Pre - true + //Post - + SCOPED_LOCK_MUTEX(THIS_LOCK) + + //Flush the RamSegments to disk + flushRamSegments(); + while (segmentInfos.size() > 1 + || (segmentInfos.size() == 1 + && (SegmentReader::hasDeletions(segmentInfos.info(0)) + || segmentInfos.info(0)->getDir()!=directory + || (useCompoundFile + && (!SegmentReader::usesCompoundFile(segmentInfos.info(0)) + || SegmentReader::hasSeparateNorms(segmentInfos.info(0))))))) { + int32_t minSegment = segmentInfos.size() - mergeFactor; + mergeSegments(minSegment < 0 ? 0 : minSegment); + } +} + + +QString IndexWriter::newSegmentName() +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + return QLatin1Char('_') + QString::number(segmentInfos.counter++, 36); +} + +void IndexWriter::flushRamSegments() +{ + //Func - Merges all RAM-resident segments. + //Pre - ramDirectory != NULL + //Post - The RAM-resident segments have been merged to disk + + CND_PRECONDITION(ramDirectory != NULL, "ramDirectory is NULL"); + + int32_t minSegment = segmentInfos.size()-1; //don't make this unsigned... + CND_CONDITION(minSegment >= -1, "minSegment must be >= -1"); + + int32_t docCount = 0; + //Iterate through all the segements and check if the directory is a ramDirectory + while (minSegment >= 0 && + segmentInfos.info(minSegment)->getDir() == ramDirectory) { + docCount += segmentInfos.info(minSegment)->docCount; + minSegment--; + } + if (minSegment < 0 || // add one FS segment? + (docCount + segmentInfos.info(minSegment)->docCount) > mergeFactor || + !(segmentInfos.info(segmentInfos.size()-1)->getDir() == ramDirectory)) + minSegment++; + + CND_CONDITION(minSegment >= 0, "minSegment must be >= 0"); + if (minSegment >= segmentInfos.size()) + return; // none to merge + mergeSegments(minSegment); +} + +void IndexWriter::maybeMergeSegments() { + //Func - Incremental Segment Merger + //Pre - + //Post - + + int64_t targetMergeDocs = minMergeDocs; + + // find segments smaller than current target size + while (targetMergeDocs <= maxMergeDocs) { + int32_t minSegment = segmentInfos.size(); + int32_t mergeDocs = 0; + + while (--minSegment >= 0) { + SegmentInfo* si = segmentInfos.info(minSegment); + if (si->docCount >= targetMergeDocs) + break; + mergeDocs += si->docCount; + } + + if (mergeDocs >= targetMergeDocs){ + // found a merge to do + mergeSegments(minSegment+1); + }else + break; + + //increase target size + targetMergeDocs *= mergeFactor; + } +} + +void IndexWriter::mergeSegments(const uint32_t minSegment) +{ + mergeSegments(minSegment, segmentInfos.size()); +} + +void IndexWriter::mergeSegments(const uint32_t minSegment, const uint32_t end) +{ + CLVector segmentsToDelete(false); + QString mergedName = newSegmentName(); +#ifdef _CL_DEBUG_INFO + fprintf(_CL_DEBUG_INFO, "merging segments\n"); +#endif + SegmentMerger merger(this, mergedName); + for (size_t i = minSegment; i < end; i++) { + SegmentInfo* si = segmentInfos.info(i); +#ifdef _CL_DEBUG_INFO + fprintf(_CL_DEBUG_INFO, " %s (%d docs)\n", + si->name.toLocal8Bit().constData(), si->docCount); +#endif + SegmentReader* reader = _CLNEW SegmentReader(si); + merger.add(reader); + // if we own the directory + if ((reader->getDirectory() == this->directory) + || (reader->getDirectory() == this->ramDirectory)) { + // queue segment for deletion + segmentsToDelete.push_back(reader); + } + } + + int32_t mergedDocCount = merger.merge(); + +#ifdef _CL_DEBUG_INFO + fprintf(_CL_DEBUG_INFO, "\n into %s (%d docs)\n", + mergedName.toLocal8Bit().constData(), mergedDocCount); +#endif + + segmentInfos.clearto(minSegment);// remove old infos & add new + segmentInfos.add(_CLNEW SegmentInfo(mergedName, mergedDocCount, directory)); + + // close readers before we attempt to delete now-obsolete segments + merger.closeReaders(); + + LuceneLock* lock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); + LockWith2 with (lock, commitLockTimeout, this, &segmentsToDelete, true); + { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) // in- & inter-process sync + with.run(); + } + _CLDELETE( lock ); + + if (useCompoundFile) { + QStringList filesToDelete; + merger.createCompoundFile(mergedName + QLatin1String(".tmp"), filesToDelete); + + LuceneLock* lock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); + LockWithCFS with(lock, commitLockTimeout, directory, this, mergedName, + filesToDelete); + { + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) // in- & inter-process sync + with.run(); + } + _CLDELETE(lock); + } +} + +void IndexWriter::deleteSegments(CLVector* segments) +{ + QStringList deletable; + + {//scope delete deleteArray object + QStringList deleteArray; + readDeleteableFiles(deleteArray); + deleteFiles(deleteArray, deletable); // try to delete deleteable + } + + QStringList files; + for (uint32_t i = 0; i < segments->size(); i++) { + SegmentReader* reader = (*segments)[i]; + files.clear(); + reader->files(files); + if (reader->getDirectory() == this->directory) + deleteFiles(files, deletable); // try to delete our files + else + deleteFiles(files, reader->getDirectory()); // delete, eg, RAM files + } + + writeDeleteableFiles(deletable); // note files we can't delete +} + +void IndexWriter::deleteFiles(const QStringList& files) +{ + QStringList currentDeletable; + readDeleteableFiles(currentDeletable); + + // try to delete deleteable + QStringList deletable; + deleteFiles(currentDeletable, deletable); + + // try to delete our files + deleteFiles(files, deletable); + + // note files we can't delete + writeDeleteableFiles(deletable); +} + +void IndexWriter::readDeleteableFiles(QStringList& result) +{ + if (!directory->fileExists(QLatin1String("deletable"))) + return; + + IndexInput* input = directory->openInput(QLatin1String("deletable")); + try { + // read file names + TCHAR tname[CL_MAX_PATH]; + for (int32_t i = input->readInt(); i > 0; i--) { + int32_t read = input->readString(tname, CL_MAX_PATH); + result.push_back(QString::fromWCharArray(tname, read)); + } + } _CLFINALLY ( + input->close(); + _CLDELETE(input); + ); +} + +void IndexWriter::deleteFiles(const QStringList& files, QStringList& deletable) +{ + QStringList::const_iterator itr; + for (itr = files.begin(); itr != files.end(); ++itr) { + if (!getDirectory()->fileExists((*itr))) + continue; + + if (!getDirectory()->deleteFile((*itr), false)) { + if (directory->fileExists((*itr))) { +#ifdef _CL_DEBUG_INFO + fprintf(_CL_DEBUG_INFO, "%s; Will re-try later.\n", err.what()); +#endif + // add to deletable + deletable.push_back((*itr)); + } + } + } +} + +void IndexWriter::deleteFiles(const QStringList& files, Directory* directory) +{ + QStringList::const_iterator itr; + for (itr = files.begin(); itr != files.end(); ++itr) + directory->deleteFile((*itr), true); +} + +void IndexWriter::writeDeleteableFiles(const QStringList& files) +{ + IndexOutput* output = directory->createOutput(QLatin1String("deleteable.new")); + try { + output->writeInt(files.size()); + + TCHAR tfile[CL_MAX_PATH]; + QStringList::const_iterator itr; + for (itr = files.begin(); itr != files.end(); ++itr) { + tfile[(*itr).toWCharArray(tfile)] = '\0'; + output->writeString(tfile, _tcslen(tfile)); + } + } _CLFINALLY ( + output->close(); + _CLDELETE(output); + ); + + directory->renameFile(QLatin1String("deleteable.new"), + QLatin1String("deletable")); +} + +void IndexWriter::addIndexes(Directory** dirs) +{ + //Func - Add several indexes located in different directories into the current + // one managed by this instance + //Pre - dirs != NULL and contains directories of several indexes + // dirsLength > 0 and contains the number of directories + //Post - The indexes located in the directories in dirs have been merged with + // the pre(current) index. The Resulting index has also been optimized + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + CND_PRECONDITION(dirs != NULL, "dirs is NULL"); + + // start with zero or 1 seg so optimize the current + optimize(); + + int32_t start = segmentInfos.size(); + + //Iterate through the directories + for (int32_t i = 0; dirs[i] != NULL; ++i) { + // DSR: Changed SegmentInfos constructor arg (see bug discussion below). + SegmentInfos sis(false); + sis.read(dirs[i]); + for (int32_t j = 0; j < sis.size(); j++) + segmentInfos.add(sis.info(j)); // add each info + } + + // commented out by tbusch to solve a bug and to be conform with + // java lucene + + // merge newly added segments in log(n) passes + //while (segmentInfos.size() > start + mergeFactor) { + // for (int32_t base = start; base < segmentInfos.size(); base++) { + // int32_t end = min(segmentInfos.size(), base + mergeFactor); + // if (end - base > 1) + // mergeSegments(base, end); + // } + //} + + // cleanup + optimize(); +} + + +void IndexWriter::addIndexes(IndexReader** readers) +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + optimize(); // start with zero or 1 seg + + QString mergedName = newSegmentName(); + SegmentMerger merger(this, mergedName); + + CLVector segmentsToDelete; + SegmentReader* sReader = NULL; + if (segmentInfos.size() == 1) { // add existing index, if any + sReader = _CLNEW SegmentReader(segmentInfos.info(0)); + merger.add(sReader); + segmentsToDelete.push_back(sReader); // queue segment for deletion + } + + int32_t readersLength = 0; + while (readers[readersLength] != NULL) + merger.add(readers[readersLength++]); + + int32_t docCount = merger.merge(); // merge 'em + + // pop old infos & add new + segmentInfos.clearto(0); + segmentInfos.add(_CLNEW SegmentInfo(mergedName, docCount, directory)); + + if (sReader != NULL) { + sReader->close(); + _CLDELETE(sReader); + } + + LuceneLock* lock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); + LockWith2 with(lock, commitLockTimeout, this, &segmentsToDelete, true); + { + // in- & inter-process sync + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + with.run(); + } + _CLDELETE(lock); + + if (useCompoundFile) { + QStringList filesToDelete; + merger.createCompoundFile(mergedName + QLatin1String(".tmp"), + filesToDelete); + + LuceneLock* cfslock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); + LockWithCFS with(cfslock, commitLockTimeout, directory, this, mergedName, + filesToDelete); + { + // in- & inter-process sync + SCOPED_LOCK_MUTEX(directory->THIS_LOCK) + with.run(); + } + _CLDELETE(cfslock); + } +} + +// #pragma mark -- IndexWriter::LockWith2 + +IndexWriter::LockWith2::LockWith2(CL_NS(store)::LuceneLock* lock, + int64_t lockWaitTimeout, + IndexWriter* indexWriter, + CL_NS(util)::CLVector* std, + bool _create) + : CL_NS(store)::LuceneLockWith(lock, lockWaitTimeout) + , create(_create) + , writer(indexWriter) + , segmentsToDelete(std) +{ +} + +void IndexWriter::LockWith2::doBody() +{ + //Func - Writes segmentInfos to or reads segmentInfos from disk + //Pre - writer != NULL + //Post - if create is true then segementInfos has been written to disk + // otherwise segmentInfos has been read from disk + + CND_PRECONDITION(writer != NULL, "writer is NULL"); + + if (create) { + writer->segmentInfos.write(writer->getDirectory()); + // delete now-unused segments + if (segmentsToDelete != NULL) + writer->deleteSegments(segmentsToDelete); + } else { + writer->segmentInfos.read(writer->getDirectory()); + } +} + +// #pragma mark -- IndexWriter::LockWithCFS + +IndexWriter::LockWithCFS::LockWithCFS(CL_NS(store)::LuceneLock* lock, + int64_t lockWaitTimeout, + CL_NS(store)::Directory* dir, + IndexWriter* indexWriter, + const QString& segmentName, + const QStringList& ftd) + : CL_NS(store)::LuceneLockWith(lock, lockWaitTimeout) + , segName(segmentName) + , writer(indexWriter) + , directory(dir) + , filesToDelete(ftd) +{ +} + +void IndexWriter::LockWithCFS::doBody() +{ + //Func - Writes segmentInfos to or reads segmentInfos from disk + //Pre - writer != NULL + //Post - if create is true then segementInfos has been written to disk + // otherwise segmentInfos has been read from disk + + CND_PRECONDITION(directory != NULL, "directory is NULL"); + CND_PRECONDITION(!segName.isEmpty(), "mergedName is NULL"); + + // make compound file visible for SegmentReaders + directory->renameFile(segName + QLatin1String(".tmp"), + segName + QLatin1String(".cfs")); + // delete now unused files of segment + writer->deleteFiles(filesToDelete); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/IndexWriter.h b/3rdparty/clucene/src/CLucene/index/IndexWriter.h new file mode 100644 index 0000000..80476c8 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/IndexWriter.h @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_IndexWriter_ +#define _lucene_index_IndexWriter_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/util/VoidList.h" +#include "CLucene/search/Similarity.h" +#include "CLucene/store/Lock.h" +#include "CLucene/store/TransactionalRAMDirectory.h" + +#include "SegmentHeader.h" + +CL_NS_DEF(index) + +/** +An IndexWriter creates and maintains an index. + +The third argument to the +constructor +determines whether a new index is created, or whether an existing index is +opened for the addition of new documents. + +In either case, documents are added with the addDocument method. +When finished adding documents, close should be called. + +

If an index will not have more documents added for a while and optimal search +performance is desired, then the optimize +method should be called before the index is closed. + +

Opening an IndexWriter creates a lock file for the directory in use. Trying to open +another IndexWriter on the same directory will lead to an IOException. The IOException +is also thrown if an IndexReader on the same directory is used to delete documents +from the index. + +@see IndexModifier IndexModifier supports the important methods of IndexWriter plus deletion +*/ +class IndexWriter : LUCENE_BASE +{ + class LockWith2 : public CL_NS(store)::LuceneLockWith + { + public: + LockWith2(CL_NS(store)::LuceneLock* lock, + int64_t lockWaitTimeout, + IndexWriter* wr, + CL_NS(util)::CLVector* std, + bool create); + + ~LockWith2() {} + + void doBody(); + + private: + bool create; + IndexWriter* writer; + CL_NS(util)::CLVector* segmentsToDelete; + }; + friend class LockWith2; + + class LockWithCFS : public CL_NS(store)::LuceneLockWith + { + public: + LockWithCFS(CL_NS(store)::LuceneLock* lock, + int64_t lockWaitTimeout, + CL_NS(store)::Directory* dir, + IndexWriter* wr, + const QString& segName, + const QStringList& ftd); + + ~LockWithCFS() {} + + void doBody(); + + private: + QString segName; + IndexWriter* writer; + CL_NS(store)::Directory* directory; + QStringList filesToDelete; + }; + friend class IndexWriter::LockWithCFS; + + // indicates if the writers is open - this way close can be called multiple + // times + bool isOpen; + + // how to analyze text + CL_NS(analysis)::Analyzer* analyzer; + + CL_NS(search)::Similarity* similarity; // how to normalize + + /** Use compound file setting. Normally defaults to true, except when + * using a RAMDirectory. This minimizes the number of files used. + * Setting this to false may improve indexing performance, but + * may also cause file handle problems. + */ + bool useCompoundFile; + bool closeDir; + + // for temp segs + CL_NS(store)::TransactionalRAMDirectory* ramDirectory; + + CL_NS(store)::LuceneLock* writeLock; + + void _IndexWriter(const bool create); + + void _finalize(); + + // where this index resides + CL_NS(store)::Directory* directory; + + + int32_t getSegmentsCounter() { return segmentInfos.counter; } + int32_t maxFieldLength; + int32_t mergeFactor; + int32_t minMergeDocs; + int32_t maxMergeDocs; + int32_t termIndexInterval; + + int64_t writeLockTimeout; + int64_t commitLockTimeout; +public: + DEFINE_MUTEX(THIS_LOCK) + + // Release the write lock, if needed. + SegmentInfos segmentInfos; + + // Release the write lock, if needed. + ~IndexWriter(); + + /** + * The Java implementation of Lucene silently truncates any tokenized + * field if the number of tokens exceeds a certain threshold. Although + * that threshold is adjustable, it is easy for the client programmer + * to be unaware that such a threshold exists, and to become its + * unwitting victim. + * CLucene implements a less insidious truncation policy. Up to + * DEFAULT_MAX_FIELD_LENGTH tokens, CLucene behaves just as JLucene + * does. If the number of tokens exceeds that threshold without any + * indication of a truncation preference by the client programmer, + * CLucene raises an exception, prompting the client programmer to + * explicitly set a truncation policy by adjusting maxFieldLength. + */ + LUCENE_STATIC_CONSTANT(int32_t, DEFAULT_MAX_FIELD_LENGTH = 10000); + LUCENE_STATIC_CONSTANT(int32_t, FIELD_TRUNC_POLICY__WARN = -1); + int32_t getMaxFieldLength() const{ return maxFieldLength; } + void setMaxFieldLength(int32_t val){ maxFieldLength = val; } + + /** + * Default value is 10. Change using {@link #setMaxBufferedDocs(int)}. + */ + LUCENE_STATIC_CONSTANT(int32_t, DEFAULT_MAX_BUFFERED_DOCS = 10); + /** Determines the minimal number of documents required before the buffered + * in-memory documents are merging and a new Segment is created. + * Since Documents are merged in a {@link RAMDirectory}, + * large value gives faster indexing. At the same time, mergeFactor limits + * the number of files open in a FSDirectory. + * + *

The default value is DEFAULT_MAX_BUFFERED_DOCS.*/ + void setMaxBufferedDocs(int32_t val){ minMergeDocs = val; } + /** + * @see #setMaxBufferedDocs + */ + int32_t getMaxBufferedDocs(){ return minMergeDocs; } + + /** + * Default value for the write lock timeout (1,000). + */ + LUCENE_STATIC_CONSTANT(int64_t, WRITE_LOCK_TIMEOUT = 1000); + /** + * Sets the maximum time to wait for a write lock (in milliseconds). + */ + void setWriteLockTimeout(int64_t writeLockTimeout) + { this->writeLockTimeout = writeLockTimeout; } + /** + * @see #setWriteLockTimeout + */ + int64_t getWriteLockTimeout() { return writeLockTimeout; } + + /** + * Default value for the commit lock timeout (10,000). + */ + LUCENE_STATIC_CONSTANT(int64_t, COMMIT_LOCK_TIMEOUT = 10000); + /** + * Sets the maximum time to wait for a commit lock (in milliseconds). + */ + void setCommitLockTimeout(int64_t commitLockTimeout) + { this->commitLockTimeout = commitLockTimeout; } + /** + * @see #setCommitLockTimeout + */ + int64_t getCommitLockTimeout() { return commitLockTimeout; } + + static const QLatin1String WRITE_LOCK_NAME; //"write.lock"; + static const QLatin1String COMMIT_LOCK_NAME; //"commit.lock"; + + /** + * Default value is 10. Change using {@link #setMergeFactor(int)}. + */ + LUCENE_STATIC_CONSTANT(int32_t, DEFAULT_MERGE_FACTOR = 10); + /* Determines how often segment indices are merged by addDocument(). With + * smaller values, less RAM is used while indexing, and searches on + * unoptimized indices are faster, but indexing speed is slower. With larger + * values more RAM is used while indexing and searches on unoptimized indices + * are slower, but indexing is faster. Thus larger values (> 10) are best + * for batched index creation, and smaller values (< 10) for indices that are + * interactively maintained. + * + *

This must never be less than 2. The default value is 10. + */ + int32_t getMergeFactor() const{ return mergeFactor; } + void setMergeFactor(int32_t val){ mergeFactor = val; } + + + /** Expert: The fraction of terms in the "dictionary" which should be stored + * in RAM. Smaller values use more memory, but make searching slightly + * faster, while larger values use less memory and make searching slightly + * slower. Searching is typically not dominated by dictionary lookup, so + * tweaking this is rarely useful. + */ + LUCENE_STATIC_CONSTANT(int32_t, DEFAULT_TERM_INDEX_INTERVAL = 128); + /** Expert: Set the interval between indexed terms. Large values cause less + * memory to be used by IndexReader, but slow random-access to terms. Small + * values cause more memory to be used by an IndexReader, and speed + * random-access to terms. + * + * This parameter determines the amount of computation required per query + * term, regardless of the number of documents that contain that term. In + * particular, it is the maximum number of other terms that must be + * scanned before a term is located and its frequency and position information + * may be processed. In a large index with user-entered query terms, query + * processing time is likely to be dominated not by term lookup but rather + * by the processing of frequency and positional data. In a small index + * or when many uncommon query terms are generated (e.g., by wildcard + * queries) term lookup may become a dominant cost. + * + * In particular, numUniqueTerms/interval terms are read into + * memory by an IndexReader, and, on average, interval/2 terms + * must be scanned for each random term access. + * + * @see #DEFAULT_TERM_INDEX_INTERVAL + */ + void setTermIndexInterval(int32_t interval) { termIndexInterval = interval; } + /** Expert: Return the interval between indexed terms. + * + * @see #setTermIndexInterval(int) + */ + int32_t getTermIndexInterval() { return termIndexInterval; } + + /** Determines the minimal number of documents required before the buffered + * in-memory documents are merging and a new Segment is created. + * Since Documents are merged in a {@link RAMDirectory}, + * large value gives faster indexing. At the same time, mergeFactor limits + * the number of files open in a FSDirectory. + * + *

The default value is 10.*/ + int32_t getMinMergeDocs() const{ return minMergeDocs; } + void setMinMergeDocs(int32_t val){ minMergeDocs = val; } + + /** Determines the largest number of documents ever merged by addDocument(). + * Small values (e.g., less than 10,000) are best for interactive indexing, + * as this limits the length of pauses while indexing to a few seconds. + * Larger values are best for batched indexing and speedier searches. + * + *

The default value is {@link #DEFAULT_MAX_MERGE_DOCS}. + */ + LUCENE_STATIC_CONSTANT(int32_t, DEFAULT_MAX_MERGE_DOCS = LUCENE_INT32_MAX_SHOULDBE); + /**Determines the largest number of documents ever merged by addDocument(). + * Small values (e.g., less than 10,000) are best for interactive indexing, + * as this limits the length of pauses while indexing to a few seconds. + * Larger values are best for batched indexing and speedier searches. + * + *

The default value is {@link Integer#MAX_VALUE}. + */ + int32_t getMaxMergeDocs() const{ return maxMergeDocs; } + void setMaxMergeDocs(int32_t val){ maxMergeDocs = val; } + + /** + * Constructs an IndexWriter for the index in path. + * Text will be analyzed with a. If create + * is true, then a new, empty index will be created in + * path, replacing the index already there, if any. + * + * @param path the path to the index directory + * @param a the analyzer to use + * @param create true to create the index or overwrite + * the existing one; false to append to the existing + * index + * @throws IOException if the directory cannot be read/written to, or + * if it does not exist, and create is + * false + */ + IndexWriter(const QString& path, CL_NS(analysis)::Analyzer* a, + const bool create, const bool closeDir = true); + + + /**Constructs an IndexWriter for the index in d. Text will be + * analyzed with a. If create is true, then a new, + * empty index will be created in d, replacing the index already + * there, if any. + */ + IndexWriter(CL_NS(store)::Directory* d, CL_NS(analysis)::Analyzer* a, + const bool create, const bool closeDir = false); + + // Flushes all changes to an index, closes all associated files, and closes + // the directory that the index is stored in. + void close(); + + // Returns the number of documents currently in this index. synchronized + int32_t docCount(); + + + // Adds a document to this index, using the provided analyzer instead of + // the value of {@link #getAnalyzer()}. If the document contains more than + // {@link #setMaxFieldLength(int)} terms for a given field, the remainder + // are discarded. + void addDocument(CL_NS(document)::Document* doc, + CL_NS(analysis)::Analyzer* analyzer = NULL); + + + // Merges all segments together into a single segment, optimizing an index + // for search. synchronized + void optimize(); + + + /**Merges all segments from an array of indices into this index. + * + *

This may be used to parallelize batch indexing. A large document + * collection can be broken into sub-collections. Each sub-collection can be + * indexed in parallel, on a different thread, process or machine. The + * complete index can then be created by merging sub-collection indices + * with this method. + * + *

After this completes, the index is optimized. + *@synchronized + */ + void addIndexes(CL_NS(store)::Directory** dirs); + + /** Merges the provided indexes into this index. + *

After this completes, the index is optimized.

+ *

The provided IndexReaders are not closed.

+ */ + void addIndexes(IndexReader** readers); + + + /** Returns the directory this index resides in. */ + CL_NS(store)::Directory* getDirectory() { return directory; } + + /** Get the current setting of whether to use the compound file format. + * Note that this just returns the value you set with setUseCompoundFile(boolean) + * or the default. You cannot use this to query the status of an existing index. + * @see #setUseCompoundFile(boolean) + */ + bool getUseCompoundFile() { return useCompoundFile; } + + /** Setting to turn on usage of a compound file. When on, multiple files + * for each segment are merged into a single file once the segment creation + * is finished. This is done regardless of what directory is in use. + */ + void setUseCompoundFile(bool value) { useCompoundFile = value; } + + + /** Expert: Set the Similarity implementation used by this IndexWriter. + * + * @see Similarity#setDefault(Similarity) + */ + void setSimilarity(CL_NS(search)::Similarity* similarity) + { this->similarity = similarity; } + + /** Expert: Return the Similarity implementation used by this IndexWriter. + * + *

This defaults to the current value of {@link Similarity#getDefault()}. + */ + CL_NS(search)::Similarity* getSimilarity() { return this->similarity; } + + /** Returns the analyzer used by this index. */ + CL_NS(analysis)::Analyzer* getAnalyzer() { return analyzer; } + +private: + /** Merges all RAM-resident segments. */ + void flushRamSegments(); + + /** Incremental segment merger. */ + void maybeMergeSegments(); + + // Pops segments off of segmentInfos stack down to minSegment, merges them, + // and pushes the merged index onto the top of the segmentInfos stack. + void mergeSegments(const uint32_t minSegment); + + // Merges the named range of segments, replacing them in the stack with a + // single segment. + void mergeSegments(const uint32_t minSegment, const uint32_t end); + + // Some operating systems (e.g. Windows) don't permit a file to be deleted + // while it is opened for read (e.g. by another process or thread). So we + // assume that when a delete fails it is because the file is open in another + // process, and queue the file for subsequent deletion. + void deleteSegments(CL_NS(util)::CLVector* segments); + + void deleteFiles(const QStringList& files); + void readDeleteableFiles(QStringList& files); + void deleteFiles(const QStringList& files, QStringList& deletable); + void deleteFiles(const QStringList& files, CL_NS(store)::Directory* directory); + void writeDeleteableFiles(const QStringList& files); + + // synchronized + QString newSegmentName(); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/MultiReader.cpp b/3rdparty/clucene/src/CLucene/index/MultiReader.cpp new file mode 100644 index 0000000..1260d04 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/MultiReader.cpp @@ -0,0 +1,722 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "MultiReader.h" + +#include "IndexReader.h" +#include "CLucene/document/Document.h" +#include "Terms.h" +#include "SegmentMergeQueue.h" + +CL_NS_USE(store) +CL_NS_USE(util) +CL_NS_DEF(index) + +MultiReader::MultiReader(IndexReader** subReaders): + IndexReader(subReaders == NULL || subReaders[0] == NULL ? NULL : subReaders[0]->getDirectory()), + normsCache(true, true) +{ + initialize(subReaders); +} + +MultiReader::MultiReader(Directory* directory, SegmentInfos* sis, IndexReader** subReaders): + IndexReader(directory, sis, false), + normsCache(true, true) +{ + initialize(subReaders); +} + + +MultiReader::~MultiReader() { +//Func - Destructor +//Pre - true +//Post - The instance has been destroyed all IndexReader instances +// this instance managed have been destroyed to + + _CLDELETE_ARRAY(ones); + _CLDELETE_ARRAY(starts); + + //Iterate through the subReaders and destroy each reader + if (subReaders && subReadersLength > 0) { + for (int32_t i = 0; i < subReadersLength; i++) { + _CLDELETE(subReaders[i]); + } + } + //Destroy the subReaders array + _CLDELETE_ARRAY(subReaders); +} + +void MultiReader::initialize(IndexReader** subReaders){ + this->subReadersLength = 0; + this->subReaders = subReaders; + + //count the subReaders size + if ( subReaders != NULL ){ + while ( subReaders[subReadersLength] != NULL ){ + subReadersLength++; + } + } + _maxDoc = 0; + _numDocs = -1; + ones = NULL; + + starts = _CL_NEWARRAY(int32_t,subReadersLength + 1); // build starts array + for (int32_t i = 0; i < subReadersLength; i++) { + starts[i] = _maxDoc; + + // compute maxDocs + _maxDoc += subReaders[i]->maxDoc(); + if (subReaders[i]->hasDeletions()) + _hasDeletions = true; + } + starts[subReadersLength] = _maxDoc; +} + +bool MultiReader::getTermFreqVectors(int32_t n, Array& result){ + int32_t i = readerIndex(n); // find segment num + return subReaders[i]->getTermFreqVectors(n - starts[i], result); // dispatch to segment +} + +TermFreqVector* MultiReader::getTermFreqVector(int32_t n, const TCHAR* field){ + int32_t i = readerIndex(n); // find segment num + return subReaders[i]->getTermFreqVector(n - starts[i], field); +} + + +int32_t MultiReader::numDocs() { + SCOPED_LOCK_MUTEX(THIS_LOCK) + if (_numDocs == -1) { // check cache + int32_t n = 0; // cache miss--recompute + for (int32_t i = 0; i < subReadersLength; i++) + n += subReaders[i]->numDocs(); // sum from readers + _numDocs = n; + } + return _numDocs; +} + +int32_t MultiReader::maxDoc() const { + return _maxDoc; +} + +bool MultiReader::document(int32_t n, CL_NS(document)::Document* doc){ + int32_t i = readerIndex(n); // find segment num + return subReaders[i]->document(n - starts[i],doc); // dispatch to segment reader +} + +bool MultiReader::isDeleted(const int32_t n) { + int32_t i = readerIndex(n); // find segment num + return subReaders[i]->isDeleted(n - starts[i]); // dispatch to segment reader +} + +uint8_t* MultiReader::norms(const TCHAR* field){ + SCOPED_LOCK_MUTEX(THIS_LOCK) + uint8_t* bytes; + bytes = normsCache.get(field); + if (bytes != NULL){ + return bytes; // cache hit + } + + if ( !hasNorms(field) ) + return fakeNorms(); + + bytes = _CL_NEWARRAY(uint8_t,maxDoc()); + for (int32_t i = 0; i < subReadersLength; i++) + subReaders[i]->norms(field, bytes + starts[i]); + + //Unfortunately the data in the normCache can get corrupted, since it's being loaded with string + //keys that may be deleted while still in use by the map. To prevent this field is duplicated + //and then stored in the normCache + TCHAR* key = STRDUP_TtoT(field); + //update cache + normsCache.put(key, bytes); + + return bytes; +} + +void MultiReader::norms(const TCHAR* field, uint8_t* result) { + SCOPED_LOCK_MUTEX(THIS_LOCK) + uint8_t* bytes = normsCache.get(field); + if (bytes==NULL && !hasNorms(field)) + bytes=fakeNorms(); + + if (bytes != NULL){ // cache hit + int32_t len = maxDoc(); + memcpy(result,bytes,len * sizeof(int32_t)); + } + + for (int32_t i = 0; i < subReadersLength; i++) // read from segments + subReaders[i]->norms(field, result + starts[i]); +} + + +void MultiReader::doSetNorm(int32_t n, const TCHAR* field, uint8_t value){ + normsCache.remove(field); // clear cache + int32_t i = readerIndex(n); // find segment num + subReaders[i]->setNorm(n-starts[i], field, value); // dispatch +} + +TermEnum* MultiReader::terms() const { + return _CLNEW MultiTermEnum(subReaders, starts, NULL); +} + +TermEnum* MultiReader::terms(const Term* term) const { + return _CLNEW MultiTermEnum(subReaders, starts, term); +} + +int32_t MultiReader::docFreq(const Term* t) const { + int32_t total = 0; // sum freqs in Multi + for (int32_t i = 0; i < subReadersLength; i++) + total += subReaders[i]->docFreq(t); + return total; +} + +TermDocs* MultiReader::termDocs() const { + TermDocs* ret = _CLNEW MultiTermDocs(subReaders, starts); + return ret; +} + +TermPositions* MultiReader::termPositions() const { + TermPositions* ret = (TermPositions*)_CLNEW MultiTermPositions(subReaders, starts); + return ret; +} + +void MultiReader::doDelete(const int32_t n) { + _numDocs = -1; // invalidate cache + int32_t i = readerIndex(n); // find segment num + subReaders[i]->deleteDocument(n - starts[i]); // dispatch to segment reader + _hasDeletions = true; +} + +int32_t MultiReader::readerIndex(const int32_t n) const { // find reader for doc n: + int32_t lo = 0; // search starts array + int32_t hi = subReadersLength - 1; // for first element less + // than n, return its index + while (hi >= lo) { + int32_t mid = (lo + hi) >> 1; + int32_t midValue = starts[mid]; + if (n < midValue) + hi = mid - 1; + else if (n > midValue) + lo = mid + 1; + else{ // found a match + while (mid+1 < subReadersLength && starts[mid+1] == midValue) { + mid++; // scan to last match + } + return mid; + } + } + return hi; +} + +bool MultiReader::hasNorms(const TCHAR* field) { + for (int i = 0; i < subReadersLength; i++) { + if (subReaders[i]->hasNorms(field)) + return true; + } + return false; +} +uint8_t* MultiReader::fakeNorms() { + if (ones==NULL) + ones=SegmentReader::createFakeNorms(maxDoc()); + return ones; +} + +void MultiReader::doUndeleteAll(){ + for (int32_t i = 0; i < subReadersLength; i++) + subReaders[i]->undeleteAll(); + _hasDeletions = false; + _numDocs = -1; +} +void MultiReader::doCommit() { + for (int32_t i = 0; i < subReadersLength; i++) + subReaders[i]->commit(); +} + +void MultiReader::doClose() { + SCOPED_LOCK_MUTEX(THIS_LOCK) + for (int32_t i = 0; i < subReadersLength; i++){ + subReaders[i]->close(); + } +} + + +void MultiReader::getFieldNames(FieldOption fldOption, StringArrayWithDeletor& retarray){ + StringArrayWithDeletor temp; + CLHashList hashList; + for (int32_t i = 0; i < subReadersLength; i++) { + IndexReader* reader = subReaders[i]; + reader->getFieldNames(fldOption, temp); + + //create a unique list of names. + StringArrayWithDeletor::iterator itr = temp.begin(); + while ( itr != temp.end() ){ + if ( hashList.find(*itr) == hashList.end() ) + hashList.insert(STRDUP_TtoT(*itr)); + itr++; + } + } + //move the items into the return + CLHashList::iterator itr = hashList.begin(); + while ( itr != hashList.end() ){ + retarray.push_back(*itr);//no need to copy, already done! + itr++; + } +} + + +MultiTermDocs::MultiTermDocs(){ +//Func - Default constructor +// Initialises an empty MultiTermDocs. +// This constructor is needed to allow the constructor of MultiTermPositions +// initialise the instance by itself +//Pre - true +//Post - An empty + + subReaders = NULL; + subReadersLength = 0; + starts = NULL; + base = 0; + pointer = 0; + current = NULL; + term = NULL; + readerTermDocs = NULL; +} + +MultiTermDocs::MultiTermDocs(IndexReader** r, const int32_t* s){ +//Func - Constructor +//Pre - if r is NULL then rLen must be 0 else if r != NULL then rLen > 0 +// s != NULL +//Post - The instance has been created + + //count readers + subReadersLength = 0; + subReaders = r; + + CND_PRECONDITION(s != NULL, "s is NULL"); + + if ( subReaders != NULL ){ + while ( subReaders[subReadersLength] != NULL ) + subReadersLength++; + } + + starts = s; + base = 0; + pointer = 0; + current = NULL; + term = NULL; + + readerTermDocs = NULL; + + //Check if there are subReaders + if(subReaders != NULL && subReadersLength > 0){ + readerTermDocs = _CL_NEWARRAY(TermDocs*, subReadersLength+1); + + CND_CONDITION(readerTermDocs != NULL,"No memory could be allocated for readerTermDocs"); + + //Initialize the readerTermDocs pointer array to NULLs + for ( int32_t i=0;idoc(); +} +int32_t MultiTermDocs::freq() const { + CND_PRECONDITION(current!=NULL,"current==NULL, check that next() was called"); + return current->freq(); +} + +void MultiTermDocs::seek(TermEnum* termEnum){ + seek(termEnum->term(false)); +} + +void MultiTermDocs::seek( Term* tterm) { +//Func - Resets the instance for a new search +//Pre - tterm != NULL +//Post - The instance has been reset for a new search + + CND_PRECONDITION(tterm != NULL, "tterm is NULL"); + + //Assigning tterm is done as below for a reason + //The construction ensures that if seek is called from within + //MultiTermDocs with as argument this->term (seek(this->term)) that the assignment + //will succeed and all referencecounters represent the correct situation + + //Get a pointer from tterm and increase its reference counter + Term *TempTerm = _CL_POINTER(tterm); + + //Finialize term to ensure we decrease the reference counter of the instance which term points to + _CLDECDELETE(term); + + //Assign TempTerm to term + term = TempTerm; + + base = 0; + pointer = 0; + current = NULL; +} + +bool MultiTermDocs::next() { + if (current != NULL && current->next()) { + return true; + } else if (pointer < subReadersLength) { + base = starts[pointer]; + current = termDocs(pointer++); + return next(); + } else + return false; +} + +int32_t MultiTermDocs::read(int32_t* docs, int32_t* freqs, int32_t length) { + while (true) { + while (current == NULL) { + if (pointer < subReadersLength) { // try next segment + base = starts[pointer]; + current = termDocs(pointer++); + } else { + return 0; + } + } + int32_t end = current->read(docs, freqs,length); + if (end == 0) { // none left in segment + current = NULL; + } else { // got some + int32_t b = base; // adjust doc numbers + for (int32_t i = 0; i < end; i++) + docs[i] += b; + return end; + } + } +} + +bool MultiTermDocs::skipTo(const int32_t target) { + do { + if (!next()) + return false; + } while (target > doc()); + return true; +} + +void MultiTermDocs::close() { +//Func - Closes all MultiTermDocs managed by this instance +//Pre - true +//Post - All the MultiTermDocs have been closed + + + //Check if readerTermDocs is valid + if (readerTermDocs){ + TermDocs* curTD = NULL; + //iterate through the readerTermDocs array + for (int32_t i = 0; i < subReadersLength; i++) { + //Retrieve the i-th TermDocs instance + curTD = readerTermDocs[i]; + + //Check if it is a valid pointer + if (curTD != NULL) { + //Close it + curTD->close(); + _CLDELETE(curTD); + } + } + + _CLDELETE_ARRAY(readerTermDocs); + } + + //current previously pointed to a member of readerTermDocs; ensure that + //it doesn't now point to invalid memory. + current = NULL; + base = 0; + pointer = 0; + + _CLDECDELETE(term); +} + +TermDocs* MultiTermDocs::termDocs(const IndexReader* reader) const { + TermDocs* ret = reader->termDocs(); + return ret; +} + +TermDocs* MultiTermDocs::termDocs(const int32_t i) const { + if (term == NULL) + return NULL; + TermDocs* result = readerTermDocs[i]; + if (result == NULL){ + readerTermDocs[i] = termDocs(subReaders[i]); + result = readerTermDocs[i]; + } + result->seek(term); + + return result; +} + + +MultiTermEnum::MultiTermEnum( + IndexReader** subReaders, const int32_t *starts, const Term* t){ +//Func - Constructor +// Opens all enumerations of all readers +//Pre - readers != NULL and contains an array of IndexReader instances each responsible for +// reading a single segment +// subReadersLength >= 0 and represents the number of readers in the readers array +// starts is an array of +//Post - An instance of has been created + +//Pre - if readers is NULL then subReadersLength must be 0 else if readers != NULL then subReadersLength > 0 +// s != NULL +//Post - The instance has been created + + int32_t subReadersLength = 0; + if ( subReaders != NULL ){ + while ( subReaders[subReadersLength] != NULL ) + subReadersLength++; + } + CND_PRECONDITION(starts != NULL,"starts is NULL"); + + //Temporary variables + IndexReader* reader = NULL; + TermEnum* termEnum = NULL; + SegmentMergeInfo* smi = NULL; + _docFreq = 0; + _term = NULL; + queue = _CLNEW SegmentMergeQueue(subReadersLength); + + CND_CONDITION (queue != NULL, "Could not allocate memory for queue"); + + //iterate through all the readers + for ( int32_t i=0;iterms(t); + }else{ + //termEnum is an enumeration of all the Terms and TermInfos in the set. + termEnum = reader->terms(); + } + + //Instantiate an new SegmentMerginfo + smi = _CLNEW SegmentMergeInfo(starts[i], termEnum, reader); + + // Note that in the call termEnum->getTerm(false) below false is required because + // otherwise a reference is leaked. By passing false getTerm is + // ordered to return an unowned reference instead. (Credits for DSR) + if (t == NULL ? smi->next() : termEnum->term(false) != NULL){ + // initialize queue + queue->put(smi); + } else{ + //Close the SegmentMergeInfo + smi->close(); + //And have it deleted + _CLDELETE(smi); + } + } + + //Check if the queue has elements + if (t != NULL && queue->size() > 0) { + next(); + } +} + +MultiTermEnum::~MultiTermEnum(){ +//Func - Destructor +//Pre - true +//Post - All the resource have been freed and the instance has been deleted + + //Close the enumeration + close(); + + //Delete the queue + _CLDELETE(queue); +} + +bool MultiTermEnum::next(){ +//Func - Move the current term to the next in the set of enumerations +//Pre - true +//Post - Returns true if term has been moved to the next in the set of enumerations +// Returns false if this was not possible + + SegmentMergeInfo* top = queue->top(); + if (top == NULL) { + _CLDECDELETE(_term); + _term = NULL; + return false; + } + + //The getTerm method requires the client programmer to indicate whether he + // owns the returned reference, so we can discard ours + // right away. + _CLDECDELETE(_term); + + //Assign term the term of top and make sure the reference counter is increased + _term = _CL_POINTER(top->term); + _docFreq = 0; + + //Find the next term + while (top != NULL && _term->compareTo(top->term) == 0) { + //don't delete, this is the top + queue->pop(); + // increment freq + _docFreq += top->termEnum->docFreq(); + if (top->next()){ + // restore queue + queue->put(top); + }else{ + // done with a segment + top->close(); + _CLDELETE(top); + } + top = queue->top(); + } + + return true; +} + + +Term* MultiTermEnum::term() { +//Func - Returns the current term of the set of enumerations +//Pre - pointer is true or false and indicates if the reference counter +// of term must be increased or not +// next() must have been called once! +//Post - pointer = true -> term has been returned with an increased reference counter +// pointer = false -> term has been returned + + return _CL_POINTER(_term); +} + +Term* MultiTermEnum::term(bool pointer) { + if ( pointer ) + return _CL_POINTER(_term); + else + return _term; +} + +int32_t MultiTermEnum::docFreq() const { +//Func - Returns the document frequency of the current term in the set +//Pre - termInfo != NULL +// next() must have been called once +//Post - The document frequency of the current enumerated term has been returned + + return _docFreq; +} + + +void MultiTermEnum::close() { +//Func - Closes the set of enumerations in the queue +//Pre - queue holds a valid reference to a SegmentMergeQueue +//Post - The queue has been closed all SegmentMergeInfo instance have been deleted by +// the closing of the queue +// term has been finalized and reset to NULL + + // Needed when this enumeration hasn't actually been exhausted yet + _CLDECDELETE(_term); + + //Close the queue This will destroy all SegmentMergeInfo instances! + queue->close(); + +} + + + + + +MultiTermPositions::MultiTermPositions(IndexReader** r, const int32_t* s){ +//Func - Constructor +//Pre - if r is NULL then rLen must be 0 else if r != NULL then rLen > 0 +// s != NULL +//Post - The instance has been created + + subReaders = r; + subReadersLength = 0; + if ( subReaders != NULL ){ + while ( subReaders[subReadersLength] != NULL ) + subReadersLength ++ ; + } + + CND_PRECONDITION(s != NULL, "s is NULL"); + + starts = s; + base = 0; + pointer = 0; + current = NULL; + term = NULL; + + readerTermDocs = NULL; + + //Check if there are readers + if(subReaders != NULL && subReadersLength > 0){ + readerTermDocs = (TermDocs**)_CL_NEWARRAY(SegmentTermPositions*,subReadersLength); + + CND_CONDITION(readerTermDocs != NULL,"No memory could be allocated for readerTermDocs"); + + //Initialize the readerTermDocs pointer array + for ( int32_t i=0;icurrent to always +// be a SegmentTermPositions rather than merely a SegmentTermDocs. +// To that end, we override the termDocs(IndexReader&) method to produce +// a SegmentTermPositions via the underlying reader's termPositions method +// rather merely producing a SegmentTermDocs via the reader's termDocs +// method. + + TermPositions* tp = reader->termPositions(); + TermDocs* ret = tp->__asTermDocs(); + + CND_CONDITION(ret != NULL, + "Dynamic downcast in MultiTermPositions::termDocs from" + " TermPositions to TermDocs failed." + ); + return ret; + } + +int32_t MultiTermPositions::nextPosition() { + //Func - + //Pre - current != NULL + //Post - + CND_PRECONDITION(current != NULL,"current is NULL"); + + TermPositions* curAsTP = current->__asTermPositions(); + + CND_CONDITION(curAsTP != NULL, + "Dynamic downcast in MultiTermPositions::nextPosition from" + " SegmentTermDocs to TermPositions failed." + ) + return curAsTP->nextPosition(); +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/MultiReader.h b/3rdparty/clucene/src/CLucene/index/MultiReader.h new file mode 100644 index 0000000..1d76814 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/MultiReader.h @@ -0,0 +1,202 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_MultiReader +#define _lucene_index_MultiReader + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "SegmentHeader.h" +#include "IndexReader.h" +#include "CLucene/document/Document.h" +#include "Terms.h" +#include "SegmentMergeQueue.h" + +CL_NS_DEF(index) + +/** An IndexReader which reads multiple indexes, appending their content. +*/ +class MultiTermDocs:public virtual TermDocs { +private: +protected: + TermDocs** readerTermDocs; + + IndexReader** subReaders; + int32_t subReadersLength; + const int32_t* starts; + Term* term; + + int32_t base; + int32_t pointer; + + TermDocs* current; // == segTermDocs[pointer] +public: + MultiTermDocs(); + MultiTermDocs(IndexReader** subReaders, const int32_t* s); + virtual ~MultiTermDocs(); + + int32_t doc() const; + int32_t freq() const; + + void seek(TermEnum* termEnum); + void seek(Term* tterm); + bool next(); + + /** Optimized implementation. */ + int32_t read(int32_t* docs, int32_t* freqs, int32_t length); + + /** As yet unoptimized implementation. */ + bool skipTo(const int32_t target); + + void close(); + + virtual TermPositions* __asTermPositions(); +protected: + virtual TermDocs* termDocs(const IndexReader* reader) const; +private: + TermDocs* termDocs(const int32_t i) const; + +}; + + +//MultiTermEnum represents the enumeration of all terms of all readers +class MultiTermEnum:public TermEnum { +private: + SegmentMergeQueue* queue; + + Term* _term; + int32_t _docFreq; +public: + //Constructor + //Opens all enumerations of all readers + MultiTermEnum(IndexReader** subReaders, const int32_t* starts, const Term* t); + + //Destructor + ~MultiTermEnum(); + + //Move the current term to the next in the set of enumerations + bool next(); + + //Returns a pointer to the current term of the set of enumerations + Term* term(); + Term* term(bool pointer); + + //Returns the document frequency of the current term in the set + int32_t docFreq() const; + + //Closes the set of enumerations in the queue + void close(); + + + const char* getObjectName(){ return MultiTermEnum::getClassName(); } + static const char* getClassName(){ return "MultiTermEnum"; } +}; + + +class MultiTermPositions:public MultiTermDocs,public TermPositions { +public: + MultiTermPositions(IndexReader** subReaders, const int32_t* s); + ~MultiTermPositions() {}; + int32_t nextPosition(); + + + virtual TermDocs* __asTermDocs(); + virtual TermPositions* __asTermPositions(); +protected: + TermDocs* termDocs(const IndexReader* reader) const; +}; + + +class MultiReader:public IndexReader{ +private: + bool _hasDeletions; + IndexReader** subReaders; + int32_t subReadersLength; + int32_t* starts; // 1st docno for each segment + + CL_NS(util)::CLHashtable > normsCache; + int32_t _maxDoc; + int32_t _numDocs; + void initialize(IndexReader** subReaders); + + int32_t readerIndex(const int32_t n) const; + + bool hasNorms(const TCHAR* field); + uint8_t* ones; + uint8_t* fakeNorms(); +protected: + void doSetNorm(int32_t n, const TCHAR* field, uint8_t value); + void doUndeleteAll(); + void doCommit(); + // synchronized + void doClose(); + + // synchronized + void doDelete(const int32_t n); +public: + /** Construct reading the named set of readers. */ + MultiReader(CL_NS(store)::Directory* directory, SegmentInfos* sis, IndexReader** subReaders); + + /** + *

Construct a MultiReader aggregating the named set of (sub)readers. + * Directory locking for delete, undeleteAll, and setNorm operations is + * left to the subreaders.

+ *

Note that all subreaders are closed if this Multireader is closed.

+ * @param subReaders set of (sub)readers + * @throws IOException + */ + MultiReader(IndexReader** subReaders); + + ~MultiReader(); + + /** Return an array of term frequency vectors for the specified document. + * The array contains a vector for each vectorized field in the document. + * Each vector vector contains term numbers and frequencies for all terms + * in a given vectorized field. + * If no such fields existed, the method returns null. + */ + bool getTermFreqVectors(int32_t n, Array& result); + TermFreqVector* getTermFreqVector(int32_t n, const TCHAR* field); + + + // synchronized + int32_t numDocs(); + + int32_t maxDoc() const; + + bool document(int32_t n, CL_NS(document)::Document* doc); + + bool isDeleted(const int32_t n); + bool hasDeletions() const{ return _hasDeletions; } + + // synchronized + uint8_t* norms(const TCHAR* field); + void norms(const TCHAR* field, uint8_t* result); + + TermEnum* terms() const; + TermEnum* terms(const Term* term) const; + + //Returns the document frequency of the current term in the set + int32_t docFreq(const Term* t=NULL) const; + TermDocs* termDocs() const; + TermPositions* termPositions() const; + + + /** + * @see IndexReader#getFieldNames(IndexReader.FieldOption fldOption) + */ + void getFieldNames(FieldOption fldOption, CL_NS(util)::StringArrayWithDeletor& retarray); +}; + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/index/SegmentHeader.h b/3rdparty/clucene/src/CLucene/index/SegmentHeader.h new file mode 100644 index 0000000..00b0899 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentHeader.h @@ -0,0 +1,314 @@ +/* +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_SegmentHeader_ +#define _lucene_index_SegmentHeader_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include "SegmentInfos.h" +#include "CLucene/util/BitSet.h" +#include "CLucene/util/VoidMap.h" +#include "Term.h" +#include "FieldInfos.h" +#include "FieldsReader.h" +#include "IndexReader.h" +#include "TermInfosReader.h" +#include "CompoundFile.h" +#include "CLucene/util/ThreadLocal.h" + +CL_NS_DEF(index) + +class SegmentReader; + +class SegmentTermDocs : public virtual TermDocs +{ + int32_t _doc; + int32_t skipInterval; + int32_t numSkips; + int32_t skipCount; + CL_NS(store)::IndexInput* skipStream; + int32_t skipDoc; + int64_t freqPointer; + int64_t proxPointer; + int64_t skipPointer; + bool haveSkipped; + +protected: + // SegmentReader parent + const SegmentReader* parent; + CL_NS(store)::IndexInput* freqStream; + int32_t count; + int32_t df; + int32_t _freq; + CL_NS(util)::BitSet* deletedDocs; +public: + virtual ~SegmentTermDocs(); + + virtual void seek(TermEnum* termEnum); + virtual void seek(Term* term); + virtual void seek(const TermInfo* ti); + + virtual void close(); + virtual int32_t doc()const; + virtual int32_t freq()const; + + virtual bool next(); + + /** Optimized implementation. */ + virtual int32_t read(int32_t* docs, int32_t* freqs, int32_t length); + + /** Optimized implementation. */ + virtual bool skipTo(const int32_t target); + + virtual TermPositions* __asTermPositions(); + + // \param Parent must be a segment reader + SegmentTermDocs( const SegmentReader* Parent); +protected: + virtual void skippingDoc(){} + virtual void skipProx(int64_t proxPointer){} +}; + + +class SegmentTermPositions : public SegmentTermDocs, public TermPositions +{ +private: + CL_NS(store)::IndexInput* proxStream; + int32_t proxCount; + int32_t position; + +public: + // \param Parent must be a segment reader + SegmentTermPositions(const SegmentReader* Parent); + ~SegmentTermPositions(); + + void seek(const TermInfo* ti); + void close(); + int32_t nextPosition(); + bool next(); + int32_t read(int32_t* docs, int32_t* freqs, int32_t length); + virtual TermDocs* __asTermDocs(); + virtual TermPositions* __asTermPositions(); + + //resolve SegmentTermDocs/TermPositions ambiguity + void seek(Term* term){ SegmentTermDocs::seek(term); } + void seek(TermEnum* termEnum){ SegmentTermDocs::seek(termEnum); } + int32_t doc() const{ return SegmentTermDocs::doc(); } + int32_t freq() const{ return SegmentTermDocs::freq(); } + bool skipTo(const int32_t target){ return SegmentTermDocs::skipTo(target); } + +protected: + void skippingDoc(); + /** Called by super.skipTo(). */ + void skipProx(int64_t proxPointer); +}; + +// An IndexReader responsible for reading 1 segment of an index +class SegmentReader : public IndexReader +{ + /** + * The class Norm represents the normalizations for a field. + * These normalizations are read from an IndexInput in into an array of bytes called bytes + */ + class Norm : LUCENE_BASE + { + int32_t number; + SegmentReader* reader; + QString segment; // segment name + + public: + CL_NS(store)::IndexInput* in; + uint8_t* bytes; + bool dirty; + //Constructor + Norm(CL_NS(store)::IndexInput* instrm, int32_t number, + SegmentReader* reader, const QString& segment); + //Destructor + ~Norm(); + + void reWrite(); + }; + friend class SegmentReader::Norm; + + //Holds the name of the segment that is being read + QString segment; + + //Indicates if there are documents marked as deleted + bool deletedDocsDirty; + bool normsDirty; + bool undeleteAll; + + //Holds all norms for all fields in the segment + typedef CL_NS(util)::CLHashtable NormsType; + NormsType _norms; + + uint8_t* ones; + uint8_t* fakeNorms(); + + // Compound File Reader when based on a compound file segment + CompoundFileReader* cfsReader; + // Reads the Field Info file + FieldsReader* fieldsReader; + TermVectorsReader* termVectorsReaderOrig; + CL_NS(util)::ThreadLocal >termVectorsLocal; + + void initialize(SegmentInfo* si); + + // Create a clone from the initial TermVectorsReader and store it in the + // ThreadLocal. @return TermVectorsReader + TermVectorsReader* getTermVectorsReader(); + +protected: + // Marks document docNum as deleted + void doDelete(const int32_t docNum); + void doUndeleteAll(); + void doCommit(); + void doSetNorm(int32_t doc, const TCHAR* field, uint8_t value); + + // can return null if norms aren't stored + uint8_t* getNorms(const TCHAR* field); + +public: + /** + Func - Constructor. + Opens all files of a segment + .fnm -> Field Info File + Field names are stored in the field info file, with suffix .fnm. + .frq -> Frequency File + The .frq file contains the lists of documents which contain + each term, along with the frequency of the term in that document. + .prx -> Prox File + The prox file contains the lists of positions that each term occurs + at within documents. + .tis -> Term Info File + This file is sorted by Term. Terms are ordered first lexicographically + by the term's field name, and within that lexicographically by the term's text. + .del -> Deletion File + The .del file is optional, and only exists when a segment contains deletions + .f[0-9]* -> Norm File + Contains s, for each document, a byte that encodes a value that is + multiplied into the score for hits on that field: + */ + SegmentReader(SegmentInfo* si); + + SegmentReader(SegmentInfos* sis, SegmentInfo* si); + // Destructor. + virtual ~SegmentReader(); + + // Closes all streams to the files of a single segment + void doClose(); + + // Checks if a segment managed by SegmentInfo si has deletions + static bool hasDeletions(const SegmentInfo* si); + bool hasDeletions() const; + bool hasNorms(const TCHAR* field) const; + + // Returns all file names managed by this SegmentReader + void files(QStringList& retarray); + // Returns an enumeration of all the Terms and TermInfos in the set. + TermEnum* terms() const; + // Returns an enumeration of terms starting at or after the named term t + TermEnum* terms(const Term* t) const; + + // Gets the document identified by n + bool document(int32_t n, CL_NS(document)::Document* doc); + + // Checks if the n-th document has been marked deleted + bool isDeleted(const int32_t n); + + // Returns an unpositioned TermDocs enumerator. + TermDocs* termDocs() const; + // Returns an unpositioned TermPositions enumerator. + TermPositions* termPositions() const; + + // Returns the number of documents which contain the term t + int32_t docFreq(const Term* t) const; + + // Returns the actual number of documents in the segment + int32_t numDocs(); + // Returns the number of all the documents in the segment including the + // ones that have been marked deleted + int32_t maxDoc() const; + + // Returns the bytes array that holds the norms of a named field. + // Returns fake norms if norms aren't available + uint8_t* norms(const TCHAR* field); + + // Reads the Norms for field from disk + void norms(const TCHAR* field, uint8_t* bytes); + + // concatenating segment with ext and x + QString SegmentName(const QString& ext, const int32_t x = -1); + // Creates a filename in buffer by concatenating segment with ext and x + void SegmentName(QString& buffer, int32_t bufferLen, const QString& ext, + const int32_t x = -1); + + /** + * @see IndexReader#getFieldNames(IndexReader.FieldOption fldOption) + */ + void getFieldNames(FieldOption fldOption, CL_NS(util)::StringArrayWithDeletor& retarray); + + static bool usesCompoundFile(SegmentInfo* si); + + /** Return a term frequency vector for the specified document and field. The + * vector returned contains term numbers and frequencies for all terms in + * the specified field of this document, if the field had storeTermVector + * flag set. If the flag was not set, the method returns null. + * @throws IOException + */ + TermFreqVector* getTermFreqVector(int32_t docNumber, const TCHAR* field = NULL); + + /** Return an array of term frequency vectors for the specified document. + * The array contains a vector for each vectorized field in the document. + * Each vector vector contains term numbers and frequencies for all terms + * in a given vectorized field. + * If no such fields existed, the method returns null. + * @throws IOException + */ + bool getTermFreqVectors(int32_t docNumber, Array& result); + +private: + //Open all norms files for all fields + void openNorms(CL_NS(store)::Directory* cfsDir); + //Closes all norms files + void closeNorms(); + + // a bitVector that manages which documents have been deleted + CL_NS(util)::BitSet* deletedDocs; + // an IndexInput to the frequency file + CL_NS(store)::IndexInput* freqStream; + // For reading the fieldInfos file + FieldInfos* fieldInfos; + // For reading the Term Dictionary .tis file + TermInfosReader* tis; + // an IndexInput to the prox file + CL_NS(store)::IndexInput* proxStream; + + static bool hasSeparateNorms(SegmentInfo* si); + static uint8_t* createFakeNorms(int32_t size); + + // allow various classes to access the internals of this. this allows us + // to have a more tight idea of the package + friend class IndexReader; + friend class IndexWriter; + friend class SegmentTermDocs; + friend class SegmentTermPositions; + friend class MultiReader; +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/SegmentInfos.cpp b/3rdparty/clucene/src/CLucene/index/SegmentInfos.cpp new file mode 100644 index 0000000..f62c406 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentInfos.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#include "CLucene/StdHeader.h" +#include "SegmentInfos.h" + +#include "CLucene/store/Directory.h" +#include "CLucene/util/Misc.h" + +CL_NS_USE(store) +CL_NS_USE(util) +CL_NS_DEF(index) + +SegmentInfo::SegmentInfo(const QString& Name, const int32_t DocCount, + CL_NS(store)::Directory* Dir) + : docCount(DocCount) + , dir(Dir) +{ + //Func - Constructor. Initialises SegmentInfo. + //Pre - Name holds the unique name in the directory Dir + // DocCount holds the number of documents in the segment + // Dir holds the Directory where the segment resides + //Post - The instance has been created. name contains the duplicated string + // Name. docCount = DocCount and dir references Dir + name = Name; +} + +SegmentInfo::~SegmentInfo() +{ +} + +SegmentInfos::SegmentInfos(bool _deleteMembers) + : deleteMembers(_deleteMembers) +{ + //Func - Constructor + //Pre - deleteMembers indicates if the instance to be created must delete + // all SegmentInfo instances it manages when the instance is destroyed + // or not true -> must delete, false may not delete + //Post - An instance of SegmentInfos has been created. + + //initialize counter to 0 + counter = 0; + version = Misc::currentTimeMillis(); +} + +SegmentInfos::~SegmentInfos() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed. Depending on the constructor used + // the SegmentInfo instances that this instance managed have been + // deleted or not. + + if (deleteMembers) { + segmentInfosType::iterator it; + for (it = infos.begin(); it != infos.end(); ++it) + _CLLDELETE(*it); + } + //Clear the list of SegmentInfo instances - make sure everything is deleted + infos.clear(); +} + +SegmentInfo* SegmentInfos::info(int32_t i) const +{ + //Func - Returns a reference to the i-th SegmentInfo in the list. + //Pre - i >= 0 + //Post - A reference to the i-th SegmentInfo instance has been returned + + CND_PRECONDITION(i >= 0, "i contains negative number"); + + //Get the i-th SegmentInfo instance + SegmentInfo *ret = infos.value(i, 0); + + //Condition check to see if the i-th SegmentInfo has been retrieved + CND_CONDITION(ret != NULL, "No SegmentInfo instance found"); + + return ret; +} + +void SegmentInfos::clearto(size_t _min) +{ + // Make sure we actually need to remove + if (infos.size() > _min) { + segmentInfosType::iterator itr; + segmentInfosType::iterator eitr = infos.end(); + segmentInfosType::iterator bitr = infos.begin() + _min; + + for(itr = bitr; itr != eitr; ++itr) + _CLLDELETE((*itr)); + infos.erase(bitr, eitr); + } +} + +void SegmentInfos::add(SegmentInfo* info) +{ + infos.push_back(info); +} + +int32_t SegmentInfos::size() const +{ + return infos.size(); +} + +void SegmentInfos::read(Directory* directory) +{ + //Func - Reads segments file that resides in directory. + //Pre - directory contains a valid reference + //Post - The segments file has been read and for each segment found + // a SegmentsInfo intance has been created and stored. + + //Open an IndexInput to the segments file and check if valid + IndexInput* input = directory->openInput(QLatin1String("segments")); + if (input) { + try { + int32_t format = input->readInt(); + // file contains explicit format info + if (format < 0) { + // check that it is a format we can understand + if (format < FORMAT) { + TCHAR err[30]; + _sntprintf(err, 30, _T("Unknown format version: %d"), format); + _CLTHROWT(CL_ERR_Runtime, err); + } + // read version + version = input->readLong(); + // read counter + counter = input->readInt(); + } else { + // file is in old format without explicit format info + counter = format; + } + + //Temporary variable for storing the name of the segment + char aname[CL_MAX_PATH] = { 0 }; + TCHAR tname[CL_MAX_PATH] = { 0 }; + + //read segmentInfos + for (int32_t i = input->readInt(); i > 0; --i) { + // read the name of the segment + input->readString(tname, CL_MAX_PATH); + STRCPY_TtoA(aname, tname, CL_MAX_PATH); + + //Instantiate a new SegmentInfo Instance + SegmentInfo* si = _CLNEW SegmentInfo(QLatin1String(aname), + input->readInt(), directory); + + //Condition check to see if si points to an instance + CND_CONDITION(si != NULL, "Memory allocation for si failed") ; + + //store SegmentInfo si + infos.push_back(si); + } + + if (format >= 0) { + // in old format the version number may be at the end of the file + if (input->getFilePointer() >= input->length()) { + // old file format without version number + version = Misc::currentTimeMillis(); + } else { + // read version + version = input->readLong(); + } + } + } _CLFINALLY ( + //destroy the inputStream input. The destructor of IndexInput will + //also close the Inputstream input + _CLDELETE(input); + ); + } +} + +void SegmentInfos::write(Directory* directory) +{ + //Func - Writes a new segments file based upon the SegmentInfo instances it manages + //Pre - directory is a valid reference to a Directory + //Post - The new segment has been written to disk + + //Open an IndexOutput to the segments file and check if valid + IndexOutput* output = directory->createOutput(QLatin1String("segments.new")); + if (output) { + try { + // write FORMAT + output->writeInt(FORMAT); + // every write changes the index + output->writeLong(++version); + // Write the counter + output->writeInt(counter); + + // Write the number of SegmentInfo Instances which is equal to the number + // of segments in directory as each SegmentInfo manages a single segment + output->writeInt(infos.size()); + + //temporary value for wide segment name + TCHAR tname[CL_MAX_PATH]; + + //Iterate through all the SegmentInfo instances + for (uint32_t i = 0; i < infos.size(); ++i) { + //Retrieve the SegmentInfo + SegmentInfo *si = infos.value(i, 0); + //Condition check to see if si has been retrieved + CND_CONDITION(si != NULL, "No SegmentInfo instance found"); + + //Write the name of the current segment + int32_t count = si->name.toWCharArray(tname); + tname[count] = '\0'; + output->writeString(tname, _tcslen(tname)); + + //Write the number of documents in the segment + output->writeInt(si->docCount); + } + } _CLFINALLY( + output->close(); + _CLDELETE(output); + ); + + // install new segment info + directory->renameFile(QLatin1String("segments.new"), + QLatin1String("segments")); + } +} + + +int64_t SegmentInfos::readCurrentVersion(Directory* directory) +{ + int32_t format = 0; + int64_t version = 0; + IndexInput* input = directory->openInput(QLatin1String("segments")); + try { + format = input->readInt(); + if (format < 0){ + if (format < FORMAT) { + TCHAR err[30]; + _sntprintf(err, 30, _T("Unknown format version: %d"), format); + _CLTHROWT(CL_ERR_Runtime, err); + } + // read version + version = input->readLong(); + } + } _CLFINALLY ( + input->close(); + _CLDELETE(input); + ); + + if (format < 0) + return version; + + // We cannot be sure about the format of the file. Therefore we have to + // read the whole file and cannot simply seek to the version entry. + SegmentInfos segmentInfos; + segmentInfos.read(directory); + return segmentInfos.getVersion(); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentInfos.h b/3rdparty/clucene/src/CLucene/index/SegmentInfos.h new file mode 100644 index 0000000..ce71838 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentInfos.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#ifndef _lucene_index_SegmentInfos_ +#define _lucene_index_SegmentInfos_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include "CLucene/store/Directory.h" + +CL_NS_DEF(index) + +class SegmentInfo : LUCENE_BASE +{ +public: + SegmentInfo(const QString& Name, const int32_t DocCount, + CL_NS(store)::Directory* Dir); + ~SegmentInfo(); + + ///Gets the Directory where the segment resides + CL_NS(store)::Directory* getDir() const { return dir; } + + //Unique name in directory dir + QString name; + + //Number of docs in the segment + const int32_t docCount; + +private: + //Directory where the segment resides + CL_NS(store)::Directory* dir; +}; + +typedef QVector segmentInfosType; + +//SegmentInfos manages a list of SegmentInfo instances +//Each SegmentInfo contains information about a segment in a directory. +// +//The active segments in the index are stored in the segment info file. +//An index only has a single file in this format, and it is named "segments". +//This lists each segment by name, and also contains the size of each segment. +//The format of the file segments is defined as follows: +// +// SegCount +//Segments --> SegCount, +// +//SegCount, SegSize --> UInt32 +// +//SegName --> String +// +//SegName is the name of the segment, and is used as the file name prefix +//for all of the files that compose the segment's index. +// +//SegSize is the number of documents contained in the segment index. +// +//Note: +//At http://jakarta.apache.org/lucene/docs/fileformats.html the definition +//of all file formats can be found. Note that java lucene currently +//defines Segments as follows: +// +//Segments --> Format, Version, SegCount, SegCount +// +//Format, SegCount, SegSize --> UInt32 +// +//Format and Version have not been implemented yet +class SegmentInfos : LUCENE_BASE +{ +public: + SegmentInfos(bool deleteMembers = true); + ~SegmentInfos(); + + //delete and clears objects 'from' from to 'to' + void clearto(size_t to); + + //count of segment infos + int32_t size() const; + + //add a segment info + void add(SegmentInfo* info); + + //Returns a reference to the i-th SegmentInfo in the list. + SegmentInfo* info(int32_t i) const; + + // version number when this SegmentInfos was generated. + int64_t getVersion() const { return version; } + + static int64_t readCurrentVersion(CL_NS(store)::Directory* directory); + + //Reads segments file that resides in directory + void read(CL_NS(store)::Directory* directory); + + //Writes a new segments file based upon the SegmentInfo instances it manages + void write(CL_NS(store)::Directory* directory); + +private: + // The file format version, a negative number. + // Works since counter, the old 1st entry, is always >= 0 + LUCENE_STATIC_CONSTANT(int32_t, FORMAT = -1); + + // counts how often the index has been changed by adding or deleting docs. + // starting with the current time in milliseconds forces to create unique + // version numbers. + int64_t version; + + segmentInfosType infos; + + // used to name new segments + int32_t counter; + + // allow IndexWriter to use counter + friend class IndexWriter; + + bool deleteMembers; +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.cpp b/3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.cpp new file mode 100644 index 0000000..85ac784 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.cpp @@ -0,0 +1,104 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "SegmentMergeInfo.h" + +#include "SegmentTermEnum.h" +#include "SegmentHeader.h" + +CL_NS_DEF(index) + +SegmentMergeInfo::SegmentMergeInfo(const int32_t b, TermEnum* te, IndexReader* r): + reader(r),termEnum(te),base(b), docMap(NULL) { +//Func - Constructor +//Pre - b >= 0 +// te contains a valid reference to a SegmentTermEnum instance +// r contains a valid reference to a SegmentReader instance +//Post - The instance has been created + + CND_PRECONDITION(b >= 0, "b is a negative number"); + + postings=NULL; + term = te->term(); +} + +SegmentMergeInfo::~SegmentMergeInfo(){ +//Func - Destructor +//Pre - true +//Post - The instance has been destroyed + + close(); +} + +int32_t* SegmentMergeInfo::getDocMap(){ + if ( docMap == NULL ){ + // build array which maps document numbers around deletions + if (reader->hasDeletions()) { + //Get the total number of documents managed by the reader including the deleted ones + int32_t maxDoc = reader->maxDoc(); + //Create a map for all documents + docMap = _CL_NEWARRAY(int32_t,maxDoc); + int32_t j = 0; + //Iterate through all the document numbers + for (int32_t i = 0; i < maxDoc; i++) { + //Check if document i is marked deleted + if (reader->isDeleted(i)){ + //Document i has not been marked deleted so assign -1 + docMap[i] = -1; + }else{ + docMap[i] = j++; + } + } + } + } + return docMap; +} + +TermPositions* SegmentMergeInfo::getPositions() { + if (postings == NULL) { + postings = reader->termPositions(); + } + return postings; +} + + +bool SegmentMergeInfo::next() { +//Func - Moves the current term of the enumeration termEnum to the next and term +// points to this new current term +//Pre - true +//Post - Returns true if the term has been moved to the next otherwise false + if (termEnum->next()) { + _CLDECDELETE(term); + term = termEnum->term(); + return true; + } else { + _CLDECDELETE(term); //TODO: test HighFreqTerms errors with this + term = NULL; + return false; + } +} + +void SegmentMergeInfo::close() { +//Func - Closes the the resources +//Pre - true +//Post - The resources have been closed + + //First make sure posting has been closed + if ( postings != NULL ){ + postings->close(); + _CLVDELETE(postings); //todo: not a clucene object... should be + } + + if ( termEnum != NULL ){ + termEnum->close(); + _CLDELETE(termEnum); + } + _CLDECDELETE(term); + _CLDELETE_ARRAY(docMap); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.h b/3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.h new file mode 100644 index 0000000..7ffd46a --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentMergeInfo.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_SegmentMergeInfo_ +#define _lucene_index_SegmentMergeInfo_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "SegmentTermEnum.h" +#include "SegmentHeader.h" + +CL_NS_DEF(index) +class SegmentMergeInfo:LUCENE_BASE { + int32_t* docMap; // maps around deleted docs + TermPositions* postings; +public: + TermEnum* termEnum; + Term* term; + int32_t base; + IndexReader* reader; + + //Constructor + SegmentMergeInfo(const int32_t b, TermEnum* te, IndexReader* r); + + //Destructor + ~SegmentMergeInfo(); + + //Moves the current term of the enumeration termEnum to the next and term + //points to this new current term + bool next(); + + //Closes the the resources + void close(); + + // maps around deleted docs + int32_t* getDocMap(); + + TermPositions* getPositions(); +}; +CL_NS_END +#endif + diff --git a/3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.cpp b/3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.cpp new file mode 100644 index 0000000..8797812 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.cpp @@ -0,0 +1,74 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "SegmentMergeQueue.h" + +#include "SegmentMergeInfo.h" +CL_NS_DEF(index) + + + SegmentMergeQueue::SegmentMergeQueue(const int32_t size) { + //Func - Constructor + // Creates a queue of length size + //Pre - size >= 0 + //Post - The queue has been created of length size + + //BVK: bug. changed condition from size > 0 to size >= 0 + //if size is 0, as it is when retrieving a TermEnum + //from an empty index this should this should not fail. + CND_PRECONDITION(size >= 0, "size is too small"); + + //Call the initialize method of its superclass. The boolean value passed here + //indicates that the superclass PriorityQueue takes the responsibility to have its elements deleted + //The destructor of SegmentMergInfo will make sure that each intstance it will be closed properly + //before it is deleted + initialize(size,true); + } + + SegmentMergeQueue::~SegmentMergeQueue(){ + //Func - Destructor + // Does nothing as its parent class will clean up everything + //Pre - true + //Post - true + close(); + } + + void SegmentMergeQueue::close() { + //Func - Closes and destroyes all SegmentMergeInfo Instances in the queue + //Pre - true + //post - All SegmentMergeInfo Instances in the queue have been closed and deleted + // The queue is now empty but can still be used + + //call the clear method of the parent class PriorityQueue + clear(); + } + + bool SegmentMergeQueue::lessThan(SegmentMergeInfo* stiA, SegmentMergeInfo* stiB) { + //Func - Overloaded method that implements the lessThan operator for the parent class + // This method is used by the parent class Priority queue to reorder its internal + // data structures. This implementation check if stiA is less than the current term of stiB. + //Pre - stiA != NULL + // stiB != NULL + //Post - true is returned if stiA < stiB otherwise false + + CND_PRECONDITION(stiA != NULL, "stiA is NULL"); + CND_PRECONDITION(stiB != NULL, "stiB is NULL"); + + //Compare the two terms + int32_t comparison = stiA->term->compareTo(stiB->term); + //Check if they match + if (comparison == 0){ //todo: can we do an optimized compare here? compare using equals, then compare properly? + //If the match check if the base of stiA is smaller than the base of stiB + //Note that different bases means that the terms of stiA an stiB ly in different segments + return stiA->base < stiB->base; + }else{ + //Terms didn't match so return the difference in positions + return comparison < 0; + } + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.h b/3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.h new file mode 100644 index 0000000..faa6902 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentMergeQueue.h @@ -0,0 +1,38 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_SegmentMergeQueue_ +#define _lucene_index_SegmentMergeQueue_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/PriorityQueue.h" +#include "SegmentMergeInfo.h" + +CL_NS_DEF(index) + class SegmentMergeQueue :public CL_NS(util)::PriorityQueue > { + public: + //Constructor + //Creates a queue of length size + SegmentMergeQueue(const int32_t size); + + //Destructor + //Does nothing as its parent class will clean up everything + ~SegmentMergeQueue(); + + //Closes and destroyes all SegmentMergeInfo Instances in the queue + void close(); + protected: + //Overloaded method that implements the lessThan operator for the parent class + //This method is used by the parent class Priority queue to reorder its internal + //data structures. This implementation check if stiA is less than the current term of stiB. + bool lessThan(SegmentMergeInfo* stiA, SegmentMergeInfo* stiB); + + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/index/SegmentMerger.cpp b/3rdparty/clucene/src/CLucene/index/SegmentMerger.cpp new file mode 100644 index 0000000..40814da --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentMerger.cpp @@ -0,0 +1,723 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "SegmentMerger.h" + +CL_NS_USE(util) +CL_NS_USE(document) +CL_NS_USE(store) +CL_NS_DEF(index) + +// File extensions of old-style index files +int COMPOUND_EXTENSIONS_LENGTH = 7; +const char* COMPOUND_EXTENSIONS = "fnm\0" "frq\0" "prx\0" "fdx\0" "fdt\0" "tii\0" "tis\0"; + +int VECTOR_EXTENSIONS_LENGTH = 3; +const char* VECTOR_EXTENSIONS = "tvx\0" "tvd\0" "tvf\0"; + +SegmentMerger::SegmentMerger(IndexWriter* writer, const QString& name) +{ + //Func - Constructor + //Pre - dir holds a valid reference to a Directory + // name != NULL + //Post - Instance has been created + + CND_PRECONDITION(!name.isEmpty(), "name is NULL"); + + freqOutput = NULL; + proxOutput = NULL; + termInfosWriter = NULL; + queue = NULL; + fieldInfos = NULL; + useCompoundFile = writer->getUseCompoundFile(); + skipBuffer = _CLNEW CL_NS(store)::RAMIndexOutput(); + + segment = name; + directory = writer->getDirectory(); + termIndexInterval = writer->getTermIndexInterval(); + + lastSkipDoc=0; + lastSkipFreqPointer=0; + lastSkipProxPointer=0; + skipInterval=0; +} + +SegmentMerger::~SegmentMerger() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + //Clear the readers set + readers.clear(); + + //Delete field Infos + _CLDELETE(fieldInfos); + //Close and destroy the IndexOutput to the Frequency File + if (freqOutput != NULL) { + freqOutput->close(); + _CLDELETE(freqOutput); + } + //Close and destroy the IndexOutput to the Prox File + if (proxOutput != NULL) { + proxOutput->close(); + _CLDELETE(proxOutput); + } + //Close and destroy the termInfosWriter + if (termInfosWriter != NULL) { + termInfosWriter->close(); + _CLDELETE(termInfosWriter); + } + //Close and destroy the queue + if (queue != NULL) { + queue->close(); + _CLDELETE(queue); + } + //close and destory the skipBuffer + if (skipBuffer != NULL) { + skipBuffer->close(); + _CLDELETE(skipBuffer); + } +} + +void SegmentMerger::add(IndexReader* reader) +{ + //Func - Adds a IndexReader to the set of readers + //Pre - reader contains a valid reference to a IndexReader + //Post - The SegementReader reader has been added to the set of readers + + readers.push_back(reader); +} + +IndexReader* SegmentMerger::segmentReader(const int32_t i) +{ + //Func - Returns a reference to the i-th IndexReader + //Pre - 0 <= i < readers.size() + //Post - A reference to the i-th IndexReader has been returned + + CND_PRECONDITION(i >= 0, "i is a negative number"); + CND_PRECONDITION((size_t)i < readers.size(), + "i is bigger than the number of IndexReader instances"); + + //Retrieve the i-th IndexReader + IndexReader* ret = readers[i]; + CND_CONDITION(ret != NULL, "No IndexReader found"); + + return ret; +} + +int32_t SegmentMerger::merge() +{ + int32_t value = mergeFields(); + mergeTerms(); + mergeNorms(); + + if (fieldInfos->hasVectors()) + mergeVectors(); + + return value; +} + +void SegmentMerger::closeReaders() +{ + for (uint32_t i = 0; i < readers.size(); i++) { + // close readers + IndexReader* reader = readers[i]; + reader->close(); + } +} + +void SegmentMerger::createCompoundFile(const QString& filename, QStringList& files) +{ + CompoundFileWriter* cfsWriter = _CLNEW CompoundFileWriter(directory, filename); + + { //msvc6 scope fix + // Basic files + for (int32_t i = 0; i < COMPOUND_EXTENSIONS_LENGTH; i++) { + files.push_back(Misc::qjoin(segment, QLatin1String("."), + QLatin1String(COMPOUND_EXTENSIONS+(i*4)))); + } + } + + { //msvc6 scope fix + // Field norm files + for (int32_t i = 0; i < fieldInfos->size(); i++) { + FieldInfo* fi = fieldInfos->fieldInfo(i); + if (fi->isIndexed && !fi->omitNorms) { + TCHAR tbuf[10]; + char abuf[10]; + _i64tot(i, tbuf, 10); + STRCPY_TtoA(abuf, tbuf, 10); + + files.push_back(Misc::qjoin(segment, QLatin1String(".f"), + QLatin1String(abuf))); + } + } + } + + // Vector files + if (fieldInfos->hasVectors()) { + for (int32_t i = 0; i < VECTOR_EXTENSIONS_LENGTH; i++) { + files.push_back(Misc::qjoin(segment, QLatin1String("."), + QLatin1String(VECTOR_EXTENSIONS+(i*4)))); + } + } + + { //msvc6 scope fix + // Now merge all added files + for (size_t i=0;iaddFile(files[i]); + } + } + + // Perform the merge + cfsWriter->close(); + _CLDELETE(cfsWriter); +} + +void SegmentMerger::addIndexed(IndexReader* reader, FieldInfos* fieldInfos, + StringArrayWithDeletor& names, bool storeTermVectors, + bool storePositionWithTermVector, bool storeOffsetWithTermVector) +{ + StringArrayWithDeletor::const_iterator itr = names.begin(); + while (itr != names.end()) { + fieldInfos->add(*itr, true, + storeTermVectors, storePositionWithTermVector, + storeOffsetWithTermVector, !reader->hasNorms(*itr)); + ++itr; + } +} + +int32_t SegmentMerger::mergeFields() +{ + //Func - Merge the fields of all segments + //Pre - true + //Post - The field infos and field values of all segments have been merged. + + //Create a new FieldInfos + fieldInfos = _CLNEW FieldInfos(); // merge field names + + //Condition check to see if fieldInfos points to a valid instance + CND_CONDITION(fieldInfos != NULL, "Memory allocation for fieldInfos failed"); + + IndexReader* reader = NULL; + + int32_t docCount = 0; + + //Iterate through all readers + for (uint32_t i = 0; i < readers.size(); i++) { + //get the i-th reader + reader = readers[i]; + //Condition check to see if reader points to a valid instance + CND_CONDITION(reader != NULL,"No IndexReader found"); + + StringArrayWithDeletor tmp; + + tmp.clear(); + reader->getFieldNames(IndexReader::TERMVECTOR_WITH_POSITION_OFFSET, tmp); + addIndexed(reader, fieldInfos, tmp, true, true, true); + + tmp.clear(); + reader->getFieldNames(IndexReader::TERMVECTOR_WITH_POSITION, tmp); + addIndexed(reader, fieldInfos, tmp, true, true, false); + + tmp.clear(); + reader->getFieldNames(IndexReader::TERMVECTOR_WITH_OFFSET, tmp); + addIndexed(reader, fieldInfos, tmp, true, false, true); + + tmp.clear(); + reader->getFieldNames(IndexReader::TERMVECTOR, tmp); + addIndexed(reader, fieldInfos, tmp, true, false, false); + + tmp.clear(); + reader->getFieldNames(IndexReader::INDEXED, tmp); + addIndexed(reader, fieldInfos, tmp, false, false, false); + + tmp.clear(); + reader->getFieldNames(IndexReader::UNINDEXED, tmp); + if (tmp.size() > 0) { + TCHAR** arr = _CL_NEWARRAY(TCHAR*,tmp.size()+1); + tmp.toArray(arr); + fieldInfos->add((const TCHAR**)arr, false); + _CLDELETE_ARRAY(arr); + //no need to delete the contents, since tmp is responsible for it + } + } + + //Create the filename of the new FieldInfos file + QString buf = Misc::segmentname(segment, QLatin1String(".fnm")); + //Write the new FieldInfos file to the directory + fieldInfos->write(directory, buf); + + // merge field values + // Instantiate Fieldswriter which will write in directory for the segment + // name segment using the new merged fieldInfos + FieldsWriter* fieldsWriter = _CLNEW FieldsWriter(directory, segment, fieldInfos); + + //Condition check to see if fieldsWriter points to a valid instance + CND_CONDITION(fieldsWriter != NULL, "Memory allocation for fieldsWriter failed"); + + try { + IndexReader* reader = NULL; + int32_t maxDoc = 0; + //Iterate through all readers + for (uint32_t i = 0; i < readers.size(); i++) { + // get the i-th reader + reader = readers[i]; + + + // Condition check to see if reader points to a valid instance + CND_CONDITION(reader != NULL, "No IndexReader found"); + + // Get the total number documents including the documents that have + // been marked deleted + int32_t maxDoc = reader->maxDoc(); + + //document buffer + Document doc; + + //Iterate through all the documents managed by the current reader + for (int32_t j = 0; j < maxDoc; j++) { + //Check if the j-th document has been deleted, if so skip it + if (!reader->isDeleted(j)) { + //Get the document + if (reader->document(j, &doc)) { + //Add the document to the new FieldsWriter + fieldsWriter->addDocument(&doc); + docCount++; + //doc is cleard for re-use + doc.clear(); + } + } + } + } + } _CLFINALLY ( + //Close the fieldsWriter + fieldsWriter->close(); + //And have it deleted as it not used any more + _CLDELETE(fieldsWriter); + ); + + return docCount; +} + +void SegmentMerger::mergeVectors() +{ + TermVectorsWriter* termVectorsWriter = + _CLNEW TermVectorsWriter(directory, segment, fieldInfos); + + try { + for (uint32_t r = 0; r < readers.size(); r++) { + IndexReader* reader = readers[r]; + int32_t maxDoc = reader->maxDoc(); + for (int32_t docNum = 0; docNum < maxDoc; docNum++) { + // skip deleted docs + if (reader->isDeleted(docNum)) + continue; + + Array tmp; + if (reader->getTermFreqVectors(docNum, tmp)) + termVectorsWriter->addAllDocVectors(tmp); + tmp.deleteAll(); + } + } + } _CLFINALLY ( + _CLDELETE(termVectorsWriter); + ); +} + + +void SegmentMerger::mergeTerms() +{ + //Func - Merge the terms of all segments + //Pre - fieldInfos != NULL + //Post - The terms of all segments have been merged + + CND_PRECONDITION(fieldInfos != NULL, "fieldInfos is NULL"); + + try{ + //create a filename for the new Frequency File for segment + QString buf = Misc::segmentname(segment, QLatin1String(".frq")); + //Open an IndexOutput to the new Frequency File + freqOutput = directory->createOutput(buf); + + //create a filename for the new Prox File for segment + buf = Misc::segmentname(segment, QLatin1String(".prx")); + //Open an IndexOutput to the new Prox File + proxOutput = directory->createOutput(buf); + + //Instantiate a new termInfosWriter which will write in directory + //for the segment name segment using the new merged fieldInfos + termInfosWriter = _CLNEW TermInfosWriter(directory, segment, fieldInfos, + termIndexInterval); + + //Condition check to see if termInfosWriter points to a valid instance + CND_CONDITION(termInfosWriter != NULL, + "Memory allocation for termInfosWriter failed"); + + skipInterval = termInfosWriter->skipInterval; + queue = _CLNEW SegmentMergeQueue(readers.size()); + + //And merge the Term Infos + mergeTermInfos(); + } _CLFINALLY ( + //Close and destroy the IndexOutput to the Frequency File + if (freqOutput != NULL) { + freqOutput->close(); _CLDELETE(freqOutput); + } + + //Close and destroy the IndexOutput to the Prox File + if (proxOutput != NULL) + { + proxOutput->close(); + _CLDELETE(proxOutput); + } + + //Close and destroy the termInfosWriter + if (termInfosWriter != NULL) { + termInfosWriter->close(); + _CLDELETE(termInfosWriter); + } + + //Close and destroy the queue + if (queue != NULL) { + queue->close(); + _CLDELETE(queue); + } + ); +} + +void SegmentMerger::mergeTermInfos() +{ + //Func - Merges all TermInfos into a single segment + //Pre - true + //Post - All TermInfos have been merged into a single segment + + //Condition check to see if queue points to a valid instance + CND_CONDITION(queue != NULL, "Memory allocation for queue failed"); + + //base is the id of the first document in a segment + int32_t base = 0; + + IndexReader* reader = NULL; + SegmentMergeInfo* smi = NULL; + + //iterate through all the readers + for (uint32_t i = 0; i < readers.size(); i++) { + //Get the i-th reader + reader = readers[i]; + + //Condition check to see if reader points to a valid instance + CND_CONDITION(reader != NULL, "No IndexReader found"); + + //Get the term enumeration of the reader + TermEnum* termEnum = reader->terms(); + //Instantiate a new SegmentMerginfo for the current reader and enumeration + smi = _CLNEW SegmentMergeInfo(base, termEnum, reader); + + //Condition check to see if smi points to a valid instance + CND_CONDITION(smi != NULL, "Memory allocation for smi failed") ; + + //Increase the base by the number of documents that have not been marked deleted + //so base will contain a new value for the first document of the next iteration + base += reader->numDocs(); + //Get the next current term + if (smi->next()) { + //Store the SegmentMergeInfo smi with the initialized SegmentTermEnum TermEnum + //into the queue + queue->put(smi); + } else { + //Apparently the end of the TermEnum of the SegmentTerm has been reached so + //close the SegmentMergeInfo smi + smi->close(); + //And destroy the instance and set smi to NULL (It will be used later in this method) + _CLDELETE(smi); + } + } + + //Instantiate an array of SegmentMergeInfo instances called match + SegmentMergeInfo** match = _CL_NEWARRAY(SegmentMergeInfo*,readers.size()+1); + + //Condition check to see if match points to a valid instance + CND_CONDITION(match != NULL, "Memory allocation for match failed") ; + + SegmentMergeInfo* top = NULL; + + //As long as there are SegmentMergeInfo instances stored in the queue + while (queue->size() > 0) { + int32_t matchSize = 0; + + // pop matching terms + + //Pop the first SegmentMergeInfo from the queue + match[matchSize++] = queue->pop(); + //Get the Term of match[0] + Term* term = match[0]->term; + + //Condition check to see if term points to a valid instance + CND_CONDITION(term != NULL,"term is NULL") ; + + //Get the current top of the queue + top = queue->top(); + + //For each SegmentMergInfo still in the queue + //Check if term matches the term of the SegmentMergeInfo instances in the queue + while (top != NULL && term->equals(top->term)) { + //A match has been found so add the matching SegmentMergeInfo to the match array + match[matchSize++] = queue->pop(); + //Get the next SegmentMergeInfo + top = queue->top(); + } + match[matchSize]=NULL; + + //add new TermInfo + mergeTermInfo(match); //matchSize + + //Restore the SegmentTermInfo instances in the match array back into the queue + while (matchSize > 0) { + smi = match[--matchSize]; + + //Condition check to see if smi points to a valid instance + CND_CONDITION(smi != NULL, "smi is NULL"); + + //Move to the next term in the enumeration of SegmentMergeInfo smi + if (smi->next()) { + //There still are some terms so restore smi in the queue + queue->put(smi); + + } else { + //Done with a segment + //No terms anymore so close this SegmentMergeInfo instance + smi->close(); + _CLDELETE(smi); + } + } + } + + _CLDELETE_ARRAY(match); +} + +void SegmentMerger::mergeTermInfo(SegmentMergeInfo** smis) +{ + //Func - Merge the TermInfo of a term found in one or more segments. + //Pre - smis != NULL and it contains segments that are positioned at the same term. + // n is equal to the number of SegmentMergeInfo instances in smis + // freqOutput != NULL + // proxOutput != NULL + //Post - The TermInfo of a term has been merged + + CND_PRECONDITION(smis != NULL, "smis is NULL"); + CND_PRECONDITION(freqOutput != NULL, "freqOutput is NULL"); + CND_PRECONDITION(proxOutput != NULL, "proxOutput is NULL"); + + //Get the file pointer of the IndexOutput to the Frequency File + int64_t freqPointer = freqOutput->getFilePointer(); + //Get the file pointer of the IndexOutput to the Prox File + int64_t proxPointer = proxOutput->getFilePointer(); + + //Process postings from multiple segments all positioned on the same term. + int32_t df = appendPostings(smis); + + int64_t skipPointer = writeSkip(); + + //df contains the number of documents across all segments where this term was found + if (df > 0) { + //add an entry to the dictionary with pointers to prox and freq files + termInfo.set(df, freqPointer, proxPointer, (int32_t)(skipPointer - freqPointer)); + //Precondition check for to be sure that the reference to + //smis[0]->term will be valid + CND_PRECONDITION(smis[0]->term != NULL, "smis[0]->term is NULL"); + //Write a new TermInfo + termInfosWriter->add(smis[0]->term, &termInfo); + } +} + + +int32_t SegmentMerger::appendPostings(SegmentMergeInfo** smis) +{ + //Func - Process postings from multiple segments all positioned on the + // same term. Writes out merged entries into freqOutput and + // the proxOutput streams. + //Pre - smis != NULL and it contains segments that are positioned at the same term. + // n is equal to the number of SegmentMergeInfo instances in smis + // freqOutput != NULL + // proxOutput != NULL + //Post - Returns number of documents across all segments where this term was found + + CND_PRECONDITION(smis != NULL, "smis is NULL"); + CND_PRECONDITION(freqOutput != NULL, "freqOutput is NULL"); + CND_PRECONDITION(proxOutput != NULL, "proxOutput is NULL"); + + int32_t lastDoc = 0; + int32_t df = 0; //Document Counter + + resetSkip(); + SegmentMergeInfo* smi = NULL; + + //Iterate through all SegmentMergeInfo instances in smis + int32_t i = 0; + while ((smi=smis[i]) != NULL) { + //Get the i-th SegmentMergeInfo + + //Condition check to see if smi points to a valid instance + CND_PRECONDITION(smi != NULL, " is NULL"); + + //Get the term positions + TermPositions* postings = smi->getPositions(); + //Get the base of this segment + int32_t base = smi->base; + //Get the docMap so we can see which documents have been deleted + int32_t* docMap = smi->getDocMap(); + //Seek the termpost + postings->seek(smi->termEnum); + while (postings->next()) { + int32_t doc = postings->doc(); + //Check if there are deletions + if (docMap != NULL) + doc = docMap[doc]; // map around deletions + doc += base; // convert to merged space + + //Condition check to see doc is eaqual to or bigger than lastDoc + CND_CONDITION(doc >= lastDoc,"docs out of order"); + + //Increase the total frequency over all segments + df++; + + if ((df % skipInterval) == 0) { + bufferSkip(lastDoc); + } + + //Calculate a new docCode + //use low bit to flag freq=1 + int32_t docCode = (doc - lastDoc) << 1; + lastDoc = doc; + + //Get the frequency of the Term + int32_t freq = postings->freq(); + if (freq == 1) { + //write doc & freq=1 + freqOutput->writeVInt(docCode | 1); + } else { + //write doc + freqOutput->writeVInt(docCode); + //write frequency in doc + freqOutput->writeVInt(freq); + } + + int32_t lastPosition = 0; + // write position deltas + for (int32_t j = 0; j < freq; j++) { + //Get the next position + int32_t position = postings->nextPosition(); + //Write the difference between position and the last position + proxOutput->writeVInt(position - lastPosition); + lastPosition = position; + } + } + + i++; + } + + //Return total number of documents across all segments where term was found + return df; +} + +void SegmentMerger::resetSkip() +{ + skipBuffer->reset(); + lastSkipDoc = 0; + lastSkipFreqPointer = freqOutput->getFilePointer(); + lastSkipProxPointer = proxOutput->getFilePointer(); +} + +void SegmentMerger::bufferSkip(int32_t doc) +{ + int64_t freqPointer = freqOutput->getFilePointer(); + int64_t proxPointer = proxOutput->getFilePointer(); + + skipBuffer->writeVInt(doc - lastSkipDoc); + skipBuffer->writeVInt((int32_t) (freqPointer - lastSkipFreqPointer)); + skipBuffer->writeVInt((int32_t) (proxPointer - lastSkipProxPointer)); + + lastSkipDoc = doc; + lastSkipFreqPointer = freqPointer; + lastSkipProxPointer = proxPointer; +} + +int64_t SegmentMerger::writeSkip() +{ + int64_t skipPointer = freqOutput->getFilePointer(); + skipBuffer->writeTo(freqOutput); + return skipPointer; +} + +// Func - Merges the norms for all fields +// Pre - fieldInfos != NULL +// Post - The norms for all fields have been merged +void SegmentMerger::mergeNorms() +{ + CND_PRECONDITION(fieldInfos != NULL, "fieldInfos is NULL"); + + //iterate through all the Field Infos instances + for (int32_t i = 0; i < fieldInfos->size(); i++) { + //Get the i-th FieldInfo + FieldInfo* fi = fieldInfos->fieldInfo(i); + //Is this Field indexed? + if (fi->isIndexed && !fi->omitNorms) { + //Create and Instantiate an IndexOutput to that norm file + QString buf = Misc::segmentname(segment, QLatin1String(".f"), i); + IndexOutput* output = directory->createOutput(buf); + + //Condition check to see if output points to a valid instance + CND_CONDITION(output != NULL, "No Outputstream retrieved"); + + uint8_t* input = NULL; + try { + for (uint32_t j = 0; j < readers.size(); ++j) { + // get the next index reader + condition check + IndexReader* reader = readers[j]; + CND_CONDITION(reader != NULL, "No reader found"); + + // Get the total number of documents including the documents + // that have been marked deleted + int32_t maxDoc = reader->maxDoc(); + if (maxDoc > 0) { + // if there are docs, allocate buffer to read it's norms + uint8_t* data = (uint8_t*)realloc(input, maxDoc * + sizeof(uint8_t)); + if (data) { + input = data; + memset(input, 0, maxDoc * sizeof(uint8_t)); + // Get an IndexInput to the norm file for this + // field in this segment + reader->norms(fi->name, input); + + //Iterate through all the documents + for(int32_t k = 0; k < maxDoc; k++) { + //Check if document k is deleted + if (!reader->isDeleted(k)) { + //write the new norm + output->writeByte(input[k]); + } + } + } + } + } + } _CLFINALLY ( + if (output != NULL) { + output->close(); + _CLDELETE(output); + } + free(input); + ); + } + } +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentMerger.h b/3rdparty/clucene/src/CLucene/index/SegmentMerger.h new file mode 100644 index 0000000..230843b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentMerger.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_SegmentMerger_ +#define _lucene_index_SegmentMerger_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include "CLucene/store/Directory.h" +#include "CLucene/store/RAMDirectory.h" +#include "CLucene/util/VoidList.h" +#include "SegmentMergeInfo.h" +#include "SegmentMergeQueue.h" +#include "IndexWriter.h" +#include "FieldInfos.h" +#include "FieldsWriter.h" +#include "TermInfosWriter.h" + +CL_NS_DEF(index) + +/** +* The SegmentMerger class combines two or more Segments, represented by an IndexReader ({@link #add}, +* into a single Segment. After adding the appropriate readers, call the merge method to combine the +* segments. +*

+* If the compoundFile flag is set, then the segments will be merged into a compound file. +* +* +* @see #merge +* @see #add +*/ +class SegmentMerger : LUCENE_BASE +{ + bool useCompoundFile; + + CL_NS(store)::RAMIndexOutput* skipBuffer; + int32_t lastSkipDoc; + int64_t lastSkipFreqPointer; + int64_t lastSkipProxPointer; + + void resetSkip(); + void bufferSkip(int32_t doc); + int64_t writeSkip(); + + //Directory of the segment + CL_NS(store)::Directory* directory; + //name of the new segment + QString segment; + //Set of IndexReaders + CL_NS(util)::CLVector > readers; + //Field Infos for t he FieldInfo instances of all fields + FieldInfos* fieldInfos; + + //The queue that holds SegmentMergeInfo instances + SegmentMergeQueue* queue; + //IndexOutput to the new Frequency File + CL_NS(store)::IndexOutput* freqOutput; + //IndexOutput to the new Prox File + CL_NS(store)::IndexOutput* proxOutput; + //Writes Terminfos that have been merged + TermInfosWriter* termInfosWriter; + TermInfo termInfo; //(new) minimize consing + + int32_t termIndexInterval; + int32_t skipInterval; + +public: + /** + * + * @param dir The Directory to merge the other segments into + * @param name The name of the new segment + * @param compoundFile true if the new segment should use a compoundFile + */ + SegmentMerger( IndexWriter* writer, const QString& name ); + + //Destructor + ~SegmentMerger(); + + /** + * Add an IndexReader to the collection of readers that are to be merged + * @param reader + */ + void add(IndexReader* reader); + + /** + * + * @param i The index of the reader to return + * @return The ith reader to be merged + */ + IndexReader* segmentReader(const int32_t i); + + /** + * Merges the readers specified by the {@link #add} method into the + * directory passed to the constructor + * @return The number of documents that were merged + * @throws IOException + */ + int32_t merge(); + /** + * close all IndexReaders that have been added. + * Should not be called before merge(). + * @throws IOException + */ + void closeReaders(); +private: + void addIndexed(IndexReader* reader, FieldInfos* fieldInfos, + CL_NS(util)::StringArrayWithDeletor& names, + bool storeTermVectors, bool storePositionWithTermVector, + bool storeOffsetWithTermVector); + + /** + * Merge the fields of all segments + * @return The number of documents in all of the readers + * @throws IOException + */ + int32_t mergeFields(); + + /** + * Merge the TermVectors from each of the segments into the new one. + * @throws IOException + */ + void mergeVectors(); + + /** Merge the terms of all segments */ + void mergeTerms(); + + /** Merges all TermInfos into a single segment */ + void mergeTermInfos(); + + /** Merge one term found in one or more segments. The array smis + * contains segments that are positioned at the same term. N + * is the number of cells in the array actually occupied. + * + * @param smis array of segments + * @param n number of cells in the array actually occupied + */ + void mergeTermInfo( SegmentMergeInfo** smis); + + /** Process postings from multiple segments all positioned on the + * same term. Writes out merged entries into freqOutput and + * the proxOutput streams. + * + * @param smis array of segments + * @param n number of cells in the array actually occupied + * @return number of documents across all segments where this term was found + */ + int32_t appendPostings(SegmentMergeInfo** smis); + + //Merges the norms for all fields + void mergeNorms(); + + void createCompoundFile(const QString& filename, QStringList& files); + friend class IndexWriter; //allow IndexWriter to use createCompoundFile +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/SegmentReader.cpp b/3rdparty/clucene/src/CLucene/index/SegmentReader.cpp new file mode 100644 index 0000000..ba06171 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentReader.cpp @@ -0,0 +1,816 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#include "CLucene/StdHeader.h" +#include "SegmentHeader.h" + +#include "FieldInfos.h" +#include "FieldsReader.h" +#include "IndexReader.h" +#include "TermInfosReader.h" +#include "Terms.h" +#include "CLucene/search/Similarity.h" + +CL_NS_USE(util) +CL_NS_USE(store) +CL_NS_USE(document) +CL_NS_USE(search) +CL_NS_DEF(index) + +SegmentReader::Norm::Norm(IndexInput* instrm, int32_t n, SegmentReader* r, + const QString& seg) + : number(n) + , reader(r) + , segment(seg) + , in(instrm) + , bytes(NULL) + , dirty(false) +{ + //Func - Constructor + //Pre - instrm is a valid reference to an IndexInput + //Post - A Norm instance has been created with an empty bytes array + bytes = NULL; + dirty = false; +} + +SegmentReader::Norm::~Norm() +{ + //Func - Destructor + //Pre - true + //Post - The IndexInput in has been deleted (and closed by its destructor) + // and the array too. + + //Close and destroy the inputstream in-> The inputstream will be closed + // by its destructor. Note that the IndexInput 'in' actually is a pointer!!!!! + _CLDELETE(in); + + //Delete the bytes array + _CLDELETE_ARRAY(bytes); + +} + +void SegmentReader::Norm::reWrite() +{ + QString buf(segment + QLatin1String(".tmp")); + + // NOTE: norms are re-written in regular directory, not cfs + IndexOutput* out = reader->getDirectory()->createOutput(buf); + try { + out->writeBytes(bytes, reader->maxDoc()); + } _CLFINALLY ( + out->close(); + _CLDELETE(out) + ); + + QString fileName(segment); + if (reader->cfsReader == NULL) + fileName.append(QLatin1String(".f%1")).arg(number); + else // use a different file name if we have compound format + fileName.append(QLatin1String(".s%1")).arg(number); + + reader->getDirectory()->renameFile(buf, fileName); + this->dirty = false; +} + +SegmentReader::SegmentReader(SegmentInfo* si) + : IndexReader(si->getDir()) + , _norms(false, false) +{ + initialize(si); +} + +SegmentReader::SegmentReader(SegmentInfos* sis, SegmentInfo* si) + : IndexReader(si->getDir(), sis, false) + , _norms(false, false) +{ + initialize(si); +} + +void SegmentReader::initialize(SegmentInfo* si) +{ + //Pre - si-> is a valid reference to SegmentInfo instance + // identified by si-> + //Post - All files of the segment have been read + + deletedDocs = NULL; + ones = NULL; + //There are no documents yet marked as deleted + deletedDocsDirty = false; + + normsDirty=false; + undeleteAll=false; + + //Duplicate the name of the segment from SegmentInfo to segment + segment = si->name; + // make sure that all index files have been read or are kept open + // so that if an index update removes them we'll still have them + freqStream = NULL; + proxStream = NULL; + + //instantiate a buffer large enough to hold a directory path + QString buf; + + // Use compound file directory for some files, if it exists + Directory* cfsDir = getDirectory(); + SegmentName(buf, CL_MAX_PATH, QLatin1String(".cfs")); + if (cfsDir->fileExists(buf)) { + cfsReader = _CLNEW CompoundFileReader(cfsDir, buf); + cfsDir = cfsReader; + }else + cfsReader = NULL; + + // Create the name of the field info file with suffix .fnm in buf + SegmentName(buf, CL_MAX_PATH, QLatin1String(".fnm")); + fieldInfos = _CLNEW FieldInfos(cfsDir, buf ); + + // Condition check to see if fieldInfos points to a valid instance + CND_CONDITION(fieldInfos != NULL, + "No memory could be allocated for fieldInfos"); + + // Create the name of the frequence file with suffix .frq in buf + SegmentName(buf ,CL_MAX_PATH, QLatin1String(".frq")); + + // Open an IndexInput freqStream to the frequency file + freqStream = cfsDir->openInput( buf ); + + // Condition check to see if freqStream points to a valid instance and was + // able to open the frequency file + CND_CONDITION(freqStream != NULL, + "IndexInput freqStream could not open the frequency file"); + + // Create the name of the prox file with suffix .prx in buf + SegmentName(buf, CL_MAX_PATH, QLatin1String(".prx")); + + // Open an IndexInput proxStream to the prox file + proxStream = cfsDir->openInput( buf ); + + // Condition check to see if proxStream points to a valid instance and was + // able to open the prox file + CND_CONDITION(proxStream != NULL, + "IndexInput proxStream could not open proximity file"); + + // Instantiate a FieldsReader for reading the Field Info File + fieldsReader = _CLNEW FieldsReader(cfsDir, segment, fieldInfos); + + // Condition check to see if fieldsReader points to a valid instance + CND_CONDITION(fieldsReader != NULL, + "No memory could be allocated for fieldsReader"); + + //Instantiate a TermInfosReader for reading the Term Dictionary .tis file + tis = _CLNEW TermInfosReader(cfsDir, segment, fieldInfos); + + //Condition check to see if tis points to a valid instance + CND_CONDITION(tis != NULL,"No memory could be allocated for tis"); + + // Check if the segment has deletion according to the SegmentInfo instance + // si-> NOTE: the bitvector is stored using the regular directory, not cfs + if (hasDeletions(si)) { + //Create a deletion file with suffix .del + SegmentName(buf, CL_MAX_PATH, QLatin1String(".del")); + // Instantiate a BitVector that manages which documents have been deleted + deletedDocs = _CLNEW BitSet(getDirectory(), buf); + } + + // Open the norm file. There's a norm file for each indexed field with a + // byte for each document. The .f[0-9]* file contains, for each document, + // a byte that encodes a value that is multiplied into the score for hits + // on that field + openNorms(cfsDir); + + termVectorsReaderOrig = NULL; + if (fieldInfos->hasVectors()) // open term vector files only as needed + termVectorsReaderOrig = _CLNEW TermVectorsReader(cfsDir, segment, fieldInfos); +} + +SegmentReader::~SegmentReader() +{ + //Func - Destructor. + //Pre - doClose has been invoked! + //Post - the instance has been destroyed + + doClose(); //this means that index reader doesn't need to be closed manually + + _CLDELETE(fieldInfos); + _CLDELETE(fieldsReader); + _CLDELETE(tis); + _CLDELETE(freqStream); + _CLDELETE(proxStream); + _CLDELETE(deletedDocs); + _CLDELETE_ARRAY(ones); + _CLDELETE(termVectorsReaderOrig); + _CLDECDELETE(cfsReader); +} + +void SegmentReader::doCommit() +{ + QString bufdel(segment + QLatin1String(".del")); + + if (deletedDocsDirty) { // re-write deleted + QString buftmp(segment + QLatin1String(".tmp")); + deletedDocs->write(getDirectory(), buftmp); + getDirectory()->renameFile(buftmp, bufdel); + } + + if(undeleteAll && getDirectory()->fileExists(bufdel)) + getDirectory()->deleteFile(bufdel, true); + + if (normsDirty) { // re-write norms + NormsType::iterator itr = _norms.begin(); + while (itr != _norms.end()) { + Norm* norm = itr->second; + if (norm->dirty) { + norm->reWrite(); + } + ++itr; + } + } + deletedDocsDirty = false; + normsDirty = false; + undeleteAll = false; +} + +void SegmentReader::doClose() +{ + //Func - Closes all streams to the files of a single segment + //Pre - fieldsReader != NULL + // tis != NULL + //Post - All streams to files have been closed + + CND_PRECONDITION(fieldsReader != NULL, "fieldsReader is NULL"); + CND_PRECONDITION(tis != NULL, "tis is NULL"); + + //Close the fieldsReader + fieldsReader->close(); + //Close the TermInfosReader + tis->close(); + + //Close the frequency stream + if (freqStream != NULL){ + freqStream->close(); + } + //Close the prox stream + if (proxStream != NULL){ + proxStream->close(); + } + + //Close the norm file + closeNorms(); + + if (termVectorsReaderOrig != NULL) + termVectorsReaderOrig->close(); + + if (cfsReader != NULL) + cfsReader->close(); +} + +bool SegmentReader::hasDeletions() const +{ + return deletedDocs != NULL; +} + +//static +bool SegmentReader::usesCompoundFile(SegmentInfo* si) +{ + return si->getDir()->fileExists(si->name + QLatin1String(".cfs")); +} + +//static +bool SegmentReader::hasSeparateNorms(SegmentInfo* si) +{ + QString pattern(si->name); + pattern.append(QLatin1String(".s")); + size_t patternLength = pattern.length(); + + QStringList names = si->getDir()->list(); + foreach (const QString& name, names) { + int length = name.length(); + if (length > patternLength && name.left(patternLength) == pattern) { + if (name.at(patternLength) >= QLatin1Char('0') + && name.at(patternLength) <= QLatin1Char('9')) { + return true; + } + } + } + return false; +} + +bool SegmentReader::hasDeletions(const SegmentInfo* si) +{ + //Func - Static method + // Checks if a segment managed by SegmentInfo si-> has deletions + //Pre - si-> holds a valid reference to an SegmentInfo instance + //Post - if the segement contains deleteions true is returned otherwise flas + + //Check if the deletion file exists and return the result + QString f; + Misc::segmentname(f, CL_MAX_PATH, si->name, QLatin1String(".del"), -1); + return si->getDir()->fileExists(f); +} + +//synchronized +void SegmentReader::doDelete(const int32_t docNum) +{ + //Func - Marks document docNum as deleted + //Pre - docNum >=0 and DocNum < maxDoc() + // docNum contains the number of the document that must be + // marked deleted + //Post - The document identified by docNum has been marked deleted + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + CND_PRECONDITION(docNum >= 0, "docNum is a negative number"); + CND_PRECONDITION(docNum < maxDoc(), + "docNum is bigger than the total number of documents"); + + //Check if deletedDocs exists + if (deletedDocs == NULL) { + deletedDocs = _CLNEW BitSet(maxDoc()); + + //Condition check to see if deletedDocs points to a valid instance + CND_CONDITION(deletedDocs != NULL, + "No memory could be allocated for deletedDocs"); + } + //Flag that there are documents marked deleted + deletedDocsDirty = true; + undeleteAll = false; + //Mark document identified by docNum as deleted + deletedDocs->set(docNum); + +} + +void SegmentReader::doUndeleteAll() +{ + _CLDELETE(deletedDocs); + deletedDocsDirty = false; + undeleteAll = true; +} + +void SegmentReader::files(QStringList& retarray) +{ + //Func - Returns all file names managed by this SegmentReader + //Pre - segment != NULL + //Post - All filenames managed by this SegmentRead have been returned + + CND_PRECONDITION(segment != NULL, "segment is NULL"); + + QString temp; + #define _ADD_SEGMENT(ext) \ + temp = SegmentName(ext); \ + if (getDirectory()->fileExists(temp)) \ + retarray.push_back(temp); + + //Add the name of the Field Info file + _ADD_SEGMENT(QLatin1String(".cfs")); + _ADD_SEGMENT(QLatin1String(".fnm")); + _ADD_SEGMENT(QLatin1String(".fdx")); + _ADD_SEGMENT(QLatin1String(".fdt")); + _ADD_SEGMENT(QLatin1String(".tii")); + _ADD_SEGMENT(QLatin1String(".tis")); + _ADD_SEGMENT(QLatin1String(".frq")); + _ADD_SEGMENT(QLatin1String(".prx")); + _ADD_SEGMENT(QLatin1String(".del")); + _ADD_SEGMENT(QLatin1String(".tvx")); + _ADD_SEGMENT(QLatin1String(".tvd")); + _ADD_SEGMENT(QLatin1String(".tvf")); + _ADD_SEGMENT(QLatin1String(".tvp")); + + //iterate through the field infos + for (int32_t i = 0; i < fieldInfos->size(); ++i) { + //Get the field info for the i-th field + FieldInfo* fi = fieldInfos->fieldInfo(i); + //Check if the field has been indexed + if (fi->isIndexed && !fi->omitNorms) { + QString name; + if (cfsReader == NULL) + name = SegmentName(QLatin1String(".f"), i); + else + name = SegmentName(QLatin1String(".s"), i); + + //The field has been indexed so add its norm file + if (getDirectory()->fileExists(name)) + retarray.push_back(name); + } + } +} + +TermEnum* SegmentReader::terms() const +{ + //Func - Returns an enumeration of all the Terms and TermInfos in the set. + //Pre - tis != NULL + //Post - An enumeration of all the Terms and TermInfos in the set has been returned + + CND_PRECONDITION(tis != NULL, "tis is NULL"); + + return tis->terms(); +} + +TermEnum* SegmentReader::terms(const Term* t) const +{ + //Func - Returns an enumeration of terms starting at or after the named term t + //Pre - t != NULL + // tis != NULL + //Post - An enumeration of terms starting at or after the named term t + + CND_PRECONDITION(t != NULL, "t is NULL"); + CND_PRECONDITION(tis != NULL, "tis is NULL"); + + return tis->terms(t); +} + +bool SegmentReader::document(int32_t n, Document* doc) +{ + //Func - Returns a document identified by n + //Pre - n >=0 and identifies the document n + //Post - if the document has been deleted then an exception has been thrown + // otherwise a reference to the found document has been returned + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + CND_PRECONDITION(n >= 0, "n is a negative number"); + + //Check if the n-th document has been marked deleted + if (isDeleted(n)) + _CLTHROWA(CL_ERR_InvalidState, "attempt to access a deleted document" ); + + //Retrieve the n-th document + return fieldsReader->doc(n, doc); +} + +bool SegmentReader::isDeleted(const int32_t n) +{ + //Func - Checks if the n-th document has been marked deleted + //Pre - n >=0 and identifies the document n + //Post - true has been returned if document n has been deleted otherwise fralse + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + CND_PRECONDITION(n >= 0, "n is a negative number"); + + //Is document n deleted + return (deletedDocs != NULL && deletedDocs->get(n)); +} + +TermDocs* SegmentReader::termDocs() const +{ + //Func - Returns an unpositioned TermDocs enumerator. + //Pre - true + //Post - An unpositioned TermDocs enumerator has been returned + + return _CLNEW SegmentTermDocs(this); +} + +TermPositions* SegmentReader::termPositions() const +{ + //Func - Returns an unpositioned TermPositions enumerator. + //Pre - true + //Post - An unpositioned TermPositions enumerator has been returned + + return _CLNEW SegmentTermPositions(this); +} + +int32_t SegmentReader::docFreq(const Term* t) const +{ + //Func - Returns the number of documents which contain the term t + //Pre - t holds a valid reference to a Term + //Post - The number of documents which contain term t has been returned + + //Get the TermInfo ti for Term t in the set + TermInfo* ti = tis->get(t); + //Check if an TermInfo has been returned + if (ti) { + //Get the frequency of the term + int32_t ret = ti->docFreq; + //TermInfo ti is not needed anymore so delete it + _CLDELETE( ti ); + //return the number of documents which containt term t + return ret; + } + + //No TermInfo returned so return 0 + return 0; +} + +int32_t SegmentReader::numDocs() +{ + //Func - Returns the actual number of documents in the segment + //Pre - true + //Post - The actual number of documents in the segments + + //Get the number of all the documents in the segment including the ones that have + //been marked deleted + int32_t n = maxDoc(); + + //Check if there any deleted docs + if (deletedDocs != NULL) + //Substract the number of deleted docs from the number returned by maxDoc + n -= deletedDocs->count(); + + //return the actual number of documents in the segment + return n; +} + +int32_t SegmentReader::maxDoc() const +{ + //Func - Returns the number of all the documents in the segment including + // the ones that have been marked deleted + //Pre - true + //Post - The total number of documents in the segment has been returned + + return fieldsReader->size(); +} + +void SegmentReader::getFieldNames(FieldOption fldOption, + StringArrayWithDeletor& retarray) +{ + size_t len = fieldInfos->size(); + for (size_t i = 0; i < len; i++) { + bool v = false; + FieldInfo* fi = fieldInfos->fieldInfo(i); + if (fldOption & IndexReader::ALL) { + v = true; + } else { + if (!fi->isIndexed && (fldOption & IndexReader::UNINDEXED)) { + v = true; + } + + if (fi->isIndexed && (fldOption & IndexReader::INDEXED)) { + v = true; + } + + if (fi->isIndexed && fi->storeTermVector == false + && (fldOption & IndexReader::INDEXED_NO_TERMVECTOR)) { + v = true; + } + + if ((fldOption & IndexReader::TERMVECTOR) + && fi->storeTermVector == true + && fi->storePositionWithTermVector == false + && fi->storeOffsetWithTermVector == false) { + v = true; + } + + if (fi->isIndexed && fi->storeTermVector + && (fldOption & IndexReader::INDEXED_WITH_TERMVECTOR)) { + v = true; + } + + if (fi->storePositionWithTermVector + && fi->storeOffsetWithTermVector == false + && (fldOption & IndexReader::TERMVECTOR_WITH_POSITION)) { + v = true; + } + + if (fi->storeOffsetWithTermVector + && fi->storePositionWithTermVector == false + && (fldOption & IndexReader::TERMVECTOR_WITH_OFFSET)) { + v = true; + } + + if ((fi->storeOffsetWithTermVector && fi->storePositionWithTermVector) + && (fldOption & IndexReader::TERMVECTOR_WITH_POSITION_OFFSET)) { + v = true; + } + } + + if (v) + retarray.push_back(STRDUP_TtoT(fi->name)); + } +} + +bool SegmentReader::hasNorms(const TCHAR* field) const +{ + return _norms.find(field) != _norms.end(); +} + + +void SegmentReader::norms(const TCHAR* field, uint8_t* bytes) +{ + //Func - Reads the Norms for field from disk starting at offset in the inputstream + //Pre - field != NULL + // bytes != NULL is an array of bytes which is to be used to read the norms into. + // it is advisable to have bytes initalized by zeroes! + //Post - The if an inputstream to the norm file could be retrieved the bytes have been read + // You are never sure whether or not the norms have been read into bytes properly!!!!!!!!!!!!!!!!! + + CND_PRECONDITION(field != NULL, "field is NULL"); + CND_PRECONDITION(bytes != NULL, "field is NULL"); + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + Norm* norm = _norms.get(field); + if ( norm == NULL ){ + memcpy(bytes, fakeNorms(), maxDoc()); + return; + } + + if (norm->bytes != NULL) { // can copy from cache + memcpy(bytes, norm->bytes, maxDoc()); + return; + } + + IndexInput* _normStream = norm->in->clone(); + CND_PRECONDITION(_normStream != NULL, "normStream==NULL") + + // read from disk + try { + _normStream->seek(0); + _normStream->readBytes(bytes, maxDoc()); + } _CLFINALLY ( + //Have the normstream closed + _normStream->close(); + //Destroy the normstream + _CLDELETE( _normStream ); + ); +} + +uint8_t* SegmentReader::createFakeNorms(int32_t size) +{ + uint8_t* ones = _CL_NEWARRAY(uint8_t,size); + memset(ones, DefaultSimilarity::encodeNorm(1.0f), size); + return ones; +} + +uint8_t* SegmentReader::fakeNorms() +{ + if (ones == NULL) + ones = createFakeNorms(maxDoc()); + return ones; +} + +// can return null if norms aren't stored +uint8_t* SegmentReader::getNorms(const TCHAR* field) +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + Norm* norm = _norms.get(field); + if (norm == NULL) + return NULL; // not indexed, or norms not stored + + if (norm->bytes == NULL) { // value not yet read + uint8_t* bytes = _CL_NEWARRAY(uint8_t, maxDoc()); + norms(field, bytes); + norm->bytes = bytes; // cache it + } + return norm->bytes; +} + +uint8_t* SegmentReader::norms(const TCHAR* field) +{ + //Func - Returns the bytes array that holds the norms of a named field + //Pre - field != NULL and contains the name of the field for which the norms + // must be retrieved + //Post - If there was norm for the named field then a bytes array has been allocated + // and returned containing the norms for that field. If the named field is unknown NULL is returned. + + CND_PRECONDITION(field != NULL, "field is NULL"); + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + uint8_t* bytes = getNorms(field); + if (bytes == NULL) + bytes = fakeNorms(); + return bytes; +} + +void SegmentReader::doSetNorm(int32_t doc, const TCHAR* field, uint8_t value) +{ + Norm* norm = _norms.get(field); + if (norm == NULL) // not an indexed field + return; + + norm->dirty = true; // mark it dirty + normsDirty = true; + + uint8_t* bits = norms(field); + bits[doc] = value; // set the value +} + +QString SegmentReader::SegmentName(const QString& ext, const int32_t x) +{ + //Func - Returns an allocated buffer in which it creates a filename by + // concatenating segment with ext and x + //Pre ext != NULL and holds the extension + // x contains a number + //Post - A buffer has been instantiated an when x = -1 buffer contains the concatenation of + // segment and ext otherwise buffer contains the contentation of segment, ext and x + + CND_PRECONDITION(!ext.isEmpty(), "ext is NULL"); + + QString buf; + SegmentName(buf, CL_MAX_PATH, ext, x); + return buf; +} + +void SegmentReader::SegmentName(QString& buffer, int32_t bufferLen, + const QString& ext, const int32_t x) +{ + //Func - Creates a filename in buffer by concatenating segment with ext and x + //Pre - buffer != NULL + // ext != NULL + // x contains a number + //Post - When x = -1 buffer contains the concatenation of segment and ext otherwise + // buffer contains the contentation of segment, ext and x + + CND_PRECONDITION(!segment.isEmpty(), "Segment is NULL"); + + Misc::segmentname(buffer, bufferLen, segment, ext, x); +} + +void SegmentReader::openNorms(Directory* cfsDir) +{ + //Func - Open all norms files for all fields + // Creates for each field a norm Instance with an open inputstream to + // a corresponding norm file ready to be read + //Pre - true + //Post - For each field a norm instance has been created with an open inputstream to + // a corresponding norm file ready to be read + + //Iterate through all the fields + for (int32_t i = 0; i < fieldInfos->size(); i++) { + //Get the FieldInfo for the i-th field + FieldInfo* fi = fieldInfos->fieldInfo(i); + //Check if the field is indexed + if (fi->isIndexed && !fi->omitNorms ) { + //Allocate a buffer + QString fileName; + + // look first if there are separate norms in compound format + SegmentName(fileName, CL_MAX_PATH, QLatin1String(".s"), fi->number); + Directory* d = getDirectory(); + if(!d->fileExists(fileName)){ + SegmentName(fileName, CL_MAX_PATH, QLatin1String(".f"), fi->number); + d = cfsDir; + } + + _norms.put(fi->name, _CLNEW Norm(d->openInput(fileName), + fi->number, this, segment)); + } + } +} + +void SegmentReader::closeNorms() +{ + //Func - Close all the norms stored in norms + //Pre - true + //Post - All the norms have been destroyed + + SCOPED_LOCK_MUTEX(_norms.THIS_LOCK) + + //Create an interator initialized at the beginning of norms + NormsType::iterator itr = _norms.begin(); + //Iterate through all the norms + while (itr != _norms.end()) { + // Get, delete the norm + _CLDELETE(itr->second); + // Move the interator to the next norm in the norms collection. + // Note ++ is an overloaded operator + ++itr; + } + _norms.clear(); //bvk: they're deleted, so clear them so that they are not re-used +} + +TermVectorsReader* SegmentReader::getTermVectorsReader() +{ + TermVectorsReader* tvReader = termVectorsLocal.get(); + if (tvReader == NULL) { + tvReader = termVectorsReaderOrig->clone(); + termVectorsLocal.set(tvReader); + } + return tvReader; +} + +TermFreqVector* SegmentReader::getTermFreqVector(int32_t docNumber, + const TCHAR* field) +{ + if (field) { + FieldInfo* fi = fieldInfos->fieldInfo(field); + // Check if this field is invalid or has no stored term vector + if (fi == NULL || !fi->storeTermVector || termVectorsReaderOrig == NULL) + return NULL; + } + + TermVectorsReader* termVectorsReader = getTermVectorsReader(); + if (termVectorsReader == NULL) + return NULL; + + return termVectorsReader->get(docNumber, field); +} + +bool SegmentReader::getTermFreqVectors(int32_t docNumber, + Array& result) +{ + if (termVectorsReaderOrig == NULL) + return false; + + TermVectorsReader* termVectorsReader = getTermVectorsReader(); + if (termVectorsReader == NULL) + return false; + + return termVectorsReader->get(docNumber, result); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentTermDocs.cpp b/3rdparty/clucene/src/CLucene/index/SegmentTermDocs.cpp new file mode 100644 index 0000000..50951e9 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentTermDocs.cpp @@ -0,0 +1,216 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "SegmentHeader.h" + +#include "CLucene/store/IndexInput.h" +#include "Term.h" + +CL_NS_DEF(index) + + SegmentTermDocs::SegmentTermDocs(const SegmentReader* _parent){ + //Func - Constructor + //Pre - Paren != NULL + //Post - The instance has been created + + CND_PRECONDITION(_parent != NULL,"Parent is NULL"); + + parent = _parent; + deletedDocs = parent->deletedDocs; + + _doc = 0; + _freq = 0; + count = 0; + df = 0; + + skipInterval=0; + numSkips=0; + skipCount=0; + skipStream=NULL; + skipDoc=0; + freqPointer=0; + proxPointer=0; + skipPointer=0; + haveSkipped=false; + + freqStream = parent->freqStream->clone(); + skipInterval = parent->tis->getSkipInterval(); + } + + SegmentTermDocs::~SegmentTermDocs() { + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + close(); + } + + TermPositions* SegmentTermDocs::__asTermPositions(){ + return NULL; + } + + void SegmentTermDocs::seek(Term* term) { + TermInfo* ti = parent->tis->get(term); + seek(ti); + _CLDELETE(ti); + } + + void SegmentTermDocs::seek(TermEnum* termEnum){ + TermInfo* ti=NULL; + + // use comparison of fieldinfos to verify that termEnum belongs to the same segment as this SegmentTermDocs + if ( termEnum->getObjectName() == SegmentTermEnum::getClassName() ){ + SegmentTermEnum* te = (SegmentTermEnum*)termEnum; + te->fieldInfos = parent->fieldInfos; + ti = te->getTermInfo(); + }else{ + ti = parent->tis->get(termEnum->term(false)); + } + + seek(ti); + _CLDELETE(ti); + } + void SegmentTermDocs::seek(const TermInfo* ti) { + count = 0; + if (ti == NULL) { + df = 0; + } else { + df = ti->docFreq; + _doc = 0; + skipDoc = 0; + skipCount = 0; + numSkips = df / skipInterval; + freqPointer = ti->freqPointer; + proxPointer = ti->proxPointer; + skipPointer = freqPointer + ti->skipOffset; + freqStream->seek(freqPointer); + haveSkipped = false; + } + } + + void SegmentTermDocs::close() { + + //Check if freqStream still exists + if (freqStream != NULL){ + freqStream->close(); //todo: items like these can probably be delete, because deleting the object also closes it...do everywhere + _CLDELETE( freqStream ); + } + if (skipStream != NULL){ + skipStream->close(); + _CLDELETE( skipStream ); + } + } + + int32_t SegmentTermDocs::doc()const { + return _doc; + } + int32_t SegmentTermDocs::freq()const { + return _freq; + } + + +bool SegmentTermDocs::next() +{ + while (true) { + if (count == df) + return false; + + uint32_t docCode = freqStream->readVInt(); + _doc += docCode >> 1; //unsigned shift + if ((docCode & 1) != 0) // if low bit is set + _freq = 1; // _freq is one + else + _freq = freqStream->readVInt(); // else read _freq + count++; + + if (deletedDocs == NULL || (_doc >= 0 && !deletedDocs->get(_doc))) + break; + skippingDoc(); + } + return true; +} + + +int32_t SegmentTermDocs::read(int32_t* docs, int32_t* freqs, int32_t length) +{ + int32_t i = 0; + // TODO: one optimization would be to get the pointer buffer for ram or mmap + // dirs and iterate over them instead of using readByte() intensive functions. + while (i < length && count < df) { + uint32_t docCode = freqStream->readVInt(); + _doc += docCode >> 1; + if ((docCode & 1) != 0) // if low bit is set + _freq = 1; // _freq is one + else + _freq = freqStream->readVInt(); // else read _freq + count++; + + if (deletedDocs == NULL || (_doc >= 0 && !deletedDocs->get(_doc))) { + docs[i] = _doc; + freqs[i] = _freq; + i++; + } + } + return i; +} + + bool SegmentTermDocs::skipTo(const int32_t target){ + if (df >= skipInterval) { // optimized case + if (skipStream == NULL) + skipStream = freqStream->clone(); // lazily clone + + if (!haveSkipped) { // lazily seek skip stream + skipStream->seek(skipPointer); + haveSkipped = true; + } + + // scan skip data + int32_t lastSkipDoc = skipDoc; + int64_t lastFreqPointer = freqStream->getFilePointer(); + int64_t lastProxPointer = -1; + int32_t numSkipped = -1 - (count % skipInterval); + + while (target > skipDoc) { + lastSkipDoc = skipDoc; + lastFreqPointer = freqPointer; + lastProxPointer = proxPointer; + + if (skipDoc != 0 && skipDoc >= _doc) + numSkipped += skipInterval; + + if(skipCount >= numSkips) + break; + + skipDoc += skipStream->readVInt(); + freqPointer += skipStream->readVInt(); + proxPointer += skipStream->readVInt(); + + skipCount++; + } + + // if we found something to skip, then skip it + if (lastFreqPointer > freqStream->getFilePointer()) { + freqStream->seek(lastFreqPointer); + skipProx(lastProxPointer); + + _doc = lastSkipDoc; + count += numSkipped; + } + + } + + // done skipping, now just scan + + do { + if (!next()) + return false; + } while (target > _doc); + return true; + } + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentTermEnum.cpp b/3rdparty/clucene/src/CLucene/index/SegmentTermEnum.cpp new file mode 100644 index 0000000..20e286f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentTermEnum.cpp @@ -0,0 +1,389 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "SegmentTermEnum.h" + +#include "Terms.h" +#include "FieldInfos.h" +#include "Term.h" +#include "TermInfo.h" +#include "TermInfosWriter.h" + +CL_NS_USE(store) +CL_NS_DEF(index) + + SegmentTermEnum::SegmentTermEnum(IndexInput* i, FieldInfos* fis, const bool isi): + fieldInfos(fis){ + //Func - Constructor + //Pre - i holds a reference to an instance of IndexInput + // fis holds a reference to an instance of FieldInfos + // isi + //Post - An instance of SegmentTermEnum has been created + input = i; + position = -1; + //Instantiate a Term with empty field, empty text and which is interned (see term.h what interned means) + _term = _CLNEW Term; + isIndex = isi; + termInfo = _CLNEW TermInfo(); + indexPointer = 0; + buffer = NULL; + bufferLength = 0; + prev = NULL; + formatM1SkipInterval = 0; + + //Set isClone to false as the instance is not clone of another instance + isClone = false; + + + int32_t firstInt = input->readInt(); + if (firstInt >= 0) { + // original-format file, without explicit format version number + format = 0; + size = firstInt; + + // back-compatible settings + indexInterval = 128; + skipInterval = LUCENE_INT32_MAX_SHOULDBE; // switch off skipTo optimization + + } else { + // we have a format version number + format = firstInt; + + // check that it is a format we can understand + if (format < TermInfosWriter::FORMAT){ + TCHAR err[30]; + _sntprintf(err,30,_T("Unknown format version: %d"), format); + _CLTHROWT(CL_ERR_Runtime,err); + } + + size = input->readLong(); // read the size + + if(format == -1){ + if (!isIndex) { + indexInterval = input->readInt(); + formatM1SkipInterval = input->readInt(); + } + // switch off skipTo optimization for file format prior to 1.4rc2 in order to avoid a bug in + // skipTo implementation of these versions + skipInterval = LUCENE_INT32_MAX_SHOULDBE; + }else{ + indexInterval = input->readInt(); + skipInterval = input->readInt(); + } + } + } + + SegmentTermEnum::SegmentTermEnum(const SegmentTermEnum& clone): + fieldInfos(clone.fieldInfos) + { + //Func - Constructor + // The instance is created by cloning all properties of clone + //Pre - clone holds a valid reference to SegmentTermEnum + //Post - An instance of SegmentTermEnum with the same properties as clone + + input = clone.input->clone(); + //Copy the postion from the clone + position = clone.position; + + if ( clone._term != NULL ){ + _term = _CLNEW Term; + _term->set(clone._term,clone._term->text()); + }else + _term = NULL; + isIndex = clone.isIndex; + termInfo = _CLNEW TermInfo(clone.termInfo); + indexPointer = clone.indexPointer; + buffer = clone.buffer==NULL?NULL:(TCHAR*)malloc(sizeof(TCHAR) * (clone.bufferLength+1)); + bufferLength = clone.bufferLength; + prev = clone.prev==NULL?NULL:_CLNEW Term(clone.prev->field(),clone.prev->text(),false); + size = clone.size; + + format = clone.format; + indexInterval= clone.indexInterval; + skipInterval = clone.skipInterval; + formatM1SkipInterval = clone.formatM1SkipInterval; + //Set isClone to true as this instance is a clone of another instance + isClone = true; + + //Copy the contents of buffer of clone to the buffer of this instance + if ( clone.buffer != NULL ) + memcpy(buffer,clone.buffer,bufferLength * sizeof(TCHAR)); + } + + SegmentTermEnum::~SegmentTermEnum(){ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed. If this instance was a clone + // then the inputstream is closed and deleted too. + + //todo: revisit this... close() should clean up most of everything. + + //Finalize prev + _CLDECDELETE(prev ); + //Finalize term + _CLDECDELETE( _term ); + + + //Delete the buffer if necessary + free(buffer); + //Delete termInfo if necessary + _CLDELETE(termInfo); + + //Check if this instance is a clone + if ( isClone ){ + //Close the inputstream + input->close(); + //delete the inputstream + _CLDELETE(input); + } + } + + bool SegmentTermEnum::next(){ + //Func - Moves the current of the set to the next in the set + //Pre - true + //Post - If the end has been reached NULL is returned otherwise the term has + // become the next Term in the enumeration + + //Increase position by and and check if the end has been reached + if (position++ >= size-1) { + //delete term + _CLDECDELETE(_term); + return false; + } + + //delete the previous enumerated term + Term* tmp=NULL; + if ( prev != NULL ){ + int32_t usage = prev->__cl_refcount; + if ( usage > 1 ){ + _CLDECDELETE(prev); //todo: tune other places try and delete its term + }else + tmp = prev; //we are going to re-use this term + } + //prev becomes the current enumerated term + prev = _term; + //term becomes the next term read from inputStream input + _term = readTerm(tmp); + + //Read docFreq, the number of documents which contain the term. + termInfo->docFreq = input->readVInt(); + //Read freqPointer, a pointer into the TermFreqs file (.frq) + termInfo->freqPointer += input->readVLong(); + + //Read proxPointer, a pointer into the TermPosition file (.prx). + termInfo->proxPointer += input->readVLong(); + + if(format == -1){ + // just read skipOffset in order to increment file pointer; + // value is never used since skipTo is switched off + if (!isIndex) { + if (termInfo->docFreq > formatM1SkipInterval) { + termInfo->skipOffset = input->readVInt(); + } + } + }else{ + if (termInfo->docFreq >= skipInterval) + termInfo->skipOffset = input->readVInt(); + } + + //Check if the enumeration is an index + if (isIndex) + //read index pointer + indexPointer += input->readVLong(); + + return true; + } + + Term* SegmentTermEnum::term() { + //Func - Returns the current term. + //Pre - pointer is true or false and indicates if the reference counter + // of term must be increased or not + // next() must have been called once! + //Post - pointer = true -> term has been returned with an increased reference counter + // pointer = false -> term has been returned + + return _CL_POINTER(_term); + } + Term* SegmentTermEnum::term(bool pointer) { + if ( pointer ) + return _CL_POINTER(_term); + else + return _term; + } + + void SegmentTermEnum::scanTo(const Term *term){ + //Func - Scan for Term without allocating new Terms + //Pre - term != NULL + //Post - The iterator term has been moved to the position where Term is expected to be + // in the enumeration + while ( term->compareTo(this->_term) > 0 && next()) + { + } + } + + void SegmentTermEnum::close() { + //Func - Closes the enumeration to further activity, freeing resources. + //Pre - true + //Post - The inputStream input has been closed + + input->close(); + } + + int32_t SegmentTermEnum::docFreq() const { + //Func - Returns the document frequency of the current term in the set + //Pre - termInfo != NULL + // next() must have been called once + //Post - The document frequency of the current enumerated term has been returned + + return termInfo->docFreq; + } + + void SegmentTermEnum::seek(const int64_t pointer, const int32_t p, Term* t, TermInfo* ti) { + //Func - Repositions term and termInfo within the enumeration + //Pre - pointer >= 0 + // p >= 0 and contains the new position within the enumeration + // t is a valid reference to a Term and is the new current term in the enumeration + // ti is a valid reference to a TermInfo and is corresponding TermInfo form the new + // current Term + //Post - term and terminfo have been repositioned within the enumeration + + //Reset the IndexInput input to pointer + input->seek(pointer); + //Assign the new position + position = p; + + //finalize the current term + if ( _term == NULL || _term->__cl_refcount > 1 ){ + _CLDECDELETE(_term); + //Get a pointer from t and increase the reference counter of t + _term = _CLNEW Term; //cannot use reference, because TermInfosReader uses non ref-counted array + } + _term->set(t,t->text()); + + //finalize prev + _CLDECDELETE(prev); + + //Change the current termInfo so it matches the new current term + termInfo->set(ti); + + //Have the buffer grown if needed + if ( bufferLength <= _term->textLength() ) + growBuffer(_term->textLength(), true ); // copy term text into buffer + else + _tcsncpy(buffer,_term->text(),bufferLength); //just copy the buffer + } + + TermInfo* SegmentTermEnum::getTermInfo()const { + //Func - Returns a clone of the current termInfo + //Pre - termInfo != NULL + // next() must have been called once + //Post - A clone of the current termInfo has been returned + + return _CLNEW TermInfo(*termInfo); //clone + } + + void SegmentTermEnum::getTermInfo(TermInfo* ti)const { + //Func - Retrieves a clone of termInfo through the reference ti + //Pre - ti contains a valid reference to TermInfo + // termInfo != NULL + // next() must have been called once + //Post - ti contains a clone of termInfo + + ti->set(termInfo); + } + + int64_t SegmentTermEnum::freqPointer()const { + //Func - Returns the freqpointer of the current termInfo + //Pre - termInfo != NULL + // next() must have been called once + //Post - The freqpointer of the current termInfo has been returned + + return termInfo->freqPointer; + } + + int64_t SegmentTermEnum::proxPointer()const { + //Func - Returns the proxPointer of the current termInfo + //Pre - termInfo != NULL + // next() must have been called once + //Post - the proxPointer of the current termInfo has been returned + + return termInfo->proxPointer; + } + + SegmentTermEnum* SegmentTermEnum::clone() const { + //Func - Returns a clone of this instance + //Pre - true + //Post - An clone of this instance has been returned + + return _CLNEW SegmentTermEnum(*this); + } + + Term* SegmentTermEnum::readTerm(Term* reuse) { + //Func - Reads the next term in the enumeration + //Pre - true + //Post - The next Term in the enumeration has been read and returned + + //Read the start position from the inputStream input + int32_t start = input->readVInt(); + //Read the length of term in the inputStream input + int32_t length = input->readVInt(); + + //Calculated the total lenght of bytes that buffer must be to contain the current + //chars in buffer and the new ones yet to be read + uint32_t totalLength = start + length; + + if (static_cast(bufferLength) < totalLength+1) + growBuffer(totalLength, false); + + //Read a length number of characters into the buffer from position start in the inputStream input + input->readChars(buffer, start, length); + //Null terminate the string + buffer[totalLength] = 0; + + //Return a new Term + int32_t field = input->readVInt(); + const TCHAR* fieldname = fieldInfos->fieldName(field); + if ( reuse == NULL ) + reuse = _CLNEW Term; + + reuse->set(fieldname, buffer, false); + return reuse; + } + + void SegmentTermEnum::growBuffer(const uint32_t length, bool force_copy) { + //Func - Instantiate a buffer of length length+1 + //Pre - length > 0 + //Post - pre(buffer) has been deleted with its contents. A new buffer + // has been allocated of length length+1 and the text of term has been copied + // to buffer + //todo: we could guess that we will need to re-grow this + //buffer a few times...so start off with a reasonable grow + //value... + if ( bufferLength > length ) + return; + + //Store the new bufferLength + if ( length - bufferLength < LUCENE_SEGMENTTERMENUM_GROWSIZE ) + bufferLength = length+LUCENE_SEGMENTTERMENUM_GROWSIZE; + else + bufferLength = length+1; + + bool copy = buffer==NULL; + + //Instantiate the new buffer + 1 is needed for terminator '\0' + if ( buffer == NULL ) + buffer = (TCHAR*)malloc(sizeof(TCHAR) * (bufferLength+1)); + else + buffer = (TCHAR*)realloc(buffer, sizeof(TCHAR) * (bufferLength+1)); + + if ( copy || force_copy){ + //Copy the text of term into buffer + _tcsncpy(buffer,_term->text(),bufferLength); + } + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentTermEnum.h b/3rdparty/clucene/src/CLucene/index/SegmentTermEnum.h new file mode 100644 index 0000000..0d50103 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentTermEnum.h @@ -0,0 +1,138 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_SegmentTermEnum_ +#define _lucene_index_SegmentTermEnum_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Terms.h" +#include "FieldInfos.h" +#include "TermInfo.h" + +CL_NS_DEF(index) + +/** + * SegmentTermEnum is an enumeration of all Terms and TermInfos + */ +class SegmentTermEnum:public TermEnum{ +private: + Term* _term; ///points to the current Term in the enumeration + TermInfo* termInfo; ///points to the TermInfo matching the current Term in the enumeration + + bool isIndex; ///Indicates if the Segment is a an index + bool isClone; ///Indicates if SegmentTermEnum is an orignal instance or + ///a clone of another SegmentTermEnum + + TCHAR* buffer; ///The buffer that contains the data read from the Term Infos File + uint32_t bufferLength; ///Length of the buffer + + int32_t format; + int32_t formatM1SkipInterval; + + CL_NS(store)::IndexInput* input; ///The IndexInput that reads from the Term Infos File + FieldInfos* fieldInfos; ///contains the Field Infos for the segment + int64_t size; ///The size of the enumeration + int64_t position; ///The position of the current (term) in the enumeration + int64_t indexPointer; + Term* prev; ///The previous current + int32_t indexInterval; + int32_t skipInterval; + + friend class TermInfosReader; + friend class SegmentTermDocs; +protected: + + /** + * Constructor. + * The instance is created by cloning all properties of clone + */ + SegmentTermEnum( const SegmentTermEnum& clone); + +public: + ///Constructor + SegmentTermEnum(CL_NS(store)::IndexInput* i, FieldInfos* fis, const bool isi ); + + ///Destructor + ~SegmentTermEnum(); + + /** + * Moves the current of the set to the next in the set + */ + bool next(); + + /** + * Returns a pointer to the current term. + */ + Term* term(); + /** + * Returns the current term. + */ + Term* term(bool pointer); + + /** + * Scan for Term term without allocating new Terms + */ + void scanTo(const Term *term); + + /** + * Closes the enumeration to further activity, freeing resources. + */ + void close(); + + /** + * Returns the document frequency of the current term in the set + */ + int32_t docFreq() const; + + /** + * Repositions term and termInfo within the enumeration + */ + void seek(const int64_t pointer, const int32_t p, Term* t, TermInfo* ti); + + /** + * Returns a clone of the current termInfo + */ + TermInfo* getTermInfo()const; + + /** + * Retrieves a clone of termInfo through the reference ti + */ + void getTermInfo(TermInfo* ti)const; + + /** + * Returns the freqPointer from the current TermInfo in the enumeration. + */ + int64_t freqPointer() const; + + /** + * Returns the proxPointer from the current TermInfo in the enumeration. + */ + int64_t proxPointer() const; + + /** + * Returns a clone of this instance + */ + SegmentTermEnum* clone() const; + + const char* getObjectName(){ return SegmentTermEnum::getClassName(); } + static const char* getClassName(){ return "SegmentTermEnum"; } + +private: + /** + * Reads the next term in the enumeration + */ + Term* readTerm(Term* reuse); + /** + * Instantiate a buffer of length length+1 + */ + void growBuffer(const uint32_t length, bool force_copy); + +}; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/index/SegmentTermPositions.cpp b/3rdparty/clucene/src/CLucene/index/SegmentTermPositions.cpp new file mode 100644 index 0000000..e481838 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentTermPositions.cpp @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "SegmentHeader.h" + +#include "Terms.h" + +CL_NS_USE(util) +CL_NS_DEF(index) + +SegmentTermPositions::SegmentTermPositions(const SegmentReader* _parent): + SegmentTermDocs(_parent){ +//Func - Constructor +//Pre - Parent != NULL +//Post - The instance has been created + + CND_PRECONDITION(_parent != NULL, "Parent is NULL"); + + proxStream = _parent->proxStream->clone(); + + CND_CONDITION(proxStream != NULL,"proxStream is NULL"); + + position = 0; + proxCount = 0; +} + +SegmentTermPositions::~SegmentTermPositions() { +//Func - Destructor +//Pre - true +//Post - The intance has been closed + close(); +} + +TermDocs* SegmentTermPositions::__asTermDocs(){ + return (TermDocs*) this; +} +TermPositions* SegmentTermPositions::__asTermPositions(){ + return (TermPositions*) this; +} + +void SegmentTermPositions::seek(const TermInfo* ti) { + SegmentTermDocs::seek(ti); + if (ti != NULL) + proxStream->seek(ti->proxPointer); + proxCount = 0; +} + +void SegmentTermPositions::close() { +//Func - Frees the resources +//Pre - true +//Post - The resources have been freed + + SegmentTermDocs::close(); + //Check if proxStream still exists + if(proxStream){ + proxStream->close(); + _CLDELETE( proxStream ); + } +} + +int32_t SegmentTermPositions::nextPosition() { + /* DSR:CL_BUG: Should raise exception if proxCount == 0 at the + ** beginning of this method, as in + ** if (--proxCount == 0) throw ...; + ** The JavaDocs for TermPositions.nextPosition declare this constraint, + ** but CLucene doesn't enforce it. */ + proxCount--; + return position += proxStream->readVInt(); +} + +bool SegmentTermPositions::next() { + for (int32_t f = proxCount; f > 0; f--) // skip unread positions + proxStream->readVInt(); + + if (SegmentTermDocs::next()) { // run super + proxCount = _freq; // note frequency + position = 0; // reset position + return true; + } + return false; +} + +int32_t SegmentTermPositions::read(int32_t* docs, int32_t* freqs, int32_t length) { + _CLTHROWA(CL_ERR_InvalidState,"TermPositions does not support processing multiple documents in one call. Use TermDocs instead."); +} + +void SegmentTermPositions::skippingDoc() { + for (int32_t f = _freq; f > 0; f--) // skip all positions + proxStream->readVInt(); +} + +void SegmentTermPositions::skipProx(int64_t proxPointer){ + proxStream->seek(proxPointer); + proxCount = 0; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/SegmentTermVector.cpp b/3rdparty/clucene/src/CLucene/index/SegmentTermVector.cpp new file mode 100644 index 0000000..5e9ac3c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/SegmentTermVector.cpp @@ -0,0 +1,188 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "TermVector.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(util) +CL_NS_DEF(index) + +Array SegmentTermPositionVector::EMPTY_TERM_POS; + +SegmentTermVector::SegmentTermVector(const TCHAR* field, TCHAR** terms, Array* termFreqs) { + this->field = STRDUP_TtoT(field); + this->terms = terms; + this->termsLen = -1; //lazily get the size of the terms + this->termFreqs = termFreqs; +} + +SegmentTermVector::~SegmentTermVector(){ + _CLDELETE_CARRAY(field); + _CLDELETE_CARRAY_ALL(terms); + + _CLDELETE_ARRAY(termFreqs->values); + _CLDELETE(termFreqs); +} +TermPositionVector* SegmentTermVector::__asTermPositionVector(){ + return NULL; +} + +const TCHAR* SegmentTermVector::getField() { +return field; +} + +TCHAR* SegmentTermVector::toString() const{ +StringBuffer sb; +sb.appendChar('{'); +sb.append(field); +sb.append(_T(": ")); + +int32_t i=0; +while ( terms && terms[i] != NULL ){ + if (i>0) + sb.append(_T(", ")); + sb.append(terms[i]); + sb.appendChar('/'); + + sb.appendInt((*termFreqs)[i]); +} +sb.appendChar('}'); +return sb.toString(); +} + +int32_t SegmentTermVector::size() { +if ( terms == NULL ) + return 0; + +if ( termsLen == -1 ){ + termsLen=0; + while ( terms[termsLen] != 0 ) + termsLen++; +} +return termsLen; +} + +const TCHAR** SegmentTermVector::getTerms() { + return (const TCHAR**)terms; +} + +const Array* SegmentTermVector::getTermFrequencies() { + return termFreqs; +} + +int32_t SegmentTermVector::binarySearch(TCHAR** a, const int32_t arraylen, const TCHAR* key) const +{ + int32_t low = 0; + int32_t hi = arraylen - 1; + int32_t mid = 0; + while (low <= hi) + { + mid = (low + hi) >> 1; + + int32_t c = _tcscmp(a[mid],key); + if (c==0) + return mid; + else if (c > 0) + hi = mid - 1; + else // This gets the insertion point right on the last loop. + low = ++mid; + } + return -mid - 1; +} + +int32_t SegmentTermVector::indexOf(const TCHAR* termText) { + if(terms == NULL) + return -1; + int32_t res = binarySearch(terms, size(), termText); + return res >= 0 ? res : -1; +} + +void SegmentTermVector::indexesOf(const TCHAR** termNumbers, const int32_t start, const int32_t len, Array& ret) { + // TODO: there must be a more efficient way of doing this. + // At least, we could advance the lower bound of the terms array + // as we find valid indexes. Also, it might be possible to leverage + // this even more by starting in the middle of the termNumbers array + // and thus dividing the terms array maybe in half with each found index. + ret.length = len; + ret.values = _CL_NEWARRAY(int32_t,len); + for (int32_t i=0; i* termFreqs, Array< Array >* positions, Array< Array >* offsets): + SegmentTermVector(field,terms,termFreqs) +{ + this->offsets = offsets; + this->positions = positions; +} + +SegmentTermPositionVector::~SegmentTermPositionVector(){ + if ( offsets ){ + for (size_t i=0;ilength;i++){ + if ( offsets->values != NULL ){ + Array& offs = offsets->values[i]; + for ( size_t j=0;jvalues); + _CLDELETE(offsets); + } + if ( positions ){ + for (size_t i=0;ilength;i++){ + if ( positions->values != NULL ){ + Array& pos = positions->values[i]; + for ( size_t j=0;jvalues); + _CLDELETE(positions); + } +} + +TermPositionVector* SegmentTermPositionVector::__asTermPositionVector(){ + return this; +} +/** +* Returns an array of TermVectorOffsetInfo in which the term is found. +* +* @param index The position in the array to get the offsets from +* @return An array of TermVectorOffsetInfo objects or the empty list +* @see org.apache.lucene.analysis.Token +*/ +Array* SegmentTermPositionVector::getOffsets(int32_t index) { + if(offsets == NULL) + return NULL; + if (index >=0 && index < offsets->length) + return &offsets->values[index]; + else + return &TermVectorOffsetInfo::EMPTY_OFFSET_INFO; +} + +/** +* Returns an array of positions in which the term is found. +* Terms are identified by the index at which its number appears in the +* term String array obtained from the indexOf method. +*/ +Array* SegmentTermPositionVector::getTermPositions(int32_t index) { + if(positions == NULL) + return NULL; + + if (index >=0 && index < positions->length) + return &positions->values[index]; + else + return &EMPTY_TERM_POS; +} +CL_NS_END + diff --git a/3rdparty/clucene/src/CLucene/index/Term.cpp b/3rdparty/clucene/src/CLucene/index/Term.cpp new file mode 100644 index 0000000..5ff7bb2 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/Term.cpp @@ -0,0 +1,182 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ + +#include "CLucene/StdHeader.h" +#include "Term.h" +#include "CLucene/util/StringIntern.h" + +CL_NS_USE(util) +CL_NS_DEF(index) + +Term::Term() +{ + init(); +} + +Term::Term(const TCHAR* fld, const TCHAR* txt, bool internField) +{ + init(); + set(fld, txt, internField); +} + +Term::Term(const Term* fieldTerm, const TCHAR* txt) +{ + init(); + set(fieldTerm, txt); +} + +Term::Term(const TCHAR* fld, const TCHAR* txt) +{ + init(); + set(fld, txt); +} + +Term::~Term() +{ + if (internF) + CLStringIntern::unintern(_field); + _field = NULL; + +#ifndef LUCENE_TERM_TEXT_LENGTH + if (_text != LUCENE_BLANK_STRING) + _CLDELETE_CARRAY(_text); +#endif +} + +const TCHAR* Term::field() const +{ + return _field; +} + +const TCHAR* Term::text() const +{ + return _text; +} + +void Term::set(const Term* term, const TCHAR* txt) +{ + set(term->field(), txt, false); +} + +void Term::set(const TCHAR* fld, const TCHAR* txt,bool internField) +{ + CND_PRECONDITION(fld != NULL, "fld contains NULL"); + CND_PRECONDITION(txt != NULL, "txt contains NULL"); + + //save field for unintern later + const TCHAR* oldField = _field; + cachedHashCode = 0; + textLen = _tcslen(txt); + + //Delete text if it is the owner +#ifdef LUCENE_TERM_TEXT_LENGTH + if (textLen > LUCENE_TERM_TEXT_LENGTH) + textLen = LUCENE_TERM_TEXT_LENGTH; + + _tcsncpy(_text,txt,textLen+1); + _text[textLen]=0; +#else + //if the term text buffer is bigger than what we have + if (_text && textLen > textLenBuf) { + if (_text != LUCENE_BLANK_STRING) { + _CLDELETE_ARRAY(_text); + } else { + _text = NULL; + } + textLenBuf = 0; + } + + if (_text == LUCENE_BLANK_STRING) { + _text = LUCENE_BLANK_STRING; + } else if (_text == NULL) { + if (txt[0] == 0) { + //if the string is blank and we aren't re-using the buffer... + _text = LUCENE_BLANK_STRING; + } else { + //duplicate the text + _text = stringDuplicate(txt); + textLenBuf = textLen; + } + } else { + //re-use the buffer + _tcscpy(_text,txt); + } +#endif + + //Set Term Field + if (internField) { + _field = CLStringIntern::intern(fld CL_FILELINE); + } else { + _field = fld; + } + + //unintern old field after interning new one, + if (internF) + CLStringIntern::unintern(oldField); + internF = internField; + + CND_PRECONDITION(_tcscmp(fld, _field) == 0, "field not equal"); +} + +bool Term::equals(const Term* other) const +{ + if (cachedHashCode != 0 && other->cachedHashCode != 0 + && other->cachedHashCode != cachedHashCode) + return false; + + if (_field == other->_field) { + if (textLen == other->textLen) + return (_tcscmp(_text, other->_text) == 0); + return false; + } + + return false; +} + +size_t Term::hashCode() +{ + if (cachedHashCode == 0) + cachedHashCode = Misc::thashCode(_field) + Misc::thashCode(_text, textLen); + + return cachedHashCode; +} + +int32_t Term::compareTo(const Term* other) const +{ + //Check ret to see if text needs to be compared + if (_field == other->_field) + return _tcscmp(_text, other->_text); + + int32_t ret = _tcscmp(_field, other->_field); + if (ret == 0) + ret = _tcscmp(_text, other->_text); + return ret; +} + +TCHAR* Term::toString() const +{ + return CL_NS(util)::Misc::join(_field, _T(":"), _text); +} + +void Term::init() +{ + textLen = 0; + internF = false; + cachedHashCode = 0; + _field = LUCENE_BLANK_STRING; + +#ifdef LUCENE_TERM_TEXT_LENGTH + _text[0] = 0; +#else + _text = LUCENE_BLANK_STRING; + textLenBuf = 0; +#endif +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/Term.h b/3rdparty/clucene/src/CLucene/index/Term.h new file mode 100644 index 0000000..68eefd1 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/Term.h @@ -0,0 +1,146 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_Term_ +#define _lucene_index_Term_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/Misc.h" +#include "CLucene/util/StringIntern.h" + +CL_NS_DEF(index) + +/* +A Term represents a word from text. This is the unit of search. It is +composed of two elements, the text of the word, as a string, and the name of +the field that the text occured in, an interned string. + +Note that terms may represent more than words from text fields, but also +things like dates, email addresses, urls, etc. + +IMPORTANT NOTE: +Term inherits from the template class LUCENE_REFBASE which tries to do +some garbage collection by counting the references an instance has. As a result +of this construction you MUST use _CLDECDELETE(obj) when you want to delete an +of Term! + +ABOUT intrn + +intrn indicates if field and text are interned or not. Interning of Strings +is the process of converting duplicated strings to shared ones. + +*/ +class Term : LUCENE_REFBASE +{ +private: + const TCHAR* _field; + bool internF; // Indicates if Term Field is interned(and therefore must be uninternd). + size_t cachedHashCode; + size_t textLen; // a cache of text len, this allows for a preliminary comparison of text lengths + +#ifdef LUCENE_TERM_TEXT_LENGTH + TCHAR _text[LUCENE_TERM_TEXT_LENGTH + 1]; +#else + TCHAR* _text; + size_t textLenBuf; //a cache of text len, this allows for a preliminary comparison of text lengths +#endif + + void init(); +public: + + //uses the specified fieldTerm's field. this saves on intern'ing time. + Term(const Term* fieldTerm, const TCHAR* txt); + + ///Constructs a blank term + Term(); + + // TODO: need to be private, a few other things need to be changed first... + Term(const TCHAR* fld, const TCHAR* txt, bool internField); + + /** + * Constructor. Constructs a Term with the given field and text. Field and + * text are not copied Field and text are deleted in destructor only if + * intern is false. + */ + Term(const TCHAR* fld, const TCHAR* txt); + + ///Destructor. + ~Term(); + + ///Returns the field of this term, an interned string. The field indicates + ///the part of a document which this term came from. + const TCHAR* field() const; /// + TCHAR* toString() const; + + size_t hashCode(); + + class Equals:public CL_NS_STD(binary_function) + { + public: + bool operator()( const Term* val1, const Term* val2 ) const + { + return val1->equals(val2); + } + }; + + class Compare:LUCENE_BASE, public CL_NS(util)::Compare::_base // + { + public: + bool operator()(Term* t1, Term* t2) const + { + return (t1->compareTo(t2) < 0); + } + + size_t operator()(Term* t) const + { + return t->hashCode(); + } + }; +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/TermInfo.cpp b/3rdparty/clucene/src/CLucene/index/TermInfo.cpp new file mode 100644 index 0000000..ac11073 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermInfo.cpp @@ -0,0 +1,53 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ + +#include "CLucene/StdHeader.h" +#include "TermInfo.h" + +CL_NS_DEF(index) + +TermInfo::TermInfo() +{ + set(0, 0, 0, 0); +} + +TermInfo::~TermInfo() +{ +} + +TermInfo::TermInfo(int32_t df, int64_t fp, int64_t pp) +{ + set(df, fp, pp, 0); +} + +TermInfo::TermInfo(const TermInfo* ti) +{ + if (ti) + set(ti); +} + +void TermInfo::set(const TermInfo* ti) +{ + if (ti) + set(ti->docFreq, ti->freqPointer, ti->proxPointer, ti->skipOffset); +} + +void TermInfo::set(int32_t df, int64_t fp, int64_t pp, int32_t so) +{ + CND_PRECONDITION(df >= 0, "df contains negative number"); + CND_PRECONDITION(fp >= 0, "fp contains negative number"); + CND_PRECONDITION(pp >= 0, "pp contains negative number"); + + docFreq = df; + freqPointer = fp; + proxPointer = pp; + skipOffset = so; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/TermInfo.h b/3rdparty/clucene/src/CLucene/index/TermInfo.h new file mode 100644 index 0000000..57b7a9a --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermInfo.h @@ -0,0 +1,61 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_TermInfo +#define _lucene_index_TermInfo + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(index) + +// A TermInfo is the record of information stored for a term. +class TermInfo : LUCENE_BASE +{ +public: + // The number of documents which contain the term. + int32_t docFreq; + + //A pointer into the TermFreqs file (.frq) + //The .frq file contains the lists of documents which contain each term, + //along with the frequency of the term in that document. + int64_t freqPointer; + + //A pointer into the TermPosition file (.prx). + //The .prx file contains the lists of positions that each term + //occurs at within documents. + int64_t proxPointer; + + int32_t skipOffset; + + //Constructor + TermInfo(); + + //Constructor + TermInfo(int32_t df, int64_t fp, int64_t pp); + + //Constructor + //Initialises this instance by copying the values of another TermInfo ti + TermInfo(const TermInfo* ti); + + //Destructor + ~TermInfo(); + + //Sets a new document frequency, a new freqPointer and a new proxPointer + void set(int32_t docFreq, int64_t freqPointer, int64_t proxPointer, + int32_t skipOffset); + + //Sets a new document frequency, a new freqPointer and a new proxPointer + //by copying these values from another instance of TermInfo + void set(const TermInfo* ti); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/TermInfosReader.cpp b/3rdparty/clucene/src/CLucene/index/TermInfosReader.cpp new file mode 100644 index 0000000..8f9e43d --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermInfosReader.cpp @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "TermInfosReader.h" + +#include "CLucene/store/Directory.h" +#include "CLucene/util/Misc.h" +#include "FieldInfos.h" +#include "Term.h" +#include "Terms.h" +#include "TermInfo.h" +#include "TermInfosWriter.h" + +CL_NS_USE(store) +CL_NS_USE(util) +CL_NS_DEF(index) + +TermInfosReader::TermInfosReader(Directory* dir, const QString& seg, + FieldInfos* fis) + : directory(dir) + , fieldInfos (fis) +{ + //Func - Constructor. + // Reads the TermInfos file (.tis) and eventually the Term Info Index file (.tii) + //Pre - dir is a reference to a valid Directory + // Fis contains a valid reference to an FieldInfos instance + // seg != NULL and contains the name of the segment + //Post - An instance has been created and the index named seg has been read. (Remember + // a segment is nothing more then an independently readable index) + + CND_PRECONDITION(!seg.isEmpty(), "seg is NULL"); + + //Initialize the name of the segment + segment = seg; + //There are no indexTerms yet + indexTerms = NULL; + //So there are no indexInfos + indexInfos = NULL; + //So there are no indexPointers + indexPointers = NULL; + //Create a filname fo a Term Info File + QString tisFile = Misc::segmentname(segment, QLatin1String(".tis")); + QString tiiFile = Misc::segmentname(segment, QLatin1String(".tii")); + + //Create an SegmentTermEnum for storing all the terms read of the segment + origEnum = _CLNEW SegmentTermEnum( directory->openInput( tisFile ), fieldInfos, false); + indexEnum = _CLNEW SegmentTermEnum( directory->openInput( tiiFile ), fieldInfos, true); + + //Check if enumerator points to a valid instance + CND_CONDITION(origEnum != NULL, "No memory could be allocated for orig enumerator"); + CND_CONDITION(indexEnum != NULL, "No memory could be allocated for index enumerator"); + + //Get the size of the enumeration and store it in size + _size = origEnum->size; +} + +TermInfosReader::~TermInfosReader() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + //Close the TermInfosReader to be absolutly sure that enumerator has been closed + //and the arrays indexTerms, indexPointers and indexInfos and their elements + //have been destroyed + close(); +} + +void TermInfosReader::close() +{ + //Func - Close the enumeration of TermInfos + //Pre - true + //Post - The _enumeration has been closed and the arrays + + //Check if indexTerms and indexInfos exist + if (indexTerms && indexInfos){ + //Iterate through arrays indexTerms and indexPointer to + //destroy their elements +#ifdef _DEBUG + for (int32_t i = 0; i < indexTermsLength; ++i) { + if (indexTerms[i].__cl_refcount != 1) { + CND_PRECONDITION(indexTerms[i].__cl_refcount == 1, + "TermInfosReader term was references more than internally"); + } + // _CLDECDELETE(indexTerms[i]); + //_CLDELETE(indexInfos[i]); + } +#endif + //Delete the arrays + _CLDELETE_ARRAY(indexTerms); + _CLDELETE_ARRAY(indexInfos); + } + + //Delete the arrays + _CLDELETE_ARRAY(indexPointers); + + if (origEnum != NULL) { + origEnum->close(); + + //Get a pointer to IndexInput used by the enumeration but + //instantiated in the constructor by directory.open( tisFile ) + IndexInput *is = origEnum->input; + + //Delete the enumuration enumerator + _CLDELETE(origEnum); + + //Delete the IndexInput + _CLDELETE(is); + } + + if (indexEnum != NULL){ + indexEnum->close(); + + //Get a pointer to IndexInput used by the enumeration but + //instantiated in the constructor by directory.open( tiiFile ) + IndexInput *is = indexEnum->input; + + //Delete the enumuration enumerator + _CLDELETE(indexEnum); + + //Delete the IndexInput + _CLDELETE(is); + } +} + +int64_t TermInfosReader::size() const +{ + //Func - Return the size of the enumeration of TermInfos + //Pre - true + //Post - size has been returened + + return _size; +} + +Term* TermInfosReader::get(const int32_t position) +{ + //Func - Returns the nth term in the set + //Pre - position > = 0 + //Post - The n-th term in the set has been returned + + //Check if the size is 0 because then there are no terms + if (_size == 0) + return NULL; + + SegmentTermEnum* enumerator = getEnum(); + + if (enumerator != NULL //an enumeration exists + && enumerator->term(false) != NULL // term is at or past current + && position >= enumerator->position + && position < (enumerator->position + enumerator->indexInterval)) { + return scanEnum(position); // can avoid seek + } + + //random-access: must seek + seekEnum(position / enumerator->indexInterval); + + //Get the Term at position + return scanEnum(position); +} + +// TODO: currently there is no way of cleaning up a thread, if the thread ends. +// we are stuck with the terminfosreader of that thread. Hopefully this won't +// be too big a problem... solutions anyone? +SegmentTermEnum* TermInfosReader::getEnum() +{ + SegmentTermEnum* termEnum = enumerators.get(); + if (termEnum == NULL) { + termEnum = terms(); + enumerators.set(termEnum); + } + return termEnum; +} + +TermInfo* TermInfosReader::get(const Term* term) +{ + //Func - Returns a TermInfo for a term + //Pre - term holds a valid reference to term + //Post - if term can be found its TermInfo has been returned otherwise NULL + + //If the size of the enumeration is 0 then no Terms have been read + if (_size == 0) + return NULL; + + ensureIndexIsRead(); + + // optimize sequential access: first try scanning cached enum w/o seeking + SegmentTermEnum* enumerator = getEnum(); + + // optimize sequential access: first try scanning cached enumerator w/o seeking + // if the current term of the enumeration enumerator is not at the end + if (enumerator->term(false) != NULL + // AND there exists a previous current called prev and term is + // positioned after this prev + && ((enumerator->prev != NULL && term->compareTo(enumerator->prev) > 0) + // OR term is positioned at the same position as the current of + // enumerator or at a higher position + || term->compareTo(enumerator->term(false)) >= 0)) { + //Calculate the offset for the position + int32_t _enumOffset = (int32_t) + (enumerator->position / enumerator->indexInterval) + 1; + + // but before end of block the length of indexTerms (the number of + // terms in enumerator) equals _enum_offset + if (indexTermsLength == _enumOffset + // OR term is positioned in front of term found at _enumOffset in + // indexTerms + || term->compareTo(&indexTerms[_enumOffset]) < 0) { + //no need to seek, retrieve the TermInfo for term + return scanEnum(term); + } + } + + //Reposition current term in the enumeration + seekEnum(getIndexOffset(term)); + //Return the TermInfo for term + return scanEnum(term); +} + +int64_t TermInfosReader::getPosition(const Term* term) +{ + //Func - Returns the position of a Term in the set + //Pre - term holds a valid reference to a Term + // enumerator != NULL + //Post - If term was found then its position is returned otherwise -1 + + //if the enumeration is empty then return -1 + if (_size == 0) + return -1; + + ensureIndexIsRead(); + + //Retrieve the indexOffset for term + int32_t indexOffset = getIndexOffset(term); + seekEnum(indexOffset); + + SegmentTermEnum* enumerator = getEnum(); + + while(term->compareTo(enumerator->term(false)) > 0 && enumerator->next()) {} + + if (term->equals(enumerator->term(false))) + return enumerator->position; + + return -1; +} + +SegmentTermEnum* TermInfosReader::terms(const Term* term) +{ + //Func - Returns an enumeration of terms starting at or after the named term. + // If term is null then enumerator is set to the beginning + //Pre - term holds a valid reference to a Term + // enumerator != NULL + //Post - An enumeration of terms starting at or after the named term has been returned + + SegmentTermEnum* enumerator = NULL; + if (term != NULL) { + //Seek enumerator to term; delete the new TermInfo that's returned. + TermInfo* ti = get(term); + _CLDELETE(ti); + enumerator = getEnum(); + } else { + enumerator = origEnum; + } + //Clone the entire enumeration + SegmentTermEnum* cln = enumerator->clone(); + + //Check if cln points to a valid instance + CND_CONDITION(cln != NULL, "cln is NULL"); + + return cln; +} + +void TermInfosReader::ensureIndexIsRead() +{ + //Func - Reads the term info index file or .tti file. + // This file contains every IndexInterval-th entry from the .tis file, + // along with its location in the "tis" file. This is designed to be + // read entirely into memory and used to provide random access to the + // "tis" file. + //Pre - indexTerms = NULL + // indexInfos = NULL + // indexPointers = NULL + //Post - The term info index file has been read into memory + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + if ( indexTerms != NULL ) + return; + + try { + indexTermsLength = (size_t)indexEnum->size; + + // Instantiate an block of Term's,so that each one doesn't have to be new'd + indexTerms = _CL_NEWARRAY(Term,indexTermsLength); + + // Check if is indexTerms is a valid array + CND_CONDITION(indexTerms != NULL, + "No memory could be allocated for indexTerms"); + + // Instantiate an big block of TermInfo's, so that each one doesn't + // have to be new'd + indexInfos = _CL_NEWARRAY(TermInfo,indexTermsLength); + + // Check if is indexInfos is a valid array + CND_CONDITION(indexInfos != NULL, + "No memory could be allocated for indexInfos"); + + // Instantiate an array indexPointers that contains pointers to the + // term info index file + indexPointers = _CL_NEWARRAY(int64_t,indexTermsLength); + + // Check if is indexPointers is a valid array + CND_CONDITION(indexPointers != NULL, + "No memory could be allocated for indexPointers"); + + //Iterate through the terms of indexEnum + for (int32_t i = 0; indexEnum->next(); ++i) { + indexTerms[i].set(indexEnum->term(false), indexEnum->term(false)->text()); + indexEnum->getTermInfo(&indexInfos[i]); + indexPointers[i] = indexEnum->indexPointer; + } + } _CLFINALLY ( + indexEnum->close(); + // Close and delete the IndexInput is. The close is done by the destructor. + _CLDELETE( indexEnum->input ); + _CLDELETE( indexEnum ); + ); +} + +int32_t TermInfosReader::getIndexOffset(const Term* term) +{ + //Func - Returns the offset of the greatest index entry which is less than + // or equal to term. + //Pre - term holds a reference to a valid term + // indexTerms != NULL + //Post - The new offset has been returned + + //Check if is indexTerms is a valid array + CND_PRECONDITION(indexTerms != NULL, "indexTerms is NULL"); + + int32_t lo = 0; + int32_t hi = indexTermsLength - 1; + int32_t mid; + int32_t delta; + + while (hi >= lo) { + //Start in the middle betwee hi and lo + mid = (lo + hi) >> 1; + + //Check if is indexTerms[mid] is a valid instance of Term + CND_PRECONDITION(&indexTerms[mid] != NULL, "indexTerms[mid] is NULL"); + CND_PRECONDITION(mid < indexTermsLength, "mid >= indexTermsLength"); + + //Determine if term is before mid or after mid + delta = term->compareTo(&indexTerms[mid]); + if (delta < 0) { + //Calculate the new hi + hi = mid - 1; + } else if (delta > 0) { + //Calculate the new lo + lo = mid + 1; + } else { + //term has been found so return its position + return mid; + } + } + // the new starting offset + return hi; +} + +void TermInfosReader::seekEnum(const int32_t indexOffset) +{ + //Func - Reposition the current Term and TermInfo to indexOffset + //Pre - indexOffset >= 0 + // indexTerms != NULL + // indexInfos != NULL + // indexPointers != NULL + //Post - The current Term and Terminfo have been repositioned to indexOffset + + CND_PRECONDITION(indexOffset >= 0, "indexOffset contains a negative number"); + CND_PRECONDITION(indexTerms != NULL, "indexTerms is NULL"); + CND_PRECONDITION(indexInfos != NULL, "indexInfos is NULL"); + CND_PRECONDITION(indexPointers != NULL, "indexPointers is NULL"); + + SegmentTermEnum* enumerator = getEnum(); + enumerator->seek(indexPointers[indexOffset], + (indexOffset * enumerator->indexInterval) - 1, + &indexTerms[indexOffset], &indexInfos[indexOffset]); +} + +TermInfo* TermInfosReader::scanEnum(const Term* term) +{ + //Func - Scans the Enumeration of terms for term and returns the + // corresponding TermInfo instance if found. The search is started + // from the current term. + //Pre - term contains a valid reference to a Term + // enumerator != NULL + //Post - if term has been found the corresponding TermInfo has been returned + // otherwise NULL has been returned + + SegmentTermEnum* enumerator = getEnum(); + enumerator->scanTo(term); + + //Check if the at the position the Term term can be found + if (enumerator->term(false) != NULL && term->equals(enumerator->term(false))) { + //Return the TermInfo instance about term + return enumerator->getTermInfo(); + } + + //term was not found so no TermInfo can be returned + return NULL; +} + +Term* TermInfosReader::scanEnum(const int32_t position) +{ + //Func - Scans the enumeration to the requested position and returns the + // Term located at that position + //Pre - position > = 0 + // enumerator != NULL + //Post - The Term at the requested position has been returned + + SegmentTermEnum* enumerator = getEnum(); + + // As long the position of the enumeration enumerator is smaller than the + // requested one + while(enumerator->position < position) { + //Move the current of enumerator to the next + if (!enumerator->next()) { + //If there is no next it means that the requested position was to big + return NULL; + } + } + + //Return the Term a the requested position + return enumerator->term(); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/TermInfosReader.h b/3rdparty/clucene/src/CLucene/index/TermInfosReader.h new file mode 100644 index 0000000..ed202e7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermInfosReader.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_TermInfosReader_ +#define _lucene_index_TermInfosReader_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" +#include "CLucene/util/ThreadLocal.h" +#include "SegmentTermEnum.h" + +CL_NS_DEF(index) + +class FieldInfos; +class Term; +class TermInfo; +class TermInfos; +class TermInfosWriter; + +// PORT STATUS: 365707 (jlucene 1.9) +// This stores a monotonically increasing set of pairs in a +// Directory. Pairs are accessed either by Term or by ordinal position the set. +class TermInfosReader : LUCENE_BASE +{ +private: + CL_NS(store)::Directory* directory; + QString segment; + FieldInfos* fieldInfos; + + CL_NS(util)::ThreadLocal > enumerators; + + SegmentTermEnum* getEnum(); + SegmentTermEnum* origEnum; + SegmentTermEnum* indexEnum; + int64_t _size; + + Term* indexTerms; + int32_t indexTermsLength; + TermInfo* indexInfos; + int64_t* indexPointers; + + DEFINE_MUTEX(THIS_LOCK) + +public: + // Reads the TermInfos file(.tis) and eventually the Term Info Index(.tii) + TermInfosReader(CL_NS(store)::Directory* dir, const QString& segment, + FieldInfos* fis); + ~TermInfosReader(); + + //Close the enumeration of TermInfos + void close(); + + //Return the size of the enumeration of TermInfos + int64_t size() const; + + int32_t getSkipInterval() { + return origEnum->skipInterval; } + + // Returns an enumeration of terms starting at or after the named term. + // If no term is specified, an enumeration of all the Terms + // and TermInfos in the set is returned. + SegmentTermEnum* terms(const Term* term = NULL); + + // Returns the TermInfo for a Term in the set + // synchronized + TermInfo* get(const Term* term); + +private: + // Reads the term info index file or .tti file. + void ensureIndexIsRead(); + + // Returns the offset of the greatest index entry which is less than term. + int32_t getIndexOffset(const Term* term); + + // Reposition the current Term and TermInfo to indexOffset + void seekEnum(const int32_t indexOffset); + + // Scans the Enumeration of terms for term and returns the corresponding + // TermInfo instance if found. The search is started from the current term. + TermInfo* scanEnum(const Term* term); + + // Scans the enumeration to the requested position and returns the Term + // located at that position + Term* scanEnum(const int32_t position); + + // Returns the position of a Term in the set. synchronized + int64_t getPosition(const Term* term); + + // Returns the nth term in the set. synchronized + Term* get(const int32_t position); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/TermInfosWriter.cpp b/3rdparty/clucene/src/CLucene/index/TermInfosWriter.cpp new file mode 100644 index 0000000..c5b5340 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermInfosWriter.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "TermInfosWriter.h" + +#include "CLucene/store/Directory.h" +#include "CLucene/util/Misc.h" +#include "FieldInfos.h" +#include "Term.h" +#include "TermInfo.h" +#include "IndexWriter.h" + +CL_NS_USE(util) +CL_NS_USE(store) +CL_NS_DEF(index) + +TermInfosWriter::TermInfosWriter(Directory* directory, const QString& segment, + FieldInfos* fis, int32_t interval) + : fieldInfos(fis) +{ + //Func - Constructor + //Pre - directory contains a valid reference to a Directory + // segment != NULL + // fis contains a valid reference to a reference FieldInfos + //Post - The instance has been created + + CND_PRECONDITION(!segment.isEmpty(), "segment is NULL"); + //Initialize instance + initialise(directory, segment, interval, false); + + other = _CLNEW TermInfosWriter(directory, segment, fieldInfos, interval, true); + + CND_CONDITION(other != NULL, "other is NULL"); + + other->other = this; +} + +TermInfosWriter::TermInfosWriter(Directory* directory, const QString& segment, + FieldInfos* fis, int32_t interval, bool isIndex) + : fieldInfos(fis) +{ + //Func - Constructor + //Pre - directory contains a valid reference to a Directory + // segment != NULL + // fis contains a valid reference to a reference FieldInfos + // isIndex is true or false + //Post - The instance has been created + + CND_PRECONDITION(!segment.isEmpty(), "segment is NULL"); + initialise(directory, segment, interval, isIndex); +} + +void TermInfosWriter::initialise(Directory* directory, const QString& segment, + int32_t interval, bool IsIndex) +{ + //Func - Helps constructors to initialize Instance + //Pre - directory contains a valid reference to a Directory + // segment != NULL + // fis contains a valid reference to a reference FieldInfos + //Post - The instance has been initialized + + lastTerm = _CLNEW Term; + + CND_CONDITION(lastTerm != NULL, "Could not allocate memory for lastTerm"); + + lastTi = _CLNEW TermInfo(); + + CND_CONDITION(lastTi != NULL, "Could not allocate memory for lastTi"); + + lastIndexPointer = 0; + size = 0; + isIndex = IsIndex; + indexInterval = interval; + skipInterval = LUCENE_DEFAULT_TERMDOCS_SKIP_INTERVAL; + + QString buf = Misc::segmentname(segment, QLatin1String(isIndex ? ".tii" : ".tis")); + output = directory->createOutput(buf); + + output->writeInt(FORMAT); // write format + output->writeLong(0); // leave space for size + output->writeInt(indexInterval);// write indexInterval + output->writeInt(skipInterval); // write skipInterval + + //Set other to NULL by Default + other = NULL; +} + +TermInfosWriter::~TermInfosWriter() +{ + //Func - Destructor + //Pre - true + //Post - de instance has been destroyed + + close(); +} + +void TermInfosWriter::add(Term* term, const TermInfo* ti) +{ + //Func - Writes a Term and TermInfo to the outputstream + //Pre - Term must be lexicographically greater than all previous Terms added. + // Pointers of TermInfo ti (freqPointer and proxPointer) must be + // positive and greater than all previous. + + CND_PRECONDITION(isIndex || (!isIndex && term->compareTo(lastTerm) > 0),"term out of order"); + CND_PRECONDITION(ti->freqPointer >= lastTi->freqPointer,"freqPointer out of order"); + CND_PRECONDITION(ti->proxPointer >= lastTi->proxPointer,"proxPointer out of order"); + + if (!isIndex && size % indexInterval == 0) { + //add an index term + other->add(lastTerm, lastTi); + } + + //write term + writeTerm(term); + // write doc freq + output->writeVInt(ti->docFreq); + //write pointers + output->writeVLong(ti->freqPointer - lastTi->freqPointer); + output->writeVLong(ti->proxPointer - lastTi->proxPointer); + if (ti->docFreq >= skipInterval) { + output->writeVInt(ti->skipOffset); + } + + if (isIndex){ + output->writeVLong(other->output->getFilePointer() - lastIndexPointer); + lastIndexPointer = other->output->getFilePointer(); // write pointer + } + + lastTi->set(ti); + size++; +} + +void TermInfosWriter::close() { + //Func - Closes the TermInfosWriter + //Pre - true + //Post - The TermInfosWriter has been closed + + if (output){ + //write size at start + output->seek(4); // write size after format + output->writeLong(size); + output->close(); + _CLDELETE(output); + + if (!isIndex){ + if(other){ + other->close(); + _CLDELETE( other ); + } + } + _CLDECDELETE(lastTerm); + + _CLDELETE(lastTi); + } +} + +void TermInfosWriter::writeTerm(Term* term) +{ + int32_t start = Misc::stringDifference(lastTerm->text(),lastTerm->textLength(), + term->text(),term->textLength()); + int32_t length = term->textLength() - start; + + output->writeVInt(start); // write shared prefix length + output->writeVInt(length); // write delta length + output->writeChars(term->text(), start, length); // write delta chars + + int32_t fieldnum = fieldInfos->fieldNumber(term->field()); + CND_PRECONDITION(fieldnum>=-1&&fieldnumsize(),"Fieldnum is out of range"); + output->writeVInt(fieldnum); // write field num + + if ( lastTerm->__cl_refcount == 1 ){ + lastTerm->set(term,term->text()); + }else{ + _CLDECDELETE(lastTerm); + lastTerm = _CL_POINTER(term); + } +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/TermInfosWriter.h b/3rdparty/clucene/src/CLucene/index/TermInfosWriter.h new file mode 100644 index 0000000..7e3c686 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermInfosWriter.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_TermInfosWriter_ +#define _lucene_index_TermInfosWriter_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" +#include "FieldInfos.h" +#include "TermInfo.h" +#include "Term.h" + +CL_NS_DEF(index) + + +// This stores a monotonically increasing set of pairs in a +// Directory. A TermInfos can be written once, in order. +class TermInfosWriter : LUCENE_BASE +{ +private: + FieldInfos* fieldInfos; + CL_NS(store)::IndexOutput* output; + Term* lastTerm; + TermInfo* lastTi; + int64_t size; + int64_t lastIndexPointer; + bool isIndex; + TermInfosWriter* other; + + //inititalize + TermInfosWriter(CL_NS(store)::Directory* directory, + const QString& segment, FieldInfos* fis, int32_t interval, bool isIndex); +public: + /** The file format version, a negative number. */ + LUCENE_STATIC_CONSTANT(int32_t,FORMAT=-2); + + /** + * Expert: The fraction of terms in the "dictionary" which should be stored + * in RAM. Smaller values use more memory, but make searching slightly + * faster, while larger values use less memory and make searching slightly + * slower. Searching is typically not dominated by dictionary lookup, so + * tweaking this is rarely useful. + */ + int32_t indexInterval;// = 128 + + /** + * Expert: The fraction of {@link TermDocs} entries stored in skip tables, + * used to accellerate {@link TermDocs#SkipTo(int32_t)}. Larger values result in + * smaller indexes, greater acceleration, but fewer accelerable cases, while + * smaller values result in bigger indexes, less acceleration and more + * accelerable cases. More detailed experiments would be useful here. + */ + int32_t skipInterval;// = 16 + + TermInfosWriter(CL_NS(store)::Directory* directory, + const QString& segment, FieldInfos* fis, int32_t interval); + + ~TermInfosWriter(); + + /** + * Adds a new pair to the set. + * Term must be lexicographically greater than all previous Terms added. + * TermInfo pointers must be positive and greater than all previous. + */ + void add(Term* term, const TermInfo* ti); + + /** Called to complete TermInfos creation. */ + void close(); + +private: + /** Helps constructors to initialize instances */ + void initialise(CL_NS(store)::Directory* directory, + const QString& segment, int32_t interval, bool IsIndex); + void writeTerm(Term* term); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/TermVector.h b/3rdparty/clucene/src/CLucene/index/TermVector.h new file mode 100644 index 0000000..8601fbf --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermVector.h @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_index_termvector_h +#define _lucene_index_termvector_h + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" +#include "CLucene/store/IndexOutput.h" +#include "FieldInfos.h" + +CL_NS_DEF(index) + +struct TermVectorOffsetInfo; +class TermPositionVector; + +// Provides access to stored term vector of a document field. +class TermFreqVector : LUCENE_BASE +{ +public: + virtual ~TermFreqVector() {} + + // @return The field this vector is associated with. + virtual const TCHAR* getField() = 0; + + // @return The number of terms in the term vector. + virtual int32_t size() = 0; + + // @return An Array of term texts in ascending order. + virtual const TCHAR** getTerms() = 0; + + + /* Array of term frequencies. Locations of the array correspond one to one + * to the terms in the array obtained from getTerms + * method. Each location in the array contains the number of times this + * term occurs in the document or the document field. + * + * The size of the returned array is size() + * @memory Returning a pointer to internal data. Do not delete. + */ + virtual const Array* getTermFrequencies() = 0; + + + /* Return an index in the term numbers array returned from + * getTerms at which the term with the specified + * term appears. If this term does not appear in the array, + * return -1. + */ + virtual int32_t indexOf(const TCHAR* term) = 0; + + + /* Just like indexOf(int32_t) but searches for a number of terms + * at the same time. Returns an array that has the same size as the number + * of terms searched for, each slot containing the result of searching for + * that term number. + * + * @param terms array containing terms to look for + * @param start index in the array where the list of terms starts + * @param len the number of terms in the list + */ + virtual void indexesOf(const TCHAR** terms, const int32_t start, + const int32_t len, Array& ret) = 0; + + // Solve the diamond inheritence problem by providing a reinterpret function. + // No dynamic casting is required and no RTTI data is needed to do this + virtual TermPositionVector* __asTermPositionVector() = 0; +}; + + +/** +* Writer works by opening a document and then opening the fields within the document and then +* writing out the vectors for each field. +* +* Rough usage: +* + +for each document +{ +writer.openDocument(); +for each field on the document +{ +writer.openField(field); +for all of the terms +{ +writer.addTerm(...) +} +writer.closeField +} +writer.closeDocument() +} + +*/ +class TermVectorsWriter : LUCENE_BASE +{ +private: + class TVField : LUCENE_BASE + { + public: + int32_t number; + int64_t tvfPointer; + int32_t length; // number of distinct term positions + bool storePositions; + bool storeOffsets; + + TVField(int32_t number, bool storePos, bool storeOff) + : tvfPointer(0) + , length(0) + { + this->number = number; + this->storePositions = storePos; + this->storeOffsets = storeOff; + } + ~TVField() {} + }; + + class TVTerm : LUCENE_BASE + { + const TCHAR* termText; + int32_t termTextLen; //textlen cache + + public: + TVTerm(); + ~TVTerm(); + + int32_t freq; + Array* positions; + Array* offsets; + + const TCHAR* getTermText() const; + size_t getTermTextLen(); + void setTermText(const TCHAR* val); + }; + + CL_NS(store)::IndexOutput* tvx, *tvd, *tvf; + CL_NS(util)::CLVector > fields; + CL_NS(util)::CLVector > terms; + FieldInfos* fieldInfos; + + TVField* currentField; + int64_t currentDocPointer; + + void addTermInternal(const TCHAR* termText, const int32_t freq, + Array* positions, Array* offsets); + + void writeField(); + void writeDoc(); + + void openField(int32_t fieldNumber, bool storePositionWithTermVector, + bool storeOffsetWithTermVector); + +public: + LUCENE_STATIC_CONSTANT(int32_t, FORMAT_VERSION = 2); + + // The size in bytes that the FORMAT_VERSION will take up at the beginning + // of each file + LUCENE_STATIC_CONSTANT(int32_t, FORMAT_SIZE = 4); + + LUCENE_STATIC_CONSTANT(uint8_t, STORE_POSITIONS_WITH_TERMVECTOR = 0x1); + LUCENE_STATIC_CONSTANT(uint8_t, STORE_OFFSET_WITH_TERMVECTOR = 0x2); + + static const QLatin1String LUCENE_TVX_EXTENSION; + static const QLatin1String LUCENE_TVD_EXTENSION; + static const QLatin1String LUCENE_TVF_EXTENSION; + + TermVectorsWriter(CL_NS(store)::Directory* directory, const QString& segment, + FieldInfos* fieldInfos); + + ~TermVectorsWriter(); + void openDocument(); + void closeDocument(); + + /** Close all streams. */ + void close(); + bool isDocumentOpen() const; + + /** Start processing a field. This can be followed by a number of calls to + * addTerm, and a final call to closeField to indicate the end of + * processing of this field. If a field was previously open, it is + * closed automatically. + */ + void openField(const TCHAR* field); + + /** Finished processing current field. This should be followed by a call to + * openField before future calls to addTerm. + */ + void closeField(); + + /** Return true if a field is currently open. */ + bool isFieldOpen() const; + + /** + * Add a complete document specified by all its term vectors. If document has no + * term vectors, add value for tvx. + * + * @param vectors + * @throws IOException + */ + void addAllDocVectors(Array& vectors); + + /** Add term to the field's term vector. Field must already be open. + * Terms should be added in + * increasing order of terms, one call per unique termNum. ProxPointer + * is a pointer into the TermPosition file (prx). Freq is the number of + * times this term appears in this field, in this document. + * @throws IllegalStateException if document or field is not open + */ + void addTerm(const TCHAR* termText, int32_t freq, + Array* positions = NULL, Array* offsets = NULL); +}; + +class SegmentTermVector : public virtual TermFreqVector +{ +private: + const TCHAR* field; + TCHAR** terms; + int32_t termsLen; //cache + Array* termFreqs; + + int32_t binarySearch(TCHAR** a, const int32_t arraylen, const TCHAR* key) const; +public: + //note: termFreqs must be the same length as terms + SegmentTermVector(const TCHAR* field, TCHAR** terms, Array* termFreqs); + virtual ~SegmentTermVector(); + + /** + * + * @return The number of the field this vector is associated with + */ + const TCHAR* getField(); + TCHAR* toString() const; + int32_t size(); + const TCHAR** getTerms(); + const Array* getTermFrequencies(); + int32_t indexOf(const TCHAR* termText); + void indexesOf(const TCHAR** termNumbers, const int32_t start, const int32_t len, Array& ret); + + virtual TermPositionVector* __asTermPositionVector(); +}; + +class TermVectorsReader : LUCENE_BASE +{ +private: + FieldInfos* fieldInfos; + + CL_NS(store)::IndexInput* tvx; + CL_NS(store)::IndexInput* tvd; + CL_NS(store)::IndexInput* tvf; + int64_t _size; + + int32_t tvdFormat; + int32_t tvfFormat; + + + int32_t checkValidFormat(CL_NS(store)::IndexInput* in); + + void readTermVectors(const TCHAR** fields, const int64_t* tvfPointers, + const int32_t len, Array& _return); + + /** + * + * @param field The field to read in + * @param tvfPointer The pointer within the tvf file where we should start reading + * @return The TermVector located at that position + * @throws IOException + */ + SegmentTermVector* readTermVector(const TCHAR* field, const int64_t tvfPointer); + + int64_t size(); + + + DEFINE_MUTEX(THIS_LOCK) + TermVectorsReader(const TermVectorsReader& copy); +public: + TermVectorsReader(CL_NS(store)::Directory* d, const QString& segment, + FieldInfos* fieldInfos); + ~TermVectorsReader(); + + void close(); + TermVectorsReader* clone() const; + + /** + * Retrieve the term vector for the given document and field + * @param docNum The document number to retrieve the vector for + * @param field The field within the document to retrieve + * @return The TermFreqVector for the document and field or null if there is no termVector for this field. + * @throws IOException if there is an error reading the term vector files + */ + TermFreqVector* get(const int32_t docNum, const TCHAR* field); + + + /** + * Return all term vectors stored for this document or null if the could not be read in. + * + * @param docNum The document number to retrieve the vector for + * @return All term frequency vectors + * @throws IOException if there is an error reading the term vector files + */ + bool get(int32_t docNum, Array& result); +}; + + +struct TermVectorOffsetInfo +{ + int startOffset; + int endOffset; + +public: + static Array EMPTY_OFFSET_INFO; + TermVectorOffsetInfo(); + ~TermVectorOffsetInfo(); + TermVectorOffsetInfo(int32_t startOffset, int32_t endOffset); + int32_t getEndOffset() const; + void setEndOffset(int32_t endOffset); + int32_t getStartOffset() const; + void setStartOffset(int32_t startOffset); + bool equals(TermVectorOffsetInfo* o); + size_t hashCode() const; +}; + + +/* Extends TermFreqVector to provide additional information about + * positions in which each of the terms is found. A TermPositionVector not + * necessarily contains both positions and offsets, but at least one of these + * arrays exists. +*/ +class TermPositionVector : public virtual TermFreqVector +{ +public: + + /** Returns an array of positions in which the term is found. + * Terms are identified by the index at which its number appears in the + * term String array obtained from the indexOf method. + * May return null if positions have not been stored. + */ + virtual Array* getTermPositions(int32_t index) = 0; + + /** + * Returns an array of TermVectorOffsetInfo in which the term is found. + * May return null if offsets have not been stored. + * + * @see org.apache.lucene.analysis.Token + * + * @param index The position in the array to get the offsets from + * @return An array of TermVectorOffsetInfo objects or the empty list + */ + virtual Array* getOffsets(int32_t index) = 0; + + virtual ~TermPositionVector(){ + } +}; + + +class SegmentTermPositionVector: public SegmentTermVector, public TermPositionVector +{ +protected: + Array< Array >* positions; + Array< Array >* offsets; + static Array EMPTY_TERM_POS; +public: + SegmentTermPositionVector(const TCHAR* field, TCHAR** terms, + Array* termFreqs, Array< Array >* positions, + Array< Array >* offsets); + ~SegmentTermPositionVector(); + + /** + * Returns an array of TermVectorOffsetInfo in which the term is found. + * + * @param index The position in the array to get the offsets from + * @return An array of TermVectorOffsetInfo objects or the empty list + * @see org.apache.lucene.analysis.Token + */ + Array* getOffsets(int32_t index); + + /** + * Returns an array of positions in which the term is found. + * Terms are identified by the index at which its number appears in the + * term String array obtained from the indexOf method. + */ + Array* getTermPositions(int32_t index); + + const TCHAR* getField() { + return SegmentTermVector::getField(); } + + TCHAR* toString() const { + return SegmentTermVector::toString(); } + + int32_t size() { + return SegmentTermVector::size(); } + + const TCHAR** getTerms() { + return SegmentTermVector::getTerms(); } + + const Array* getTermFrequencies() { + return SegmentTermVector::getTermFrequencies(); } + + int32_t indexOf(const TCHAR* termText) { + return SegmentTermVector::indexOf(termText); } + + void indexesOf(const TCHAR** termNumbers, const int32_t start, + const int32_t len, Array& ret) { + SegmentTermVector::indexesOf(termNumbers, start, len, ret); } + + virtual TermPositionVector* __asTermPositionVector(); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/index/TermVectorReader.cpp b/3rdparty/clucene/src/CLucene/index/TermVectorReader.cpp new file mode 100644 index 0000000..53d909b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermVectorReader.cpp @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "TermVector.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(util) +CL_NS_DEF(index) + +TermVectorsReader::TermVectorsReader(CL_NS(store)::Directory* d, + const QString& segment, FieldInfos* fieldInfos) +{ + if (d->fileExists(segment + TermVectorsWriter::LUCENE_TVX_EXTENSION)) { + tvx = d->openInput(segment + TermVectorsWriter::LUCENE_TVX_EXTENSION); + checkValidFormat(tvx); + + tvd = d->openInput(segment + TermVectorsWriter::LUCENE_TVD_EXTENSION); + tvdFormat = checkValidFormat(tvd); + + tvf = d->openInput(segment + TermVectorsWriter::LUCENE_TVF_EXTENSION); + tvfFormat = checkValidFormat(tvf); + + _size = tvx->length() / 8; + }else{ + tvx = NULL; + tvd = NULL; + tvf = NULL; + _size = 0; + } + + this->fieldInfos = fieldInfos; +} + +TermVectorsReader::TermVectorsReader(const TermVectorsReader& copy) +{ + tvx = copy.tvx->clone(); + tvd = copy.tvd->clone(); + tvf = copy.tvf->clone(); + + tvdFormat = copy.tvdFormat; + tvfFormat = copy.tvfFormat; + _size = copy._size; + fieldInfos = copy.fieldInfos; +} +TermVectorsReader* TermVectorsReader::clone() const{ + if (tvx == NULL || tvd == NULL || tvf == NULL) + return NULL; + return _CLNEW TermVectorsReader(*this); +} + +TermVectorsReader::~TermVectorsReader(){ + close(); +} + +void TermVectorsReader::close(){ + // why don't we trap the exception and at least make sure that + // all streams that we can close are closed? + CLuceneError keep(0,"",false); + bool thrown = false; + + if (tvx != NULL){ + try{ + tvx->close(); + }catch(CLuceneError& err){ + if ( err.number() == CL_ERR_IO ){ + keep = err; + thrown = true; + }else + throw err; + } + _CLDELETE(tvx);//delete even if error thrown + } + if (tvd != NULL){ + try{ + tvd->close(); + }catch(CLuceneError& err){ + if ( err.number() == CL_ERR_IO ){ + keep = err; + thrown = true; + }else + throw err; + } + _CLDELETE(tvd); + } + if (tvf != NULL){ + try{ + tvf->close(); + }catch(CLuceneError& err){ + if ( err.number() == CL_ERR_IO ){ + keep = err; + thrown = true; + }else + throw err; + } + _CLDELETE(tvf); + } + + if ( thrown ) + throw keep; +} + +TermFreqVector* TermVectorsReader::get(const int32_t docNum, const TCHAR* field){ + // Check if no term vectors are available for this segment at all + int32_t fieldNumber = fieldInfos->fieldNumber(field); + TermFreqVector* result = NULL; + if (tvx != NULL) { + //We need to account for the FORMAT_SIZE at when seeking in the tvx + //We don't need to do this in other seeks because we already have the + // file pointer + //that was written in another file + tvx->seek((docNum * 8L) + TermVectorsWriter::FORMAT_SIZE); + int64_t position = tvx->readLong(); + + tvd->seek(position); + int32_t fieldCount = tvd->readVInt(); + // There are only a few fields per document. We opt for a full scan + // rather then requiring that they be ordered. We need to read through + // all of the fields anyway to get to the tvf pointers. + int32_t number = 0; + int32_t found = -1; + for (int32_t i = 0; i < fieldCount; ++i) { + if(tvdFormat == TermVectorsWriter::FORMAT_VERSION) + number = tvd->readVInt(); + else + number += tvd->readVInt(); + if (number == fieldNumber) + found = i; + } + + // This field, although valid in the segment, was not found in this + // document + if (found != -1) { + // Compute position in the tvf file + position = 0; + for (int32_t i = 0; i <= found; ++i) + position += tvd->readVLong(); + result = readTermVector(field, position); + } + } + return result; +} + + +bool TermVectorsReader::get(int32_t docNum, Array& result){ + // Check if no term vectors are available for this segment at all + if (tvx != NULL) { + //We need to offset by + tvx->seek((docNum * 8L) + TermVectorsWriter::FORMAT_SIZE); + int64_t position = tvx->readLong(); + + tvd->seek(position); + int32_t fieldCount = tvd->readVInt(); + + // No fields are vectorized for this document + if (fieldCount != 0) { + int32_t number = 0; + const TCHAR** fields = _CL_NEWARRAY(const TCHAR*,fieldCount+1); + + { //msvc6 scope fix + for (int32_t i = 0; i < fieldCount; ++i) { + if(tvdFormat == TermVectorsWriter::FORMAT_VERSION) + number = tvd->readVInt(); + else + number += tvd->readVInt(); + fields[i] = fieldInfos->fieldName(number); + } + } + fields[fieldCount]=NULL; + + // Compute position in the tvf file + position = 0; + int64_t* tvfPointers = _CL_NEWARRAY(int64_t,fieldCount); + { //msvc6 scope fix + for (int32_t i = 0; i < fieldCount; ++i) { + position += tvd->readVLong(); + tvfPointers[i] = position; + } + } + + readTermVectors(fields, tvfPointers, fieldCount, result); + _CLDELETE_ARRAY(tvfPointers); + _CLDELETE_ARRAY(fields); + } + return true; + } + return false; +} + + +int32_t TermVectorsReader::checkValidFormat(CL_NS(store)::IndexInput* in) +{ + int32_t format = in->readInt(); + if (format > TermVectorsWriter::FORMAT_VERSION) + { + CL_NS(util)::StringBuffer err; + err.append(_T("Incompatible format version: ")); + err.appendInt(format); + err.append(_T(" expected ")); + err.appendInt(TermVectorsWriter::FORMAT_VERSION); + err.append(_T(" or less")); + _CLTHROWT(CL_ERR_Runtime,err.getBuffer()); + } + return format; +} + +void TermVectorsReader::readTermVectors(const TCHAR** fields, + const int64_t* tvfPointers, const int32_t len, Array& result) +{ + result.length = len; + result.values = _CL_NEWARRAY(TermFreqVector*,len); + for (int32_t i = 0; i < len; ++i) { + result.values[i] = readTermVector(fields[i], tvfPointers[i]); + } +} + +SegmentTermVector* TermVectorsReader::readTermVector(const TCHAR* field, + const int64_t tvfPointer) +{ + // Now read the data from specified position. We don't need to offset by + // the FORMAT here since the pointer already includes the offset + tvf->seek(tvfPointer); + + int32_t numTerms = tvf->readVInt(); + // If no terms - return a constant empty termvector. However, this should never occur! + if (numTerms == 0) + return _CLNEW SegmentTermVector(field, NULL, NULL); + + bool storePositions; + bool storeOffsets; + + if(tvfFormat == TermVectorsWriter::FORMAT_VERSION){ + uint8_t bits = tvf->readByte(); + storePositions = (bits & TermVectorsWriter::STORE_POSITIONS_WITH_TERMVECTOR) != 0; + storeOffsets = (bits & TermVectorsWriter::STORE_OFFSET_WITH_TERMVECTOR) != 0; + } + else{ + tvf->readVInt(); + storePositions = false; + storeOffsets = false; + } + + TCHAR** terms = _CL_NEWARRAY(TCHAR*,numTerms+1); + Array* termFreqs = _CLNEW Array(numTerms); + + // we may not need these, but declare them + Array< Array >* positions = NULL; + Array< Array >* offsets = NULL; + if(storePositions){ + Array* tmp = _CL_NEWARRAY(Array,numTerms); + positions = _CLNEW Array< Array >(tmp, numTerms); + } + if(storeOffsets){ + Array* tmp = _CL_NEWARRAY(Array,numTerms); + offsets = _CLNEW Array< Array >(tmp, numTerms); + } + + int32_t start = 0; + int32_t deltaLength = 0; + int32_t totalLength = 0; + int32_t bufferLen=10; // init the buffer with a length of 10 character + TCHAR* buffer = (TCHAR*)malloc(bufferLen * sizeof(TCHAR)); + + for (int32_t i = 0; i < numTerms; ++i) { + start = tvf->readVInt(); + deltaLength = tvf->readVInt(); + totalLength = start + deltaLength; + if (bufferLen < totalLength) // increase buffer + { + buffer=(TCHAR*)realloc(buffer,totalLength * sizeof(TCHAR)); + bufferLen = totalLength; + } + + //read the term + tvf->readChars(buffer, start, deltaLength); + terms[i] = _CL_NEWARRAY(TCHAR,totalLength+1); + _tcsncpy(terms[i],buffer,totalLength); + terms[i][totalLength] = '\0'; //null terminate term + + //read the frequency + int32_t freq = tvf->readVInt(); + termFreqs->values[i] = freq; + + if (storePositions) { //read in the positions + Array& pos = positions->values[i]; + pos.length = freq; + pos.values = _CL_NEWARRAY(int32_t,freq); + + int32_t prevPosition = 0; + for (int32_t j = 0; j < freq; ++j) + { + pos.values[j] = prevPosition + tvf->readVInt(); + prevPosition = pos.values[j]; + } + } + + if (storeOffsets) { + Array& offs = offsets->values[i]; + offs.length = freq; + offs.values = _CL_NEWARRAY(TermVectorOffsetInfo,freq); + + int32_t prevOffset = 0; + for (int32_t j = 0; j < freq; ++j) { + int32_t startOffset = prevOffset + tvf->readVInt(); + int32_t endOffset = startOffset + tvf->readVInt(); + offs.values[j].setStartOffset(startOffset); + offs.values[j].setEndOffset(endOffset); + prevOffset = endOffset; + } + } + } + free(buffer); + terms[numTerms]=NULL; //null terminate terms array + + SegmentTermVector* tv = NULL; + if (storePositions || storeOffsets){ + return _CLNEW SegmentTermPositionVector(field, terms, termFreqs, positions, offsets); + }else { + return _CLNEW SegmentTermVector(field, terms, termFreqs); + } +} + +int64_t TermVectorsReader::size() +{ + return _size; +} + + + + +Array TermVectorOffsetInfo::EMPTY_OFFSET_INFO; + +TermVectorOffsetInfo::TermVectorOffsetInfo() +{ + startOffset = 0; + endOffset=0; +} + +TermVectorOffsetInfo::~TermVectorOffsetInfo() +{ +} + +TermVectorOffsetInfo::TermVectorOffsetInfo(int32_t startOffset, int32_t endOffset) +{ + this->endOffset = endOffset; + this->startOffset = startOffset; +} + +int32_t TermVectorOffsetInfo::getEndOffset() const +{ + return endOffset; +} + +void TermVectorOffsetInfo::setEndOffset(int32_t endOffset) +{ + this->endOffset = endOffset; +} + +int32_t TermVectorOffsetInfo::getStartOffset() const +{ + return startOffset; +} + +void TermVectorOffsetInfo::setStartOffset(int32_t startOffset) +{ + this->startOffset = startOffset; +} + +bool TermVectorOffsetInfo::equals(TermVectorOffsetInfo* termVectorOffsetInfo) +{ + if (this == termVectorOffsetInfo) + return true; + + if (endOffset != termVectorOffsetInfo->endOffset) return false; + if (startOffset != termVectorOffsetInfo->startOffset) return false; + + return true; +} + +size_t TermVectorOffsetInfo::hashCode() const +{ + size_t result; + result = startOffset; + result = 29 * result + endOffset; + return result; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/TermVectorWriter.cpp b/3rdparty/clucene/src/CLucene/index/TermVectorWriter.cpp new file mode 100644 index 0000000..276b1bb --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/TermVectorWriter.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "TermVector.h" +#include "CLucene/util/Misc.h" + +CL_NS_USE(util) +CL_NS_DEF(index) + +const QLatin1String TermVectorsWriter::LUCENE_TVX_EXTENSION(".tvx"); +const QLatin1String TermVectorsWriter::LUCENE_TVD_EXTENSION(".tvd"); +const QLatin1String TermVectorsWriter::LUCENE_TVF_EXTENSION(".tvf"); + +TermVectorsWriter::TermVectorsWriter(CL_NS(store)::Directory* directory, + const QString& segment,FieldInfos* fieldInfos) +{ + // Open files for TermVector storage + tvx = directory->createOutput(segment + LUCENE_TVX_EXTENSION); + tvx->writeInt(FORMAT_VERSION); + + tvd = directory->createOutput(segment + LUCENE_TVD_EXTENSION); + tvd->writeInt(FORMAT_VERSION); + + tvf = directory->createOutput(segment + LUCENE_TVF_EXTENSION); + tvf->writeInt(FORMAT_VERSION); + + this->fieldInfos = fieldInfos; + + currentField = NULL; + currentDocPointer = -1; +} + +TermVectorsWriter::~TermVectorsWriter() +{ + if (tvx != NULL) { + tvx->close(); + _CLDELETE(tvx); + } + + if (tvd != NULL) { + tvd->close(); + _CLDELETE(tvd); + } + + if (tvf != NULL){ + tvf->close(); + _CLDELETE(tvf); + } +} + +void TermVectorsWriter::openDocument() +{ + closeDocument(); + currentDocPointer = tvd->getFilePointer(); +} + +void TermVectorsWriter::closeDocument() +{ + if (isDocumentOpen()) { + closeField(); + writeDoc(); + fields.clear(); + currentDocPointer = -1; + } +} + +bool TermVectorsWriter::isDocumentOpen() const +{ + return currentDocPointer != -1; +} + + +void TermVectorsWriter::openField(int32_t fieldNumber, + bool storePositionWithTermVector, bool storeOffsetWithTermVector) +{ + if (!isDocumentOpen()) + _CLTHROWA(CL_ERR_InvalidState,"Cannot open field when no document is open."); + + closeField(); + currentField = _CLNEW TVField(fieldNumber, storePositionWithTermVector, + storeOffsetWithTermVector); +} + +void TermVectorsWriter::openField(const TCHAR* field) +{ + FieldInfo* fieldInfo = fieldInfos->fieldInfo(field); + openField(fieldInfo->number, fieldInfo->storePositionWithTermVector, + fieldInfo->storeOffsetWithTermVector); +} + +void TermVectorsWriter::closeField() +{ + if (isFieldOpen()) { + /* DEBUG */ + //System.out.println("closeField()"); + /* DEBUG */ + + // save field and terms + writeField(); + fields.push_back(currentField); + terms.clear(); + currentField = NULL; + } +} + +bool TermVectorsWriter::isFieldOpen() const +{ + return currentField != NULL; +} + +void TermVectorsWriter::addTerm(const TCHAR* termText, int32_t freq, + Array* positions, Array* offsets) +{ + if (!isDocumentOpen()) + _CLTHROWA(CL_ERR_InvalidState, "Cannot add terms when document is not open"); + + if (!isFieldOpen()) + _CLTHROWA(CL_ERR_InvalidState, "Cannot add terms when field is not open"); + + addTermInternal(termText, freq, positions, offsets); +} + +void TermVectorsWriter::addTermInternal(const TCHAR* termText, int32_t freq, + Array* positions, Array* offsets) +{ + TVTerm* term = _CLNEW TVTerm(); + term->setTermText(termText); + term->freq = freq; + term->positions = positions; + term->offsets = offsets; + terms.push_back(term); +} + +void TermVectorsWriter::addAllDocVectors(Array& vectors) +{ + openDocument(); + + for (int32_t i = 0; i < vectors.length; ++i) { + bool storePositionWithTermVector = false; + bool storeOffsetWithTermVector = false; + + if ( vectors[i]->__asTermPositionVector() != NULL ) { + TermPositionVector* tpVector = vectors[i]->__asTermPositionVector(); + + if (tpVector->size() > 0 && tpVector->getTermPositions(0) != NULL) + storePositionWithTermVector = true; + if (tpVector->size() > 0 && tpVector->getOffsets(0) != NULL) + storeOffsetWithTermVector = true; + + FieldInfo* fieldInfo = fieldInfos->fieldInfo(tpVector->getField()); + openField(fieldInfo->number, storePositionWithTermVector, storeOffsetWithTermVector); + + for (int32_t j = 0; j < tpVector->size(); ++j) + addTermInternal(tpVector->getTerms()[j], + (*tpVector->getTermFrequencies())[j], + tpVector->getTermPositions(j), + tpVector->getOffsets(j)); + + closeField(); + + } else { + TermFreqVector* tfVector = vectors[i]; + + FieldInfo* fieldInfo = fieldInfos->fieldInfo(tfVector->getField()); + openField(fieldInfo->number, storePositionWithTermVector, storeOffsetWithTermVector); + + for (int32_t j = 0; j < tfVector->size(); ++j) + addTermInternal(tfVector->getTerms()[j], + (*tfVector->getTermFrequencies())[j], NULL, NULL); + + closeField(); + } + } + + closeDocument(); +} + + +void TermVectorsWriter::close() +{ + try { + closeDocument(); + + // make an effort to close all streams we can but remember and re-throw + // the first exception encountered in this process +#define _DOTVWCLOSE(x) \ + if (x != NULL) { \ + try { \ + x->close(); \ + _CLDELETE(x) \ + } catch (CLuceneError& e) { \ + if ( e.number() != CL_ERR_IO ) \ + throw e; \ + if (ikeep == 0) \ + ikeep = e.number(); \ + if (keep[0] == 0) \ + strcpy(keep,e.what()); \ + } catch (...) { \ + if (keep[0] == 0) \ + strcpy(keep, "Unknown error while closing " #x);\ + } \ + } + } _CLFINALLY ( \ + char keep[200]; + int32_t ikeep = 0; + keep[0] = 0; + _DOTVWCLOSE(tvx); + _DOTVWCLOSE(tvd); + _DOTVWCLOSE(tvf); + if (keep[0] != 0) + _CLTHROWA(ikeep, keep); + ); +} + +void TermVectorsWriter::writeField() +{ + // remember where this field is written + currentField->tvfPointer = tvf->getFilePointer(); + //System.out.println("Field Pointer: " + currentField.tvfPointer); + int32_t size = terms.size(); + + tvf->writeVInt(size); + + bool storePositions = currentField->storePositions; + bool storeOffsets = currentField->storeOffsets; + uint8_t bits = 0x0; + if (storePositions) + bits |= STORE_POSITIONS_WITH_TERMVECTOR; + if (storeOffsets) + bits |= STORE_OFFSET_WITH_TERMVECTOR; + tvf->writeByte(bits); + + const TCHAR* lastTermText = LUCENE_BLANK_STRING; + int32_t lastTermTextLen = 0; + + for (int32_t i = 0; i < size; ++i) { + TVTerm* term = terms[i]; + int32_t start = CL_NS(util)::Misc::stringDifference(lastTermText, + lastTermTextLen, term->getTermText(),term->getTermTextLen()); + int32_t length = term->getTermTextLen() - start; + tvf->writeVInt(start); // write shared prefix length + tvf->writeVInt(length); // write delta length + tvf->writeChars(term->getTermText(), start, length); // write delta chars + tvf->writeVInt(term->freq); + + lastTermText = term->getTermText(); + lastTermTextLen = term->getTermTextLen(); + + if (storePositions) { + if(term->positions == NULL) + _CLTHROWA(CL_ERR_IllegalState, "Trying to write positions that are NULL!"); + + // use delta encoding for positions + int32_t position = 0; + for (int32_t j = 0; j < term->freq; ++j){ + tvf->writeVInt((*term->positions)[j] - position); + position = (*term->positions)[j]; + } + } + + if (storeOffsets) { + if(term->offsets == NULL) + _CLTHROWA(CL_ERR_IllegalState, "Trying to write offsets that are NULL!"); + + // use delta encoding for offsets + int32_t position = 0; + for (int32_t j = 0; j < term->freq; ++j) { + tvf->writeVInt((*term->offsets)[j].getStartOffset() - position); + //Save the diff between the two. + tvf->writeVInt((*term->offsets)[j].getEndOffset() - + (*term->offsets)[j].getStartOffset()); + position = (*term->offsets)[j].getEndOffset(); + } + } + } +} + +void TermVectorsWriter::writeDoc() +{ + if (isFieldOpen()) { + _CLTHROWA(CL_ERR_InvalidState, + "Field is still open while writing document"); + } + + // write document index record + tvx->writeLong(currentDocPointer); + + // write document data record + int32_t size = fields.size(); + + // write the number of fields + tvd->writeVInt(size); + + // write field numbers + for (int32_t j = 0; j < size; ++j) { + tvd->writeVInt(fields[j]->number); + } + + // write field pointers + int64_t lastFieldPointer = 0; + for (int32_t i = 0; i < size; ++i) { + TVField* field = (TVField*) fields[i]; + tvd->writeVLong(field->tvfPointer - lastFieldPointer); + + lastFieldPointer = field->tvfPointer; + } +} + +const TCHAR* TermVectorsWriter::TVTerm::getTermText() const +{ + return termText; +} + +size_t TermVectorsWriter::TVTerm::getTermTextLen() +{ + if (termTextLen==-1) + termTextLen = _tcslen(termText); + return termTextLen; +} + +void TermVectorsWriter::TVTerm::setTermText(const TCHAR* val) +{ + _CLDELETE_CARRAY(termText); + termText = STRDUP_TtoT(val); + termTextLen = -1; + +} + +TermVectorsWriter::TVTerm::TVTerm() + : freq(0) + , positions(NULL) + , offsets(NULL) +{ + termText=NULL; + termTextLen=-1; +} + +TermVectorsWriter::TVTerm::~TVTerm() +{ + _CLDELETE_CARRAY(termText) +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/index/Terms.h b/3rdparty/clucene/src/CLucene/index/Terms.h new file mode 100644 index 0000000..8064418 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/index/Terms.h @@ -0,0 +1,174 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_index_Terms_ +#define _lucene_index_Terms_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Term.h" +CL_NS_DEF(index) + +class TermEnum; //predefine +class TermPositions; + +/** TermDocs provides an interface for enumerating <document, frequency> + pairs for a term.

The document portion names each document containing + the term. Documents are indicated by number. The frequency portion gives + the number of times the term occurred in each document.

The pairs are + ordered by document number. + + @see IndexReader#termDocs() + */ +class TermDocs: LUCENE_BASE { +public: + virtual ~TermDocs(){ + } + + // Sets this to the data for a term. + // The enumeration is reset to the start of the data for this term. + virtual void seek(Term* term)=0; + + /** Sets this to the data for the current term in a {@link TermEnum}. + * This may be optimized in some implementations. + */ + virtual void seek(TermEnum* termEnum)=0; + + // Returns the current document number.

This is invalid until {@link + // #next()} is called for the first time. + virtual int32_t doc() const=0; + + // Returns the frequency of the term within the current document.

This + // is invalid until {@link #next()} is called for the first time. + virtual int32_t freq() const=0; + + // Moves to the next pair in the enumeration.

Returns true iff there is + // such a next pair in the enumeration. + virtual bool next() =0; + + // Attempts to read multiple entries from the enumeration, up to length of + // docs. Document numbers are stored in docs, and term + // frequencies are stored in freqs. The freqs array must be as + // int64_t as the docs array. + // + //

Returns the number of entries read. Zero is only returned when the + // stream has been exhausted. + virtual int32_t read(int32_t* docs, int32_t* freqs, int32_t length)=0; + + // Skips entries to the first beyond the current whose document number is + // greater than or equal to target.

Returns true iff there is such + // an entry.

Behaves as if written:

+	//   bool skipTo(int32_t target) {
+	//     do {
+	//       if (!next())
+	// 	     return false;
+	//     } while (target > doc());
+	//     return true;
+	//   }
+	// 
+ // Some implementations are considerably more efficient than that. + virtual bool skipTo(const int32_t target)=0; + + // Frees associated resources. + virtual void close() = 0; + + + /** Solve the diamond inheritence problem by providing a reinterpret function. + * No dynamic casting is required and no RTTI data is needed to do this + */ + virtual TermPositions* __asTermPositions()=0; +}; + + +// Abstract class for enumerating terms. +// +//

Term enumerations are always ordered by Term.compareTo(). Each term in +//the enumeration is greater than all that precede it. +class TermEnum: LUCENE_BASE { +public: + // Increments the enumeration to the next element. True if one exists. + virtual bool next()=0; + + // Returns a pointer to the current Term in the enumeration. + virtual Term* term()=0; + + // Returns the current Term in the enumeration. + virtual Term* term(bool pointer){ + Term* ret = term(); + if ( !pointer ) + ret->__cl_decref(); + return ret; + } + + // Returns the docFreq of the current Term in the enumeration. + virtual int32_t docFreq() const=0; + + // Closes the enumeration to further activity, freeing resources. + virtual void close() =0; + + virtual ~TermEnum(){ + } + + // Term Vector support + /** Skips terms to the first beyond the current whose value is + * greater or equal to target.

Returns true iff there is such + * an entry.

Behaves as if written:

+	*   public boolean skipTo(Term target) {
+	*     do {
+	*       if (!next())
+	* 	     return false;
+	*     } while (target > term());
+	*     return true;
+	*   }
+	* 
+ * Some implementations are considerably more efficient than that. + */ + virtual bool skipTo(Term* target){ + do { + if (!next()) + return false; + } while (target->compareTo(term(false)) > 0); + return true; + } + + /** + * Because we need to know how to cast the object, we need the objects name. + */ + virtual const char* getObjectName() = 0; +}; + + + +/** + * TermPositions provides an interface for enumerating the <document, + * frequency, <position>* > tuples for a term.

The document and + * frequency are the same as for a TermDocs. The positions portion lists the ordinal + * positions of each occurrence of a term in a document. + * + * @see IndexReader#termPositions() + */ +class TermPositions: public virtual TermDocs { +public: + // Returns next position in the current document. It is an error to call + // this more than {@link #freq()} times + // without calling {@link #next()}

This is + // invalid until {@link #next()} is called for + // the first time. + virtual int32_t nextPosition() = 0; + + virtual ~TermPositions(){ + } + + /** Solve the diamond inheritence problem by providing a reinterpret function. + * No dynamic casting is required and no RTTI data is needed to do this + */ + virtual TermDocs* __asTermDocs()=0; + virtual TermPositions* __asTermPositions()=0; +}; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/queryParser/Lexer.cpp b/3rdparty/clucene/src/CLucene/queryParser/Lexer.cpp new file mode 100644 index 0000000..861c5d3 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/Lexer.cpp @@ -0,0 +1,371 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Lexer.h" + +#include "CLucene/util/FastCharStream.h" +#include "CLucene/util/Reader.h" +#include "CLucene/util/StringBuffer.h" +#include "TokenList.h" +#include "QueryToken.h" +#include "QueryParserBase.h" + +CL_NS_USE(util) + +CL_NS_DEF(queryParser) +Lexer::Lexer(QueryParserBase* queryparser, const TCHAR* query) { + //Func - Constructor + //Pre - query != NULL and contains the query string + //Post - An instance of Lexer has been created + + this->queryparser = queryparser; + + CND_PRECONDITION(query != NULL, "query is NULL"); + + //The InputStream of Reader must be destroyed in the destructor + delSR = true; + + StringReader *r = _CLNEW StringReader(query); + + //Check to see if r has been created properly + CND_CONDITION(r != NULL, "Could not allocate memory for StringReader r"); + + //Instantie a FastCharStream instance using r and assign it to reader + reader = _CLNEW FastCharStream(r); + + //Check to see if reader has been created properly + CND_CONDITION(reader != NULL, "Could not allocate memory for FastCharStream reader"); + + //The InputStream of Reader must be destroyed in the destructor + delSR = true; + +} + + +Lexer::Lexer(QueryParserBase* queryparser, Reader* source) { + //Func - Constructor + // Initializes a new instance of the Lexer class with the specified + // TextReader to lex. + //Pre - Source contains a valid reference to a Reader + //Post - An instance of Lexer has been created using source as the reader + + this->queryparser = queryparser; + + //Instantie a FastCharStream instance using r and assign it to reader + reader = _CLNEW FastCharStream(source); + + //Check to see if reader has been created properly + CND_CONDITION(reader != NULL, "Could not allocate memory for FastCharStream reader"); + + //The InputStream of Reader must not be destroyed in the destructor + delSR = false; +} + + +Lexer::~Lexer() { + //Func - Destructor + //Pre - true + //Post - if delSR was true the InputStream input of reader has been deleted + // The instance of Lexer has been destroyed + + if (delSR) { + _CLDELETE(reader->input); + } + + _CLDELETE(reader); +} + + +void Lexer::Lex(TokenList *tokenList) { + //Func - Breaks the input stream onto the tokens list tokens + //Pre - tokens != NULL and contains a TokenList in which the tokens can be stored + //Post - The tokens have been added to the TokenList tokens + + CND_PRECONDITION(tokenList != NULL, "tokens is NULL"); + + //Get all the tokens + while(true) { + //Add the token to the tokens list + + //Get the next token + QueryToken* token = _CLNEW QueryToken; + if ( !GetNextToken(token) ){ + _CLDELETE(token); + break; + } + tokenList->add(token); + } + + //The end has been reached so create an EOF_ token + //Add the final token to the TokenList _tokens + tokenList->add(_CLNEW QueryToken( QueryToken::EOF_)); +} + + +bool Lexer::GetNextToken(QueryToken* token) { + while(!reader->Eos()) { + int ch = reader->GetNext(); + + if ( ch == -1 ) + break; + + // skipping whitespaces + if( _istspace(ch)!=0 ) { + continue; + } + TCHAR buf[2] = {ch,'\0'}; + switch(ch) { + case '+': + token->set(buf, QueryToken::PLUS); + return true; + case '-': + token->set(buf, QueryToken::MINUS); + return true; + case '(': + token->set(buf, QueryToken::LPAREN); + return true; + case ')': + token->set(buf, QueryToken::RPAREN); + return true; + case ':': + token->set(buf, QueryToken::COLON); + return true; + case '!': + token->set(buf, QueryToken::NOT); + return true; + case '^': + token->set(buf, QueryToken::CARAT); + return true; + case '~': + if( _istdigit( reader->Peek() )!=0 ) { + TCHAR number[LUCENE_MAX_FIELD_LEN]; + ReadIntegerNumber(ch, number,LUCENE_MAX_FIELD_LEN); + token->set(number, QueryToken::SLOP); + return true; + }else{ + token->set(buf, QueryToken::FUZZY); + return true; + } + break; + case '"': + return ReadQuoted(ch, token); + case '[': + return ReadInclusiveRange(ch, token); + case '{': + return ReadExclusiveRange(ch, token); + case ']': + case '}': + case '*': + queryparser->throwParserException( _T("Unrecognized TCHAR %d at %d::%d."), + ch, reader->Column(), reader->Line() ); + return false; + default: + return ReadTerm(ch, token); + + // end of swith + } + + } + return false; +} + + +void Lexer::ReadIntegerNumber(const TCHAR ch, TCHAR* buf, int buflen) { + int bp=0; + buf[bp++] = ch; + + int c = reader->Peek(); + while( c!=-1 && _istdigit(c)!=0 && bpGetNext(); + c = reader->Peek(); + } + buf[bp++] = 0; +} + + +bool Lexer::ReadInclusiveRange(const TCHAR prev, QueryToken* token) { + int ch = prev; + StringBuffer range; + range.appendChar(ch); + + while(!reader->Eos()) { + ch = reader->GetNext(); + if ( ch == -1 ) + break; + range.appendChar(ch); + + if(ch == ']'){ + token->set(range.getBuffer(), QueryToken::RANGEIN); + return true; + } + } + queryparser->throwParserException(_T("Unterminated inclusive range! %d %d::%d"),' ', + reader->Column(),reader->Column()); + return false; +} + + +bool Lexer::ReadExclusiveRange(const TCHAR prev, QueryToken* token) { + int ch = prev; + StringBuffer range; + range.appendChar(ch); + + while(!reader->Eos()) { + ch = reader->GetNext(); + + if (ch==-1) + break; + range.appendChar(ch); + + if(ch == '}'){ + token->set(range.getBuffer(), QueryToken::RANGEEX); + return true; + } + } + queryparser->throwParserException(_T("Unterminated exclusive range! %d %d::%d"),' ', + reader->Column(),reader->Column() ); + return false; +} + +bool Lexer::ReadQuoted(const TCHAR prev, QueryToken* token) { + int ch = prev; + StringBuffer quoted; + quoted.appendChar(ch); + + while(!reader->Eos()) { + ch = reader->GetNext(); + + if (ch==-1) + break; + + quoted.appendChar(ch); + + if(ch == '"'){ + token->set(quoted.getBuffer(), QueryToken::QUOTED); + return true; + } + } + queryparser->throwParserException(_T("Unterminated string! %d %d::%d"),' ', + reader->Column(),reader->Column()); + return false; +} + + +bool Lexer::ReadTerm(const TCHAR prev, QueryToken* token) { + int ch = prev; + bool completed = false; + int32_t asteriskCount = 0; + bool hasQuestion = false; + + StringBuffer val; + TCHAR buf[3]; //used for readescaped + + while(true) { + switch(ch) { + case -1: + break; + case '\\': + { + if ( ReadEscape(ch, buf) ) + val.append( buf ); + else + return false; + } + break; + + case LUCENE_WILDCARDTERMENUM_WILDCARD_STRING: + asteriskCount++; + val.appendChar(ch); + break; + case LUCENE_WILDCARDTERMENUM_WILDCARD_CHAR: + hasQuestion = true; + val.appendChar(ch); + break; + case '\n': + case '\t': + case ' ': + case '+': + case '-': + case '!': + case '(': + case ')': + case ':': + case '^': + case '[': + case ']': + case '{': + case '}': + case '~': + case '"': + // create new QueryToken + reader->UnGet(); + completed = true; + break; + default: + val.appendChar(ch); + break; + // end of switch + } + + if(completed || ch==-1 || reader->Eos() ) + break; + else + ch = reader->GetNext(); + } + + // create new QueryToken + if(hasQuestion) + token->set(val.getBuffer(), QueryToken::WILDTERM); + else if(asteriskCount == 1 && val.getBuffer()[val.length() - 1] == '*') + token->set(val.getBuffer(), QueryToken::PREFIXTERM); + else if(asteriskCount > 0) + token->set(val.getBuffer(), QueryToken::WILDTERM); + else if( _tcsicmp(val.getBuffer(), _T("AND"))==0 || _tcscmp(val.getBuffer(), _T("&&"))==0 ) + token->set(val.getBuffer(), QueryToken::AND_); + else if( _tcsicmp(val.getBuffer(), _T("OR"))==0 || _tcscmp(val.getBuffer(), _T("||"))==0) + token->set(val.getBuffer(), QueryToken::OR); + else if( _tcsicmp(val.getBuffer(), _T("NOT"))==0 ) + token->set(val.getBuffer(), QueryToken::NOT); + else { + bool isnum = true; + int32_t nlen=val.length(); + for (int32_t i=0;iset(val.getBuffer(), QueryToken::NUMBER); + else + token->set(val.getBuffer(), QueryToken::TERM); + } + return true; +} + + +bool Lexer::ReadEscape(TCHAR prev, TCHAR* buf) { + TCHAR ch = prev; + int bp=0; + buf[bp++] = ch; + + ch = reader->GetNext(); + int32_t idx = _tcscspn( buf, _T("\\+-!():^[]{}\"~*") ); + if(idx == 0) { + buf[bp++] = ch; + buf[bp++]=0; + return true; + } + queryparser->throwParserException(_T("Unrecognized escape sequence at %d %d::%d"), ' ', + reader->Column(),reader->Line()); + return false; +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/queryParser/Lexer.h b/3rdparty/clucene/src/CLucene/queryParser/Lexer.h new file mode 100644 index 0000000..b3b5552 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/Lexer.h @@ -0,0 +1,67 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#ifndef _lucene_queryParser_Lexer_ +#define _lucene_queryParser_Lexer_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/FastCharStream.h" +#include "CLucene/util/Reader.h" +#include "CLucene/util/StringBuffer.h" + +#include "TokenList.h" + +CL_NS_DEF(queryParser) +class QueryParserBase; + // A simple Lexer that is used by QueryParser. + class Lexer:LUCENE_BASE + { + private: + CL_NS(util)::FastCharStream* reader; + QueryParserBase* queryparser; //holds the queryparser so that we can do callbacks + bool delSR; //Indicates if the reader must be deleted or not + + public: + // Initializes a new instance of the Lexer class with the specified + // query to lex. + Lexer(QueryParserBase* queryparser, const TCHAR* query); + + // Initializes a new instance of the Lexer class with the specified + // TextReader to lex. + Lexer(QueryParserBase* queryparser, CL_NS(util)::Reader* source); + + //Breaks the input stream onto the tokens list tokens + void Lex(TokenList *tokens); + + ~Lexer(); + + private: + bool GetNextToken(QueryToken* token); + + // Reads an integer number. buf should quite large, probably as large as a field should ever be + void ReadIntegerNumber(const TCHAR ch, TCHAR* buf, int buflen); + + // Reads an inclusive range like [some words] + bool ReadInclusiveRange(const TCHAR prev, QueryToken* token); + + // Reads an exclusive range like {some words} + bool ReadExclusiveRange(const TCHAR prev, QueryToken* token); + + // Reads quoted string like "something else" + bool ReadQuoted(const TCHAR prev, QueryToken* token); + + bool ReadTerm(const TCHAR prev, QueryToken* token); + + //reads an escaped character into the buf. Buf requires at least 3 characters + bool ReadEscape(const TCHAR prev, TCHAR* buf); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.cpp b/3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.cpp new file mode 100644 index 0000000..b57896b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.cpp @@ -0,0 +1,215 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "MultiFieldQueryParser.h" +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/search/BooleanQuery.h" +#include "CLucene/search/PhraseQuery.h" +#include "CLucene/search/SearchHeader.h" +#include "QueryParser.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_USE(search) +CL_NS_USE(analysis) + +CL_NS_DEF(queryParser) + +MultiFieldQueryParser::MultiFieldQueryParser(const TCHAR** fields, + CL_NS(analysis)::Analyzer* analyzer, BoostMap* boosts) + : QueryParser(NULL, analyzer) +{ + this->fields = fields; + this->boosts = boosts; +} + +MultiFieldQueryParser::~MultiFieldQueryParser() +{ +} + +//static +Query* MultiFieldQueryParser::parse(const TCHAR* query, const TCHAR** fields, + Analyzer* analyzer) +{ + BooleanQuery* bQuery = _CLNEW BooleanQuery(); + int32_t i = 0; + while (fields[i] != NULL){ + Query* q = QueryParser::parse(query, fields[i], analyzer); + if (q && (q->getQueryName() != _T("BooleanQuery") + || ((BooleanQuery*)q)->getClauseCount() > 0)) { + bQuery->add(q , true, false, false); + } else { + _CLDELETE(q); + } + i++; + } + return bQuery; +} + +//static +Query* MultiFieldQueryParser::parse(const TCHAR* query, const TCHAR** fields, + const uint8_t* flags, Analyzer* analyzer) +{ + BooleanQuery* bQuery = _CLNEW BooleanQuery(); + int32_t i = 0; + while ( fields[i] != NULL ) { + Query* q = QueryParser::parse(query, fields[i], analyzer); + if (q && (q->getQueryName() != _T("BooleanQuery") + || ((BooleanQuery*)q)->getClauseCount() > 0)) { + uint8_t flag = flags[i]; + switch (flag) { + case MultiFieldQueryParser::REQUIRED_FIELD: + bQuery->add(q, true, true, false); + break; + case MultiFieldQueryParser::PROHIBITED_FIELD: + bQuery->add(q, true, false, true); + break; + default: + bQuery->add(q, true, false, false); + break; + } + } else { + _CLDELETE(q); + } + i++; + } + return bQuery; +} + + +Query* MultiFieldQueryParser::GetFieldQuery(const TCHAR* field, TCHAR* queryText, int32_t slop){ + if (field == NULL) { + CL_NS_STD(vector) clauses; + for (int i = 0; fields[i]!=NULL; ++i) { + Query* q = QueryParser::GetFieldQuery(fields[i], queryText); + if (q != NULL) { + //If the user passes a map of boosts + if (boosts != NULL) { + //Get the boost from the map and apply them + BoostMap::const_iterator itr = boosts->find(fields[i]); + if (itr != boosts->end()) { + q->setBoost(itr->second); + } + } + if (q->getQueryName() == PhraseQuery::getClassName()) { + ((PhraseQuery*)q)->setSlop(slop); + } + //if (q instanceof MultiPhraseQuery) { + // ((MultiPhraseQuery) q).setSlop(slop); + //} + q = QueryAddedCallback(fields[i], q); + if ( q ) + clauses.push_back(_CLNEW BooleanClause(q, true, false,false)); + } + } + if (clauses.size() == 0) // happens for stopwords + return NULL; + Query* q = QueryParser::GetBooleanQuery(clauses); + return q; + }else{ + Query* q = QueryParser::GetFieldQuery(field, queryText); + if ( q ) + q = QueryAddedCallback(field,q); + return q; + } +} + + +Query* MultiFieldQueryParser::GetFieldQuery(const TCHAR* field, TCHAR* queryText){ + return GetFieldQuery(field, queryText, 0); +} + + +CL_NS(search)::Query* MultiFieldQueryParser::GetFuzzyQuery(const TCHAR* field, TCHAR* termStr){ + if (field == NULL) { + CL_NS_STD(vector) clauses; + for (int i = 0; fields[i]!=NULL; ++i) { + Query* q = QueryParser::GetFuzzyQuery(fields[i], termStr); //todo: , minSimilarity + if ( q ){ + q = QueryAddedCallback(fields[i], q); + if ( q ){ + clauses.push_back(_CLNEW BooleanClause(q,true,false,false) ); + } + } + } + return QueryParser::GetBooleanQuery(clauses); + }else{ + Query* q = QueryParser::GetFuzzyQuery(field, termStr);//todo: , minSimilarity + if ( q ) + q = QueryAddedCallback(field,q); + return q; + } +} + +Query* MultiFieldQueryParser::GetPrefixQuery(const TCHAR* field, TCHAR* termStr){ + if (field == NULL) { + CL_NS_STD(vector) clauses; + for (int i = 0; fields[i]!=NULL; ++i) { + Query* q = QueryParser::GetPrefixQuery(fields[i], termStr); + if ( q ){ + q = QueryAddedCallback(fields[i],q); + if ( q ){ + clauses.push_back(_CLNEW BooleanClause(q,true,false,false)); + } + } + } + return QueryParser::GetBooleanQuery(clauses); + }else{ + Query* q = QueryParser::GetPrefixQuery(field, termStr); + if ( q ) + q = QueryAddedCallback(field,q); + return q; + } +} + +Query* MultiFieldQueryParser::GetWildcardQuery(const TCHAR* field, TCHAR* termStr){ + if (field == NULL) { + CL_NS_STD(vector) clauses; + for (int i = 0; fields[i]!=NULL; ++i) { + Query* q = QueryParser::GetWildcardQuery(fields[i], termStr); + if ( q ){ + q = QueryAddedCallback(fields[i],q); + if ( q ){ + clauses.push_back(_CLNEW BooleanClause(q,true,false,false)); + } + } + } + return QueryParser::GetBooleanQuery(clauses); + }else{ + Query* q = QueryParser::GetWildcardQuery(field, termStr); + if ( q ) + q = QueryAddedCallback(field,q); + return q; + } +} + + +Query* MultiFieldQueryParser::GetRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, bool inclusive){ + if (field == NULL) { + CL_NS_STD(vector) clauses; + for (int i = 0; fields[i]!=NULL; ++i) { + Query* q = QueryParser::GetRangeQuery(fields[i], part1, part2, inclusive); + if ( q ){ + q = QueryAddedCallback(fields[i],q); + if ( q ){ + clauses.push_back(_CLNEW BooleanClause(q,true,false,false)); + } + } + } + return QueryParser::GetBooleanQuery(clauses); + }else{ + Query* q = QueryParser::GetRangeQuery(field, part1, part2, inclusive); + if ( q ) + q = QueryAddedCallback(field,q); + return q; + } +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.h b/3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.h new file mode 100644 index 0000000..bf7d652 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/MultiFieldQueryParser.h @@ -0,0 +1,136 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef MultiFieldQueryParser_H +#define MultiFieldQueryParser_H + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/search/SearchHeader.h" +#include "QueryParser.h" + + +CL_NS_DEF(queryParser) + +typedef CL_NS(util)::CLHashMap BoostMap; + + /** + * A QueryParser which constructs queries to search multiple fields. + * + */ + class MultiFieldQueryParser: public QueryParser + { + protected: + const TCHAR** fields; + BoostMap* boosts; + public: + LUCENE_STATIC_CONSTANT(uint8_t, NORMAL_FIELD=0); + LUCENE_STATIC_CONSTANT(uint8_t, REQUIRED_FIELD=1); + LUCENE_STATIC_CONSTANT(uint8_t, PROHIBITED_FIELD=2); + + /** + * Creates a MultiFieldQueryParser. + * + *

It will, when parse(String query) + * is called, construct a query like this (assuming the query consists of + * two terms and you specify the two fields title and body):

+ * + * + * (title:term1 body:term1) (title:term2 body:term2) + * + * + *

When setDefaultOperator(AND_OPERATOR) is set, the result will be:

+ * + * + * +(title:term1 body:term1) +(title:term2 body:term2) + * + * + *

In other words, all the query's terms must appear, but it doesn't matter in + * what fields they appear.

+ */ + MultiFieldQueryParser(const TCHAR** fields, CL_NS(analysis)::Analyzer* a, BoostMap* boosts = NULL); + virtual ~MultiFieldQueryParser(); + + /** + *

+ * Parses a query which searches on the fields specified. + *

+ * If x fields are specified, this effectively constructs: + *

+         * 
+         * (field1:query) (field2:query) (field3:query)...(fieldx:query)
+         * 
+         * 
+ * + * @param query Query string to parse + * @param fields Fields to search on + * @param analyzer Analyzer to use + * @throws ParserException if query parsing fails + * @throws TokenMgrError if query parsing fails + */ + static CL_NS(search)::Query* parse(const TCHAR* query, const TCHAR** fields, CL_NS(analysis)::Analyzer* analyzer); + + /** + *

+ * Parses a query, searching on the fields specified. + * Use this if you need to specify certain fields as required, + * and others as prohibited. + *

+         * Usage:
+         * 
+         * String[] fields = {"filename", "contents", "description"};
+         * int32_t[] flags = {MultiFieldQueryParser.NORMAL FIELD,
+         *                MultiFieldQueryParser.REQUIRED FIELD,
+         *                MultiFieldQueryParser.PROHIBITED FIELD,};
+         * parse(query, fields, flags, analyzer);
+         * 
+         * 
+ *

+ * The code above would construct a query: + *

+         * 
+         * (filename:query) +(contents:query) -(description:query)
+         * 
+         * 
+ * + * @param query Query string to parse + * @param fields Fields to search on + * @param flags Flags describing the fields + * @param analyzer Analyzer to use + * @throws ParserException if query parsing fails + * @throws TokenMgrError if query parsing fails + */ + static CL_NS(search)::Query* parse(const TCHAR* query, const TCHAR** fields, const uint8_t* flags, CL_NS(analysis)::Analyzer* analyzer); + + + + protected: + CL_NS(search)::Query* GetFieldQuery(const TCHAR* field, TCHAR* queryText); + CL_NS(search)::Query* GetFieldQuery(const TCHAR* field, TCHAR* queryText, int32_t slop); + CL_NS(search)::Query* GetFuzzyQuery(const TCHAR* field, TCHAR* termStr); + CL_NS(search)::Query* GetRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, bool inclusive); + CL_NS(search)::Query* GetPrefixQuery(const TCHAR* field, TCHAR* termStr); + CL_NS(search)::Query* GetWildcardQuery(const TCHAR* field, TCHAR* termStr); + + /** + * A special virtual function for the MultiFieldQueryParser which can be used + * to clean up queries. Once the field name is known and the query has been + * created, its passed to this function. + * An example of this usage is to set boosts. + */ + virtual CL_NS(search)::Query* QueryAddedCallback(const TCHAR* field, CL_NS(search)::Query* query){ return query; } + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/queryParser/QueryParser.cpp b/3rdparty/clucene/src/CLucene/queryParser/QueryParser.cpp new file mode 100644 index 0000000..b11eec0 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/QueryParser.cpp @@ -0,0 +1,509 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "QueryParser.h" + +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/util/Reader.h" +#include "CLucene/search/SearchHeader.h" +#include "CLucene/index/Term.h" + +#include "TokenList.h" +#include "QueryToken.h" +#include "QueryParserBase.h" +#include "Lexer.h" + +CL_NS_USE(util) +CL_NS_USE(index) +CL_NS_USE(analysis) +CL_NS_USE(search) + +CL_NS_DEF(queryParser) + + QueryParser::QueryParser(const TCHAR* _field, Analyzer* _analyzer) : QueryParserBase(_analyzer){ + //Func - Constructor. + // Instantiates a QueryParser for the named field _field + //Pre - _field != NULL + //Post - An instance has been created + + if ( _field ) + field = STRDUP_TtoT(_field); + else + field = NULL; + tokens = NULL; + lowercaseExpandedTerms = true; + } + + QueryParser::~QueryParser() { + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + _CLDELETE_CARRAY(field); + } + + //static + Query* QueryParser::parse(const TCHAR* query, const TCHAR* field, Analyzer* analyzer){ + //Func - Returns a new instance of the Query class with a specified query, field and + // analyzer values. + //Pre - query != NULL and holds the query to parse + // field != NULL and holds the default field for query terms + // analyzer holds a valid reference to an Analyzer and is used to + // find terms in the query text + //Post - query has been parsed and an instance of Query has been returned + + CND_PRECONDITION(query != NULL, "query is NULL"); + CND_PRECONDITION(field != NULL, "field is NULL"); + + QueryParser parser(field, analyzer); + return parser.parse(query); + } + + Query* QueryParser::parse(const TCHAR* query){ + //Func - Returns a parsed Query instance + //Pre - query != NULL and contains the query value to be parsed + //Post - Returns a parsed Query Instance + + CND_PRECONDITION(query != NULL, "query is NULL"); + + //Instantie a Stringer that can read the query string + Reader* r = _CLNEW StringReader(query); + + //Check to see if r has been created properly + CND_CONDITION(r != NULL, "Could not allocate memory for StringReader r"); + + //Pointer for the return value + Query* ret = NULL; + + try{ + //Parse the query managed by the StringReader R and return a parsed Query instance + //into ret + ret = parse(r); + }_CLFINALLY ( + _CLDELETE(r); + ); + + return ret; + } + + Query* QueryParser::parse(Reader* reader){ + //Func - Returns a parsed Query instance + //Pre - reader contains a valid reference to a Reader and manages the query string + //Post - A parsed Query instance has been returned or + + //instantiate the TokenList tokens + TokenList _tokens; + this->tokens = &_tokens; + + //Instantiate a lexer + Lexer lexer(this, reader); + + //tokens = lexer.Lex(); + //Lex the tokens + lexer.Lex(tokens); + + //Peek to the first token and check if is an EOF + if (tokens->peek()->Type == QueryToken::EOF_){ + // The query string failed to yield any tokens. We discard the + // TokenList tokens and raise an exceptioin. + QueryToken* token = this->tokens->extract(); + _CLDELETE(token); + _CLTHROWA(CL_ERR_Parse, "No query given."); + } + + //Return the parsed Query instance + Query* ret = MatchQuery(field); + this->tokens = NULL; + return ret; + } + + int32_t QueryParser::MatchConjunction(){ + //Func - matches for CONJUNCTION + // CONJUNCTION ::= | + //Pre - tokens != NULL + //Post - if the first token is an AND or an OR then + // the token is extracted and deleted and CONJ_AND or CONJ_OR is returned + // otherwise CONJ_NONE is returned + + CND_PRECONDITION(tokens != NULL, "tokens is NULL"); + + switch(tokens->peek()->Type){ + case QueryToken::AND_ : + //Delete the first token of tokenlist + ExtractAndDeleteToken(); + return CONJ_AND; + case QueryToken::OR : + //Delete the first token of tokenlist + ExtractAndDeleteToken(); + return CONJ_OR; + default : + return CONJ_NONE; + } + } + + int32_t QueryParser::MatchModifier(){ + //Func - matches for MODIFIER + // MODIFIER ::= | | + //Pre - tokens != NULL + //Post - if the first token is a PLUS the token is extracted and deleted and MOD_REQ is returned + // if the first token is a MINUS or NOT the token is extracted and deleted and MOD_NOT is returned + // otherwise MOD_NONE is returned + CND_PRECONDITION(tokens != NULL, "tokens is NULL"); + + switch(tokens->peek()->Type){ + case QueryToken::PLUS : + //Delete the first token of tokenlist + ExtractAndDeleteToken(); + return MOD_REQ; + case QueryToken::MINUS : + case QueryToken::NOT : + //Delete the first token of tokenlist + ExtractAndDeleteToken(); + return MOD_NOT; + default : + return MOD_NONE; + } + } + + Query* QueryParser::MatchQuery(const TCHAR* field){ + //Func - matches for QUERY + // QUERY ::= [MODIFIER] QueryParser::CLAUSE ( [MODIFIER] CLAUSE)* + //Pre - field != NULL + //Post - + + CND_PRECONDITION(tokens != NULL, "tokens is NULL"); + + CL_NS_STD(vector) clauses; + + Query* q = NULL; + + int32_t mods = MOD_NONE; + int32_t conj = CONJ_NONE; + + //match for MODIFIER + mods = MatchModifier(); + + //match for CLAUSE + q = MatchClause(field); + AddClause(clauses, CONJ_NONE, mods, q); + + // match for CLAUSE* + while(true){ + QueryToken* p = tokens->peek(); + if(p->Type == QueryToken::EOF_){ + QueryToken* qt = MatchQueryToken(QueryToken::EOF_); + _CLDELETE(qt); + break; + } + + if(p->Type == QueryToken::RPAREN){ + //MatchQueryToken(QueryToken::RPAREN); + break; + } + + //match for a conjuction (AND OR NOT) + conj = MatchConjunction(); + //match for a modifier + mods = MatchModifier(); + + q = MatchClause(field); + if ( q != NULL ) + AddClause(clauses, conj, mods, q); + } + + // finalize query + if(clauses.size() == 1){ //bvk: removed this && firstQuery != NULL + BooleanClause* c = clauses[0]; + Query* q = c->query; + + //Condition check to be sure clauses[0] is valid + CND_CONDITION(c != NULL, "c is NULL"); + + //Tell the boolean clause not to delete its query + c->deleteQuery=false; + //Clear the clauses list + clauses.clear(); + _CLDELETE(c); + + return q; + }else{ + return GetBooleanQuery(clauses); + } + } + + Query* QueryParser::MatchClause(const TCHAR* field){ + //Func - matches for CLAUSE + // CLAUSE ::= [TERM ] ( TERM | ( QUERY )) + //Pre - field != NULL + //Post - + + Query* q = NULL; + const TCHAR* sfield = field; + bool delField = false; + + QueryToken *DelToken = NULL; + + //match for [TERM ] + QueryToken* term = tokens->extract(); + if(term->Type == QueryToken::TERM && tokens->peek()->Type == QueryToken::COLON){ + DelToken = MatchQueryToken(QueryToken::COLON); + + CND_CONDITION(DelToken != NULL,"DelToken is NULL"); + _CLDELETE(DelToken); + + TCHAR* tmp = STRDUP_TtoT(term->Value); + discardEscapeChar(tmp); + delField = true; + sfield = tmp; + _CLDELETE(term); + }else{ + tokens->push(term); + term = NULL; + } + + // match for + // TERM | ( QUERY ) + if(tokens->peek()->Type == QueryToken::LPAREN){ + DelToken = MatchQueryToken(QueryToken::LPAREN); + + CND_CONDITION(DelToken != NULL,"DelToken is NULL"); + _CLDELETE(DelToken); + + q = MatchQuery(sfield); + //DSR:2004.11.01: + //If exception is thrown while trying to match trailing parenthesis, + //need to prevent q from leaking. + + try{ + DelToken = MatchQueryToken(QueryToken::RPAREN); + + CND_CONDITION(DelToken != NULL,"DelToken is NULL"); + _CLDELETE(DelToken); + + }catch(...) { + _CLDELETE(q); + throw; + } + }else{ + q = MatchTerm(sfield); + } + + if ( delField ) + _CLDELETE_CARRAY(sfield); + return q; + } + + + Query* QueryParser::MatchTerm(const TCHAR* field){ + //Func - matches for TERM + // TERM ::= TERM | PREFIXTERM | WILDTERM | NUMBER + // [ ] [ []] + // | ( | ) [ ] + // | [SLOP] [ ] + //Pre - field != NULL + //Post - + + QueryToken* term = NULL; + QueryToken* slop = NULL; + QueryToken* boost = NULL; + + bool prefix = false; + bool wildcard = false; + bool fuzzy = false; + bool rangein = false; + Query* q = NULL; + + term = tokens->extract(); + QueryToken* DelToken = NULL; //Token that is about to be deleted + + switch(term->Type){ + case QueryToken::TERM: + case QueryToken::NUMBER: + case QueryToken::PREFIXTERM: + case QueryToken::WILDTERM: + { //start case + //Check if type of QueryToken term is a prefix term + if(term->Type == QueryToken::PREFIXTERM){ + prefix = true; + } + //Check if type of QueryToken term is a wildcard term + if(term->Type == QueryToken::WILDTERM){ + wildcard = true; + } + //Peek to see if the type of the next token is fuzzy term + if(tokens->peek()->Type == QueryToken::FUZZY){ + DelToken = MatchQueryToken(QueryToken::FUZZY); + + CND_CONDITION(DelToken !=NULL, "DelToken is NULL"); + _CLDELETE(DelToken); + + fuzzy = true; + } + if(tokens->peek()->Type == QueryToken::CARAT){ + DelToken = MatchQueryToken(QueryToken::CARAT); + + CND_CONDITION(DelToken !=NULL, "DelToken is NULL"); + _CLDELETE(DelToken); + + boost = MatchQueryToken(QueryToken::NUMBER); + + if(tokens->peek()->Type == QueryToken::FUZZY){ + DelToken = MatchQueryToken(QueryToken::FUZZY); + + CND_CONDITION(DelToken !=NULL, "DelToken is NULL"); + _CLDELETE(DelToken); + + fuzzy = true; + } + } //end if type==CARAT + + discardEscapeChar(term->Value); //clean up + if(wildcard){ + q = GetWildcardQuery(field,term->Value); + break; + }else if(prefix){ + //Create a PrefixQuery + term->Value[_tcslen(term->Value)-1] = 0; //discard the * + q = GetPrefixQuery(field,term->Value); + break; + }else if(fuzzy){ + //Create a FuzzyQuery + + //Check if the last char is a ~ + if(term->Value[_tcslen(term->Value)-1] == '~'){ + //remove the ~ + term->Value[_tcslen(term->Value)-1] = '\0'; + } + + q = GetFuzzyQuery(field,term->Value); + break; + }else{ + q = GetFieldQuery(field, term->Value); + break; + } + } + + + case QueryToken::RANGEIN: + case QueryToken::RANGEEX:{ + if(term->Type == QueryToken::RANGEIN){ + rangein = true; + } + + if(tokens->peek()->Type == QueryToken::CARAT){ + DelToken = MatchQueryToken(QueryToken::CARAT); + + CND_CONDITION(DelToken !=NULL, "DelToken is NULL"); + _CLDELETE(DelToken); + + boost = MatchQueryToken(QueryToken::NUMBER); + } + + TCHAR* noBrackets = term->Value + 1; + noBrackets[_tcslen(noBrackets)-1] = 0; + q = ParseRangeQuery(field, noBrackets, rangein); + break; + } + + + case QueryToken::QUOTED:{ + if(tokens->peek()->Type == QueryToken::SLOP){ + slop = MatchQueryToken(QueryToken::SLOP); + } + + if(tokens->peek()->Type == QueryToken::CARAT){ + DelToken = MatchQueryToken(QueryToken::CARAT); + + CND_CONDITION(DelToken !=NULL, "DelToken is NULL"); + _CLDELETE(DelToken); + + boost = MatchQueryToken(QueryToken::NUMBER); + } + + //remove the quotes + TCHAR* quotedValue = term->Value+1; + quotedValue[_tcslen(quotedValue)-1] = '\0'; + + int32_t islop = phraseSlop; + if(slop != NULL ){ + try { + TCHAR* end; //todo: should parse using float... + islop = (int32_t)_tcstoi64(slop->Value+1, &end, 10); + }catch(...){ + //ignored + } + } + + q = GetFieldQuery(field, quotedValue, islop); + _CLDELETE(slop); + } + } // end of switch + + _CLDELETE(term); + + + if( q!=NULL && boost != NULL ){ + qreal f = 1.0F; + try { + TCHAR* tmp; + f = _tcstod(boost->Value, &tmp); + }catch(...){ + //ignored + } + _CLDELETE(boost); + + q->setBoost( f); + } + + return q; + } + + QueryToken* QueryParser::MatchQueryToken(QueryToken::Types expectedType){ + //Func - matches for QueryToken of the specified type and returns it + // otherwise Exception throws + //Pre - tokens != NULL + //Post - + + CND_PRECONDITION(tokens != NULL,"tokens is NULL"); + + if(tokens->count() == 0){ + throwParserException(_T("Error: Unexpected end of program"),' ',0,0); + } + + //Extract a token form the TokenList tokens + QueryToken* t = tokens->extract(); + //Check if the type of the token t matches the expectedType + if (expectedType != t->Type){ + TCHAR buf[200]; + _sntprintf(buf,200,_T("Error: Unexpected QueryToken: %d, expected: %d"),t->Type,expectedType); + _CLDELETE(t); + throwParserException(buf,' ',0,0); + } + + //Return the matched token + return t; + } + + void QueryParser::ExtractAndDeleteToken(void){ + //Func - Extracts the first token from the Tokenlist tokenlist + // and destroys it + //Pre - true + //Post - The first token has been extracted and destroyed + + CND_PRECONDITION(tokens != NULL, "tokens is NULL"); + + //Extract the token from the TokenList tokens + QueryToken* t = tokens->extract(); + //Condition Check Token may not be NULL + CND_CONDITION(t != NULL, "Token is NULL"); + //Delete Token + _CLDELETE(t); + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/queryParser/QueryParser.h b/3rdparty/clucene/src/CLucene/queryParser/QueryParser.h new file mode 100644 index 0000000..a2fc85c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/QueryParser.h @@ -0,0 +1,165 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_queryParser_QueryParser_ +#define _lucene_queryParser_QueryParser_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/analysis/AnalysisHeader.h" +#include "CLucene/util/Reader.h" +#include "CLucene/search/SearchHeader.h" +#include "CLucene/index/Term.h" + +#include "TokenList.h" +#include "QueryToken.h" +#include "QueryParserBase.h" +#include "Lexer.h" + +CL_NS_DEF(queryParser) + +/** +* @brief CLucene's default query parser. +* +*

It's a query parser. +* The only method that clients should need to call is Parse(). +* The syntax for query const TCHAR*s is as follows: +* A Query is a series of clauses. A clause may be prefixed by:

+*
    +*
  • a plus (+) or a minus (-) sign, indicating that the +* clause is required or prohibited respectively; or
  • +*
  • a term followed by a colon, indicating the field to be searched. +* This enables one to construct queries which search multiple fields.
  • +*
+*

+* A clause may be either:

+*
    +*
  • a term, indicating all the documents that contain this term; or
  • +*
  • a nested query, enclosed in parentheses. Note that this may be +* used with a +/- prefix to require any of a set of terms.
  • +*
+*

+* Thus, in BNF, the query grammar is:

+* +* Query ::= ( Clause )* +* Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" ) +* +*

+* Examples of appropriately formatted queries can be found in the test cases. +*

+*/ +class QueryParser : public QueryParserBase +{ +private: + const TCHAR* field; + TokenList* tokens; +public: + /** + * Initializes a new instance of the QueryParser class with a specified field and + * analyzer values. + */ + QueryParser(const TCHAR* field, CL_NS(analysis)::Analyzer* analyzer); + ~QueryParser(); + + /** + * Returns a parsed Query instance. + * Note: this call is not threadsafe, either use a seperate QueryParser for each thread, or use a thread lock + * The query value to be parsed. + * A parsed Query instance. + */ + virtual CL_NS(search)::Query* parse(const TCHAR* query); + + /** + * Returns a parsed Query instance. + * Note: this call is not threadsafe, either use a seperate QueryParser for each thread, or use a thread lock + * The TextReader value to be parsed. + * A parsed Query instance. + */ + virtual CL_NS(search)::Query* parse(CL_NS(util)::Reader* reader); + + /** + * Returns a new instance of the Query class with a specified query, field and + * analyzer values. + */ + static CL_NS(search)::Query* parse(const TCHAR* query, const TCHAR* field, CL_NS(analysis)::Analyzer* analyzer); + + CL_NS(analysis)::Analyzer* getAnalyzer() { return analyzer; } + + /** + * @return Returns the field. + */ + const TCHAR* getField() { return field; } + + //deprecated functions + _CL_DEPRECATED( setLowercaseExpandedTerms ) void setLowercaseWildcardTerms(bool lowercaseWildcardTerms){ setLowercaseExpandedTerms(lowercaseWildcardTerms); } + _CL_DEPRECATED( getLowercaseExpandedTerms ) bool getLowercaseWildcardTerms() const { return getLowercaseExpandedTerms(); } +protected: + //these functions may be defined under certain compilation conditions. + //note that this functionality is deprecated, you should create your own queryparser + //if you want to remove this functionality...it will be removed... be warned! +#ifdef NO_PREFIX_QUERY + virtual CL_NS(search)::Query* GetPrefixQuery(const TCHAR* field,const TCHAR* termStr){ return NULL; } +#endif +#ifdef NO_FUZZY_QUERY + virtual CL_NS(search)::Query* GetFuzzyQuery(const TCHAR* field,const TCHAR* termStr){ return NULL; } +#endif +#ifdef NO_RANGE_QUERY + virtual CL_NS(search)::Query* GetRangeQuery(const TCHAR* field, const TCHAR* part1, const TCHAR* part2, bool inclusive) { return NULL; } +#endif +#ifdef NO_WILDCARD_QUERY + virtual CL_NS(search)::Query* GetWildcardQuery(const TCHAR* field, TCHAR* termStr) { return NULL; } +#endif +private: + /** + * matches for CONJUNCTION + * CONJUNCTION ::= | + */ + int32_t MatchConjunction(); + + /** + * matches for MODIFIER + * MODIFIER ::= | | + */ + int32_t MatchModifier(); + + /** + * matches for QUERY + * QUERY ::= [MODIFIER] CLAUSE ( [MODIFIER] CLAUSE)* + */ + CL_NS(search)::Query* MatchQuery(const TCHAR* field); + + /** + * matches for CLAUSE + * CLAUSE ::= [TERM ] ( TERM | ( QUERY )) + */ + CL_NS(search)::Query* MatchClause(const TCHAR* field); + + /** + * matches for TERM + * TERM ::= TERM | PREFIXTERM | WILDTERM | NUMBER + * [ ] [ []] + * + * | ( | ) [ ] + * | [SLOP] [ ] + */ + CL_NS(search)::Query* MatchTerm(const TCHAR* field); + + /** + * matches for QueryToken of the specified type and returns it + * otherwise Exception throws + */ + QueryToken* MatchQueryToken(QueryToken::Types expectedType); + + /** + * Extracts the first token from the Tokenlist tokenlist + * and destroys it + */ + void ExtractAndDeleteToken(void); +}; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.cpp b/3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.cpp new file mode 100644 index 0000000..7b95b30 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.cpp @@ -0,0 +1,369 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "QueryParserBase.h" + +#include "CLucene/search/TermQuery.h" +#include "CLucene/search/PhraseQuery.h" +#include "CLucene/search/RangeQuery.h" +#include "CLucene/search/FuzzyQuery.h" +#include "CLucene/search/WildcardQuery.h" +#include "CLucene/search/PrefixQuery.h" + + +CL_NS_USE(search) +CL_NS_USE(util) +CL_NS_USE(analysis) +CL_NS_USE(index) + +CL_NS_DEF(queryParser) + +QueryParserBase::QueryParserBase(Analyzer* analyzer){ +//Func - Constructor +//Pre - true +//Post - instance has been created with PhraseSlop = 0 + this->analyzer = analyzer; + this->defaultOperator = OR_OPERATOR; + this->phraseSlop = 0; + this->lowercaseExpandedTerms = true; +} + +QueryParserBase::~QueryParserBase(){ +//Func - Destructor +//Pre - true +//Post - The instance has been destroyed +} + + +void QueryParserBase::discardEscapeChar(TCHAR* source) const{ + int len = _tcslen(source); + int j = 0; + for (int i = 0; i < len; i++) { + if (source[i] == '\\' && source[i+1] != '\0' ) { + _tcscpy(source+i,source+i+1); + len--; + } + } +} + +void QueryParserBase::AddClause(CL_NS_STD(vector)& clauses, int32_t conj, int32_t mods, Query* q){ +//Func - Adds the next parsed clause. +//Pre - +//Post - + + bool required, prohibited; + + // If this term is introduced by AND, make the preceding term required, + // unless it's already prohibited. + const uint32_t nPreviousClauses = clauses.size(); + if (nPreviousClauses > 0 && conj == CONJ_AND) { + BooleanClause* c = clauses[nPreviousClauses-1]; + if (!c->prohibited) + c->required = true; + } + + if (nPreviousClauses > 0 && defaultOperator == AND_OPERATOR && conj == CONJ_OR) { + // If this term is introduced by OR, make the preceding term optional, + // unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b) + // notice if the input is a OR b, first term is parsed as required; without + // this modification a OR b would parse as +a OR b + BooleanClause* c = clauses[nPreviousClauses-1]; + if (!c->prohibited){ + c->required = false; + c->prohibited = false; + } + } + + // We might have been passed a NULL query; the term might have been + // filtered away by the analyzer. + if (q == NULL) + return; + + if (defaultOperator == OR_OPERATOR) { + // We set REQUIRED if we're introduced by AND or +; PROHIBITED if + // introduced by NOT or -; make sure not to set both. + prohibited = (mods == MOD_NOT); + required = (mods == MOD_REQ); + if (conj == CONJ_AND && !prohibited) { + required = true; + } + } else { + // We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED + // if not PROHIBITED and not introduced by OR + prohibited = (mods == MOD_NOT); + required = (!prohibited && conj != CONJ_OR); + } + + if ( required && prohibited ) + throwParserException( _T("Clause cannot be both required and prohibited"), ' ',0,0); + clauses.push_back(_CLNEW BooleanClause(q,true, required, prohibited)); +} + +void QueryParserBase::throwParserException(const TCHAR* message, TCHAR ch, int32_t col, int32_t line ) +{ + TCHAR msg[1024]; + _sntprintf(msg,1024,message,ch,col,line); + _CLTHROWT (CL_ERR_Parse, msg ); +} + + +Query* QueryParserBase::GetFieldQuery(const TCHAR* field, TCHAR* queryText, int32_t slop){ + Query* ret = GetFieldQuery(field,queryText); + if ( ret && ret->getQueryName() == PhraseQuery::getClassName() ) + ((PhraseQuery*)ret)->setSlop(slop); + + return ret; +} + +Query* QueryParserBase::GetFieldQuery(const TCHAR* field, TCHAR* queryText){ +//Func - Returns a query for the specified field. +// Use the analyzer to get all the tokens, and then build a TermQuery, +// PhraseQuery, or nothing based on the term count +//Pre - field != NULL +// analyzer contains a valid reference to an Analyzer +// queryText != NULL and contains the query +//Post - A query instance has been returned for the specified field + + CND_PRECONDITION(field != NULL, "field is NULL"); + CND_PRECONDITION(queryText != NULL, "queryText is NULL"); + + //Instantiate a stringReader for queryText + StringReader reader(queryText); + TokenStream* source = analyzer->tokenStream(field, &reader); + CND_CONDITION(source != NULL,"source is NULL"); + + StringArrayConstWithDeletor v; + + Token t; + int positionCount = 0; + bool severalTokensAtSamePosition = false; + + //Get the tokens from the source + try{ + while (source->next(&t)){ + v.push_back(STRDUP_TtoT(t.termText())); + + if (t.getPositionIncrement() != 0) + positionCount += t.getPositionIncrement(); + else + severalTokensAtSamePosition = true; + } + }catch(CLuceneError& err){ + if ( err.number() != CL_ERR_IO ) + throw err; + } + _CLDELETE(source); + + //Check if there are any tokens retrieved + if (v.size() == 0){ + return NULL; + }else{ + if (v.size() == 1){ + Term* t = _CLNEW Term(field, v[0]); + Query* ret = _CLNEW TermQuery( t ); + _CLDECDELETE(t); + return ret; + }else{ + if (severalTokensAtSamePosition) { + if (positionCount == 1) { + // no phrase query: + BooleanQuery* q = _CLNEW BooleanQuery; //todo: disableCoord=true here, but not implemented in BooleanQuery + StringArrayConst::iterator itr = v.begin(); + while ( itr != v.end() ){ + Term* t = _CLNEW Term(field, *itr); + q->add(_CLNEW TermQuery(t),true, false,false);//should occur... + _CLDECDELETE(t); + ++itr; + } + return q; + }else { + _CLTHROWA(CL_ERR_UnsupportedOperation, "MultiPhraseQuery NOT Implemented"); + } + }else{ + PhraseQuery* q = _CLNEW PhraseQuery; + q->setSlop(phraseSlop); + + StringArrayConst::iterator itr = v.begin(); + while ( itr != v.end() ){ + const TCHAR* data = *itr; + Term* t = _CLNEW Term(field, data); + q->add(t); + _CLDECDELETE(t); + ++itr; + } + return q; + } + } + } +} + +void QueryParserBase::setLowercaseExpandedTerms(bool lowercaseExpandedTerms){ + this->lowercaseExpandedTerms = lowercaseExpandedTerms; +} +bool QueryParserBase::getLowercaseExpandedTerms() const { + return lowercaseExpandedTerms; +} +void QueryParserBase::setDefaultOperator(int oper){ + this->defaultOperator=oper; +} +int QueryParserBase::getDefaultOperator() const{ + return defaultOperator; +} + + +Query* QueryParserBase::ParseRangeQuery(const TCHAR* field, TCHAR* queryText, bool inclusive) +{ + //todo: this must be fixed, [-1--5] (-1 to -5) should yield a result, but won't parse properly + //because it uses an analyser, should split it up differently... + + // Use the analyzer to get all the tokens. There should be 1 or 2. + StringReader reader(queryText); + TokenStream* source = analyzer->tokenStream(field, &reader); + + TCHAR* terms[2]; + terms[0]=NULL;terms[1]=NULL; + Token t; + bool tret=true; + bool from=true; + while(tret) + { + try{ + tret = source->next(&t); + }catch (CLuceneError& err){ + if ( err.number() == CL_ERR_IO ) + tret=false; + else + throw err; + } + if (tret) + { + if ( !from && _tcscmp(t.termText(),_T("TO"))==0 ) + continue; + + + TCHAR* tmp = STRDUP_TtoT(t.termText()); + discardEscapeChar(tmp); + terms[from? 0 : 1] = tmp; + + if (from) + from = false; + else + break; + } + } + Query* ret = GetRangeQuery(field, terms[0], terms[1],inclusive); + _CLDELETE_CARRAY(terms[0]); + _CLDELETE_CARRAY(terms[1]); + _CLDELETE(source); + + return ret; +} + +Query* QueryParserBase::GetPrefixQuery(const TCHAR* field, TCHAR* termStr){ +//Pre - field != NULL and field contains the name of the field that the query will use +// termStr != NULL and is the token to use for building term for the query +// (WITH or WITHOUT a trailing '*' character!) +//Post - A PrefixQuery instance has been returned + + CND_PRECONDITION(field != NULL,"field is NULL"); + CND_PRECONDITION(termStr != NULL,"termStr is NULL"); + + if ( lowercaseExpandedTerms ) + _tcslwr(termStr); + + Term* t = _CLNEW Term(field, termStr); + CND_CONDITION(t != NULL,"Could not allocate memory for term t"); + + Query *q = _CLNEW PrefixQuery(t); + CND_CONDITION(q != NULL,"Could not allocate memory for PrefixQuery q"); + + _CLDECDELETE(t); + return q; +} + +Query* QueryParserBase::GetFuzzyQuery(const TCHAR* field, TCHAR* termStr){ +//Func - Factory method for generating a query (similar to getPrefixQuery}). Called when parser parses +// an input term token that has the fuzzy suffix (~) appended. +//Pre - field != NULL and field contains the name of the field that the query will use +// termStr != NULL and is the token to use for building term for the query +// (WITH or WITHOUT a trailing '*' character!) +//Post - A FuzzyQuery instance has been returned + + CND_PRECONDITION(field != NULL,"field is NULL"); + CND_PRECONDITION(termStr != NULL,"termStr is NULL"); + + if ( lowercaseExpandedTerms ) + _tcslwr(termStr); + + Term* t = _CLNEW Term(field, termStr); + CND_CONDITION(t != NULL,"Could not allocate memory for term t"); + + Query *q = _CLNEW FuzzyQuery(t); + CND_CONDITION(q != NULL,"Could not allocate memory for FuzzyQuery q"); + + _CLDECDELETE(t); + return q; +} + + +Query* QueryParserBase::GetWildcardQuery(const TCHAR* field, TCHAR* termStr){ + CND_PRECONDITION(field != NULL,"field is NULL"); + CND_PRECONDITION(termStr != NULL,"termStr is NULL"); + + if ( lowercaseExpandedTerms ) + _tcslwr(termStr); + + Term* t = _CLNEW Term(field, termStr); + CND_CONDITION(t != NULL,"Could not allocate memory for term t"); + Query* q = _CLNEW WildcardQuery(t); + _CLDECDELETE(t); + + return q; +} + +Query* QueryParserBase::GetBooleanQuery(CL_NS_STD(vector)& clauses){ + if ( clauses.size() == 0 ) + return NULL; + + BooleanQuery* query = _CLNEW BooleanQuery(); + //Condition check to see if query has been allocated properly + CND_CONDITION(query != NULL, "No memory could be allocated for query"); + + //iterate through all the clauses + for( uint32_t i=0;iadd(clauses[i]); + } + return query; +} + + +CL_NS(search)::Query* QueryParserBase::GetRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, bool inclusive){ + //todo: does jlucene handle rangequeries differntly? if we are using + //a certain type of analyser, the terms may be filtered out, which + //is not necessarily what we want. + if (lowercaseExpandedTerms) { + _tcslwr(part1); + _tcslwr(part2); + } + //todo: should see if we can parse the strings as dates... currently we leave that up to the end-developer... + Term* t1 = _CLNEW Term(field,part1); + Term* t2 = _CLNEW Term(field,part2); + Query* ret = _CLNEW RangeQuery(t1, t2, inclusive); + _CLDECDELETE(t1); + _CLDECDELETE(t2); + + return ret; +} + + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.h b/3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.h new file mode 100644 index 0000000..261e587 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/QueryParserBase.h @@ -0,0 +1,204 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_queryParser_QueryParserBase_ +#define _lucene_queryParser_QueryParserBase_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/VoidList.h" +#include "CLucene/search/BooleanClause.h" +#include "CLucene/analysis/Analyzers.h" +#include "QueryToken.h" + +CL_NS_DEF(queryParser) + + /** + * Contains default implementations used by QueryParser. + * You can override any of these to provide a customised QueryParser. + */ + class QueryParserBase:LUCENE_BASE + { + protected: + /* The actual operator the parser uses to combine query terms */ + int defaultOperator; + int32_t phraseSlop; + + bool lowercaseExpandedTerms; + + LUCENE_STATIC_CONSTANT(int, CONJ_NONE=0); + LUCENE_STATIC_CONSTANT(int, CONJ_AND=1); + LUCENE_STATIC_CONSTANT(int, CONJ_OR=2); + + LUCENE_STATIC_CONSTANT(int, MOD_NONE=0); + LUCENE_STATIC_CONSTANT(int, MOD_NOT=10); + LUCENE_STATIC_CONSTANT(int, MOD_REQ=11); + + CL_NS(analysis)::Analyzer* analyzer; + + public: + QueryParserBase(CL_NS(analysis)::Analyzer* analyzer); + ~QueryParserBase(); + + /** + * Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically + * lower-cased or not. Default is true. + */ + void setLowercaseExpandedTerms(bool lowercaseExpandedTerms); + + /** + * @see #setLowercaseExpandedTerms(boolean) + */ + bool getLowercaseExpandedTerms() const; + + //values used for setOperator + LUCENE_STATIC_CONSTANT(int, OR_OPERATOR=0); + LUCENE_STATIC_CONSTANT(int, AND_OPERATOR=1); + + /** + * Sets the boolean operator of the QueryParser. + * In default mode (OR_OPERATOR) terms without any modifiers + * are considered optional: for example capital of Hungary is equal to + * capital OR of OR Hungary.
+ * In AND_OPERATOR mode terms are considered to be in conjuction: the + * above mentioned query is parsed as capital AND of AND Hungary + */ + void setDefaultOperator(int oper); + /** + * Gets implicit operator setting, which will be either AND_OPERATOR + * or OR_OPERATOR. + */ + int getDefaultOperator() const; + + //public so that the lexer can call this + virtual void throwParserException(const TCHAR* message, TCHAR ch, int32_t col, int32_t line ); + + /** + * Sets the default slop for phrases. If zero, then exact phrase matches + * are required. Default value is zero. + */ + void setPhraseSlop(int phraseSlop) { this->phraseSlop = phraseSlop; } + + /** + * Gets the default slop for phrases. + */ + int getPhraseSlop() { return phraseSlop; } + + protected: + + /** + * Removes the escaped characters + */ + void discardEscapeChar(TCHAR* token) const; + + //Analyzes the expanded term termStr with the StandardFilter and the LowerCaseFilter. + TCHAR* AnalyzeExpandedTerm(const TCHAR* field, TCHAR* termStr); + + // Adds the next parsed clause. + virtual void AddClause(std::vector& clauses, int32_t conj, int32_t mods, CL_NS(search)::Query* q); + + /** + * Returns a termquery, phrasequery for the specified field. + * Note: this is only a partial implementation, since MultiPhraseQuery is not implemented yet + * return NULL to disallow + */ + virtual CL_NS(search)::Query* GetFieldQuery(const TCHAR* field, TCHAR* queryText); + + /** + * Delegates to GetFieldQuery(string, string), and adds slop onto phrasequery. + * Can be used to remove slop functionality + */ + virtual CL_NS(search)::Query* GetFieldQuery(const TCHAR* field, TCHAR* queryText, int32_t slop); + + /** + * Factory method for generating a query (similar to + * {@link #GetWildcardQuery}). Called when parser parses an input term + * token that uses prefix notation; that is, contains a single '*' wildcard + * character as its last character. Since this is a special case + * of generic wildcard term, and such a query can be optimized easily, + * this usually results in a different query object. + *

+ * Depending on settings, a prefix term may be lower-cased + * automatically. It will not go through the default Analyzer, + * however, since normal Analyzers are unlikely to work properly + * with wildcard templates. + *

+ * Can be overridden by extending classes, to provide custom handling for + * wild card queries, which may be necessary due to missing analyzer calls. + * + * @param field Name of the field query will use. + * @param termStr Term token to use for building term for the query + * (without trailing '*' character!) + * + * @return Resulting {@link Query} built for the term + * return NULL to disallow + */ + virtual CL_NS(search)::Query* GetPrefixQuery(const TCHAR* field, TCHAR* termStr); + + /** + * Factory method for generating a query. Called when parser + * parses an input term token that contains one or more wildcard + * characters (? and *), but is not a prefix term token (one + * that has just a single * character at the end) + *

+ * Depending on settings, prefix term may be lower-cased + * automatically. It will not go through the default Analyzer, + * however, since normal Analyzers are unlikely to work properly + * with wildcard templates. + *

+ * Can be overridden by extending classes, to provide custom handling for + * wildcard queries, which may be necessary due to missing analyzer calls. + * + * @param field Name of the field query will use. + * @param termStr Term token that contains one or more wild card + * characters (? or *), but is not simple prefix term + * + * @return Resulting {@link Query} built for the term + * return NULL to disallow + */ + virtual CL_NS(search)::Query* GetWildcardQuery(const TCHAR* field, TCHAR* termStr); + + /** + * Factory method for generating a query (similar to + * {@link #GetWildcardQuery}). Called when parser parses + * an input term token that has the fuzzy suffix (~) appended. + * + * @param field Name of the field query will use. + * @param termStr Term token to use for building term for the query + * + * @return Resulting {@link Query} built for the term + * return NULL to disallow + */ + virtual CL_NS(search)::Query* GetFuzzyQuery(const TCHAR* field, TCHAR* termStr); + + /** + * Factory method for generating query, given a set of clauses. + * By default creates a boolean query composed of clauses passed in. + * + * Can be overridden by extending classes, to modify query being + * returned. + * + * @param clauses Vector that contains {@link BooleanClause} instances + * to join. + * + * @return Resulting {@link Query} object. + * return NULL to disallow + * + * Memory: clauses must all be cleaned up by this function. + */ + virtual CL_NS(search)::Query* GetBooleanQuery(std::vector& clauses); + + /** + * return NULL to disallow + */ + virtual CL_NS(search)::Query* GetRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, bool inclusive); + virtual CL_NS(search)::Query* ParseRangeQuery(const TCHAR* field, TCHAR* str, bool inclusive); + + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/queryParser/QueryToken.cpp b/3rdparty/clucene/src/CLucene/queryParser/QueryToken.cpp new file mode 100644 index 0000000..ee88a3c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/QueryToken.cpp @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "QueryToken.h" + +CL_NS_DEF(queryParser) + + +QueryToken::QueryToken(): + Value(NULL) +{ + set(UNKNOWN_); +} +QueryToken::QueryToken(TCHAR* value, const int32_t start, const int32_t end, const QueryToken::Types type): + Value(NULL) +{ + set(value,start,end,type); +} + +QueryToken::~QueryToken(){ +//Func - Destructor +//Pre - true +//Post - Instance has been destroyed + + #ifndef LUCENE_TOKEN_WORD_LENGTH + _CLDELETE_CARRAY( Value ); + #endif +} + +// Initializes a new instance of the Token class LUCENE_EXPORT. +// +QueryToken::QueryToken(TCHAR* value, const QueryToken::Types type): + Value(NULL) +{ + set(value,type); +} + +// Initializes a new instance of the Token class LUCENE_EXPORT. +// +QueryToken::QueryToken(QueryToken::Types type): + Value(NULL) +{ + set(type); +} + + +void QueryToken::set(TCHAR* value, const Types type){ + set(value,0,-1,type); +} +void QueryToken::set(TCHAR* value, const int32_t start, const int32_t end, const Types type){ + #ifndef LUCENE_TOKEN_WORD_LENGTH + _CLDELETE_CARRAY(Value); + Value = STRDUP_TtoT(value); + #else + _tcsncpy(Value,value,LUCENE_TOKEN_WORD_LENGTH); + Value[LUCENE_TOKEN_WORD_LENGTH]; + #endif + this->Start = start; + this->End = end; + this->Type = type; + + if ( this->End < 0 ) + this->End = _tcslen(Value); +} +void QueryToken::set(Types type){ + set(LUCENE_BLANK_STRING,0,0,type); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/queryParser/QueryToken.h b/3rdparty/clucene/src/CLucene/queryParser/QueryToken.h new file mode 100644 index 0000000..739a667 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/QueryToken.h @@ -0,0 +1,76 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_queryParser_QueryToken_ +#define _lucene_queryParser_QueryToken_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "QueryParserBase.h" + +CL_NS_DEF(queryParser) + + // Token class that used by QueryParser. + class QueryToken:LUCENE_BASE + { + public: + enum Types + { + AND_, + OR, + NOT, + PLUS, + MINUS, + LPAREN, + RPAREN, + COLON, + CARAT, + QUOTED, + TERM, + SLOP, + FUZZY, + PREFIXTERM, + WILDTERM, + RANGEIN, + RANGEEX, + NUMBER, + EOF_, + UNKNOWN_ + }; + + + #ifdef LUCENE_TOKEN_WORD_LENGTH + TCHAR Value[LUCENE_TOKEN_WORD_LENGTH+1]; + #else + TCHAR* Value; + #endif + + int32_t Start; + int32_t End; + QueryToken::Types Type; + + // Initializes a new instance of the Token class. + QueryToken(TCHAR* value, const int32_t start, const int32_t end, const Types type); + + // Initializes a new instance of the Token class. + QueryToken(TCHAR* value, const Types type); + + // Initializes a new instance of the Token class. + QueryToken(Types type); + + // Initializes an empty instance of the Token class. + QueryToken(); + + ~QueryToken(); + + void set(TCHAR* value, const int32_t start, const int32_t end, const Types type); + void set(TCHAR* value, const Types type); + void set(Types type); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/queryParser/TokenList.cpp b/3rdparty/clucene/src/CLucene/queryParser/TokenList.cpp new file mode 100644 index 0000000..7d30b93 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/TokenList.cpp @@ -0,0 +1,79 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "TokenList.h" + +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/VoidList.h" +#include "QueryToken.h" + +CL_NS_DEF(queryParser) + + TokenList::TokenList(){ + //Func - Constructor + //Pre - true + //Post - Instance has been created + } + + TokenList::~TokenList(){ + //Func - Destructor + //Pre - true + //Post - The tokenlist has been destroyed + + tokens.clear(); + } + + void TokenList::add(QueryToken* token){ + //Func - Adds a QueryToken token to the TokenList + //Pre - token != NULL + //Post - token has been added to the token list + + CND_PRECONDITION(token != NULL, "token != NULL"); + + tokens.insert(tokens.begin(),token); + } + + void TokenList::push(QueryToken* token){ + //Func - + //Pre - token != NULL + //Post - + + CND_PRECONDITION(token != NULL, "token is NULL"); + + tokens.push_back(token); + } + + QueryToken* TokenList::peek() { + /* DSR:2004.11.01: Reverted my previous (circa April 2004) fix (which + ** raised an exception if Peek was called when there were no tokens) in + ** favor of returning the EOF token. This solution is much better + ** integrated with the rest of the code in the queryParser subsystem. */ + size_t nTokens = tokens.size(); + if (nTokens == 0) { + push(_CLNEW QueryToken(QueryToken::EOF_)); + nTokens++; + } + return tokens[nTokens-1]; + } + + QueryToken* TokenList::extract(){ + //Func - Extract token from the TokenList + //Pre - true + //Post - Retracted token has been returned + + QueryToken* token = peek(); + //Retract the current peeked token + tokens.delete_back(); + + return token; + } + + int32_t TokenList::count() const + { + return tokens.size(); + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/queryParser/TokenList.h b/3rdparty/clucene/src/CLucene/queryParser/TokenList.h new file mode 100644 index 0000000..3166bba --- /dev/null +++ b/3rdparty/clucene/src/CLucene/queryParser/TokenList.h @@ -0,0 +1,38 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_queryParser_TokenList_ +#define _lucene_queryParser_TokenList_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/VoidList.h" +#include "QueryToken.h" +CL_NS_DEF(queryParser) + + // Represents a list of the tokens. + class TokenList:LUCENE_BASE + { + private: + CL_NS(util)::CLVector tokens; //todo:,CL_NS(util)::Deletor::Object + public: + TokenList(); + ~TokenList(); + + void add(QueryToken* token); + + void push(QueryToken* token); + + QueryToken* peek(); + + QueryToken* extract(); + + int32_t count() const; + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/BooleanClause.h b/3rdparty/clucene/src/CLucene/search/BooleanClause.h new file mode 100644 index 0000000..b89cb31 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/BooleanClause.h @@ -0,0 +1,90 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_BooleanClause_ +#define _lucene_search_BooleanClause_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif +#include "SearchHeader.h" + +CL_NS_DEF(search) + // A clause in a BooleanQuery. + class BooleanClause:LUCENE_BASE { + public: + class Compare:public CL_NS_STD(binary_function) + { + public: + bool operator()( const BooleanClause* val1, const BooleanClause* val2 ) const{ + return val1->equals(val2); + } + }; + + // The query whose matching documents are combined by the boolean query. + Query* query; + + int32_t getClauseCount(); + + // If true, documents documents which do not + // match this sub-query will not match the boolean query. + bool required; + + // If true, documents documents which do + // match this sub-query will not match the boolean query. + bool prohibited; + + bool deleteQuery; + + // Constructs a BooleanClause with query q, required + // r and prohibited p. + BooleanClause(Query* q, const bool DeleteQuery,const bool req, const bool p): + query(q), + required(req), + prohibited(p), + deleteQuery(DeleteQuery) + { + } + + BooleanClause(const BooleanClause& clone): +#if defined(LUCENE_ENABLE_MEMLEAKTRACKING) +#elif defined(LUCENE_ENABLE_REFCOUNT) +#else + LuceneVoidBase(), +#endif + query(clone.query->clone()), + required(clone.required), + prohibited(clone.prohibited), + deleteQuery(true) + { + } + + BooleanClause* clone() const{ + BooleanClause* ret = _CLNEW BooleanClause(*this); + return ret; + } + + ~BooleanClause(){ + if ( deleteQuery ) + _CLDELETE( query ); + } + + /** Returns true iff o is equal to this. */ + bool equals(const BooleanClause* other) const { + return this->query->equals(other->query) + && (this->required == other->required) + && (this->prohibited == other->prohibited); + } + + size_t hashCode() const{ + return query->hashCode() ^ (this->required?1:0) ^ (this->prohibited?2:0); + } + }; + + +CL_NS_END +#endif + diff --git a/3rdparty/clucene/src/CLucene/search/BooleanQuery.cpp b/3rdparty/clucene/src/CLucene/search/BooleanQuery.cpp new file mode 100644 index 0000000..3fd36d8 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/BooleanQuery.cpp @@ -0,0 +1,363 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "BooleanQuery.h" + +#include "BooleanClause.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/StringBuffer.h" +#include "CLucene/util/Arrays.h" +#include "SearchHeader.h" +#include "BooleanScorer.h" +#include "Scorer.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + + BooleanQuery::BooleanQuery(): + clauses(true) + { + } + + BooleanQuery::BooleanQuery(const BooleanQuery& clone): + Query(clone) + { + for ( uint32_t i=0;iclone(); + clause->deleteQuery=true; + add(clause); + } + } + + BooleanQuery::~BooleanQuery(){ + clauses.clear(); + } + + size_t BooleanQuery::hashCode() const { + //todo: do cachedHashCode, and invalidate on add/remove clause + size_t ret = 0; + for (uint32_t i = 0 ; i < clauses.size(); i++) { + BooleanClause* c = clauses[i]; + ret = 31 * ret + c->hashCode(); + } + ret = ret ^ Similarity::floatToByte(getBoost()); + return ret; + } + + const TCHAR* BooleanQuery::getQueryName() const{ + return getClassName(); + } + const TCHAR* BooleanQuery::getClassName(){ + return _T("BooleanQuery"); + } + + /** + * Default value is 1024. Use org.apache.lucene.maxClauseCount + * system property to override. + */ + size_t BooleanQuery::maxClauseCount = LUCENE_BOOLEANQUERY_MAXCLAUSECOUNT; + size_t BooleanQuery::getMaxClauseCount(){ + return maxClauseCount; + } + + void BooleanQuery::setMaxClauseCount(size_t maxClauseCount){ + BooleanQuery::maxClauseCount = maxClauseCount; + } + + void BooleanQuery::add(Query* query, const bool deleteQuery, const bool required, const bool prohibited) { + BooleanClause* bc = _CLNEW BooleanClause(query,deleteQuery,required, prohibited); + try{ + add(bc); + }catch(...){ + _CLDELETE(bc); + throw; + } + } + + void BooleanQuery::add(BooleanClause* clause) { + if (clauses.size() >= getMaxClauseCount()) + _CLTHROWA(CL_ERR_TooManyClauses,"Too Many Clauses"); + + clauses.push_back(clause); + } + + + size_t BooleanQuery::getClauseCount() const { + return (int32_t) clauses.size(); + } + + TCHAR* BooleanQuery::toString(const TCHAR* field) const{ + StringBuffer buffer; + if (getBoost() != 1.0) { + buffer.append(_T("(")); + } + + for (uint32_t i = 0 ; i < clauses.size(); i++) { + BooleanClause* c = clauses[i]; + if (c->prohibited) + buffer.append(_T("-")); + else if (c->required) + buffer.append(_T("+")); + + if ( c->query->instanceOf(BooleanQuery::getClassName()) ) { // wrap sub-bools in parens + buffer.append(_T("(")); + + TCHAR* buf = c->query->toString(field); + buffer.append(buf); + _CLDELETE_CARRAY( buf ); + + buffer.append(_T(")")); + } else { + TCHAR* buf = c->query->toString(field); + buffer.append(buf); + _CLDELETE_CARRAY( buf ); + } + if (i != clauses.size()-1) + buffer.append(_T(" ")); + + if (getBoost() != 1.0) { + buffer.append(_T(")^")); + buffer.appendFloat(getBoost(),1); + } + } + return buffer.toString(); + } + + + + + BooleanClause** BooleanQuery::getClauses() const + { + CND_MESSAGE(false, "Warning: BooleanQuery::getClauses() is deprecated") + BooleanClause** ret = _CL_NEWARRAY(BooleanClause*, clauses.size()+1); + getClauses(ret); + return ret; + } + + void BooleanQuery::getClauses(BooleanClause** ret) const + { + size_t size=clauses.size(); + for ( uint32_t i=0;iprohibited) { // just return clause + Query* query = c->query->rewrite(reader); // rewrite first + + //if the query doesn't actually get re-written, + //then return a clone (because the BooleanQuery + //will register different to the returned query. + if ( query == c->query ) + query = query->clone(); + + if (getBoost() != 1.0f) { // incorporate boost + query->setBoost(getBoost() * query->getBoost()); + } + + return query; + } + } + + BooleanQuery* clone = NULL; // recursively rewrite + for (uint32_t i = 0 ; i < clauses.size(); i++) { + BooleanClause* c = clauses[i]; + Query* query = c->query->rewrite(reader); + if (query != c->query) { // clause rewrote: must clone + if (clone == NULL) + clone = (BooleanQuery*)this->clone(); + //todo: check if delete query should be on... + //in fact we should try and get rid of these + //for compatibility sake + clone->clauses.set (i, _CLNEW BooleanClause(query, true, c->required, c->prohibited)); + } + } + if (clone != NULL) { + return clone; // some clauses rewrote + } else + return this; // no clauses rewrote + } + + + Query* BooleanQuery::clone() const{ + BooleanQuery* clone = _CLNEW BooleanQuery(*this); + return clone; + } + + /** Returns true iff o is equal to this. */ + bool BooleanQuery::equals(Query* o)const { + if (!(o->instanceOf(BooleanQuery::getClassName()))) + return false; + const BooleanQuery* other = (BooleanQuery*)o; + + bool ret = (this->getBoost() == other->getBoost()); + if ( ret ){ + CLListEquals comp; + ret = comp.equals(&this->clauses,&other->clauses); + } + return ret; + } + + qreal BooleanQuery::BooleanWeight::getValue() { return parentQuery->getBoost(); } + Query* BooleanQuery::BooleanWeight::getQuery() { return (Query*)parentQuery; } + + + + + + BooleanQuery::BooleanWeight::BooleanWeight(Searcher* searcher, + CLVector >* clauses, BooleanQuery* parentQuery) + { + this->searcher = searcher; + this->parentQuery = parentQuery; + this->clauses = clauses; + for (uint32_t i = 0 ; i < clauses->size(); i++) { + weights.push_back((*clauses)[i]->query->_createWeight(searcher)); + } + } + BooleanQuery::BooleanWeight::~BooleanWeight(){ + this->weights.clear(); + } + + qreal BooleanQuery::BooleanWeight::sumOfSquaredWeights() { + qreal sum = 0.0f; + for (uint32_t i = 0 ; i < weights.size(); i++) { + BooleanClause* c = (*clauses)[i]; + Weight* w = weights[i]; + if (!c->prohibited) + sum += w->sumOfSquaredWeights(); // sum sub weights + } + sum *= parentQuery->getBoost() * parentQuery->getBoost(); // boost each sub-weight + return sum ; + } + + void BooleanQuery::BooleanWeight::normalize(qreal norm) { + norm *= parentQuery->getBoost(); // incorporate boost + for (uint32_t i = 0 ; i < weights.size(); i++) { + BooleanClause* c = (*clauses)[i]; + Weight* w = weights[i]; + if (!c->prohibited) + w->normalize(norm); + } + } + + Scorer* BooleanQuery::BooleanWeight::scorer(IndexReader* reader){ + // First see if the (faster) ConjunctionScorer will work. This can be + // used when all clauses are required. Also, at this point a + // BooleanScorer cannot be embedded in a ConjunctionScorer, as the hits + // from a BooleanScorer are not always sorted by document number (sigh) + // and hence BooleanScorer cannot implement skipTo() correctly, which is + // required by ConjunctionScorer. + bool allRequired = true; + bool noneBoolean = true; + { //msvc6 scope fix + for (uint32_t i = 0 ; i < weights.size(); i++) { + BooleanClause* c = (*clauses)[i]; + if (!c->required) + allRequired = false; + if (c->query->instanceOf(BooleanQuery::getClassName())) + noneBoolean = false; + } + } + + if (allRequired && noneBoolean) { // ConjunctionScorer is okay + ConjunctionScorer* result = + _CLNEW ConjunctionScorer(parentQuery->getSimilarity(searcher)); + for (uint32_t i = 0 ; i < weights.size(); i++) { + Weight* w = weights[i]; + Scorer* subScorer = w->scorer(reader); + if (subScorer == NULL) + return NULL; + result->add(subScorer); + } + return result; + } + + // Use good-old BooleanScorer instead. + BooleanScorer* result = _CLNEW BooleanScorer(parentQuery->getSimilarity(searcher)); + + { //msvc6 scope fix + for (uint32_t i = 0 ; i < weights.size(); i++) { + BooleanClause* c = (*clauses)[i]; + Weight* w = weights[i]; + Scorer* subScorer = w->scorer(reader); + if (subScorer != NULL) + result->add(subScorer, c->required, c->prohibited); + else if (c->required) + return NULL; + } + } + + return result; + } + + void BooleanQuery::BooleanWeight::explain(IndexReader* reader, int32_t doc, Explanation* result){ + int32_t coord = 0; + int32_t maxCoord = 0; + qreal sum = 0.0f; + Explanation* sumExpl = _CLNEW Explanation; + for (uint32_t i = 0 ; i < weights.size(); i++) { + BooleanClause* c = (*clauses)[i]; + Weight* w = weights[i]; + Explanation* e = _CLNEW Explanation; + w->explain(reader, doc, e); + if (!c->prohibited) + maxCoord++; + if (e->getValue() > 0) { + if (!c->prohibited) { + sumExpl->addDetail(e); + sum += e->getValue(); + coord++; + e = NULL; //prevent e from being deleted + } else { + //we want to return something else... + _CLDELETE(sumExpl); + result->setValue(0.0f); + result->setDescription(_T("match prohibited")); + return; + } + } else if (c->required) { + _CLDELETE(sumExpl); + result->setValue(0.0f); + result->setDescription(_T("match prohibited")); + return; + } + + _CLDELETE(e); + } + sumExpl->setValue(sum); + + if (coord == 1){ // only one clause matched + Explanation* tmp = sumExpl; + sumExpl = sumExpl->getDetail(0)->clone(); // eliminate wrapper + _CLDELETE(tmp); + } + + sumExpl->setDescription(_T("sum of:")); + qreal coordFactor = parentQuery->getSimilarity(searcher)->coord(coord, maxCoord); + if (coordFactor == 1.0f){ // coord is no-op + result->set(*sumExpl); // eliminate wrapper + _CLDELETE(sumExpl); + } else { + result->setDescription( _T("product of:")); + result->addDetail(sumExpl); + + StringBuffer explbuf; + explbuf.append(_T("coord(")); + explbuf.appendInt(coord); + explbuf.append(_T("/")); + explbuf.appendInt(maxCoord); + explbuf.append(_T(")")); + result->addDetail(_CLNEW Explanation(coordFactor, explbuf.getBuffer())); + result->setValue(sum*coordFactor); + } + } + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/BooleanQuery.h b/3rdparty/clucene/src/CLucene/search/BooleanQuery.h new file mode 100644 index 0000000..27b67d1 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/BooleanQuery.h @@ -0,0 +1,126 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_BooleanQuery_ +#define _lucene_search_BooleanQuery_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "ConjunctionScorer.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/StringBuffer.h" +#include "SearchHeader.h" +#include "BooleanClause.h" +#include "BooleanScorer.h" +#include "Scorer.h" + +CL_NS_DEF(search) + + + // A Query that matches documents matching boolean combinations of other + // queries, typically {@link TermQuery}s or {@link PhraseQuery}s. + class BooleanQuery:public Query { + public: + typedef CL_NS(util)::CLVector > ClausesType; + private: + BooleanQuery::ClausesType clauses; + static size_t maxClauseCount; + + class BooleanWeight: public Weight { + private: + Searcher* searcher; + CL_NS(util)::CLVector > weights; + ClausesType* clauses; + BooleanQuery* parentQuery; + public: + BooleanWeight(Searcher* searcher, + CL_NS(util)::CLVector >* clauses, + BooleanQuery* parentQuery); + ~BooleanWeight(); + Query* getQuery(); + qreal getValue(); + qreal sumOfSquaredWeights(); + void normalize(qreal norm); + Scorer* scorer(CL_NS(index)::IndexReader* reader); + void explain(CL_NS(index)::IndexReader* reader, int32_t doc, Explanation* ret); + };//booleanweight + + protected: + Weight* _createWeight(Searcher* searcher) { + return _CLNEW BooleanWeight(searcher,&clauses,this); + } + BooleanQuery(const BooleanQuery& clone); + public: + /** Constructs an empty boolean query. */ + BooleanQuery(); + + ~BooleanQuery(); + + const TCHAR* getQueryName() const; + static const TCHAR* getClassName(); + + /** Return the maximum number of clauses permitted, 1024 by default. + * Attempts to add more than the permitted number of clauses cause {@link + * TooManyClauses} to be thrown.*/ + static size_t getMaxClauseCount(); + + /** Set the maximum number of clauses permitted. */ + static void setMaxClauseCount(size_t maxClauseCount); + + /** Adds a clause to a boolean query. Clauses may be: + *

    + *
  • required which means that documents which do not + * match this sub-query will not match the boolean query; + *
  • prohibited which means that documents which do + * match this sub-query will not match the boolean query; or + *
  • neither, in which case matched documents are neither prohibited from + * nor required to match the sub-query. However, a document must match at + * least 1 sub-query to match the boolean query. + *
+ * It is an error to specify a clause as both required and + * prohibited. + * + * @see #getMaxClauseCount() + */ + void add(Query* query, const bool required, const bool prohibited){ + add(query,false,required,prohibited); + } + void add(Query* query, const bool deleteQuery, const bool required, const bool prohibited); + + /** Copies the clauses of this query into the array. + * The array must be at least as long as getClauseCount() + * If you want to use the clauses, make sure you null terminate it. + */ + void getClauses(BooleanClause** clauses) const; + + ///@deprecated + _CL_DEPRECATED( getClauses(clauses) ) BooleanClause** getClauses() const; + + /** + * Give client code access to clauses.size() so we know how + * large the array returned by getClauses is. + */ + size_t getClauseCount() const; + + /** Adds a clause to a boolean query. + * @see #getMaxClauseCount() + */ + void add(BooleanClause* clause); + + Query* rewrite(CL_NS(index)::IndexReader* reader); + Query* clone() const; + bool equals(Query* o) const; + + /** Prints a user-readable version of this query. */ + TCHAR* toString(const TCHAR* field) const; + /** Returns a hash code value for this object.*/ + size_t hashCode() const; + }; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/BooleanScorer.cpp b/3rdparty/clucene/src/CLucene/search/BooleanScorer.cpp new file mode 100644 index 0000000..ae7ee40 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/BooleanScorer.cpp @@ -0,0 +1,248 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "BooleanScorer.h" + +#include "Scorer.h" +#include "Similarity.h" + +CL_NS_USE(util) +CL_NS_DEF(search) + + BooleanScorer::BooleanScorer(Similarity* similarity): + Scorer(similarity), + scorers(NULL), + maxCoord (1), + nextMask (1), + end(0), + current(NULL), + requiredMask (0), + prohibitedMask (0), + coordFactors (NULL) + { + bucketTable = _CLNEW BucketTable(this); + } + + BooleanScorer::~BooleanScorer(){ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + _CLDELETE(bucketTable); + _CLDELETE_ARRAY(coordFactors); + _CLDELETE(scorers); + } + + + bool BooleanScorer::next() { + bool more; + do { + while (bucketTable->first != NULL) { // more queued + current = bucketTable->first; + bucketTable->first = current->next; // pop the queue + + // check prohibited & required + if ((current->bits & prohibitedMask) == 0 && + (current->bits & requiredMask) == requiredMask) { + return true; + } + } + + // refill the queue + more = false; + end += BooleanScorer::BucketTable_SIZE; + for (SubScorer* sub = scorers; sub != NULL; sub = sub->next) { + Scorer* scorer = sub->scorer; + int32_t doc; + while (!sub->done && (doc=scorer->doc()) < end) { + sub->collector->collect(doc, scorer->score()); + sub->done = !scorer->next(); + } + if (!sub->done) { + more = true; + } + } + } while (bucketTable->first != NULL || more); + + return false; + } + + qreal BooleanScorer::score(){ + if (coordFactors == NULL) + computeCoordFactors(); + return current->score * coordFactors[current->coord]; + } + + bool BooleanScorer::skipTo(int32_t target) { + _CLTHROWA(CL_ERR_UnsupportedOperation,"UnsupportedOperationException: BooleanScorer::skipTo"); + } + + void BooleanScorer::explain(int32_t doc, Explanation* ret) { + _CLTHROWA(CL_ERR_UnsupportedOperation,"UnsupportedOperationException: BooleanScorer::explain"); + } + + TCHAR* BooleanScorer::toString() { + CL_NS(util)::StringBuffer buffer; + buffer.append(_T("boolean(")); + for (SubScorer* sub = scorers; sub != NULL; sub = sub->next) { + buffer.append(sub->scorer->toString()); + buffer.append(_T(" ")); + } + buffer.appendChar(')'); + return buffer.toString(); + } + + void BooleanScorer::add(Scorer* scorer, const bool required, const bool prohibited) { + int32_t mask = 0; + if (required || prohibited) { + if (nextMask == 0) + _CLTHROWA(CL_ERR_IndexOutOfBounds, "More than 32 required/prohibited clauses in query."); + mask = nextMask; + nextMask = ( nextMask << 1 ); + } else + mask = 0; + + if (!prohibited) + maxCoord++; + + if (prohibited) + prohibitedMask |= mask; // update prohibited mask + else if (required) + requiredMask |= mask; // update required mask + + //scorer, HitCollector, and scorers is delete in the SubScorer + scorers = _CLNEW SubScorer(scorer, required, prohibited, + bucketTable->newCollector(mask), scorers); + } + + void BooleanScorer::computeCoordFactors(){ + coordFactors = _CL_NEWARRAY(qreal,maxCoord); + for (int32_t i = 0; i < maxCoord; i++) + coordFactors[i] = getSimilarity()->coord(i, maxCoord-1); + } + + /*void BooleanScorer::score(HitCollector* results, const int32_t maxDoc) { + if (coordFactors == NULL) + computeCoordFactors(); + + while (currentDoc < maxDoc) { + currentDoc = (currentDoc+BucketTable_SIZEnext) + t->scorer->score((t->collector), currentDoc); + bucketTable->collectHits(results); + } + }*/ + + + + + BooleanScorer::SubScorer::SubScorer(Scorer* scr, const bool r, const bool p, HitCollector* c, SubScorer* nxt): + scorer(scr), + required(r), + prohibited(p), + collector(c), + next(nxt) + { + //Func - Constructor + //Pre - scr != NULL, + // c != NULL + // nxt may or may not be NULL + //Post - The instance has been created + + CND_PRECONDITION(scr != NULL,"scr is NULL"); + CND_PRECONDITION(c != NULL,"c is NULL"); + + done = !scorer->next(); + } + + BooleanScorer::SubScorer::~SubScorer(){ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + for (SubScorer * ptr = next; ptr; ){ + SubScorer* next = ptr->next; + ptr->next = NULL; + _CLDELETE(ptr); + ptr = next; + } + _CLDELETE(scorer); + _CLDELETE(collector); + } + + BooleanScorer::Bucket::Bucket(): + doc(-1), + score(0.0), + bits(0), + coord(0), + next(NULL) + { + } + BooleanScorer::Bucket::~Bucket(){ + } + + + + + BooleanScorer::BucketTable::BucketTable(BooleanScorer* scr): + scorer(scr), + first(NULL) + { + buckets = _CL_NEWARRAY(Bucket,BucketTable_SIZE); + } + BooleanScorer::BucketTable::~BucketTable(){ + clear(); + _CLDELETE_ARRAY(buckets); + } + + void BooleanScorer::BucketTable::clear(){ + //delete first; + first = NULL; + } + int32_t BooleanScorer::BucketTable::size() const { return BooleanScorer::BucketTable_SIZE; } + + HitCollector* BooleanScorer::BucketTable::newCollector(const int32_t mask) { + return _CLNEW Collector(mask, this); + } + + + + + + + + + + BooleanScorer::Collector::Collector(const int32_t msk, BucketTable* bucketTbl): + bucketTable(bucketTbl), + mask(msk) + { + } + + void BooleanScorer::Collector::collect(const int32_t doc, const qreal score){ + BucketTable* table = bucketTable; + int32_t i = doc & (BooleanScorer::BucketTable_SIZE-1); + Bucket* bucket = &table->buckets[i]; + + if (bucket->doc != doc) { // invalid bucket + bucket->doc = doc; // set doc + bucket->score = score; // initialize score + bucket->bits = mask; // initialize mask + bucket->coord = 1; // initialize coord + + bucket->next = table->first; // push onto valid list + table->first = bucket; + } else { // valid bucket + bucket->score += score; // increment score + bucket->bits |= mask; // add bits in mask + bucket->coord++; // increment coord + } + } + + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/BooleanScorer.h b/3rdparty/clucene/src/CLucene/search/BooleanScorer.h new file mode 100644 index 0000000..2147bc5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/BooleanScorer.h @@ -0,0 +1,99 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_BooleanScorer_ +#define _lucene_search_BooleanScorer_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Scorer.h" + +CL_NS_DEF(search) + +class BooleanScorer : public Scorer { +public: + class Bucket : LUCENE_BASE { + public: + int32_t doc; // tells if bucket is valid + qreal score; // incremental score + int32_t bits; // used for bool constraints + int32_t coord; // count of terms in score + Bucket* next; // next valid bucket + + Bucket(); + ~Bucket(); + }; + + class SubScorer: LUCENE_BASE { + public: + bool done; + Scorer* scorer; + bool required; + bool prohibited; + HitCollector* collector; + SubScorer* next; + SubScorer(Scorer* scr, const bool r, const bool p, HitCollector* c, SubScorer* nxt); + ~SubScorer(); + }; + + class BucketTable:LUCENE_BASE { + private: + BooleanScorer* scorer; + public: + Bucket* buckets; + Bucket* first; // head of valid list + + BucketTable(BooleanScorer* scr); + int32_t size() const; + HitCollector* newCollector(const int32_t mask); + void clear(); + ~BucketTable(); + + }; + + class Collector: public HitCollector { + private: + BucketTable* bucketTable; + int32_t mask; + public: + Collector(const int32_t mask, BucketTable* bucketTable); + + void collect(const int32_t doc, const qreal score); + }; + + SubScorer* scorers; + BucketTable* bucketTable; + + int32_t maxCoord; + int32_t nextMask; + + int32_t end; + Bucket* current; + +public: + LUCENE_STATIC_CONSTANT(int32_t,BucketTable_SIZE=1024); + int32_t requiredMask; + int32_t prohibitedMask; + qreal* coordFactors; + + BooleanScorer(Similarity* similarity); + ~BooleanScorer(); + void add(Scorer* scorer, const bool required, const bool prohibited); + int32_t doc() const { return current->doc; } + bool next(); + qreal score(); + bool skipTo(int32_t target); + void explain(int32_t doc, Explanation* ret); + TCHAR* toString(); + void computeCoordFactors(); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.cpp b/3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.cpp new file mode 100644 index 0000000..694556c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.cpp @@ -0,0 +1,86 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CachingWrapperFilter.h" + +CL_NS_DEF(search) +CL_NS_USE(index) +CL_NS_USE(util) + +AbstractCachingFilter::AbstractCachingFilter(): + cache(false,true) +{ +} +AbstractCachingFilter::AbstractCachingFilter(const AbstractCachingFilter& copy): + cache(false,true) +{ +} +AbstractCachingFilter::~AbstractCachingFilter(){ +} +AbstractCachingFilter::BitSetHolder::BitSetHolder(CL_NS(util)::BitSet* bits, bool deleteBs){ + this->bits = bits; + this->deleteBs = deleteBs; +} +AbstractCachingFilter::BitSetHolder::~BitSetHolder(){ + if ( deleteBs ) + _CLDELETE(bits); +} + + +BitSet* AbstractCachingFilter::bits(IndexReader* reader){ + SCOPED_LOCK_MUTEX(cache.THIS_LOCK) + BitSetHolder* cached = cache.get(reader); + if ( cached != NULL ) + return cached->bits; + BitSet* bs = doBits(reader); + BitSetHolder* bsh = _CLNEW BitSetHolder(bs, doShouldDeleteBitSet(bs)); + cache.put(reader,bsh); + return bs; +} +void AbstractCachingFilter::closeCallback(CL_NS(index)::IndexReader* reader, void*){ + SCOPED_LOCK_MUTEX(cache.THIS_LOCK) + cache.remove(reader); +} + + + + +CachingWrapperFilter::CachingWrapperFilter(Filter* filter, bool deleteFilter){ + this->filter = filter; + this->deleteFilter = deleteFilter; +} +CachingWrapperFilter::CachingWrapperFilter(const CachingWrapperFilter& copy): + AbstractCachingFilter(copy) +{ + this->filter = copy.filter->clone(); + this->deleteFilter = true; +} +Filter* CachingWrapperFilter::clone() const{ + return _CLNEW CachingWrapperFilter(*this); +} +TCHAR* CachingWrapperFilter::toString(){ + TCHAR* fs = filter->toString(); + int len = _tcslen(fs)+23; + TCHAR* ret = _CL_NEWARRAY(TCHAR,len); + _sntprintf(ret,len,_T("CachingWrapperFilter(%s)"),fs); + _CLDELETE_CARRAY(fs); + return ret; +} +BitSet* CachingWrapperFilter::doBits(IndexReader* reader){ + return filter->bits(reader); +} +bool CachingWrapperFilter::doShouldDeleteBitSet( CL_NS(util)::BitSet* bits ){ + return filter->shouldDeleteBitSet(bits); +} +CachingWrapperFilter::~CachingWrapperFilter(){ + if ( deleteFilter ){ + _CLDELETE(filter); + }else + filter=NULL; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.h b/3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.h new file mode 100644 index 0000000..e48a182 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/CachingWrapperFilter.h @@ -0,0 +1,80 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_CachingWrapperFilter_ +#define _lucene_search_CachingWrapperFilter_ + +#include "CLucene/util/BitSet.h" +#include "CLucene/index/IndexReader.h" +#include "Filter.h" + +CL_NS_DEF(search) +/** + * Wraps another filter's result and caches it. The purpose is to allow + * filters to implement this and allow itself to be cached. Alternatively, + * use the CachingWrapperFilter to cache the filter. + */ +class AbstractCachingFilter: public Filter +{ + class BitSetHolder: LUCENE_BASE{ + bool deleteBs; + public: + BitSetHolder(CL_NS(util)::BitSet* bits, bool deleteBs); + ~BitSetHolder(); + CL_NS(util)::BitSet* bits; + }; + void closeCallback(CL_NS(index)::IndexReader* reader, void* param); + typedef CL_NS(util)::CLHashMap, + CL_NS(util)::Equals::Void, + CL_NS(util)::Deletor::Object, + CL_NS(util)::Deletor::Object > CacheType; + + CacheType cache; + +protected: + AbstractCachingFilter( const AbstractCachingFilter& copy ); + virtual CL_NS(util)::BitSet* doBits( CL_NS(index)::IndexReader* reader ) = 0; + virtual bool doShouldDeleteBitSet( CL_NS(util)::BitSet* bits ){ return false; } + AbstractCachingFilter(); +public: + virtual ~AbstractCachingFilter(); + + /** Returns a BitSet with true for documents which should be permitted in + search results, and false for those that should not. */ + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader ); + + virtual Filter *clone() const = 0; + virtual TCHAR *toString() = 0; + + bool shouldDeleteBitSet( const CL_NS(util)::BitSet* bits ) const{ return false; } +}; + +/** + * Wraps another filter's result and caches it. The purpose is to allow + * filters to simply filter, and then wrap with this class to add + * caching, keeping the two concerns decoupled yet composable. + */ +class CachingWrapperFilter: public AbstractCachingFilter +{ +private: + Filter* filter; + bool deleteFilter; +protected: + CachingWrapperFilter( const CachingWrapperFilter& copy ); + CL_NS(util)::BitSet* doBits( CL_NS(index)::IndexReader* reader ); + bool doShouldDeleteBitSet( CL_NS(util)::BitSet* bits ); +public: + CachingWrapperFilter( Filter* filter, bool deleteFilter=true ); + ~CachingWrapperFilter(); + + Filter *clone() const; + TCHAR *toString(); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/ChainedFilter.cpp b/3rdparty/clucene/src/CLucene/search/ChainedFilter.cpp new file mode 100644 index 0000000..4b6389c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/ChainedFilter.cpp @@ -0,0 +1,213 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ + +#include +#include +#include "ChainedFilter.h" + +CL_NS_DEF(search) +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_USE(document) + + +ChainedFilter::ChainedFilter( Filter ** _filters, int _op ): + filters(_filters), + logicArray(NULL), + logic(_op) +{ +} +ChainedFilter::ChainedFilter( Filter** _filters, int* _array ): + filters(_filters), + logicArray(_array), + logic(-1) +{ +} +ChainedFilter::ChainedFilter( const ChainedFilter& copy ) : + logicArray( copy.logicArray ), + logic( copy.logic ) +{ + filters = copy.filters; +} +ChainedFilter::~ChainedFilter(void) +{ + +} + +Filter* ChainedFilter::clone() const { + return _CLNEW ChainedFilter(*this ); +} + +const TCHAR* ChainedFilter::getLogicString(int logic){ + if ( logic == ChainedFilter::OR ) + return _T("OR"); + else if ( logic == ChainedFilter::AND ) + return _T("AND"); + else if ( logic == ChainedFilter::ANDNOT ) + return _T("ANDNOT"); + else if ( logic == ChainedFilter::XOR ) + return _T("XOR"); + else if ( logic >= ChainedFilter::USER ){ + return _T("USER"); + } + return _T(""); +} + +TCHAR* ChainedFilter::toString() +{ + + Filter** filter = filters; + + StringBuffer buf(_T("ChainedFilter: [")); + int* la = logicArray; + while(*filter ) + { + if ( filter != filters ) + buf.appendChar(' '); + buf.append(getLogicString(logic==-1?*la:logic)); + buf.appendChar(' '); + + TCHAR* filterstr = (*filter)->toString(); + buf.append(filterstr); + _CLDELETE_ARRAY( filterstr ); + + filter++; + if ( logic == -1 ) + la++; + } + + buf.appendChar(']'); + + return buf.toString(); +} + + +/** Returns a BitSet with true for documents which should be permitted in +search results, and false for those that should not. */ +BitSet* ChainedFilter::bits( IndexReader* reader ) +{ + if( logic != -1 ) + return bits( reader, logic ); + else if( logicArray != NULL ) + return bits( reader, logicArray ); + else + return bits( reader, DEFAULT ); +} + + +BitSet* ChainedFilter::bits( IndexReader* reader, int logic ) +{ + BitSet* bts = NULL; + + Filter** filter = filters; + + // see discussion at top of file + if( *filter ) { + BitSet* tmp = (*filter)->bits( reader ); + if ( (*filter)->shouldDeleteBitSet(tmp) ) //if we are supposed to delete this BitSet, then + bts = tmp; //we can safely call it our own + else if ( tmp == NULL ){ + int32_t len = reader->maxDoc(); + bts = _CLNEW BitSet( len ); //bitset returned null, which means match _all_ + for (int32_t i=0;iset(i); + }else{ + bts = tmp->clone(); //else it is probably cached, so we need to copy it before using it. + } + filter++; + } + else + bts = _CLNEW BitSet( reader->maxDoc() ); + + while( *filter ) { + doChain( bts, reader, logic, *filter ); + filter++; + } + + return bts; +} + + +BitSet* ChainedFilter::bits( IndexReader* reader, int* _logicArray ) +{ + BitSet* bts = NULL; + + Filter** filter = filters; + int* logic = _logicArray; + + // see discussion at top of file + if( *filter ) { + BitSet* tmp = (*filter)->bits( reader ); + if ( (*filter)->shouldDeleteBitSet(tmp) ) //if we are supposed to delete this BitSet, then + bts = tmp; //we can safely call it our own + else if ( tmp == NULL ){ + int32_t len = reader->maxDoc(); + bts = _CLNEW BitSet( len ); //bitset returned null, which means match _all_ + for (int32_t i=0;iset(i); //todo: this could mean that we can skip certain types of filters + } + else + { + bts = tmp->clone(); //else it is probably cached, so we need to copy it before using it. + } + filter++; + logic++; + } + else + bts = _CLNEW BitSet( reader->maxDoc() ); + + while( *filter ) { + doChain( bts, reader, *logic, *filter ); + filter++; + logic++; + } + + return bts; +} + +void ChainedFilter::doUserChain( CL_NS(util)::BitSet* chain, CL_NS(util)::BitSet* filter, int logic ){ + _CLTHROWA(CL_ERR_Runtime,"User chain logic not implemented by superclass"); +} + +BitSet* ChainedFilter::doChain( BitSet* resultset, IndexReader* reader, int logic, Filter* filter ) +{ + BitSet* filterbits = filter->bits( reader ); + int32_t maxDoc = reader->maxDoc(); + int32_t i=0; + if ( logic >= ChainedFilter::USER ){ + doUserChain(resultset,filterbits,logic); + }else{ + switch( logic ) + { + case OR: + for( i=0; i < maxDoc; i++ ) + resultset->set( i, (resultset->get(i) || (filterbits==NULL || filterbits->get(i) ))?1:0 ); + break; + case AND: + for( i=0; i < maxDoc; i++ ) + resultset->set( i, (resultset->get(i) && (filterbits==NULL || filterbits->get(i) ))?1:0 ); + break; + case ANDNOT: + for( i=0; i < maxDoc; i++ ) + resultset->set( i, (resultset->get(i) && (filterbits==NULL || filterbits->get(i)))?0:1 ); + break; + case XOR: + for( i=0; i < maxDoc; i++ ) + resultset->set( i, resultset->get(i) ^ ((filterbits==NULL || filterbits->get(i) )?1:0) ); + break; + default: + doChain( resultset, reader, DEFAULT, filter ); + } + } + + if ( filter->shouldDeleteBitSet(filterbits) ) + _CLDELETE( filterbits ); + + return resultset; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/ChainedFilter.h b/3rdparty/clucene/src/CLucene/search/ChainedFilter.h new file mode 100644 index 0000000..f4d9d00 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/ChainedFilter.h @@ -0,0 +1,86 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_ChainedFilter_ +#define _lucene_search_ChainedFilter_ + +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/BitSet.h" +#include "CLucene/search/Filter.h" + +CL_NS_DEF(search) + +/* +Discussion - brian@unixpoet.com + +From ChainedFilter.java: + +... + +// First AND operation takes place against a completely false +// bitset and will always return zero results. Thanks to +// Daniel Armbrust for pointing this out and suggesting workaround. + +if (logic[0] == AND) +{ + result = (BitSet) chain[i].bits(reader).clone(); + ++i; +} + +... + +The observation is correct and it was buggy. The problem is that the same +issue remains for the ANDNOT logic op but with the inverse result: all bits +set to 1. The result of the other ops, i.e. OR, AND, XOR for the first filter +ends up just copying the bitset of the first filter (explicitly in the case of the AND). + +Why not do the same for the NAND? This will have the side effect of rendering the first op +in the logic array superflous - not a big problem. + +The only "problem" is that we will return different results then the Java +Lucene code - though I prefer CLucene to be a correct implementation and only maintain +API compat rather than full 100% compat with Lucene. +*/ +class ChainedFilter: public Filter +{ +public: + LUCENE_STATIC_CONSTANT(int, OR = 0); //set current bit if the chain is set OR if the filter bit is set + LUCENE_STATIC_CONSTANT(int, AND = 1); //set current bit if the chain is set AND the filter bit is set + LUCENE_STATIC_CONSTANT(int, ANDNOT = 2); //set current bit if the chain is not set AND the filter bit is not set + LUCENE_STATIC_CONSTANT(int, XOR = 3); //set current bit if the chain is set OR the filter bit is set BUT not both is set + + LUCENE_STATIC_CONSTANT(int, USER = 5); //add this value to user defined value, then override doUserChain + + LUCENE_STATIC_CONSTANT(int, DEFAULT = OR); + +protected: + Filter **filters; + int *logicArray; + int logic; + + ChainedFilter( const ChainedFilter& copy ); + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader, int logic ); + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader, int* logicArray ); + CL_NS(util)::BitSet* doChain( CL_NS(util)::BitSet* result, CL_NS(index)::IndexReader* reader, int logic, Filter* filter ); + + virtual void doUserChain( CL_NS(util)::BitSet* chain, CL_NS(util)::BitSet* filter, int logic ); + virtual const TCHAR* getLogicString(int logic); +public: + ChainedFilter( Filter** filters, int op = DEFAULT ); + ChainedFilter( Filter** filters, int* _array ); + virtual ~ChainedFilter(); + + /** Returns a BitSet with true for documents which should be permitted in + search results, and false for those that should not. */ + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader ); + + virtual Filter* clone() const; + + TCHAR* toString(); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/Compare.h b/3rdparty/clucene/src/CLucene/search/Compare.h new file mode 100644 index 0000000..ab38b17 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Compare.h @@ -0,0 +1,161 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_Compare_ +#define _lucene_search_Compare_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "FieldSortedHitQueue.h" + +CL_NS_DEF(search) + + +class ScoreDocComparators:LUCENE_BASE { +protected: + ScoreDocComparators(){} +public: + ~ScoreDocComparators(){ + } + + class Relevance:public ScoreDocComparator { + public: + int32_t compare (struct ScoreDoc* i, struct ScoreDoc* j) { + if (i->score > j->score) return -1; + if (i->score < j->score) return 1; + return 0; + } + CL_NS(util)::Comparable* sortValue (struct ScoreDoc* i) { + return _CLNEW CL_NS(util)::Compare::Float (i->score); + } + int32_t sortType() { + return SortField::DOCSCORE; + } + }; + + class IndexOrder:public ScoreDocComparator{ + public: + IndexOrder(): + ScoreDocComparator() + { + + } + int32_t compare (struct ScoreDoc* i, struct ScoreDoc* j) { + if (i->doc < j->doc) return -1; + if (i->doc > j->doc) return 1; + return 0; + } + CL_NS(util)::Comparable* sortValue (struct ScoreDoc* i) { + return _CLNEW CL_NS(util)::Compare::Int32(i->doc); + } + int32_t sortType() { + return SortField::DOC; + } + }; + + + class String: public ScoreDocComparator { + FieldCache::StringIndex* index; +#ifdef _CL__CND_DEBUG + int32_t length; +#endif + public: + String(FieldCache::StringIndex* index, int32_t len) + { +#ifdef _CL__CND_DEBUG + this->length = len; +#endif + this->index = index; + } + + int32_t compare (struct ScoreDoc* i, struct ScoreDoc* j) { + CND_PRECONDITION(i->docdoc>=length") + CND_PRECONDITION(j->docdoc>=length") + if (index->order[i->doc] < index->order[j->doc]) return -1; + if (index->order[i->doc] > index->order[j->doc]) return 1; + return 0; + } + + CL_NS(util)::Comparable* sortValue (struct ScoreDoc* i) { + return _CLNEW CL_NS(util)::Compare::TChar(index->lookup[index->order[i->doc]]); + } + + int32_t sortType() { + return SortField::STRING; + } + }; + + class Int32:public ScoreDocComparator{ + int32_t* fieldOrder; +#ifdef _CL__CND_DEBUG + int32_t length; +#endif + public: + Int32(int32_t* fieldOrder, int32_t len) + { + this->fieldOrder = fieldOrder; +#ifdef _CL__CND_DEBUG + this->length = len; +#endif + } + + + int32_t compare (struct ScoreDoc* i, struct ScoreDoc* j) { + CND_PRECONDITION(i->docdoc>=length") + CND_PRECONDITION(j->docdoc>=length") + if (fieldOrder[i->doc] < fieldOrder[j->doc]) return -1; + if (fieldOrder[i->doc] > fieldOrder[j->doc]) return 1; + return 0; + } + + CL_NS(util)::Comparable* sortValue (struct ScoreDoc* i) { + CND_PRECONDITION(i->docdoc>=length") + return _CLNEW CL_NS(util)::Compare::Int32(fieldOrder[i->doc]); + } + + int32_t sortType() { + return SortField::INT; + } + }; + + class Float:public ScoreDocComparator { + qreal* fieldOrder; +#ifdef _CL__CND_DEBUG + int32_t length; +#endif + public: + Float(qreal* fieldOrder, int32_t len) + { + this->fieldOrder = fieldOrder; +#ifdef _CL__CND_DEBUG + this->length = len; +#endif + } + + int32_t compare (struct ScoreDoc* i, struct ScoreDoc* j) { + CND_PRECONDITION(i->docdoc>=length") + CND_PRECONDITION(j->docdoc>=length") + if (fieldOrder[i->doc] < fieldOrder[j->doc]) return -1; + if (fieldOrder[i->doc] > fieldOrder[j->doc]) return 1; + return 0; + } + + CL_NS(util)::Comparable* sortValue (struct ScoreDoc* i) { + CND_PRECONDITION(i->docdoc>=length") + return _CLNEW CL_NS(util)::Compare::Float(fieldOrder[i->doc]); + } + + int32_t sortType() { + return SortField::FLOAT; + } + }; +}; + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/ConjunctionScorer.cpp b/3rdparty/clucene/src/CLucene/search/ConjunctionScorer.cpp new file mode 100644 index 0000000..9b7846f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/ConjunctionScorer.cpp @@ -0,0 +1,144 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "ConjunctionScorer.h" +#include "CLucene/util/Arrays.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + + Scorer* ConjunctionScorer::first() const{ + if ( scorers.end() == scorers.begin() ) + return NULL; + + return *scorers.begin(); + } //get First + Scorer* ConjunctionScorer::last() { + if ( scorers.end() == scorers.begin() ) + return NULL; + + CL_NS_STD(list)::iterator i = scorers.end(); + --i; + return *i; + } //get Last + + class _ScorerSorter:public CL_NS(util)::Arrays::_Arrays{ + public: + bool equals(Scorer* o1,Scorer* o2) const{ + return o1->doc() == o2->doc(); + } + int32_t compare(Scorer* o1,Scorer* o2) const{ + return o1->doc() - o2->doc(); + } + }; + _ScorerSorter __ScorerSorter; + + void ConjunctionScorer::sortScorers() { + // move scorers to an array + int32_t size = scorers.size(); + Scorer** array = _CL_NEWARRAY(Scorer*,size+1); + scorers.toArray(array); + scorers.clear(); // empty the list + + // note that this comparator is not consistent with equals! + __ScorerSorter.sort(array,size,0,size); + + for (int32_t i = 0; idoc() < last()->doc()) { // find doc w/ all clauses + more = first()->skipTo(last()->doc()); // skip first upto last + Scorer* scorer = *scorers.begin(); + scorers.delete_front(); + scorers.push_back(scorer); // move first to last + } + return more; // found a doc with all clauses + } + + + void ConjunctionScorer::init() { + more = scorers.size() > 0; + + // compute coord factor + coord = getSimilarity()->coord(scorers.size(), scorers.size()); + + // move each scorer to its first entry + CL_NS_STD(list)::iterator i = scorers.begin(); + while (more && i!=scorers.end()) { + more = ((Scorer*)*i)->next(); + ++i; + } + + if (more) + sortScorers(); // initial sort of list + + firstTime = false; + } + + ConjunctionScorer::ConjunctionScorer(Similarity* similarity): + Scorer(similarity), + scorers(false), + firstTime(true), + more(true), + coord(0.0) + { + } + ConjunctionScorer::~ConjunctionScorer(){ + scorers.setDoDelete(true); + } + + TCHAR *CL_NS(search)::Scorer::toString(void){ + return STRDUP_TtoT(_T("ConjunctionScorer")); + } + + + void ConjunctionScorer::add(Scorer* scorer){ + scorers.push_back(scorer); + } + + + int32_t ConjunctionScorer::doc() const{ return first()->doc(); } + + bool ConjunctionScorer::next() { + if (firstTime) { + init(); + } else if (more) { + more = last()->next(); // trigger further scanning + } + return doNext(); + } + + bool ConjunctionScorer::skipTo(int32_t target) { + CL_NS_STD(list)::iterator i = scorers.begin(); + while (more && i!=scorers.end()) { + more = ((Scorer*)*i)->skipTo(target); + ++i; + } + if (more) + sortScorers(); // re-sort scorers + return doNext(); + } + + qreal ConjunctionScorer::score(){ + qreal score = 0.0f; // sum scores + CL_NS_STD(list)::const_iterator i = scorers.begin(); + while (i!=scorers.end()){ + score += (*i)->score(); + ++i; + } + score *= coord; + return score; + } + + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/ConjunctionScorer.h b/3rdparty/clucene/src/CLucene/search/ConjunctionScorer.h new file mode 100644 index 0000000..4b68072 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/ConjunctionScorer.h @@ -0,0 +1,50 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_ConjunctionScorer_ +#define _lucene_search_ConjunctionScorer_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif +#include "Scorer.h" +#include "Similarity.h" + +CL_NS_DEF(search) + +/** Scorer for conjunctions, sets of queries, all of which are required. */ +class ConjunctionScorer: public Scorer { +private: + CL_NS(util)::CLLinkedList > scorers; + bool firstTime; + bool more; + qreal coord; + + Scorer* first() const; + Scorer* last(); + void sortScorers(); + bool doNext(); + void init(); +public: + ConjunctionScorer(Similarity* similarity); + virtual ~ConjunctionScorer(); + TCHAR* toString(void){ + return STRDUP_TtoT(_T("ConjunctionScorer")); + } + void add(Scorer* scorer); + int32_t doc() const; + bool next(); + bool skipTo(int32_t target); + qreal score(); + virtual void explain(int32_t doc, Explanation* ret) { + _CLTHROWA(CL_ERR_UnsupportedOperation,"UnsupportedOperationException: ConjunctionScorer::explain"); + } + + +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/DateFilter.cpp b/3rdparty/clucene/src/CLucene/search/DateFilter.cpp new file mode 100644 index 0000000..9258582 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/DateFilter.cpp @@ -0,0 +1,93 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "DateFilter.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_USE(document) +CL_NS_DEF(search) + + DateFilter::~DateFilter(){ + _CLDECDELETE( start ); + _CLDECDELETE( end ); + } + + DateFilter::DateFilter(const DateFilter& copy): + start( _CL_POINTER(copy.start) ), + end ( _CL_POINTER(copy.end) ) + { + } + + /** Constructs a filter for field f matching times between + from and to. */ + DateFilter::DateFilter(const TCHAR* f, int64_t from, int64_t to) + { + TCHAR* tmp = DateField::timeToString(from); + start = _CLNEW Term(f, tmp); + _CLDELETE_CARRAY(tmp); + + tmp = DateField::timeToString(to); + end = _CLNEW Term(start, tmp); + _CLDELETE_CARRAY(tmp); + } + + /** Constructs a filter for field f matching times before + time. */ + DateFilter* DateFilter::Before(const TCHAR* field, int64_t time) { + return _CLNEW DateFilter(field, 0,time); + } + + /** Constructs a filter for field f matching times after + time. */ + DateFilter* DateFilter::After(const TCHAR* field, int64_t time) { + return _CLNEW DateFilter(field,time, DATEFIELD_DATE_MAX ); + } + + /** Returns a BitSet with true for documents which should be permitted in + search results, and false for those that should not. */ + BitSet* DateFilter::bits(IndexReader* reader) { + BitSet* bts = _CLNEW BitSet(reader->maxDoc()); + + TermEnum* enumerator = reader->terms(start); + if (enumerator->term(false) == NULL){ + _CLDELETE(enumerator); + return bts; + } + TermDocs* termDocs = reader->termDocs(); + + try { + while (enumerator->term(false)->compareTo(end) <= 0) { + termDocs->seek(enumerator->term(false)); + while (termDocs->next()) { + bts->set(termDocs->doc()); + } + if (!enumerator->next()) { + break; + } + } + } _CLFINALLY ( + termDocs->close(); + _CLDELETE(termDocs); + enumerator->close(); + _CLDELETE(enumerator); + ); + return bts; + } + + Filter* DateFilter::clone() const{ + return _CLNEW DateFilter(*this); + } + + TCHAR* DateFilter::toString(){ + size_t len = _tcslen(start->field()) + start->textLength() + end->textLength() + 8; + TCHAR* ret = _CL_NEWARRAY(TCHAR,len); + ret[0]=0; + _sntprintf(ret,len,_T("%s: [%s-%s]"), start->field(),start->text(),end->text()); + return ret; + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/DateFilter.h b/3rdparty/clucene/src/CLucene/search/DateFilter.h new file mode 100644 index 0000000..b37272b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/DateFilter.h @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_DateFilter_ +#define _lucene_search_DateFilter_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/document/DateField.h" +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/BitSet.h" +#include "Filter.h" + +CL_NS_DEF(search) + /** + * A Filter that restricts search results to a range of time. + * + *

For this to work, documents must have been indexed with a + * {@link DateField}. + */ + class DateFilter: public Filter { + private: + CL_NS(index)::Term* start; + CL_NS(index)::Term* end; + + protected: + DateFilter(const DateFilter& copy); + public: + ~DateFilter(); + + /** Constructs a filter for field f matching times between + from and to. */ + DateFilter(const TCHAR* f, int64_t from, int64_t to); + + /** Constructs a filter for field f matching times before + time. */ + static DateFilter* Before(const TCHAR* field, int64_t time) ; + + /** Constructs a filter for field f matching times after + time. */ + static DateFilter* After(const TCHAR* field, int64_t time) ; + + /** Returns a BitSet with true for documents which should be permitted in + search results, and false for those that should not. */ + CL_NS(util)::BitSet* bits(CL_NS(index)::IndexReader* reader) ; + + Filter* clone() const; + + TCHAR* toString(); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.cpp b/3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.cpp new file mode 100644 index 0000000..1fbf2e9 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.cpp @@ -0,0 +1,85 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "ExactPhraseScorer.h" + +#include "PhraseScorer.h" +#include "CLucene/index/Terms.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + + ExactPhraseScorer::ExactPhraseScorer(Weight* weight, TermPositions** tps, + int32_t* positions, Similarity* similarity, uint8_t* norms): + PhraseScorer(weight, tps, positions, similarity, norms){ + //Func - Constructor + //Pre - tps != NULL + // tpsLength >= 0 + // n != NULL + //Post - Instance has been created + + CND_PRECONDITION(tps != NULL,"tps is NULL"); + CND_PRECONDITION(tps[0] != NULL,"tps is NULL"); + //CND_PRECONDITION(n != NULL,"n is NULL") =this is checked already in PhraseScorer + + } + + qreal ExactPhraseScorer::phraseFreq(){ + //Func - Returns the freqency of the phrase + //Pre - first != NULL + // last != NULL + // pq != NULL + // size of the PhraseQueue pq is 0 + //Post - The frequency of the phrase has been returned + + CND_PRECONDITION(first != NULL,"first is NULL"); + CND_PRECONDITION(last != NULL,"last is NULL"); + CND_PRECONDITION(pq != NULL,"pq is NULL"); + CND_PRECONDITION(pq->size()==0,"pq is not empty"); + + //build pq from list + + //Add the nodes of the list of PhrasePositions and store them + //into the PhraseQueue pq so it can used to build + //a list of sorted nodes + for (PhrasePositions* pp = first; pp != NULL; pp = pp->_next) { + //Read the first TermPosition of the current PhrasePositions pp + pp->firstPosition(); + //Store the current PhrasePositions pp into the PhraseQueue pq + pq->put(pp); + } + //pqToList requires that first and last be NULL when it's called. + //This is done at the beginning of pqToList() + //In this case, the nodes of the linked list are referenced by pq (see + //above loop), so we can clear our pointers to the head and tail of the + //linked list without fear of leaking the nodes. + + //rebuild list from pq + pqToList(); + + //Initialize freq at 0 + int32_t freq = 0; + + //find position with all terms + do { + //scan forward in first + while (first->position < last->position){ + do{ + if (!first->nextPosition()){ + return (qreal)freq; + } + } while (first->position < last->position); + //Make the current first node the last node in the list + firstToLast(); + } + //all equal: a match has been found + freq++; + } while (last->nextPosition()); + + return (qreal)freq; + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.h b/3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.h new file mode 100644 index 0000000..d82aa9e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/ExactPhraseScorer.h @@ -0,0 +1,31 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_ExactPhraseScorer_ +#define _lucene_search_ExactPhraseScorer_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "PhraseScorer.h" +#include "CLucene/index/Terms.h" + +CL_NS_DEF(search) + + class ExactPhraseScorer: public PhraseScorer { + public: + ExactPhraseScorer(Weight* weight, CL_NS(index)::TermPositions** tps, int32_t* positions, + Similarity* similarity, uint8_t* norms ); + + ~ExactPhraseScorer(){ + } + protected: + //Returns the exact freqency of the phrase + qreal phraseFreq(); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/Explanation.cpp b/3rdparty/clucene/src/CLucene/search/Explanation.cpp new file mode 100644 index 0000000..87189b7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Explanation.cpp @@ -0,0 +1,133 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Explanation.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_USE(util) +CL_NS_DEF(search) + + +Explanation::Explanation(qreal value, const TCHAR* description) { + this->value = value; + _tcsncpy(this->description,description,LUCENE_SEARCH_EXPLANATION_DESC_LEN); +} + +Explanation::Explanation() { + this->value = 0; + this->description[0]=0; +} + +Explanation::Explanation(const Explanation& copy){ + set(copy); +} +void Explanation::set(const Explanation& copy){ + this->value = copy.value; + STRCPY_TtoT(description,copy.description,LUCENE_SEARCH_EXPLANATION_DESC_LEN); + + details.clear(); + typedef CL_NS(util)::Deletor::Object Deletor; + CL_NS(util)::CLArrayList::const_iterator itr; + itr = copy.details.begin(); + while ( itr != copy.details.end() ){ + details.push_back( (*itr)->clone() ); + ++itr; + } +} + +Explanation::~Explanation(){ +} + +void Explanation::setDescription(const TCHAR* description) { + _tcsncpy(this->description,description,LUCENE_SEARCH_EXPLANATION_DESC_LEN); +} + + +Explanation* Explanation::clone() const{ + return _CLNEW Explanation(*this); +} + +qreal Explanation::getValue() const{ + return value; +} + +void Explanation::setValue(qreal value) { + this->value = value; +} + +const TCHAR* Explanation::getDescription() const { + return description; +} + +///todo: mem leaks +TCHAR* Explanation::toString(int32_t depth) { + StringBuffer buffer; + for (int32_t i = 0; i < depth; i++) { + buffer.append(_T(" ")); + } + buffer.appendFloat(getValue(),2); + buffer.append(_T(" = ")); + buffer.append(getDescription()); + buffer.append(_T("\n")); + + for ( uint32_t j=0;jtoString(depth+1); + buffer.append(tmp); + _CLDELETE_CARRAY(tmp); + } + return buffer.toString(); +} + +int Explanation::getDetailsLength(){ + return details.size(); +} +Explanation* Explanation::getDetail(int i){ + return details[i]; +} +/** The sub-nodes of this explanation node. */ +void Explanation::getDetails(Explanation** ret) { + uint32_t size = details.size(); + for ( uint32_t i=0;iclone(); + } + ret[size] = NULL; +} + +/** Adds a sub-node to this explanation node. */ +void Explanation::addDetail(Explanation* detail) { + details.push_back(detail); +} + +/** Render an explanation as text. */ +TCHAR* Explanation::toString() { + return toString(0); +} + +/** Render an explanation as HTML. */ +///todo: mem leaks +TCHAR* Explanation::toHtml() { + StringBuffer buffer; + TCHAR* tmp; + buffer.append(_T("

    \n")); + + buffer.append(_T("
  • ")); + buffer.appendFloat(getValue(),2); + buffer.append(_T(" = ")); + + buffer.append(getDescription()); + buffer.append(_T("
  • \n")); + + for ( uint32_t i=0;itoHtml(); + buffer.append(tmp); + _CLDELETE_CARRAY(tmp); + } + buffer.append(_T("
\n")); + + return buffer.toString(); +} +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/Explanation.h b/3rdparty/clucene/src/CLucene/search/Explanation.h new file mode 100644 index 0000000..7c95822 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Explanation.h @@ -0,0 +1,66 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_Explanation +#define _lucene_search_Explanation + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(search) + + #define LUCENE_SEARCH_EXPLANATION_DESC_LEN 200 + class Explanation :LUCENE_BASE { + private: + qreal value; // the value of this node + TCHAR description[LUCENE_SEARCH_EXPLANATION_DESC_LEN]; // what it represents + CL_NS(util)::CLArrayList > details; // sub-explanations + + TCHAR* toString(int32_t depth); + protected: + Explanation(const Explanation& copy); + public: + Explanation(); + ~Explanation(); + + Explanation(qreal value, const TCHAR* description); + void set(const Explanation& other); + + Explanation* clone() const; + + /** The value assigned to this explanation node. */ + qreal getValue() const; + + /** Sets the value assigned to this explanation node. */ + void setValue(qreal value); + + /** A description of this explanation node. */ + const TCHAR* getDescription() const; ///count = count; + this->order = values; + this->lookup = lookup; + } + + ~StringIndex(){ + _CLDELETE_ARRAY(order); + + for ( int i=0;ifield as integers and returns an array + * of size reader.maxDoc() of the value each document + * has in the given field. + * @param reader Used to get field values. + * @param field Which field contains the integers. + * @return The values in the given field for each document. + * @throws IOException If any error occurs. + */ + virtual FieldCacheAuto* getInts (CL_NS(index)::IndexReader* reader, const TCHAR* field) = 0; + + /** Checks the internal cache for an appropriate entry, and if + * none is found, reads the terms in field as floats and returns an array + * of size reader.maxDoc() of the value each document + * has in the given field. + * @param reader Used to get field values. + * @param field Which field contains the floats. + * @return The values in the given field for each document. + * @throws IOException If any error occurs. + */ + virtual FieldCacheAuto* getFloats (CL_NS(index)::IndexReader* reader, const TCHAR* field) = 0; + + /** Checks the internal cache for an appropriate entry, and if none + * is found, reads the term values in field and returns an array + * of size reader.maxDoc() containing the value each document + * has in the given field. + * @param reader Used to get field values. + * @param field Which field contains the strings. + * @return The values in the given field for each document. + * @throws IOException If any error occurs. + */ + virtual FieldCacheAuto* getStrings (CL_NS(index)::IndexReader* reader, const TCHAR* field) = 0; + + /** Checks the internal cache for an appropriate entry, and if none + * is found reads the term values in field and returns + * an array of them in natural order, along with an array telling + * which element in the term array each document uses. + * @param reader Used to get field values. + * @param field Which field contains the strings. + * @return Array of terms and index into the array for each document. + * @throws IOException If any error occurs. + */ + virtual FieldCacheAuto* getStringIndex (CL_NS(index)::IndexReader* reader, const TCHAR* field) = 0; + + /** Checks the internal cache for an appropriate entry, and if + * none is found reads field to see if it contains integers, floats + * or strings, and then calls one of the other methods in this class to get the + * values. For string values, a FieldCache::StringIndex is returned. After + * calling this method, there is an entry in the cache for both + * type AUTO and the actual found type. + * @param reader Used to get field values. + * @param field Which field contains the values. + * @return int32_t[], qreal[] or FieldCache::StringIndex. + * @throws IOException If any error occurs. + */ + virtual FieldCacheAuto* getAuto (CL_NS(index)::IndexReader* reader, const TCHAR* field) = 0; + + /** Checks the internal cache for an appropriate entry, and if none + * is found reads the terms out of field and calls the given SortComparator + * to get the sort values. A hit in the cache will happen if reader, + * field, and comparator are the same (using equals()) + * as a previous call to this method. + * @param reader Used to get field values. + * @param field Which field contains the values. + * @param comparator Used to convert terms into something to sort by. + * @return Array of sort objects, one for each document. + * @throws IOException If any error occurs. + */ + virtual FieldCacheAuto* getCustom (CL_NS(index)::IndexReader* reader, const TCHAR* field, SortComparator* comparator) = 0; +}; + +/** A class holding an AUTO field. In java lucene an Object + is used, but we use this. + contentType: + 1 - integer array + 2 - float array + 3 - FieldCache::StringIndex object + This class is also used when returning getInt, getFloat, etc + because we have no way of returning the size of the array and this + class can be used to determine the array size +*/ +class FieldCacheAuto:LUCENE_BASE{ +public: + enum{ + INT_ARRAY=1, + FLOAT_ARRAY=2, + STRING_INDEX=3, + STRING_ARRAY=4, + COMPARABLE_ARRAY=5, + SORT_COMPARATOR=6, + SCOREDOC_COMPARATOR=7 + }; + + FieldCacheAuto(int32_t len, int32_t type); + ~FieldCacheAuto(); + ///if contents should be deleted too, depending on type + bool ownContents; + int32_t contentLen; //number of items in the list + uint8_t contentType; + int32_t* intArray; //item 1 + qreal* floatArray; //item 2 + FieldCache::StringIndex* stringIndex; //item 3 + TCHAR** stringArray; //item 4 + CL_NS(util)::Comparable** comparableArray; //item 5 + SortComparator* sortComparator; //item 6 + ScoreDocComparator* scoreDocComparator; //item 7 + +}; + + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/search/FieldCacheImpl.cpp b/3rdparty/clucene/src/CLucene/search/FieldCacheImpl.cpp new file mode 100644 index 0000000..6205209 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldCacheImpl.cpp @@ -0,0 +1,529 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "FieldCacheImpl.h" + +CL_NS_USE(util) +CL_NS_USE(index) +CL_NS_DEF(search) + +FieldCacheImpl::FieldCacheImpl(): + cache(false,true){ +} +FieldCacheImpl::~FieldCacheImpl(){ + cache.clear(); +} + +FieldCacheImpl::FileEntry::FileEntry (const TCHAR* field, int32_t type) { + this->field = CLStringIntern::intern(field CL_FILELINE); + this->type = type; + this->custom = NULL; + this->_hashCode = 0; + } + + /** Creates one of these objects for a custom comparator. */ + FieldCacheImpl::FileEntry::FileEntry (const TCHAR* field, SortComparatorSource* custom) { + this->field = CLStringIntern::intern(field CL_FILELINE); + this->type = SortField::CUSTOM; + this->custom = custom; + this->_hashCode = 0; + } + FieldCacheImpl::FileEntry::~FileEntry(){ + CLStringIntern::unintern(field); + } + + size_t FieldCacheImpl::FileEntry::hashCode(){ + if ( _hashCode == 0 ){ + //todo: cache hashcode? + size_t ret = Misc::thashCode(field); + if ( custom != NULL ) + ret = ret ^ custom->hashCode(); + ret = ret ^ (type*7); //type with a seed + _hashCode = ret; + } + return _hashCode; + } + int32_t FieldCacheImpl::FileEntry::compareTo(const FieldCacheImpl::FileEntry* other) const{ + if ( other->field == this->field ){ + if ( other->type == this->type ){ + if ( other->custom == NULL ){ + if ( this->custom == NULL ) + return 0; //both null + else + return 1; + }else if ( this->custom == NULL ) + return -1; + else if ( other->custom < this->custom ) + return -1; + else if ( other->custom > this->custom ) + return 1; + else + return 0; + }else if ( other->type > this->type ) + return 1; + else + return -1; + + }else + return _tcscmp(other->field,this->field); + } + + /** Two of these are equal iff they reference the same field and type. */ + /*bool FieldCacheImpl::FileEntry::equals (FileEntry* other) { + if (other->field == field && other->type == type) { + if (other->custom == NULL) { + if (custom == NULL) + return true; + } else if (other->custom->equals (custom)) { + return true; + } + } + }*/ + + /** Composes a hashcode based on the field and type. */ + /*size_t FieldCacheImpl::FileEntry::hashCode() { + return field->hashCode() ^ type ^ (custom==NULL ? 0 : custom->hashCode()); + }*/ + + + + + + /** See if an object is in the cache. */ + FieldCacheAuto* FieldCacheImpl::lookup (IndexReader* reader, const TCHAR* field, int32_t type) { + FieldCacheAuto* ret = NULL; + FileEntry* entry = _CLNEW FileEntry (field, type); + { + SCOPED_LOCK_MUTEX(THIS_LOCK) + fieldcacheCacheReaderType* readerCache = cache.get(reader); + if (readerCache != NULL) + ret = readerCache->get (entry); + _CLDELETE(entry); + } + return ret; + } + + + /** See if a custom object is in the cache. */ + FieldCacheAuto* FieldCacheImpl::lookup (IndexReader* reader, const TCHAR* field, SortComparatorSource* comparer) { + FieldCacheAuto* ret = NULL; + FileEntry* entry = _CLNEW FileEntry (field, comparer); + { + SCOPED_LOCK_MUTEX(THIS_LOCK) + fieldcacheCacheReaderType* readerCache = cache.get(reader); + if (readerCache != NULL) + ret = readerCache->get (entry); + _CLDELETE(entry); +} + return ret; + } + + void FieldCacheImpl::closeCallback(CL_NS(index)::IndexReader* reader, void* fieldCacheImpl){ + FieldCacheImpl* fci = (FieldCacheImpl*)fieldCacheImpl; + SCOPED_LOCK_MUTEX(fci->THIS_LOCK) + fci->cache.remove(reader); + } + + /** Put an object into the cache. */ + void FieldCacheImpl::store (IndexReader* reader, const TCHAR* field, int32_t type, FieldCacheAuto* value) { + FileEntry* entry = _CLNEW FileEntry (field, type); + { + SCOPED_LOCK_MUTEX(THIS_LOCK) + fieldcacheCacheReaderType* readerCache = cache.get(reader); + if (readerCache == NULL) { + readerCache = _CLNEW fieldcacheCacheReaderType; + cache.put(reader,readerCache); + reader->addCloseCallback(closeCallback, this); + } + readerCache->put (entry, value); + //this is supposed to return the previous value, but it needs to be deleted!!! + } + } + + /** Put a custom object into the cache. */ + void FieldCacheImpl::store (IndexReader* reader, const TCHAR* field, SortComparatorSource* comparer, FieldCacheAuto* value) { + FileEntry* entry = _CLNEW FileEntry (field, comparer); + { + SCOPED_LOCK_MUTEX(THIS_LOCK) + fieldcacheCacheReaderType* readerCache = cache.get(reader); + if (readerCache == NULL) { + readerCache = _CLNEW fieldcacheCacheReaderType; + cache.put(reader, readerCache); + reader->addCloseCallback(FieldCacheImpl::closeCallback, this); + } + readerCache->put(entry, value); + //this is supposed to return the previous value, but it needs to be deleted!!! + } + } + + + + + + // inherit javadocs + FieldCacheAuto* FieldCacheImpl::getInts (IndexReader* reader, const TCHAR* field) { + field = CLStringIntern::intern(field CL_FILELINE); + FieldCacheAuto* ret = lookup (reader, field, SortField::INT); + if (ret == NULL) { + int32_t retLen = reader->maxDoc(); + int32_t* retArray = _CL_NEWARRAY(int32_t,retLen); + memset(retArray,0,sizeof(int32_t)*retLen); + if (retLen > 0) { + TermDocs* termDocs = reader->termDocs(); + + Term* term = _CLNEW Term (field, LUCENE_BLANK_STRING, false); + TermEnum* termEnum = reader->terms (term); + _CLDECDELETE(term); + try { + if (termEnum->term(false) == NULL) { + _CLTHROWA(CL_ERR_Runtime,"no terms in field"); //todo: add detailed error: + field); + } + do { + Term* term = termEnum->term(false); + if (term->field() != field) + break; + + TCHAR* end; + int32_t termval = (int32_t)_tcstoi64(term->text(), &end, 10); + termDocs->seek (termEnum); + while (termDocs->next()) { + retArray[termDocs->doc()] = termval; + } + } while (termEnum->next()); + } _CLFINALLY( + termDocs->close(); + _CLDELETE(termDocs); + termEnum->close(); + _CLDELETE(termEnum); + ) + } + + FieldCacheAuto* fa = _CLNEW FieldCacheAuto(retLen,FieldCacheAuto::INT_ARRAY); + fa->intArray = retArray; + + store (reader, field, SortField::INT, fa); + CLStringIntern::unintern(field); + return fa; + } + CLStringIntern::unintern(field); + return ret; + } + + // inherit javadocs + FieldCacheAuto* FieldCacheImpl::getFloats (IndexReader* reader, const TCHAR* field){ + field = CLStringIntern::intern(field CL_FILELINE); + FieldCacheAuto* ret = lookup (reader, field, SortField::FLOAT); + if (ret == NULL) { + int32_t retLen = reader->maxDoc(); + qreal* retArray = _CL_NEWARRAY(qreal,retLen); + memset(retArray,0,sizeof(qreal)*retLen); + if (retLen > 0) { + TermDocs* termDocs = reader->termDocs(); + + Term* term = _CLNEW Term (field, LUCENE_BLANK_STRING, false); + TermEnum* termEnum = reader->terms (term); + _CLDECDELETE(term); + + try { + if (termEnum->term(false) == NULL) { + _CLTHROWA(CL_ERR_Runtime,"no terms in field "); //todo: make richer error + field); + } + do { + Term* term = termEnum->term(false); + if (term->field() != field) + break; + + TCHAR* tmp; + qreal termval = _tcstod(term->text(),&tmp); + termDocs->seek (termEnum); + while (termDocs->next()) { + retArray[termDocs->doc()] = termval; + } + } while (termEnum->next()); + } _CLFINALLY( + termDocs->close(); + _CLDELETE(termDocs); + termEnum->close(); + _CLDELETE(termEnum); + ) + } + + FieldCacheAuto* fa = _CLNEW FieldCacheAuto(retLen,FieldCacheAuto::FLOAT_ARRAY); + fa->floatArray = retArray; + + store (reader, field, SortField::FLOAT, fa); + CLStringIntern::unintern(field); + return fa; + } + CLStringIntern::unintern(field); + return ret; + } + + + // inherit javadocs + FieldCacheAuto* FieldCacheImpl::getStrings (IndexReader* reader, const TCHAR* field){ + //todo: this is not really used, i think? + field = CLStringIntern::intern(field CL_FILELINE); + FieldCacheAuto* ret = lookup (reader, field, SortField::STRING); + if (ret == NULL) { + int32_t retLen = reader->maxDoc(); + TCHAR** retArray = _CL_NEWARRAY(TCHAR*,retLen+1); + memset(retArray,0,sizeof(TCHAR*)*(retLen+1)); + if (retLen > 0) { + TermDocs* termDocs = reader->termDocs(); + + Term* term = _CLNEW Term (field, LUCENE_BLANK_STRING, false); + TermEnum* termEnum = reader->terms (term); + _CLDECDELETE(term); + + try { + if (termEnum->term(false) == NULL) { + _CLTHROWA(CL_ERR_Runtime,"no terms in field "); //todo: extend to + field); + } + do { + Term* term = termEnum->term(false); + if (term->field() != field) + break; + const TCHAR* termval = term->text(); + termDocs->seek (termEnum); + while (termDocs->next()) { + retArray[termDocs->doc()] = STRDUP_TtoT(termval); //todo: any better way of doing this??? + } + } while (termEnum->next()); + } _CLFINALLY( + retArray[retLen]=NULL; + termDocs->close(); + _CLDELETE(termDocs); + termEnum->close(); + _CLDELETE(termEnum); + ) + } + + + FieldCacheAuto* fa = _CLNEW FieldCacheAuto(retLen,FieldCacheAuto::STRING_ARRAY); + fa->stringArray = retArray; + fa->ownContents=true; + store (reader, field, SortField::STRING, fa); + CLStringIntern::unintern(field); + return fa; + } + CLStringIntern::unintern(field); + return ret; + } + + // inherit javadocs + FieldCacheAuto* FieldCacheImpl::getStringIndex (IndexReader* reader, const TCHAR* field){ + field = CLStringIntern::intern(field CL_FILELINE); + FieldCacheAuto* ret = lookup (reader, field, STRING_INDEX); + int32_t t = 0; // current term number + if (ret == NULL) { + int32_t retLen = reader->maxDoc(); + int32_t* retArray = _CL_NEWARRAY(int32_t,retLen); + memset(retArray,0,sizeof(int32_t)*retLen); + + TCHAR** mterms = _CL_NEWARRAY(TCHAR*,retLen+2); + mterms[0]=NULL; + if ( retLen > 0 ) { + TermDocs* termDocs = reader->termDocs(); + + Term* term = _CLNEW Term (field, LUCENE_BLANK_STRING, false); + TermEnum* termEnum = reader->terms (term); + _CLDECDELETE(term); + + + CND_PRECONDITION(t+1 <= retLen, "t out of bounds"); + + // an entry for documents that have no terms in this field + // should a document with no terms be at top or bottom? + // this puts them at the top - if it is changed, FieldDocSortedHitQueue + // needs to change as well. + mterms[t++] = NULL; + + try { + if (termEnum->term(false) == NULL) { + _CLTHROWA(CL_ERR_Runtime,"no terms in field"); //todo: make rich message " + field); + } + do { + Term* term = termEnum->term(false); + if (term->field() != field) + break; + + // store term text + // we expect that there is at most one term per document + if (t >= retLen+1) + _CLTHROWA(CL_ERR_Runtime,"there are more terms than documents in field"); //todo: rich error \"" + field + "\""); + mterms[t] = STRDUP_TtoT(term->text()); + + termDocs->seek (termEnum); + while (termDocs->next()) { + retArray[termDocs->doc()] = t; + } + + t++; + } while (termEnum->next()); + CND_PRECONDITION(tclose(); + _CLDELETE(termDocs); + termEnum->close(); + _CLDELETE(termEnum); + ); + + if (t == 0) { + // if there are no terms, make the term array + // have a single NULL entry + _CLDELETE_ARRAY(mterms); + mterms = _CL_NEWARRAY(TCHAR*,1); //todo: delete old mterms? + mterms[0]=NULL; + } else if (t < retLen) { //todo: check, was mterms.length + // if there are less terms than documents, + // trim off the dead array space + //const TCHAR** terms = _CL_NEWARRAY(TCHAR,t); + //System.arraycopy (mterms, 0, terms, 0, t); + //mterms = terms; + + //we simply shorten the length of the array... + + } + } + FieldCache::StringIndex* value = _CLNEW FieldCache::StringIndex (retArray, mterms,t); + + FieldCacheAuto* fa = _CLNEW FieldCacheAuto(retLen,FieldCacheAuto::STRING_INDEX); + fa->stringIndex = value; + fa->ownContents=true; + store (reader, field, STRING_INDEX, fa); + CLStringIntern::unintern(field); + return fa; + } + CLStringIntern::unintern(field); + return ret; + } + + // inherit javadocs + FieldCacheAuto* FieldCacheImpl::getAuto (IndexReader* reader, const TCHAR* field) { + field = CLStringIntern::intern(field CL_FILELINE); + FieldCacheAuto* ret = lookup (reader, field, SortField::AUTO); + if (ret == NULL) { + Term* term = _CLNEW Term (field, LUCENE_BLANK_STRING, false); + TermEnum* enumerator = reader->terms (term); + _CLDECDELETE(term); + + try { + Term* term = enumerator->term(false); + if (term == NULL) { + _CLTHROWA(CL_ERR_Runtime,"no terms in field - cannot determine sort type"); //todo: make rich error: " + field + " + } + if (term->field() == field) { + const TCHAR* termtext = term->text(); + size_t termTextLen = term->textLength(); + + bool isint=true; + for ( size_t i=0;iclose(); _CLDELETE(enumerator) ); + + } + CLStringIntern::unintern(field); + return ret; + } + + + // inherit javadocs + FieldCacheAuto* FieldCacheImpl::getCustom (IndexReader* reader, const TCHAR* field, SortComparator* comparator){ + field = CLStringIntern::intern(field CL_FILELINE); + + FieldCacheAuto* ret = lookup (reader, field, comparator); + if (ret == NULL) { + int32_t retLen = reader->maxDoc(); + Comparable** retArray = _CL_NEWARRAY(Comparable*,retLen); + memset(retArray,0,sizeof(Comparable*)*retLen); + if (retLen > 0) { + TermDocs* termDocs = reader->termDocs(); + TermEnum* termEnum = reader->terms (); + + try { + if (termEnum->term(false) == NULL) { + _CLTHROWA(CL_ERR_Runtime,"no terms in field "); //todo: make rich error + field); + } + do { + Term* term = termEnum->term(false); + if (term->field() != field) + break; + Comparable* termval = comparator->getComparable (term->text()); + termDocs->seek (termEnum); + while (termDocs->next()) { + retArray[termDocs->doc()] = termval; + } + } while (termEnum->next()); + } _CLFINALLY ( + termDocs->close(); + _CLDELETE(termDocs); + termEnum->close(); + _CLDELETE(termEnum); + ); + } + + FieldCacheAuto* fa = _CLNEW FieldCacheAuto(retLen,FieldCacheAuto::COMPARABLE_ARRAY); + fa->comparableArray = retArray; + fa->ownContents=true; + store (reader, field, SortField::CUSTOM, fa); + CLStringIntern::unintern(field); + return fa; + } + CLStringIntern::unintern(field); + return ret; + } + + + FieldCacheImpl::fieldcacheCacheReaderType::fieldcacheCacheReaderType(){ + setDeleteKey(false); + setDeleteValue(false); + } + FieldCacheImpl::fieldcacheCacheReaderType::~fieldcacheCacheReaderType(){ + iterator itr = begin(); + while ( itr != end() ){ + FileEntry* f = itr->first; + if ( f->getType() != SortField::AUTO ) + _CLDELETE( itr->second ); + _CLDELETE( f ); + ++itr; + } + clear(); + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/FieldCacheImpl.h b/3rdparty/clucene/src/CLucene/search/FieldCacheImpl.h new file mode 100644 index 0000000..ac3c4ca --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldCacheImpl.h @@ -0,0 +1,144 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_FieldCacheImpl_ +#define _lucene_search_FieldCacheImpl_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/IndexReader.h" +#include "FieldCache.h" +#include "Sort.h" + + +CL_NS_DEF(search) + + +/** + * Expert: The default cache implementation, storing all values in memory. + * + */ +class FieldCacheImpl: public FieldCache { +public: + DEFINE_MUTEX(THIS_LOCK) + + /** Expert: Every key in the internal cache is of this type. */ + class FileEntry:LUCENE_BASE { + const TCHAR* field; // which Field + int32_t type; // which SortField type + SortComparatorSource* custom; // which custom comparator + size_t _hashCode; + public: + /** Creates one of these objects. */ + FileEntry (const TCHAR* field, int32_t type); + + /** Creates one of these objects for a custom comparator. */ + FileEntry (const TCHAR* field, SortComparatorSource* custom); + ~FileEntry(); + + int32_t getType() const{ return type; } + + /** Two of these are equal iff they reference the same field and type. */ + bool equals (FileEntry* other) const; + + /** Composes a hashcode based on the field and type. */ + size_t hashCode(); + + int32_t compareTo(const FileEntry* other) const; + + class Compare:LUCENE_BASE, public CL_NS(util)::Compare::_base // + { + public: + bool operator()( FileEntry* f1, FileEntry* f2 ) const{ + return ( f1->compareTo(f2) < 0 ); + } + size_t operator()( FileEntry* t ) const{ + return t->hashCode(); + } + }; + class Equals:LUCENE_BASE, public CL_NS(util)::Compare::_base // + { + public: + bool operator()( FileEntry* f1, FileEntry* f2 ) const{ + return ( f1->compareTo(f2) == 0 ); + } + }; + }; + + FieldCacheImpl(); + ~FieldCacheImpl(); +private: + + ///the type that is stored in the field cache. can't use a typedef because + ///the decorated name would become too long + class fieldcacheCacheReaderType: public CL_NS(util)::CLHashMap, + CL_NS(util)::Deletor::Object >{ + public: + fieldcacheCacheReaderType(); + ~fieldcacheCacheReaderType(); + }; + + //note: typename gets too long if using cacheReaderType as a typename + typedef CL_NS(util)::CLHashMap, + CL_NS(util)::Equals::Void, + CL_NS(util)::Deletor::Object, + CL_NS(util)::Deletor::Object > fieldcacheCacheType; + + /** The internal cache. Maps FileEntry to array of interpreted term values. **/ + //todo: make indexreader remove itself from here when the reader is shut + fieldcacheCacheType cache; + + /** See if an object is in the cache. */ + FieldCacheAuto* lookup (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type) ; + + /** See if a custom object is in the cache. */ + FieldCacheAuto* lookup (CL_NS(index)::IndexReader* reader, const TCHAR* field, SortComparatorSource* comparer); + + /** Put an object into the cache. */ + void store (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, FieldCacheAuto* value); + + /** Put a custom object into the cache. */ + void store (CL_NS(index)::IndexReader* reader, const TCHAR* field, SortComparatorSource* comparer, FieldCacheAuto* value); + +public: + + // inherit javadocs + FieldCacheAuto* getInts (CL_NS(index)::IndexReader* reader, const TCHAR* field); + + // inherit javadocs + FieldCacheAuto* getFloats (CL_NS(index)::IndexReader* reader, const TCHAR* field); + + // inherit javadocs + FieldCacheAuto* getStrings (CL_NS(index)::IndexReader* reader, const TCHAR* field); + + // inherit javadocs + FieldCacheAuto* getStringIndex (CL_NS(index)::IndexReader* reader, const TCHAR* field); + + // inherit javadocs + FieldCacheAuto* getAuto (CL_NS(index)::IndexReader* reader, const TCHAR* field); + + // inherit javadocs + FieldCacheAuto* getCustom (CL_NS(index)::IndexReader* reader, const TCHAR* field, SortComparator* comparator); + + + /** + * Callback for when IndexReader closes. This causes + * any cache to be removed for the specified reader. + */ + static void closeCallback(CL_NS(index)::IndexReader* reader, void* fieldCacheImpl); +}; + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/FieldDoc.h b/3rdparty/clucene/src/CLucene/search/FieldDoc.h new file mode 100644 index 0000000..6ce915a --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldDoc.h @@ -0,0 +1,70 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_FieldDoc_ +#define _lucene_search_FieldDoc_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "ScoreDoc.h" + +CL_NS_DEF(search) + +/** + * Expert: A ScoreDoc which also contains information about + * how to sort the referenced document. In addition to the + * document number and score, this object contains an array + * of values for the document from the field(s) used to sort. + * For example, if the sort criteria was to sort by fields + * "a", "b" then "c", the fields object array + * will have three elements, corresponding respectively to + * the term values for the document in fields "a", "b" and "c". + * The class of each element in the array will be either + * Integer, Float or String depending on the type of values + * in the terms of each field. + * + * @see ScoreDoc + * @see TopFieldDocs + */ +class FieldDoc: public ScoreDoc { +public: + + /** Expert: The values which are used to sort the referenced document. + * The order of these will match the original sort criteria given by a + * Sort object. Each Object will be either an Integer, Float or String, + * depending on the type of values in the terms of the original field. + * @see Sort + * @see Searchable#search(Query,Filter,int32_t,Sort) + */ + CL_NS(util)::Comparable** fields; + + /** Expert: Creates one of these objects with empty sort information. */ + FieldDoc (int32_t doc, qreal score): + ScoreDoc(doc,score) { + fields=NULL; + } + + /** Expert: Creates one of these objects with the given sort information. */ + FieldDoc (int32_t doc, qreal score, CL_NS(util)::Comparable** fields): + ScoreDoc(doc,score) + { + this->fields = fields; + } + + ~FieldDoc(){ + if ( fields != NULL ){ + for ( int i=0;fields[i]!=NULL;i++ ) + _CLDELETE(fields[i]); + _CLDELETE_ARRAY(fields); + } + } +}; + +CL_NS_END +#endif + diff --git a/3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.cpp b/3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.cpp new file mode 100644 index 0000000..0a52109 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.cpp @@ -0,0 +1,171 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "FieldDocSortedHitQueue.h" + + +CL_NS_USE(util) +CL_NS_DEF(search) + + +FieldDoc::FieldDoc (int32_t doc, qreal score) +{ + this->scoreDoc.doc = doc; + this->scoreDoc.score = score; + fields=NULL; +} + +FieldDoc::FieldDoc (int32_t doc, qreal score, CL_NS(util)::Comparable** fields) +{ + this->scoreDoc.doc = doc; + this->scoreDoc.score = score; + this->fields = fields; +} + +FieldDoc::~FieldDoc(){ + if ( fields != NULL ){ + for ( int i=0;fields[i]!=NULL;i++ ) + _CLDELETE(fields[i]); + _CLDELETE_ARRAY(fields); + } +} + + + +FieldDocSortedHitQueue::FieldDocSortedHitQueue (SortField** fields, int32_t size) { + this->fields = fields; + _countsize(); + //this->collators = hasCollators (fields); + initialize (size,true); +} + +bool FieldDocSortedHitQueue::lessThan (FieldDoc* docA, FieldDoc* docB) { + int32_t n = fieldsLen; + int32_t c = 0; + qreal f1,f2,r1,r2; + int32_t i1,i2; + const TCHAR *s1, *s2; + + for (int32_t i=0; igetType(); + if (fields[i]->getReverse()) { + switch (type) { + case SortField::DOCSCORE: + r1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue(); + r2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue(); + if (r1 < r2) c = -1; + if (r1 > r2) c = 1; + break; + case SortField::DOC: + case SortField::INT: + i1 = __REINTERPRET_CAST(Compare::Int32*, docA->fields[i])->getValue(); + i2 = __REINTERPRET_CAST(Compare::Int32*, docB->fields[i])->getValue(); + if (i1 > i2) c = -1; + if (i1 < i2) c = 1; + break; + case SortField::STRING: + s1 = __REINTERPRET_CAST(Compare::TChar*, docA->fields[i])->getValue(); + s2 = __REINTERPRET_CAST(Compare::TChar*, docB->fields[i])->getValue(); + if (s2 == NULL) c = -1; // could be NULL if there are + else if (s1 == NULL) c = 1; // no terms in the given field + else c = _tcscmp(s2,s1); //else if (fields[i].getLocale() == NULL) { + + /*todo: collators not impl + } else { + c = collators[i].compare (s2, s1); + }*/ + break; + case SortField::FLOAT: + f1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue(); + f2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue(); + if (f1 > f2) c = -1; + if (f1 < f2) c = 1; + break; + case SortField::CUSTOM: + c = docB->fields[i]->compareTo (docA->fields[i]); + break; + case SortField::AUTO: + // we cannot handle this - even if we determine the type of object (qreal or + // Integer), we don't necessarily know how to compare them (both SCORE and + // qreal both contain floats, but are sorted opposite of each other). Before + // we get here, each AUTO should have been replaced with its actual value. + _CLTHROWA (CL_ERR_Runtime,"FieldDocSortedHitQueue cannot use an AUTO SortField"); + default: + _CLTHROWA (CL_ERR_Runtime, "invalid SortField type"); //todo: rich error... : "+type); + } + } else { + switch (type) { + case SortField::DOCSCORE: + r1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue(); + r2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue(); + if (r1 > r2) c = -1; + if (r1 < r2) c = 1; + break; + case SortField::DOC: + case SortField::INT: + i1 = __REINTERPRET_CAST(Compare::Int32*, docA->fields[i])->getValue(); + i2 = __REINTERPRET_CAST(Compare::Int32*, docB->fields[i])->getValue(); + if (i1 < i2) c = -1; + if (i1 > i2) c = 1; + break; + case SortField::STRING: + s1 = __REINTERPRET_CAST(Compare::TChar*, docA->fields[i])->getValue(); + s2 = __REINTERPRET_CAST(Compare::TChar*, docB->fields[i])->getValue(); + // NULL values need to be sorted first, because of how FieldCache.getStringIndex() + // works - in that routine, any documents without a value in the given field are + // put first. + if (s1 == NULL) c = -1; // could be NULL if there are + else if (s2 == NULL) c = 1; // no terms in the given field + else c = _tcscmp(s1,s2); //else if (fields[i].getLocale() == NULL) { + + /* todo: collators not implemented } else { + c = collators[i].compare (s1, s2); + }*/ + break; + case SortField::FLOAT: + f1 = __REINTERPRET_CAST(Compare::Float*, docA->fields[i])->getValue(); + f2 = __REINTERPRET_CAST(Compare::Float*, docB->fields[i])->getValue(); + if (f1 < f2) c = -1; + if (f1 > f2) c = 1; + break; + case SortField::CUSTOM: + c = docA->fields[i]->compareTo (docB->fields[i]); + break; + case SortField::AUTO: + // we cannot handle this - even if we determine the type of object (qreal or + // Integer), we don't necessarily know how to compare them (both SCORE and + // qreal both contain floats, but are sorted opposite of each other). Before + // we get here, each AUTO should have been replaced with its actual value. + _CLTHROWA (CL_ERR_Runtime,"FieldDocSortedHitQueue cannot use an AUTO SortField"); + default: + _CLTHROWA (CL_ERR_Runtime,"invalid SortField type"); //todo: rich error... : "+type); + } + } + } + return c > 0; +} + +void FieldDocSortedHitQueue::setFields (SortField** fields) { + SCOPED_LOCK_MUTEX(THIS_LOCK) + if (this->fields == NULL) { + this->fields = fields; + _countsize(); + //this->collators = hasCollators (fields); + }else if ( fields == NULL ) + this->fields = NULL; +} + +FieldDocSortedHitQueue::~FieldDocSortedHitQueue(){ + if ( fields != NULL ){ + for ( int i=0;fields[i]!=NULL;i++ ) + _CLDELETE(fields[i]); + _CLDELETE_ARRAY(fields); + } +} + +CL_NS_END + diff --git a/3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.h b/3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.h new file mode 100644 index 0000000..5a46b3b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldDocSortedHitQueue.h @@ -0,0 +1,159 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_FieldDocSortedHitQueue_ +#define _lucene_search_FieldDocSortedHitQueue_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Sort.h" +#include "CLucene/util/PriorityQueue.h" + +CL_NS_DEF(search) + +/** + * Expert: A ScoreDoc which also contains information about + * how to sort the referenced document. In addition to the + * document number and score, this object contains an array + * of values for the document from the field(s) used to sort. + * For example, if the sort criteria was to sort by fields + * "a", "b" then "c", the fields object array + * will have three elements, corresponding respectively to + * the term values for the document in fields "a", "b" and "c". + * The class of each element in the array will be either + * Integer, Float or String depending on the type of values + * in the terms of each field. + * + * @see ScoreDoc + * @see TopFieldDocs + */ +class FieldDoc: LUCENE_BASE { +public: + //FieldDoc did inherit from ScoreDoc, but now we make the scoredoc a member + struct ScoreDoc scoreDoc; + + /** Expert: The values which are used to sort the referenced document. + * The order of these will match the original sort criteria given by a + * Sort object. Each Object will be either an Integer, Float or String, + * depending on the type of values in the terms of the original field. + * @see Sort + * @see Searchable#search(Query,Filter,int32_t,Sort) + */ + CL_NS(util)::Comparable** fields; + + /** Expert: Creates one of these objects with empty sort information. */ + FieldDoc (int32_t doc, qreal score); + /** Expert: Creates one of these objects with the given sort information. */ + FieldDoc (int32_t doc, qreal score, CL_NS(util)::Comparable** fields); + ~FieldDoc(); +}; + +/** + * Expert: Collects sorted results from Searchable's and collates them. + * The elements put into this queue must be of type FieldDoc. + */ +class FieldDocSortedHitQueue: + public CL_NS(util)::PriorityQueue > +{ +private: + DEFINE_MUTEX(THIS_LOCK) + + // this cannot contain AUTO fields - any AUTO fields should + // have been resolved by the time this class is used. + SortField** fields; + int32_t fieldsLen; + + void _countsize(){ + fieldsLen=0; + while(fields[fieldsLen]!=NULL) + fieldsLen++; + } + + // used in the case where the fields are sorted by locale + // based strings + //todo: not implemented in clucene because locales has not been implemented + //Collator[] collators; //volatile + +public: + /** + * Creates a hit queue sorted by the given list of fields. + * @param fields Field names, in priority order (highest priority first). + * @param size The number of hits to retain. Must be greater than zero. + */ + FieldDocSortedHitQueue (SortField** fields, int32_t size); + ~FieldDocSortedHitQueue(); + + + /** + * Allows redefinition of sort fields if they are NULL. + * This is to handle the case using ParallelMultiSearcher where the + * original list contains AUTO and we don't know the actual sort + * type until the values come back. The fields can only be set once. + * This method is thread safe. + * @param fields + */ + void setFields (SortField** fields); + + /** Returns the fields being used to sort. */ + SortField** getFields() { + return fields; + } + + /** Returns an array of collators, possibly NULL. The collators + * correspond to any SortFields which were given a specific locale. + * @param fields Array of sort fields. + * @return Array, possibly NULL. + + private Collator[] hasCollators (SortField[] fields) { + if (fields == NULL) return NULL; + Collator[] ret = new Collator[fields.length]; + for (int32_t i=0; ia is less relevant than b. + * @param a FieldDoc + * @param b FieldDoc + * @return true if document a should be sorted after document b. + */ + bool lessThan (FieldDoc* docA, FieldDoc* docB); +}; + + +/** +* Expert: Returned by low-level sorted search implementations. +* +* @see Searchable#search(Query,Filter,int32_t,Sort) +*/ +class TopFieldDocs: public TopDocs { +public: + /// The fields which were used to sort results by. + SortField** fields; + + FieldDoc** fieldDocs; + + /** Creates one of these objects. + * @param totalHits Total number of hits for the query. + * @param fieldDocs The top hits for the query. + * @param scoreDocs The top hits for the query. + * @param scoreDocsLen Length of fieldDocs and scoreDocs + * @param fields The sort criteria used to find the top hits. + */ + TopFieldDocs (int32_t totalHits, FieldDoc** fieldDocs, int32_t scoreDocsLen, SortField** fields); + ~TopFieldDocs(); +}; + +CL_NS_END +#endif + diff --git a/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp b/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp new file mode 100644 index 0000000..04f45e9 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.cpp @@ -0,0 +1,212 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "FieldSortedHitQueue.h" +#include "FieldDocSortedHitQueue.h" +#include "Compare.h" + +CL_NS_USE(util) +CL_NS_USE(index) +CL_NS_DEF(search) + +FieldSortedHitQueue::hitqueueCacheType FieldSortedHitQueue::Comparators(false,true); + +FieldSortedHitQueue::FieldSortedHitQueue (IndexReader* reader, SortField** _fields, int32_t size): + fieldsLen(0), + maxscore(1.0f) +{ + while ( _fields[fieldsLen] != 0 ) + fieldsLen++; + + comparators = _CL_NEWARRAY(ScoreDocComparator*,fieldsLen+1); + SortField** tmp = _CL_NEWARRAY(SortField*,fieldsLen+1); + for (int32_t i=0; igetField(); + //todo: fields[i].getLocale(), not implemented + comparators[i] = getCachedComparator (reader, fieldname, _fields[i]->getType(), _fields[i]->getFactory()); + tmp[i] = _CLNEW SortField (fieldname, comparators[i]->sortType(), _fields[i]->getReverse()); + } + comparatorsLen = fieldsLen; + comparators[fieldsLen]=NULL; + tmp[fieldsLen] = NULL; + this->fields = tmp; + + initialize(size,true); +} + + +bool FieldSortedHitQueue::lessThan (FieldDoc* docA, FieldDoc* docB) { + // keep track of maximum score + if (docA->scoreDoc.score > maxscore) maxscore = docA->scoreDoc.score; + if (docB->scoreDoc.score > maxscore) maxscore = docB->scoreDoc.score; + + // run comparators + int32_t c = 0; + for ( int32_t i=0; c==0 && igetReverse()) ? comparators[i]->compare (&docB->scoreDoc, &docA->scoreDoc) : + comparators[i]->compare (&docA->scoreDoc, &docB->scoreDoc); + } + // avoid random sort order that could lead to duplicates (bug #31241): + if (c == 0) + return docA->scoreDoc.doc > docB->scoreDoc.doc; + return c > 0; +} + + +//static +ScoreDocComparator* FieldSortedHitQueue::comparatorString (IndexReader* reader, const TCHAR* field) { + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getStringIndex (reader, field); + //CLStringIntern::unintern(field); + + CND_PRECONDITION(fa->contentType==FieldCacheAuto::STRING_INDEX,"Content type is incorrect"); + fa->ownContents = false; + return _CLNEW ScoreDocComparators::String(fa->stringIndex, fa->contentLen); +} + +//static +ScoreDocComparator* FieldSortedHitQueue::comparatorInt (IndexReader* reader, const TCHAR* field){ + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getInts (reader, field); + //CLStringIntern::unintern(field); + + CND_PRECONDITION(fa->contentType==FieldCacheAuto::INT_ARRAY,"Content type is incorrect"); + return _CLNEW ScoreDocComparators::Int32(fa->intArray, fa->contentLen); + } + +//static + ScoreDocComparator* FieldSortedHitQueue::comparatorFloat (IndexReader* reader, const TCHAR* field) { + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getFloats (reader, field); + //CLStringIntern::unintern(field); + + CND_PRECONDITION(fa->contentType==FieldCacheAuto::FLOAT_ARRAY,"Content type is incorrect"); + return _CLNEW ScoreDocComparators::Float (fa->floatArray, fa->contentLen); + } +//static + ScoreDocComparator* FieldSortedHitQueue::comparatorAuto (IndexReader* reader, const TCHAR* field){ + //const TCHAR* field = CLStringIntern::intern(fieldname CL_FILELINE); + FieldCacheAuto* fa = FieldCache::DEFAULT->getAuto (reader, field); + //CLStringIntern::unintern(field); + + if (fa->contentType == FieldCacheAuto::STRING_INDEX ) { + return comparatorString (reader, field); + } else if (fa->contentType == FieldCacheAuto::INT_ARRAY) { + return comparatorInt (reader, field); + } else if (fa->contentType == FieldCacheAuto::FLOAT_ARRAY) { + return comparatorFloat (reader, field); + } else if (fa->contentType == FieldCacheAuto::STRING_ARRAY) { + return comparatorString (reader, field); + } else { + _CLTHROWA(CL_ERR_Runtime, "unknown data type in field"); //todo: rich error information: '"+field+"'"); + } + } + + + //todo: Locale locale, not implemented yet + ScoreDocComparator* FieldSortedHitQueue::getCachedComparator (IndexReader* reader, const TCHAR* fieldname, int32_t type, SortComparatorSource* factory){ + if (type == SortField::DOC) + return ScoreDocComparator::INDEXORDER; + if (type == SortField::DOCSCORE) + return ScoreDocComparator::RELEVANCE; + ScoreDocComparator* comparator = lookup (reader, fieldname, type, factory); + if (comparator == NULL) { + switch (type) { + case SortField::AUTO: + comparator = comparatorAuto (reader, fieldname); + break; + case SortField::INT: + comparator = comparatorInt (reader, fieldname); + break; + case SortField::FLOAT: + comparator = comparatorFloat (reader, fieldname); + break; + case SortField::STRING: + //if (locale != NULL) + // comparator = comparatorStringLocale (reader, fieldname, locale); + //else + comparator = comparatorString (reader, fieldname); + break; + case SortField::CUSTOM: + comparator = factory->newComparator (reader, fieldname); + break; + default: + _CLTHROWA(CL_ERR_Runtime,"unknown field type"); + //todo: extend error + //throw _CLNEW RuntimeException ("unknown field type: "+type); + } + store (reader, fieldname, type, factory, comparator); + } + return comparator; + } + + + FieldDoc* FieldSortedHitQueue::fillFields (FieldDoc* doc) const{ + int32_t n = comparatorsLen; + Comparable** fields = _CL_NEWARRAY(Comparable*,n+1); + for (int32_t i=0; isortValue(&doc->scoreDoc); + fields[n]=NULL; + doc->fields = fields; + if (maxscore > 1.0f) + doc->scoreDoc.score /= maxscore; // normalize scores + return doc; + } + + ScoreDocComparator* FieldSortedHitQueue::lookup (IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory) { + ScoreDocComparator* sdc = NULL; + FieldCacheImpl::FileEntry* entry = (factory != NULL) + ? _CLNEW FieldCacheImpl::FileEntry (field, factory) + : _CLNEW FieldCacheImpl::FileEntry (field, type); + + { + SCOPED_LOCK_MUTEX(Comparators.THIS_LOCK) + hitqueueCacheReaderType* readerCache = Comparators.get(reader); + if (readerCache == NULL){ + _CLDELETE(entry); + return NULL; + } + + sdc = readerCache->get (entry); + _CLDELETE(entry); + } + return sdc; + } + + void FieldSortedHitQueue::closeCallback(CL_NS(index)::IndexReader* reader, void*){ + SCOPED_LOCK_MUTEX(Comparators.THIS_LOCK) + Comparators.remove(reader); + } + + //static + void FieldSortedHitQueue::store (IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory, ScoreDocComparator* value) { + FieldCacheImpl::FileEntry* entry = (factory != NULL) + ? _CLNEW FieldCacheImpl::FileEntry (field, factory) + : _CLNEW FieldCacheImpl::FileEntry (field, type); + + { + SCOPED_LOCK_MUTEX(Comparators.THIS_LOCK) + hitqueueCacheReaderType* readerCache = Comparators.get(reader); + if (readerCache == NULL) { + readerCache = _CLNEW hitqueueCacheReaderType(true); + Comparators.put(reader,readerCache); + reader->addCloseCallback(FieldSortedHitQueue::closeCallback,NULL); + } + readerCache->put (entry, value); + //return NULL; //supposed to return previous value... + } + } + +FieldSortedHitQueue::~FieldSortedHitQueue(){ + _CLDELETE_ARRAY(comparators); + if ( fields != NULL ){ + for ( int i=0;fields[i]!=NULL;i++ ) + _CLDELETE(fields[i]); + _CLDELETE_ARRAY(fields); + } +} +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.h b/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.h new file mode 100644 index 0000000..d7b16ce --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FieldSortedHitQueue.h @@ -0,0 +1,216 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_FieldSortedHitQueue_ +#define _lucene_search_FieldSortedHitQueue_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "FieldCache.h" +#include "Sort.h" +#include "FieldDocSortedHitQueue.h" +#include "SearchHeader.h" +#include "FieldCacheImpl.h" +#include "CLucene/util/PriorityQueue.h" + +CL_NS_DEF(search) + + +/** + * Expert: A hit queue for sorting by hits by terms in more than one field. + * Uses FieldCache.DEFAULT for maintaining internal term lookup tables. + * + * @see Searchable#search(Query,Filter,int32_t,Sort) + * @see FieldCache + */ +class FieldSortedHitQueue: public CL_NS(util)::PriorityQueue > { + + ///the type that is stored in the field cache. can't use a typedef because + ///the decorated name would become too long + class hitqueueCacheReaderType: public CL_NS(util)::CLHashMap, + CL_NS(util)::Deletor::Object >{ + + public: + hitqueueCacheReaderType(bool deleteValue){ + setDeleteKey(true); + setDeleteValue(deleteValue); + } + ~hitqueueCacheReaderType(){ + clear(); + } + + }; + +public: //todo: remove this and below after close callback is implemented + //note: typename gets too long if using cacheReaderType as a typename + typedef CL_NS(util)::CLHashMap, + CL_NS(util)::Equals::Void, + CL_NS(util)::Deletor::Object, + CL_NS(util)::Deletor::Object > hitqueueCacheType; + + /** Internal cache of comparators. Similar to FieldCache, only + * caches comparators instead of term values. + */ + static hitqueueCacheType Comparators; +private: + + /** Returns a comparator if it is in the cache.*/ + static ScoreDocComparator* lookup (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory); + + /** Stores a comparator into the cache. + returns the valid ScoreDocComparator. + */ + static void store (CL_NS(index)::IndexReader* reader, const TCHAR* field, int32_t type, SortComparatorSource* factory, ScoreDocComparator* value); + + + //todo: Locale locale, not implemented yet + static ScoreDocComparator* getCachedComparator (CL_NS(index)::IndexReader* reader, + const TCHAR* fieldname, int32_t type, SortComparatorSource* factory); + + + /** + * Returns a comparator for sorting hits according to a field containing integers. + * @param reader Index to use. + * @param fieldname Field containg integer values. + * @return Comparator for sorting hits. + * @throws IOException If an error occurs reading the index. + */ + static ScoreDocComparator* comparatorInt (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); + + /** + * Returns a comparator for sorting hits according to a field containing floats. + * @param reader Index to use. + * @param fieldname Field containg float values. + * @return Comparator for sorting hits. + * @throws IOException If an error occurs reading the index. + */ + static ScoreDocComparator* comparatorFloat (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); + + /** + * Returns a comparator for sorting hits according to a field containing strings. + * @param reader Index to use. + * @param fieldname Field containg string values. + * @return Comparator for sorting hits. + * @throws IOException If an error occurs reading the index. + */ + static ScoreDocComparator* comparatorString (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); + + + //todo: + /** + * Returns a comparator for sorting hits according to a field containing strings. + * @param reader Index to use. + * @param fieldname Field containg string values. + * @return Comparator for sorting hits. + * @throws IOException If an error occurs reading the index. + + static ScoreDocComparator* comparatorStringLocale (IndexReader* reader, TCHAR* fieldname, Locale locale){ + Collator collator = Collator.getInstance (locale); + TCHAR* field = fieldname.intern(); + TCHAR** index = FieldCache.DEFAULT.getStrings (reader, field); + return _CLNEW ScoreDocComparator() { + + public int32_t compare (ScoreDoc i, ScoreDoc j) { + return collator.compare (index[i.doc], index[j.doc]); + } + + public Comparable sortValue (ScoreDoc i) { + return index[i.doc]; + } + + public int32_t sortType() { + return SortField.STRING; + } + }; + }*/ + + /** + * Returns a comparator for sorting hits according to values in the given field. + * The terms in the field are looked at to determine whether they contain integers, + * floats or strings. Once the type is determined, one of the other static methods + * in this class is called to get the comparator. + * @param reader Index to use. + * @param fieldname Field containg values. + * @return Comparator for sorting hits. + * @throws IOException If an error occurs reading the index. + */ + static ScoreDocComparator* comparatorAuto (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); + + +protected: + /** Stores a comparator corresponding to each field being sorted by */ + ScoreDocComparator** comparators; + int32_t comparatorsLen; + + /** Stores the sort criteria being used. */ + SortField** fields; + int32_t fieldsLen; + + /** Stores the maximum score value encountered, for normalizing. + * we only care about scores greater than 1.0 - if all the scores + * are less than 1.0, we don't have to normalize. */ + qreal maxscore; + + /** + * Returns whether a is less relevant than b. + * @param a ScoreDoc + * @param b ScoreDoc + * @return true if document a should be sorted after document b. + */ + bool lessThan (FieldDoc* docA, FieldDoc* docB); +public: + + /** + * Creates a hit queue sorted by the given list of fields. + * @param reader Index to use. + * @param fields Field names, in priority order (highest priority first). Cannot be null or empty. + * @param size The number of hits to retain. Must be greater than zero. + * @throws IOException + */ + FieldSortedHitQueue (CL_NS(index)::IndexReader* reader, SortField** fields, int32_t size); + + ~FieldSortedHitQueue(); + + /** + * Callback for when IndexReader closes. This causes + * any Comparators to be removed for the specified reader. + */ + static void closeCallback(CL_NS(index)::IndexReader* reader, void* param); + + /** + * Given a FieldDoc object, stores the values used + * to sort the given document. These values are not the raw + * values out of the index, but the internal representation + * of them. This is so the given search hit can be collated + * by a MultiSearcher with other search hits. + * @param doc The FieldDoc to store sort values into. + * @return The same FieldDoc passed in. + * @see Searchable#search(Query,Filter,int32_t,Sort) + */ + FieldDoc* fillFields (FieldDoc* doc) const; + + void setFields (SortField** fields){ + this->fields = fields; + } + + /** Returns the SortFields being used by this hit queue. */ + SortField** getFields() { + return fields; + } +}; + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/Filter.h b/3rdparty/clucene/src/CLucene/search/Filter.h new file mode 100644 index 0000000..309c5a9 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Filter.h @@ -0,0 +1,46 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_Filter_ +#define _lucene_search_Filter_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/BitSet.h" + +CL_NS_DEF(search) + // Abstract base class providing a mechanism to restrict searches to a subset + // of an index. + class Filter: LUCENE_BASE { + public: + virtual ~Filter(){ + } + + virtual Filter* clone() const = 0; + + /** + * Returns a BitSet with true for documents which should be permitted in + * search results, and false for those that should not. + * MEMORY: read shouldDeleteBitSet + */ + virtual CL_NS(util)::BitSet* bits(CL_NS(index)::IndexReader* reader)=0; + + /** + * Because of the problem of cached bitsets with the CachingWrapperFilter, + * CLucene has no way of knowing whether to delete the bitset returned from bits(). + * To properly clean memory from bits(), pass the bitset to this function. The + * Filter should be deleted if this function returns true. + */ + virtual bool shouldDeleteBitSet(const CL_NS(util)::BitSet* bs) const{ return true; } + + //Creates a user-readable version of this query and returns it as as string + virtual TCHAR* toString()=0; + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/FilteredTermEnum.cpp b/3rdparty/clucene/src/CLucene/search/FilteredTermEnum.cpp new file mode 100644 index 0000000..f90ceea --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FilteredTermEnum.cpp @@ -0,0 +1,136 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" + +#include "FilteredTermEnum.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + + + FilteredTermEnum::FilteredTermEnum(){ + //Func - Constructor + //Pre - true + //Post - Instance has been created + + currentTerm = NULL; + actualEnum = NULL; + } + + FilteredTermEnum::~FilteredTermEnum() { + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + close(); + } + + int32_t FilteredTermEnum::docFreq() const { + //Func - Returns the docFreq of the current Term in the enumeration. + //Pre - next() must have been called at least once + //Post - if actualEnum is NULL result is -1 otherwise the frequencey is returned + + if (actualEnum == NULL){ + return -1; + } + return actualEnum->docFreq(); + } + + bool FilteredTermEnum::next() { + //Func - Increments the enumeration to the next element. + //Pre - true + //Post - Returns True if the enumeration has been moved to the next element otherwise false + + //The actual enumerator is not initialized! + if (actualEnum == NULL){ + return false; + } + + //Finalize the currentTerm and reset it to NULL + _CLDECDELETE( currentTerm ); + + //Iterate through the enumeration + while (currentTerm == NULL) { + if (endEnum()) + return false; + if (actualEnum->next()) { + //Order term not to return reference ownership here. */ + Term* term = actualEnum->term(false); + //Compare the retrieved term + if (termCompare(term)){ + //Matched so finalize the current + _CLDECDELETE(currentTerm); + //Get a reference to the matched term + currentTerm = _CL_POINTER(term); + return true; + } + }else + return false; + } + _CLDECDELETE(currentTerm); + currentTerm = NULL; + + return false; + } + + Term* FilteredTermEnum::term() { + //Func - Returns the current Term in the enumeration. + //Pre - next() must have been called at least once + // pointer is true or false + //Post - if pre(pointer) is true the reference counter of currentTerm is increased + // and current Term is returned otherwise currentTerm is only returned + + return _CL_POINTER(currentTerm); + } + Term* FilteredTermEnum::term(bool pointer) { + if ( pointer ) + return _CL_POINTER(currentTerm); + else + return currentTerm; + } + + void FilteredTermEnum::close(){ + //Func - Closes the enumeration to further activity, freeing resources. + //Pre - true + //Post - The Enumeration has been closed + + //Check if actualEnum is valid + if (actualEnum){ + //Close the enumeration + actualEnum->close(); + } + + //Destroy the enumeration + _CLDELETE(actualEnum); + + //Destroy currentTerm + _CLDECDELETE(currentTerm); + } + + void FilteredTermEnum::setEnum(TermEnum* actualEnum) { + //Func - Sets the actual Enumeration + //Pre - actualEnum != NULL + //Post - The instance has been created + + CND_PRECONDITION(actualEnum != NULL,"actualEnum is NULL"); + + _CLDELETE(this->actualEnum); + + this->actualEnum = actualEnum; + + // Find the first term that matches + //Ordered term not to return reference ownership here. + Term* term = actualEnum->term(false); + if (term != NULL && termCompare(term)){ + _CLDECDELETE(currentTerm); + currentTerm = _CL_POINTER(term); + }else{ + next(); + } + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/FilteredTermEnum.h b/3rdparty/clucene/src/CLucene/search/FilteredTermEnum.h new file mode 100644 index 0000000..035ae38 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FilteredTermEnum.h @@ -0,0 +1,61 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_FilteredTermEnum_ +#define _lucene_search_FilteredTermEnum_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" + +CL_NS_DEF(search) + //FilteredTermEnum is an abstract class for enumerating a subset of all terms. + // + //Term enumerations are always ordered by term->compareTo(). Each term in + //the enumeration is greater than all that precede it. + + class FilteredTermEnum: public CL_NS(index)::TermEnum { + public: + //Constructor + FilteredTermEnum(); + //Destructor + virtual ~FilteredTermEnum(); + + //Equality measure on the term + virtual qreal difference() = 0; + + //Returns the docFreq of the current Term in the enumeration. + int32_t docFreq() const ; + + //Increments the enumeration to the next element + bool next() ; + + //Returns a pointer to the current Term in the enumeration. + CL_NS(index)::Term* term(); + CL_NS(index)::Term* term(bool pointer); + + //Closes the enumeration to further activity, freeing resources. + void close(); + + protected: + //Equality compare on the term */ + virtual bool termCompare(CL_NS(index)::Term* term) = 0; + + //Indiciates the end of the enumeration has been reached + virtual bool endEnum() = 0; + + void setEnum(CL_NS(index)::TermEnum* actualEnum) ; + + private: + CL_NS(index)::Term* currentTerm; + CL_NS(index)::TermEnum* actualEnum; + + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/FuzzyQuery.cpp b/3rdparty/clucene/src/CLucene/search/FuzzyQuery.cpp new file mode 100644 index 0000000..e95d48d --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FuzzyQuery.cpp @@ -0,0 +1,357 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "FuzzyQuery.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + + /** + * Constructor for enumeration of all terms from specified reader which share a prefix of + * length prefixLength with term and which have a fuzzy similarity > + * minSimilarity. + * + * @param reader Delivers terms. + * @param term Pattern term. + * @param minSimilarity Minimum required similarity for terms from the reader. Default value is 0.5f. + * @param prefixLength Length of required common prefix. Default value is 0. + * @throws IOException + */ + FuzzyTermEnum::FuzzyTermEnum(const IndexReader* reader, Term* term, qreal minSimilarity, size_t prefixLength): + distance(0), + _endEnum(false), + prefix(LUCENE_BLANK_STRING), + prefixLength(0), + minimumSimilarity(minSimilarity) + { + //Func - Constructor + //Pre - reader contains a valid reference to an IndexReader + // term != NULL + //Post - The instance has been created + + CND_PRECONDITION(term != NULL,"term is NULL"); + + scale_factor = 1.0f / (1.0f - minimumSimilarity); + searchTerm = _CL_POINTER(term); + + text = STRDUP_TtoT(term->text()); + textLen = term->textLength(); + + + //Initialize e to NULL + e = NULL; + eWidth = 0; + eHeight = 0; + + if(prefixLength > 0 && prefixLength < textLen){ + this->prefixLength = prefixLength; + + prefix = _CL_NEWARRAY(TCHAR,prefixLength+1); + _tcsncpy(prefix,text,prefixLength); + prefix[prefixLength]='\0'; + + textLen = prefixLength; + text[textLen]='\0'; + } + + + //Set the enumeration + Term* trm = _CLNEW Term(term, prefix); + setEnum(reader->terms(trm)); + _CLDECDELETE(trm); + } + + FuzzyTermEnum::~FuzzyTermEnum(){ + //Func - Destructor + //Pre - true + //Post - FuzzyTermEnum has been destroyed + + //Close the enumeration + close(); + } + + bool FuzzyTermEnum::endEnum() { + //Func - Returns the fact if the current term in the enumeration has reached the end + //Pre - true + //Post - The boolean value of endEnum has been returned + + return _endEnum; + } + + void FuzzyTermEnum::close(){ + //Func - Close the enumeration + //Pre - true + //Post - The enumeration has been closed + + FilteredTermEnum::close(); + + //Finalize the searchTerm + _CLDECDELETE(searchTerm); + //Destroy e + _CLDELETE_ARRAY(e); + + _CLDELETE_CARRAY(text); + + if ( prefix != LUCENE_BLANK_STRING ) + _CLDELETE_CARRAY(prefix); + } + + bool FuzzyTermEnum::termCompare(Term* term) { + //Func - Compares term with the searchTerm using the Levenshtein distance. + //Pre - term is NULL or term points to a Term + //Post - if pre(term) is NULL then false is returned otherwise + // if the distance of the current term in the enumeration is bigger than the FUZZY_THRESHOLD + // then true is returned + + if (term == NULL){ + return false; //Note that endEnum is not set to true! + } + + const TCHAR* termText = term->text(); + size_t termTextLen = term->textLength(); + + //Check if the field name of searchTerm of term match + //(we can use == because fields are interned) + if ( searchTerm->field() == term->field() && + (prefixLength==0 || _tcsncmp(termText,prefix,prefixLength)==0 )) { + + const TCHAR* target = termText+prefixLength; + size_t targetLen = termTextLen-prefixLength; + + //Calculate the Levenshtein distance + int32_t dist = editDistance(text, target, textLen, targetLen); + distance = 1 - ((qreal)dist / (qreal)min(textLen, targetLen)); + return (distance > minimumSimilarity); + } + _endEnum = true; + return false; + } + + qreal FuzzyTermEnum::difference() { + //Func - Returns the difference between the distance and the fuzzy threshold + // multiplied by the scale factor + //Pre - true + //Post - The difference is returned + + return (qreal)((distance - minimumSimilarity) * scale_factor ); + } + + + /** Finds and returns the smallest of three integers + precondition: Must define int32_t __t for temporary storage and result + */ + #define min3(a, b, c) __t = (a < b) ? a : b; __t = (__t < c) ? __t : c; + + int32_t FuzzyTermEnum::editDistance(const TCHAR* s, const TCHAR* t, const int32_t n, const int32_t m) { + //Func - Calculates the Levenshtein distance also known as edit distance is a measure of similiarity + // between two strings where the distance is measured as the number of character + // deletions, insertions or substitutions required to transform one string to + // the other string. + //Pre - s != NULL and contains the source string + // t != NULL and contains the target string + // n >= 0 and contains the length of the source string + // m >= 0 and containts the length of th target string + //Post - The distance has been returned + + CND_PRECONDITION(s != NULL, "s is NULL"); + CND_PRECONDITION(t != NULL, "t is NULL"); + CND_PRECONDITION(n >= 0," n is a negative number"); + CND_PRECONDITION(n >= 0," n is a negative number"); + + int32_t i; // iterates through s + int32_t j; // iterates through t + TCHAR s_i; // ith character of s + + if (n == 0) + return m; + if (m == 0) + return n; + + //Check if the array must be reallocated because it is too small or does not exist + if (e == NULL || eWidth <= n || eHeight <= m) { + //Delete e if possible + _CLDELETE_ARRAY(e); + //resize e + eWidth = max(eWidth, n+1); + eHeight = max(eHeight, m+1); + e = _CL_NEWARRAY(int32_t,eWidth*eHeight); + } + + CND_CONDITION(e != NULL,"e is NULL"); + + // init matrix e + for (i = 0; i <= n; i++){ + e[i + (0*eWidth)] = i; + } + for (j = 0; j <= m; j++){ + e[0 + (j*eWidth)] = j; + } + + int32_t __t; //temporary variable for min3 + + // start computing edit distance + for (i = 1; i <= n; i++) { + s_i = s[i - 1]; + for (j = 1; j <= m; j++) { + if (s_i != t[j-1]){ + min3(e[i + (j*eWidth) - 1], e[i + ((j-1)*eWidth)], e[i + ((j-1)*eWidth)-1]); + e[i + (j*eWidth)] = __t+1; + }else{ + min3(e[i + (j*eWidth) -1]+1, e[i + ((j-1)*eWidth)]+1, e[i + ((j-1)*eWidth)-1]); + e[i + (j*eWidth)] = __t; + } + } + } + + // we got the result! + return e[n + ((m)*eWidth)]; + } + + + /** + * Create a new FuzzyQuery that will match terms with a similarity + * of at least minimumSimilarity to term. + * If a prefixLength > 0 is specified, a common prefix + * of that length is also required. + * + * @param term the term to search for + * @param minimumSimilarity a value between 0 and 1 to set the required similarity + * between the query term and the matching terms. For example, for a + * minimumSimilarity of 0.5 a term of the same length + * as the query term is considered similar to the query term if the edit distance + * between both terms is less than length(term)*0.5 + * @param prefixLength length of common (non-fuzzy) prefix + * @throws IllegalArgumentException if minimumSimilarity is > 1 or < 0 + * or if prefixLength < 0 or > term.text().length(). + */ + FuzzyQuery::FuzzyQuery(Term* term, qreal minimumSimilarity, size_t prefixLength): + MultiTermQuery(term) + { + //Func - Constructor + //Pre - term != NULL + //Post - The instance has been created + + CND_PRECONDITION(term != NULL,"term is NULL"); + + if (minimumSimilarity > 1.0f) + _CLTHROWA(CL_ERR_IllegalArgument,"minimumSimilarity > 1"); + else if (minimumSimilarity < 0.0f) + _CLTHROWA(CL_ERR_IllegalArgument,"minimumSimilarity < 0"); + + this->minimumSimilarity = minimumSimilarity; + + if(prefixLength >= term->textLength()) + _CLTHROWA(CL_ERR_IllegalArgument,"prefixLength >= term.textLength()"); + this->prefixLength = prefixLength; + + } + + + qreal FuzzyQuery::defaultMinSimilarity = 0.5f; + + FuzzyQuery::~FuzzyQuery(){ + //Func - Destructor + //Pre - true + //Post - Instance has been destroyed + } + + TCHAR* FuzzyQuery::toString(const TCHAR* field) const{ + //Func - Returns the query string + //Pre - field != NULL + //Post - The query string has been returned + + CND_PRECONDITION(field != NULL,"field is NULL"); + + StringBuffer buffer; + const TCHAR* b = MultiTermQuery::toString(field); + + buffer.append ( b ); + _CLDELETE_CARRAY(b); + buffer.append( _T("~") ); + + buffer.appendFloat(minimumSimilarity,1); + + return buffer.toString(); + } + + const TCHAR* FuzzyQuery::getQueryName() const{ + //Func - Returns the name of the query + //Pre - true + //post - The string FuzzyQuery has been returned + + return getClassName(); + } + const TCHAR* FuzzyQuery::getClassName(){ + //Func - Returns the name of the query + //Pre - true + //post - The string FuzzyQuery has been returned + + return _T("FuzzyQuery"); + } + + + /** + * Returns the minimum similarity that is required for this query to match. + * @return float value between 0.0 and 1.0 + */ + qreal FuzzyQuery::getMinSimilarity() const { + return minimumSimilarity; + } + + FuzzyQuery::FuzzyQuery(const FuzzyQuery& clone): + MultiTermQuery(clone) + { + this->minimumSimilarity = clone.getMinSimilarity(); + this->prefixLength = clone.getPrefixLength(); + + //if(prefixLength < 0) + // _CLTHROWA(CL_ERR_IllegalArgument,"prefixLength < 0"); + //else + if(prefixLength >= clone.getTerm()->textLength()) + _CLTHROWA(CL_ERR_IllegalArgument,"prefixLength >= term.textLength()"); + + } + + Query* FuzzyQuery::clone() const{ + return _CLNEW FuzzyQuery(*this); + } + size_t FuzzyQuery::hashCode() const{ + //todo: we should give the query a seeding value... but + //need to do it for all hascode functions + size_t val = Similarity::floatToByte(getBoost()) ^ getTerm()->hashCode(); + val ^= Similarity::floatToByte(this->getMinSimilarity()); + val ^= this->getPrefixLength(); + return val; + } + bool FuzzyQuery::equals(Query* other) const{ + if (!(other->instanceOf(FuzzyQuery::getClassName()))) + return false; + + FuzzyQuery* fq = (FuzzyQuery*)other; + return (this->getBoost() == fq->getBoost()) + && this->getMinSimilarity() == fq->getMinSimilarity() + && this->getPrefixLength() == fq->getPrefixLength() + && getTerm()->equals(fq->getTerm()); + } + + /** + * Returns the prefix length, i.e. the number of characters at the start + * of a term that must be identical (not fuzzy) to the query term if the query + * is to match that term. + */ + size_t FuzzyQuery::getPrefixLength() const { + return prefixLength; + } + + FilteredTermEnum* FuzzyQuery::getEnum(IndexReader* reader){ + Term* term = getTerm(false); + FuzzyTermEnum* ret = _CLNEW FuzzyTermEnum(reader, term, minimumSimilarity, prefixLength); + return ret; + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/FuzzyQuery.h b/3rdparty/clucene/src/CLucene/search/FuzzyQuery.h new file mode 100644 index 0000000..e58637b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/FuzzyQuery.h @@ -0,0 +1,156 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_FuzzyQuery_ +#define _lucene_search_FuzzyQuery_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/Term.h" +#include "MultiTermQuery.h" + + +CL_NS_DEF(search) + + // class FuzzyQuery implements the fuzzy search query + class FuzzyQuery: public MultiTermQuery { + private: + qreal minimumSimilarity; + size_t prefixLength; + protected: + FuzzyQuery(const FuzzyQuery& clone); + public: + static qreal defaultMinSimilarity; + + /** + * Create a new FuzzyQuery that will match terms with a similarity + * of at least minimumSimilarity to term. + * If a prefixLength > 0 is specified, a common prefix + * of that length is also required. + * + * @param term the term to search for + * @param minimumSimilarity a value between 0 and 1 to set the required similarity + * between the query term and the matching terms. For example, for a + * minimumSimilarity of 0.5 a term of the same length + * as the query term is considered similar to the query term if the edit distance + * between both terms is less than length(term)*0.5 + * @param prefixLength length of common (non-fuzzy) prefix + * @throws IllegalArgumentException if minimumSimilarity is > 1 or < 0 + * or if prefixLength < 0 or > term.text().length(). + */ + FuzzyQuery(CL_NS(index)::Term* term, qreal minimumSimilarity=defaultMinSimilarity, size_t prefixLength=0); + //Destructor + ~FuzzyQuery(); + + TCHAR* toString(const TCHAR* field) const; + + //Returns the name "FuzzyQuery" + static const TCHAR* getClassName(); + const TCHAR* getQueryName() const; + + Query* clone() const; + bool equals(Query * other) const; + size_t hashCode() const; + + /** + * Returns the minimum similarity that is required for this query to match. + * @return float value between 0.0 and 1.0 + */ + qreal getMinSimilarity() const; + + /** + * Returns the prefix length, i.e. the number of characters at the start + * of a term that must be identical (not fuzzy) to the query term if the query + * is to match that term. + */ + size_t getPrefixLength() const; + + protected: + FilteredTermEnum* getEnum(CL_NS(index)::IndexReader* reader); + }; + + /** FuzzyTermEnum is a subclass of FilteredTermEnum for enumerating all + * terms that are similiar to the specified filter term. + * + * Term enumerations are always ordered by Term.compareTo(). Each term in + * the enumeration is greater than all that precede it. + */ + class FuzzyTermEnum: public FilteredTermEnum { + private: + qreal distance; + bool _endEnum; + + CL_NS(index)::Term* searchTerm; + TCHAR* text; + size_t textLen; + TCHAR* prefix; + size_t prefixLength; + qreal minimumSimilarity; + double scale_factor; + + + /** + * This static array saves us from the time required to create a new array + * everytime editDistance is called. + */ + int32_t* e; + int32_t eWidth; + int32_t eHeight; + + /****************************** + * Compute Levenshtein distance + ******************************/ + + /** + Levenshtein distance also known as edit distance is a measure of similiarity + between two strings where the distance is measured as the number of character + deletions, insertions or substitutions required to transform one string to + the other string. +

This method takes in four parameters; two strings and their respective + lengths to compute the Levenshtein distance between the two strings. + The result is returned as an integer. + */ + int32_t editDistance(const TCHAR* s, const TCHAR* t, const int32_t n, const int32_t m) ; + + protected: + /** + The termCompare method in FuzzyTermEnum uses Levenshtein distance to + calculate the distance between the given term and the comparing term. + */ + bool termCompare(CL_NS(index)::Term* term) ; + + ///Returns the fact if the current term in the enumeration has reached the end + bool endEnum(); + public: + + /** + * Empty prefix and minSimilarity of 0.5f are used. + * + * @param reader + * @param term + * @throws IOException + * @see #FuzzyTermEnum(IndexReader, Term, qreal, int32_t) + */ + FuzzyTermEnum(const CL_NS(index)::IndexReader* reader, CL_NS(index)::Term* term, qreal minSimilarity=FuzzyQuery::defaultMinSimilarity, size_t prefixLength=0); + /** Destructor */ + ~FuzzyTermEnum(); + /** Close the enumeration */ + void close(); + + /** Returns the difference between the distance and the fuzzy threshold + * multiplied by the scale factor + */ + qreal difference(); + + + const char* getObjectName(){ return FuzzyTermEnum::getClassName(); } + static const char* getClassName(){ return "FuzzyTermEnum"; } + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/HitQueue.cpp b/3rdparty/clucene/src/CLucene/search/HitQueue.cpp new file mode 100644 index 0000000..c9aecc6 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/HitQueue.cpp @@ -0,0 +1,107 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "HitQueue.h" + +CL_NS_DEF(search) + +void HitQueue::upHeap(){ + size_t i = _size; + ScoreDoc node = heap[i]; // save bottom node (WAS object) + int32_t j = ((uint32_t)i) >> 1; + while (j > 0 && lessThan(node,heap[j])) { + heap[i] = heap[j]; // shift parents down + i = j; + j = ((uint32_t)j) >> 1; + } + heap[i] = node; // install saved node +} +void HitQueue::downHeap(){ + size_t i = 1; + ScoreDoc node = heap[i]; // save top node + size_t j = i << 1; // find smaller child + size_t k = j + 1; + if (k <= _size && lessThan(heap[k], heap[j])) { + j = k; + } + while (j <= _size && lessThan(heap[j],node)) { + heap[i] = heap[j]; // shift up child + i = j; + j = i << 1; + k = j + 1; + if (k <= _size && lessThan(heap[k], heap[j])) { + j = k; + } + } + heap[i] = node; // install saved node +} + +void HitQueue::adjustTop(){ + downHeap(); +} +size_t HitQueue::size(){ + return _size; +} + +struct ScoreDoc& HitQueue::top(){ + if ( _size == 0 ) + _CLTHROWA(CL_ERR_IndexOutOfBounds, "Attempted to access empty hitqueue::top"); + return heap[1]; +} + +void HitQueue::put(struct ScoreDoc& element){ + if ( _size>=maxSize ) + _CLTHROWA(CL_ERR_IndexOutOfBounds,"add is out of bounds"); + + _size++; + heap[_size] = element; + upHeap(); +} + +ScoreDoc HitQueue::pop(){ + if (_size > 0) { + ScoreDoc result = heap[1]; // save first value + heap[1] = heap[_size]; // move last to first + + _size--; + downHeap(); // adjust heap + return result; + } else + _CLTHROWA(CL_ERR_IndexOutOfBounds, "Attempted to access empty hitqueue::top"); +} + +bool HitQueue::insert(struct ScoreDoc& element){ + if(_size < maxSize){ + put(element); + return true; + }else if(_size > 0 && !lessThan(element, heap[1])){ + heap[1] = element; + adjustTop(); + return true; + }else + return false; +} + +HitQueue::HitQueue(const int32_t maxSize){ + _size = 0; + this->maxSize = maxSize; + int32_t heapSize = maxSize + 1; + heap = _CL_NEWARRAY(ScoreDoc,heapSize); +} +HitQueue::~HitQueue(){ + _CLDELETE_ARRAY(heap); +} + +bool HitQueue::lessThan(struct ScoreDoc& hitA, struct ScoreDoc& hitB){ + if (hitA.score == hitB.score) + return hitA.doc > hitB.doc; + else + return hitA.score < hitB.score; +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/HitQueue.h b/3rdparty/clucene/src/CLucene/search/HitQueue.h new file mode 100644 index 0000000..0bd196a --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/HitQueue.h @@ -0,0 +1,55 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_HitQueue_ +#define _lucene_search_HitQueue_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "SearchHeader.h" + +CL_NS_DEF(search) + +/** +* An optimised PriorityQueue which takes ScoreDoc structs. Some by-ref passing +* and memory related optimisations have been done. +*/ +class HitQueue: LUCENE_BASE { +private: + ScoreDoc* heap; + size_t _size; + size_t maxSize; + + void upHeap(); + void downHeap(); + +protected: + bool lessThan(struct ScoreDoc& hitA, struct ScoreDoc& hitB); + +public: + void adjustTop(); + struct ScoreDoc& top(); + void put(struct ScoreDoc& element); + ScoreDoc pop(); + /** + * Adds element to the PriorityQueue in log(size) time if either + * the PriorityQueue is not full, or not lessThan(element, top()). + * @param element + * @return true if element is added, false otherwise. + */ + bool insert(struct ScoreDoc& element); + /** + * Returns the number of elements currently stored in the PriorityQueue. + */ + size_t size(); + HitQueue(const int32_t maxSize); + ~HitQueue(); + +}; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/Hits.cpp b/3rdparty/clucene/src/CLucene/search/Hits.cpp new file mode 100644 index 0000000..38c489f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Hits.cpp @@ -0,0 +1,174 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" + +#include "SearchHeader.h" +#include "CLucene/document/Document.h" +#include "CLucene/index/IndexReader.h" +#include "Filter.h" +#include "CLucene/search/SearchHeader.h" + +CL_NS_USE(document) +CL_NS_USE(util) +CL_NS_USE(index) + +CL_NS_DEF(search) + + HitDoc::HitDoc(const qreal s, const int32_t i) + { + //Func - Constructor + //Pre - true + //Post - The instance has been created + + next = NULL; + prev = NULL; + doc = NULL; + score = s; + id = i; + } + + HitDoc::~HitDoc(){ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + _CLDELETE(doc); + } + + + Hits::Hits(Searcher* s, Query* q, Filter* f, const Sort* _sort): + query(q), searcher(s), filter(f), sort(_sort) + { + //Func - Constructor + //Pre - s contains a valid reference to a searcher s + // q contains a valid reference to a Query + // f is NULL or contains a pointer to a filter + //Post - The instance has been created + + _length = 0; + first = NULL; + last = NULL; + numDocs = 0; + maxDocs = 200; + + //retrieve 100 initially + getMoreDocs(50); + } + + Hits::~Hits(){ + + } + int32_t Hits::length() const { + return _length; + } + + Document& Hits::doc(const int32_t n){ + HitDoc* hitDoc = getHitDoc(n); + + // Update LRU cache of documents + remove(hitDoc); // remove from list, if there + addToFront(hitDoc); // add to front of list + if (numDocs > maxDocs) { // if cache is full + HitDoc* oldLast = last; + remove(last); // flush last + + _CLDELETE( oldLast->doc ); + oldLast->doc = NULL; + } + + if (hitDoc->doc == NULL){ + hitDoc->doc = _CLNEW Document; + searcher->doc(hitDoc->id, hitDoc->doc); // cache miss: read document + } + + return *hitDoc->doc; + } + + int32_t Hits::id (const int32_t n){ + return getHitDoc(n)->id; + } + + qreal Hits::score(const int32_t n){ + return getHitDoc(n)->score; + } + + void Hits::getMoreDocs(const size_t m){ + size_t _min = m; + { + size_t nHits = hitDocs.size(); + if ( nHits > _min) + _min = nHits; + } + + size_t n = _min * 2; // double # retrieved + TopDocs* topDocs = NULL; + if ( sort==NULL ) + topDocs = (TopDocs*)((Searchable*)searcher)->_search(query, filter, n); + else + topDocs = (TopDocs*)((Searchable*)searcher)->_search(query, filter, n, sort); + _length = topDocs->totalHits; + ScoreDoc* scoreDocs = topDocs->scoreDocs; + int32_t scoreDocsLength = topDocs->scoreDocsLength; + + qreal scoreNorm = 1.0f; + //Check that scoreDocs is a valid pointer before using it + if (scoreDocs != NULL){ + if (_length > 0 && scoreDocs[0].score > 1.0f){ + scoreNorm = 1.0f / scoreDocs[0].score; + } + + int32_t end = scoreDocsLength < _length ? scoreDocsLength : _length; + for (int32_t i = hitDocs.size(); i < end; i++) { + hitDocs.push_back(_CLNEW HitDoc(scoreDocs[i].score*scoreNorm, scoreDocs[i].doc)); + } + } + + _CLDELETE(topDocs); + } + + HitDoc* Hits::getHitDoc(const size_t n){ + if (n >= _length){ + TCHAR buf[100]; + _sntprintf(buf, 100,_T("Not a valid hit number: %d"),n); + _CLTHROWT(CL_ERR_IndexOutOfBounds, buf ); + } + if (n >= hitDocs.size()) + getMoreDocs(n); + + return hitDocs[n]; + } + + void Hits::addToFront(HitDoc* hitDoc) { // insert at front of cache + if (first == NULL) + last = hitDoc; + else + first->prev = hitDoc; + + hitDoc->next = first; + first = hitDoc; + hitDoc->prev = NULL; + + numDocs++; + } + + void Hits::remove(const HitDoc* hitDoc) { // remove from cache + if (hitDoc->doc == NULL) // it's not in the list + return; // abort + + if (hitDoc->next == NULL) + last = hitDoc->prev; + else + hitDoc->next->prev = hitDoc->prev; + + if (hitDoc->prev == NULL) + first = hitDoc->next; + else + hitDoc->prev->next = hitDoc->next; + + numDocs--; + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/IndexSearcher.cpp b/3rdparty/clucene/src/CLucene/search/IndexSearcher.cpp new file mode 100644 index 0000000..c948cfa --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/IndexSearcher.cpp @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "IndexSearcher.h" + +#include "SearchHeader.h" +#include "Scorer.h" +#include "FieldDocSortedHitQueue.h" +#include "CLucene/store/Directory.h" +#include "CLucene/document/Document.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/Term.h" +#include "CLucene/util/BitSet.h" +#include "FieldSortedHitQueue.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_USE(document) + +CL_NS_DEF(search) + +class SimpleTopDocsCollector : public HitCollector +{ +private: + qreal minScore; + const CL_NS(util)::BitSet* bits; + HitQueue* hq; + size_t nDocs; + int32_t* totalHits; + +public: + SimpleTopDocsCollector(const CL_NS(util)::BitSet* bs, HitQueue* hitQueue, + int32_t* totalhits, size_t ndocs, const qreal ms=-1.0f) + : minScore(ms), + bits(bs), + hq(hitQueue), + nDocs(ndocs), + totalHits(totalhits) {} + ~SimpleTopDocsCollector() {} + + void collect(const int32_t doc, const qreal score) + { + if (score > 0.0f // ignore zeroed buckets + && (bits == NULL || bits->get(doc))) { // skip docs not in bits + ++totalHits[0]; + if (hq->size() < nDocs || (minScore==-1.0f || score >= minScore)) { + ScoreDoc sd = {doc, score}; + hq->insert(sd); // update hit queue + if ( minScore != -1.0f ) + minScore = hq->top().score; // maintain minScore + } + } + } +}; + +class SortedTopDocsCollector : public HitCollector +{ +private: + const CL_NS(util)::BitSet* bits; + FieldSortedHitQueue* hq; + size_t nDocs; + int32_t* totalHits; +public: + SortedTopDocsCollector(const CL_NS(util)::BitSet* bs, + FieldSortedHitQueue* hitQueue, int32_t* totalhits, size_t _nDocs) + : bits(bs), + hq(hitQueue), + nDocs(_nDocs), + totalHits(totalhits) + { + } + ~SortedTopDocsCollector() {} + + void collect(const int32_t doc, const qreal score) + { + if (score > 0.0f && // ignore zeroed buckets + (bits==NULL || bits->get(doc))) { // skip docs not in bits + ++totalHits[0]; + // TODO: see jlucene way... with fields def??? + FieldDoc* fd = _CLNEW FieldDoc(doc, score); + if ( !hq->insert(fd) ) // update hit queue + _CLDELETE(fd); + } + } +}; + +class SimpleFilteredCollector : public HitCollector +{ +private: + CL_NS(util)::BitSet* bits; + HitCollector* results; +public: + SimpleFilteredCollector(CL_NS(util)::BitSet* bs, HitCollector* collector) + : bits(bs), + results(collector) {} + ~SimpleFilteredCollector() {} + +protected: + void collect(const int32_t doc, const qreal score) + { + // skip docs not in bits + if (bits->get(doc)) + results->collect(doc, score); + } +}; + + +IndexSearcher::IndexSearcher(const QString& path) +{ + //Func - Constructor + // Creates a searcher searching the index in the named directory. + //Pre - path != NULL + //Post - The instance has been created + + CND_PRECONDITION(!path.isEmpty(), "path is NULL"); + + reader = IndexReader::open(path); + readerOwner = true; +} + +IndexSearcher::IndexSearcher(CL_NS(store)::Directory* directory) +{ + //Func - Constructor + // Creates a searcher searching the index in the specified directory. + //Pre - path != NULL + //Post - The instance has been created + + CND_PRECONDITION(directory != NULL, "directory is NULL"); + + reader = IndexReader::open(directory); + readerOwner = true; +} + +IndexSearcher::IndexSearcher(IndexReader* r) +{ + //Func - Constructor + // Creates a searcher searching the index with the provide IndexReader + //Pre - path != NULL + //Post - The instance has been created + + reader = r; + readerOwner = false; +} + +IndexSearcher::~IndexSearcher() +{ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + close(); +} + +void IndexSearcher::close() +{ + //Func - Frees resources associated with this Searcher. + //Pre - true + //Post - The resources associated have been freed + if (readerOwner && reader){ + reader->close(); + _CLDELETE(reader); + } +} + +// inherit javadoc +int32_t IndexSearcher::docFreq(const Term* term) const +{ + //Func - + //Pre - reader != NULL + //Post - + + CND_PRECONDITION(reader != NULL, "reader is NULL"); + return reader->docFreq(term); +} + +// inherit javadoc +bool IndexSearcher::doc(int32_t i, CL_NS(document)::Document* d) +{ + //Func - Retrieves i-th document found + // For use by HitCollector implementations. + //Pre - reader != NULL + //Post - The i-th document has been returned + + CND_PRECONDITION(reader != NULL, "reader is NULL"); + return reader->document(i,d); +} + +// inherit javadoc +int32_t IndexSearcher::maxDoc() const +{ + //Func - Return total number of documents including the ones marked deleted + //Pre - reader != NULL + //Post - The total number of documents including the ones marked deleted + // has been returned + + CND_PRECONDITION(reader != NULL, "reader is NULL"); + return reader->maxDoc(); +} + +TopDocs* IndexSearcher::_search(Query* query, Filter* filter, const int32_t nDocs) +{ + //Func - + //Pre - reader != NULL + //Post - + + CND_PRECONDITION(reader != NULL, "reader is NULL"); + CND_PRECONDITION(query != NULL, "query is NULL"); + + Weight* weight = query->weight(this); + Scorer* scorer = weight->scorer(reader); + if (scorer == NULL){ + return _CLNEW TopDocs(0, NULL, 0); + } + + BitSet* bits = filter != NULL ? filter->bits(reader) : NULL; + HitQueue* hq = _CLNEW HitQueue(nDocs); + + //Check hq has been allocated properly + CND_CONDITION(hq != NULL, "Could not allocate memory for HitQueue hq"); + + int32_t* totalHits = _CL_NEWARRAY(int32_t,1); + totalHits[0] = 0; + + SimpleTopDocsCollector hitCol(bits,hq,totalHits,nDocs,0.0f); + scorer->score( &hitCol ); + _CLDELETE(scorer); + + int32_t scoreDocsLength = hq->size(); + + ScoreDoc* scoreDocs = _CL_NEWARRAY(ScoreDoc,scoreDocsLength); + + for (int32_t i = scoreDocsLength-1; i >= 0; --i) // put docs in array + scoreDocs[i] = hq->pop(); + + int32_t totalHitsInt = totalHits[0]; + + _CLDELETE(hq); + if ( bits != NULL && filter->shouldDeleteBitSet(bits) ) + _CLDELETE(bits); + _CLDELETE_ARRAY(totalHits); + Query* wq = weight->getQuery(); + if ( query != wq ) //query was re-written + _CLLDELETE(wq); + _CLDELETE(weight); + + return _CLNEW TopDocs(totalHitsInt, scoreDocs, scoreDocsLength); +} + +// inherit javadoc +TopFieldDocs* IndexSearcher::_search(Query* query, Filter* filter, + const int32_t nDocs, const Sort* sort) +{ + CND_PRECONDITION(reader != NULL, "reader is NULL"); + CND_PRECONDITION(query != NULL, "query is NULL"); + + Weight* weight = query->weight(this); + Scorer* scorer = weight->scorer(reader); + if (scorer == NULL) { + return _CLNEW TopFieldDocs(0, NULL, 0, NULL ); + } + + BitSet* bits = filter != NULL ? filter->bits(reader) : NULL; + FieldSortedHitQueue hq(reader, sort->getSort(), nDocs); + int32_t* totalHits = _CL_NEWARRAY(int32_t,1); + totalHits[0]=0; + + SortedTopDocsCollector hitCol(bits,&hq,totalHits,nDocs); + scorer->score(&hitCol); + _CLDELETE(scorer); + + int32_t hqLen = hq.size(); + FieldDoc** fieldDocs = _CL_NEWARRAY(FieldDoc*,hqLen); + for (int32_t i = hqLen-1; i >= 0; --i){ // put docs in array + fieldDocs[i] = hq.fillFields (hq.pop()); + } + + Query* wq = weight->getQuery(); + if ( query != wq ) //query was re-written + _CLLDELETE(wq); + _CLDELETE(weight); + + SortField** hqFields = hq.getFields(); + hq.setFields(NULL); //move ownership of memory over to TopFieldDocs + int32_t totalHits0 = totalHits[0]; + if ( bits != NULL && filter->shouldDeleteBitSet(bits) ) + _CLDELETE(bits); + _CLDELETE_ARRAY(totalHits); + return _CLNEW TopFieldDocs(totalHits0, fieldDocs, hqLen, hqFields ); +} + +void IndexSearcher::_search(Query* query, Filter* filter, HitCollector* results) +{ + //Func - _search an index and fetch the results + // Applications should only use this if they need all of the + // matching documents. The high-level search API (search(Query)) + // is usually more efficient, as it skips non-high-scoring hits. + //Pre - query is a valid reference to a query filter may or may not be NULL + // results is a valid reference to a HitCollector and used to store the results + //Post - filter if non-NULL, a bitset used to eliminate some documents + + CND_PRECONDITION(reader != NULL, "reader is NULL"); + CND_PRECONDITION(query != NULL, "query is NULL"); + + BitSet* bits = NULL; + SimpleFilteredCollector* fc = NULL; + + if (filter != NULL){ + bits = filter->bits(reader); + fc = _CLNEW SimpleFilteredCollector(bits, results); + } + + Weight* weight = query->weight(this); + Scorer* scorer = weight->scorer(reader); + if (scorer != NULL) { + if (fc == NULL){ + scorer->score(results); + }else{ + scorer->score((HitCollector*)fc); + } + _CLDELETE(scorer); + } + + _CLDELETE(fc); + _CLDELETE(weight); + if ( bits != NULL && filter->shouldDeleteBitSet(bits) ) + _CLDELETE(bits); +} + +Query* IndexSearcher::rewrite(Query* original) +{ + Query* query = original; + Query* last = original; + for (Query* rewrittenQuery = query->rewrite(reader); + rewrittenQuery != query; + rewrittenQuery = query->rewrite(reader)) { + query = rewrittenQuery; + if ( query != last && last != original) { + _CLDELETE(last); + } + last = query; + } + return query; +} + +void IndexSearcher::explain(Query* query, int32_t doc, Explanation* ret) +{ + Weight* weight = query->weight(this); + weight->explain(reader, doc, ret); + + Query* wq = weight->getQuery(); + if ( query != wq ) //query was re-written + _CLLDELETE(wq); + _CLDELETE(weight); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/IndexSearcher.h b/3rdparty/clucene/src/CLucene/search/IndexSearcher.h new file mode 100644 index 0000000..307e026 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/IndexSearcher.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_search_IndexSearcher_ +#define _lucene_search_IndexSearcher_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "SearchHeader.h" +#include "CLucene/store/Directory.h" +#include "CLucene/document/Document.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/Term.h" +#include "CLucene/util/BitSet.h" +#include "HitQueue.h" +#include "FieldSortedHitQueue.h" + +CL_NS_DEF(search) +/** Implements search over a single IndexReader. +* +*

Applications usually need only call the inherited {@link search(Query*)} +* or {@link search(Query*,Filter*)} methods. +*/ +class IndexSearcher:public Searcher{ + CL_NS(index)::IndexReader* reader; + bool readerOwner; + +public: + /// Creates a searcher searching the index in the named directory. + IndexSearcher(const QString& path); + + /// Creates a searcher searching the index in the specified directory. + IndexSearcher(CL_NS(store)::Directory* directory); + + /// Creates a searcher searching the provided index. + IndexSearcher(CL_NS(index)::IndexReader* r); + + ~IndexSearcher(); + + /// Frees resources associated with this Searcher. + void close(); + + int32_t docFreq(const CL_NS(index)::Term* term) const; + + bool doc(int32_t i, CL_NS(document)::Document* document); + + int32_t maxDoc() const; + + TopDocs* _search(Query* query, Filter* filter, const int32_t nDocs); + TopFieldDocs* _search(Query* query, Filter* filter, const int32_t nDocs, + const Sort* sort); + + void _search(Query* query, Filter* filter, HitCollector* results); + + CL_NS(index)::IndexReader* getReader() { + return reader; } + + Query* rewrite(Query* original); + void explain(Query* query, int32_t doc, Explanation* ret); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/search/MultiSearcher.cpp b/3rdparty/clucene/src/CLucene/search/MultiSearcher.cpp new file mode 100644 index 0000000..bed7f0d --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/MultiSearcher.cpp @@ -0,0 +1,227 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "MultiSearcher.h" + +#include "SearchHeader.h" +#include "HitQueue.h" +#include "CLucene/document/Document.h" +#include "CLucene/index/Term.h" +#include "FieldDocSortedHitQueue.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_USE(document) + +CL_NS_DEF(search) + + /** Creates a searcher which searches searchers. */ + MultiSearcher::MultiSearcher(Searchable** _searchables): + _maxDoc(0) { + searchablesLen = 0; + while ( _searchables[searchablesLen] != NULL ) + ++searchablesLen; + + searchables=_CL_NEWARRAY(Searchable*,searchablesLen+1); + starts = _CL_NEWARRAY(int32_t,searchablesLen + 1); // build starts array + for (int32_t i = 0; i < searchablesLen; ++i) { + searchables[i]=_searchables[i]; + starts[i] = _maxDoc; + _maxDoc += searchables[i]->maxDoc(); // compute maxDocs + } + starts[searchablesLen] = _maxDoc; + } + + MultiSearcher::~MultiSearcher() { + _CLDELETE_ARRAY(searchables); + _CLDELETE_ARRAY(starts); + } + + + // inherit javadoc + void MultiSearcher::close() { + for (int32_t i = 0; i < searchablesLen; ++i){ + searchables[i]->close(); + searchables[i]=NULL; + } + } + + int32_t MultiSearcher::docFreq(const Term* term) const { + int32_t docFreq = 0; + for (int32_t i = 0; i < searchablesLen; ++i) + docFreq += searchables[i]->docFreq(term); + return docFreq; + } + + /** For use by {@link HitCollector} implementations. */ + bool MultiSearcher::doc(int32_t n, Document* d) { + int32_t i = subSearcher(n); // find searcher index + return searchables[i]->doc(n - starts[i], d); // dispatch to searcher + } + + int32_t MultiSearcher::searcherIndex(int32_t n) const{ + return subSearcher(n); + } + + /** Returns index of the searcher for document n in the array + * used to construct this searcher. */ + int32_t MultiSearcher::subSearcher(int32_t n) const{ + // replace w/ call to Arrays.binarySearch in Java 1.2 + int32_t lo = 0; // search starts array + int32_t hi = searchablesLen - 1; // for first element less + // than n, return its index + int32_t mid,midValue; + while (hi >= lo) { + mid = (lo + hi) >> 1; + midValue = starts[mid]; + if (n < midValue) + hi = mid - 1; + else if (n > midValue) + lo = mid + 1; + else{ // found a match + while (mid+1 < searchablesLen && starts[mid+1] == midValue) { + ++mid; // scan to last match + } + return mid; + } + } + return hi; + } + + /** Returns the document number of document n within its + * sub-index. */ + int32_t MultiSearcher::subDoc(int32_t n) const{ + return n - starts[subSearcher(n)]; + } + + int32_t MultiSearcher::maxDoc() const{ + return _maxDoc; + } + + TopDocs* MultiSearcher::_search(Query* query, Filter* filter, const int32_t nDocs) { + HitQueue* hq = _CLNEW HitQueue(nDocs); + int32_t totalHits = 0; + TopDocs* docs; + int32_t j; + ScoreDoc* scoreDocs; + for (int32_t i = 0; i < searchablesLen; i++) { // search each searcher + docs = searchables[i]->_search(query, filter, nDocs); + totalHits += docs->totalHits; // update totalHits + scoreDocs = docs->scoreDocs; + for ( j = 0; j scoreDocsLength; ++j) { // merge scoreDocs int_to hq + scoreDocs[j].doc += starts[i]; // convert doc + if ( !hq->insert(scoreDocs[j])) + break; // no more scores > minScore + } + + _CLDELETE(docs); + } + + int32_t scoreDocsLen = hq->size(); + scoreDocs = _CL_NEWARRAY(ScoreDoc, scoreDocsLen); + {//MSVC 6 scope fix + for (int32_t i = scoreDocsLen-1; i >= 0; --i) // put docs in array + scoreDocs[i] = hq->pop(); + } + + //cleanup + _CLDELETE(hq); + + return _CLNEW TopDocs(totalHits, scoreDocs, scoreDocsLen); + } + + /** Lower-level search API. + * + *

{@link HitCollector#collect(int32_t,qreal)} is called for every non-zero + * scoring document. + * + *

Applications should only use this if they need all of the + * matching documents. The high-level search API ({@link + * Searcher#search(Query)}) is usually more efficient, as it skips + * non-high-scoring hits. + * + * @param query to match documents + * @param filter if non-null, a bitset used to eliminate some documents + * @param results to receive hits + */ + void MultiSearcher::_search(Query* query, Filter* filter, HitCollector* results){ + for (int32_t i = 0; i < searchablesLen; ++i) { + /* DSR:CL_BUG: Old implementation leaked and was misconceived. We need + ** to have the original HitCollector ($results) collect *all* hits; + ** the MultiHitCollector instantiated below serves only to adjust + ** (forward by starts[i]) the docNo passed to $results. + ** Old implementation instead created a sort of linked list of + ** MultiHitCollectors that applied the adjustments in $starts + ** cumulatively (and was never deleted). */ + HitCollector *docNoAdjuster = _CLNEW MultiHitCollector(results, starts[i]); + searchables[i]->_search(query, filter, docNoAdjuster); + _CLDELETE(docNoAdjuster); + } + } + + TopFieldDocs* MultiSearcher::_search (Query* query, Filter* filter, const int32_t n, const Sort* sort){ + FieldDocSortedHitQueue* hq = NULL; + int32_t totalHits = 0; + TopFieldDocs* docs; + int32_t j; + FieldDoc** fieldDocs; + + for (int32_t i = 0; i < searchablesLen; ++i) { // search each searcher + docs = searchables[i]->_search (query, filter, n, sort); + if (hq == NULL){ + hq = _CLNEW FieldDocSortedHitQueue (docs->fields, n); + docs->fields = NULL; //hit queue takes fields memory + } + + totalHits += docs->totalHits; // update totalHits + fieldDocs = docs->fieldDocs; + for(j = 0;jscoreDocsLength;++j){ // merge scoreDocs into hq + fieldDocs[j]->scoreDoc.doc += starts[i]; // convert doc + if (!hq->insert (fieldDocs[j]) ) + break; // no more scores > minScore + } + for ( int32_t x=0;xsize(); + fieldDocs = _CL_NEWARRAY(FieldDoc*,hqlen); + for (j = hqlen - 1; j >= 0; j--) // put docs in array + fieldDocs[j] = hq->pop(); + + SortField** hqFields = hq->getFields(); + hq->setFields(NULL); //move ownership of memory over to TopFieldDocs + _CLDELETE(hq); + + return _CLNEW TopFieldDocs (totalHits, fieldDocs, hqlen, hqFields); + } + + Query* MultiSearcher::rewrite(Query* original) { + Query** queries = _CL_NEWARRAY(Query*,searchablesLen+1); + for (int32_t i = 0; i < searchablesLen; ++i) + queries[i] = searchables[i]->rewrite(original); + queries[searchablesLen]=NULL; + return original->combine(queries); + } + + void MultiSearcher::explain(Query* query, int32_t doc, Explanation* ret) { + int32_t i = subSearcher(doc); // find searcher index + searchables[i]->explain(query,doc-starts[i], ret); // dispatch to searcher + } + + MultiHitCollector::MultiHitCollector(HitCollector* _results, int32_t _start): + results(_results), + start(_start) { + } + + void MultiHitCollector::collect(const int32_t doc, const qreal score) { + results->collect(doc + start, score); + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/MultiSearcher.h b/3rdparty/clucene/src/CLucene/search/MultiSearcher.h new file mode 100644 index 0000000..1021fbb --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/MultiSearcher.h @@ -0,0 +1,95 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_multisearcher +#define _lucene_search_multisearcher + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "SearchHeader.h" +#include "CLucene/document/Document.h" +#include "CLucene/index/Term.h" + +CL_NS_DEF(search) + + class MultiHitCollector: public HitCollector{ + private: + HitCollector* results; + int32_t start; + public: + MultiHitCollector(HitCollector* _results, int32_t _start); + void collect(const int32_t doc, const qreal score) ; + }; + + + /** Implements search over a set of Searchables. + * + *

Applications usually need only call the inherited {@link #search(Query)} + * or {@link #search(Query,Filter)} methods. + */ + class MultiSearcher: public Searcher { + private: + Searchable** searchables; + int32_t searchablesLen; + int32_t* starts; + int32_t _maxDoc; + protected: + int32_t* getStarts() { + return starts; + } + + public: + /** Creates a searcher which searches Searchables. */ + MultiSearcher(Searchable** searchables); + + ~MultiSearcher(); + + /** Frees resources associated with this Searcher. */ + void close() ; + + int32_t docFreq(const CL_NS(index)::Term* term) const ; + + /** For use by {@link HitCollector} implementations. */ + bool doc(int32_t n, CL_NS(document)::Document* document); + + /** For use by {@link HitCollector} implementations to identify the + * index of the sub-searcher that a particular hit came from. */ + int32_t searcherIndex(int32_t n) const; + + int32_t subSearcher(int32_t n) const; + + int32_t subDoc(int32_t n) const; + + int32_t maxDoc() const; + + TopDocs* _search(Query* query, Filter* filter, const int32_t nDocs) ; + + TopFieldDocs* _search (Query* query, Filter* filter, const int32_t n, const Sort* sort); + + /** Lower-level search API. + * + *

{@link HitCollector#collect(int32_t,qreal)} is called for every non-zero + * scoring document. + * + *

Applications should only use this if they need all of the + * matching documents. The high-level search API ({@link + * Searcher#search(Query)}) is usually more efficient, as it skips + * non-high-scoring hits. + * + * @param query to match documents + * @param filter if non-null, a bitset used to eliminate some documents + * @param results to receive hits + */ + void _search(Query* query, Filter* filter, HitCollector* results); + + Query* rewrite(Query* original); + void explain(Query* query, int32_t doc, Explanation* ret); + }; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/MultiTermQuery.cpp b/3rdparty/clucene/src/CLucene/search/MultiTermQuery.cpp new file mode 100644 index 0000000..3bf8d7a --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/MultiTermQuery.cpp @@ -0,0 +1,98 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "MultiTermQuery.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + +/** Constructs a query for terms matching term. */ + + MultiTermQuery::MultiTermQuery(Term* t){ + //Func - Constructor + //Pre - t != NULL + //Post - The instance has been created + + CND_PRECONDITION(t != NULL, "t is NULL"); + + term = _CL_POINTER(t); + + } + MultiTermQuery::MultiTermQuery(const MultiTermQuery& clone): + Query(clone) + { + term = _CLNEW Term(clone.getTerm(false),clone.getTerm(false)->text()); + } + + MultiTermQuery::~MultiTermQuery(){ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + _CLDECDELETE(term); + } + + Term* MultiTermQuery::getTerm(bool pointer) const{ + if ( pointer ) + return _CL_POINTER(term); + else + return term; + } + + Query* MultiTermQuery::rewrite(IndexReader* reader) { + FilteredTermEnum* enumerator = getEnum(reader); + BooleanQuery* query = _CLNEW BooleanQuery(); + try { + do { + Term* t = enumerator->term(false); + if (t != NULL) { + TermQuery* tq = _CLNEW TermQuery(t); // found a match + tq->setBoost(getBoost() * enumerator->difference()); // set the boost + query->add(tq,true, false, false); // add to q + } + } while (enumerator->next()); + } _CLFINALLY ( enumerator->close(); _CLDELETE(enumerator) ); + + //if we only added one clause and the clause is not prohibited then + //we can just return the query + if (query->getClauseCount() == 1) { // optimize 1-clause queries + BooleanClause* c=0; + query->getClauses(&c); + + if (!c->prohibited) { // just return clause + c->deleteQuery=false; + Query* ret = c->query; + + _CLDELETE(query); + return ret; + } + } + return query; + } + + Query* MultiTermQuery::combine(Query** queries) { + return Query::mergeBooleanQueries(queries); + } + + /** Prints a user-readable version of this query. */ + TCHAR* MultiTermQuery::toString(const TCHAR* field) const{ + StringBuffer buffer; + + if ( field==NULL || _tcscmp(term->field(),field)!=0 ) { + buffer.append(term->field()); + buffer.append( _T(":")); + } + buffer.append(term->text()); + if (getBoost() != 1.0f) { + buffer.appendChar ( '^' ); + buffer.appendFloat( getBoost(),1); + } + return buffer.toString(); + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/MultiTermQuery.h b/3rdparty/clucene/src/CLucene/search/MultiTermQuery.h new file mode 100644 index 0000000..d376453 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/MultiTermQuery.h @@ -0,0 +1,62 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_MultiTermQuery_ +#define _lucene_search_MultiTermQuery_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/StringBuffer.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "FilteredTermEnum.h" +#include "SearchHeader.h" +#include "BooleanQuery.h" +#include "TermQuery.h" + +CL_NS_DEF(search) + /** + * A {@link Query} that matches documents containing a subset of terms provided + * by a {@link FilteredTermEnum} enumeration. + *

+ * MultiTermQuery is not designed to be used by itself. + *
+ * The reason being that it is not intialized with a {@link FilteredTermEnum} + * enumeration. A {@link FilteredTermEnum} enumeration needs to be provided. + *

+ * For example, {@link WildcardQuery} and {@link FuzzyQuery} extend + * MultiTermQuery to provide {@link WildcardTermEnum} and + * {@link FuzzyTermEnum}, respectively. + */ + class MultiTermQuery: public Query { + private: + CL_NS(index)::Term* term; + protected: + MultiTermQuery(const MultiTermQuery& clone); + + /** Construct the enumeration to be used, expanding the pattern term. */ + virtual FilteredTermEnum* getEnum(CL_NS(index)::IndexReader* reader) = 0; + public: + /** Constructs a query for terms matching term. */ + MultiTermQuery(CL_NS(index)::Term* t); + + virtual ~MultiTermQuery(); + + /** Returns the pattern term. */ + CL_NS(index)::Term* getTerm(bool pointer=true) const; + + Query* combine(Query** queries); + + /** Prints a user-readable version of this query. */ + TCHAR* toString(const TCHAR* field) const; + + Query* rewrite(CL_NS(index)::IndexReader* reader); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/PhrasePositions.cpp b/3rdparty/clucene/src/CLucene/search/PhrasePositions.cpp new file mode 100644 index 0000000..7611056 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PhrasePositions.cpp @@ -0,0 +1,116 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "PhrasePositions.h" + +#include "CLucene/index/Terms.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + + PhrasePositions::PhrasePositions(TermPositions* Tp, const int32_t OffSet){ + //Func - Constructor + //Pre - t != NULL + // OffSet != NULL + //Post - The instance has been created + + CND_PRECONDITION(Tp != NULL,"Tp is NULL"); + CND_PRECONDITION(OffSet >= 0 ,"OffSet is a negative number"); + + tp = Tp; + offset = OffSet; + position = 0; + count = 0; + doc = 0; + + _next = NULL; + } + + PhrasePositions::~PhrasePositions(){ + //Func - Destructor + //Pre - true + //Post - The instance has been deleted + + //delete next Phrase position and by doing that + //all PhrasePositions in the list + _CLDELETE(_next); + + //Check if tp is valid + if ( tp != NULL ){ + //Close TermPositions tp + tp->close(); + _CLDELETE(tp); + } + } + + bool PhrasePositions::next(){ + //Func - Increments to next doc + //Pre - tp != NULL + //Post - if there was no next then doc = INT_MAX otherwise + // doc contains the current document number + + CND_PRECONDITION(tp != NULL,"tp is NULL"); + + //Move to the next in TermPositions tp + if (!tp->next()) { + //There is no next so close the stream + tp->close(); + //delete tp and reset tp to NULL + _CLVDELETE(tp); //todo: not a clucene object... should be + //Assign Doc sentinel value + doc = INT_MAX; + return false; + }else{ + doc = tp->doc(); + position = 0; + return true; + } + } + bool PhrasePositions::skipTo(int32_t target){ + if (!tp->skipTo(target)) { + tp->close(); // close stream + doc = LUCENE_INT32_MAX_SHOULDBE; // sentinel value + return false; + } + doc = tp->doc(); + position = 0; + return true; + } + void PhrasePositions::firstPosition(){ + //Func - Read the first TermPosition + //Pre - tp != NULL + //Post - + + CND_PRECONDITION(tp != NULL,"tp is NULL"); + + //read first pos + count = tp->freq(); + //Move to the next TermPosition + nextPosition(); + } + + bool PhrasePositions::nextPosition(){ + //Func - Move to the next position + //Pre - tp != NULL + //Post - + + CND_PRECONDITION(tp != NULL,"tp is NULL"); + + if (count-- > 0) { + //read subsequent pos's + position = tp->nextPosition() - offset; + + //Check position always bigger than or equal to 0 + //bvk: todo, bug??? position < 0 occurs, cant figure out why, + //old version does it too and will fail the "SearchTest" test + //CND_CONDITION(position >= 0, "position has become a negative number"); + return true; + }else{ + return false; + } + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/PhrasePositions.h b/3rdparty/clucene/src/CLucene/search/PhrasePositions.h new file mode 100644 index 0000000..b6c8437 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PhrasePositions.h @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_PhrasePositions_ +#define _lucene_search_PhrasePositions_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/Terms.h" + +CL_NS_DEF(search) + + class PhrasePositions:LUCENE_BASE { + public: + int32_t doc; // current doc + int32_t position; // position in doc + int32_t count; // remaining pos in this doc + int32_t offset; // position in phrase + CL_NS(index)::TermPositions* tp; // stream of positions + PhrasePositions* _next; // used to make lists + + + //Constructor + PhrasePositions(CL_NS(index)::TermPositions* Tp, const int32_t o); + //Destructor + ~PhrasePositions(); + + bool next(); + bool skipTo(int32_t target); + + void firstPosition(); + + bool nextPosition(); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/PhraseQuery.cpp b/3rdparty/clucene/src/CLucene/search/PhraseQuery.cpp new file mode 100644 index 0000000..899cb3c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PhraseQuery.cpp @@ -0,0 +1,463 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "PhraseQuery.h" + +#include "SearchHeader.h" +#include "Scorer.h" +#include "BooleanQuery.h" +#include "TermQuery.h" + +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "CLucene/index/IndexReader.h" + +#include "CLucene/util/StringBuffer.h" +#include "CLucene/util/VoidList.h" +#include "CLucene/util/Arrays.h" + +#include "ExactPhraseScorer.h" +#include "SloppyPhraseScorer.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + + PhraseQuery::PhraseQuery(): + terms(false) + { + //Func - Constructor + //Pre - true + //Post - An empty PhraseQuery has been created + + slop = 0; + + field = NULL; + } + PhraseQuery::PhraseQuery(const PhraseQuery& clone): + Query(clone), terms(false) + { + slop = clone.slop; + field = clone.field; + int32_t size=clone.positions.size(); + { //msvc6 scope fix + for ( int32_t i=0;ipositions.push_back( n ); + } + } + size=clone.terms.size(); + { //msvc6 scope fix + for ( int32_t i=0;iterms.push_back( _CL_POINTER(clone.terms[i])); + } + } + } + Query* PhraseQuery::clone() const{ + return _CLNEW PhraseQuery(*this); + } + bool PhraseQuery::equals(CL_NS(search)::Query *other) const{ + if (!(other->instanceOf(PhraseQuery::getClassName()))) + return false; + + PhraseQuery* pq = (PhraseQuery*)other; + bool ret = (this->getBoost() == pq->getBoost()) + && (this->slop == pq->slop); + + if ( ret ){ + CLListEquals, + const CL_NS(util)::CLVector > comp; + ret = comp.equals(&this->terms,&pq->terms); + } + + if ( ret ){ + CLListEquals, + const CL_NS(util)::CLVector > comp; + ret = comp.equals(&this->positions,&pq->positions); + } + return ret; + } + + + PhraseQuery::~PhraseQuery(){ + //Func - Destructor + //Pre - true + //Post 0 The instance has been destroyed + + //Iterate through all the terms + for (uint32_t i = 0; i < terms.size(); i++){ + _CLLDECDELETE(terms[i]); + } + positions.clear(); + } + + size_t PhraseQuery::hashCode() const { + //todo: do cachedHashCode, and invalidate on add/remove clause + size_t ret = Similarity::floatToByte(getBoost()) ^ Similarity::floatToByte(slop); + + { //msvc6 scope fix + for ( int32_t i=0;terms.size();i++ ) + ret = 31 * ret + terms[i]->hashCode(); + } + { //msvc6 scope fix + for ( int32_t i=0;positions.size();i++ ) + ret = 31 * ret + positions[i]; + } + return ret; + } + + const TCHAR* PhraseQuery::getClassName(){ + return _T("PhraseQuery"); + } + const TCHAR* PhraseQuery::getQueryName() const{ + //Func - Returns the string "PhraseQuery" + //Pre - true + //Post - The string "PhraseQuery" has been returned + return getClassName(); + } + + + /** + * Adds a term to the end of the query phrase. + * The relative position of the term is the one immediately after the last term added. + */ + void PhraseQuery::add(Term* term) { + CND_PRECONDITION(term != NULL,"term is NULL"); + + int32_t position = 0; + + if(positions.size() > 0) + position = (positions[positions.size()-1]) + 1; + + add(term, position); + } + + void PhraseQuery::add(Term* term, int32_t position) { + //Func - Adds a term to the end of the query phrase. + //Pre - term != NULL + //Post - The term has been added if its field matches the field of the PhraseQuery + // and true is returned otherwise false is returned + CND_PRECONDITION(term != NULL,"term is NULL"); + + if (terms.size() == 0) + field = term->field(); + else{ + //Check if the field of the _CLNEW term matches the field of the PhraseQuery + //can use != because fields are interned + if ( term->field() != field){ + //return false; + TCHAR buf[200]; + _sntprintf(buf,200,_T("All phrase terms must be in the same field: %s"),term->field()); + _CLTHROWT(CL_ERR_IllegalArgument,buf); + } + } + //Store the _CLNEW term + terms.push_back(_CL_POINTER(term)); + + positions.push_back(position); + } + + void PhraseQuery::getPositions(Array& result) const{ + result.length = positions.size(); + result.values = _CL_NEWARRAY(int32_t,result.length); + for(int32_t i = 0; i < result.length; i++){ + result.values[i] = positions[i]; + } + } + int32_t* PhraseQuery::getPositions() const{ + CND_WARNING(false,"getPositions() is deprecated") + + Array arr; + getPositions(arr); + return arr.values; + } + + Weight* PhraseQuery::_createWeight(Searcher* searcher) { + if (terms.size() == 1) { // optimize one-term case + Term* term = terms[0]; + Query* termQuery = _CLNEW TermQuery(term); + termQuery->setBoost(getBoost()); + Weight* ret = termQuery->_createWeight(searcher); + _CLDELETE(termQuery); + return ret; + } + return _CLNEW PhraseWeight(searcher,this); + } + + + Term** PhraseQuery::getTerms() const{ + //Func - added by search highlighter + //Pre - + //Post - + + //Let size contain the number of terms + int32_t size = terms.size(); + Term** ret = _CL_NEWARRAY(Term*,size+1); + + CND_CONDITION(ret != NULL,"Could not allocated memory for ret"); + + //Iterate through terms and copy each pointer to ret + for ( int32_t i=0;itext() ); + //Check if i is at the end of terms + if (i != terms.size()-1){ + buffer.append(_T(" ")); + } + } + + buffer.append( _T("\"") ); + + if (slop != 0) { + buffer.append(_T("~")); + buffer.appendFloat(slop,0); + } + + //Check if there is an other boost factor than 1.0 + if (getBoost() != 1.0f) { + buffer.append(_T("^")); + buffer.appendFloat( getBoost(),1 ); + } + + //return the query string + return buffer.toString(); + } + + + + + + + + + PhraseQuery::PhraseWeight::PhraseWeight(Searcher* searcher, PhraseQuery* _this) { + this->_this=_this; + this->value = 0; + this->idf = 0; + this->queryNorm = 0; + this->queryWeight = 0; + this->searcher = searcher; + } + + TCHAR* PhraseQuery::PhraseWeight::toString() { + return STRDUP_TtoT(_T("weight(PhraseQuery)")); + } + PhraseQuery::PhraseWeight::~PhraseWeight(){ + } + + + Query* PhraseQuery::PhraseWeight::getQuery() { return _this; } + qreal PhraseQuery::PhraseWeight::getValue() { return value; } + + qreal PhraseQuery::PhraseWeight::sumOfSquaredWeights(){ + idf = _this->getSimilarity(searcher)->idf(&_this->terms, searcher); + queryWeight = idf * _this->getBoost(); // compute query weight + return queryWeight * queryWeight; // square it + } + + void PhraseQuery::PhraseWeight::normalize(qreal queryNorm) { + this->queryNorm = queryNorm; + queryWeight *= queryNorm; // normalize query weight + value = queryWeight * idf; // idf for document + } + + Scorer* PhraseQuery::PhraseWeight::scorer(IndexReader* reader) { + //Func - + //Pre - + //Post - + + //Get the length of terms + int32_t tpsLength = _this->terms.size(); + + //optimize zero-term case + if (tpsLength == 0) + return NULL; + + TermPositions** tps = _CL_NEWARRAY(TermPositions*,tpsLength+1); + + //Check if tps has been allocated properly + CND_CONDITION(tps != NULL,"Could not allocate memory for tps"); + + TermPositions* p = NULL; + + //Iterate through all terms + int32_t size = _this->terms.size(); + for (int32_t i = 0; i < size; i++) { + //Get the termPostitions for the i-th term + p = reader->termPositions(_this->terms[i]); + + //Check if p is valid + if (p == NULL) { + //Delete previous retrieved termPositions + while (--i >= 0){ + _CLVDELETE(tps[i]); //todo: not a clucene object... should be + } + _CLDELETE_ARRAY(tps); + return NULL; + } + + //Store p at i in tps + tps[i] = p; + } + tps[tpsLength] = NULL; + + Scorer* ret = NULL; + + Array positions; + _this->getPositions(positions); + int32_t slop = _this->getSlop(); + if ( slop != 0) + // optimize exact case + //todo: need to pass these: this, tps, + ret = _CLNEW SloppyPhraseScorer(this,tps,positions.values, + _this->getSimilarity(searcher), + slop, reader->norms(_this->field)); + else + ret = _CLNEW ExactPhraseScorer(this, tps, positions.values, + _this->getSimilarity(searcher), + reader->norms(_this->field)); + positions.deleteArray(); + + CND_CONDITION(ret != NULL,"Could not allocate memory for ret"); + + //tps can be deleted safely. SloppyPhraseScorer or ExactPhraseScorer will take care + //of its values + + _CLDELETE_ARRAY(tps); + return ret; + } + + void PhraseQuery::PhraseWeight::explain(IndexReader* reader, int32_t doc, Explanation* result){ + TCHAR descbuf[LUCENE_SEARCH_EXPLANATION_DESC_LEN+1]; + TCHAR* tmp; + + tmp = getQuery()->toString(); + _sntprintf(descbuf,LUCENE_SEARCH_EXPLANATION_DESC_LEN,_T("weight(%s in %d), product of:"), + tmp,doc); + _CLDELETE_CARRAY(tmp); + result->setDescription(descbuf); + + StringBuffer docFreqs; + StringBuffer query; + query.appendChar('\"'); + for (uint32_t i = 0; i < _this->terms.size(); i++) { + if (i != 0) { + docFreqs.appendChar(' '); + query.appendChar(' '); + } + + Term* term = _this->terms[i]; + + docFreqs.append(term->text()); + docFreqs.appendChar('='); + docFreqs.appendInt(searcher->docFreq(term)); + + query.append(term->text()); + } + query.appendChar('\"'); + + _sntprintf(descbuf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("idf(%s: %s)"),_this->field,docFreqs.getBuffer()); + Explanation* idfExpl = _CLNEW Explanation(idf, descbuf); + + // explain query weight + Explanation* queryExpl = _CLNEW Explanation; + tmp = getQuery()->toString(); + _sntprintf(descbuf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("queryWeight(%s), product of:"),tmp); + _CLDELETE_CARRAY(tmp); + queryExpl->setDescription(descbuf); + + Explanation* boostExpl = _CLNEW Explanation(_this->getBoost(), _T("boost")); + if (_this->getBoost() != 1.0f) + queryExpl->addDetail(boostExpl); + queryExpl->addDetail(idfExpl); + + Explanation* queryNormExpl = _CLNEW Explanation(queryNorm,_T("queryNorm")); + queryExpl->addDetail(queryNormExpl); + + queryExpl->setValue(boostExpl->getValue() * + idfExpl->getValue() * + queryNormExpl->getValue()); + + result->addDetail(queryExpl); + + // explain field weight + Explanation* fieldExpl = _CLNEW Explanation; + _sntprintf(descbuf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("fieldWeight(%s:%s in %d), product of:"), + _this->field,query.getBuffer(),doc); + fieldExpl->setDescription(descbuf); + + + Explanation* tfExpl = _CLNEW Explanation; + scorer(reader)->explain(doc, tfExpl); + fieldExpl->addDetail(tfExpl); + fieldExpl->addDetail(idfExpl); + + Explanation* fieldNormExpl = _CLNEW Explanation(); + uint8_t* fieldNorms = reader->norms(_this->field); + qreal fieldNorm = + fieldNorms!=NULL ? Similarity::decodeNorm(fieldNorms[doc]) : 0.0f; + fieldNormExpl->setValue(fieldNorm); + + + _sntprintf(descbuf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("fieldNorm(field=%s, doc=%d)"),_this->field,doc); + fieldNormExpl->setDescription(descbuf); + fieldExpl->addDetail(fieldNormExpl); + + fieldExpl->setValue(tfExpl->getValue() * + idfExpl->getValue() * + fieldNormExpl->getValue()); + + result->addDetail(fieldExpl); + + // combine them + result->setValue(queryExpl->getValue() * fieldExpl->getValue()); + + if (queryExpl->getValue() == 1.0f){ + result->set(*fieldExpl); + _CLDELETE(fieldExpl); + } + } + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/PhraseQuery.h b/3rdparty/clucene/src/CLucene/search/PhraseQuery.h new file mode 100644 index 0000000..6b32558 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PhraseQuery.h @@ -0,0 +1,127 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_PhraseQuery_ +#define _lucene_search_PhraseQuery_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "SearchHeader.h" +#include "Scorer.h" +#include "BooleanQuery.h" +#include "TermQuery.h" + +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "CLucene/index/IndexReader.h" + +#include "CLucene/util/StringBuffer.h" +#include "CLucene/util/VoidList.h" + +#include "ExactPhraseScorer.h" +#include "SloppyPhraseScorer.h" + +CL_NS_DEF(search) + // A Query that matches documents containing a particular sequence of terms. + // This may be combined with other terms with a {@link BooleanQuery}. + class PhraseQuery: public Query { + private: + CL_NS(util)::CLVector positions; + int32_t slop; + + const TCHAR* field; + CL_NS(util)::CLVector terms; + + + class PhraseWeight: public Weight { + private: + Searcher* searcher; + qreal value; + qreal idf; + qreal queryNorm; + qreal queryWeight; + PhraseQuery* _this; + public: + PhraseWeight(Searcher* searcher, PhraseQuery* _this); + ~PhraseWeight(); + TCHAR* toString(); + + Query* getQuery(); + qreal getValue(); + + qreal sumOfSquaredWeights(); + void normalize(qreal queryNorm); + Scorer* scorer(CL_NS(index)::IndexReader* reader); + void explain(CL_NS(index)::IndexReader* reader, int32_t doc, Explanation* ret); + TCHAR* toString(TCHAR* f); + bool equals(PhraseWeight* o); + }; + friend class PhraseWeight; + protected: + Weight* _createWeight(Searcher* searcher); + PhraseQuery(const PhraseQuery& clone); + public: + //Constructor + PhraseQuery(); + + //Destructor + ~PhraseQuery(); + + //Returns the string "PhraseQuery" + const TCHAR* getQueryName() const; + static const TCHAR* getClassName(); + + //Sets the number of other words permitted between words in query phrase. + //If zero, then this is an exact phrase search. For larger values this works + //like a WITHIN or NEAR operator. + // + //The slop is in fact an edit-distance, where the units correspond to + //moves of terms in the query phrase out of position. For example, to switch + //the order of two words requires two moves (the first move places the words + //atop one another), so to permit re-orderings of phrases, the slop must be + //at least two. + // + //More exact matches are scored higher than sloppier matches, thus search + //results are sorted by exactness. + // + //The slop is zero by default, requiring exact matches. + void setSlop(const int32_t s) { slop = s; } + + //Returns the slop. See setSlop(). + int32_t getSlop() const { return slop; } + + //Adds a term to the end of the query phrase. + void add(CL_NS(index)::Term* term); + void add(CL_NS(index)::Term* term, int32_t position); + + + + //Returns the sum of squared weights + qreal sumOfSquaredWeights(Searcher* searcher); + + //Normalizes the Weight + void normalize(const qreal norm); + + Scorer* scorer(CL_NS(index)::IndexReader* reader); + + //added by search highlighter + CL_NS(index)::Term** getTerms() const; + _CL_DEPRECATED( deleteDocuments ) int32_t* getPositions() const; ///@deprecated. use getPositions(Array& result) + void getPositions(Array& result) const; + const TCHAR* getFieldName() const{ return field; } + + //Prints a user-readable version of this query. + TCHAR* toString(const TCHAR* f) const; + + Query* clone() const; + bool equals(CL_NS(search)::Query *) const; + + size_t hashCode() const; + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/PhraseQueue.h b/3rdparty/clucene/src/CLucene/search/PhraseQueue.h new file mode 100644 index 0000000..c0682fc --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PhraseQueue.h @@ -0,0 +1,36 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_PriorityQueue_ +#define _lucene_search_PriorityQueue_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/PriorityQueue.h" +#include "PhrasePositions.h" + +CL_NS_DEF(search) + class PhraseQueue: public CL_NS(util)::PriorityQueue > { + public: + PhraseQueue(const int32_t size) { + initialize(size,false); + } + ~PhraseQueue(){ + } + + protected: + bool lessThan(PhrasePositions* pp1, PhrasePositions* pp2) { + if (pp1->doc == pp2->doc) + return pp1->position < pp2->position; + else + return pp1->doc < pp2->doc; + } + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/PhraseScorer.cpp b/3rdparty/clucene/src/CLucene/search/PhraseScorer.cpp new file mode 100644 index 0000000..b2da231 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PhraseScorer.cpp @@ -0,0 +1,225 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "PhraseScorer.h" + +#include "PhraseQueue.h" +#include "PhrasePositions.h" +#include "Scorer.h" +#include "Similarity.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + + + PhraseScorer::PhraseScorer(Weight* weight, TermPositions** tps, + int32_t* positions, Similarity* similarity, uint8_t* norms): + Scorer(similarity) + { + //Func - Constructor + //Pre - tps != NULL and is an array of TermPositions + // tpsLength >= 0 + // n != NULL + //Post - The instance has been created + + CND_PRECONDITION(tps != NULL,"tps is NULL"); + + //norms are only used if phraseFreq returns more than 0.0 + //phraseFreq should only return more than 0.0 if norms != NULL + //CND_PRECONDITION(n != NULL,"n is NULL"); + + firstTime = true; + more = true; + this->norms = norms; + this->weight = weight; + this->value = weight->getValue(); + + //reset internal pointers + first = NULL; + last = NULL; + + //use pq to build a sorted list of PhrasePositions + int32_t i = 0; + while(tps[i] != NULL){ + PhrasePositions *pp = _CLNEW PhrasePositions(tps[i], positions[i]); + CND_CONDITION(pp != NULL,"Could not allocate memory for pp"); + + //Store PhrasePos into the PhrasePos pq + if (last != NULL) { // add next to end of list + last->_next = pp; + } else + first = pp; + last = pp; + + i++; + } + + pq = _CLNEW PhraseQueue(i); //i==tps.length + CND_CONDITION(pq != NULL,"Could not allocate memory for pq"); + } + + PhraseScorer::~PhraseScorer() { + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + //The PhraseQueue pq (which is a PriorityQueue) pq is actually empty at present, the elements + //having been transferred by pqToList() to the linked list starting with + //first. The nodes of that linked list are deleted by the destructor of + //first, rather than the destructor of pq. + _CLDELETE(first); + _CLDELETE(pq); + } + + bool PhraseScorer::next(){ + if (firstTime) { + init(); + firstTime = false; + } else if (more) { + more = last->next(); // trigger further scanning + } + return doNext(); + } + + // next without initial increment + bool PhraseScorer::doNext() { + while (more) { + while (more && first->doc < last->doc) { // find doc w/ all the terms + more = first->skipTo(last->doc); // skip first upto last + firstToLast(); // and move it to the end + } + + if (more) { + // found a doc with all of the terms + freq = phraseFreq(); // check for phrase + if (freq == 0.0f) // no match + more = last->next(); // trigger further scanning + else + return true; // found a match + } + } + return false; // no more matches + } + + qreal PhraseScorer::score(){ + //System.out.println("scoring " + first.doc); + qreal raw = getSimilarity()->tf(freq) * value; // raw score + return raw * Similarity::decodeNorm(norms[first->doc]); // normalize + } + + bool PhraseScorer::skipTo(int32_t target) { + for (PhrasePositions* pp = first; more && pp != NULL; pp = pp->_next) { + more = pp->skipTo(target); + } + if (more) + sort(); // re-sort + return doNext(); + } + + void PhraseScorer::init() { + for (PhrasePositions* pp = first; more && pp != NULL; pp = pp->_next) + more = pp->next(); + if(more) + sort(); + } + + void PhraseScorer::sort() { + pq->clear(); + for (PhrasePositions* pp = first; pp != NULL; pp = pp->_next) + pq->put(pp); + pqToList(); + } + + + + void PhraseScorer::pqToList(){ + //Func - Transfers the PhrasePositions from the PhraseQueue pq to + // the PhrasePositions list with first as its first element + //Pre - pq != NULL + // first = NULL + // last = NULL + //Post - All PhrasePositions have been transfered to the list + // of PhrasePositions of which the first element is pointed to by first + // and the last element is pointed to by last + + CND_PRECONDITION(pq != NULL,"pq is NULL"); + + last = first = NULL; + + PhrasePositions* PhrasePos = NULL; + + //As long pq is not empty + while (pq->top() != NULL){ + //Pop a PhrasePositions instance + PhrasePos = pq->pop(); + + // add next to end of list + if (last != NULL) { + last->_next = PhrasePos; + } else { + first = PhrasePos; + } + + //Let last point to the new last PhrasePositions instance just added + last = PhrasePos; + //Reset the next of last to NULL + last->_next = NULL; + } + + //Check to see that pq is empty now + CND_CONDITION(pq->size()==0, "pq is not empty while it should be"); + } + + void PhraseScorer::firstToLast(){ + //Func - Moves first to the end of the list + //Pre - first is NULL or points to an PhrasePositions Instance + // last is NULL or points to an PhrasePositions Instance + // first and last both are NULL or both are not NULL + //Post - The first element has become the last element in the list + + CND_PRECONDITION(((first==NULL && last==NULL) ||(first !=NULL && last != NULL)), + "Either first or last is NULL but not both"); + + //Check if first and last are valid pointers + if(first && last){ + last->_next = first; + last = first; + first = first->_next; + last->_next = NULL; + } + } + + + void PhraseScorer::explain(int32_t _doc, Explanation* tfExplanation) { + while (next() && doc() < _doc){ + } + + qreal phraseFreq = (doc() == _doc) ? freq : 0.0f; + tfExplanation->setValue(getSimilarity()->tf(phraseFreq)); + + StringBuffer buf; + buf.append(_T("tf(phraseFreq=")); + buf.appendFloat(phraseFreq,2); + buf.append(_T(")")); + tfExplanation->setDescription(buf.getBuffer()); + } + + TCHAR* PhraseScorer::toString() { + StringBuffer buf; + buf.append(_T("scorer(")); + + TCHAR* tmp = weight->toString(); + buf.append(tmp); + _CLDELETE_CARRAY(tmp); + + buf.append(_T(")")); + + return buf.toString(); + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/PhraseScorer.h b/3rdparty/clucene/src/CLucene/search/PhraseScorer.h new file mode 100644 index 0000000..89f7a1f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PhraseScorer.h @@ -0,0 +1,65 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_PhraseScorer_ +#define _lucene_search_PhraseScorer_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "PhraseQueue.h" +#include "PhrasePositions.h" +#include "Scorer.h" +#include "Similarity.h" + +CL_NS_DEF(search) + + class PhraseScorer: public Scorer { + private: + Weight* weight; + qreal freq; + bool firstTime; + bool more; + + protected: + uint8_t* norms; + qreal value; + + PhraseQueue* pq; //is used to order the list point to by first and last + PhrasePositions* first; //Points to the first in the list of PhrasePositions + PhrasePositions* last; //Points to the last in the list of PhrasePositions + + public: + //Constructor + PhraseScorer(Weight* weight, CL_NS(index)::TermPositions** tps, + int32_t* positions, Similarity* similarity, uint8_t* norms); + virtual ~PhraseScorer(); + + int32_t doc() const { return first->doc; } + bool next(); + qreal score(); + bool skipTo(int32_t target); + + + void explain(int32_t doc, Explanation* ret); + TCHAR* toString(); + protected: + virtual qreal phraseFreq() =0; + + //Transfers the PhrasePositions from the PhraseQueue pq to + //the PhrasePositions list with first as its first element + void pqToList(); + + //Moves first to the end of the list + void firstToLast(); + private: + bool doNext(); + void init(); + void sort(); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/PrefixQuery.cpp b/3rdparty/clucene/src/CLucene/search/PrefixQuery.cpp new file mode 100644 index 0000000..6bb27d1 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PrefixQuery.cpp @@ -0,0 +1,273 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "PrefixQuery.h" +#include "CLucene/util/BitSet.h" + +CL_NS_USE(util) +CL_NS_USE(index) +CL_NS_DEF(search) + + PrefixQuery::PrefixQuery(Term* Prefix){ + //Func - Constructor. + // Constructs a query for terms starting with prefix + //Pre - Prefix != NULL + //Post - The instance has been created + + //Get a pointer to Prefix + prefix = _CL_POINTER(Prefix); + } + + PrefixQuery::PrefixQuery(const PrefixQuery& clone):Query(clone){ + prefix = _CL_POINTER(clone.prefix); + } + Query* PrefixQuery::clone() const{ + return _CLNEW PrefixQuery(*this); + } + + Term* PrefixQuery::getPrefix(bool pointer){ + if ( pointer ) + return _CL_POINTER(prefix); + else + return prefix; + } + + PrefixQuery::~PrefixQuery(){ + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed. + + //Delete prefix by finalizing it + _CLDECDELETE(prefix); + } + + + /** Returns a hash code value for this object.*/ + size_t PrefixQuery::hashCode() const { + return Similarity::floatToByte(getBoost()) ^ prefix->hashCode(); + } + + const TCHAR* PrefixQuery::getQueryName()const{ + //Func - Returns the name "PrefixQuery" + //Pre - true + //Post - The string "PrefixQuery" has been returned + + return getClassName(); + } + const TCHAR* PrefixQuery::getClassName(){ + //Func - Returns the name "PrefixQuery" + //Pre - true + //Post - The string "PrefixQuery" has been returned + + return _T("PrefixQuery"); + } + + bool PrefixQuery::equals(Query * other) const{ + if (!(other->instanceOf(PrefixQuery::getClassName()))) + return false; + + PrefixQuery* rq = (PrefixQuery*)other; + bool ret = (this->getBoost() == rq->getBoost()) + && (this->prefix->equals(rq->prefix)); + + return ret; + } + + Query* PrefixQuery::rewrite(IndexReader* reader){ + BooleanQuery* query = _CLNEW BooleanQuery(); + TermEnum* enumerator = reader->terms(prefix); + Term* lastTerm = NULL; + try { + const TCHAR* prefixText = prefix->text(); + const TCHAR* prefixField = prefix->field(); + const TCHAR* tmp; + size_t i; + int32_t prefixLen = prefix->textLength(); + do { + lastTerm = enumerator->term(); + if (lastTerm != NULL && lastTerm->field() == prefixField ){ + + //now see if term->text() starts with prefixText + int32_t termLen = lastTerm->textLength(); + if ( prefixLen>termLen ) + break; //the prefix is longer than the term, can't be matched + + tmp = lastTerm->text(); + + //check for prefix match in reverse, since most change will be at the end + for ( i=prefixLen-1;i!=-1;--i ){ + if ( tmp[i] != prefixText[i] ){ + tmp=NULL;//signals inequality + break; + } + } + if ( tmp == NULL ) + break; + + TermQuery* tq = _CLNEW TermQuery(lastTerm); // found a match + tq->setBoost(getBoost()); // set the boost + query->add(tq,true,false, false); // add to query + } else + break; + _CLDECDELETE(lastTerm); + } while (enumerator->next()); + }_CLFINALLY( + enumerator->close(); + _CLDELETE(enumerator); + _CLDECDELETE(lastTerm); + ); + _CLDECDELETE(lastTerm); + + + //if we only added one clause and the clause is not prohibited then + //we can just return the query + if (query->getClauseCount() == 1) { // optimize 1-clause queries + BooleanClause* c=0; + query->getClauses(&c); + + if (!c->prohibited) { // just return clause + c->deleteQuery=false; + Query* ret = c->query; + + _CLDELETE(query); + return ret; + } + } + + return query; + } + + Query* PrefixQuery::combine(Query** queries) { + return Query::mergeBooleanQueries(queries); + } + + TCHAR* PrefixQuery::toString(const TCHAR* field) const{ + //Func - Creates a user-readable version of this query and returns it as as string + //Pre - field != NULL + //Post - a user-readable version of this query has been returned as as string + + //Instantiate a stringbuffer buffer to store the readable version temporarily + CL_NS(util)::StringBuffer buffer; + //check if field equal to the field of prefix + if( field==NULL || _tcscmp(prefix->field(),field) != 0 ) { + //Append the field of prefix to the buffer + buffer.append(prefix->field()); + //Append a colon + buffer.append(_T(":") ); + } + //Append the text of the prefix + buffer.append(prefix->text()); + //Append a wildchar character + buffer.append(_T("*")); + //if the boost factor is not eaqual to 1 + if (getBoost() != 1.0f) { + //Append ^ + buffer.append(_T("^")); + //Append the boost factor + buffer.appendFloat( getBoost(),1); + } + //Convert StringBuffer buffer to TCHAR block and return it + return buffer.toString(); + } + + + + + + + + +PrefixFilter::PrefixFilter( Term* prefix ) +{ + this->prefix = _CL_POINTER(prefix); +} + +PrefixFilter::~PrefixFilter() +{ + _CLDECDELETE(prefix); +} + +PrefixFilter::PrefixFilter( const PrefixFilter& copy ) : + prefix( _CL_POINTER(copy.prefix) ) +{ +} + +Filter* PrefixFilter::clone() const { + return _CLNEW PrefixFilter(*this ); +} + +TCHAR* PrefixFilter::toString() +{ + //Instantiate a stringbuffer buffer to store the readable version temporarily + CL_NS(util)::StringBuffer buffer; + //check if field equal to the field of prefix + if( prefix->field() != NULL ) { + //Append the field of prefix to the buffer + buffer.append(prefix->field()); + //Append a colon + buffer.append(_T(":") ); + } + //Append the text of the prefix + buffer.append(prefix->text()); + buffer.append(_T("*")); + + //Convert StringBuffer buffer to TCHAR block and return it + return buffer.toString(); +} + +/** Returns a BitSet with true for documents which should be permitted in +search results, and false for those that should not. */ +BitSet* PrefixFilter::bits( IndexReader* reader ) +{ + BitSet* bts = _CLNEW BitSet( reader->maxDoc() ); + TermEnum* enumerator = reader->terms(prefix); + TermDocs* docs = reader->termDocs(); + const TCHAR* prefixText = prefix->text(); + const TCHAR* prefixField = prefix->field(); + const TCHAR* tmp; + size_t i; + int32_t prefixLen = prefix->textLength(); + Term* lastTerm = NULL; + + try{ + do{ + lastTerm = enumerator->term(false); + if (lastTerm != NULL && lastTerm->field() == prefixField ){ + //now see if term->text() starts with prefixText + int32_t termLen = lastTerm->textLength(); + if ( prefixLen>termLen ) + break; //the prefix is longer than the term, can't be matched + + tmp = lastTerm->text(); + + //check for prefix match in reverse, since most change will be at the end + for ( i=prefixLen-1;i!=-1;--i ){ + if ( tmp[i] != prefixText[i] ){ + tmp=NULL;//signals inequality + break; + } + } + if ( tmp == NULL ) + break; + + docs->seek(enumerator); + while (docs->next()) { + bts->set(docs->doc()); + } + } + }while(enumerator->next()); + } _CLFINALLY( + docs->close(); + _CLDELETE(docs); + enumerator->close(); + _CLDELETE(enumerator); + ) + + return bts; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/PrefixQuery.h b/3rdparty/clucene/src/CLucene/search/PrefixQuery.h new file mode 100644 index 0000000..8e3f413 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/PrefixQuery.h @@ -0,0 +1,75 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_PrefixQuery +#define _lucene_search_PrefixQuery +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "CLucene/index/IndexReader.h" +#include "SearchHeader.h" +#include "BooleanQuery.h" +#include "TermQuery.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_DEF(search) + //PrefixQuery is a Query that matches documents containing terms with a specified prefix. + + class PrefixQuery: public Query { + private: + CL_NS(index)::Term* prefix; + protected: + PrefixQuery(const PrefixQuery& clone); + public: + + //Constructor. Constructs a query for terms starting with prefix + PrefixQuery(CL_NS(index)::Term* Prefix); + + //Destructor + ~PrefixQuery(); + + //Returns the name "PrefixQuery" + const TCHAR* getQueryName() const; + static const TCHAR* getClassName(); + + /** Returns the prefix of this query. */ + CL_NS(index)::Term* getPrefix(bool pointer=true); + + Query* combine(Query** queries); + Query* rewrite(CL_NS(index)::IndexReader* reader); + Query* clone() const; + bool equals(Query * other) const; + + //Creates a user-readable version of this query and returns it as as string + TCHAR* toString(const TCHAR* field) const; + + size_t hashCode() const; + }; + + + class PrefixFilter: public Filter + { + private: + CL_NS(index)::Term* prefix; + protected: + PrefixFilter( const PrefixFilter& copy ); + + public: + PrefixFilter(CL_NS(index)::Term* prefix); + ~PrefixFilter(); + + /** Returns a BitSet with true for documents which should be permitted in + search results, and false for those that should not. */ + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader ); + + Filter* clone() const; + TCHAR* toString(); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/QueryFilter.cpp b/3rdparty/clucene/src/CLucene/search/QueryFilter.cpp new file mode 100644 index 0000000..2dbe2d7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/QueryFilter.cpp @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "QueryFilter.h" +#include "IndexSearcher.h" + +CL_NS_DEF(search) +CL_NS_USE(util) +CL_NS_USE(index) + + +QueryFilter::QueryFilter( const Query* query ) +{ + this->query = query->clone(); +} + + +QueryFilter::~QueryFilter() +{ + _CLDELETE( query ); +} + + +QueryFilter::QueryFilter( const QueryFilter& copy ) +{ + this->query = copy.query->clone(); +} + + +Filter* QueryFilter::clone() const { + return _CLNEW QueryFilter(*this ); +} + + +TCHAR* QueryFilter::toString() +{ + TCHAR* qt = query->toString(); + size_t len = _tcslen(qt) + 14; + TCHAR* ret = _CL_NEWARRAY( TCHAR, len ); + ret[0] = 0; + _sntprintf( ret, len, _T("QueryFilter(%s)"), qt ); + _CLDELETE_CARRAY(qt); + return ret; +} + + +/** Returns a BitSet with true for documents which should be permitted in +search results, and false for those that should not. */ +BitSet* QueryFilter::bits( IndexReader* reader ) +{ + BitSet* bits = _CLNEW BitSet(reader->maxDoc()); + + IndexSearcher s(reader); + QFHitCollector hc(bits); + s._search(query, NULL, &hc); + return bits; +} + + +QueryFilter::QFHitCollector::QFHitCollector(CL_NS(util)::BitSet* bits){ + this->bits = bits; +} + +void QueryFilter::QFHitCollector::collect(const int32_t doc, const qreal score) { + bits->set(doc); // set bit for hit +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/QueryFilter.h b/3rdparty/clucene/src/CLucene/search/QueryFilter.h new file mode 100644 index 0000000..8d423b2 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/QueryFilter.h @@ -0,0 +1,44 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_QueryFilter_ +#define _lucene_search_QueryFilter_ + +#include "CLucene/util/BitSet.h" +#include "CLucene/index/IndexReader.h" +#include "SearchHeader.h" +#include "CachingWrapperFilter.h" + +CL_NS_DEF(search) + +class QueryFilter: public Filter +{ +private: + Query* query; + + class QFHitCollector: public HitCollector{ + CL_NS(util)::BitSet* bits; + public: + QFHitCollector(CL_NS(util)::BitSet* bits); + void collect(const int32_t doc, const qreal score); + }; + +protected: + QueryFilter( const QueryFilter& copy ); +public: + QueryFilter( const Query* query ); + + ~QueryFilter(); + + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader ); + + Filter *clone() const; + + TCHAR *toString(); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/RangeFilter.cpp b/3rdparty/clucene/src/CLucene/search/RangeFilter.cpp new file mode 100644 index 0000000..66ee5ce --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/RangeFilter.cpp @@ -0,0 +1,150 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "RangeFilter.h" + +CL_NS_DEF(search) +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_USE(document) + + +RangeFilter::RangeFilter( const TCHAR* fieldName, const TCHAR* lowerTerm, const TCHAR* upperTerm, bool includeLower, bool includeUpper ) +{ + this->field = STRDUP_TtoT(fieldName); + if ( lowerTerm != NULL ) + this->lowerValue = STRDUP_TtoT(lowerTerm); + else + this->lowerValue = NULL; + if ( upperTerm != NULL ) + this->upperValue = STRDUP_TtoT(upperTerm); + else + this->upperValue = NULL; + this->includeLower = includeLower; + this->includeUpper = includeUpper; +} + + +/** + * Constructs a filter for field fieldName matching + * less than or equal to upperTerm. + */ +RangeFilter* RangeFilter::Less( TCHAR* fieldName, TCHAR* upperTerm ) { + return new RangeFilter( fieldName, NULL, upperTerm, false, true ); +} + + +/** +* Constructs a filter for field fieldName matching +* more than or equal to lowerTerm. +*/ +RangeFilter* RangeFilter::More( TCHAR* fieldName, TCHAR* lowerTerm ) { + return new RangeFilter( fieldName, lowerTerm, NULL, true, false ); +} + + +RangeFilter::~RangeFilter() +{ + _CLDELETE_CARRAY( lowerValue ); + _CLDELETE_CARRAY( field ); + _CLDELETE_CARRAY( upperValue ); +} + + +RangeFilter::RangeFilter( const RangeFilter& copy ) : + field( STRDUP_TtoT(copy.field) ), + lowerValue( STRDUP_TtoT(copy.lowerValue) ), + upperValue( STRDUP_TtoT(copy.upperValue) ), + includeLower( copy.includeLower ), + includeUpper( copy.includeUpper ) +{ +} + + +Filter* RangeFilter::clone() const { + return _CLNEW RangeFilter(*this ); +} + + +TCHAR* RangeFilter::toString() +{ + size_t len = (field ? _tcslen(field) : 0) + (lowerValue ? _tcslen(lowerValue) : 0) + (upperValue ? _tcslen(upperValue) : 0) + 8; + TCHAR* ret = _CL_NEWARRAY( TCHAR, len ); + ret[0] = 0; + _sntprintf( ret, len, _T("%s: [%s-%s]"), field, (lowerValue?lowerValue:_T("")), (upperValue?upperValue:_T("")) ); + + return ret; +} + + +/** Returns a BitSet with true for documents which should be permitted in +search results, and false for those that should not. */ +BitSet* RangeFilter::bits( IndexReader* reader ) +{ + BitSet* bts = _CLNEW BitSet( reader->maxDoc() ); + Term* term = NULL; + + Term* t = _CLNEW Term( field, (lowerValue ? lowerValue : _T("")), false ); + TermEnum* enumerator = reader->terms( t ); // get enumeration of all terms after lowerValue + _CLDECDELETE( t ); + + if( enumerator->term(false) == NULL ) { + _CLDELETE( enumerator ); + return bts; + } + + bool checkLower = false; + if( !includeLower ) // make adjustments to set to exclusive + checkLower = true; + + TermDocs* termDocs = reader->termDocs(); + + try + { + do + { + term = enumerator->term(); + + if( term == NULL || _tcscmp(term->field(), field) ) + break; + + if( !checkLower || lowerValue == NULL || _tcscmp(term->text(), lowerValue) > 0 ) + { + checkLower = false; + if( upperValue != NULL ) + { + int compare = _tcscmp( upperValue, term->text() ); + + /* if beyond the upper term, or is exclusive and + * this is equal to the upper term, break out */ + if( (compare < 0) || (!includeUpper && compare == 0) ) + break; + } + + termDocs->seek( enumerator->term(false) ); + while( termDocs->next() ) { + bts->set( termDocs->doc() ); + } + } + + _CLDECDELETE( term ); + } + while( enumerator->next() ); + } + _CLFINALLY + ( + _CLDECDELETE( term ); + termDocs->close(); + _CLVDELETE( termDocs ); + enumerator->close(); + _CLDELETE( enumerator ); + ); + + return bts; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/RangeFilter.h b/3rdparty/clucene/src/CLucene/search/RangeFilter.h new file mode 100644 index 0000000..0865e35 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/RangeFilter.h @@ -0,0 +1,51 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ + +#ifndef _lucene_search_RangeFilter_ +#define _lucene_search_RangeFilter_ + +#include "CLucene/document/DateField.h" +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/BitSet.h" +#include "CLucene/search/Filter.h" + +CL_NS_DEF(search) + +class RangeFilter: public Filter +{ +private: + const TCHAR* field; + TCHAR* lowerValue; + TCHAR* upperValue; + bool includeLower; + bool includeUpper; + +protected: + RangeFilter( const RangeFilter& copy ); + +public: + RangeFilter( const TCHAR* fieldName, const TCHAR* lowerValue, const TCHAR* upperValue, bool includeLower, bool includeUpper ); + + static RangeFilter* Less( TCHAR* fieldName, TCHAR* upperTerm ); + + static RangeFilter* More( TCHAR* fieldName, TCHAR* lowerTerm ); + + ~RangeFilter(); + + /** Returns a BitSet with true for documents which should be permitted in + search results, and false for those that should not. */ + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader ); + + Filter* clone() const; + + TCHAR* toString(); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/RangeQuery.cpp b/3rdparty/clucene/src/CLucene/search/RangeQuery.cpp new file mode 100644 index 0000000..4fc2420 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/RangeQuery.cpp @@ -0,0 +1,204 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "RangeQuery.h" + +#include "SearchHeader.h" +#include "Scorer.h" +#include "BooleanQuery.h" +#include "TermQuery.h" + +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/StringBuffer.h" + + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + + RangeQuery::RangeQuery(Term* lowerTerm, Term* upperTerm, const bool Inclusive){ + //Func - Constructor + //Pre - (LowerTerm != NULL OR UpperTerm != NULL) AND + // if LowerTerm and UpperTerm are valid pointer then the fieldnames must be the same + //Post - The instance has been created + + if (lowerTerm == NULL && upperTerm == NULL) + { + _CLTHROWA(CL_ERR_IllegalArgument,"At least one term must be non-null"); + } + if (lowerTerm != NULL && upperTerm != NULL && lowerTerm->field() != upperTerm->field()) + { + _CLTHROWA(CL_ERR_IllegalArgument,"Both terms must be for the same field"); + } + + // if we have a lowerTerm, start there. otherwise, start at beginning + if (lowerTerm != NULL) { + this->lowerTerm = _CL_POINTER(lowerTerm); + } + else { + this->lowerTerm = _CLNEW Term(upperTerm, LUCENE_BLANK_STRING); + } + this->upperTerm = (upperTerm != NULL ? _CL_POINTER(upperTerm) : NULL); + this->inclusive = Inclusive; + } + RangeQuery::RangeQuery(const RangeQuery& clone): + Query(clone){ + this->inclusive = clone.inclusive; + this->upperTerm = (clone.upperTerm != NULL ? _CL_POINTER(clone.upperTerm) : NULL ); + this->lowerTerm = (clone.lowerTerm != NULL ? _CL_POINTER(clone.lowerTerm) : NULL ); + } + Query* RangeQuery::clone() const{ + return _CLNEW RangeQuery(*this); + } + + RangeQuery::~RangeQuery() { + //Func - Destructor + //Pre - true + //Post - The instance has been destroyed + + _CLDECDELETE(lowerTerm); + _CLDECDELETE(upperTerm); + } + + /** Returns a hash code value for this object.*/ + size_t RangeQuery::hashCode() const { + return Similarity::floatToByte(getBoost()) ^ + (lowerTerm != NULL ? lowerTerm->hashCode() : 0) ^ + (upperTerm != NULL ? upperTerm->hashCode() : 0) ^ + (this->inclusive ? 1 : 0); + } + + const TCHAR* RangeQuery::getQueryName() const{ + return getClassName(); + } + const TCHAR* RangeQuery::getClassName(){ + return _T("RangeQuery"); + } + + Query* RangeQuery::combine(Query** queries) { + return Query::mergeBooleanQueries(queries); + } + + bool RangeQuery::equals(Query * other) const{ + if (!(other->instanceOf(RangeQuery::getClassName()))) + return false; + + RangeQuery* rq = (RangeQuery*)other; + bool ret = (this->getBoost() == rq->getBoost()) + && (this->isInclusive() == rq->isInclusive()) + && (this->getLowerTerm()->equals(rq->getLowerTerm())) + && (this->getUpperTerm()->equals(rq->getUpperTerm())); + + return ret; + } + + + /** + * FIXME: Describe rewrite method here. + * + * @param reader an IndexReader value + * @return a Query value + * @exception IOException if an error occurs + */ + Query* RangeQuery::rewrite(IndexReader* reader){ + + BooleanQuery* query = _CLNEW BooleanQuery; + TermEnum* enumerator = reader->terms(lowerTerm); + Term* lastTerm = NULL; + try { + bool checkLower = false; + if (!inclusive) // make adjustments to set to exclusive + checkLower = true; + + const TCHAR* testField = getField(); + do { + lastTerm = enumerator->term(); + if (lastTerm != NULL && lastTerm->field() == testField ) { + if (!checkLower || _tcscmp(lastTerm->text(),lowerTerm->text()) > 0) { + checkLower = false; + if (upperTerm != NULL) { + int compare = _tcscmp(upperTerm->text(),lastTerm->text()); + /* if beyond the upper term, or is exclusive and + * this is equal to the upper term, break out */ + if ((compare < 0) || (!inclusive && compare == 0)) + break; + } + TermQuery* tq = _CLNEW TermQuery(lastTerm); // found a match + tq->setBoost(getBoost()); // set the boost + query->add(tq, true, false, false); // add to query + } + }else { + break; + } + _CLDECDELETE(lastTerm); + } + while (enumerator->next()); + }catch(...){ + _CLDECDELETE(lastTerm); //always need to delete this + _CLDELETE(query); //in case of error, delete the query + enumerator->close(); + _CLDELETE(enumerator); + throw; //rethrow + } + _CLDECDELETE(lastTerm); //always need to delete this + enumerator->close(); + _CLDELETE(enumerator); + + return query; + } + + /** Prints a user-readable version of this query. */ + TCHAR* RangeQuery::toString(const TCHAR* field) const + { + StringBuffer buffer; + if ( field==NULL || _tcscmp(getField(),field)!=0 ) + { + buffer.append( getField() ); + buffer.append( _T(":")); + } + buffer.append(inclusive ? _T("[") : _T("{")); + buffer.append(lowerTerm != NULL ? lowerTerm->text() : _T("NULL")); + buffer.append(_T(" TO ")); + buffer.append(upperTerm != NULL ? upperTerm->text() : _T("NULL")); + buffer.append(inclusive ? _T("]") : _T("}")); + if (getBoost() != 1.0f) + { + buffer.append( _T("^")); + buffer.appendFloat( getBoost(),1 ); + } + return buffer.toString(); + } + + + const TCHAR* RangeQuery::getField() const + { + return (lowerTerm != NULL ? lowerTerm->field() : upperTerm->field()); + } + + /** Returns the lower term of this range query */ + Term* RangeQuery::getLowerTerm(bool pointer) const { + if ( pointer ) + return _CL_POINTER(lowerTerm); + else + return lowerTerm; + } + + /** Returns the upper term of this range query */ + Term* RangeQuery::getUpperTerm(bool pointer) const { + if ( pointer ) + return _CL_POINTER(upperTerm); + else + return upperTerm; + } + + /** Returns true if the range query is inclusive */ + bool RangeQuery::isInclusive() const { return inclusive; } + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/RangeQuery.h b/3rdparty/clucene/src/CLucene/search/RangeQuery.h new file mode 100644 index 0000000..9a7733c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/RangeQuery.h @@ -0,0 +1,71 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_RangeQuery_ +#define _lucene_search_RangeQuery_ +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "SearchHeader.h" +#include "Scorer.h" +#include "TermQuery.h" + +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" + +#include "CLucene/util/StringBuffer.h" + + +CL_NS_DEF(search) + /** Constructs a query selecting all terms greater than + * lowerTerm but less than upperTerm. + * There must be at least one term and either term may be null, + * in which case there is no bound on that side, but if there are + * two terms, both terms must be for the same field. + */ + class RangeQuery: public Query + { + private: + CL_NS(index)::Term* lowerTerm; + CL_NS(index)::Term* upperTerm; + bool inclusive; + protected: + RangeQuery(const RangeQuery& clone); + + public: + // Constructs a query selecting all terms greater than + // lowerTerm but less than upperTerm. + // There must be at least one term and either term may be NULL-- + // in which case there is no bound on that side, but if there are + // two term, both terms must be for the same field. + RangeQuery(CL_NS(index)::Term* LowerTerm, CL_NS(index)::Term* UpperTerm, const bool Inclusive); + ~RangeQuery(); + + const TCHAR* getQueryName() const; + static const TCHAR* getClassName(); + + Query* rewrite(CL_NS(index)::IndexReader* reader); + + Query* combine(Query** queries); + + // Prints a user-readable version of this query. + TCHAR* toString(const TCHAR* field) const; + + Query* clone() const; + + bool equals(Query * other) const; + + CL_NS(index)::Term* getLowerTerm(bool pointer=true) const; + CL_NS(index)::Term* getUpperTerm(bool pointer=true) const; + bool isInclusive() const; + const TCHAR* getField() const; + + size_t hashCode() const; + }; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/Scorer.h b/3rdparty/clucene/src/CLucene/search/Scorer.h new file mode 100644 index 0000000..0d1d435 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Scorer.h @@ -0,0 +1,80 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_Scorer_ +#define _lucene_search_Scorer_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Similarity.h" +#include "SearchHeader.h" +#include "Explanation.h" + +CL_NS_DEF(search) + /** Expert: Implements scoring for a class of queries. */ +class Scorer: LUCENE_BASE { + private: + Similarity* similarity; + protected: + /** Constructs a Scorer. */ + Scorer(Similarity* similarity) { + this->similarity = similarity; + } + public: + virtual ~Scorer(){ + } + + /** Returns the Similarity implementation used by this scorer. */ + Similarity* getSimilarity() const{ + return this->similarity; + } + + /** Scores all documents and passes them to a collector. */ + void score(HitCollector* hc) { + while (next()) { + hc->collect(doc(), score()); + } + } + + /** Advance to the next document matching the query. Returns true iff there + * is another match. */ + virtual bool next() = 0; + + /** Returns the current document number. Initially invalid, until {@link + * #next()} is called the first time. */ + virtual int32_t doc() const = 0; + + /** Returns the score of the current document. Initially invalid, until + * {@link #next()} is called the first time. */ + virtual qreal score() = 0; + + /** Skips to the first match beyond the current whose document number is + * greater than or equal to target.

Returns true iff there is such + * a match.

Behaves as if written:

+         *   boolean skipTo(int32_t target) {
+         *     do {
+         *       if (!next())
+         * 	     return false;
+         *     } while (target > doc());
+         *     return true;
+         *   }
+         * 
+ * Most implementations are considerably more efficient than that. + */ + virtual bool skipTo(int32_t target) = 0; + + /** Returns an explanation of the score for doc. */ + virtual void explain(int32_t doc, Explanation* ret) = 0; + + + /** Returns an string which explains the object */ + virtual TCHAR* toString() = 0; + + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/SearchHeader.cpp b/3rdparty/clucene/src/CLucene/search/SearchHeader.cpp new file mode 100644 index 0000000..56e4ad5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/SearchHeader.cpp @@ -0,0 +1,141 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "SearchHeader.h" +#include "BooleanQuery.h" +#include "FieldDocSortedHitQueue.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + +CL_NS(document)::Document* Searchable::doc(const int32_t i){ + CL_NS(document)::Document* ret = _CLNEW CL_NS(document)::Document; + if (!doc(i,ret) ) + _CLDELETE(ret); + return ret; +} + +//static +Query* Query::mergeBooleanQueries(Query** queries) { + CL_NS(util)::CLVector allClauses; + int32_t i = 0; + while ( queries[i] != NULL ){ + BooleanQuery* bq = (BooleanQuery*)queries[i]; + + int32_t size = bq->getClauseCount(); + BooleanClause** clauses = _CL_NEWARRAY(BooleanClause*, size); + bq->getClauses(clauses); + + for (int32_t j = 0;j::iterator itr = allClauses.begin(); + while (itr != allClauses.end() ) { + result->add(*itr); + } + return result; +} + +Query::Query(const Query& clone):boost(clone.boost){ + //constructor +} +Weight* Query::_createWeight(Searcher* searcher){ + _CLTHROWA(CL_ERR_UnsupportedOperation,"UnsupportedOperationException: Query::_createWeight"); +} + +Query::Query(): + boost(1.0f) +{ + //constructor +} +Query::~Query(){ +} + +/** Expert: called to re-write queries into primitive queries. */ +Query* Query::rewrite(CL_NS(index)::IndexReader* reader){ + return this; +} + +Query* Query::combine(Query** queries){ + _CLTHROWA(CL_ERR_UnsupportedOperation,"UnsupportedOperationException: Query::combine"); +} +Similarity* Query::getSimilarity(Searcher* searcher) { + return searcher->getSimilarity(); +} +bool Query::instanceOf(const TCHAR* other) const{ + const TCHAR* t = getQueryName(); + if ( t==other || _tcscmp( t, other )==0 ) + return true; + else + return false; +} +TCHAR* Query::toString() const{ + return toString(LUCENE_BLANK_STRING); +} + +void Query::setBoost(qreal b) { boost = b; } + +qreal Query::getBoost() const { return boost; } + +Weight* Query::weight(Searcher* searcher){ + Query* query = searcher->rewrite(this); + Weight* weight = query->_createWeight(searcher); + qreal sum = weight->sumOfSquaredWeights(); + qreal norm = getSimilarity(searcher)->queryNorm(sum); + weight->normalize(norm); + return weight; +} + +TopFieldDocs::TopFieldDocs (int32_t totalHits, FieldDoc** fieldDocs, int32_t scoreDocsLen, SortField** fields): + TopDocs (totalHits, NULL, scoreDocsLen) +{ + this->fields = fields; + this->fieldDocs = fieldDocs; + this->scoreDocs = _CL_NEWARRAY(ScoreDoc,scoreDocsLen); + for (int32_t i=0;iscoreDocs[i] = this->fieldDocs[i]->scoreDoc; +} +TopFieldDocs::~TopFieldDocs(){ + if ( fieldDocs ){ + for (int32_t i=0;i= 0 +//Post - The instance has been created + +} + +TopDocs::~TopDocs(){ +//Func - Destructor +//Pre - true +//Post - The instance has been destroyed + + _CLDELETE_ARRAY(scoreDocs); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/SearchHeader.h b/3rdparty/clucene/src/CLucene/search/SearchHeader.h new file mode 100644 index 0000000..4a896a5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/SearchHeader.h @@ -0,0 +1,456 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_SearchHeader_ +#define _lucene_search_SearchHeader_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/Term.h" +#include "Filter.h" +#include "CLucene/document/Document.h" +#include "Sort.h" +#include "CLucene/util/VoidList.h" +#include "Explanation.h" +#include "Similarity.h" + +CL_NS_DEF(search) + + //predefine classes + class Scorer; + class Query; + class Hits; + class Sort; + class FieldDoc; + class TopFieldDocs; + + /** Expert: Returned by low-level search implementations. + * @see TopDocs */ + struct ScoreDoc { + /** Expert: A hit document's number. + * @see Searcher#doc(int32_t) + */ + int32_t doc; + + /** Expert: The score of this document for the query. */ + qreal score; + }; + + /** Expert: Returned by low-level search implementations. + * @see Searcher#search(Query,Filter,int32_t) */ + class TopDocs:LUCENE_BASE { + public: + /** Expert: The total number of hits for the query. + * @see Hits#length() + */ + int32_t totalHits; + + /** Expert: The top hits for the query. */ + ScoreDoc* scoreDocs; + int32_t scoreDocsLength; + + /** Expert: Constructs a TopDocs. TopDocs takes ownership of the ScoreDoc array*/ + TopDocs(const int32_t th, ScoreDoc* sds, int32_t scoreDocsLength); + ~TopDocs(); + }; + + // Lower-level search API. + // @see Searcher#search(Query,HitCollector) + class HitCollector: LUCENE_BASE { + public: + /** Called once for every non-zero scoring document, with the document number + * and its score. + * + *

If, for example, an application wished to collect all of the hits for a + * query in a BitSet, then it might:

+      *   Searcher searcher = new IndexSearcher(indexReader);
+      *   final BitSet bits = new BitSet(indexReader.maxDoc());
+      *   searcher.search(query, new HitCollector() {
+      *       public void collect(int32_t doc, float score) {
+      *         bits.set(doc);
+      *       }
+      *     });
+      * 
+ * + *

Note: This is called in an inner search loop. For good search + * performance, implementations of this method should not call + * {@link Searcher#doc(int32_t)} or + * {@link IndexReader#document(int32_t)} on every + * document number encountered. Doing so can slow searches by an order + * of magnitude or more. + *

Note: The score passed to this method is a raw score. + * In other words, the score will not necessarily be a float whose value is + * between 0 and 1. + */ + virtual void collect(const int32_t doc, const qreal score) = 0; + virtual ~HitCollector(){} + }; + + /** Expert: Calculate query weights and build query scorers. + * + *

A Weight is constructed by a query, given a Searcher ({@link + * Query#_createWeight(Searcher)}). The {@link #sumOfSquaredWeights()} method + * is then called on the top-level query to compute the query normalization + * factor (@link Similarity#queryNorm(qreal)}). This factor is then passed to + * {@link #normalize(qreal)}. At this point the weighting is complete and a + * scorer may be constructed by calling {@link #scorer(IndexReader)}. + */ + class Weight: LUCENE_BASE { + public: + virtual ~Weight(){ + }; + + /** The query that this concerns. */ + virtual Query* getQuery() = 0; + + /** The weight for this query. */ + virtual qreal getValue() = 0; + + /** The sum of squared weights of contained query clauses. */ + virtual qreal sumOfSquaredWeights() = 0; + + /** Assigns the query normalization factor to this. */ + virtual void normalize(qreal norm) = 0; + + /** Constructs a scorer for this. */ + virtual Scorer* scorer(CL_NS(index)::IndexReader* reader) = 0; + + /** An explanation of the score computation for the named document. */ + virtual void explain(CL_NS(index)::IndexReader* reader, int32_t doc, Explanation* ret) = 0; + + virtual TCHAR* toString(){ + return STRDUP_TtoT(_T("Weight")); + } + }; + + class HitDoc:LUCENE_BASE { + public: + qreal score; + int32_t id; + CL_NS(document)::Document* doc; + + HitDoc* next; // in doubly-linked cache + HitDoc* prev; // in doubly-linked cache + + HitDoc(const qreal s, const int32_t i); + ~HitDoc(); + }; + + + + // A ranked list of documents, used to hold search results. + class Hits:LUCENE_BASE { + private: + Query* query; + Searcher* searcher; + Filter* filter; + const Sort* sort; + + size_t _length; // the total number of hits + CL_NS(util)::CLVector > hitDocs; // cache of hits retrieved + + HitDoc* first; // head of LRU cache + HitDoc* last; // tail of LRU cache + int32_t numDocs; // number cached + int32_t maxDocs; // max to cache + + public: + Hits(Searcher* s, Query* q, Filter* f, const Sort* sort=NULL); + ~Hits(); + + /** Returns the total number of hits available in this set. */ + int32_t length() const; + + /** Returns the stored fields of the nth document in this set. +

Documents are cached, so that repeated requests for the same element may + return the same Document object. + * + * @memory Memory belongs to the hits object. Don't delete the return value. + */ + CL_NS(document)::Document& doc(const int32_t n); + + /** Returns the id for the nth document in this set. */ + int32_t id (const int32_t n); + + /** Returns the score for the nth document in this set. */ + qreal score(const int32_t n); + + private: + // Tries to add new documents to hitDocs. + // Ensures that the hit numbered _min has been retrieved. + void getMoreDocs(const size_t _min); + + HitDoc* getHitDoc(const size_t n); + + void addToFront(HitDoc* hitDoc); + + void remove(const HitDoc* hitDoc); + + }; + + /** The interface for search implementations. + * + *

Implementations provide search over a single index, over multiple + * indices, and over indices on remote servers. + */ + class Searchable: LUCENE_BASE { + public: + virtual ~Searchable(){ + } + + /** Lower-level search API. + * + *

{@link HitCollector#collect(int32_t,qreal)} is called for every non-zero + * scoring document. + * + *

Applications should only use this if they need all of the + * matching documents. The high-level search API ({@link + * Searcher#search(Query*)}) is usually more efficient, as it skips + * non-high-scoring hits. + * + * @param query to match documents + * @param filter if non-null, a bitset used to eliminate some documents + * @param results to receive hits + */ + virtual void _search(Query* query, Filter* filter, HitCollector* results) = 0; + + /** Frees resources associated with this Searcher. + * Be careful not to call this method while you are still using objects + * like {@link Hits}. + */ + virtual void close() = 0; + + /** Expert: Returns the number of documents containing term. + * Called by search code to compute term weights. + * @see IndexReader#docFreq(Term). + */ + virtual int32_t docFreq(const CL_NS(index)::Term* term) const = 0; + + /** Expert: Returns one greater than the largest possible document number. + * Called by search code to compute term weights. + * @see IndexReader#maxDoc(). + */ + virtual int32_t maxDoc() const = 0; + + /** Expert: Low-level search implementation. Finds the top n + * hits for query, applying filter if non-null. + * + *

Called by {@link Hits}. + * + *

Applications should usually call {@link Searcher#search(Query*)} or + * {@link Searcher#search(Query*,Filter*)} instead. + */ + virtual TopDocs* _search(Query* query, Filter* filter, const int32_t n) = 0; + + /** Expert: Returns the stored fields of document i. + * Called by {@link HitCollector} implementations. + * @see IndexReader#document(int32_t). + */ + virtual bool doc(int32_t i, CL_NS(document)::Document* d) = 0; + _CL_DEPRECATED( doc(i, document) ) CL_NS(document)::Document* doc(const int32_t i); + + /** Expert: called to re-write queries into primitive queries. */ + virtual Query* rewrite(Query* query) = 0; + + /** Returns an Explanation that describes how doc scored against + * query. + * + *

This is intended to be used in developing Similarity implementations, + * and, for good performance, should not be displayed with every hit. + * Computing an explanation is as expensive as executing the query over the + * entire index. + */ + virtual void explain(Query* query, int32_t doc, Explanation* ret) = 0; + + /** Expert: Low-level search implementation with arbitrary sorting. Finds + * the top n hits for query, applying + * filter if non-null, and sorting the hits by the criteria in + * sort. + * + *

Applications should usually call {@link + * Searcher#search(Query,Filter,Sort)} instead. + */ + virtual TopFieldDocs* _search(Query* query, Filter* filter, const int32_t n, const Sort* sort) = 0; + }; + + + + /** An abstract base class for search implementations. + * Implements some common utility methods. + */ + class Searcher:public Searchable { + private: + /** The Similarity implementation used by this searcher. */ + Similarity* similarity; + + public: + Searcher(){ + similarity = Similarity::getDefault(); + } + virtual ~Searcher(){ + } + + // Returns the documents matching query. + Hits* search(Query* query) { + return search(query, (Filter*)NULL ); + } + + // Returns the documents matching query and + // filter. + Hits* search(Query* query, Filter* filter) { + return _CLNEW Hits(this, query, filter); + } + + /** Returns documents matching query sorted by + * sort. + */ + Hits* search(Query* query, const Sort* sort){ + return _CLNEW Hits(this, query, NULL, sort); + } + + /** Returns documents matching query and filter, + * sorted by sort. + */ + Hits* search(Query* query, Filter* filter, const Sort* sort){ + return _CLNEW Hits(this, query, filter, sort); + } + + /** Lower-level search API. + * + *

{@link HitCollector#collect(int32_t ,qreal)} is called for every non-zero + * scoring document. + * + *

Applications should only use this if they need all of the + * matching documents. The high-level search API ({@link + * Searcher#search(Query*)}) is usually more efficient, as it skips + * non-high-scoring hits. + *

Note: The score passed to this method is a raw score. + * In other words, the score will not necessarily be a float whose value is + * between 0 and 1. + */ + void _search(Query* query, HitCollector* results) { + Searchable::_search(query, NULL, results); + } + + /** Expert: Set the Similarity implementation used by this Searcher. + * + * @see Similarity#setDefault(Similarity) + */ + void setSimilarity(Similarity* similarity) { + this->similarity = similarity; + } + + /** Expert: Return the Similarity implementation used by this Searcher. + * + *

This defaults to the current value of {@link Similarity#getDefault()}. + */ + Similarity* getSimilarity(){ + return this->similarity; + } + }; + + /** The abstract base class for queries. +

Instantiable subclasses are: +

    +
  • {@link TermQuery} +
  • {@link MultiTermQuery} +
  • {@link BooleanQuery} +
  • {@link WildcardQuery} +
  • {@link PhraseQuery} +
  • {@link PrefixQuery} +
  • {@link PhrasePrefixQuery} +
  • {@link FuzzyQuery} +
  • {@link RangeQuery} +
  • {@link spans.SpanQuery} +
+

A parser for queries is contained in: +

    +
  • {@link queryParser.QueryParser QueryParser} +
+ */ + class Query :LUCENE_BASE { + private: + // query boost factor + qreal boost; + protected: + Query(const Query& clone); + public: + Query(); + virtual ~Query(); + + /** Sets the boost for this query clause to b. Documents + * matching this clause will (in addition to the normal weightings) have + * their score multiplied by b. + */ + void setBoost(qreal b); + + /** Gets the boost for this clause. Documents matching + * this clause will (in addition to the normal weightings) have their score + * multiplied by b. The boost is 1.0 by default. + */ + qreal getBoost() const; + + /** Expert: Constructs an initializes a Weight for a top-level query. */ + Weight* weight(Searcher* searcher); + + /** Expert: called to re-write queries into primitive queries. */ + virtual Query* rewrite(CL_NS(index)::IndexReader* reader); + + /** Expert: called when re-writing queries under MultiSearcher. + * + *

Only implemented by derived queries, with no + * {@link #_createWeight(Searcher)} implementatation. + */ + virtual Query* combine(Query** queries); + + /** Expert: merges the clauses of a set of BooleanQuery's into a single + * BooleanQuery. + * + *

A utility for use by {@link #combine(Query[])} implementations. + */ + static Query* mergeBooleanQueries(Query** queries); + + /** Expert: Returns the Similarity implementation to be used for this query. + * Subclasses may override this method to specify their own Similarity + * implementation, perhaps one that delegates through that of the Searcher. + * By default the Searcher's Similarity implementation is returned.*/ + Similarity* getSimilarity(Searcher* searcher); + + /** Returns a clone of this query. */ + virtual Query* clone() const = 0; + virtual const TCHAR* getQueryName() const = 0; + bool instanceOf(const TCHAR* other) const; + + /** Prints a query to a string, with field as the default field + * for terms.

The representation used is one that is readable by + * {@link queryParser.QueryParser QueryParser} + * (although, if the query was created by the parser, the printed + * representation may not be exactly what was parsed). + */ + virtual TCHAR* toString(const TCHAR* field) const = 0; + + virtual bool equals(Query* other) const = 0; + virtual size_t hashCode() const = 0; + + /** Prints a query to a string. */ + TCHAR* toString() const; + + + /** Expert: Constructs an appropriate Weight implementation for this query. + * + *

Only implemented by primitive queries, which re-write to themselves. + * This is an Internal function + */ + virtual Weight* _createWeight(Searcher* searcher); + + }; + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/Similarity.cpp b/3rdparty/clucene/src/CLucene/search/Similarity.cpp new file mode 100644 index 0000000..d33a036 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Similarity.cpp @@ -0,0 +1,233 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Similarity.h" + +#include "CLucene/index/Term.h" +#include "SearchHeader.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + +#ifdef _CL_HAVE_NO_FLOAT_BYTE + #if defined(_LUCENE_PRAGMA_WARNINGS) + #pragma message ("==================Using fallback float<->byte encodings!!!==================") + #else + #warning "==================Using fallback float<->byte encodings!!!==================" + #endif + + //if the autoconf figured out that we can't do the conversions properly, then + //we fall back on the old, inaccurate way of doing things. + qreal NORM_TABLE[] = { + 0.0,5.820766E-10,6.9849193E-10,8.1490725E-10,9.313226E-10,1.1641532E-9,1.3969839E-9, + 1.6298145E-9,1.8626451E-9,2.3283064E-9,2.7939677E-9,3.259629E-9,3.7252903E-9, + 4.656613E-9,5.5879354E-9,6.519258E-9,7.4505806E-9,9.313226E-9,1.1175871E-8,1.3038516E-8, + 1.4901161E-8,1.8626451E-8,2.2351742E-8,2.6077032E-8,2.9802322E-8,3.7252903E-8,4.4703484E-8, + 5.2154064E-8,5.9604645E-8,7.4505806E-8,8.940697E-8,1.0430813E-7,1.1920929E-7,1.4901161E-7, + 1.7881393E-7,2.0861626E-7,2.3841858E-7,2.9802322E-7,3.5762787E-7,4.172325E-7,4.7683716E-7, + 5.9604645E-7,7.1525574E-7,8.34465E-7,9.536743E-7,1.1920929E-6,1.4305115E-6,1.66893E-6, + 1.9073486E-6,2.3841858E-6,2.861023E-6,3.33786E-6,3.8146973E-6,4.7683716E-6,5.722046E-6, + 6.67572E-6,7.6293945E-6,9.536743E-6,1.1444092E-5,1.335144E-5,1.5258789E-5,1.9073486E-5, + 2.2888184E-5,2.670288E-5,3.0517578E-5,3.8146973E-5,4.5776367E-5,5.340576E-5,6.1035156E-5, + 7.6293945E-5,9.1552734E-5,1.0681152E-4,1.2207031E-4,1.5258789E-4,1.8310547E-4,2.1362305E-4, + 2.4414062E-4,3.0517578E-4,3.6621094E-4,4.272461E-4,4.8828125E-4,6.1035156E-4,7.324219E-4, + 8.544922E-4,9.765625E-4,0.0012207031,0.0014648438,0.0017089844,0.001953125,0.0024414062, + 0.0029296875,0.0034179688,0.00390625,0.0048828125,0.005859375,0.0068359375, + 0.0078125,0.009765625,0.01171875,0.013671875,0.015625,0.01953125,0.0234375, + 0.02734375,0.03125,0.0390625,0.046875,0.0546875,0.0625,0.078125,0.09375,0.109375, + 0.125,0.15625,0.1875,0.21875,0.25,0.3125,0.375,0.4375,0.5,0.625,0.75, + 0.875,1.0,1.25,1.5,1.75,2,2.5,3,3.5,4.0,5.0,6.0,7.0,8.0,10.0,12.0,14.0,16.0,20.0,24.0,28.0,32.0,40.0,48.0,56.0, + 64.0,80.0,96.0,112.0,128.0,160.0,192.0,224.0,256.0,320.0,384.0,448.0,512.0,640.0,768.0,896.0,1024.0,1280.0,1536.0,1792.0, + 2048.0,2560.0,3072.0,3584.0,4096.0,5120.0,6144.0,7168.0,8192.0,10240.0,12288.0,14336.0,16384.0,20480.0,24576.0, + 28672.0,32768.0,40960.0,49152.0,57344.0,65536.0,81920.0,98304.0,114688.0,131072.0,163840.0,196608.0, + 229376.0,262144.0,327680.0,393216.0,458752.0,524288.0,655360.0,786432.0,917504.0,1048576.0,1310720.0, + 1572864.0,1835008.0,2097152.0,2621440.0,3145728.0,3670016.0,4194304.0,5242880.0,6291456.0,7340032.0, + 8388608.0,10485760.0,12582912.0,14680064.0,16777216.0,20971520.0,25165824.0,29360128.0,33554432.0, + 41943040.0,50331648.0,58720256.0,67108864.0,83886080.0,100663296.0,117440512.0,134217728.0, + 167772160.0,201326592.0,234881024.0,268435456.0,335544320.0,402653184.0,469762048.0,536870912.0, + 671088640.0,805306368.0,939524096.0,1073741824.0,1342177280.0,1610612736.0,1879048192.0, + 2147483648.0,2684354560.0,3221225472.0,3758096384.0,4294967296.0,5368709120.0,6442450944.0,7516192768.0 + }; + + qreal Similarity::byteToFloat(uint8_t b) { + return NORM_TABLE[b]; + } + + uint8_t Similarity::floatToByte(qreal f) { + return Similarity::encodeNorm(f); + } + +#else + + /** Cache of decoded bytes. */ + qreal NORM_TABLE[256]; + bool NORM_TABLE_initd=false; + + //float to bits conversion utilities... + union clvalue { + int32_t i; + float f; //must use a float type, else types dont match up + }; + + int32_t floatToIntBits(qreal value) + { + clvalue u; + int32_t e, f; + u.f = (float)value; + e = u.i & 0x7f800000; + f = u.i & 0x007fffff; + + if (e == 0x7f800000 && f != 0) + u.i = 0x7fc00000; + + return u.i; + } + + qreal intBitsToFloat(int32_t bits) + { + clvalue u; + u.i = bits; + return u.f; + } + + + qreal Similarity::byteToFloat(uint8_t b) { + if (b == 0) // zero is a special case + return 0.0f; + int32_t mantissa = b & 7; + int32_t exponent = (b >> 3) & 31; + int32_t bits = ((exponent+(63-15)) << 24) | (mantissa << 21); + return intBitsToFloat(bits); + } + + uint8_t Similarity::floatToByte(qreal f) { + if (f < 0.0f) // round negatives up to zero + f = 0.0f; + + if (f == 0.0f) // zero is a special case + return 0; + + int32_t bits = floatToIntBits(f); // parse qreal into parts + int32_t mantissa = (bits & 0xffffff) >> 21; + int32_t exponent = (((bits >> 24) & 0x7f) - 63) + 15; + + if (exponent > 31) { // overflow: use max value + exponent = 31; + mantissa = 7; + } + + if (exponent < 0) { // underflow: use min value + exponent = 0; + mantissa = 1; + } + + return (uint8_t)((exponent << 3) | mantissa); // pack into a uint8_t + } +#endif + + /** The Similarity implementation used by default. */ + Similarity* _defaultImpl=NULL; + + void Similarity::setDefault(Similarity* similarity) { + _defaultImpl = similarity; + } + + Similarity* Similarity::getDefault() { + if ( _defaultImpl == NULL ){ + _defaultImpl = _CLNEW DefaultSimilarity(); + } + return _defaultImpl; + } + + qreal Similarity::decodeNorm(uint8_t b) { +#ifndef _CL_HAVE_NO_FLOAT_BYTE + if ( !NORM_TABLE_initd ){ + for (int i = 0; i < 256; i++) + NORM_TABLE[i] = byteToFloat(i); + NORM_TABLE_initd=true; + } +#endif + return NORM_TABLE[b]; + } + + uint8_t Similarity::encodeNorm(qreal f) { +#ifdef _CL_HAVE_NO_FLOAT_BYTE + int32_t i=0; + if ( f <= 0 ) + return 0; + + while ( i<256 && f > NORM_TABLE[i] ){ + i++; + } + if ( i == 0 ) + return 0; + else if ( i == 255 && f>NORM_TABLE[255] ) + return 255; + else + return i; +#else + return floatToByte(f); +#endif + } + + + qreal Similarity::idf(Term* term, Searcher* searcher) { + return idf(searcher->docFreq(term), searcher->maxDoc()); + } + + + qreal Similarity::idf(CL_NS(util)::CLVector* terms, Searcher* searcher) { + qreal _idf = 0.0f; + for (CL_NS(util)::CLVector::iterator i = terms->begin(); i != terms->end(); i++ ) { + _idf += idf((Term*)*i, searcher); + } + return _idf; + } + + Similarity::~Similarity(){ + } + + + + + DefaultSimilarity::DefaultSimilarity(){ + } + DefaultSimilarity::~DefaultSimilarity(){ + } + + qreal DefaultSimilarity::lengthNorm(const TCHAR* fieldName, int32_t numTerms) { + if ( numTerms == 0 ) //prevent div by zero + return 0; + qreal ret = (qreal)(1.0 / sqrt((qreal)numTerms)); + return ret; + } + + qreal DefaultSimilarity::queryNorm(qreal sumOfSquaredWeights) { + if ( sumOfSquaredWeights == 0 ) //prevent div by zero + return 0.0f; + qreal ret = (qreal)(1.0 / sqrt(sumOfSquaredWeights)); + return ret; + } + + qreal DefaultSimilarity::tf(qreal freq) { + return sqrt(freq); + } + + qreal DefaultSimilarity::sloppyFreq(int32_t distance) { + return 1.0f / (distance + 1); + } + + qreal DefaultSimilarity::idf(int32_t docFreq, int32_t numDocs) { + return (qreal)(log(numDocs/(qreal)(docFreq+1)) + 1.0); + } + + qreal DefaultSimilarity::coord(int32_t overlap, int32_t maxOverlap) { + if ( maxOverlap == 0 ) + return 0.0f; + return overlap / (qreal)maxOverlap; + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/Similarity.h b/3rdparty/clucene/src/CLucene/search/Similarity.h new file mode 100644 index 0000000..426af69 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Similarity.h @@ -0,0 +1,268 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_Similarity_ +#define _lucene_search_Similarity_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/Term.h" + +CL_NS_DEF(search) + +class Searcher;//save including the searchheader.h +class DefaultSimilarity; + +/** Expert: Scoring API. +*

Subclasses implement search scoring. +* +*

The score of query q for document d is defined +* in terms of these methods as follows: +* +* +* +* +* +* +* +* +* +* +* +*
score(q,d) =
+* Σ +* {@link #tf(int32_t) tf}(t in d) * +* {@link #idf(Term,Searcher) idf}(t) * +* {@link Field#getBoost getBoost}(t.field in d) * +* {@link #lengthNorm(TCHAR*,int32_t) lengthNorm}(t.field in d) +*  * +* {@link #coord(int32_t,int32_t) coord}(q,d) * +* {@link #queryNorm(qreal) queryNorm}(q) +*
+* t in q +*
+* +* @see #setDefault(Similarity) +* @see IndexWriter#setSimilarity(Similarity) +* @see Searcher#setSimilarity(Similarity) +*/ +class Similarity:LUCENE_BASE { +public: + virtual ~Similarity(); + + /** Set the default Similarity implementation used by indexing and search + * code. + * + * @see Searcher#setSimilarity(Similarity) + * @see IndexWriter#setSimilarity(Similarity) + */ + static void setDefault(Similarity* similarity); + + /** Return the default Similarity implementation used by indexing and search + * code. + * + *

This is initially an instance of {@link DefaultSimilarity}. + * + * @see Searcher#setSimilarity(Similarity) + * @see IndexWriter#setSimilarity(Similarity) + */ + static Similarity* getDefault(); + + /** Encodes a normalization factor for storage in an index. + * + *

The encoding uses a five-bit exponent and three-bit mantissa, thus + * representing values from around 7x10^9 to 2x10^-9 with about one + * significant decimal digit of accuracy. Zero is also represented. + * Negative numbers are rounded up to zero. Values too large to represent + * are rounded down to the largest representable value. Positive values too + * small to represent are rounded up to the smallest positive representable + * value. + * + * @see Field#setBoost(qreal) + */ + static uint8_t encodeNorm(qreal f); + + /** Decodes a normalization factor stored in an index. + * @see #encodeNorm(qreal) + */ + static qreal decodeNorm(uint8_t b); + + static uint8_t floatToByte(qreal f); + static qreal byteToFloat(uint8_t b); + + /** Computes a score factor for a phrase. + * + *

The default implementation sums the {@link #idf(Term,Searcher)} factor + * for each term in the phrase. + * + * @param terms the terms in the phrase + * @param searcher the document collection being searched + * @return a score factor for the phrase + */ + qreal idf(CL_NS(util)::CLVector* terms, Searcher* searcher); + //qreal idf(Term** terms, Searcher* searcher); + + + /** Computes a score factor for a simple term. + * + *

The default implementation is:

+   *   return idf(searcher.docFreq(term), searcher.maxDoc());
+   * 
+ * + * Note that {@link Searcher#maxDoc()} is used instead of + * {@link IndexReader#numDocs()} because it is proportional to + * {@link Searcher#docFreq(Term)} , i.e., when one is inaccurate, + * so is the other, and in the same direction. + * + * @param term the term in question + * @param searcher the document collection being searched + * @return a score factor for the term + */ + qreal idf(CL_NS(index)::Term* term, Searcher* searcher); + + + /** Computes a score factor based on a term or phrase's frequency in a + * document. This value is multiplied by the {@link #idf(Term, Searcher)} + * factor for each term in the query and these products are then summed to + * form the initial score for a document. + * + *

Terms and phrases repeated in a document indicate the topic of the + * document, so implementations of this method usually return larger values + * when freq is large, and smaller values when freq + * is small. + * + *

The default implementation calls {@link #tf(qreal)}. + * + * @param freq the frequency of a term within a document + * @return a score factor based on a term's within-document frequency + */ + inline qreal tf(int32_t freq){ return tf((qreal)freq); } + + /** Computes the normalization value for a field given the total number of + * terms contained in a field. These values, together with field boosts, are + * stored in an index and multipled into scores for hits on each field by the + * search code. + * + *

Matches in longer fields are less precise, so implemenations of this + * method usually return smaller values when numTokens is large, + * and larger values when numTokens is small. + * + *

That these values are computed under {@link + * IndexWriter#addDocument(Document)} and stored then using + * {#encodeNorm(qreal)}. Thus they have limited precision, and documents + * must be re-indexed if this method is altered. + * + * @param fieldName the name of the field + * @param numTokens the total number of tokens contained in fields named + * fieldName of doc. + * @return a normalization factor for hits on this field of this document + * + * @see Field#setBoost(qreal) + */ + virtual qreal lengthNorm(const TCHAR* fieldName, int32_t numTokens) = 0; + + /** Computes the normalization value for a query given the sum of the squared + * weights of each of the query terms. This value is then multipled into the + * weight of each query term. + * + *

This does not affect ranking, but rather just attempts to make scores + * from different queries comparable. + * + * @param sumOfSquaredWeights the sum of the squares of query term weights + * @return a normalization factor for query weights + */ + virtual qreal queryNorm(qreal sumOfSquaredWeights) = 0; + + /** Computes the amount of a sloppy phrase match, based on an edit distance. + * This value is summed for each sloppy phrase match in a document to form + * the frequency that is passed to {@link #tf(qreal)}. + * + *

A phrase match with a small edit distance to a document passage more + * closely matches the document, so implementations of this method usually + * return larger values when the edit distance is small and smaller values + * when it is large. + * + * @see PhraseQuery#setSlop(int32_t) + * @param distance the edit distance of this sloppy phrase match + * @return the frequency increment for this match + */ + virtual qreal sloppyFreq(int32_t distance) = 0; + + /** Computes a score factor based on a term or phrase's frequency in a + * document. This value is multiplied by the {@link #idf(Term, Searcher)} + * factor for each term in the query and these products are then summed to + * form the initial score for a document. + * + *

Terms and phrases repeated in a document indicate the topic of the + * document, so implemenations of this method usually return larger values + * when freq is large, and smaller values when freq + * is small. + * + * @param freq the frequency of a term within a document + * @return a score factor based on a term's within-document frequency + */ + virtual qreal tf(qreal freq) = 0; + + /** Computes a score factor based on a term's document frequency (the number + * of documents which contain the term). This value is multiplied by the + * {@link #tf(int32_t)} factor for each term in the query and these products are + * then summed to form the initial score for a document. + * + *

Terms that occur in fewer documents are better indicators of topic, so + * implemenations of this method usually return larger values for rare terms, + * and smaller values for common terms. + * + * @param docFreq the number of documents which contain the term + * @param numDocs the total number of documents in the collection + * @return a score factor based on the term's document frequency + */ + virtual qreal idf(int32_t docFreq, int32_t numDocs) = 0; + + /** Computes a score factor based on the fraction of all query terms that a + * document contains. This value is multiplied into scores. + * + *

The presence of a large portion of the query terms indicates a better + * match with the query, so implemenations of this method usually return + * larger values when the ratio between these parameters is large and smaller + * values when the ratio between them is small. + * + * @param overlap the number of query terms matched in the document + * @param maxOverlap the total number of terms in the query + * @return a score factor based on term overlap with the query + */ + virtual qreal coord(int32_t overlap, int32_t maxOverlap) = 0; +}; + + +/** Expert: Default scoring implementation. */ +class DefaultSimilarity: public Similarity { +public: + DefaultSimilarity(); + ~DefaultSimilarity(); + + /** Implemented as 1/sqrt(numTerms). */ + qreal lengthNorm(const TCHAR* fieldName, int32_t numTerms); + + /** Implemented as 1/sqrt(sumOfSquaredWeights). */ + qreal queryNorm(qreal sumOfSquaredWeights); + + /** Implemented as sqrt(freq). */ + inline qreal tf(qreal freq); + + /** Implemented as 1 / (distance + 1). */ + qreal sloppyFreq(int32_t distance); + + /** Implemented as log(numDocs/(docFreq+1)) + 1. */ + qreal idf(int32_t docFreq, int32_t numDocs); + + /** Implemented as overlap / maxOverlap. */ + qreal coord(int32_t overlap, int32_t maxOverlap); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.cpp b/3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.cpp new file mode 100644 index 0000000..b7683b0 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.cpp @@ -0,0 +1,106 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "SloppyPhraseScorer.h" + +#include "PhraseScorer.h" +#include "CLucene/index/Terms.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + + SloppyPhraseScorer::SloppyPhraseScorer(Weight* weight, CL_NS(index)::TermPositions** tps, + int32_t* positions, Similarity* similarity, + int32_t slop, uint8_t* norms): + PhraseScorer(weight,tps,positions,similarity,norms){ + //Func - Constructor + //Pre - tps != NULL + // tpsLength >= 0 + // n != NULL + //Post - Instance has been created + + CND_PRECONDITION(tps != NULL, "tps is NULL"); + //CND_PRECONDITION(n != NULL, _T("n is NULL")) = checked in PhraseScorer; + + this->slop = slop; + } + + qreal SloppyPhraseScorer::phraseFreq() { + //Func - Returns the freqency of the phrase + //Pre - first != NULL + // last != NULL + // pq != NULL + //Post - The frequency of the phrase has been returned + + CND_PRECONDITION(first != NULL,"first is NULL"); + CND_PRECONDITION(last != NULL,"last is NULL"); + CND_PRECONDITION(pq != NULL,"pq is NULL"); + + //Clear the PhraseQueue pq; + pq->clear(); + + int32_t end = 0; + + //declare iterator + PhrasePositions* pp = NULL; + + // build pq from list + + //Sort the list of PhrasePositions using pq + for (pp = first; pp != NULL; pp = pp->_next) { + //Read the first TermPosition of the current PhrasePositions pp + pp->firstPosition(); + //Check if the position of the pp is bigger than end + if (pp->position > end){ + end = pp->position; + } + //Store the current PhrasePositions pp into the PhraseQueue pp + pq->put(pp); + } + + qreal freq = 0.0f; + + bool done = false; + + do { + //Pop a PhrasePositions pp from the PhraseQueue pp + pp = pq->pop(); + //Get start position + int32_t start = pp->position; + //Get next position + int32_t next = pq->top()->position; + + for (int32_t pos = start; pos <= next; pos = pp->position) { + //advance pp to min window + start = pos; + + if (!pp->nextPosition()) { + //ran out of a term -- done + done = true; + break; + } + } + + //Calculate matchLength + int32_t matchLength = end - start; + //Check if matchLength is smaller than slop + if (matchLength <= slop){ + // penalize longer matches + freq += 1.0 / (matchLength + 1); + } + + if (pp->position > end){ + end = pp->position; + } + + //restore pq + pq->put(pp); + }while (!done); + + return freq; + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.h b/3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.h new file mode 100644 index 0000000..31516e3 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/SloppyPhraseScorer.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_SloppyPhraseScorer_ +#define _lucene_search_SloppyPhraseScorer_ +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "PhraseScorer.h" +#include "CLucene/index/Terms.h" + + +CL_NS_DEF(search) + class SloppyPhraseScorer: public PhraseScorer { + private: + int32_t slop; + + public: + SloppyPhraseScorer(Weight* weight, CL_NS(index)::TermPositions** tps, + int32_t* positions, Similarity* similarity, + int32_t slop, uint8_t* norms); + ~SloppyPhraseScorer(){ + } + + protected: + qreal phraseFreq(); + }; +CL_NS_END +#endif + diff --git a/3rdparty/clucene/src/CLucene/search/Sort.cpp b/3rdparty/clucene/src/CLucene/search/Sort.cpp new file mode 100644 index 0000000..5a17a78 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Sort.cpp @@ -0,0 +1,345 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Sort.h" +#include "Compare.h" + +CL_NS_USE(util) +CL_NS_DEF(search) + + + + /** Represents sorting by document score (relevancy). */ + SortField* SortField::FIELD_SCORE = _CLNEW SortField (NULL, DOCSCORE,false); + + /** Represents sorting by document number (index order). */ + SortField* SortField::FIELD_DOC = _CLNEW SortField (NULL, DOC,false); + + + /** Represents sorting by computed relevance. Using this sort criteria + * returns the same results as calling {@link Searcher#search(Query) Searcher#search()} + * without a sort criteria, only with slightly more overhead. */ + Sort* Sort::RELEVANCE = _CLNEW Sort(); + + /** Represents sorting by index order. */ + Sort* Sort::INDEXORDER = _CLNEW Sort (SortField::FIELD_DOC); + + + + + /** Creates a sort by terms in the given field where the type of term value + * is determined dynamically ({@link #AUTO AUTO}). + * @param field Name of field to sort by, cannot be null. + */ + SortField::SortField (const TCHAR* field) { + this->type = AUTO; + this->reverse = false; + this->field = CLStringIntern::intern(field CL_FILELINE); + this->factory = NULL; + } + + /** Creates a sort, possibly in reverse, by terms in the given field where + * the type of term value is determined dynamically ({@link #AUTO AUTO}). + * @param field Name of field to sort by, cannot be null. + * @param reverse True if natural order should be reversed. + + SortField::SortField (const TCHAR* field, bool reverse) { + this->field = CLStringIntern::intern(field CL_FILELINE); + this->reverse = reverse; + this->type = AUTO; + this->factory = NULL; + }*/ + + + /** Creates a sort, possibly in reverse, by terms in the given field with the + * type of term values explicitly given. + * @param field Name of field to sort by. Can be null if + * type is SCORE or DOC. + * @param type Type of values in the terms. + * @param reverse True if natural order should be reversed (default=false). + */ + SortField::SortField (const TCHAR* field, int32_t type, bool reverse) { + this->field = (field != NULL) ? CLStringIntern::intern(field CL_FILELINE) : field; + this->type = type; + this->reverse = reverse; + this->factory = NULL; + } + + SortField::SortField(const SortField& clone){ + this->field = (clone.field != NULL) ? CLStringIntern::intern(clone.field CL_FILELINE) : clone.field; + this->type = clone.type; + this->reverse = clone.reverse; + this->factory = clone.factory; + } + SortField* SortField::clone() const{ + return _CLNEW SortField(*this); + } + + /** Creates a sort by terms in the given field sorted + * according to the given locale. + * @param field Name of field to sort by, cannot be null. + * @param locale Locale of values in the field. + */ + /*SortField::SortField (TCHAR* field, Locale* locale) { + this->field = (field != NULL) ? CLStringIntern::intern(field): field; + this->type = STRING; + this->locale = locale; + }*/ + + /** Creates a sort, possibly in reverse, by terms in the given field sorted + * according to the given locale. + * @param field Name of field to sort by, cannot be null. + * @param locale Locale of values in the field. + */ + /*SortField::SortField (TCHAR* field, Locale* locale, bool reverse) { + this->field = (field != NULL) ? CLStringIntern::intern(field): field; + this->type = STRING; + this->locale = locale; + this->reverse = reverse; + }*/ + + + /** Creates a sort, possibly in reverse, with a custom comparison function. + * @param field Name of field to sort by; cannot be null. + * @param comparator Returns a comparator for sorting hits. + * @param reverse True if natural order should be reversed (default=false). + */ + SortField::SortField (const TCHAR* field, SortComparatorSource* comparator, bool reverse) { + this->field = (field != NULL) ? CLStringIntern::intern(field CL_FILELINE): field; + this->type = CUSTOM; + this->reverse = reverse; + this->factory = comparator; + } + + SortField::~SortField(){ + CLStringIntern::unintern(field); + } + + TCHAR* SortField::toString() const { + CL_NS(util)::StringBuffer buffer; + switch (type) { + case DOCSCORE: buffer.append(_T("")); + break; + + case DOC: buffer.append(_T("")); + break; + + case CUSTOM: buffer.append (_T("getName()); + buffer.append(_T(">")); + break; + + default: buffer.append( _T("\"")); + buffer.append( field ); + buffer.append( _T("\"") ); + break; + } + + //if (locale != null) buffer.append ("("+locale+")"); todo: + if (reverse) buffer.appendChar('!'); + + return buffer.toString(); + } + + + + + + + + + + + + + + /** Sorts by computed relevance. This is the same sort criteria as + * calling {@link Searcher#search(Query) Searcher#search()} without a sort criteria, only with + * slightly more overhead. */ + Sort::Sort() { + fields=NULL; + SortField** fields=_CL_NEWARRAY(SortField*,3); + fields[0]=SortField::FIELD_SCORE; + fields[1]=SortField::FIELD_DOC; + fields[2]=NULL; + setSort (fields); + _CLDELETE_ARRAY(fields); + } + + Sort::~Sort(){ + clear(); + } + void Sort::clear(){ + if ( fields != NULL ){ + int32_t i=0; + while ( fields[i] != NULL ){ + if ( fields[i] != SortField::FIELD_SCORE && + fields[i] != SortField::FIELD_DOC ){ + _CLDELETE(fields[i]); + } + i++; + } + _CLDELETE_ARRAY(fields); + } + } + + /** Sorts possibly in reverse by the terms in field then by + * index order (document number). The type of value in field is determined + * automatically. + * @see SortField#AUTO + */ + Sort::Sort (const TCHAR* field, bool reverse) { + this->fields=NULL; + setSort (field, reverse); + } + + + /** Sorts in succession by the terms in each field. + * The type of value in field is determined + * automatically. + * @see SortField#AUTO + */ + Sort::Sort (const TCHAR** fields) { + this->fields=NULL; + setSort (fields); + } + + + /** Sorts by the criteria in the given SortField. */ + Sort::Sort (SortField* field) { + this->fields=NULL; + setSort (field); + } + + + /** Sorts in succession by the criteria in each SortField. */ + Sort::Sort (SortField** fields) { + this->fields=NULL; + setSort (fields); + } + + + /** Sets the sort to the terms in field possibly in reverse, + * then by index order (document number). */ + void Sort::setSort (const TCHAR* field, bool reverse) { + clear(); + fields = _CL_NEWARRAY(SortField*,3); + fields[0] = _CLNEW SortField (field, SortField::AUTO, reverse); + fields[1] = SortField::FIELD_DOC; + fields[2] = NULL; + } + + + /** Sets the sort to the terms in each field in succession. */ + void Sort::setSort (const TCHAR** fieldnames) { + clear(); + + int32_t n = 0; + while ( fieldnames[n] != NULL ) + n++; + + fields = _CL_NEWARRAY(SortField*,n+1); + for (int32_t i = 0; i < n; ++i) { + fields[i] = _CLNEW SortField (fieldnames[i], SortField::AUTO,false); + } + fields[n]=NULL; + } + + + /** Sets the sort to the given criteria. */ + void Sort::setSort (SortField* field) { + clear(); + + this->fields = _CL_NEWARRAY(SortField*,2); + this->fields[0] = field; + this->fields[1] = NULL; + } + + + /** Sets the sort to the given criteria in succession. */ + void Sort::setSort (SortField** fields) { + clear(); + + int n=0; + while ( fields[n] != NULL ) + n++; + this->fields = _CL_NEWARRAY(SortField*,n+1); + for (int i=0;ifields[i]=fields[i]; + } + + TCHAR* Sort::toString() const { + CL_NS(util)::StringBuffer buffer; + + int32_t i = 0; + while ( fields[i] != NULL ){ + if (i>0) + buffer.appendChar(','); + + const TCHAR* p = fields[i]->toString(); + buffer.append(p); + _CLDELETE_CARRAY(p); + + i++; + } + + return buffer.toString(); + } + + + + + + ScoreDocComparator* ScoreDocComparator::INDEXORDER = _CLNEW ScoreDocComparators::IndexOrder; + ScoreDocComparator* ScoreDocComparator::RELEVANCE = _CLNEW ScoreDocComparators::Relevance; + + ScoreDocComparator::~ScoreDocComparator(){ + } + + +class ScoreDocComparatorImpl: public ScoreDocComparator{ + Comparable** cachedValues; + FieldCacheAuto* fca; + int32_t cachedValuesLen; +public: + ScoreDocComparatorImpl(FieldCacheAuto* fca){ + this->fca = fca; + if ( fca->contentType != FieldCacheAuto::COMPARABLE_ARRAY ) + _CLTHROWA(CL_ERR_InvalidCast,"Invalid field cache auto type"); + this->cachedValues = fca->comparableArray; + this->cachedValuesLen = fca->contentLen; + } + ~ScoreDocComparatorImpl(){ + } + int32_t compare (struct ScoreDoc* i, struct ScoreDoc* j){ + CND_PRECONDITION(i->doc >= 0 && i->doc < cachedValuesLen, "i->doc out of range") + CND_PRECONDITION(j->doc >= 0 && j->doc < cachedValuesLen, "j->doc out of range") + return cachedValues[i->doc]->compareTo (cachedValues[j->doc]); + } + + CL_NS(util)::Comparable* sortValue (struct ScoreDoc* i){ + CND_PRECONDITION(i->doc >= 0 && i->doc < cachedValuesLen, "i->doc out of range") + return cachedValues[i->doc]; + } + + int32_t sortType(){ + return SortField::CUSTOM; + } +}; + +ScoreDocComparator* SortComparator::newComparator (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname){ + return _CLNEW ScoreDocComparatorImpl(FieldCache::DEFAULT->getCustom (reader, fieldname, this)); +} +SortComparator::SortComparator(){ +} +SortComparator::~SortComparator(){ +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/Sort.h b/3rdparty/clucene/src/CLucene/search/Sort.h new file mode 100644 index 0000000..cfe96d5 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/Sort.h @@ -0,0 +1,356 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_Sort_ +#define _lucene_search_Sort_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/IndexReader.h" +#include "SearchHeader.h" + +CL_NS_DEF(search) + + class SortField; //predefine + class Sort; + +/** + * Expert: Compares two ScoreDoc objects for sorting. + * + */ + class ScoreDocComparator:LUCENE_BASE { + protected: + ScoreDocComparator(){} + public: + virtual ~ScoreDocComparator(); +// CL_NS(util)::Comparable** cachedValues; +// ScoreDocComparator(CL_NS(util)::Comparable** cachedValues); + + /** + * Compares two ScoreDoc objects and returns a result indicating their + * sort order. + * @param i First ScoreDoc + * @param j Second ScoreDoc + * @return -1 if i should come before j
1 if i should come after j
0 if they are equal + * @see java.util.Comparator + */ + virtual int32_t compare (struct ScoreDoc* i, struct ScoreDoc* j) = 0; + + /** + * Returns the value used to sort the given document. The + * object returned must implement the java.io.Serializable + * interface. This is used by multisearchers to determine how to collate results from their searchers. + * @see FieldDoc + * @param i Document + * @return Serializable object + */ + virtual CL_NS(util)::Comparable* sortValue (struct ScoreDoc* i) = 0; + + + /** + * Returns the type of sort. Should return SortField.SCORE, SortField.DOC, SortField.STRING, SortField.INTEGER, + * SortField::FLOAT or SortField.CUSTOM. It is not valid to return SortField.AUTO. + * This is used by multisearchers to determine how to collate results from their searchers. + * @return One of the constants in SortField. + * @see SortField + */ + virtual int32_t sortType() = 0; + + /** Special comparator for sorting hits according to computed relevance (document score). */ + static ScoreDocComparator* RELEVANCE; + + /** Special comparator for sorting hits according to index order (document number). */ + static ScoreDocComparator* INDEXORDER; + }; + +/** + * Expert: returns a comparator for sorting ScoreDocs. + * + */ +class SortComparatorSource:LUCENE_BASE { +public: + virtual ~SortComparatorSource(){ + } + + /** + * return a reference to a string describing the name of the comparator + * this is used in the explanation + */ + virtual TCHAR* getName() = 0; + + virtual size_t hashCode() = 0; + + /** + * Creates a comparator for the field in the given index. + * @param reader Index to create comparator for. + * @param fieldname Field to create comparator for. + * @return Comparator of ScoreDoc objects. + * @throws IOException If an error occurs reading the index. + */ + virtual ScoreDocComparator* newComparator (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname) = 0; +}; + + +/** + * Abstract base class for sorting hits returned by a Query. + * + *

This class should only be used if the other SortField + * types (SCORE, DOC, STRING, INT, FLOAT) do not provide an + * adequate sorting. It maintains an internal cache of values which + * could be quite large. The cache is an array of Comparable, + * one for each document in the index. There is a distinct + * Comparable for each unique term in the field - if + * some documents have the same term in the field, the cache + * array will have entries which reference the same Comparable. + * + */ +class SortComparator: public SortComparatorSource { +public: + virtual ScoreDocComparator* newComparator (CL_NS(index)::IndexReader* reader, const TCHAR* fieldname); + + SortComparator(); + virtual ~SortComparator(); + + /** + * Returns an object which, when sorted according to natural order, + * will order the Term values in the correct order. + *

For example, if the Terms contained integer values, this method + * would return new Integer(termtext). Note that this + * might not always be the most efficient implementation - for this + * particular example, a better implementation might be to make a + * ScoreDocLookupComparator that uses an internal lookup table of int. + * @param termtext The textual value of the term. + * @return An object representing termtext that sorts + * according to the natural order of termtext. + * @see Comparable + * @see ScoreDocComparator + */ + virtual CL_NS(util)::Comparable* getComparable (const TCHAR* termtext) = 0; + +}; + + +/** + * Stores information about how to sort documents by terms in an individual + * field. Fields must be indexed in order to sort by them. + * + */ +class SortField:LUCENE_BASE { +private: + const TCHAR* field; + int32_t type; // defaults to determining type dynamically + //Locale* locale; // defaults to "natural order" (no Locale) + bool reverse; // defaults to natural order + SortComparatorSource* factory; + +protected: + SortField (const SortField& clone); +public: + virtual ~SortField(); + + /** Sort by document score (relevancy). Sort values are Float and higher + * values are at the front. + * PORTING: this is the same as SCORE in java, it had to be renamed because + * SCORE is a system macro on some platforms (AIX). + */ + LUCENE_STATIC_CONSTANT(int32_t, DOCSCORE=0); + + /** Sort by document number (index order). Sort values are Integer and lower + * values are at the front. */ + LUCENE_STATIC_CONSTANT(int32_t, DOC=1); + + /** Guess type of sort based on field contents. A regular expression is used + * to look at the first term indexed for the field and determine if it + * represents an integer number, a floating point number, or just arbitrary + * string characters. */ + LUCENE_STATIC_CONSTANT(int32_t, AUTO=2); + + /** Sort using term values as Strings. Sort values are String and lower + * values are at the front. */ + LUCENE_STATIC_CONSTANT(int32_t, STRING=3); + + /** Sort using term values as encoded Integers. Sort values are Integer and + * lower values are at the front. */ + LUCENE_STATIC_CONSTANT(int32_t, INT=4); + + /** Sort using term values as encoded Floats. Sort values are Float and + * lower values are at the front. */ + LUCENE_STATIC_CONSTANT(int32_t, FLOAT=5); + + /** Sort using a custom Comparator. Sort values are any Comparable and + * sorting is done according to natural order. */ + LUCENE_STATIC_CONSTANT(int32_t, CUSTOM=9); + + // IMPLEMENTATION NOTE: the FieldCache.STRING_INDEX is in the same "namespace" + // as the above static int values. Any new values must not have the same value + // as FieldCache.STRING_INDEX. + + /** Represents sorting by document score (relevancy). */ + static SortField* FIELD_SCORE; + + /** Represents sorting by document number (index order). */ + static SortField* FIELD_DOC; + + SortField (const TCHAR* field); + //SortField (const TCHAR* field, bool reverse); + //todo: we cannot make reverse use default field of =false. + //because bool and int are the same type in c, overloading is not possible + SortField (const TCHAR* field, int32_t type, bool reverse); + + /* + SortField (TCHAR* field, Locale* locale) { + SortField (TCHAR* field, Locale* locale, bool reverse);*/ + + SortField (const TCHAR* field, SortComparatorSource* comparator, bool reverse=false); + + /** Returns the name of the field. Could return null + * if the sort is by SCORE or DOC. + * @return Name of field, possibly null. + */ + const TCHAR* getField() const { return field; } + + SortField* clone() const; + + /** Returns the type of contents in the field. + * @return One of the constants SCORE, DOC, AUTO, STRING, INT or FLOAT. + */ + int32_t getType() const { return type; } + + /** Returns the Locale by which term values are interpreted. + * May return null if no Locale was specified. + * @return Locale, or null. + */ + /*Locale getLocale() { + return locale; + }*/ + + /** Returns whether the sort should be reversed. + * @return True if natural order should be reversed. + */ + bool getReverse() const { return reverse; } + + SortComparatorSource* getFactory() const { return factory; } + + TCHAR* toString() const; +}; + + + +/** + * Encapsulates sort criteria for returned hits. + * + *

The fields used to determine sort order must be carefully chosen. + * Documents must contain a single term in such a field, + * and the value of the term should indicate the document's relative position in + * a given sort order. The field must be indexed, but should not be tokenized, + * and does not need to be stored (unless you happen to want it back with the + * rest of your document data). In other words: + * + *

document.add (new Field ("byNumber", Integer.toString(x), false, true, false)); + *
+ * + *

Valid Types of Values

+ * + *

There are three possible kinds of term values which may be put into + * sorting fields: Integers, Floats, or Strings. Unless + * {@link SortField SortField} objects are specified, the type of value + * in the field is determined by parsing the first term in the field. + * + *

Integer term values should contain only digits and an optional + * preceeding negative sign. Values must be base 10 and in the range + * Integer.MIN_VALUE and Integer.MAX_VALUE inclusive. + * Documents which should appear first in the sort + * should have low value integers, later documents high values + * (i.e. the documents should be numbered 1..n where + * 1 is the first and n the last). + * + *

Float term values should conform to values accepted by + * {@link Float Float.valueOf(String)} (except that NaN + * and Infinity are not supported). + * Documents which should appear first in the sort + * should have low values, later documents high values. + * + *

String term values can contain any valid String, but should + * not be tokenized. The values are sorted according to their + * {@link Comparable natural order}. Note that using this type + * of term value has higher memory requirements than the other + * two types. + * + *

Object Reuse

+ * + *

One of these objects can be + * used multiple times and the sort order changed between usages. + * + *

This class is thread safe. + * + *

Memory Usage

+ * + *

Sorting uses of caches of term values maintained by the + * internal HitQueue(s). The cache is static and contains an integer + * or float array of length IndexReader.maxDoc() for each field + * name for which a sort is performed. In other words, the size of the + * cache in bytes is: + * + *

4 * IndexReader.maxDoc() * (# of different fields actually used to sort) + * + *

For String fields, the cache is larger: in addition to the + * above array, the value of every term in the field is kept in memory. + * If there are many unique terms in the field, this could + * be quite large. + * + *

Note that the size of the cache is not affected by how many + * fields are in the index and might be used to sort - only by + * the ones actually used to sort a result set. + * + *

The cache is cleared each time a new IndexReader is + * passed in, or if the value returned by maxDoc() + * changes for the current IndexReader. This class is not set up to + * be able to efficiently sort hits from more than one index + * simultaneously. + * + */ +class Sort:LUCENE_BASE { + // internal representation of the sort criteria + SortField** fields; + void clear(); +public: + ~Sort(); + + /** Represents sorting by computed relevance. Using this sort criteria + * returns the same results as calling {@link Searcher#search(Query) Searcher#search()} + * without a sort criteria, only with slightly more overhead. */ + static Sort* RELEVANCE; + + /** Represents sorting by index order. */ + static Sort* INDEXORDER; + + Sort(); + Sort (const TCHAR* field, bool reverse=false); + Sort (const TCHAR** fields); + Sort (SortField* field); + Sort (SortField** fields); + void setSort (const TCHAR* field, bool reverse=false); + void setSort (const TCHAR** fieldnames); + void setSort (SortField* field); + void setSort (SortField** fields); + + TCHAR* toString() const; + + /** + * Representation of the sort criteria. + * @return a pointer to the of SortField array used in this sort criteria + */ + SortField** getSort() const{ return fields; } +}; + + + + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/TermQuery.cpp b/3rdparty/clucene/src/CLucene/search/TermQuery.cpp new file mode 100644 index 0000000..a04c20f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/TermQuery.cpp @@ -0,0 +1,213 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "TermQuery.h" + +#include "SearchHeader.h" +#include "Scorer.h" +#include "CLucene/index/Term.h" +#include "TermScorer.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/StringBuffer.h" +#include "CLucene/index/Terms.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + + + /** Constructs a query for the term t. */ + TermQuery::TermQuery(Term* t): + term( _CL_POINTER(t) ) + { + } + TermQuery::TermQuery(const TermQuery& clone): + Query(clone){ + this->term=_CL_POINTER(clone.term); + } + TermQuery::~TermQuery(){ + _CLDECDELETE(term); + } + + Query* TermQuery::clone() const{ + return _CLNEW TermQuery(*this); + } + + const TCHAR* TermQuery::getClassName(){ + return _T("TermQuery"); + } + const TCHAR* TermQuery::getQueryName() const{ + return getClassName(); + } + size_t TermQuery::hashCode() const { + return Similarity::floatToByte(getBoost()) ^ term->hashCode(); + } + + + //added by search highlighter + Term* TermQuery::getTerm(bool pointer) const + { + if ( pointer ) + return _CL_POINTER(term); + else + return term; + } + + + /** Prints a user-readable version of this query. */ + TCHAR* TermQuery::toString(const TCHAR* field) const{ + CL_NS(util)::StringBuffer buffer; + if ( field==NULL || _tcscmp(term->field(),field)!= 0 ) { + buffer.append(term->field()); + buffer.append(_T(":")); + } + buffer.append(term->text()); + if (getBoost() != 1.0f) { + buffer.append(_T("^")); + buffer.appendFloat( getBoost(),1 ); + } + return buffer.toString(); + } + + /** Returns true iff o is equal to this. */ + bool TermQuery::equals(Query* other) const { + if (!(other->instanceOf(TermQuery::getClassName()))) + return false; + + TermQuery* tq = (TermQuery*)other; + return (this->getBoost() == tq->getBoost()) + && this->term->equals(tq->term); + } + + + TermQuery::TermWeight::TermWeight(Searcher* searcher, TermQuery* _this, Term* _term) { + this->_this = _this; + this->_term = _term; + this->searcher = searcher; + value=0; + idf=0; + queryNorm=0; + queryWeight=0; + } + TermQuery::TermWeight::~TermWeight(){ + } + + //return a *new* string describing this object + TCHAR* TermQuery::TermWeight::toString() { + int32_t size=_tcslen(_this->getQueryName()) + 10; + TCHAR* tmp = _CL_NEWARRAY(TCHAR, size);//_tcslen(weight()) + _sntprintf(tmp,size,_T("weight(%s)"),_this->getQueryName()); + return tmp; + } + + qreal TermQuery::TermWeight::sumOfSquaredWeights() { + idf = _this->getSimilarity(searcher)->idf(_term, searcher); // compute idf + queryWeight = idf * _this->getBoost(); // compute query weight + return queryWeight * queryWeight; // square it + } + + void TermQuery::TermWeight::normalize(qreal queryNorm) { + this->queryNorm = queryNorm; + queryWeight *= queryNorm; // normalize query weight + value = queryWeight * idf; // idf for document + } + + Scorer* TermQuery::TermWeight::scorer(IndexReader* reader) { + TermDocs* termDocs = reader->termDocs(_term); + + if (termDocs == NULL) + return NULL; + + return _CLNEW TermScorer(this, termDocs, _this->getSimilarity(searcher), + reader->norms(_term->field())); + } + + void TermQuery::TermWeight::explain(IndexReader* reader, int32_t doc, Explanation* result){ + TCHAR buf[LUCENE_SEARCH_EXPLANATION_DESC_LEN]; + TCHAR* tmp; + + tmp = getQuery()->toString(); + _sntprintf(buf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("weight(%s in %d), product of:"),tmp,doc); + _CLDELETE_CARRAY(tmp); + result->setDescription(buf); + + _sntprintf(buf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("idf(docFreq=%d)"), searcher->docFreq(_term) ); + Explanation* idfExpl = _CLNEW Explanation(idf, buf); + + // explain query weight + Explanation* queryExpl = _CLNEW Explanation(); + tmp = getQuery()->toString(); + _sntprintf(buf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("queryWeight(%s), product of:"), tmp); + _CLDELETE_CARRAY(tmp); + queryExpl->setDescription(buf); + + Explanation* boostExpl = _CLNEW Explanation(_this->getBoost(), _T("boost")); + if (_this->getBoost() != 1.0f) + queryExpl->addDetail(boostExpl); + else + _CLDELETE(boostExpl); + + queryExpl->addDetail(idfExpl->clone()); + + Explanation* queryNormExpl = _CLNEW Explanation(queryNorm,_T("queryNorm")); + queryExpl->addDetail(queryNormExpl); + + queryExpl->setValue(_this->getBoost()* // always 1.0 + idfExpl->getValue() * + queryNormExpl->getValue()); + + // explain field weight + const TCHAR* field = _term->field(); + Explanation* fieldExpl = _CLNEW Explanation(); + + tmp = _term->toString(); + _sntprintf(buf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("fieldWeight(%s in %d), product of:"),tmp,doc); + _CLDELETE_CARRAY(tmp); + fieldExpl->setDescription(buf); + + Scorer* sc = scorer(reader); + Explanation* tfExpl = _CLNEW Explanation; + sc->explain(doc, tfExpl); + _CLDELETE(sc); + fieldExpl->addDetail(tfExpl); + fieldExpl->addDetail(idfExpl); + + Explanation* fieldNormExpl = _CLNEW Explanation(); + uint8_t* fieldNorms = reader->norms(field); + qreal fieldNorm = + fieldNorms!=NULL ? Similarity::decodeNorm(fieldNorms[doc]) : 0.0f; + fieldNormExpl->setValue(fieldNorm); + + _sntprintf(buf,LUCENE_SEARCH_EXPLANATION_DESC_LEN, + _T("fieldNorm(field=%s, doc=%d)"),field,doc); + fieldNormExpl->setDescription(buf); + fieldExpl->addDetail(fieldNormExpl); + + fieldExpl->setValue(tfExpl->getValue() * + idfExpl->getValue() * + fieldNormExpl->getValue()); + + /*if (queryExpl->getValue() == 1.0f){ + _CLDELETE(result); + return fieldExpl; + }else{*/ + result->addDetail(queryExpl); + result->addDetail(fieldExpl); + + // combine them + result->setValue(queryExpl->getValue() * fieldExpl->getValue()); + //} + } + + Weight* TermQuery::_createWeight(Searcher* searcher) { + return _CLNEW TermWeight(searcher,this,term); + } +CL_NS_END + diff --git a/3rdparty/clucene/src/CLucene/search/TermQuery.h b/3rdparty/clucene/src/CLucene/search/TermQuery.h new file mode 100644 index 0000000..a7dd803 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/TermQuery.h @@ -0,0 +1,81 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_TermQuery_ +#define _lucene_search_TermQuery_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "SearchHeader.h" +#include "Scorer.h" +#include "CLucene/index/Term.h" +#include "TermScorer.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/StringBuffer.h" +#include "CLucene/index/Terms.h" + +CL_NS_DEF(search) + + + /** A Query that matches documents containing a term. + This may be combined with other terms with a {@link BooleanQuery}. + */ + class TermQuery: public Query { + private: + CL_NS(index)::Term* term; + + + class TermWeight: public Weight { + private: + Searcher* searcher; + qreal value; + qreal idf; + qreal queryNorm; + qreal queryWeight; + TermQuery* _this; + CL_NS(index)::Term* _term; + + public: + TermWeight(Searcher* searcher, TermQuery* _this, CL_NS(index)::Term* _term); + ~TermWeight(); + TCHAR* toString(); + Query* getQuery() { return (Query*)_this; } + qreal getValue() { return value; } + + qreal sumOfSquaredWeights(); + void normalize(qreal queryNorm); + Scorer* scorer(CL_NS(index)::IndexReader* reader); + void explain(CL_NS(index)::IndexReader* reader, int32_t doc, Explanation* ret); + }; + + protected: + Weight* _createWeight(Searcher* searcher); + TermQuery(const TermQuery& clone); + public: + // Constructs a query for the term t. + TermQuery(CL_NS(index)::Term* t); + ~TermQuery(); + + static const TCHAR* getClassName(); + const TCHAR* getQueryName() const; + + //added by search highlighter + CL_NS(index)::Term* getTerm(bool pointer=true) const; + + // Prints a user-readable version of this query. + TCHAR* toString(const TCHAR* field) const; + + bool equals(Query* other) const; + Query* clone() const; + + /** Returns a hash code value for this object.*/ + size_t hashCode() const; + }; +CL_NS_END +#endif + diff --git a/3rdparty/clucene/src/CLucene/search/TermScorer.cpp b/3rdparty/clucene/src/CLucene/search/TermScorer.cpp new file mode 100644 index 0000000..ddd7f74 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/TermScorer.cpp @@ -0,0 +1,120 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "TermScorer.h" + +#include "CLucene/index/Terms.h" +#include "TermQuery.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + + //TermScorer takes TermDocs and delets it when TermScorer is cleaned up + TermScorer::TermScorer(Weight* w, CL_NS(index)::TermDocs* td, + Similarity* similarity,uint8_t* _norms): + Scorer(similarity), + termDocs(td), + norms(_norms), + weight(w), + weightValue(w->getValue()), + _doc(0), + pointer(0), + pointerMax(0) + { + memset(docs,0,32*sizeof(int32_t)); + memset(freqs,0,32*sizeof(int32_t)); + + for (int32_t i = 0; i < LUCENE_SCORE_CACHE_SIZE; i++) + scoreCache[i] = getSimilarity()->tf(i) * weightValue; + } + + TermScorer::~TermScorer(){ + _CLDELETE(termDocs); + } + bool TermScorer::next(){ + pointer++; + if (pointer >= pointerMax) { + pointerMax = termDocs->read(docs, freqs, 32); // refill buffer + if (pointerMax != 0) { + pointer = 0; + } else { + termDocs->close(); // close stream + _doc = LUCENE_INT32_MAX_SHOULDBE; // set to sentinel value + return false; + } + } + _doc = docs[pointer]; + return true; + } + + bool TermScorer::skipTo(int32_t target) { + // first scan in cache + for (pointer++; pointer < pointerMax; pointer++) { + if (docs[pointer] >= target) { + _doc = docs[pointer]; + return true; + } + } + + // not found in cache, seek underlying stream + bool result = termDocs->skipTo(target); + if (result) { + pointerMax = 1; + pointer = 0; + docs[pointer] = _doc = termDocs->doc(); + freqs[pointer] = termDocs->freq(); + } else { + _doc = LUCENE_INT32_MAX_SHOULDBE; + } + return result; + } + + void TermScorer::explain(int32_t doc, Explanation* tfExplanation) { + TermQuery* query = (TermQuery*)weight->getQuery(); + int32_t tf = 0; + while (pointer < pointerMax) { + if (docs[pointer] == doc) + tf = freqs[pointer]; + pointer++; + } + if (tf == 0) { + while (termDocs->next()) { + if (termDocs->doc() == doc) { + tf = termDocs->freq(); + } + } + } + termDocs->close(); + tfExplanation->setValue(getSimilarity()->tf(tf)); + + TCHAR buf[LUCENE_SEARCH_EXPLANATION_DESC_LEN+1]; + TCHAR* termToString = query->getTerm(false)->toString(); + _sntprintf(buf,LUCENE_SEARCH_EXPLANATION_DESC_LEN,_T("tf(termFreq(%s)=%d)"), termToString, tf); + _CLDELETE_CARRAY(termToString); + tfExplanation->setDescription(buf); + } + + TCHAR* TermScorer::toString() { + TCHAR* wb = weight->toString(); + int32_t rl = _tcslen(wb) + 9; //9=_tcslen("scorer(" ")") + 1 + TCHAR* ret = _CL_NEWARRAY(TCHAR,rl); + _sntprintf(ret,rl,_T("scorer(%s)"), wb); + _CLDELETE_ARRAY(wb); + return ret; + } + + qreal TermScorer::score(){ + int32_t f = freqs[pointer]; + qreal raw = // compute tf(f)*weight + f < LUCENE_SCORE_CACHE_SIZE // check cache + ? scoreCache[f] // cache hit + : getSimilarity()->tf(f) * weightValue; // cache miss + + return raw * Similarity::decodeNorm(norms[_doc]); // normalize for field + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/TermScorer.h b/3rdparty/clucene/src/CLucene/search/TermScorer.h new file mode 100644 index 0000000..ccbf5f7 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/TermScorer.h @@ -0,0 +1,53 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_TermScorer_ +#define _lucene_search_TermScorer_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Scorer.h" +#include "CLucene/index/Terms.h" +#include "CLucene/search/Similarity.h" +#include "SearchHeader.h" + +CL_NS_DEF(search) + + class TermScorer: public Scorer { + private: + CL_NS(index)::TermDocs* termDocs; + uint8_t* norms; + Weight* weight; + const qreal weightValue; + int32_t _doc; + + int32_t docs[32]; // buffered doc numbers + int32_t freqs[32]; // buffered term freqs + int32_t pointer; + int32_t pointerMax; + + qreal scoreCache[LUCENE_SCORE_CACHE_SIZE]; + public: + + //TermScorer takes TermDocs and delets it when TermScorer is cleaned up + TermScorer(Weight* weight, CL_NS(index)::TermDocs* td, + Similarity* similarity, uint8_t* _norms); + + ~TermScorer(); + + int32_t doc() const { return _doc; } + + bool next(); + bool skipTo(int32_t target); + void explain(int32_t doc, Explanation* ret); + TCHAR* toString(); + + qreal score(); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/WildcardQuery.cpp b/3rdparty/clucene/src/CLucene/search/WildcardQuery.cpp new file mode 100644 index 0000000..9373cef --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/WildcardQuery.cpp @@ -0,0 +1,147 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "WildcardQuery.h" +#include "CLucene/util/BitSet.h" + +CL_NS_USE(index) +CL_NS_USE(util) +CL_NS_DEF(search) + + + WildcardQuery::WildcardQuery(Term* term): + MultiTermQuery( term ){ + //Func - Constructor + //Pre - term != NULL + //Post - Instance has been created + + } + + WildcardQuery::~WildcardQuery(){ + //Func - Destructor + //Pre - true + //Post - true + + } + + const TCHAR* WildcardQuery::getQueryName() const{ + //Func - Returns the string "WildcardQuery" + //Pre - true + //Post - The string "WildcardQuery" has been returned + return getClassName(); + } + + const TCHAR* WildcardQuery::getClassName(){ + return _T("WildcardQuery"); + } + + + FilteredTermEnum* WildcardQuery::getEnum(IndexReader* reader) { + return _CLNEW WildcardTermEnum(reader, getTerm(false)); + } + + WildcardQuery::WildcardQuery(const WildcardQuery& clone): + MultiTermQuery(clone) + { + } + + Query* WildcardQuery::clone() const{ + return _CLNEW WildcardQuery(*this); + } + size_t WildcardQuery::hashCode() const{ + //todo: we should give the query a seeding value... but + //need to do it for all hascode functions + return Similarity::floatToByte(getBoost()) ^ getTerm()->hashCode(); + } + bool WildcardQuery::equals(Query* other) const{ + if (!(other->instanceOf(WildcardQuery::getClassName()))) + return false; + + WildcardQuery* tq = (WildcardQuery*)other; + return (this->getBoost() == tq->getBoost()) + && getTerm()->equals(tq->getTerm()); + } + + + + + + + + + + + + +WildcardFilter::WildcardFilter( Term* term ) +{ + this->term = _CL_POINTER(term); +} + +WildcardFilter::~WildcardFilter() +{ + _CLDECDELETE(term); +} + +WildcardFilter::WildcardFilter( const WildcardFilter& copy ) : + term( _CL_POINTER(copy.term) ) +{ +} + +Filter* WildcardFilter::clone() const { + return _CLNEW WildcardFilter(*this ); +} + + +TCHAR* WildcardFilter::toString() +{ + //Instantiate a stringbuffer buffer to store the readable version temporarily + CL_NS(util)::StringBuffer buffer; + //check if field equal to the field of prefix + if( term->field() != NULL ) { + //Append the field of prefix to the buffer + buffer.append(term->field()); + //Append a colon + buffer.append(_T(":") ); + } + //Append the text of the prefix + buffer.append(term->text()); + + //Convert StringBuffer buffer to TCHAR block and return it + return buffer.toString(); +} + + +/** Returns a BitSet with true for documents which should be permitted in +search results, and false for those that should not. */ +BitSet* WildcardFilter::bits( IndexReader* reader ) +{ + BitSet* bts = _CLNEW BitSet( reader->maxDoc() ); + + WildcardTermEnum termEnum (reader, term); + if (termEnum.term(false) == NULL) + return bts; + + TermDocs* termDocs = reader->termDocs(); + try{ + do{ + termDocs->seek(&termEnum); + + while (termDocs->next()) { + bts->set(termDocs->doc()); + } + }while(termEnum.next()); + } _CLFINALLY( + termDocs->close(); + _CLDELETE(termDocs); + termEnum.close(); + ) + + return bts; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/WildcardQuery.h b/3rdparty/clucene/src/CLucene/search/WildcardQuery.h new file mode 100644 index 0000000..cfc38f6 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/WildcardQuery.h @@ -0,0 +1,69 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_WildcardQuery_ +#define _lucene_search_WildcardQuery_ +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/Term.h" +#include "MultiTermQuery.h" +#include "WildcardTermEnum.h" + +CL_NS_DEF(search) + + /** Implements the wildcard search query. Supported wildcards are *, which + * matches any character sequence (including the empty one), and ?, + * which matches any single character. Note this query can be slow, as it + * needs to iterate over all terms. In order to prevent extremely slow WildcardQueries, + * a Wildcard term must not start with one of the wildcards * or + * ?. + * + * @see WildcardTermEnum + */ + class WildcardQuery: public MultiTermQuery { + protected: + FilteredTermEnum* getEnum(CL_NS(index)::IndexReader* reader); + WildcardQuery(const WildcardQuery& clone); + public: + WildcardQuery(CL_NS(index)::Term* term); + ~WildcardQuery(); + + //Returns the string "WildcardQuery" + const TCHAR* getQueryName() const; + static const TCHAR* getClassName(); + + size_t hashCode() const; + bool equals(Query* other) const; + Query* clone() const; + }; + + + +class WildcardFilter: public Filter +{ +private: + CL_NS(index)::Term* term; +protected: + WildcardFilter( const WildcardFilter& copy ); + +public: + WildcardFilter(CL_NS(index)::Term* term); + ~WildcardFilter(); + + /** Returns a BitSet with true for documents which should be permitted in + search results, and false for those that should not. */ + CL_NS(util)::BitSet* bits( CL_NS(index)::IndexReader* reader ); + + Filter* clone() const; + TCHAR* toString(); +}; + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/search/WildcardTermEnum.cpp b/3rdparty/clucene/src/CLucene/search/WildcardTermEnum.cpp new file mode 100644 index 0000000..bed9e6e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/WildcardTermEnum.cpp @@ -0,0 +1,150 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "WildcardTermEnum.h" + +CL_NS_USE(index) +CL_NS_DEF(search) + + bool WildcardTermEnum::termCompare(Term* term) { + if ( term!=NULL && __term->field() == term->field() ) { + const TCHAR* searchText = term->text(); + const TCHAR* patternText = __term->text(); + if ( _tcsncmp( searchText, pre, preLen ) == 0 ){ + return wildcardEquals(patternText+preLen, __term->textLength()-preLen, 0, searchText, term->textLength(), preLen); + } + } + _endEnum = true; + return false; + } + + /** Creates new WildcardTermEnum */ + WildcardTermEnum::WildcardTermEnum(IndexReader* reader, Term* term): + FilteredTermEnum(), + __term(_CL_POINTER(term)), + fieldMatch(false), + _endEnum(false) + { + + pre = stringDuplicate(term->text()); + + const TCHAR* sidx = _tcschr( pre, LUCENE_WILDCARDTERMENUM_WILDCARD_STRING ); + const TCHAR* cidx = _tcschr( pre, LUCENE_WILDCARDTERMENUM_WILDCARD_CHAR ); + const TCHAR* tidx = sidx; + if (tidx == NULL) + tidx = cidx; + else if ( cidx && cidx > pre) + tidx = min(sidx, cidx); + CND_PRECONDITION(tidx != NULL, "tidx==NULL"); + int32_t idx = (int32_t)(tidx - pre); + preLen = idx; + CND_PRECONDITION(preLentextLength(), "preLen >= term->textLength()"); + pre[preLen]=0; //trim end + + Term* t = _CLNEW Term(__term, pre); + setEnum( reader->terms(t) ); + _CLDECDELETE(t); + } + + void WildcardTermEnum::close() + { + if ( __term != NULL ){ + FilteredTermEnum::close(); + + _CLDECDELETE(__term); + __term = NULL; + + _CLDELETE_CARRAY( pre ); + } + } + WildcardTermEnum::~WildcardTermEnum() { + close(); + } + + qreal WildcardTermEnum::difference() { + return 1.0f; + } + + bool WildcardTermEnum::endEnum() { + return _endEnum; + } + + bool WildcardTermEnum::wildcardEquals(const TCHAR* pattern, int32_t patternLen, int32_t patternIdx, const TCHAR* str, int32_t strLen, int32_t stringIdx) + { + for (int32_t p = patternIdx; ; ++p) + { + for (int32_t s = stringIdx; ; ++p, ++s) + { + // End of str yet? + bool sEnd = (s >= strLen); + // End of pattern yet? + bool pEnd = (p >= patternLen); + + // If we're looking at the end of the str... + if (sEnd) + { + // Assume the only thing left on the pattern is/are wildcards + bool justWildcardsLeft = true; + + // Current wildcard position + int32_t wildcardSearchPos = p; + // While we haven't found the end of the pattern, + // and haven't encountered any non-wildcard characters + while (wildcardSearchPos < patternLen && justWildcardsLeft) + { + // Check the character at the current position + TCHAR wildchar = pattern[wildcardSearchPos]; + // If it's not a wildcard character, then there is more + // pattern information after this/these wildcards. + + if (wildchar != LUCENE_WILDCARDTERMENUM_WILDCARD_CHAR && + wildchar != LUCENE_WILDCARDTERMENUM_WILDCARD_STRING){ + justWildcardsLeft = false; + }else{ + // to prevent "cat" matches "ca??" + if (wildchar == LUCENE_WILDCARDTERMENUM_WILDCARD_CHAR) + return false; + + wildcardSearchPos++; // Look at the next character + } + } + + // This was a prefix wildcard search, and we've matched, so + // return true. + if (justWildcardsLeft) + return true; + } + + // If we've gone past the end of the str, or the pattern, + // return false. + if (sEnd || pEnd) + break; + + // Match a single character, so continue. + if (pattern[p] == LUCENE_WILDCARDTERMENUM_WILDCARD_CHAR) + continue; + + if (pattern[p] == LUCENE_WILDCARDTERMENUM_WILDCARD_STRING) + { + // Look at the character beyond the '*'. + ++p; + // Examine the str, starting at the last character. + for (int32_t i = strLen; i >= s; --i) + { + if (wildcardEquals(pattern, patternLen, p, str, strLen, i)) + return true; + } + break; + } + if (pattern[p] != str[s]) + break; + } + return false; + } + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/search/WildcardTermEnum.h b/3rdparty/clucene/src/CLucene/search/WildcardTermEnum.h new file mode 100644 index 0000000..2a03735 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/search/WildcardTermEnum.h @@ -0,0 +1,67 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_search_WildcardTermEnum_ +#define _lucene_search_WildcardTermEnum_ +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/index/IndexReader.h" +#include "CLucene/index/Term.h" +#include "CLucene/index/Terms.h" +#include "FilteredTermEnum.h" + +CL_NS_DEF(search) + /** + * Subclass of FilteredTermEnum for enumerating all terms that match the + * specified wildcard filter term-> + *

+ * Term enumerations are always ordered by term->compareTo(). Each term in + * the enumeration is greater than all that precede it. + */ + class WildcardTermEnum: public FilteredTermEnum { + private: + CL_NS(index)::Term* __term; + TCHAR* pre; + int32_t preLen; + bool fieldMatch; + bool _endEnum; + + /******************************************** + * const TCHAR* equality with support for wildcards + ********************************************/ + + protected: + bool termCompare(CL_NS(index)::Term* term) ; + + public: + + /** + * Creates a new WildcardTermEnum. Passing in a + * {@link Term Term} that does not contain a + * LUCENE_WILDCARDTERMENUM_WILDCARD_STRING or + * LUCENE_WILDCARDTERMENUM_WILDCARD_CHAR will cause an exception to be thrown. + */ + WildcardTermEnum(CL_NS(index)::IndexReader* reader, CL_NS(index)::Term* term); + ~WildcardTermEnum(); + + qreal difference() ; + + bool endEnum() ; + + /** + * Determines if a word matches a wildcard pattern. + */ + static bool wildcardEquals(const TCHAR* pattern, int32_t patternLen, int32_t patternIdx, const TCHAR* str, int32_t strLen, int32_t stringIdx); + + void close(); + + const char* getObjectName(){ return WildcardTermEnum::getClassName(); } + static const char* getClassName(){ return "WildcardTermEnum"; } + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/store/Directory.h b/3rdparty/clucene/src/CLucene/store/Directory.h new file mode 100644 index 0000000..818bc7a --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/Directory.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#ifndef _lucene_store_Directory +#define _lucene_store_Directory + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Lock.h" +#include "CLucene/util/VoidList.h" +#include "CLucene/util/Misc.h" + +#include "IndexInput.h" +#include "IndexOutput.h" + +CL_NS_DEF(store) + +/** A Directory is a flat list of files. Files may be written once, when they +* are created. Once a file is created it may only be opened for read, or +* deleted. Random access is permitted both when reading and writing. +* +*

Direct i/o is not used directly, but rather all i/o is +* through this API. This permits things such as:

    +*
  • implementation of RAM-based indices; +*
  • implementation indices stored in a database, via a database; +*
  • implementation of an index as a single file; +*
+* +*/ +class Directory : LUCENE_REFBASE +{ +protected: + Directory() {} + // Removes an existing file in the directory. + virtual bool doDeleteFile(const QString& name) = 0; + +public: + DEFINE_MUTEX(THIS_LOCK) + + virtual ~Directory() {}; + + // Returns an array of strings, one for each file in the directory. + virtual QStringList list() const = 0; + + // Returns true iff a file with the given name exists. + virtual bool fileExists(const QString& name) const = 0; + + // Returns the time the named file was last modified. + virtual int64_t fileModified(const QString& name) const = 0; + + // Returns the length of a file in the directory. + virtual int64_t fileLength(const QString& name) const = 0; + + // Returns a stream reading an existing file. + virtual IndexInput* openInput(const QString& name) = 0; + virtual IndexInput* openInput(const QString& name, int32_t bufferSize) + { + // didnt overload bufferSize + return openInput(name); + } + + // Set the modified time of an existing file to now. + virtual void touchFile(const QString& name) = 0; + + // Removes an existing file in the directory. + virtual bool deleteFile(const QString& name, const bool throwError = true) { + bool ret = doDeleteFile(name); + if (!ret && throwError) { + char buffer[200]; + _snprintf(buffer, 200, "couldn't delete file %s", + name.toLocal8Bit().constData()); + _CLTHROWA(CL_ERR_IO, buffer); + } + return ret; + } + + // Renames an existing file in the directory. + // If a file already exists with the new name, then it is replaced. + virtual void renameFile(const QString& from, const QString& to) = 0; + + // Creates a new, empty file in the directory with the given name. + // Returns a stream writing this file. + virtual IndexOutput* createOutput(const QString& name) = 0; + + // Construct a {@link Lock}. + // @param name the name of the lock file + virtual LuceneLock* makeLock(const QString& name) = 0; + + // Closes the store. + virtual void close() = 0; + + virtual QString toString() const = 0; + + virtual QString getDirectoryType() const = 0; +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp b/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp new file mode 100644 index 0000000..5f96e91 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp @@ -0,0 +1,662 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#include +#include +#include +#include +#include + +#include "CLucene/StdHeader.h" +#include "FSDirectory.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/Misc.h" +#include "CLucene/debug/condition.h" + +CL_NS_DEF(store) +CL_NS_USE(util) + +bool FSDirectory::disableLocks = false; + +// This cache of directories ensures that there is a unique Directory instance +// per path, so that synchronization on the Directory can be used to synchronize +// access between readers and writers. +static CL_NS(util)::CLHashMap DIRECTORIES(false, false); + +// # pragma mark -- FSDirectory::FSLock + +FSDirectory::FSLock::FSLock(const QString& _lockDir, const QString& name) + : lockDir(_lockDir) + , lockFile(_lockDir + QDir::separator() + name) +{ +} + +FSDirectory::FSLock::~FSLock() +{ +} + +bool FSDirectory::FSLock::obtain() +{ + if (disableLocks) + return true; + + if (QFile::exists(lockFile)) + return false; + + QDir dir(lockDir); + if (!dir.exists()) { + if (!dir.mkpath(lockDir)) { + // 34: len of "Couldn't create lock directory: " + char* err = _CL_NEWARRAY( + char, 34 + strlen(lockDir.toLocal8Bit().constData()) + 1); + strcpy(err, "Couldn't create lock directory: "); + strcat(err, lockDir.toLocal8Bit().constData()); + _CLTHROWA_DEL(CL_ERR_IO, err); + } + } + + QFile file(lockFile); + return file.open(QIODevice::ReadWrite); +} + +void FSDirectory::FSLock::release() +{ + if (disableLocks) + return; + + QFile file(lockFile); + file.remove(); +} + +bool FSDirectory::FSLock::isLocked() +{ + if (disableLocks) + return false; + return QFile::exists(lockFile); +} + +QString FSDirectory::FSLock::toString() const +{ + QString ret(QLatin1String("Lock@")); + return ret.append(lockFile); +} + +// # pragma mark -- FSDirectory::FSIndexInput + +FSDirectory::FSIndexInput::FSIndexInput(const QString& path, int32_t bufferSize) + : BufferedIndexInput(bufferSize) +{ + CND_PRECONDITION(!path.isEmpty(), "path is NULL"); + + handle = _CLNEW SharedHandle(); + handle->fhandle.setFileName(path); + handle->fhandle.open(QIODevice::ReadOnly); + + if (handle->fhandle.error() != QFile::NoError) { + switch(handle->fhandle.error()) { + case 1: + _CLTHROWA(CL_ERR_IO, "An error occurred when reading from the file"); + break; + case 2: + _CLTHROWA(CL_ERR_IO, "An error occurred when writing to the file."); + break; + case 5: + _CLTHROWA(CL_ERR_IO, "The file could not be opened."); + break; + case 6: + _CLTHROWA(CL_ERR_IO, "The operation was aborted."); + break; + case 7: + _CLTHROWA(CL_ERR_IO, "A timeout occurred."); + break; + case 8: + _CLTHROWA(CL_ERR_IO, "An unspecified error occurred."); + break; + case 9: + _CLTHROWA(CL_ERR_IO, "The file could not be removed."); + break; + case 10: + _CLTHROWA(CL_ERR_IO, "The file could not be renamed."); + break; + case 11: + _CLTHROWA(CL_ERR_IO, "The position in the file could not be changed."); + break; + case 12: + _CLTHROWA(CL_ERR_IO, "The file could not be resized.e"); + break; + case 13: + _CLTHROWA(CL_ERR_IO, "The file could not be accessed."); + break; + case 14: + _CLTHROWA(CL_ERR_IO, "The file could not be copied."); + break; + case 4: + default: + _CLTHROWA(CL_ERR_IO, "A fatal error occurred."); + } + } + + //Store the file length + handle->_length = handle->fhandle.size(); + handle->_fpos = 0; + this->_pos = 0; +} + +FSDirectory::FSIndexInput::FSIndexInput(const FSIndexInput& other) + : BufferedIndexInput(other) +{ + if (other.handle == NULL) + _CLTHROWA(CL_ERR_NullPointer, "other handle is null"); + + SCOPED_LOCK_MUTEX(*other.handle->THIS_LOCK) + + _pos = other.handle->_fpos; + handle = _CL_POINTER(other.handle); +} + +FSDirectory::FSIndexInput::~FSIndexInput() +{ + FSIndexInput::close(); +} + +void FSDirectory::FSIndexInput::close() +{ + BufferedIndexInput::close(); +#ifdef _LUCENE_THREADMUTEX + if (handle != NULL) { + // Here we have a bit of a problem... We need to lock the handle to + // ensure that we can safely delete the handle... But if we delete the + // handle, then the scoped unlock, won't be able to unlock the mutex... + + // take a reference of the lock object... + _LUCENE_THREADMUTEX* mutex = handle->THIS_LOCK; + //lock the mutex + mutex->lock(); + + // determine if we are about to delete the handle... + bool doUnlock = (handle->__cl_refcount > 1); + // decdelete (deletes if refcount is down to 0) + _CLDECDELETE(handle); + + if (doUnlock) + mutex->unlock(); + else + delete mutex; + } +#else + _CLDECDELETE(handle); +#endif +} + +IndexInput* FSDirectory::FSIndexInput::clone() const +{ + return _CLNEW FSDirectory::FSIndexInput(*this); +} + +void FSDirectory::FSIndexInput::seekInternal(const int64_t position) +{ + CND_PRECONDITION(position >= 0 && position < handle->_length, + "Seeking out of range") + _pos = position; +} + +void FSDirectory::FSIndexInput::readInternal(uint8_t* b, const int32_t len) +{ + SCOPED_LOCK_MUTEX(*handle->THIS_LOCK) + + CND_PRECONDITION(handle != NULL, "shared file handle has closed"); + CND_PRECONDITION(handle->fhandle.isOpen(), "file is not open"); + + if (handle->_fpos != _pos) { + handle->fhandle.seek(_pos); + if (handle->fhandle.pos() != _pos) + _CLTHROWA( CL_ERR_IO, "File IO Seek error"); + handle->_fpos = _pos; + } + + bufferLength = (int32_t)handle->fhandle.read((char*)b, len); + if (bufferLength == 0) + _CLTHROWA(CL_ERR_IO, "read past EOF"); + + if (bufferLength == -1) + _CLTHROWA(CL_ERR_IO, "read error"); + + _pos += bufferLength; + handle->_fpos =_pos; +} + +// # pragma mark -- FSDirectory::FSIndexInput::SharedHandle + +FSDirectory::FSIndexInput::SharedHandle::SharedHandle() + : _fpos(0) + , _length(0) +{ +#ifdef _LUCENE_THREADMUTEX + THIS_LOCK = new _LUCENE_THREADMUTEX; +#endif +} + +FSDirectory::FSIndexInput::SharedHandle::~SharedHandle() +{ + if (fhandle.isOpen()) + fhandle.close(); +} + +// # pragma mark -- FSDirectory::FSIndexOutput + +FSDirectory::FSIndexOutput::FSIndexOutput(const QString& path) +{ + //O_BINARY - Opens file in binary (untranslated) mode + //O_CREAT - Creates and opens new file for writing. Has no effect if file specified by filename exists + //O_RANDOM - Specifies that caching is optimized for, but not restricted to, random access from disk. + //O_WRONLY - Opens file for writing only; + fhandle.setFileName(path); + fhandle.open(QIODevice::ReadWrite | QIODevice::Truncate); + + if (fhandle.error() != QFile::NoError) { + switch(fhandle.error()) { + case 1: + _CLTHROWA(CL_ERR_IO, "An error occurred when reading from the file"); + break; + case 2: + _CLTHROWA(CL_ERR_IO, "An error occurred when writing to the file."); + break; + case 5: + _CLTHROWA(CL_ERR_IO, "The file could not be opened."); + break; + case 6: + _CLTHROWA(CL_ERR_IO, "The operation was aborted."); + break; + case 7: + _CLTHROWA(CL_ERR_IO, "A timeout occurred."); + break; + case 8: + _CLTHROWA(CL_ERR_IO, "An unspecified error occurred."); + break; + case 9: + _CLTHROWA(CL_ERR_IO, "The file could not be removed."); + break; + case 10: + _CLTHROWA(CL_ERR_IO, "The file could not be renamed."); + break; + case 11: + _CLTHROWA(CL_ERR_IO, "The position in the file could not be changed."); + break; + case 12: + _CLTHROWA(CL_ERR_IO, "The file could not be resized.e"); + break; + case 13: + _CLTHROWA(CL_ERR_IO, "The file could not be accessed."); + break; + case 14: + _CLTHROWA(CL_ERR_IO, "The file could not be copied."); + break; + case 4: + default: + _CLTHROWA(CL_ERR_IO, "A fatal error occurred."); + } + } +} + +FSDirectory::FSIndexOutput::~FSIndexOutput() +{ + if (fhandle.isOpen()) { + try { + FSIndexOutput::close(); + } catch (CLuceneError& err) { + //ignore IO errors... + if (err.number() != CL_ERR_IO) + throw; + } + } +} + +void FSDirectory::FSIndexOutput::close() +{ + try { + BufferedIndexOutput::close(); + } catch (CLuceneError& err) { + //ignore IO errors... + if (err.number() != CL_ERR_IO) + throw; + } + fhandle.close(); +} + +int64_t FSDirectory::FSIndexOutput::length() +{ + CND_PRECONDITION(fhandle.isOpen(), "file is not open"); + return fhandle.size(); +} + +void FSDirectory::FSIndexOutput::seek(const int64_t pos) +{ + CND_PRECONDITION(fhandle.isOpen(), "file is not open"); + + BufferedIndexOutput::seek(pos); + fhandle.seek(pos); + if (fhandle.pos() != pos) + _CLTHROWA(CL_ERR_IO, "File IO Seek error"); +} + +void FSDirectory::FSIndexOutput::flushBuffer(const uint8_t* b, const int32_t size) +{ + CND_PRECONDITION(fhandle.isOpen(), "file is not open"); + + if (size > 0 && fhandle.write((const char*)b, size) != size) + _CLTHROWA(CL_ERR_IO, "File IO Write error"); +} + +// # pragma mark -- FSDirectory + +FSDirectory::FSDirectory(const QString& path, const bool createDir) + : Directory() + , refCount(0) + , useMMap(false) +{ + //set a realpath so that if we change directory, we can still function + directory = QFileInfo(path).absoluteFilePath(); + lockDir = directory; + + QDir dir(lockDir); + if (!dir.exists()) { + if (!dir.mkpath(lockDir)) + _CLTHROWA_DEL(CL_ERR_IO, "Cannot create temp directory"); + } + + QFileInfo info(lockDir); + if (info.isFile() || info.isSymLink()) + _CLTHROWA(CL_ERR_IO, "Found regular file where directory expected"); + + if (createDir) + create(); + + dir.setPath(directory); + if (!dir.exists()) { + //19: len of " is not a directory" + char* err = + _CL_NEWARRAY(char, 19 + strlen(path.toLocal8Bit().constData()) + 1); + strcpy(err, path.toLocal8Bit().constData()); + strcat(err, " is not a directory"); + _CLTHROWA_DEL(CL_ERR_IO, err); + } +} + +void FSDirectory::create() +{ + SCOPED_LOCK_MUTEX(THIS_LOCK) + + bool clear = false; + QDir dir(directory); + if (!dir.exists()) { + if (!dir.mkpath(directory)) { + char* err = _CL_NEWARRAY( // 27 len of "Couldn't create directory:" + char, 27 + strlen(directory.toLocal8Bit().constData()) + 1); + strcpy(err, "Couldn't create directory: "); + strcat(err, directory.toLocal8Bit().constData()); + _CLTHROWA_DEL(CL_ERR_IO, err); + } + } else { + clear = true; + } + + QFileInfo info(directory); + if (info.isFile() || info.isSymLink()) { + char tmp[1024]; + _snprintf(tmp, 1024, "%s not a directory", + directory.toLocal8Bit().constData()); + _CLTHROWA(CL_ERR_IO, tmp); + } + + if (clear) { + dir.setPath(directory); + // clear probably existing lucene index files + QStringList fileList = dir.entryList(QDir::Files | QDir::Hidden + | QDir::NoSymLinks); + foreach(const QString file, fileList) { + if (CL_NS(index)::IndexReader::isLuceneFile(file)) { + if (!dir.remove(file)) + _CLTHROWA(CL_ERR_IO, "Couldn't delete file "); + } + } + + // clear probably existing file locks + QFileInfo dirInfo(lockDir); + if (dirInfo.exists() && dirInfo.isReadable() && dirInfo.isWritable() + && !dirInfo.isFile() && !dirInfo.isSymLink()) { + QDir lockDirectory(lockDir); + fileList = dir.entryList(QStringList() << getLockPrefix() + + QLatin1Char('*'), QDir::Files | QDir::Hidden | QDir::NoSymLinks); + + foreach(const QString file, fileList) { + if (!lockDirectory.remove(file)) + _CLTHROWA(CL_ERR_IO, "Couldn't delete file "); + } + } + else { + //todo: richer error: + lockDir.getAbsolutePath()); + _CLTHROWA(CL_ERR_IO, "Cannot read lock directory"); + } + } +} + +void FSDirectory::priv_getFN(QString& buffer, const QString& name) const +{ + buffer.clear(); + buffer.append(directory); + buffer.append(QDir::separator()); + buffer.append(name); +} + +FSDirectory::~FSDirectory() +{ +} + +QStringList FSDirectory::list() const +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QDir dir(directory); + return dir.entryList(QDir::Files | QDir::Hidden); +} + +bool FSDirectory::fileExists(const QString& name) const +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QDir dir(directory); + return dir.entryList().contains(name); +} + +QString FSDirectory::getDirName() const +{ + return directory; +} + +//static +FSDirectory* FSDirectory::getDirectory(const QString& file, const bool _create) +{ + FSDirectory* dir = NULL; + { + if (file.isEmpty()) + _CLTHROWA(CL_ERR_IO, "Invalid directory"); + + SCOPED_LOCK_MUTEX(DIRECTORIES.THIS_LOCK) + dir = DIRECTORIES.get(file); + if ( dir == NULL ){ + dir = _CLNEW FSDirectory(file, _create); + DIRECTORIES.put(dir->directory, dir); + } else if (_create) { + dir->create(); + } + + { + SCOPED_LOCK_MUTEX(dir->THIS_LOCK) + dir->refCount++; + } + } + + return _CL_POINTER(dir); +} + +int64_t FSDirectory::fileModified(const QString& name) const +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QFileInfo fInfo(directory + QDir::separator() + name); + return fInfo.lastModified().toTime_t(); +} + +//static +int64_t FSDirectory::fileModified(const QString& dir, const QString& name) +{ + QFileInfo fInfo(dir + QDir::separator() + name); + return fInfo.lastModified().toTime_t(); +} + +void FSDirectory::touchFile(const QString& name) +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QFile file(directory + QDir::separator() + name); + if (!file.open(QIODevice::ReadWrite)) + _CLTHROWA(CL_ERR_IO, "IO Error while touching file"); +} + +int64_t FSDirectory::fileLength(const QString& name) const +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QFileInfo fInfo(directory + QDir::separator() + name); + return fInfo.size(); +} + +IndexInput* FSDirectory::openInput(const QString& name) +{ + return openInput(name, CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE); +} + +IndexInput* FSDirectory::openInput(const QString& name, int32_t bufferSize ) +{ + CND_PRECONDITION(directory[0]!=0,"directory is not open") + + return _CLNEW FSIndexInput(directory + QDir::separator() + name, bufferSize); +} + +void FSDirectory::close() +{ + SCOPED_LOCK_MUTEX(DIRECTORIES.THIS_LOCK) + { + SCOPED_LOCK_MUTEX(THIS_LOCK) + + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + //refcount starts at 1 + if (--refCount <= 0) { + Directory* dir = DIRECTORIES.get(getDirName()); + if (dir) { + //this will be removed in ~FSDirectory + DIRECTORIES.remove(getDirName()); + _CLDECDELETE(dir); + } + } + } +} + +QString FSDirectory::getLockPrefix() const +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QString dirName(QFileInfo(directory).absoluteFilePath()); + if (dirName.isEmpty()) + _CLTHROWA(CL_ERR_Runtime, "Invalid directory path"); + + // to be compatible with jlucene, + // we need to make some changes ... + if (dirName.at(1) == QLatin1Char(':')) + dirName[0] = dirName.at(0).toUpper(); + + TCHAR tBuffer[2048] = { 0 }; + dirName.toWCharArray(tBuffer); + + char aBuffer[4096] = { 0 }; + STRCPY_TtoA(aBuffer, tBuffer, 4096); + + QString string(QLatin1String("lucene-")); + QByteArray hash(QCryptographicHash::hash(aBuffer, QCryptographicHash::Md5)); + + // TODO: verify this !!! + return string.append(QLatin1String(hash.toHex().constData())); +} + +bool FSDirectory::doDeleteFile(const QString& name) +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QDir dir(directory); + return dir.remove(name); +} + +void FSDirectory::renameFile(const QString& from, const QString& to) +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + SCOPED_LOCK_MUTEX(THIS_LOCK) + + if (fileExists(to)) + deleteFile(to, false); + + QFile file(directory + QDir::separator() + from); + QString newFile(directory + QDir::separator() + to); + if (!file.rename(newFile)) { + // try a second time if we fail + if (fileExists(to)) + deleteFile(to, false); + + if (!file.rename(newFile)) { + QString error(QLatin1String("Could not rename: %1 to %2!!!!")); + error.arg(from).arg(newFile); + QByteArray bArray(error.toLocal8Bit()); + _CLTHROWA(CL_ERR_IO, bArray.constData()); + } + } +} + +IndexOutput* FSDirectory::createOutput(const QString& name) +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + QString file = directory + QDir::separator() + name; + if (QFileInfo(file).exists()) { + if (!QFile::remove(file)) { + QByteArray bArray("Cannot overwrite: "); + bArray.append(name.toLocal8Bit()); + _CLTHROWA(CL_ERR_IO, bArray.constData()); + } + } + return _CLNEW FSIndexOutput(file); +} + +LuceneLock* FSDirectory::makeLock(const QString& name) +{ + CND_PRECONDITION(!directory.isEmpty(), "directory is not open"); + + + QString lockFile(getLockPrefix()); + lockFile.append(QLatin1Char('-')).append(name); + + return _CLNEW FSLock(lockDir, lockFile); +} + +QString FSDirectory::toString() const +{ + return QString::fromLatin1("FSDirectory@").append(directory); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/store/FSDirectory.h b/3rdparty/clucene/src/CLucene/store/FSDirectory.h new file mode 100644 index 0000000..e967380 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/FSDirectory.h @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#ifndef _lucene_store_FSDirectory_ +#define _lucene_store_FSDirectory_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include +#include + +#include "Directory.h" +#include "Lock.h" +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/StringBuffer.h" + +CL_NS_DEF(store) + +/** +* Straightforward implementation of {@link Directory} as a directory of files. +*

If the system property 'disableLuceneLocks' has the String value of +* "true", lock creation will be disabled. +* +* @see Directory +*/ +class FSDirectory : public Directory +{ +public: + // Destructor - only call this if you are sure the directory + // is not being used anymore. Otherwise use the ref-counting + // facilities of _CLDECDELETE + ~FSDirectory(); + + // Get a list of strings, one for each file in the directory. + QStringList list() const; + + // Returns true iff a file with the given name exists. + bool fileExists(const QString& name) const; + + // Returns the text name of the directory + QString getDirName() const; ///Directories are cached, so that, for a given canonical path, the same + FSDirectory instance will always be returned. This permits + synchronization on directories. + + @param file the path to the directory. + @param create if true, create, or erase any existing contents. + @return the FSDirectory for the named file. + */ + static FSDirectory* getDirectory(const QString& file, const bool create); + + // Returns the time the named file was last modified. + int64_t fileModified(const QString& name) const; + + //static + // Returns the time the named file was last modified. + static int64_t fileModified(const QString& dir, const QString& name); + + // static + // Returns the length in bytes of a file in the directory. + int64_t fileLength(const QString& name) const; + + // Returns a stream reading an existing file. + IndexInput* openInput(const QString& name); + IndexInput* openInput(const QString& name, int32_t bufferSize); + + // Renames an existing file in the directory. + void renameFile(const QString& from, const QString& to); + + // Set the modified time of an existing file to now. + void touchFile(const QString& name); + + // Creates a new, empty file in the directory with the given name. + // Returns a stream writing this file. + IndexOutput* createOutput(const QString& name); + + // Construct a {@link Lock}. + // @param name the name of the lock file + LuceneLock* makeLock(const QString& name); + + // Decrease the ref-count to the directory by one. If the object is no + // longer needed, then the object is removed from the directory pool. + void close(); + + // If MMap is available, this can disable use of mmap reading. + void setUseMMap(bool value) { useMMap = value; } + + // Gets whether the directory is using MMap for inputstreams. + bool getUseMMap() const { return useMMap; } + + QString toString() const; + + static QString DirectoryType() { return QLatin1String("FS"); } + QString getDirectoryType() const { return QLatin1String("FS"); } + + // Set whether Lucene's use of lock files is disabled. By default, + // lock files are enabled. They should only be disabled if the index + // is on a read-only medium like a CD-ROM. + static void setDisableLocks(bool doDisableLocks) + { disableLocks = doDisableLocks; } + + // Returns whether Lucene's use of lock files is disabled. + // @return true if locks are disabled, false if locks are enabled. + static bool getDisableLocks() { return disableLocks; } + +protected: + FSDirectory(const QString& path, const bool createDir); + // Removes an existing file in the directory. + bool doDeleteFile(const QString& name); + +private: + class FSLock : public LuceneLock { + public: + FSLock (const QString& lockDir, const QString& name); + ~FSLock(); + + bool obtain(); + void release(); + bool isLocked(); + QString toString() const; + + QString lockDir; + QString lockFile; + }; + friend class FSDirectory::FSLock; + + class FSIndexInput : public BufferedIndexInput { + public: + FSIndexInput(const QString& path, int32_t bufferSize = + CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE); + ~FSIndexInput(); + + void close(); + IndexInput* clone() const; + + int64_t length() + { return handle->_length; } + + QString getDirectoryType() const + { return FSDirectory::DirectoryType(); } + + protected: + FSIndexInput(const FSIndexInput& clone); + // Random-access methods + void seekInternal(const int64_t position); + // IndexInput methods + void readInternal(uint8_t* b, const int32_t len); + + private: + // We used a shared handle between all the fsindexinput clones. + // This reduces number of file handles we need, and it means + // we dont have to use file tell (which is slow) before doing a read. + class SharedHandle : LUCENE_REFBASE { + public: + SharedHandle(); + ~SharedHandle(); + + int64_t _fpos; + int64_t _length; + + QFile fhandle; + DEFINE_MUTEX(*THIS_LOCK) + }; + SharedHandle* handle; + int64_t _pos; + }; + friend class FSDirectory::FSIndexInput; + + class FSIndexOutput : public BufferedIndexOutput { + public: + FSIndexOutput(const QString& path); + ~FSIndexOutput(); + + void close(); + int64_t length(); + void seek(const int64_t pos); + + protected: + void flushBuffer(const uint8_t* b, const int32_t size); + + private: + QFile fhandle; + }; + friend class FSDirectory::FSIndexOutput; + +private: + QString directory; + int refCount; + void create(); + + QString lockDir; + QString getLockPrefix() const; + static bool disableLocks; + + void priv_getFN(QString& buffer, const QString& name) const; + bool useMMap; +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/store/IndexInput.cpp b/3rdparty/clucene/src/CLucene/store/IndexInput.cpp new file mode 100644 index 0000000..cf7bd16 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/IndexInput.cpp @@ -0,0 +1,233 @@ + /*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "IndexInput.h" + +CL_NS_USE(util) +CL_NS_DEF(store) + + IndexInput::IndexInput() + { + } + IndexInput::IndexInput(const IndexInput& other) + { + } + + int32_t IndexInput::readInt() { + int32_t b = (readByte() << 24); + b |= (readByte() << 16); + b |= (readByte() << 8); + return (b | readByte()); + } + + int32_t IndexInput::readVInt() { + uint8_t b = readByte(); + int32_t i = b & 0x7F; + for (int32_t shift = 7; (b & 0x80) != 0; shift += 7) { + b = readByte(); + i |= (b & 0x7F) << shift; + } + return i; + } + + int64_t IndexInput::readLong() { + int64_t i = ((int64_t)readInt() << 32); + return (i | ((int64_t)readInt() & 0xFFFFFFFFL)); + } + + int64_t IndexInput::readVLong() { + uint8_t b = readByte(); + int64_t i = b & 0x7F; + for (int32_t shift = 7; (b & 0x80) != 0; shift += 7) { + b = readByte(); + i |= (((int64_t)b) & 0x7FL) << shift; + } + return i; + } + + void IndexInput::skipChars( const int32_t count) { + for (int32_t i = 0; i < count; i++) { + TCHAR b = readByte(); + if ((b & 0x80) == 0) { + // Do Nothing. + } else if ((b & 0xE0) != 0xE0) { + readByte(); + } else { + readByte(); + readByte(); + } + } + } + + int32_t IndexInput::readString(TCHAR* buffer, const int32_t maxLength){ + int32_t len = readVInt(); + int32_t ml=maxLength-1; + if ( len >= ml ){ + readChars(buffer, 0, ml); + buffer[ml] = 0; + //we have to finish reading all the data for this string! + if ( len-ml > 0 ){ + //seek(getFilePointer()+(len-ml)); <- that was the wrong way to "finish reading" + skipChars(len-ml); + } + return ml; + }else{ + readChars(buffer, 0, len); + buffer[len] = 0; + return len; + } + } + + TCHAR* IndexInput::readString(const bool _unique){ + int32_t len = readVInt(); + + if ( len == 0){ + if ( _unique ) //todo: does non unique ever occur? + return stringDuplicate(LUCENE_BLANK_STRING); + else + return LUCENE_BLANK_STRING; + } + + TCHAR* ret = _CL_NEWARRAY(TCHAR,len+1); + readChars(ret, 0, len); + ret[len] = 0; + + return ret; + } + + void IndexInput::readChars( TCHAR* buffer, const int32_t start, const int32_t len) { + const int32_t end = start + len; + TCHAR b; + for (int32_t i = start; i < end; ++i) { + b = readByte(); + if ((b & 0x80) == 0) { + b = (b & 0x7F); + } else if ((b & 0xE0) != 0xE0) { + b = (((b & 0x1F) << 6) + | (readByte() & 0x3F)); + } else { + b = ((b & 0x0F) << 12) | ((readByte() & 0x3F) << 6); + b |= (readByte() & 0x3F); + } + buffer[i] = b; + } + } + + + + + + +BufferedIndexInput::BufferedIndexInput(int32_t _bufferSize): + buffer(NULL), + bufferSize(_bufferSize), + bufferStart(0), + bufferLength(0), + bufferPosition(0) + { + } + + BufferedIndexInput::BufferedIndexInput(const BufferedIndexInput& other): + IndexInput(other), + buffer(NULL), + bufferSize(other.bufferSize), + bufferStart(other.bufferStart), + bufferLength(other.bufferLength), + bufferPosition(other.bufferPosition) + { + /* DSR: Does the fact that sometime clone.buffer is not NULL even when + ** clone.bufferLength is zero indicate memory corruption/leakage? + ** if ( clone.buffer != NULL) { */ + if (other.bufferLength != 0 && other.buffer != NULL) { + buffer = _CL_NEWARRAY(uint8_t,bufferLength); + memcpy(buffer,other.buffer,bufferLength * sizeof(uint8_t)); + } + } + + void BufferedIndexInput::readBytes(uint8_t* b, const int32_t len){ + if (len < bufferSize) { + for (int32_t i = 0; i < len; ++i) // read byte-by-byte + b[i] = readByte(); + } else { // read all-at-once + int64_t start = getFilePointer(); + seekInternal(start); + readInternal(b, len); + + bufferStart = start + len; // adjust stream variables + bufferPosition = 0; + bufferLength = 0; // trigger refill() on read + } + } + + int64_t BufferedIndexInput::getFilePointer() const{ + return bufferStart + bufferPosition; + } + + void BufferedIndexInput::seek(const int64_t pos) { + if ( pos < 0 ) + _CLTHROWA(CL_ERR_IO, "IO Argument Error. Value must be a positive value."); + if (pos >= bufferStart && pos < (bufferStart + bufferLength)) + bufferPosition = (int32_t)(pos - bufferStart); // seek within buffer + else { + bufferStart = pos; + bufferPosition = 0; + bufferLength = 0; // trigger refill() on read() + seekInternal(pos); + } + } + void BufferedIndexInput::close(){ + _CLDELETE_ARRAY(buffer); + bufferLength = 0; + bufferPosition = 0; + bufferStart = 0; + } + + + BufferedIndexInput::~BufferedIndexInput(){ + BufferedIndexInput::close(); + } + + void BufferedIndexInput::refill() { + int64_t start = bufferStart + bufferPosition; + int64_t end = start + bufferSize; + if (end > length()) // don't read past EOF + end = length(); + bufferLength = (int32_t)(end - start); + if (bufferLength == 0) + _CLTHROWA(CL_ERR_IO, "IndexInput read past EOF"); + + if (buffer == NULL){ + buffer = _CL_NEWARRAY(uint8_t,bufferSize); // allocate buffer lazily + } + readInternal(buffer, bufferLength); + + + bufferStart = start; + bufferPosition = 0; + } + + +IndexInputStream::IndexInputStream(IndexInput* input){ + this->input = input; + this->size = input->length(); + this->position = input->getFilePointer(); +} +IndexInputStream::~IndexInputStream(){ +} +int32_t IndexInputStream::fillBuffer(char* start, int32_t space){ + int64_t avail = input->length()-input->getFilePointer(); + if ( avail == 0 ) + return -1; + else if ( availreadBytes((uint8_t*)start,space); + return space; +} + +CL_NS_END + diff --git a/3rdparty/clucene/src/CLucene/store/IndexInput.h b/3rdparty/clucene/src/CLucene/store/IndexInput.h new file mode 100644 index 0000000..9453b5c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/IndexInput.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_store_IndexInput_ +#define _lucene_store_IndexInput_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/util/bufferedstream.h" +#include "IndexOutput.h" + +CL_NS_DEF(store) + + /** Abstract base class for input from a file in a {@link Directory}. A + * random-access input stream. Used for all Lucene index input operations. + * @see Directory + * @see IndexOutput + */ + class IndexInput: LUCENE_BASE { + private: + void skipChars( const int32_t count); + protected: + IndexInput(); + IndexInput(const IndexInput& clone); + public: + virtual ~IndexInput(){} + virtual IndexInput* clone() const =0; + + DEFINE_MUTEX(THIS_LOCK) + + /** Reads and returns a single byte. + * @see IndexOutput#writeByte(byte) + */ + virtual uint8_t readByte() =0; + + /** Reads a specified number of bytes into an array at the specified offset. + * @param b the array to read bytes into + * @param offset the offset in the array to start storing bytes + * @param len the number of bytes to read + * @see IndexOutput#writeBytes(byte[],int32_t) + */ + virtual void readBytes(uint8_t* b, const int32_t len) =0; + + /** Reads four bytes and returns an int. + * @see IndexOutput#writeInt(int32_t) + */ + int32_t readInt(); + + /** Reads an int stored in variable-length format. Reads between one and + * five bytes. Smaller values take fewer bytes. Negative numbers are not + * supported. + * @see IndexOutput#writeVInt(int32_t) + */ + virtual int32_t readVInt(); + + /** Reads eight bytes and returns a long. + * @see IndexOutput#writeLong(long) + */ + int64_t readLong(); + + /** Reads a long stored in variable-length format. Reads between one and + * nine bytes. Smaller values take fewer bytes. Negative numbers are not + * supported. */ + int64_t readVLong(); + + /** Reads a string. + * @see IndexOutput#writeString(String) + * maxLength is the amount read into the buffer, the whole string is still read from the stream + * returns the amount read + */ + int32_t readString(TCHAR* buffer, const int32_t maxlength); + + /** Reads a string. + * @see IndexOutput#writeString(String) + * If unique is true (default) the string will be duplicated. + * If false and the length is zero, LUCENE_BLANK_STRING is returned + */ + TCHAR* readString(const bool unique=true); + + + /** Reads UTF-8 encoded characters into an array. + * @param buffer the array to read characters into + * @param start the offset in the array to start storing characters + * @param length the number of characters to read + * @see IndexOutput#writeChars(String,int32_t,int32_t) + */ + void readChars( TCHAR* buffer, const int32_t start, const int32_t len); + + /** Closes the stream to futher operations. */ + virtual void close() =0; + + /** Returns the current position in this file, where the next read will + * occur. + * @see #seek(long) + */ + virtual int64_t getFilePointer() const =0; + + /** Sets current position in this file, where the next read will occur. + * @see #getFilePointer() + */ + virtual void seek(const int64_t pos) =0; + + /** The number of bytes in the file. */ + virtual int64_t length() = 0; + + virtual QString getDirectoryType() const = 0; + }; + + /** Abstract base class for input from a file in a {@link Directory}. A + * random-access input stream. Used for all Lucene index input operations. + * @see Directory + * @see IndexOutput + */ + class BufferedIndexInput: public IndexInput{ + private: + uint8_t* buffer; //array of bytes + void refill(); + protected: + int32_t bufferSize; //size of the buffer + int64_t bufferStart; // position in file of buffer + int32_t bufferLength; // end of valid l_byte_ts + int32_t bufferPosition; // next uint8_t to read + + /** Returns a clone of this stream. + * + *

Clones of a stream access the same data, and are positioned at the same + * point as the stream they were cloned from. + * + *

Expert: Subclasses must ensure that clones may be positioned at + * different points in the input from each other and from the stream they + * were cloned from. + */ + BufferedIndexInput(const BufferedIndexInput& clone); + BufferedIndexInput(int32_t bufferSize = CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE); + public: + + virtual ~BufferedIndexInput(); + virtual IndexInput* clone() const = 0; + void close(); + inline uint8_t readByte(){ + if (bufferPosition >= bufferLength) + refill(); + + return buffer[bufferPosition++]; + } + void readBytes(uint8_t* b, const int32_t len); + int64_t getFilePointer() const; + void seek(const int64_t pos); + + protected: + /** Expert: implements buffer refill. Reads bytes from the current position + * in the input. + * @param b the array to read bytes into + * @param offset the offset in the array to start storing bytes + * @param length the number of bytes to read + */ + virtual void readInternal(uint8_t* b, const int32_t len) = 0; + + /** Expert: implements seek. Sets current position in this file, where the + * next {@link #readInternal(byte[],int32_t,int32_t)} will occur. + * @see #readInternal(byte[],int32_t,int32_t) + */ + virtual void seekInternal(const int64_t pos) = 0; + }; + + /** + * JStream InputStream which reads from an IndexInput. This class is + * used by the FieldReader to create binary fields. You can then use + * a GZipInputStream to read compressed data or any of the other + * JStream stream types. + * + */ + class IndexInputStream: public jstreams::BufferedInputStream{ + IndexInput* input; + public: + IndexInputStream(IndexInput* input); + ~IndexInputStream(); + int32_t fillBuffer(char* start, int32_t space); + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/store/IndexOutput.cpp b/3rdparty/clucene/src/CLucene/store/IndexOutput.cpp new file mode 100644 index 0000000..04f78c3 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/IndexOutput.cpp @@ -0,0 +1,163 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "IndexOutput.h" + +CL_NS_USE(util) +CL_NS_DEF(store) + + + IndexOutput::IndexOutput() + { + } + + IndexOutput::~IndexOutput(){ + } + + BufferedIndexOutput::BufferedIndexOutput() + { + buffer = _CL_NEWARRAY(uint8_t, BUFFER_SIZE ); + bufferStart = 0; + bufferPosition = 0; + } + + BufferedIndexOutput::~BufferedIndexOutput(){ + if ( buffer != NULL ) + close(); + } + + void BufferedIndexOutput::close(){ + flush(); + _CLDELETE_ARRAY( buffer ); + + bufferStart = 0; + bufferPosition = 0; + } + + void BufferedIndexOutput::writeByte(const uint8_t b) { + CND_PRECONDITION(buffer!=NULL,"IndexOutput is closed") + if (bufferPosition >= BUFFER_SIZE) + flush(); + buffer[bufferPosition++] = b; + } + + void BufferedIndexOutput::writeBytes(const uint8_t* b, const int32_t length) { + if ( length < 0 ) + _CLTHROWA(CL_ERR_IllegalArgument, "IO Argument Error. Value must be a positive value."); + int32_t bytesLeft = BUFFER_SIZE - bufferPosition; + // is there enough space in the buffer? + if (bytesLeft >= length) { + // we add the data to the end of the buffer + memcpy(buffer + bufferPosition, b, length); + bufferPosition += length; + // if the buffer is full, flush it + if (BUFFER_SIZE - bufferPosition == 0) + flush(); + } else { + // is data larger then buffer? + if (length > BUFFER_SIZE) { + // we flush the buffer + if (bufferPosition > 0) + flush(); + // and write data at once + flushBuffer(b, length); + bufferStart += length; + } else { + // we fill/flush the buffer (until the input is written) + int64_t pos = 0; // position in the input data + int32_t pieceLength; + while (pos < length) { + if ( length - pos < bytesLeft ) + pieceLength = length - pos; + else + pieceLength = bytesLeft; + memcpy(buffer + bufferPosition, b + pos, pieceLength); + pos += pieceLength; + bufferPosition += pieceLength; + // if the buffer is full, flush it + bytesLeft = BUFFER_SIZE - bufferPosition; + if (bytesLeft == 0) { + flush(); + bytesLeft = BUFFER_SIZE; + } + } + } + } + } + + void IndexOutput::writeInt(const int32_t i) { + writeByte((uint8_t)(i >> 24)); + writeByte((uint8_t)(i >> 16)); + writeByte((uint8_t)(i >> 8)); + writeByte((uint8_t) i); + } + + void IndexOutput::writeVInt(const int32_t vi) { + uint32_t i = vi; + while ((i & ~0x7F) != 0) { + writeByte((uint8_t)((i & 0x7f) | 0x80)); + i >>= 7; //doing unsigned shift + } + writeByte( (uint8_t)i ); + } + + void IndexOutput::writeLong(const int64_t i) { + writeInt((int32_t) (i >> 32)); + writeInt((int32_t) i); + } + + void IndexOutput::writeVLong(const int64_t vi) { + uint64_t i = vi; + while ((i & ~0x7F) != 0) { + writeByte((uint8_t)((i & 0x7f) | 0x80)); + i >>= 7; //doing unsigned shift + } + writeByte((uint8_t)i); + } + + void IndexOutput::writeString(const TCHAR* s, const int32_t length ) { + writeVInt(length); + writeChars(s, 0, length); + } + + void IndexOutput::writeChars(const TCHAR* s, const int32_t start, const int32_t length){ + if ( length < 0 || start < 0 ) + _CLTHROWA(CL_ERR_IllegalArgument, "IO Argument Error. Value must be a positive value."); + + const int32_t end = start + length; + for (int32_t i = start; i < end; ++i) { + const int32_t code = (int32_t)s[i]; + if (code >= 0x01 && code <= 0x7F) + writeByte((uint8_t)code); + else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0) { + writeByte((uint8_t)(0xC0 | (code >> 6))); + writeByte((uint8_t)(0x80 | (code & 0x3F))); + } else { + writeByte((uint8_t)(0xE0 | (((uint32_t)code) >> 12))); //unsigned shift + writeByte((uint8_t)(0x80 | ((code >> 6) & 0x3F))); + writeByte((uint8_t)(0x80 | (code & 0x3F))); + } + } + } + + + int64_t BufferedIndexOutput::getFilePointer() const{ + return bufferStart + bufferPosition; + } + + void BufferedIndexOutput::seek(const int64_t pos) { + flush(); + bufferStart = pos; + } + + void BufferedIndexOutput::flush() { + flushBuffer(buffer, bufferPosition); + bufferStart += bufferPosition; + bufferPosition = 0; + } + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/store/IndexOutput.h b/3rdparty/clucene/src/CLucene/store/IndexOutput.h new file mode 100644 index 0000000..c47ee73 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/IndexOutput.h @@ -0,0 +1,152 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_store_IndexOutput_ +#define _lucene_store_IndexOutput_ +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(store) + + +/** Abstract class for output to a file in a Directory. A random-access output +* stream. Used for all Lucene index output operations. +* @see Directory +* @see IndexInput +*/ +class IndexOutput:LUCENE_BASE{ + bool isclosed; +public: + IndexOutput(); + virtual ~IndexOutput(); + + /** Writes a single byte. + * @see IndexInput#readByte() + */ + virtual void writeByte(const uint8_t b) = 0; + + /** Writes an array of bytes. + * @param b the bytes to write + * @param length the number of bytes to write + * @see IndexInput#readBytes(byte[],int32_t,int32_t) + */ + virtual void writeBytes(const uint8_t* b, const int32_t length) = 0; + + /** Writes an int as four bytes. + * @see IndexInput#readInt() + */ + void writeInt(const int32_t i); + + /** Writes an int in a variable-length format. Writes between one and + * five bytes. Smaller values take fewer bytes. Negative numbers are not + * supported. + * @see IndexInput#readVInt() + */ + void writeVInt(const int32_t vi); + + /** Writes a long as eight bytes. + * @see IndexInput#readLong() + */ + void writeLong(const int64_t i); + + /** Writes an long in a variable-length format. Writes between one and five + * bytes. Smaller values take fewer bytes. Negative numbers are not + * supported. + * @see IndexInput#readVLong() + */ + void writeVLong(const int64_t vi); + + /** Writes a string. + * @see IndexInput#readString() + */ + void writeString(const TCHAR* s, const int32_t length); + + /** Writes a sequence of UTF-8 encoded characters from a string. + * @param s the source of the characters + * @param start the first character in the sequence + * @param length the number of characters in the sequence + * @see IndexInput#readChars(char[],int32_t,int32_t) + */ + void writeChars(const TCHAR* s, const int32_t start, const int32_t length); + + /** Closes this stream to further operations. */ + virtual void close() = 0; + + /** Returns the current position in this file, where the next write will + * occur. + * @see #seek(long) + */ + virtual int64_t getFilePointer() const = 0; + + /** Sets current position in this file, where the next write will occur. + * @see #getFilePointer() + */ + virtual void seek(const int64_t pos) = 0; + + /** The number of bytes in the file. */ + virtual int64_t length() = 0; + + /** Forces any buffered output to be written. */ + virtual void flush() = 0; +}; + +/** Base implementation class for buffered {@link IndexOutput}. */ +class BufferedIndexOutput : public IndexOutput{ +public: + LUCENE_STATIC_CONSTANT(int32_t, BUFFER_SIZE=LUCENE_STREAM_BUFFER_SIZE); +private: + uint8_t* buffer; + int64_t bufferStart; // position in file of buffer + int32_t bufferPosition; // position in buffer + +public: + BufferedIndexOutput(); + virtual ~BufferedIndexOutput(); + + /** Writes a single byte. + * @see IndexInput#readByte() + */ + virtual void writeByte(const uint8_t b); + + /** Writes an array of bytes. + * @param b the bytes to write + * @param length the number of bytes to write + * @see IndexInput#readBytes(byte[],int32_t,int32_t) + */ + virtual void writeBytes(const uint8_t* b, const int32_t length); + + /** Closes this stream to further operations. */ + virtual void close(); + + /** Returns the current position in this file, where the next write will + * occur. + * @see #seek(long) + */ + int64_t getFilePointer() const; + + /** Sets current position in this file, where the next write will occur. + * @see #getFilePointer() + */ + virtual void seek(const int64_t pos); + + /** The number of bytes in the file. */ + virtual int64_t length() = 0; + + /** Forces any buffered output to be written. */ + void flush(); + +protected: + /** Expert: implements buffer write. Writes bytes at the current position in + * the output. + * @param b the bytes to write + * @param len the number of bytes to write + */ + virtual void flushBuffer(const uint8_t* b, const int32_t len) = 0; +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/store/InputStream.h b/3rdparty/clucene/src/CLucene/store/InputStream.h new file mode 100644 index 0000000..f56819e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/InputStream.h @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_store_InputStream_ +#define _lucene_store_InputStream_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(store) + +deprecated... please use IndexInput.h header +and change InputStream to IndexInput + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/store/Lock.cpp b/3rdparty/clucene/src/CLucene/store/Lock.cpp new file mode 100644 index 0000000..a66e784 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/Lock.cpp @@ -0,0 +1,27 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Lock.h" + +CL_NS_DEF(store) + + bool LuceneLock::obtain(int64_t lockWaitTimeout) { + bool locked = obtain(); + int maxSleepCount = (int)(lockWaitTimeout / LOCK_POLL_INTERVAL); + int sleepCount = 0; + while (!locked) { + if (sleepCount++ == maxSleepCount) { + _CLTHROWA(CL_ERR_IO,"Lock obtain timed out"); + } + _LUCENE_SLEEP(LOCK_POLL_INTERVAL); + locked = obtain(); + } + return locked; + } + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/store/Lock.h b/3rdparty/clucene/src/CLucene/store/Lock.h new file mode 100644 index 0000000..b5dda3b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/Lock.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_store_Lock_ +#define _lucene_store_Lock_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(store) + +class LuceneLock : LUCENE_BASE +{ +public: + LUCENE_STATIC_CONSTANT(int64_t, LOCK_POLL_INTERVAL = 1000); + + virtual ~LuceneLock() {} + + // Attempts to obtain exclusive access and immediately return upon success + // or failure. Return true if exclusive access is obtained. + virtual bool obtain() = 0; + + // Attempts to obtain an exclusive lock within amount of time given. + // Currently polls once per second until lockWaitTimeout is passed. + // @param lockWaitTimeout length of time to wait in ms + // @return true if lock was obtained + // @throws IOException if lock wait times out or obtain() throws an IOException + bool obtain(int64_t lockWaitTimeout); + + // Release exclusive access. + virtual void release() = 0; + + // Returns true if the resource is currently locked. Note that one must + // still call {@link #obtain()} before using the resource. + virtual bool isLocked() = 0; + + virtual QString toString() const = 0; +}; + + +// Utility class for executing code with exclusive access. +template +class LuceneLockWith +{ +public: + // Constructs an executor that will grab the named lock. Defaults + // lockWaitTimeout to LUCENE_COMMIT_LOCK_TIMEOUT. + // @deprecated Kept only to avoid breaking existing code. + LuceneLockWith(LuceneLock* lock, int64_t lockWaitTimeout) + { + this->lock = lock; + this->lockWaitTimeout = lockWaitTimeout; + } + + virtual ~LuceneLockWith() {} + + // Calls {@link #doBody} while lock is obtained. Blocks if lock + // cannot be obtained immediately. Retries to obtain lock once per second + // until it is obtained, or until it has tried ten times. Lock is released + // when {@link #doBody} exits. + T runAndReturn() + { + bool locked = false; + T ret = NULL; + try { + locked = lock->obtain(lockWaitTimeout); + ret = doBody(); + } _CLFINALLY ( + if (locked) + lock->release(); + ); + return ret; + } + + // @see runAndReturn + // Same as runAndReturn, except doesn't return any value. The only + // difference is that no void values are used + void run() + { + bool locked = false; + try { + locked = lock->obtain(lockWaitTimeout); + doBody(); + } _CLFINALLY ( + if (locked) + lock->release(); + ); + } + +protected: + virtual T doBody() = 0; + +private: + LuceneLock* lock; + int64_t lockWaitTimeout; +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/store/MMapInput.cpp b/3rdparty/clucene/src/CLucene/store/MMapInput.cpp new file mode 100644 index 0000000..d660032 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/MMapInput.cpp @@ -0,0 +1,203 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#if defined(LUCENE_FS_MMAP) + +#include "FSDirectory.h" +#include "CLucene/util/Misc.h" +#include "CLucene/debug/condition.h" + +#ifndef _CLCOMPILER_MSVC + #include +#endif + +CL_NS_DEF(store) +CL_NS_USE(util) + + FSDirectory::MMapIndexInput::MMapIndexInput(const char* path): + pos(0), + data(NULL), + _length(0), + isClone(false) + { + //Func - Constructor. + // Opens the file named path + //Pre - path != NULL + //Post - if the file could not be opened an exception is thrown. + + CND_PRECONDITION(path != NULL, "path is NULL"); + +#ifdef _CLCOMPILER_MSVC + mmaphandle = NULL; + fhandle = CreateFileA(path,GENERIC_READ,FILE_SHARE_READ, 0,OPEN_EXISTING,0,0); + + //Check if a valid fhandle was retrieved + if (fhandle < 0){ + DWORD err = GetLastError(); + if ( err == ERROR_FILE_NOT_FOUND ) + _CLTHROWA(CL_ERR_IO, "File does not exist"); + else if ( err == EACCES ) + _CLTHROWA(ERROR_ACCESS_DENIED, "File Access denied"); + else if ( err == ERROR_TOO_MANY_OPEN_FILES ) + _CLTHROWA(CL_ERR_IO, "Too many open files"); + else + _CLTHROWA(CL_ERR_IO, "File IO Error"); + } + + DWORD dummy=0; + _length = GetFileSize(fhandle,&dummy); + + if ( _length > 0 ){ + mmaphandle = CreateFileMappingA(fhandle,NULL,PAGE_READONLY,0,0,NULL); + if ( mmaphandle != NULL ){ + void* address = MapViewOfFile(mmaphandle,FILE_MAP_READ,0,0,0); + if ( address != NULL ){ + data = (uint8_t*)address; + return; //SUCCESS! + } + } + CloseHandle(mmaphandle); + + char* lpMsgBuf=0; + DWORD dw = GetLastError(); + + FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + lpMsgBuf, + 0, NULL ); + + char* errstr = _CL_NEWARRAY(char, strlen(lpMsgBuf)+40); + sprintf(errstr, "MMapIndexInput::MMapIndexInput failed with error %d: %s", dw, lpMsgBuf); + LocalFree(lpMsgBuf); + + _CLTHROWA_DEL(CL_ERR_IO,errstr); + } + +#else //_CLCOMPILER_MSVC + fhandle = ::open (path, O_RDONLY); + if (fhandle < 0){ + _CLTHROWA(CL_ERR_IO,strerror(errno)); + }else{ + // stat it + struct stat sb; + if (::fstat (fhandle, &sb)){ + _CLTHROWA(CL_ERR_IO,strerror(errno)); + }else{ + // get length from stat + _length = sb.st_size; + + // mmap the file + void* address = ::mmap(0, _length, PROT_READ, MAP_SHARED, fhandle, 0); + if (address == MAP_FAILED){ + _CLTHROWA(CL_ERR_IO,strerror(errno)); + }else{ + data = (uint8_t*)address; + } + } + } +#endif + } + + FSDirectory::MMapIndexInput::MMapIndexInput(const MMapIndexInput& clone): IndexInput(clone){ + //Func - Constructor + // Uses clone for its initialization + //Pre - clone is a valide instance of FSIndexInput + //Post - The instance has been created and initialized by clone + +#ifdef _CLCOMPILER_MSVC + mmaphandle = NULL; + fhandle = NULL; +#endif + + data = clone.data; + pos = clone.pos; + + //clone the file length + _length = clone._length; + //Keep in mind that this instance is a clone + isClone = true; + } + + uint8_t FSDirectory::MMapIndexInput::readByte(){ + return *(data+(pos++)); + } + + void FSDirectory::MMapIndexInput::readBytes(uint8_t* b, const int32_t len){ + memcpy(b, data+pos, len); + pos+=len; + } + int32_t FSDirectory::MMapIndexInput::readVInt(){ + uint8_t b = *(data+(pos++)); + int32_t i = b & 0x7F; + for (int shift = 7; (b & 0x80) != 0; shift += 7) { + b = *(data+(pos++)); + i |= (b & 0x7F) << shift; + } + return i; + } + int64_t FSDirectory::MMapIndexInput::getFilePointer() const{ + return pos; + } + void FSDirectory::MMapIndexInput::seek(const int64_t pos){ + this->pos=pos; + } + + FSDirectory::MMapIndexInput::~MMapIndexInput(){ + //Func - Destructor + //Pre - True + //Post - The file for which this instance is responsible has been closed. + // The instance has been destroyed + + close(); + } + + IndexInput* FSDirectory::MMapIndexInput::clone() const + { + return _CLNEW FSDirectory::MMapIndexInput(*this); + } + void FSDirectory::MMapIndexInput::close() { + //IndexInput::close(); + + if ( !isClone ){ +#ifdef _CLCOMPILER_MSVC + if ( data != NULL ){ + if ( ! UnmapViewOfFile(data) ){ + CND_PRECONDITION( false, "UnmapViewOfFile(data) failed"); //todo: change to rich error + } + } + + if ( mmaphandle != NULL ){ + if ( ! CloseHandle(mmaphandle) ){ + CND_PRECONDITION( false, "CloseHandle(mmaphandle) failed"); + } + } + if ( fhandle != NULL ){ + if ( !CloseHandle(fhandle) ){ + CND_PRECONDITION( false, "CloseHandle(fhandle) failed"); + } + } + mmaphandle = NULL; + fhandle = NULL; +#else + if ( data != NULL ) + ::munmap(data, _length); + if ( fhandle > 0 ) + ::close(fhandle); + fhandle = 0; +#endif + } + data = NULL; + pos = 0; + } + + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/store/OutputStream.h b/3rdparty/clucene/src/CLucene/store/OutputStream.h new file mode 100644 index 0000000..a82d671 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/OutputStream.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_store_IndexOutput_ +#define _lucene_store_IndexOutput_ +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +CL_NS_DEF(store) + + +deprecated... please use IndexOutput.h header +and change OutputStream to OutdexInput + + + +CL_NS_END + +#endif // _lucene_store_IndexOutput_ diff --git a/3rdparty/clucene/src/CLucene/store/RAMDirectory.cpp b/3rdparty/clucene/src/CLucene/store/RAMDirectory.cpp new file mode 100644 index 0000000..b0a7c4d --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/RAMDirectory.cpp @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#include "CLucene/StdHeader.h" +#include "RAMDirectory.h" + +#include "Lock.h" +#include "Directory.h" +#include "FSDirectory.h" +#include "CLucene/index/IndexReader.h" +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/Misc.h" +#include "CLucene/debug/condition.h" + +CL_NS_USE(util) +CL_NS_DEF(store) + +RAMFile::RAMFile() +{ + length = 0; + lastModified = Misc::currentTimeMillis(); +} + +RAMFile::~RAMFile() +{ +} + + +RAMDirectory::RAMLock::RAMLock(const QString& name, RAMDirectory* dir) + : directory(dir) +{ + fname = name; +} + +RAMDirectory::RAMLock::~RAMLock() +{ + directory = NULL; +} + +QString RAMDirectory::RAMLock::toString() const +{ + return QLatin1String("LockFile@RAM"); +} + +bool RAMDirectory::RAMLock::isLocked() +{ + return directory->fileExists(fname); +} + +bool RAMDirectory::RAMLock::obtain() +{ + SCOPED_LOCK_MUTEX(directory->files_mutex); + if (!directory->fileExists(fname)) { + IndexOutput* tmp = directory->createOutput(fname); + tmp->close(); + _CLDELETE(tmp); + + return true; + } + return false; +} + +void RAMDirectory::RAMLock::release() +{ + directory->deleteFile(fname); +} + +RAMIndexOutput::~RAMIndexOutput() +{ + if (deleteFile) + _CLDELETE(file); + file = NULL; +} + +RAMIndexOutput::RAMIndexOutput(RAMFile* f) + : file(f) +{ + pointer = 0; + deleteFile = false; +} + +RAMIndexOutput::RAMIndexOutput() + : file(_CLNEW RAMFile) +{ + pointer = 0; + deleteFile = true; +} + +void RAMIndexOutput::writeTo(IndexOutput* out) +{ + flush(); + int64_t end = file->length; + int64_t pos = 0; + int32_t p = 0; + while (pos < end) { + int32_t length = CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE; + int64_t nextPos = pos + length; + if (nextPos > end) { // at the last buffer + length = (int32_t)(end - pos); + } + out->writeBytes((uint8_t*)file->buffers[p++], length); + pos = nextPos; + } +} + +void RAMIndexOutput::reset() +{ + seek(_ILONGLONG(0)); + file->length = _ILONGLONG(0); +} + +void RAMIndexOutput::flushBuffer(const uint8_t* src, const int32_t len) +{ + uint8_t* b = NULL; + int32_t bufferPos = 0; + while (bufferPos != len) { + uint32_t bufferNumber = pointer/CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE; + int32_t bufferOffset = pointer%CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE; + int32_t bytesInBuffer = CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE - bufferOffset; + int32_t remainInSrcBuffer = len - bufferPos; + int32_t bytesToCopy = bytesInBuffer >= remainInSrcBuffer ? remainInSrcBuffer : bytesInBuffer; + + if (bufferNumber == file->buffers.size()){ + b = _CL_NEWARRAY(uint8_t, CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE); + file->buffers.push_back( b ); + }else{ + b = file->buffers[bufferNumber]; + } + memcpy(b+bufferOffset, src+bufferPos, bytesToCopy * sizeof(uint8_t)); + bufferPos += bytesToCopy; + pointer += bytesToCopy; + } + if (pointer > file->length) + file->length = pointer; + + file->lastModified = Misc::currentTimeMillis(); +} + +void RAMIndexOutput::close() +{ + BufferedIndexOutput::close(); +} + +/** Random-at methods */ +void RAMIndexOutput::seek(const int64_t pos) +{ + BufferedIndexOutput::seek(pos); + pointer = (int32_t)pos; +} + +int64_t RAMIndexOutput::length() +{ + return file->length; +} + + +RAMIndexInput::RAMIndexInput(RAMFile* f) + : file(f) +{ + pointer = 0; + _length = f->length; +} + +RAMIndexInput::RAMIndexInput(const RAMIndexInput& other) + : BufferedIndexInput(other) +{ + file = other.file; + pointer = other.pointer; + _length = other._length; +} + +RAMIndexInput::~RAMIndexInput() +{ + RAMIndexInput::close(); +} + +IndexInput* RAMIndexInput::clone() const +{ + return _CLNEW RAMIndexInput(*this); +} + +int64_t RAMIndexInput::length() +{ + return _length; +} + +QString RAMIndexInput::getDirectoryType() const +{ + return RAMDirectory::DirectoryType(); +} + +void RAMIndexInput::readInternal(uint8_t* dest, const int32_t len) +{ + const int64_t bytesAvailable = file->length - pointer; + int64_t remainder = len <= bytesAvailable ? len : bytesAvailable; + int32_t start = pointer; + int32_t destOffset = 0; + while (remainder != 0) { + int32_t bufferNumber = start / CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE; + int32_t bufferOffset = start % CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE; + int32_t bytesInBuffer = CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE - bufferOffset; + + /* The buffer's entire length (bufferLength) is defined by IndexInput.h + ** as int32_t, so obviously the number of bytes in a given segment of the + ** buffer won't exceed the the capacity of int32_t. Therefore, the + ** int64_t->int32_t cast on the next line is safe. */ + int32_t bytesToCopy = bytesInBuffer >= remainder ? static_cast(remainder) : bytesInBuffer; + uint8_t* b = file->buffers[bufferNumber]; + memcpy(dest + destOffset, b + bufferOffset, bytesToCopy * sizeof(uint8_t)); + + destOffset += bytesToCopy; + start += bytesToCopy; + remainder -= bytesToCopy; + pointer += bytesToCopy; + } +} + +void RAMIndexInput::close() +{ + BufferedIndexInput::close(); +} + +void RAMIndexInput::seekInternal(const int64_t pos) +{ + CND_PRECONDITION(pos >= 0 && pos < this->_length, "Seeking out of range") + pointer = (int32_t)pos; +} + +// #pragma mark -- RAMDirectory + +QStringList RAMDirectory::list() const +{ + SCOPED_LOCK_MUTEX(files_mutex); + + QStringList names; + + FileMap::const_iterator itr; + for (itr = files.begin(); itr != files.end(); ++itr) + names.push_back(itr->first); + + return names; +} + +RAMDirectory::RAMDirectory() + : Directory() + , files(false, true) +{ +} + +RAMDirectory::~RAMDirectory() +{ + //todo: should call close directory? +} + +void RAMDirectory::_copyFromDir(Directory* dir, bool closeDir) +{ + QStringList names = dir->list(); + uint8_t buf[CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE]; + + foreach (const QString& name, names) { + if (!CL_NS(index)::IndexReader::isLuceneFile(name)) + continue; + + // make place on ram disk + IndexOutput* os = createOutput(name); + // read current file + IndexInput* is = dir->openInput(name); + + // and copy to ram disk + //todo: this could be a problem when copying from big indexes... + int64_t readCount = 0; + int64_t len = is->length(); + while (readCount < len) { + int32_t toRead = CL_NS(store)::BufferedIndexOutput::BUFFER_SIZE; + if ((readCount + toRead) > len) + toRead = int32_t(len - readCount); + is->readBytes(buf, toRead); + os->writeBytes(buf, toRead); + readCount += toRead; + } + + // graceful cleanup + is->close(); + _CLDELETE(is); + os->close(); + _CLDELETE(os); + } + if (closeDir) + dir->close(); +} + +RAMDirectory::RAMDirectory(Directory* dir) + : Directory() + , files(false, true) +{ + _copyFromDir(dir, false); +} + +RAMDirectory::RAMDirectory(const QString& dir) + : Directory() + , files(false, true) +{ + Directory* fsdir = FSDirectory::getDirectory(dir, false); + try { + _copyFromDir(fsdir, false); + } _CLFINALLY ( + fsdir->close(); + _CLDECDELETE(fsdir); + ); +} + +bool RAMDirectory::fileExists(const QString& name) const +{ + SCOPED_LOCK_MUTEX(files_mutex); + return files.exists(name); +} + +int64_t RAMDirectory::fileModified(const QString& name) const +{ + SCOPED_LOCK_MUTEX(files_mutex); + const RAMFile* f = files.get(name); + return f->lastModified; +} + +int64_t RAMDirectory::fileLength(const QString& name) const +{ + SCOPED_LOCK_MUTEX(files_mutex); + RAMFile* f = files.get(name); + return f->length; +} + + +IndexInput* RAMDirectory::openInput(const QString& name) +{ + SCOPED_LOCK_MUTEX(files_mutex); + RAMFile* file = files.get(name); + if (file == NULL) { + _CLTHROWA(CL_ERR_IO, // DSR:PROPOSED: Better error checking. + "[RAMDirectory::open] The requested file does not exist."); + } + return _CLNEW RAMIndexInput(file); +} + +void RAMDirectory::close() +{ + SCOPED_LOCK_MUTEX(files_mutex); + files.clear(); +} + +bool RAMDirectory::doDeleteFile(const QString& name) +{ + SCOPED_LOCK_MUTEX(files_mutex); + files.remove(name); + return true; +} + +void RAMDirectory::renameFile(const QString& from, const QString& to) +{ + SCOPED_LOCK_MUTEX(files_mutex); + FileMap::iterator itr = files.find(from); + + /* DSR:CL_BUG_LEAK: + ** If a file named $to already existed, its old value was leaked. + ** My inclination would be to prevent this implicit deletion with an + ** exception, but it happens routinely in CLucene's internals (e.g., during + ** IndexWriter.addIndexes with the file named 'segments'). */ + if (files.exists(to)) + files.remove(to); + + if (itr == files.end()) { + char tmp[1024]; + _snprintf(tmp, 1024, "cannot rename %s, file does not exist", + from.toLocal8Bit().constData()); + _CLTHROWT(CL_ERR_IO, tmp); + } + + CND_PRECONDITION(itr != files.end(), "itr == files.end()") + + RAMFile* file = itr->second; + files.removeitr(itr, true, true); + files.put(to, file); +} + + +void RAMDirectory::touchFile(const QString& name) +{ + RAMFile* file = NULL; + { + SCOPED_LOCK_MUTEX(files_mutex); + file = files.get(name); + } + uint64_t ts1 = file->lastModified; + uint64_t ts2 = Misc::currentTimeMillis(); + + //make sure that the time has actually changed + while (ts1 == ts2) { + _LUCENE_SLEEP(1); + ts2 = Misc::currentTimeMillis(); + }; + + file->lastModified = ts2; +} + +IndexOutput* RAMDirectory::createOutput(const QString& name) +{ + /* Check the $files VoidMap to see if there was a previous file named + ** $name. If so, delete the old RAMFile object, but reuse the existing + ** char buffer ($n) that holds the filename. If not, duplicate the + ** supplied filename buffer ($name) and pass ownership of that memory ($n) + ** to $files. */ + + SCOPED_LOCK_MUTEX(files_mutex); + + QString n = files.getKey(name); + if (!n.isEmpty()) { + RAMFile* rf = files.get(name); + _CLDELETE(rf); + } else { + n = name; + } + + RAMFile* file = _CLNEW RAMFile(); +#ifdef _DEBUG + file->filename = n; +#endif + files[n] = file; + + return _CLNEW RAMIndexOutput(file); +} + +LuceneLock* RAMDirectory::makeLock(const QString& name) +{ + return _CLNEW RAMLock(name, this); +} + +QString RAMDirectory::toString() const +{ + return QLatin1String("RAMDirectory"); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/store/RAMDirectory.h b/3rdparty/clucene/src/CLucene/store/RAMDirectory.h new file mode 100644 index 0000000..af92e30 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/RAMDirectory.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +*/ +#ifndef _lucene_store_RAMDirectory_ +#define _lucene_store_RAMDirectory_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include "Lock.h" +#include "Directory.h" +#include "CLucene/util/VoidMap.h" +#include "CLucene/util/Arrays.h" + +CL_NS_DEF(store) + +class RAMFile : LUCENE_BASE +{ +public: + CL_NS(util)::CLVector > buffers; + int64_t length; + uint64_t lastModified; + +#ifdef _DEBUG + QString filename; +#endif + + RAMFile(); + ~RAMFile(); +}; + +class RAMIndexOutput : public BufferedIndexOutput +{ +protected: + RAMFile* file; + int32_t pointer; + bool deleteFile; + + // output methods: + void flushBuffer(const uint8_t* src, const int32_t len); + +public: + RAMIndexOutput(RAMFile* f); + RAMIndexOutput(); + /** Construct an empty output buffer. */ + virtual ~RAMIndexOutput(); + + virtual void close(); + + // Random-at methods + virtual void seek(const int64_t pos); + int64_t length(); + /** Resets this to an empty buffer. */ + void reset(); + /** Copy the current contents of this buffer to the named output. */ + void writeTo(IndexOutput* output); +}; + +class RAMIndexInput : public BufferedIndexInput +{ +private: + RAMFile* file; + int32_t pointer; + int64_t _length; + +protected: + /** IndexInput methods */ + RAMIndexInput(const RAMIndexInput& clone); + void readInternal(uint8_t *dest, const int32_t len); + + /** Random-at methods */ + void seekInternal(const int64_t pos); + +public: + RAMIndexInput(RAMFile* f); + ~RAMIndexInput(); + IndexInput* clone() const; + + void close(); + int64_t length(); + QString getDirectoryType() const; +}; + + +/** +* A memory-resident {@link Directory} implementation. +*/ +class RAMDirectory : public Directory +{ + class RAMLock : public LuceneLock + { + private: + RAMDirectory* directory; + QString fname; + public: + RAMLock(const QString& name, RAMDirectory* dir); + virtual ~RAMLock(); + bool obtain(); + void release(); + bool isLocked(); + virtual QString toString() const; + }; + + typedef CL_NS(util)::CLHashMap > FileMap; + +protected: + /// Removes an existing file in the directory. + virtual bool doDeleteFile(const QString& name); + + /** + * Creates a new RAMDirectory instance from a different + * Directory implementation. This can be used to load + * a disk-based index into memory. + *

+ * This should be used only with indices that can fit into memory. + * + * @param dir a Directory value + * @exception IOException if an error occurs + */ + void _copyFromDir(Directory* dir, bool closeDir); + FileMap files; // unlike the java Hashtable, FileMap is not synchronized, and all access must be protected by a lock + +public: +#ifndef _CL_DISABLE_MULTITHREADING //do this so that the mutable keyword still works without mt enabled + mutable DEFINE_MUTEX(files_mutex) // mutable: const methods must also be able to synchronize properly +#endif + + // Returns a null terminated array of strings, one for each file in the directory. + QStringList list() const; + + /** Constructs an empty {@link Directory}. */ + RAMDirectory(); + + // Destructor - only call this if you are sure the directory + // is not being used anymore. Otherwise use the ref-counting + // facilities of dir->close + virtual ~RAMDirectory(); + RAMDirectory(Directory* dir); + + /** + * Creates a new RAMDirectory instance from the {@link FSDirectory}. + * + * @param dir a String specifying the full index directory path + */ + RAMDirectory(const QString& dir); + + /// Returns true iff the named file exists in this directory. + bool fileExists(const QString& name) const; + + /// Returns the time the named file was last modified. + int64_t fileModified(const QString& name) const; + + /// Returns the length in bytes of a file in the directory. + int64_t fileLength(const QString& name) const; + + /// Removes an existing file in the directory. + virtual void renameFile(const QString& from, const QString& to); + + /** Set the modified time of an existing file to now. */ + void touchFile(const QString& name); + + /// Creates a new, empty file in the directory with the given name. + /// Returns a stream writing this file. + virtual IndexOutput* createOutput(const QString& name); + + /// Construct a {@link Lock}. + /// @param name the name of the lock file + LuceneLock* makeLock(const QString& name); + + /// Returns a stream reading an existing file. + IndexInput* openInput(const QString& name); + + virtual void close(); + + QString toString() const; + + static QString DirectoryType() { return QLatin1String("RAM"); } + QString getDirectoryType() const { return DirectoryType(); } +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.cpp b/3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.cpp new file mode 100644 index 0000000..056fa9b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "TransactionalRAMDirectory.h" + +CL_NS_DEF(store) +CL_NS_USE(util) + +TransactionalRAMDirectory::TransactionalRAMDirectory() + : RAMDirectory() + , filesToRestoreOnAbort(false, true) +{ + transOpen = false; +} + +TransactionalRAMDirectory::~TransactionalRAMDirectory() +{ +} + +bool TransactionalRAMDirectory::archiveOrigFileIfNecessary(const QString& name) +{ + // If a file named $name was present when the transaction started and the + // original RAMFile object has not been archived for restoration upon + // transaction abort, then do so, and return true. + // In any other case, return false. + if (fileExists(name) && filesToRemoveOnAbort.find(name) == filesToRemoveOnAbort.end()) { + // The file exists, but isn't recorded as having been created after the + // start of the transaction, so it must've been present at the start of + // the transaction. + + // Transfer memory ownership of both the key and the value from files to + // filesToRestoreOnAbort. + QString origName = files.getKey(name); + RAMFile* origFile = files.get(name); + files.remove(name, true, true); + filesToRestoreOnAbort.put(origName, origFile); + + CND_CONDITION(!fileExists(name), + "File should not exist immediately after archival."); + return true; + } + + return false; +} + +void TransactionalRAMDirectory::unarchiveOrigFile(const QString& name) +{ + QString origName = filesToRestoreOnAbort.getKey(name); + if (origName.isEmpty()) { + _CLTHROWA(CL_ERR_RAMTransaction, + "File submitted for unarchival was not archived."); + } + RAMFile* origFile = filesToRestoreOnAbort.get(name); + // Transfer memory ownership back to files from filesToRestoreOnAbort. + filesToRestoreOnAbort.remove(name, true, true); + files.put(origName, origFile); +} + +bool TransactionalRAMDirectory::transIsOpen() const +{ + return transOpen; +} + +void TransactionalRAMDirectory::transStart() +{ + if (transOpen) { + _CLTHROWA(CL_ERR_RAMTransaction, + "Must resolve previous transaction before starting another."); + } + + CND_CONDITION(filesToRemoveOnAbort.size() == 0, + "filesToRemoveOnAbort should have been cleared by either its" + " constructor or transResolved."); + + CND_CONDITION(filesToRestoreOnAbort.size() == 0, + "filesToRestoreOnAbort should have been cleared by either its" + " constructor or transResolved."); + + transOpen = true; +} + +void TransactionalRAMDirectory::transResolved() +{ + // This method implements actions common to both forms of transaction + // resolution. + filesToRemoveOnAbort.clear(); + filesToRestoreOnAbort.clear(); + transOpen = false; +} + +void TransactionalRAMDirectory::transCommit() +{ + if (!transOpen) + _CLTHROWA(CL_ERR_RAMTransaction, "There is no open transaction."); + + // All storage is in memory, so commit is ultra-simple. + transResolved(); +} + +void TransactionalRAMDirectory::transAbort() +{ + if (!transOpen) + _CLTHROWA(CL_ERR_RAMTransaction, "There is no open transaction."); + + // Delete each file in filesToRemoveOnAbort. + FilenameSet::const_iterator itrDel = filesToRemoveOnAbort.begin(); + for ( ; itrDel != filesToRemoveOnAbort.end(); ++itrDel) { + size_t nameLength = itrDel->first.length(); + + // Special exception: Refrain from deleting a lock's flag file, as that + // would interfere with the operation of the lock. + if (!(nameLength >= 5 + && itrDel->first.rightRef(5) == QLatin1String(".lock"))) { + RAMDirectory::deleteFile(itrDel->first); + } + } + // Ownership of the memory of both the key and the value never left files, + // so there's no need for a special directive to filesToRemoveOnAbort. + filesToRemoveOnAbort.clear(); + + // Now that any new-since-trans-start files with the same names as + // already-present-at-trans-start files are out of the way, restore each + // file in filesToRestoreOnAbort. + TransFileMap::const_iterator itr = filesToRestoreOnAbort.begin(); + for ( ; itr != filesToRestoreOnAbort.end(); ++itr) { + files.put(itr->first, itr->second); + filesToRestoreOnAbort.remove(itr->first); + } + + CND_CONDITION(filesToRestoreOnAbort.size() == 0, + "filesToRestoreOnAbort should be empty."); + + transResolved(); +} + +bool TransactionalRAMDirectory::doDeleteFile(const QString& name) +{ + if (!transOpen) + return RAMDirectory::doDeleteFile(name); + + bool wasOriginalAndWasArchived = archiveOrigFileIfNecessary(name); + if (!wasOriginalAndWasArchived) { + // The file to be deleted wasn't present at transaction start, so instead + // of archiving it, we delete it the conventional way, making sure to + // erase its record in filesToRemoveOnAbort if it was listed there. + filesToRemoveOnAbort.remove(name); + return RAMDirectory::doDeleteFile(name); + } + return true; +} + +void TransactionalRAMDirectory::renameFile(const QString& from, const QString& to) +{ + // During the review on 2005.03.18, decided not to implement transactional + // renameFile for two reasons: + // a) It's not needed in the limited scenario for which + // TransactionalRAMDirectory was designed (IndexWriter::addDocument and + // subcode). + // b) Supporting renaming during a transaction would add considerable + // bookkeeping overhead, reducing the performance of the overwhelmingly + // typical case (commit) in order to support the rare case (abort). + // + // This was not a thinly disguised punt due to the complication of + // implementing renameFile transactionally; rather, several implementations + // were considered, but it seemed wrongheaded to degrade the performance of + // the typical case based on the mere potential need to support renameFile + // at some future point for the benefit of the atypical case. + if (transOpen) { + _CLTHROWA(CL_ERR_RAMTransaction, + "TransactionalRAMDirectory disallows renameFile during a transaction."); + } + RAMDirectory::renameFile(from, to); +} + +IndexOutput* TransactionalRAMDirectory::createOutput(const QString& name) +{ + if (!transOpen) + return RAMDirectory::createOutput(name); + + bool wasOriginalAndWasArchived = archiveOrigFileIfNecessary(name); + try { + IndexOutput* ret = RAMDirectory::createOutput(name); + // Importantly, we store a pointer to the filename memory managed by + // files, rather than that passed in by the client (name). We don't make + // an additional copy of the filename's memory because the transactional + // metadata container filesToRemoveOnAbort is not at risk of outliving + // files. + filesToRemoveOnAbort.put(files.getKey(name), NULL); + return ret; + } catch (...) { + if (wasOriginalAndWasArchived) { + unarchiveOrigFile(name); + } + throw; + } +} + +void TransactionalRAMDirectory::close() +{ + if (transOpen) + transAbort(); + + RAMDirectory::close(); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.h b/3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.h new file mode 100644 index 0000000..44c5e8e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/store/TransactionalRAMDirectory.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_store_TransactionalRAMDirectory_ +#define _lucene_store_TransactionalRAMDirectory_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "RAMDirectory.h" +#include "CLucene/util/VoidList.h" + +CL_NS_DEF(store) + +/*** +This transactional in-memory Directory was created to address a specific +situation, and was deliberately pared down to the simplest viable +implementation. For the sake of simplicity, this implementation imposes +restrictions on what operations can be performed in the directory while a +transaction is in progress (documented in TransactionalRAMDirectory.cpp). + +Because the Lucene Directory interface itself is rather simplistic, it +would not be difficult to expand TransactionalRAMDirectory so that it +provided fully general transactionality. However, the developer of this +original implementation was of the opinion that the last thing CLucene +needs is gratuitous features that exceed their required complexity and +haven't been rigorously tested. +*/ +class TransactionalRAMDirectory : public RAMDirectory +{ +private: + typedef CL_NS(util)::CLSet FilenameSet; + FilenameSet filesToRemoveOnAbort; + + typedef CL_NS(util)::CLSet > TransFileMap; + TransFileMap filesToRestoreOnAbort; + + bool transOpen; + + void transResolved(); + bool archiveOrigFileIfNecessary(const QString& name); + void unarchiveOrigFile(const QString& name); + +protected: + bool doDeleteFile(const QString& name); + +public: + TransactionalRAMDirectory(); + virtual ~TransactionalRAMDirectory(); + + bool transIsOpen() const; + void transStart(); + void transCommit(); + void transAbort(); + + // Constrained operations: + void renameFile(const QString& from, const QString& to); + IndexOutput* createOutput(const QString& name); + + void close(); +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/Arrays.h b/3rdparty/clucene/src/CLucene/util/Arrays.h new file mode 100644 index 0000000..ba60c56 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/Arrays.h @@ -0,0 +1,164 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_Arrays_ +#define _lucene_util_Arrays_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "VoidList.h" + +CL_NS_DEF(util) + class Arrays{ + public: + template + class _Arrays { + protected: + //used by binarySearch to check for equality + virtual bool equals(_type a,_type b) const = 0; + virtual int32_t compare(_type a,_type b) const = 0; + public: + virtual ~_Arrays(){ + } + + void sort(_type* a, int32_t alen, int32_t fromIndex, int32_t toIndex) const{ + CND_PRECONDITION(fromIndex < toIndex,"fromIndex >= toIndex"); + CND_PRECONDITION(fromIndex >= 0,"fromIndex < 0"); + + // First presort the array in chunks of length 6 with insertion + // sort. A mergesort would give too much overhead for this length. + for (int32_t chunk = fromIndex; chunk < toIndex; chunk += 6) + { + int32_t end = min(chunk + 6, toIndex); + for (int32_t i = chunk + 1; i < end; i++) + { + if (compare(a[i - 1], a[i]) > 0) + { + // not already sorted + int32_t j = i; + _type elem = a[j]; + do + { + a[j] = a[j - 1]; + j--; + } + while (j > chunk && compare(a[j - 1], elem) > 0); + a[j] = elem; + } + } + } + + int32_t len = toIndex - fromIndex; + // If length is smaller or equal 6 we are done. + if (len <= 6) + return; + + _type* src = a; + _type* dest = _CL_NEWARRAY(_type,alen); + _type* t = NULL; // t is used for swapping src and dest + + // The difference of the fromIndex of the src and dest array. + int32_t srcDestDiff = -fromIndex; + + // The merges are done in this loop + for (int32_t size = 6; size < len; size <<= 1) + { + for (int32_t start = fromIndex; start < toIndex; start += size << 1) + { + // mid is the start of the second sublist; + // end the start of the next sublist (or end of array). + int32_t mid = start + size; + int32_t end = min(toIndex, mid + size); + + // The second list is empty or the elements are already in + // order - no need to merge + if (mid >= end || compare(src[mid - 1], src[mid]) <= 0) + { + memcpy(dest + start + srcDestDiff, src+start, (end-start)*sizeof(_type)); + }// The two halves just need swapping - no need to merge + else if (compare(src[start], src[end - 1]) > 0) + { + memcpy(dest+end-size+srcDestDiff, src+start, size * sizeof(_type)); + memcpy(dest+start+srcDestDiff, src+mid, (end-mid) * sizeof(_type)); + + }else{ + // Declare a lot of variables to save repeating + // calculations. Hopefully a decent JIT will put these + // in registers and make this fast + int32_t p1 = start; + int32_t p2 = mid; + int32_t i = start + srcDestDiff; + + // The main merge loop; terminates as soon as either + // half is ended + while (p1 < mid && p2 < end) + { + dest[i++] = src[(compare(src[p1], src[p2]) <= 0 + ? p1++ : p2++)]; + } + + // Finish up by copying the remainder of whichever half + // wasn't finished. + if (p1 < mid) + memcpy(dest+i,src+p1, (mid-p1) * sizeof(_type)); + else + memcpy(dest+i,src+p2, (end-p2) * sizeof(_type)); + } + } + // swap src and dest ready for the next merge + t = src; + src = dest; + dest = t; + fromIndex += srcDestDiff; + toIndex += srcDestDiff; + srcDestDiff = -srcDestDiff; + } + + // make sure the result ends up back in the right place. Note + // that src and dest may have been swapped above, so src + // contains the sorted array. + if (src != a) + { + // Note that fromIndex == 0. + memcpy(a+srcDestDiff,src,toIndex * sizeof(_type)); + } + } + }; + }; + + template + class CLListEquals: + public CL_NS_STD(binary_function) + { + typedef typename class1::const_iterator _itr1; + typedef typename class2::const_iterator _itr2; + public: + CLListEquals(){ + } + bool equals( class1* val1, class2* val2 ) const{ + static _comparator comp; + if ( val1 == val2 ) + return true; + size_t size = val1->size(); + if ( size != val2->size() ) + return false; + + _itr1 itr1 = val1->begin(); + _itr2 itr2 = val2->begin(); + while ( --size >= 0 ){ + if ( !comp(*itr1,*itr2) ) + return false; + itr1++; + itr2++; + } + return true; + } + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/BitSet.cpp b/3rdparty/clucene/src/CLucene/util/BitSet.cpp new file mode 100644 index 0000000..3679bd1 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/BitSet.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "BitSet.h" +#include "CLucene/store/Directory.h" + +CL_NS_USE(store) +CL_NS_DEF(util) + +BitSet::BitSet(const BitSet& copy) + : _size(copy._size) + , _count(-1) +{ + int32_t len = (_size >> 3) + 1; + bits = _CL_NEWARRAY(uint8_t, len); + memcpy(bits, copy.bits, len); +} + +BitSet::BitSet(int32_t size) + : _size(size) + , _count(-1) +{ + int32_t len = (_size >> 3) + 1; + bits = _CL_NEWARRAY(uint8_t, len); + memset(bits, 0, len); +} + +BitSet::BitSet(CL_NS(store)::Directory* d, const QString& name) +{ + _count = -1; + CL_NS(store)::IndexInput* input = d->openInput(name); + try { + _size = input->readInt(); // read size + _count = input->readInt(); // read count + + bits = _CL_NEWARRAY(uint8_t,(_size >> 3) + 1); // allocate bits + input->readBytes(bits, (_size >> 3) + 1); // read bits + } _CLFINALLY ( + input->close(); + _CLDELETE(input ); + ); +} + +void BitSet::write(CL_NS(store)::Directory* d, const QString& name) +{ + CL_NS(store)::IndexOutput* output = d->createOutput(name); + try { + output->writeInt(size()); // write size + output->writeInt(count()); // write count + output->writeBytes(bits, (_size >> 3) + 1); // write bits + } _CLFINALLY ( + output->close(); + _CLDELETE(output); + ); +} + +BitSet::~BitSet() +{ + _CLDELETE_ARRAY(bits); +} + +void BitSet::set(int32_t bit, bool val) +{ + if (val) + bits[bit >> 3] |= 1 << (bit & 7); + else + bits[bit >> 3] &= ~(1 << (bit & 7)); + + _count = -1; +} + +int32_t BitSet::size() const +{ + return _size; +} + +int32_t BitSet::count() +{ + // if the BitSet has been modified + if (_count == -1) { + static const uint8_t BYTE_COUNTS[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; + + int32_t c = 0; + int32_t end = (_size >> 3) + 1; + for (int32_t i = 0; i < end; i++) + c += BYTE_COUNTS[bits[i]]; // sum bits per uint8_t + _count = c; + } + return _count; +} + +BitSet* BitSet::clone() const +{ + return _CLNEW BitSet(*this); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/util/BitSet.h b/3rdparty/clucene/src/CLucene/util/BitSet.h new file mode 100644 index 0000000..e93847e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/BitSet.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_util_BitSet_ +#define _lucene_util_BitSet_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +#include "CLucene/store/Directory.h" + +CL_NS_DEF(util) + +class BitSet : LUCENE_BASE +{ +public: + // Create a bitset with the specified size + BitSet (int32_t size); + BitSet(CL_NS(store)::Directory* d, const QString& name); + void write(CL_NS(store)::Directory* d, const QString& name); + + // Destructor for the bit set + ~BitSet(); + + // get the value of the specified bit + inline bool get(const int32_t bit) const + { + return (bits[bit >> 3] & (1 << (bit & 7))) != 0; + } + + // set the value of the specified bit + void set(int32_t bit, bool val = true); + + ///returns the size of the bitset + int32_t size() const; + + // Returns the total number of one bits in this BitSet. This is + // efficiently computed and cached, so that, if the BitSet is not changed, + // no recomputation is done for repeated calls. + int32_t count(); + BitSet *clone() const; + +protected: + BitSet(const BitSet& copy); + +private: + int32_t _size; + int32_t _count; + uint8_t *bits; +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/Equators.cpp b/3rdparty/clucene/src/CLucene/util/Equators.cpp new file mode 100644 index 0000000..e112bd2 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/Equators.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "Equators.h" + +CL_NS_DEF(util) + +bool Equals::Int32::operator()(const int32_t val1, const int32_t val2) const +{ + return (val1)==(val2); +} + +bool Equals::Char::operator()(const char* val1, const char* val2) const +{ + if ( val1 == val2 ) + return true; + return (strcmp(val1, val2) == 0); +} + +#ifdef _UCS2 +bool Equals::WChar::operator()(const wchar_t* val1, const wchar_t* val2) const +{ + if (val1 == val2) + return true; + return (_tcscmp(val1, val2) == 0); +} +#endif + +bool Equals::Qstring::operator()(const QString& val1, const QString& val2) const +{ + return (val1 == val2); +} + +/////////////////////////////////////////////////////////////////////////////// +// Comparors +/////////////////////////////////////////////////////////////////////////////// + +int32_t Compare::Int32::getValue() const +{ + return value; +} + +Compare::Int32::Int32(int32_t val) +{ + value = val; +} + +Compare::Int32::Int32() +{ + value = 0; +} + +int32_t Compare::Int32::compareTo(void* o) +{ + try { + Int32* other = (Int32*)o; + if (value == other->value) + return 0; + // Returns just -1 or 1 on inequality; doing math might overflow. + return value > other->value ? 1 : -1; + } catch(...) { + _CLTHROWA(CL_ERR_Runtime, "Couldnt compare types"); + } +} + +bool Compare::Int32::operator()(int32_t t1, int32_t t2) const +{ + return t1 > t2 ? true : false; +} + +size_t Compare::Int32::operator()(int32_t t) const +{ + return t; +} + +qreal Compare::Float::getValue() const +{ + return value; +} + +Compare::Float::Float(qreal val) +{ + value = val; +} + +int32_t Compare::Float::compareTo(void* o) +{ + try { + Float* other = (Float*)o; + if (value == other->value) + return 0; + // Returns just -1 or 1 on inequality; doing math might overflow. + return value > other->value ? 1 : -1; + } catch(...) { + _CLTHROWA(CL_ERR_Runtime,"Couldnt compare types"); + } +} + +bool Compare::Char::operator()(const char* val1, const char* val2) const +{ + if ( val1 == val2) + return false; + return (strcmp(val1, val2) < 0); +} + +size_t Compare::Char::operator()(const char* val1) const +{ + return CL_NS(util)::Misc::ahashCode(val1); +} + +#ifdef _UCS2 +bool Compare::WChar::operator()(const wchar_t* val1, const wchar_t* val2) const +{ + if ( val1==val2) + return false; + return (_tcscmp(val1, val2) < 0); +} + +size_t Compare::WChar::operator()(const wchar_t* val1) const +{ + return CL_NS(util)::Misc::whashCode(val1); +} +#endif + +const TCHAR* Compare::TChar::getValue() const +{ + return s; +} + +Compare::TChar::TChar() +{ + s = NULL; +} + +Compare::TChar::TChar(const TCHAR* str) +{ + this->s = str; +} + +int32_t Compare::TChar::compareTo(void* o) +{ + try { + TChar* os = (TChar*)o; + return _tcscmp(s, os->s); + } catch(...) { + _CLTHROWA(CL_ERR_Runtime,"Couldnt compare types"); + } + +} + +bool Compare::TChar::operator()(const TCHAR* val1, const TCHAR* val2) const +{ + if (val1 == val2) + return false; + + return (_tcscmp(val1, val2) < 0); +} + +size_t Compare::TChar::operator()(const TCHAR* val1) const +{ + return CL_NS(util)::Misc::thashCode(val1); +} + +bool Compare::Qstring::operator()(const QString& val1, const QString& val2) const +{ + return (val1 < val2); +} + +size_t Compare::Qstring::operator ()(const QString& val1) const +{ + return CL_NS(util)::Misc::qhashCode(val1); +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/util/Equators.h b/3rdparty/clucene/src/CLucene/util/Equators.h new file mode 100644 index 0000000..11fcb0e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/Equators.h @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_util_Equators_ +#define _lucene_util_Equators_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +//#ifdef QT_LINUXBASE +// we are going to use qreal now, we basically maintain our own clucene anyway +//// LSB doesn't define float_t - see http://bugs.linuxbase.org/show_bug.cgi?id=2374 +//typedef float float_t; +//#endif + +CL_NS_DEF(util) + +/////////////////////////////////////////////////////////////////////////////// +// Equators +/////////////////////////////////////////////////////////////////////////////// + +class Equals{ +public: + class Int32:public CL_NS_STD(binary_function) + { + public: + bool operator()( const int32_t val1, const int32_t val2 ) const; + }; + + class Char:public CL_NS_STD(binary_function) + { + public: + bool operator()( const char* val1, const char* val2 ) const; + }; +#ifdef _UCS2 + class WChar: public CL_NS_STD(binary_function) + { + public: + bool operator()( const wchar_t* val1, const wchar_t* val2 ) const; + }; + class TChar: public WChar{ + }; +#else + class TChar: public Char{ + }; +#endif + + template + class Void:public CL_NS_STD(binary_function) + { + public: + bool operator()( _cl* val1, _cl* val2 ) const{ + return val1==val2; + } + }; + + class Qstring : public CL_NS_STD(binary_function) + { + public: + bool operator() (const QString& val1, const QString& val2) const; + }; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Comparors +/////////////////////////////////////////////////////////////////////////////// + +class Comparable : LUCENE_BASE +{ +public: + virtual ~Comparable(){ + } + + virtual int32_t compareTo(void* o) = 0; +}; + +/** @internal */ +class Compare{ +public: + class _base + { // traits class for hash containers + public: + enum + { // parameters for hash table + bucket_size = 4, // 0 < bucket_size + min_buckets = 8 + }; // min_buckets = 2 ^^ N, 0 < N + + _base() + { + } + }; + + class Int32:public _base, public Comparable{ + int32_t value; + public: + int32_t getValue() const; + Int32(int32_t val); + Int32(); + int32_t compareTo(void* o); + bool operator()( int32_t t1, int32_t t2 ) const; + size_t operator()( int32_t t ) const; + }; + + + class Float:public Comparable{ + qreal value; + public: + qreal getValue() const; + Float(qreal val); + int32_t compareTo(void* o); + }; + + + class Char: public _base // + { + public: + bool operator()( const char* val1, const char* val2 ) const; + size_t operator()( const char* val1) const; + }; + +#ifdef _UCS2 + class WChar: public _base // + { + public: + bool operator()( const wchar_t* val1, const wchar_t* val2 ) const; + size_t operator()( const wchar_t* val1) const; + }; +#endif + + class TChar: public _base, public Comparable{ + const TCHAR* s; + public: + const TCHAR* getValue() const; + + TChar(); + TChar(const TCHAR* str); + int32_t compareTo(void* o); + bool operator()( const TCHAR* val1, const TCHAR* val2 ) const; + size_t operator()( const TCHAR* val1) const; + }; + + + template + class Void:public _base // + { + public: + int32_t compareTo(_cl* o){ + if ( this == o ) + return o; + else + return this > o ? 1 : -1; + } + bool operator()( _cl* t1, _cl* t2 ) const{ + return t1 > t2 ? true : false; + } + size_t operator()( _cl* t ) const{ + return (size_t)t; + } + }; + + class Qstring : public _base + { + public: + bool operator() (const QString& val1, const QString& val2) const; + size_t operator() (const QString& val1) const; + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// allocators +/////////////////////////////////////////////////////////////////////////////// + +class Deletor +{ +public: + + template + class Array{ + public: + static void doDelete(_kt* arr){ + _CLDELETE_LARRAY(arr); + } + }; + class tcArray{ + public: + static void doDelete(const TCHAR* arr){ + _CLDELETE_CARRAY(arr); + } + }; + class acArray{ + public: + static void doDelete(const char* arr){ + _CLDELETE_CaARRAY(arr); + } + }; + + class Unintern{ + public: + static void doDelete(TCHAR* arr); + }; + template + class Object{ + public: + static void doDelete(_kt* obj){ + _CLLDELETE(obj); + } + }; + template + class Void{ + public: + static void doDelete(_kt* obj){ + _CLVDELETE(obj); + } + }; + class Dummy{ + public: + static void doDelete(const void* nothing) + { + // TODO: remove all occurances where it hits this point + // CND_WARNING(false, "Deletor::Dummy::doDelete run, set deleteKey + // or deleteValue to false"); + } + }; + class DummyInt32{ + public: + static void doDelete(const int32_t nothing){ + } + }; + class DummyFloat{ + public: + static void doDelete(const qreal nothing){ + } + }; + template + class ConstNullVal{ + public: + static void doDelete(const _type nothing) + { + // TODO: remove all occurances where it hits this point + // CND_WARNING(false, "Deletor::Dummy::doDelete run, set deleteKey + // or deleteValue to false"); + } + }; + + template + class NullVal{ + public: + static void doDelete(_type nothing) + { + // TODO: remove all occurances where it hits this point + // CND_WARNING(false, "Deletor::Dummy::doDelete run, set deleteKey + // or deleteValue to false"); + } + }; + class DummyQString { + public: + static void doDelete(const QString& nothing) { + } + }; +}; +//////////////////////////////////////////////////////////////////////////////// + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/FastCharStream.cpp b/3rdparty/clucene/src/CLucene/util/FastCharStream.cpp new file mode 100644 index 0000000..f9fbe9b --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/FastCharStream.cpp @@ -0,0 +1,107 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "FastCharStream.h" + +#include "CLucene/util/Reader.h" + +CL_NS_DEF(util) + +const int32_t FastCharStream::maxRewindSize = LUCENE_MAX_WORD_LEN*2; + + FastCharStream::FastCharStream(Reader* reader): + pos(0), + rewindPos(0), + resetPos(0), + col(1), + line(1), + input(reader) + { + input->mark(maxRewindSize); + } + FastCharStream::~FastCharStream(){ + } + void FastCharStream::readChar(TCHAR &c) { + try{ + int32_t r = input->read(); + if ( r == -1 ) + input = NULL; + c = r; + }catch(CLuceneError& err){ + if ( err.number() == CL_ERR_IO ) + input = 0; + throw err; + } + } + int FastCharStream::GetNext() + { + // printf("getnext\n"); + if (input == 0 ) // end of file + { + _CLTHROWA(CL_ERR_IO,"warning : FileReader.GetNext : Read TCHAR over EOS."); + } + // this is rather inefficient + // implementing the functions from the java version of + // charstream will be much more efficient. + ++pos; + if ( pos > resetPos + maxRewindSize && rewindPos == 0) { + // move the marker one position (~expensive) + resetPos = pos-(maxRewindSize/2); + if ( resetPos != input->reset(resetPos) ) + _CLTHROWA(CL_ERR_IO,"Unexpected reset() result"); + input->mark(maxRewindSize); + input->skip((maxRewindSize/2) - 1); + } + TCHAR ch; + readChar(ch); + + if (input == NULL) { // eof + return -1; + } + if (rewindPos == 0) { + col += 1; + if(ch == '\n') { + line++; + col = 1; + } + } else { + rewindPos--; + } + return ch; + } + + void FastCharStream::UnGet(){ +// printf("UnGet \n"); + if (input == 0) + return; + if ( pos == 0 ) { + _CLTHROWA(CL_ERR_IO,"error : No character can be UnGet"); + } + rewindPos++; + + input->reset(pos-1); + pos--; + } + + int FastCharStream::Peek() { + int c = GetNext(); + UnGet(); + return c; + } + + bool FastCharStream::Eos() const { + return input==NULL; + } + + int32_t FastCharStream::Column() const { + return col; + } + + int32_t FastCharStream::Line() const { + return line; + } +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/util/FastCharStream.h b/3rdparty/clucene/src/CLucene/util/FastCharStream.h new file mode 100644 index 0000000..24e5b56 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/FastCharStream.h @@ -0,0 +1,55 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_FastCharStream_ +#define _lucene_util_FastCharStream_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/Reader.h" + +CL_NS_DEF(util) + + /** Ported implementation of the FastCharStream class. */ + class FastCharStream:LUCENE_BASE + { + static const int32_t maxRewindSize; + int32_t pos; + int32_t rewindPos; + int64_t resetPos; + int32_t col; + int32_t line; + // read character from stream return false on error + void readChar(TCHAR &); + public: + Reader* input; + + /// Initializes a new instance of the FastCharStream class LUCENE_EXPORT. + FastCharStream(Reader* reader); + ~FastCharStream(); + + /// Returns the next TCHAR from the stream. + int GetNext(); + + void UnGet(); + + /// Returns the current top TCHAR from the input stream without removing it. + int Peek(); + + + /// Returns True if the end of stream was reached. + bool Eos() const; + + /// Gets the current column. + int32_t Column() const; + + /// Gets the current line. + int32_t Line() const; + }; +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/Misc.cpp b/3rdparty/clucene/src/CLucene/util/Misc.cpp new file mode 100644 index 0000000..42e3fd0 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/Misc.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#include "CLucene/StdHeader.h" +#include "Misc.h" + +#ifdef _CL_TIME_WITH_SYS_TIME +# include +# include +#else +# if defined(_CL_HAVE_SYS_TIME_H) +# include +# else +# include +# endif +#endif + +#ifdef _CL_HAVE_SYS_TIMEB_H +# include +#endif + +#ifdef UNDER_CE +#include +#endif + +CL_NS_DEF(util) + +uint64_t Misc::currentTimeMillis() +{ +#ifndef UNDER_CE +#if defined(_CLCOMPILER_MSVC) || defined(__MINGW32__) || defined(__BORLANDC__) + struct _timeb tstruct; + _ftime(&tstruct); + + return (((uint64_t) tstruct.time) * 1000) + tstruct.millitm; +#else + struct timeval tstruct; + if (gettimeofday(&tstruct, NULL) < 0) { + _CLTHROWA(CL_ERR_Runtime,"Error in gettimeofday call."); + } + + return (((uint64_t) tstruct.tv_sec) * 1000) + tstruct.tv_usec / 1000; +#endif +#else //UNDER_CE + QT_USE_NAMESPACE + QTime t = QTime::currentTime(); + return t.second() * 1000 + t.msec(); +#endif //UNDER_CE +} + +// #pragma mark -- char related utils + +size_t Misc::ahashCode(const char* str) +{ + // Compute the hash code using a local variable to be reentrant. + size_t hashCode = 0; + while (*str != 0) + hashCode = hashCode * 31 + *str++; + return hashCode; +} + +size_t Misc::ahashCode(const char* str, size_t len) +{ + // Compute the hash code using a local variable to be reentrant. + size_t count = len; + size_t hashCode = 0; + for (size_t i = 0; i < count; i++) + hashCode = hashCode * 31 + *str++; + return hashCode; +} + +char* Misc::ajoin(const char* a, const char* b, const char* c, const char* d, + const char* e, const char* f) +{ +#define aLEN(x) (x == NULL ? 0 : strlen(x)) + const size_t totalLen = aLEN(a) + aLEN(b) + aLEN(c) + aLEN(d) + aLEN(e) + + aLEN(f) + sizeof(char); /* Space for terminator. */ + + char* buf = _CL_NEWARRAY(char, totalLen); + buf[0] = 0; + if (a != NULL) + strcat(buf, a); + + if (b != NULL) + strcat(buf, b); + + if (c != NULL) + strcat(buf, c); + + if (d != NULL) + strcat(buf, d); + + if (e != NULL) + strcat(buf, e); + + if (f != NULL) + strcat(buf, f); + + return buf; +} + +char* Misc::segmentname(const char* segment, const char* ext, int32_t x) +{ + CND_PRECONDITION(ext != NULL, "ext is NULL"); + + char* buf = _CL_NEWARRAY(char, CL_MAX_PATH); + if (x == -1) + _snprintf(buf, CL_MAX_PATH, "%s%s", segment, ext); + else + _snprintf(buf, CL_MAX_PATH, "%s%s%d", segment, ext, x); + return buf; +} + +void Misc::segmentname(char* buffer, int32_t bufferLen, const char* segment, + const char* ext, int32_t x) +{ + CND_PRECONDITION(buffer != NULL, "buffer is NULL"); + CND_PRECONDITION(segment != NULL, "segment is NULL"); + CND_PRECONDITION(ext != NULL, "extention is NULL"); + + if (x == -1) + _snprintf(buffer, bufferLen, "%s%s", segment, ext); + else + _snprintf(buffer, bufferLen, "%s%s%d", segment, ext, x); +} + +// #pragma mark -- qt related utils + +size_t Misc::qhashCode(const QString& str) +{ + size_t hashCode = 0; + for (int i = 0; i < str.count(); ++i) + hashCode = hashCode * 31 + str.at(i).unicode(); + return hashCode; +} + +size_t Misc::qhashCode(const QString& str, size_t len) +{ + size_t count = len; + size_t hashCode = 0; + for (size_t i = 0; i < count; ++i) + hashCode = hashCode * 31 + str.at(i).unicode(); + return hashCode; +} + +QString Misc::qjoin(const QString &a, const QString &b, const QString &c, + const QString &d, const QString &e, const QString &f) +{ + QString buffer; + + if (!a.isNull() && !a.isEmpty()) + buffer.append(a); + + if (!b.isNull() && !b.isEmpty()) + buffer.append(b); + + if (!c.isNull() && !c.isEmpty()) + buffer.append(c); + + if (!d.isNull() && !d.isEmpty()) + buffer.append(d); + + if (!e.isNull() && !e.isEmpty()) + buffer.append(e); + + if (!f.isNull() && !f.isEmpty()) + buffer.append(f); + + return buffer; +} + +QString Misc::segmentname(const QString& segment, const QString& ext, int32_t x) +{ + CND_PRECONDITION(!ext.isEmpty(), "ext is NULL"); + + if (x == -1) + return QString(segment + ext); + + QString buf(QLatin1String("%1%2%3")); + return buf.arg(segment).arg(ext).arg(x); +} + +void Misc::segmentname(QString& buffer, int32_t bufferLen, + const QString& segment, const QString& ext, int32_t x) +{ + CND_PRECONDITION(!segment.isEmpty(), "segment is NULL"); + CND_PRECONDITION(!ext.isEmpty(), "extention is NULL"); + + buffer = segment + ext; + if (x != -1) + buffer += QString::number(x); +} + +// #pragma mark -- TCHAR related utils + +int32_t Misc::stringDifference(const TCHAR* s1, int32_t len1, const TCHAR* s2, + int32_t len2) +{ + int32_t len = len1 < len2 ? len1 : len2; + for (int32_t i = 0; i < len; i++) + if (s1[i] != s2[i]) + return i; + return len; +} + +/* DSR:CL_BUG: (See comment for join method in Misc.h): */ +TCHAR* Misc::join (const TCHAR* a, const TCHAR* b, const TCHAR* c, + const TCHAR* d, const TCHAR* e, const TCHAR* f) +{ +#define LEN(x) (x == NULL ? 0 : _tcslen(x)) + const size_t totalLen = LEN(a) + LEN(b) + LEN(c) + LEN(d) + LEN(e) + LEN(f) + + sizeof(TCHAR); /* Space for terminator. */ + + TCHAR* buf = _CL_NEWARRAY(TCHAR, totalLen); + buf[0] = 0; + if (a != NULL) + _tcscat(buf, a); + + if (b != NULL) + _tcscat(buf, b); + + if (c != NULL) + _tcscat(buf, c); + + if (d != NULL) + _tcscat(buf, d); + + if (e != NULL) + _tcscat(buf, e); + + if (f != NULL) + _tcscat(buf, f); + + return buf; +} + +#ifdef _UCS2 + +size_t Misc::whashCode(const wchar_t* str) +{ + // Compute the hash code using a local variable to be reentrant. + size_t hashCode = 0; + while (*str != 0) + hashCode = hashCode * 31 + *str++; + return hashCode; +} + +size_t Misc::whashCode(const wchar_t* str, size_t len) +{ + // Compute the hash code using a local variable to be reentrant. + size_t count = len; + size_t hashCode = 0; + for (size_t i = 0; i < count; i++) + hashCode = hashCode * 31 + *str++; + return hashCode; +} + +char* Misc::_wideToChar(const wchar_t* s CL_FILELINEPARAM) +{ + size_t len = _tcslen(s); + char* msg = _CL_NEWARRAY(char, len + 1); + _cpywideToChar(s, msg, len + 1); + return msg; +} + +void Misc::_cpywideToChar(const wchar_t* s, char* d, size_t len) +{ + size_t sLen = wcslen(s); + for (uint32_t i = 0; i < len && i < sLen + 1; i++) + d[i] = LUCENE_OOR_CHAR(s[i]); +} + +wchar_t* Misc::_charToWide(const char* s CL_FILELINEPARAM) +{ + size_t len = strlen(s); + wchar_t* msg = _CL_NEWARRAY(wchar_t, len + 1); + _cpycharToWide(s, msg, len + 1); + return msg; +} + +void Misc::_cpycharToWide(const char* s, wchar_t* d, size_t len) +{ + size_t sLen = strlen(s); + for (uint32_t i = 0; i < len && i < sLen + 1; i++) + d[i] = s[i]; +} + +#endif + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/util/Misc.h b/3rdparty/clucene/src/CLucene/util/Misc.h new file mode 100644 index 0000000..561c6e4 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/Misc.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team + * + * Distributable under the terms of either the Apache License (Version 2.0) or + * the GNU Lesser General Public License, as specified in the COPYING file. + * + * Changes are Copyright(C) 2007, 2008 by Nokia Corporation and/or its subsidiary(-ies), all rights reserved. +*/ +#ifndef _lucene_util_Misc_H +#define _lucene_util_Misc_H + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include + +CL_NS_DEF(util) + +class Misc +{ +public: + static uint64_t currentTimeMillis(); + + static size_t ahashCode(const char* str); + static size_t ahashCode(const char* str, size_t len); + static char* ajoin(const char* a, const char* b, const char* c = NULL, + const char* d = NULL, const char* e = NULL, const char* f = NULL); + static char* segmentname(const char* segment, const char* ext, int32_t x = -1); + static void segmentname(char* buffer, int32_t bufferLen, const char* segment, + const char* ext, int32_t x = -1); + + static size_t qhashCode(const QString& str); + static size_t qhashCode(const QString& str, size_t len); + static QString qjoin(const QString& a, const QString& b, + const QString& c = QString(), const QString& d = QString(), + const QString& e = QString(), const QString& f = QString()); + static QString segmentname(const QString& segment, const QString& ext, + int32_t x = -1 ); + static void segmentname(QString& buffer, int32_t bufferLen, + const QString& Segment, const QString& ext, int32_t x = -1); + + // Compares two strings, character by character, and returns the + // first position where the two strings differ from one another. + // + // @param s1 The first string to compare + // @param s1Len The length of the first string to compare + // @param s2 The second string to compare + // @param s2Len The length of the second string to compare + // @return The first position where the two strings differ. + static int32_t stringDifference(const TCHAR* s1, int32_t s1Len, + const TCHAR* s2, int32_t s2Len); + static TCHAR* join (const TCHAR* a, const TCHAR* b, const TCHAR* c = NULL, + const TCHAR* d = NULL, const TCHAR* e = NULL, const TCHAR* f = NULL ); + +#ifdef _UCS2 + static size_t whashCode(const wchar_t* str); + static size_t whashCode(const wchar_t* str, size_t len); + +# define thashCode whashCode + + static char* _wideToChar(const wchar_t* s CL_FILELINEPARAM); + static void _cpywideToChar(const wchar_t* s, char* d, size_t len); + + static wchar_t* _charToWide(const char* s CL_FILELINEPARAM); + static void _cpycharToWide(const char* s, wchar_t* d, size_t len); + +#else +# define thashCode ahashCode +#endif +}; + +CL_NS_END + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/PriorityQueue.h b/3rdparty/clucene/src/CLucene/util/PriorityQueue.h new file mode 100644 index 0000000..45649ee --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/PriorityQueue.h @@ -0,0 +1,177 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_PriorityQueue_ +#define _lucene_util_PriorityQueue_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif +CL_NS_DEF(util) + +// A PriorityQueue maintains a partial ordering of its elements such that the +// least element can always be found in constant time. Put()'s and pop()'s +// require log(size) time. +template class PriorityQueue:LUCENE_BASE { + private: + _type* heap; //(was object[]) + size_t _size; + bool dk; + size_t maxSize; + + void upHeap(){ + size_t i = _size; + _type node = heap[i]; // save bottom node (WAS object) + int32_t j = ((uint32_t)i) >> 1; + while (j > 0 && lessThan(node,heap[j])) { + heap[i] = heap[j]; // shift parents down + i = j; + j = ((uint32_t)j) >> 1; + } + heap[i] = node; // install saved node + } + void downHeap(){ + size_t i = 1; + _type node = heap[i]; // save top node + size_t j = i << 1; // find smaller child + size_t k = j + 1; + if (k <= _size && lessThan(heap[k], heap[j])) { + j = k; + } + while (j <= _size && lessThan(heap[j],node)) { + heap[i] = heap[j]; // shift up child + i = j; + j = i << 1; + k = j + 1; + if (k <= _size && lessThan(heap[k], heap[j])) { + j = k; + } + } + heap[i] = node; // install saved node + } + + protected: + PriorityQueue(){ + this->_size = 0; + this->dk = false; + this->heap = NULL; + this->maxSize = 0; + } + + // Determines the ordering of objects in this priority queue. Subclasses + // must define this one method. + virtual bool lessThan(_type a, _type b)=0; + + // Subclass constructors must call this. + void initialize(const int32_t maxSize, bool deleteOnClear){ + _size = 0; + dk = deleteOnClear; + int32_t heapSize = maxSize + 1; + heap = _CL_NEWARRAY(_type,heapSize); + this->maxSize = maxSize; + } + + public: + virtual ~PriorityQueue(){ + clear(); + _CLDELETE_ARRAY(heap); + } + + /** + * Adds an Object to a PriorityQueue in log(size) time. + * If one tries to add more objects than maxSize from initialize + * a RuntimeException (ArrayIndexOutOfBound) is thrown. + */ + void put(_type element){ + if ( _size>=maxSize ) + _CLTHROWA(CL_ERR_IndexOutOfBounds,"add is out of bounds"); + + ++_size; + heap[_size] = element; + upHeap(); + } + + /** + * Adds element to the PriorityQueue in log(size) time if either + * the PriorityQueue is not full, or not lessThan(element, top()). + * @param element + * @return true if element is added, false otherwise. + */ + bool insert(_type element){ + if(_size < maxSize){ + put(element); + return true; + }else if(_size > 0 && !lessThan(element, top())){ + if ( dk ){ + _valueDeletor::doDelete(heap[1]); + } + heap[1] = element; + adjustTop(); + return true; + }else + return false; + } + + /** + * Returns the least element of the PriorityQueue in constant time. + */ + _type top(){ + if (_size > 0) + return heap[1]; + else + return NULL; + } + + /** Removes and returns the least element of the PriorityQueue in log(size) + * time. + */ + _type pop(){ + if (_size > 0) { + _type result = heap[1]; // save first value + heap[1] = heap[_size]; // move last to first + + heap[_size] = (_type)0; // permit GC of objects + --_size; + downHeap(); // adjust heap + return result; + } else + return (_type)NULL; + } + + /**Should be called when the object at top changes values. Still log(n) + worst case, but it's at least twice as fast to

+		    { pq.top().change(); pq.adjustTop(); }
+		   
instead of
+		    { o = pq.pop(); o.change(); pq.push(o); }
+		   
+ */ + void adjustTop(){ + downHeap(); + } + + + /** + * Returns the number of elements currently stored in the PriorityQueue. + */ + size_t size(){ + return _size; + } + + /** + * Removes all entries from the PriorityQueue. + */ + void clear(){ + for (size_t i = 1; i <= _size; ++i){ + if ( dk ){ + _valueDeletor::doDelete(heap[i]); + } + } + _size = 0; + } + }; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/Reader.cpp b/3rdparty/clucene/src/CLucene/util/Reader.cpp new file mode 100644 index 0000000..1ce9710 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/Reader.cpp @@ -0,0 +1,186 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "Reader.h" + +CL_NS_DEF(util) + +StringReader::StringReader ( const TCHAR* value ): + Reader(NULL,true){ + reader = new jstreams::StringReader(value); +} +StringReader::StringReader ( const TCHAR* value, const int32_t length ): + Reader(NULL,true){ + reader = new jstreams::StringReader(value,length); +} +StringReader::StringReader ( const TCHAR* value, const int32_t length, bool copyData ): + Reader(NULL,true){ + reader = new jstreams::StringReader(value,length, copyData); +} +StringReader::~StringReader(){ +} + + +FileReader::FileReader ( const char* path, const char* enc, + const int32_t cachelen, const int32_t /*cachebuff*/ ): + Reader(NULL, true) +{ + this->input = new jstreams::FileInputStream(path, cachelen); + this->reader = new SimpleInputStreamReader(this->input,enc); //(this is a jstream object) +} + +FileReader::~FileReader (){ + if (input) + delete input; +} +int32_t FileReader::read(const TCHAR*& start, int32_t _min, int32_t _max) { + return reader->read(start, _min, _max); +} +int64_t FileReader::mark(int32_t readlimit) { + return reader->mark(readlimit); +} +int64_t FileReader::reset(int64_t newpos) { + return reader->reset(newpos); +} + + + +SimpleInputStreamReader::SimpleInputStreamReader(jstreams::StreamBase *i, const char* enc) +{ + finishedDecoding = false; + input = i; + charbuf.setSize(262); + + if ( strcmp(enc,"ASCII")==0 ) + encoding = ASCII; +#ifdef _UCS2 + else if ( strcmp(enc,"UTF-8")==0 ) + encoding = UTF8; + else if ( strcmp(enc,"UCS-2LE")==0 ) + encoding = UCS2_LE; +#endif + else + _CLTHROWA(CL_ERR_IllegalArgument,"Unsupported encoding, use jstreams iconv based instead"); + + mark(262); + charsLeft = 0; +} +SimpleInputStreamReader::~SimpleInputStreamReader(){ + input = NULL; +} +int32_t SimpleInputStreamReader::decode(TCHAR* start, int32_t space){ + // decode from charbuf + const char *inbuf = charbuf.readPos; + const char *inbufend = charbuf.readPos + charbuf.avail; + TCHAR *outbuf = start; + const TCHAR *outbufend = outbuf + space; + + if ( encoding == ASCII ){ + while ( outbuf inbufend ){ + break; //character incomplete + }else{ + size_t rd = lucene_utf8towc(outbuf,inbuf,inbufend-inbuf); + if ( rd == 0 ){ + error = "Invalid multibyte sequence."; + status = jstreams::Error; + return -1; + }else{ + inbuf+=rd; + outbuf++; + } + } + } +#endif //_UCS2 + }else + _CLTHROWA(CL_ERR_Runtime,"Unexpected encoding"); + + if ( outbuf < outbufend ) { + //we had enough room to convert the entire input + if ( inbuf < inbufend ) { + // last character is incomplete + // move from inbuf to the end to the start of + // the buffer + memmove(charbuf.start, inbuf, inbufend-inbuf); + charbuf.readPos = charbuf.start; + charbuf.avail = inbufend-inbuf; + } else if ( outbuf < outbufend ) { //input sequence was completely converted + charbuf.readPos = charbuf.start; + charbuf.avail = 0; + if (input == NULL) { + finishedDecoding = true; + } + } + } else { + charbuf.readPos += charbuf.avail - (inbufend-inbuf); + charbuf.avail = inbufend-inbuf; + } + return outbuf-start; +} + +int32_t SimpleInputStreamReader::fillBuffer(TCHAR* start, int32_t space) { + // fill up charbuf + if (input && charbuf.readPos == charbuf.start) { + const char *begin; + int32_t numRead; + numRead = input->read(begin, 1, charbuf.size - charbuf.avail); + //printf("filled up charbuf\n"); + if (numRead < -1) { + error = input->getError(); + status = jstreams::Error; + input = 0; + return numRead; + } + if (numRead < 1) { + // signal end of input buffer + input = 0; + if (charbuf.avail) { + error = "stream ends on incomplete character"; + status = jstreams::Error; + } + return -1; + } + // copy data into other buffer + memmove( charbuf.start + charbuf.avail, begin, numRead * sizeof(char)); + charbuf.avail = numRead + charbuf.avail; + } + // decode + int32_t n = decode(start, space); + //printf("decoded %i\n", n); + return n; +} + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/util/Reader.h b/3rdparty/clucene/src/CLucene/util/Reader.h new file mode 100644 index 0000000..6b018b3 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/Reader.h @@ -0,0 +1,138 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_Reader_ +#define _lucene_util_Reader_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "streambase.h" +#include "stringreader.h" +#include "fileinputstream.h" +#include "bufferedstream.h" + +CL_NS_DEF(util) +/** +* An inline wrapper that reads from Jos van den Oever's jstreams +*/ +class Reader:LUCENE_BASE { +typedef jstreams::StreamBase jsReader; +public: + bool deleteReader; + jsReader* reader; + + Reader(jsReader* reader, bool deleteReader){ + this->reader = reader; + this->deleteReader = deleteReader; + } + virtual ~Reader(){ + if ( deleteReader ) + delete reader; + reader = NULL; + } + inline int read(){ + const TCHAR*b; + int32_t nread = reader->read(b, 1,1); + if ( nread < -1 ) //if not eof + _CLTHROWA(CL_ERR_IO,reader->getError() ); + else if ( nread == -1 ) + return -1; + else + return b[0]; + } + /** + * Read at least 1 character, and as much as is conveniently available + */ + inline int32_t read(const TCHAR*& start){ + int32_t nread = reader->read(start,1,0); + if ( nread < -1 ) //if not eof + _CLTHROWA(CL_ERR_IO,reader->getError()); + else + return nread; + } + inline int32_t read(const TCHAR*& start, int32_t len){ + int32_t nread = reader->read(start, len, len); + if ( nread < -1 ) //if not eof + _CLTHROWA(CL_ERR_IO,reader->getError()); + else + return nread; + } + inline int64_t skip(int64_t ntoskip){ + int64_t skipped = reader->skip(ntoskip); + if ( skipped < 0 ) + _CLTHROWA(CL_ERR_IO,reader->getError()); + else + return skipped; + } + inline int64_t mark(int32_t readAheadlimit){ + int64_t pos = reader->mark(readAheadlimit); + if ( pos < 0 ) + _CLTHROWA(CL_ERR_IO,reader->getError()); + else + return pos; + } + int64_t reset(int64_t pos){ + int64_t r = reader->reset(pos); + if ( r < 0 ) + _CLTHROWA(CL_ERR_IO,reader->getError()); + else + return r; + } +}; + +///A helper class which constructs a the jstreams StringReader. +class StringReader: public Reader{ +public: + StringReader ( const TCHAR* value ); + StringReader ( const TCHAR* value, const int32_t length ); + StringReader ( const TCHAR* value, const int32_t length, bool copyData ); + ~StringReader(); +}; + +/** A very simple inputstreamreader implementation. For a +* more complete InputStreamReader, use the jstreams version +* located in the contrib package +*/ +class SimpleInputStreamReader: public jstreams::BufferedInputStream{ + int32_t decode(TCHAR* start, int32_t space); + int encoding; + enum{ + ASCII=1, + UTF8=2, + UCS2_LE=3 + }; + bool finishedDecoding; + jstreams::StreamBase* input; + int32_t charsLeft; + + jstreams::InputStreamBuffer charbuf; + int32_t fillBuffer(TCHAR* start, int32_t space); +public: + SimpleInputStreamReader(jstreams::StreamBase *i, const char* encoding); + ~SimpleInputStreamReader(); +}; + +/** +* A helper class which constructs a FileReader with a specified +* simple encodings, or a given inputstreamreader +*/ +class FileReader: public Reader{ + jstreams::FileInputStream* input; +public: + FileReader ( const char* path, const char* enc, + const int32_t cachelen = 13, + const int32_t cachebuff = 14 ); //todo: optimise these cache values + ~FileReader (); + + int32_t read(const TCHAR*& start, int32_t _min, int32_t _max); + int64_t mark(int32_t readlimit); + int64_t reset(int64_t); +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/StringBuffer.cpp b/3rdparty/clucene/src/CLucene/util/StringBuffer.cpp new file mode 100644 index 0000000..b5f1ca2 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/StringBuffer.cpp @@ -0,0 +1,335 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "StringBuffer.h" +#include "Misc.h" + +CL_NS_DEF(util) + + StringBuffer::StringBuffer(TCHAR* buf,int32_t maxlen, const bool consumeBuffer){ + buffer = buf; + bufferLength = maxlen; + bufferOwner = !consumeBuffer; + len = 0; + } + StringBuffer::StringBuffer(){ + //Func - Constructor. Allocates a buffer with the default length. + //Pre - true + //Post - buffer of length bufferLength has been allocated + + //Initialize + bufferLength = LUCENE_DEFAULT_TOKEN_BUFFER_SIZE; + len = 0; + //Allocate a buffer of length bufferLength + buffer = _CL_NEWARRAY(TCHAR,bufferLength); + bufferOwner = true; + } + + StringBuffer::StringBuffer(const int32_t initSize){ + //Func - Constructor. Allocates a buffer of length initSize + 1 + //Pre - initSize > 0 + //Post - A buffer has been allocated of length initSize + 1 + + //Initialize the bufferLength to initSize + 1 The +1 is for the terminator '\0' + bufferLength = initSize + 1; + len = 0; + //Allocate a buffer of length bufferLength + buffer = _CL_NEWARRAY(TCHAR,bufferLength); + bufferOwner = true; + } + + StringBuffer::StringBuffer(const TCHAR* value){ + //Func - Constructor. + // Creates an instance of Stringbuffer containing a copy of the string value + //Pre - value != NULL + //Post - An instance of StringBuffer has been created containing the copy of the string value + + //Initialize the length of the string to be stored in buffer + len = (int32_t) _tcslen(value); + + //Calculate the space occupied in buffer by a copy of value + const int32_t occupiedLength = len + 1; + + // Minimum allocated buffer length is LUCENE_DEFAULT_TOKEN_BUFFER_SIZE. + bufferLength = (occupiedLength >= LUCENE_DEFAULT_TOKEN_BUFFER_SIZE + ? occupiedLength : LUCENE_DEFAULT_TOKEN_BUFFER_SIZE); + + //Allocate a buffer of length bufferLength + buffer = _CL_NEWARRAY(TCHAR,bufferLength); + bufferOwner = true; + //Copy the string value into buffer + _tcsncpy(buffer, value, occupiedLength); + //Assert that the buffer has been terminated at the end of the string + CND_PRECONDITION (buffer[len] == '\0', "Buffer was not correctly terminated"); + } + + StringBuffer::~StringBuffer() { + // Func - Destructor + // Pre - true + // Post - Instanc has been destroyed + + if( bufferOwner ){ + _CLDELETE_CARRAY(buffer); + }else + buffer = NULL; + } + void StringBuffer::clear(){ + //Func - Clears the Stringbuffer and resets it to it default empty state + //Pre - true + //Post - pre(buffer) has been destroyed and a new one has been allocated + + //Destroy the current buffer if present + _CLDELETE_CARRAY(buffer); + + //Initialize + len = 0; + bufferLength = LUCENE_DEFAULT_TOKEN_BUFFER_SIZE; + //Allocate a buffer of length bufferLength + buffer = _CL_NEWARRAY(TCHAR,bufferLength); + } + + void StringBuffer::appendChar(const TCHAR character) { + //Func - Appends a single character + //Pre - true + //Post - The character has been appended to the string in the buffer + + //Check if the current buffer length is sufficient to have the string value appended + if (len + 1 > bufferLength){ + //Have the size of the current string buffer increased because it is too small + growBuffer(len + 1); + } + //Put character at position len which is the end of the string in the buffer + //Note that this action might overwrite the terminator of the string '\0', which + //is kind of tricky + buffer[len] = character; + //Increase the len by to represent the correct length of the string in the buffer + len++; + } + + void StringBuffer::append(const TCHAR* value) { + //Func - Appends a copy of the string value + //Pre - value != NULL + //Post - value has been copied and appended to the string in buffer + + append(value, _tcslen(value)); + } + void StringBuffer::append(const TCHAR* value, size_t appendedLength) { + //Func - Appends a copy of the string value + //Pre - value != NULL + // appendedLength contains the length of the string value which is to be appended + //Post - value has been copied and appended to the string in buffer + + //Check if the current buffer length is sufficient to have the string value appended + if (len + appendedLength + 1 > bufferLength){ + //Have the size of the current string buffer increased because it is too small + growBuffer(len + appendedLength + 1); + } + + //Copy the string value into the buffer at postion len + _tcsncpy(buffer + len, value, appendedLength); + + //Add the length of the copied string to len to reflect the new length of the string in + //the buffer (Note: len is not the bufferlength!) + len += appendedLength; + } + + void StringBuffer::appendInt(const int32_t value) { + //Func - Appends an integer (after conversion to a character string) + //Pre - true + //Post - The converted integer value has been appended to the string in buffer + + //instantiate a buffer of 30 charactes for the conversion of the integer + TCHAR buf[30]; + //Convert the integer value to a string buf using the radix 10 (duh) + _i64tot(value, buf, 10); + //Have the converted integer now stored in buf appended to the string in buffer + append(buf); + } + + void StringBuffer::appendFloat(const qreal value, const int32_t digits){ + //Func - Appends a qreal (after conversion to a character string) + //Pre - digits > 0. Indicates the minimum number of characters printed + //Post - The converted qreal value has been appended to the string in buffer + + //using sprintf("%f" was not reliable on other plaforms... we use a custom float convertor + //bvk: also, using sprintf and %f seems excessivelly slow + if(digits>8) + _CLTHROWA(CL_ERR_IllegalArgument,"Too many digits..."); + + //the maximum number of characters that int64 will hold is 23. so we need 23*2+2 + TCHAR buf[48]; //the buffer to hold + int64_t v = (int64_t)value; //the integer value of the float + _i64tot(v,buf,10); //add the whole number + + size_t len = 99-_tcslen(buf); //how many digits we have to work with? + size_t dig = len< (size_t)digits ? len : digits; + if ( dig > 0 ){ + _tcscat(buf,_T(".")); //add a decimal point + + int64_t remi=(int64_t)((value-v)*pow((qreal)10,(qreal)(dig+1))); //take the remainder and make a whole number + if ( remi<0 ) remi*=-1; + int64_t remadj=remi/10; + if ( remi-(remadj*10) >=5 ) + remadj++; //adjust remainder + + // add as many zeros as necessary between the decimal point and the + // significant part of the number. Fixes a bug when trying to print + // numbers that have zeros right after the decimal point + if (remadj) { + int32_t numZeros = dig - (int32_t)log10((qreal)remadj) - 1; + while(numZeros-- > 0) + _tcscat(buf,_T("0")); //add a zero before the decimal point + } + + _i64tot(remadj,buf+_tcslen(buf),10); //add the remainder + } + + append(buf); + } + + void StringBuffer::prepend(const TCHAR* value){ + //Func - Puts a copy of the string value infront of the current string in the StringBuffer + //Pre - value != NULL + //Post - The string in pre(buffer) has been shifted n positions where n equals the length of value. + // The string value was then copied to the beginning of stringbuffer + + prepend(value, _tcslen(value)); + } + + void StringBuffer::prepend(const TCHAR* value, const size_t prependedLength) { + //Func - Puts a copy of the string value in front of the string in the StringBuffer + //Pre - value != NULL + // prependedLength contains the length of the string value which is to be prepended + //Post - A copy of the string value is has been in front of the string in buffer + //todo: something is wrong with this code, i'm sure... it only grows (and therefore moves if the buffer is to small) + //Check if the current buffer length is sufficient to have the string value prepended + if (prependedLength + len + 1 > bufferLength){ + //Have the size of the current string buffer increased because it is too small + //Because prependedLength is passed as the second argument to growBuffer, + //growBuffer will have left the first prependedLength characters empty + //when it recopied buffer during reallocation. + growBuffer(prependedLength + len + 1, prependedLength); + } + + //Copy the string value into the buffer at postion 0 + _tcsncpy(buffer, value, prependedLength); + //Add the length of the copied string to len to reflect the new length of the string in + //the buffer (Note: len is not the bufferlength!) + len += prependedLength; + } + + int32_t StringBuffer::length() const{ + //Func - Returns the length of the string in the StringBuffer + //Pre - true + //Post - The length len of the string in the buffer has been returned + + return len; + } + TCHAR* StringBuffer::toString(){ + //Func - Returns a copy of the current string in the StringBuffer sized equal to the length of the string + // in the StringBuffer. + //Pre - true + //Post - The copied string has been returned + + //Instantiate a buffer equal to the length len + 1 + TCHAR* ret = _CL_NEWARRAY(TCHAR,len + 1); + if (ret){ + //Copy the string in buffer + _tcsncpy(ret, buffer, len); + //terminate the string + ret[len] = '\0'; + } + //return the the copy + return ret; + } + TCHAR* StringBuffer::getBuffer() { + //Func - '\0' terminates the buffer and returns its pointer + //Pre - true + //Post - buffer has been '\0' terminated and returned + + // Check if the current buffer is '\0' terminated + if (len == bufferLength){ + //Make space for terminator, if necessary. + growBuffer(len + 1); + } + //'\0' buffer so it can be returned properly + buffer[len] = '\0'; + + return buffer; + } + + void StringBuffer::reserve(const int32_t size){ + if ( bufferLength >= size ) + return; + bufferLength = size; + + //Allocate a new buffer of length bufferLength + TCHAR* tmp = _CL_NEWARRAY(TCHAR,bufferLength); + _tcsncpy(tmp, buffer, len); + tmp[len] = '\0'; + + //destroy the old buffer + if (buffer){ + _CLDELETE_CARRAY(buffer); + } + //Assign the new buffer tmp to buffer + buffer = tmp; + } + + void StringBuffer::growBuffer(const int32_t minLength) { + //Func - Has the buffer grown to a minimum length of minLength or bigger + //Pre - minLength >= len + 1 + //Post - The buffer has been grown to a minimum length of minLength or bigger + + growBuffer(minLength, 0); + } + void StringBuffer::growBuffer(const int32_t minLength, const int32_t skippingNInitialChars) { + //Func - Has the buffer grown to a minimum length of minLength or bigger and shifts the + // current string in buffer by skippingNInitialChars forward + //Pre - After growth, must have at least enough room for contents + terminator so + // minLength >= skippingNInitialChars + len + 1 + // skippingNInitialChars >= 0 + //Post - The buffer has been grown to a minimum length of minLength or bigger and + // if skippingNInitialChars > 0, the contents of the buffer has beeen shifted + // forward by skippingNInitialChars positions as the buffer is reallocated, + // leaving the first skippingNInitialChars uninitialized (presumably to be + // filled immediately thereafter by the caller). + + CND_PRECONDITION (skippingNInitialChars >= 0, "skippingNInitialChars is less than zero"); + CND_PRECONDITION (minLength >= skippingNInitialChars + len + 1,"skippingNInitialChars is not large enough"); + + //More aggressive growth strategy to offset smaller default buffer size: + if ( !bufferOwner ){ + if ( bufferLength 0 ){ + printf("ERROR: stringaPool still contains intern'd strings (refcounts):\n"); + __strintrntype::iterator itr = stringaPool.begin(); + while ( itr != stringaPool.end() ){ + printf(" %s (%d)\n",(itr->first), (itr->second)); + ++itr; + } + } + + if ( stringPool.size() > 0 ){ + printf("ERROR: stringPool still contains intern'd strings (refcounts):\n"); + __wcsintrntype::iterator itr = stringPool.begin(); + while ( itr != stringPool.end() ){ + _tprintf(_T(" %s (%d)\n"),(itr->first), (itr->second)); + ++itr; + } + } + #endif + } + + const TCHAR* CLStringIntern::intern(const TCHAR* str CL_FILELINEPARAM){ + if ( str == NULL ) + return NULL; + if ( str[0] == 0 ) + return LUCENE_BLANK_STRING; + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + __wcsintrntype::iterator itr = stringPool.find(str); + if ( itr==stringPool.end() ){ +#ifdef _UCS2 + TCHAR* ret = lucenewcsdup(str CL_FILELINEREF); +#else + TCHAR* ret = lucenestrdup(str CL_FILELINEREF); +#endif + stringPool[ret]= 1; + return ret; + }else{ + (itr->second)++; + return itr->first; + } + } + + bool CLStringIntern::unintern(const TCHAR* str){ + if ( str == NULL ) + return false; + if ( str[0] == 0 ) + return false; + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + __wcsintrntype::iterator itr = stringPool.find(str); + if ( itr != stringPool.end() ){ + if ( (itr->second) == 1 ){ + stringPool.removeitr(itr); + return true; + }else + (itr->second)--; + } + return false; + } + + const char* CLStringIntern::internA(const char* str CL_FILELINEPARAM){ + if ( str == NULL ) + return NULL; + if ( str[0] == 0 ) + return _LUCENE_BLANK_ASTRING; + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + __strintrntype::iterator itr = stringaPool.find(str); + if ( itr==stringaPool.end() ){ + char* ret = lucenestrdup(str CL_FILELINE); + stringaPool[ret] = 1; + return ret; + }else{ + (itr->second)++; + return itr->first; + } + } + + bool CLStringIntern::uninternA(const char* str){ + if ( str == NULL ) + return false; + if ( str[0] == 0 ) + return false; + + SCOPED_LOCK_MUTEX(THIS_LOCK) + + __strintrntype::iterator itr = stringaPool.find(str); + if ( itr!=stringaPool.end() ){ + if ( (itr->second) == 1 ){ + stringaPool.removeitr(itr); + return true; + }else + (itr->second)--; + } + return false; + } + + /* removed because of multi-threading problems... + __wcsintrntype::iterator CLStringIntern::internitr(const TCHAR* str CL_FILELINEPARAM){ + if ( str[0] == 0 ){ + if ( !blanksinitd ){ + CLStringIntern::stringPool.put(LUCENE_BLANK_STRING,1); + wblank=stringPool.find(str); + blanksinitd=true; + } + return wblank; + } + __wcsintrntype::iterator itr = stringPool.find(str); + if (itr==stringPool.end()){ +#ifdef _UCS2 + TCHAR* ret = lucenewcsdup(str CL_FILELINEREF); +#else + TCHAR* ret = lucenestrdup(str CL_FILELINEREF); +#endif + stringPool.put(ret,1); + return stringPool.find(str); + }else{ + (itr->second)++; + return itr; + } + } + bool CLStringIntern::uninternitr(__wcsintrntype::iterator itr){ + if ( itr!=stringPool.end() ){ + if ( itr==wblank ) + return false; + if ( (itr->second) == 1 ){ + stringPool.removeitr(itr); + return true; + }else + (itr->second)--; + } + return false; + } +*/ + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/util/StringIntern.h b/3rdparty/clucene/src/CLucene/util/StringIntern.h new file mode 100644 index 0000000..ded060c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/StringIntern.h @@ -0,0 +1,61 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_StringIntern_H +#define _lucene_util_StringIntern_H + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "VoidMap.h" +CL_NS_DEF(util) +typedef CL_NS(util)::CLHashMap __wcsintrntype; +typedef CL_NS(util)::CLHashMap __strintrntype; + + /** Functions for intern'ing strings. This + * is a process of pooling strings thus using less memory, + * and furthermore allows intern'd strings to be directly + * compared: + * string1==string2, rather than _tcscmp(string1,string2) + */ + class CLStringIntern{ + static __wcsintrntype stringPool; + static __strintrntype stringaPool; + STATIC_DEFINE_MUTEX(THIS_LOCK) + public: + /** + * Internalise the specified string. + * \return Returns a pointer to the internalised string + */ + static const char* internA(const char* str CL_FILELINEPARAM); + /** + * Uninternalise the specified string. Decreases + * the reference count and frees the string if + * reference count is zero + * \returns true if string was destroyed, otherwise false + */ + static bool uninternA(const char* str); + + /** + * Internalise the specified string. + * \return Returns a pointer to the internalised string + */ + static const TCHAR* intern(const TCHAR* str CL_FILELINEPARAM); + + /** + * Uninternalise the specified string. Decreases + * the reference count and frees the string if + * reference count is zero + * \returns true if string was destroyed, otherwise false + */ + static bool unintern(const TCHAR* str); + + static void shutdown(); + }; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/ThreadLocal.cpp b/3rdparty/clucene/src/CLucene/util/ThreadLocal.cpp new file mode 100644 index 0000000..a54c869 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/ThreadLocal.cpp @@ -0,0 +1,55 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" +#include "CLucene/LuceneThreads.h" +#include "ThreadLocal.h" + +CL_NS_DEF(util) + +DEFINE_MUTEX(ThreadLocalBase::ThreadLocalBase_THIS_LOCK) + +ThreadLocalBase::ShutdownHooksType ThreadLocalBase::shutdownHooks(false); +ThreadLocalBase::ThreadLocalsType ThreadLocalBase::threadLocals(false,false); + +ThreadLocalBase::ThreadLocalBase(){ +} +ThreadLocalBase::~ThreadLocalBase(){ +} + +void ThreadLocalBase::UnregisterCurrentThread(){ + _LUCENE_THREADID_TYPE id = _LUCENE_CURRTHREADID; + SCOPED_LOCK_MUTEX(ThreadLocalBase_THIS_LOCK) + + ThreadLocalsType::iterator itr = threadLocals.lower_bound(id); + ThreadLocalsType::iterator end = threadLocals.upper_bound(id); + while ( itr != end ){ + itr->second->setNull(); + ++itr; + } +} +void ThreadLocalBase::shutdown(){ + SCOPED_LOCK_MUTEX(ThreadLocalBase_THIS_LOCK) + + ThreadLocalsType::iterator itr = threadLocals.begin(); + while ( itr != threadLocals.end() ){ + itr->second->setNull(); + ++itr; + } + + ShutdownHooksType::iterator itr2 = shutdownHooks.begin(); + while ( itr2 != shutdownHooks.end() ){ + ShutdownHook* hook = *itr2; + hook(false); + } +} +void ThreadLocalBase::registerShutdownHook(ShutdownHook* hook){ + SCOPED_LOCK_MUTEX(ThreadLocalBase_THIS_LOCK) + shutdownHooks.insert(hook); +} + + +CL_NS_END diff --git a/3rdparty/clucene/src/CLucene/util/ThreadLocal.h b/3rdparty/clucene/src/CLucene/util/ThreadLocal.h new file mode 100644 index 0000000..f67c76c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/ThreadLocal.h @@ -0,0 +1,143 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_ThreadLocal_H +#define _lucene_util_ThreadLocal_H + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "CLucene/util/VoidMap.h" + +CL_NS_DEF(util) + +class ThreadLocalBase: LUCENE_BASE{ +public: + /** + * A hook called when CLucene is starting or shutting down, + * this can be used for setting up and tearing down static + * variables + */ + typedef void ShutdownHook(bool startup); + +protected: + STATIC_DEFINE_MUTEX(ThreadLocalBase_THIS_LOCK) + typedef CL_NS(util)::CLMultiMap<_LUCENE_THREADID_TYPE, ThreadLocalBase*, + CL_NS(util)::CLuceneThreadIdCompare, + CL_NS(util)::Deletor::ConstNullVal<_LUCENE_THREADID_TYPE>, + CL_NS(util)::Deletor::ConstNullVal > ThreadLocalsType; + static ThreadLocalsType threadLocals; + //todo: using http://en.wikipedia.org/wiki/Thread-local_storage#Pthreads_implementation + //would work better... but lots of testing would be needed first... + typedef CL_NS(util)::CLSetList, + CL_NS(util)::Deletor::ConstNullVal > ShutdownHooksType; + static ShutdownHooksType shutdownHooks; + + ThreadLocalBase(); +public: + virtual ~ThreadLocalBase(); + + /** + * Call this function to clear the local thread data for this + * ThreadLocal. Calling set(NULL) does the same thing, except + * this function is virtual and can be called without knowing + * the template. + */ + virtual void setNull() = 0; + + /** + * If you want to clean up thread specific memory, then you should + * make sure this thread is called when the thread is not going to be used + * again. This will clean up threadlocal data which can contain quite a lot + * of data, so if you are creating lots of new threads, then it is a good idea + * to use this function, otherwise there will be many memory leaks. + */ + static void UnregisterCurrentThread(); + + /** + * Call this function to shutdown CLucene + */ + static void shutdown(); + + /** + * Add this function to the shutdown hook list. This function will be called + * when CLucene is shutdown. + */ + static void registerShutdownHook(ShutdownHook* hook); +}; + +template +class ThreadLocal: public ThreadLocalBase{ + typedef CL_NS(util)::CLSet<_LUCENE_THREADID_TYPE, T, + CL_NS(util)::CLuceneThreadIdCompare, + CL_NS(util)::Deletor::ConstNullVal<_LUCENE_THREADID_TYPE>, + _deletor > LocalsType; + LocalsType locals; + DEFINE_MUTEX(locals_LOCK) +public: + ThreadLocal(); + ~ThreadLocal(); + T get(); + void setNull(); + void set(T t); +}; + +template +ThreadLocal::ThreadLocal(): + locals(false,true) +{ + //add this object to the base's list of threadlocals to be + //notified in case of UnregisterThread() + _LUCENE_THREADID_TYPE id = _LUCENE_CURRTHREADID; + SCOPED_LOCK_MUTEX(ThreadLocalBase_THIS_LOCK) + threadLocals.insert( CL_NS_STD(pair)(id, this) ); +} + +template +ThreadLocal::~ThreadLocal(){ + //remove this object to the base's list of threadlocals + _LUCENE_THREADID_TYPE id = _LUCENE_CURRTHREADID; + SCOPED_LOCK_MUTEX(ThreadLocalBase_THIS_LOCK) + + //remove all the thread local data for this object + locals.clear(); + + //remove this object from the ThreadLocalBase threadLocal list + ThreadLocalsType::iterator itr = threadLocals.lower_bound(id); + ThreadLocalsType::iterator end = threadLocals.upper_bound(id); + while ( itr != end ){ + if ( itr->second == this){ + threadLocals.erase(itr); + break; + } + ++itr; + } +} + +template +T ThreadLocal::get(){ + return locals.get(_LUCENE_CURRTHREADID); +} + +template +void ThreadLocal::setNull(){ + set(NULL); +} + +template +void ThreadLocal::set(T t){ + _LUCENE_THREADID_TYPE id = _LUCENE_CURRTHREADID; + locals.remove(id); + if ( t != NULL ) + locals.insert( CL_NS_STD(pair)(id, t) ); +} + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/VoidList.h b/3rdparty/clucene/src/CLucene/util/VoidList.h new file mode 100644 index 0000000..cd69088 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/VoidList.h @@ -0,0 +1,175 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_VoidList_ +#define _lucene_util_VoidList_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#include "Equators.h" + +CL_NS_DEF(util) + +/** +* A template to encapsulate various list type classes +* @internal +*/ +template +class __CLList:public _base,LUCENE_BASE { +private: + bool dv; + typedef _base base; +public: + DEFINE_MUTEX(THIS_LOCK) + + typedef typename _base::const_iterator const_iterator; + typedef typename _base::iterator iterator; + + virtual ~__CLList(){ + clear(); + } + + __CLList ( const bool deleteValue ): + dv(deleteValue) + { + } + + void setDoDelete(bool val){ dv=val; } + + //sets array to the contents of this array. + //array must be size+1, otherwise memory may be overwritten + void toArray(_kt* into) const{ + int i=0; + for ( const_iterator itr=base::begin();itr!=base::end();itr++ ){ + into[i] = *itr; + i++; + } + into[i] = NULL; + } + + void set(int32_t i, _kt val) { + if ( dv ) + _valueDeletor::doDelete((*this)[i]); + (*this)[i] = val; + } + + //todo: check this + void delete_back(){ + if ( base::size() > 0 ){ + iterator itr = base::end(); + if ( itr != base::begin()) + itr --; + _kt key = *itr; + base::erase(itr); + if ( dv ) + _valueDeletor::doDelete(key); + } + } + + void delete_front(){ + if ( base::size() > 0 ){ + iterator itr = base::begin(); + _kt key = *itr; + base::erase(itr); + if ( dv ) + _valueDeletor::doDelete(key); + } + } + + void clear(){ + if ( dv ){ + iterator itr = base::begin(); + while ( itr != base::end() ){ + _valueDeletor::doDelete(*itr); + ++itr; + } + } + base::clear(); + } + + void remove(int32_t i, bool dontDelete=false){ + iterator itr=base::begin(); + itr+=i; + _kt key = *itr; + base::erase( itr ); + if ( dv && !dontDelete ) + _valueDeletor::doDelete(key); + } + void remove(iterator itr, bool dontDelete=false){ + _kt key = *itr; + base::erase( itr ); + if ( dv && !dontDelete ) + _valueDeletor::doDelete(key); + } + +}; + +//growable arrays of Objects (like a collection or list) +//a list, so can contain duplicates +//it grows in chunks... todo: check jlucene for initial size of array, and growfactors +template +class CLVector:public __CLList<_kt, CL_NS_STD(vector)<_kt> , _valueDeletor> +{ +public: + CLVector ( const bool deleteValue=true ): + __CLList<_kt, CL_NS_STD(vector)<_kt> , _valueDeletor>(deleteValue) + { + } +}; + +//An array-backed implementation of the List interface +//a list, so can contain duplicates +//*** a very simple list - use +//(This class is roughly equivalent to Vector, except that it is unsynchronized.) +#define CLArrayList CLVector +#define CLHashSet CLHashList + +//implementation of the List interface, provides access to the first and last list elements in O(1) +//no comparator is required... and so can contain duplicates +//a simple list with no comparator +//*** a very simple list - use +#ifdef LUCENE_DISABLE_HASHING + #define CLHashList CLSetList +#else + +template +class CLHashList:public __CLList<_kt, CL_NS_HASHING(hash_set)<_kt,_Comparator> , _valueDeletor> +{ +public: + CLHashList ( const bool deleteValue=true ): + __CLList<_kt, CL_NS_HASHING(hash_set)<_kt,_Comparator> , _valueDeletor>(deleteValue) + { + } +}; +#endif + +template +class CLLinkedList:public __CLList<_kt, CL_NS_STD(list)<_kt> , _valueDeletor> +{ +public: + CLLinkedList ( const bool deleteValue=true ): + __CLList<_kt, CL_NS_STD(list)<_kt> , _valueDeletor>(deleteValue) + { + } +}; +template +class CLSetList:public __CLList<_kt, CL_NS_STD(set)<_kt,_Comparator> , _valueDeletor> +{ +public: + CLSetList ( const bool deleteValue=true ): + __CLList<_kt, CL_NS_STD(set)<_kt,_Comparator> , _valueDeletor>(deleteValue) + { + } +}; + +CL_NS_END +#endif diff --git a/3rdparty/clucene/src/CLucene/util/VoidMap.h b/3rdparty/clucene/src/CLucene/util/VoidMap.h new file mode 100644 index 0000000..b22b507 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/VoidMap.h @@ -0,0 +1,270 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef _lucene_util_VoidMap_ +#define _lucene_util_VoidMap_ + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + + +CL_NS_DEF(util) + +/** +* A template to encapsulate various map type classes +* @internal +*/ +template +class __CLMap:public _base,LUCENE_BASE { +private: + bool dk; + bool dv; + typedef _base base; +public: + DEFINE_MUTEX(THIS_LOCK) + + typedef typename _base::iterator iterator; + typedef typename _base::const_iterator const_iterator; + typedef CL_NS_STD(pair)<_kt, _vt> _pair; + + ///Default constructor for the __CLMap + __CLMap (): + dk(true), + dv(true) + { + } + + ///Deconstructor for the __CLMap + ~__CLMap (){ + clear(); + } + + void setDeleteKey(bool val){ dk = val; } + void setDeleteValue(bool val){ dv = val; } + + ///Construct the VoidMap and set the deleteTypes to the specified values + ///\param deleteKey if true then the key variable is deleted when an object is deleted + ///\param keyDelType delete the key variable using the specified type + ///\param deleteValue if true then the value variable is deleted when an object is deleted + ///\param valueDelType delete the value variable using the specified type + /*__CLMap ( const bool deleteKey, const bool deleteValue ): + dk(deleteKey), + dv(deleteValue) + { + }*/ + + ///checks to see if the specified key exists + ///\param k the key to check for + ///\returns true if the key exists + bool exists(_kt k)const{ + const_iterator itr = base::find(k); + bool ret = itr!=base::end(); + return ret; + } + + ///put the specified pair into the map. remove any old items first + ///\param k the key + ///\param v the value + void put(_kt k,_vt v){ + //todo: check if this is always right! + //must should look through code, for + //cases where map is not unique!!! + if ( dk || dv ) + remove(k); + + //todo: replacing the old item might be quicker... + + base::insert(_pair(k,v)); + } + + + ///using a non-const key, get a non-const value + _vt get( _kt k) const { + const_iterator itr = base::find(k); + if ( itr==base::end() ) + return _vt(); + else + return itr->second; + } + ///using a non-const key, get the actual key + _kt getKey( _kt k) const { + const_iterator itr = base::find(k); + if ( itr==base::end() ) + return _kt(); + else + return itr->first; + } + + void removeitr (iterator itr, const bool dontDeleteKey = false, const bool dontDeleteValue = false){ + //delete key&val first. This prevents potential loops (deleting object removes itself) + _kt key = itr->first; + _vt val = itr->second; + base::erase(itr); + + //keys & vals need to be deleted after erase, because the hashvalue is still needed + if ( dk && !dontDeleteKey ) + _KeyDeletor::doDelete(key); + if ( dv && !dontDeleteValue ) + _ValueDeletor::doDelete(val); + } + ///delete and optionally delete the specified key and associated value + void remove(_kt key, const bool dontDeleteKey = false, const bool dontDeleteValue = false){ + iterator itr = base::find(key); + if ( itr!=base::end() ) + removeitr(itr,dontDeleteKey,dontDeleteValue); + } + + ///clear all keys and values in the map + void clear(){ + if ( dk || dv ){ + iterator itr = base::begin(); + while ( itr!=base::end() ){ + #ifdef _CL_HAVE_EXT_HASH_MAP + removeitr(itr); + itr = base::begin(); + + #else + if ( dk ) + _KeyDeletor::doDelete(itr->first); + if ( dv ) + _ValueDeletor::doDelete(itr->second); + ++itr; + + #endif + } + } + base::clear(); + } +}; + +// makes no guarantees as to the order of the map +// cannot contain duplicate keys; each key can map to at most one value +#define CLHashtable CLHashMap + +#if defined(_CL_HAVE_GOOGLE_DENSE_HASH_MAP) +//do nothing +#elif defined(LUCENE_DISABLE_HASHING) + + //a CLSet with CLHashMap traits +template +class CLHashMap:public __CLMap<_kt,_vt, + CL_NS_STD(map)<_kt,_vt, _Compare>, + _KeyDeletor,_ValueDeletor> +{ + typedef typename CL_NS_STD(map)<_kt,_vt,_Compare> _base; + typedef __CLMap<_kt, _vt, CL_NS_STD(map)<_kt,_vt, _Compare>, + _KeyDeletor,_ValueDeletor> _this; +public: + CLHashMap ( const bool deleteKey=false, const bool deleteValue=false ) + { + _this::setDeleteKey(deleteKey); + _this::setDeleteValue(deleteValue); + } +}; +#elif defined(_CL_HAVE_EXT_HASH_MAP) + //ext/hash_map syntax +//HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized +template +class CLHashMap:public __CLMap<_kt,_vt, + CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher,_Equals>, + _KeyDeletor,_ValueDeletor> +{ + typedef __CLMap<_kt,_vt, CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher,_Equals>, + _KeyDeletor,_ValueDeletor> _this; +public: + CLHashMap ( const bool deleteKey=false, const bool deleteValue=false ) + { + _this::setDeleteKey(deleteKey); + _this::setDeleteValue(deleteValue); + } +}; + +#else +//HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized +template +class CLHashMap:public __CLMap<_kt,_vt, + CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher>, + _KeyDeletor,_ValueDeletor> +{ + typedef __CLMap<_kt,_vt, CL_NS_HASHING(hash_map)<_kt,_vt, _Hasher>, + _KeyDeletor,_ValueDeletor> _this; +public: + CLHashMap ( const bool deleteKey=false, const bool deleteValue=false ) + { + _this::setDeleteKey(deleteKey); + _this::setDeleteValue(deleteValue); + } +}; +#endif + +//A collection that contains no duplicates +//does not guarantee that the order will remain constant over time +template +class CLSet:public __CLMap<_kt,_vt, + CL_NS_STD(map)<_kt,_vt, _Compare>, + _KeyDeletor,_ValueDeletor> +{ + typedef typename CL_NS_STD(map)<_kt,_vt,_Compare> _base; + typedef __CLMap<_kt, _vt, CL_NS_STD(map)<_kt,_vt, _Compare>, + _KeyDeletor,_ValueDeletor> _this; +public: + CLSet ( const bool deleteKey=false, const bool deleteValue=false ) + { + _this::setDeleteKey(deleteKey); + _this::setDeleteValue(deleteValue); + } +}; + + +//A collection that can contains duplicates +template +class CLMultiMap:public __CLMap<_kt,_vt, + CL_NS_STD(multimap)<_kt,_vt>, + _KeyDeletor,_ValueDeletor> +{ + typedef typename CL_NS_STD(multimap)<_kt,_vt> _base; + typedef __CLMap<_kt, _vt, CL_NS_STD(multimap)<_kt,_vt>, + _KeyDeletor,_ValueDeletor> _this; +public: + CLMultiMap ( const bool deleteKey=false, const bool deleteValue=false ) + { + _this::setDeleteKey(deleteKey); + _this::setDeleteValue(deleteValue); + } +}; + + +//*** need to create a class that allows duplicates - use +//#define CLSet __CLMap +CL_NS_END + +#ifdef _CL_HAVE_GOOGLE_DENSE_HASH_MAP +#include "GoogleSparseMap.h" +#endif + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/bufferedstream.h b/3rdparty/clucene/src/CLucene/util/bufferedstream.h new file mode 100644 index 0000000..d905955 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/bufferedstream.h @@ -0,0 +1,157 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Jos van den Oever +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +/* This file is part of Strigi Desktop Search + * + * Copyright (C) 2006 Jos van den Oever + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef BUFFEREDSTREAM_H +#define BUFFEREDSTREAM_H + +#include "streambase.h" +#include "inputstreambuffer.h" + +#include +#include + +namespace jstreams { + +template +class BufferedInputStream : public StreamBase { +private: + bool finishedWritingToBuffer; + InputStreamBuffer buffer; + + void writeToBuffer(int32_t minsize); + int32_t read_(const T*& start, int32_t min, int32_t max); +protected: + /** + * This function must be implemented by the subclasses. + * It should write a maximum of @p space characters at the buffer + * position pointed to by @p start. If no more data is available due to + * end of file, -1 should be returned. If an error occurs, the status + * should be set to Error, an error message should be set and the function + * must return -1. + **/ + virtual int32_t fillBuffer(T* start, int32_t space) = 0; + // this function might be useful if you want to reuse a bufferedstream + void resetBuffer() {printf("implement 'resetBuffer'\n");} + BufferedInputStream(); +public: + int32_t read(const T*& start, int32_t min, int32_t max); + int64_t reset(int64_t); + virtual int64_t skip(int64_t ntoskip); +}; + +template +BufferedInputStream::BufferedInputStream() { + finishedWritingToBuffer = false; +} + +template +void +BufferedInputStream::writeToBuffer(int32_t ntoread) { + int32_t missing = ntoread - buffer.avail; + int32_t nwritten = 0; + while (missing > 0 && nwritten >= 0) { + int32_t space; + space = buffer.makeSpace(missing); + T* start = buffer.readPos + buffer.avail; + nwritten = fillBuffer(start, space); + assert(StreamBase::status != Eof); + if (nwritten > 0) { + buffer.avail += nwritten; + missing = ntoread - buffer.avail; + } + } + if (nwritten < 0) { + finishedWritingToBuffer = true; + } +} +template +int32_t +BufferedInputStream::read(const T*& start, int32_t min, int32_t max) { + if (StreamBase::status == Error) return -2; + if (StreamBase::status == Eof) return -1; + + // do we need to read data into the buffer? + if (!finishedWritingToBuffer && min > buffer.avail) { + // do we have enough space in the buffer? + writeToBuffer(min); + if (StreamBase::status == Error) return -2; + } + + int32_t nread = buffer.read(start, max); + + BufferedInputStream::position += nread; + if (BufferedInputStream::position > BufferedInputStream::size + && BufferedInputStream::size > 0) { + // error: we read more than was specified in size + // this is an error because all dependent code might have been labouring + // under a misapprehension + BufferedInputStream::status = Error; + BufferedInputStream::error = "Stream is longer than specified."; + nread = -2; + } else if (BufferedInputStream::status == Ok && buffer.avail == 0 + && finishedWritingToBuffer) { + BufferedInputStream::status = Eof; + if (BufferedInputStream::size == -1) { + BufferedInputStream::size = BufferedInputStream::position; + } + // save one call to read() by already returning -1 if no data is there + if (nread == 0) nread = -1; + } + return nread; +} +template +int64_t +BufferedInputStream::reset(int64_t newpos) { + if (StreamBase::status == Error) return -2; + // check to see if we have this position + int64_t d = BufferedInputStream::position - newpos; + if (buffer.readPos - d >= buffer.start && -d < buffer.avail) { + BufferedInputStream::position -= d; + buffer.avail += (int32_t)d; + buffer.readPos -= d; + StreamBase::status = Ok; + } + return StreamBase::position; +} +template +int64_t +BufferedInputStream::skip(int64_t ntoskip) { + const T *begin; + int32_t nread; + int64_t skipped = 0; + while (ntoskip) { + int32_t step = (int32_t)((ntoskip > buffer.size) ?buffer.size :ntoskip); + nread = read(begin, 1, step); + if (nread <= 0) { + return skipped; + } + ntoskip -= nread; + skipped += nread; + } + return skipped; +} +} + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/dirent.cpp b/3rdparty/clucene/src/CLucene/util/dirent.cpp new file mode 100644 index 0000000..3c5c542 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/dirent.cpp @@ -0,0 +1,221 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Matt J. Weinstein +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#include "CLucene/StdHeader.h" + +#if !defined(_CL_HAVE_DIRENT_H) && !defined(_CL_HAVE_SYS_NDIR_H) && !defined(_CL_HAVE_SYS_DIR_H) && !defined(_CL_HAVE_NDIR_H) +#include "dirent.h" + +DIR * +opendir (const char *szPath) +{ + DIR *nd; + char szFullPath[CL_MAX_PATH]; + + errno = 0; + + if (!szPath) + { + errno = EFAULT; + return NULL; + } + + if (szPath[0] == '\0') + { + errno = ENOTDIR; + return NULL; + } + + /* Attempt to determine if the given path really is a directory. */ + struct _stat rcs; + if ( _stat(szPath,&rcs) == -1) + { + /* call GetLastError for more error info */ + errno = ENOENT; + return NULL; + } + if (!(rcs.st_mode & _S_IFDIR)) + { + /* Error, entry exists but not a directory. */ + errno = ENOTDIR; + return NULL; + } + + /* Make an absolute pathname. */ + _realpath(szPath,szFullPath); + + /* Allocate enough space to store DIR structure and the complete + * directory path given. */ + //nd = (DIR *) malloc (sizeof (DIR) + _tcslen (szFullPath) + _tcslen (DIRENT_SLASH) + + // _tcslen (DIRENT_SEARCH_SUFFIX)+1); + nd = new DIR; + + if (!nd) + { + /* Error, out of memory. */ + errno = ENOMEM; + return NULL; + } + + /* Create the search expression. */ + strcpy (nd->dd_name, szFullPath); + + /* Add on a slash if the path does not end with one. */ + if (nd->dd_name[0] != '\0' && + nd->dd_name[strlen (nd->dd_name) - 1] != '/' && + nd->dd_name[strlen (nd->dd_name) - 1] != '\\') + { + strcat (nd->dd_name, DIRENT_SLASH); + } + + /* Add on the search pattern */ + strcat (nd->dd_name, DIRENT_SEARCH_SUFFIX); + + /* Initialize handle to -1 so that a premature closedir doesn't try + * to call _findclose on it. */ + nd->dd_handle = -1; + + /* Initialize the status. */ + nd->dd_stat = 0; + + /* Initialize the dirent structure. ino and reclen are invalid under + * Win32, and name simply points at the appropriate part of the + * findfirst_t structure. */ + //nd->dd_dir.d_ino = 0; + //nd->dd_dir.d_reclen = 0; + nd->dd_dir.d_namlen = 0; + nd->dd_dir.d_name = nd->dd_dta.name; + + return nd; +} + + +struct dirent * readdir (DIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return NULL; + } + + if (dirp->dd_dir.d_name != dirp->dd_dta.name) + { + /* The structure does not seem to be set up correctly. */ + errno = EINVAL; + return NULL; + } + + bool bCallFindNext = true; + + if (dirp->dd_stat < 0) + { + /* We have already returned all files in the directory + * (or the structure has an invalid dd_stat). */ + return NULL; + } + else if (dirp->dd_stat == 0) + { + /* We haven't started the search yet. */ + /* Start the search */ + dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta)); + + if (dirp->dd_handle == -1) + { + /* Whoops! Seems there are no files in that + * directory. */ + dirp->dd_stat = -1; + } + else + { + dirp->dd_stat = 1; + } + + /* Dont call _findnext first time. */ + bCallFindNext = false; + } + + while (dirp->dd_stat > 0) + { + if (bCallFindNext) + { + /* Get the next search entry. */ + if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) + { + /* We are off the end or otherwise error. */ + _findclose (dirp->dd_handle); + dirp->dd_handle = -1; + dirp->dd_stat = -1; + return NULL; + } + else + { + /* Update the status to indicate the correct + * number. */ + dirp->dd_stat++; + } + } + + /* Successfully got an entry. Everything about the file is + * already appropriately filled in except the length of the + * file name. */ + dirp->dd_dir.d_namlen = strlen (dirp->dd_dir.d_name); + + bool bThisFolderOrUpFolder = dirp->dd_dir.d_name[0] == '.' && + (dirp->dd_dir.d_name[1] == 0 || (dirp->dd_dir.d_name[1] == '.' && dirp->dd_dir.d_name[2] == 0)); + + if (!bThisFolderOrUpFolder) + { + struct _stat buf; + char buffer[CL_MAX_DIR]; + size_t bl = strlen(dirp->dd_name)-strlen(DIRENT_SEARCH_SUFFIX); + strncpy(buffer,dirp->dd_name,bl); + buffer[bl]=0; + strcat(buffer, dirp->dd_dir.d_name); + if ( _stat(buffer,&buf) == 0 ) + { + /* Finally we have a valid entry. */ + return &dirp->dd_dir; + } + } + + /* Allow to find next file. */ + bCallFindNext = true; + } + + return NULL; +} + + + +int32_t +closedir (DIR * dirp) +{ + int32_t rc; + + errno = 0; + rc = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + + if (dirp->dd_handle != -1) + { + rc = _findclose (dirp->dd_handle); + } + + /* Delete the dir structure. */ + _CLVDELETE(dirp); + + return rc; +} +#endif //HAVE_DIRENT_H + diff --git a/3rdparty/clucene/src/CLucene/util/dirent.h b/3rdparty/clucene/src/CLucene/util/dirent.h new file mode 100644 index 0000000..71cd34c --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/dirent.h @@ -0,0 +1,105 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Matt J. Weinstein +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +#ifndef lucene_util_dirent_H +#define lucene_util_dirent_H + +#if defined(_LUCENE_PRAGMA_ONCE) +# pragma once +#endif + +#if !defined(_CL_HAVE_DIRENT_H) && !defined(_CL_HAVE_SYS_NDIR_H) && !defined(_CL_HAVE_SYS_DIR_H) && !defined(_CL_HAVE_NDIR_H) + +/** +\unit + * dirent.c + * + * Derived from DIRLIB.C by Matt J. Weinstein + * This note appears in the DIRLIB.H + * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 + * + * Updated by Jeremy Bettis + * Significantly revised and rewinddir, seekdir and telldir added by Colin + * Cut down again & changed by Ben van Klinken + * Peters + * + */ + +/** dirent structure - used by the dirent.h directory iteration functions */ +struct dirent +{ + unsigned short d_namlen; /* Length of name in d_name. */ + char *d_name; /* File name. */ +}; + +/** DIR structure - used by the dirent.h directory iteration functions*/ +struct DIR +{ + /** disk transfer area for this dir */ + struct _finddata_t dd_dta; + + /* dirent struct to return from dir (NOTE: this makes this thread + * safe as long as only one thread uses a particular DIR struct at + * a time) */ + struct dirent dd_dir; + + /** _findnext handle */ + intptr_t dd_handle; + + /** + * Status of search: + * 0 = not started yet (next entry to read is first entry) + * -1 = off the end + * positive = 0 based index of next entry + */ + int32_t dd_stat; + + /** given path for dir with search pattern (struct is extended) */ + char dd_name[CL_MAX_DIR]; + +}; + +#define DIRENT_SEARCH_SUFFIX "*" +#define DIRENT_SLASH PATH_DELIMITERA + + +/** +* Returns a pointer to a DIR structure appropriately filled in to begin +* searching a directory. +*/ +DIR* opendir (const char* filespec); + +/** +* Return a pointer to a dirent structure filled with the information on the +* next entry in the directory. +*/ +struct dirent* readdir (DIR* dir); + +/** +* Frees up resources allocated by opendir. +*/ +int32_t closedir (DIR* dir); + + +#elif defined (_CL_HAVE_DIRENT_H) +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) + +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if defined(_CL_HAVE_SYS_NDIR_H) +# include +# endif +# if defined(_CL_HHAVE_SYS_DIR_H) +# include +# endif +# if defined(_CL_HHAVE_NDIR_H) +# include +# endif + +#endif //HAVE_DIRENT_H +#endif diff --git a/3rdparty/clucene/src/CLucene/util/fileinputstream.cpp b/3rdparty/clucene/src/CLucene/util/fileinputstream.cpp new file mode 100644 index 0000000..9125d84 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/fileinputstream.cpp @@ -0,0 +1,103 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Jos van den Oever +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +/* This file is part of Strigi Desktop Search + * + * Copyright (C) 2006 Jos van den Oever + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include "jstreamsconfig.h" +#include "fileinputstream.h" + +#ifndef UNDER_CE +#include +#endif +#include +namespace jstreams { + +const int32_t FileInputStream::defaultBufferSize = 1048576; +FileInputStream::FileInputStream(const char *filepath, int32_t buffersize) { + // try to open the file for reading + file = fopen(filepath, "rb"); + this->filepath = filepath; + if (file == 0) { + // handle error + error = "Could not read file '"; + error += filepath; + error += "': "; +#ifndef UNDER_CE + error += strerror(errno); +#endif + status = Error; + return; + } + // determine file size. if the stream is not seekable, the size will be -1 + fseek(file, 0, SEEK_END); + size = ftell(file); + fseek(file, 0, SEEK_SET); + + // if the file has size 0, make sure that it's really empty + // this is useful for filesystems like /proc that report files as size 0 + // for files that do contain content + if (size == 0) { + char dummy[1]; + size_t n = fread(dummy, 1, 1, file); + if (n == 1) { + size = -1; + fseek(file, 0, SEEK_SET); + } else { + fclose(file); + file = 0; + return; + } + } + + // allocate memory in the buffer + int32_t bufsize = (size <= buffersize) ?size+1 :buffersize; + mark(bufsize); +} +FileInputStream::~FileInputStream() { + if (file) { + if (fclose(file)) { + // handle error + error = "Could not close file '" + filepath + "'."; + } + } +} +int32_t +FileInputStream::fillBuffer(char* start, int32_t space) { + if (file == 0) return -1; + // read into the buffer + int32_t nwritten = fread(start, 1, space, file); + // check the file stream status + if (ferror(file)) { + error = "Could not read from file '" + filepath + "'."; + fclose(file); + file = 0; + status = Error; + return -1; + } + if (feof(file)) { + fclose(file); + file = 0; + } + return nwritten; +} +} diff --git a/3rdparty/clucene/src/CLucene/util/fileinputstream.h b/3rdparty/clucene/src/CLucene/util/fileinputstream.h new file mode 100644 index 0000000..144423d --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/fileinputstream.h @@ -0,0 +1,38 @@ +/** + * Copyright 2003-2006 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FILEINPUTSTREAM_H +#define FILEINPUTSTREAM_H + +#include "bufferedstream.h" + +namespace jstreams { + +class FileInputStream : public BufferedInputStream { +private: + FILE *file; + std::string filepath; + +public: + static const int32_t defaultBufferSize; + FileInputStream(const char *filepath, int32_t buffersize=defaultBufferSize); + ~FileInputStream(); + int32_t fillBuffer(char* start, int32_t space); +}; + +} // end namespace jstreams + +#endif + diff --git a/3rdparty/clucene/src/CLucene/util/inputstreambuffer.h b/3rdparty/clucene/src/CLucene/util/inputstreambuffer.h new file mode 100644 index 0000000..873e811 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/inputstreambuffer.h @@ -0,0 +1,126 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Jos van den Oever +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +/* This file is part of Strigi Desktop Search + * + * Copyright (C) 2006 Jos van den Oever + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef INPUTSTREAMBUFFER_H +#define INPUTSTREAMBUFFER_H + +#include + +namespace jstreams { + +template +class InputStreamBuffer { +private: +public: + T* start; + int32_t size; + T* readPos; + int32_t avail; + + InputStreamBuffer(); + ~InputStreamBuffer(); + void setSize(int32_t size); + int32_t read(const T*& start, int32_t max=0); + + /** + * This function prepares the buffer for a new write. + * returns the number of available places. + **/ + int32_t makeSpace(int32_t needed); +}; + +template +InputStreamBuffer::InputStreamBuffer() { + readPos = start = 0; + size = avail = 0; +} +template +InputStreamBuffer::~InputStreamBuffer() { + free(start); +} +template +void +InputStreamBuffer::setSize(int32_t size) { + // store pointer information + int32_t offset = (int32_t)(readPos - start); + + // allocate memory in the buffer + if ( start == 0 ) + start = (T*)malloc(size*sizeof(T)); + else + start = (T*)realloc(start, size*sizeof(T)); + this->size = size; + + // restore pointer information + readPos = start + offset; +} +template +int32_t +InputStreamBuffer::makeSpace(int32_t needed) { + // determine how much space is available for writing + int32_t space = size - ((int32_t)(readPos - start)) - avail; + if (space >= needed) { + // there's enough space + return space; + } + + if (avail) { + if (readPos != start) { +// printf("moving\n"); + // move data to the start of the buffer + memmove(start, readPos, avail*sizeof(T)); + space += (int32_t)(readPos - start); + readPos = start; + } + } else { + // we may start writing at the start of the buffer + readPos = start; + space = size; + } + if (space >= needed) { + // there's enough space now + return space; + } + + // still not enough space, we have to allocate more +// printf("resize %i %i %i %i %i\n", avail, needed, space, size + needed - space, size); + setSize(size + needed - space); + return needed; +} +template +int32_t +InputStreamBuffer::read(const T*& start, int32_t max) { + start = readPos; + if (max <= 0 || max > avail) { + max = avail; + } + readPos += max; + avail -= max; + return max; +} + +} // end namespace jstreams + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/jstreamsconfig.h b/3rdparty/clucene/src/CLucene/util/jstreamsconfig.h new file mode 100644 index 0000000..2a6ce9f --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/jstreamsconfig.h @@ -0,0 +1,9 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ + +//this is just a compatibility header for jstreams +#include "CLucene/StdHeader.h" diff --git a/3rdparty/clucene/src/CLucene/util/streambase.h b/3rdparty/clucene/src/CLucene/util/streambase.h new file mode 100644 index 0000000..b0d9dc1 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/streambase.h @@ -0,0 +1,148 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Jos van den Oever +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +* +* Changes are Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +------------------------------------------------------------------------------*/ +/* This file is part of Strigi Desktop Search + * + * Copyright (C) 2006 Jos van den Oever + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef STREAMBASE_H +#define STREAMBASE_H + +#include + +#if defined(_BUILD_FOR_QT_) + #include "StdHeader.h" +#endif + +#define INT32MAX 0x7FFFFFFFL + +namespace jstreams { + +enum StreamStatus { Ok, Eof, Error }; + +/** + * @short Base class for stream read access to many different file types. + * + * This class is based on the interface java.io.InputStream. It allows + * for uniform access to streamed resources. + * The main difference with the java equivalent is a performance improvement. + * When reading data, data is not copied into a buffer provided by the caller, + * but a pointer to the read data is provided. This makes this interface + * especially useful for deriving from it and implementing filterers or + * transformers. + */ +// java mapping: long=int64, int=int32, byte=uint8_t +template +class StreamBase { +protected: + int64_t size; + int64_t position; + std::string error; + StreamStatus status; +public: + StreamBase() :size(-1), position(0), status(Ok){ } + virtual ~StreamBase(){} + /** + * @brief Return a string representation of the last error. + * If no error has occurred, an empty string is returned. + **/ + const char* getError() const { return error.c_str(); } + StreamStatus getStatus() const { return status; } + /** + * @brief Get the current position in the stream. + * The value obtained from this function can be used to reset the stream. + **/ + int64_t getPosition() const { return position; } + /** + * @brief Return the size of the stream. + * If the size of the stream is unknown, -1 + * is returned. If the end of the stream has been reached the size is + * always known. + **/ + int64_t getSize() const { return size; } + /** + * @brief Reads characters from the stream and sets \a start to + * the first character that was read. + * + * If @p ntoread is @c 0, then at least one character will be read. + * + * @param start Pointer passed by reference that will be set to point to + * the retrieved array of characters. If the end of the stream + * is encountered or an error occurs, the value of @p start + * is undefined. + * @param min The number of characters to read from the stream. + * @param max The maximum number of characters to read from the stream. + * @return the number of characters that were read. If -1 is returned, the + * end of the stream has been reached. If -2 is returned, an error + * has occurred. + **/ + virtual int32_t read(const T*& start, int32_t min, int32_t max) = 0; + /** + * Skip @param ntoskip bytes. Unless an error occurs or the end of file is + * encountered, this amount of bytes is skipped. + * This function returns new position in the stream. + **/ + virtual int64_t skip(int64_t ntoskip); + /** + * @brief Repositions this stream to given requested position. + * Reset is guaranteed to work after a successful call to read(), + * when the new position is in the range of the data returned by read(). + * This means that @p pos must lie between than the position + * corresponding to the start parameter (x) of the read function + * and the position corresponding to the last position in the returned + * buffer (x + nread). + **/ + virtual int64_t reset(int64_t pos) = 0; + int64_t mark(int32_t readlimit) { + int64_t p = getPosition(); + const T* ptr; + read(ptr, readlimit, -1); + return reset(p); + } +}; +#define SKIPSTEP 1024 +template +int64_t +StreamBase::skip(int64_t ntoskip) { + const T *begin; + int32_t nread; + int64_t skipped = 0; + while (ntoskip) { + int32_t step = (int32_t)((ntoskip > SKIPSTEP) ?SKIPSTEP :ntoskip); + nread = read(begin, 1, step); + if (nread < -1 ) { + // an error occurred + return nread; + } else if (nread < 1) { + ntoskip = 0; + } else { + skipped += nread; + ntoskip -= nread; + } + } + return skipped; +} + +} // end namespace jstreams + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/stringreader.h b/3rdparty/clucene/src/CLucene/util/stringreader.h new file mode 100644 index 0000000..698d07e --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/stringreader.h @@ -0,0 +1,124 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Jos van den Oever +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +/* This file is part of Strigi Desktop Search + * + * Copyright (C) 2006 Jos van den Oever + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef STRINGREADER_H +#define STRINGREADER_H + +/** + * Author: Jos van den Oever + * Ben van Klinken + **/ + + +#include "streambase.h" + +namespace jstreams { + +template +class StringReader : public StreamBase { +private: + int64_t markpt; + T* data; + bool dataowner; + StringReader(const StringReader&); + void operator=(const StringReader&); +public: + StringReader(const T* value, int32_t length = -1, bool copy = true); + ~StringReader(); + int32_t read(const T*& start, int32_t min, int32_t max); + int64_t skip(int64_t ntoskip); + int64_t reset(int64_t pos); +}; + +typedef StringReader StringInputStream; + +template +StringReader::StringReader(const T* value, int32_t length, bool copy) + : markpt(0), dataowner(copy) { + if (length < 0) { + length = 0; + while (value[length] != '\0') { + length++; + } + } + StreamBase::size = length; + if (copy) { + data = new T[length+1]; + size_t s = (size_t)(length*sizeof(T)); + memcpy(data, value, s); + data[length] = 0; + } else { + // casting away const is ok, because we don't write anyway + data = (T*)value; + } +} +template +StringReader::~StringReader() { + if (dataowner) { + delete [] data; + } +} +template +int32_t +StringReader::read(const T*& start, int32_t min, int32_t max) { + int64_t left = StreamBase::size - StreamBase::position; + if (left == 0) { + StreamBase::status = Eof; + return -1; + } + if (min < 0) min = 0; + int32_t nread = (int32_t)((max > left || max < 1) ?left :max); + start = data + StreamBase::position; + StreamBase::position += nread; + if (StreamBase::position == StreamBase::size) { + StreamBase::status = Eof; + } + return nread; +} +template +int64_t +StringReader::skip(int64_t ntoskip) { + const T* start; + return read(start, ntoskip, ntoskip); +} +template +int64_t +StringReader::reset(int64_t newpos) { + if (newpos < 0) { + StreamBase::status = Ok; + StreamBase::position = 0; + } else if (newpos < StreamBase::size) { + StreamBase::status = Ok; + StreamBase::position = newpos; + } else { + StreamBase::position = StreamBase::size; + StreamBase::status = Eof; + } + return StreamBase::position; +} + +} // end namespace jstreams + +#endif diff --git a/3rdparty/clucene/src/CLucene/util/subinputstream.h b/3rdparty/clucene/src/CLucene/util/subinputstream.h new file mode 100644 index 0000000..8ae3e33 --- /dev/null +++ b/3rdparty/clucene/src/CLucene/util/subinputstream.h @@ -0,0 +1,141 @@ +/*------------------------------------------------------------------------------ +* Copyright (C) 2003-2006 Jos van den Oever +* +* Distributable under the terms of either the Apache License (Version 2.0) or +* the GNU Lesser General Public License, as specified in the COPYING file. +------------------------------------------------------------------------------*/ +/* This file is part of Strigi Desktop Search + * + * Copyright (C) 2006 Jos van den Oever + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifndef SUBINPUTSTREAM_H +#define SUBINPUTSTREAM_H + +#include "streambase.h" + +namespace jstreams { + +template +class SubInputStream : public StreamBase { +private: + const int64_t offset; + StreamBase *input; +public: + SubInputStream(StreamBase *input, int64_t size=-1); + int32_t read(const T*& start, int32_t min, int32_t max); + int64_t reset(int64_t newpos); + int64_t skip(int64_t ntoskip); +}; +template +SubInputStream::SubInputStream(StreamBase *i, int64_t length) + : offset(i->getPosition()), input(i) { + assert(length >= -1); +// printf("substream offset: %lli\n", offset); + StreamBase::size = length; +} + +template +int32_t SubInputStream::read(const T*& start, int32_t min, int32_t max) { + if (StreamBase::size != -1) { + const int64_t left = StreamBase::size - StreamBase::position; + if (left == 0) { + return -1; + } + // restrict the amount of data that can be read + if (max <= 0 || max > left) { + max = (int32_t)left; + } + if (min > max) min = max; + if (left < min) min = (int32_t)left; + } + int32_t nread = input->read(start, min, max); + if (nread < -1) { + fprintf(stderr, "substream too short.\n"); + StreamBase::status = Error; + StreamBase::error = input->getError(); + } else if (nread < min) { + if (StreamBase::size == -1) { + StreamBase::status = Eof; + if (nread > 0) { + StreamBase::position += nread; + StreamBase::size = StreamBase::position; + } + } else { +// fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! nread %i min %i max %i size %lli\n", nread, min, max, size); +// fprintf(stderr, "pos %lli parentpos %lli\n", position, input->getPosition()); +// fprintf(stderr, "status: %i error: %s\n", input->getStatus(), input->getError()); + // we expected data but didn't get enough so that's an error + StreamBase::status = Error; + StreamBase::error = "Premature end of stream\n"; + nread = -2; + } + } else { + StreamBase::position += nread; + if (StreamBase::position == StreamBase::size) { + StreamBase::status = Eof; + } + } + return nread; +} + +template +int64_t SubInputStream::reset(int64_t newpos) { +// fprintf(stderr, "subreset pos: %lli newpos: %lli offset: %lli\n", position, +// newpos, offset); + StreamBase::position = input->reset(newpos + offset); + if (StreamBase::position < offset) { + printf("###########\n"); + StreamBase::status = Error; + StreamBase::error = input->getError(); + } else { + StreamBase::position -= offset; + StreamBase::status = input->getStatus(); + } + return StreamBase::position; +} + +template +int64_t SubInputStream::skip(int64_t ntoskip) { +// printf("subskip pos: %lli ntoskip: %lli offset: %lli\n", position, ntoskip, offset); + if (StreamBase::size == StreamBase::position) { + StreamBase::status = Eof; + return -1; + } + if (StreamBase::size != -1) { + const int64_t left = StreamBase::size - StreamBase::position; + // restrict the amount of data that can be skipped + if (ntoskip > left) { + ntoskip = left; + } + } + int64_t skipped = input->skip(ntoskip); + if (input->getStatus() == Error) { + StreamBase::status = Error; + StreamBase::error = input->getError(); + } else { + StreamBase::position += skipped; + if (StreamBase::position == StreamBase::size) { + StreamBase::status = Eof; + } + } + return skipped; +} + +} //end namespace jstreams + +#endif diff --git a/demos/arthurplugin/arthur_plugin.qrc b/demos/arthurplugin/arthur_plugin.qrc new file mode 100644 index 0000000..e5170e6 --- /dev/null +++ b/demos/arthurplugin/arthur_plugin.qrc @@ -0,0 +1,7 @@ + + + bg1.jpg + flower.jpg + flower_alpha.jpg + + diff --git a/demos/arthurplugin/arthurplugin.pro b/demos/arthurplugin/arthurplugin.pro new file mode 100644 index 0000000..c5132b4 --- /dev/null +++ b/demos/arthurplugin/arthurplugin.pro @@ -0,0 +1,54 @@ + +QTDIR = $$QT_SOURCE_TREE + +CONFIG += designer plugin +TEMPLATE = lib +TARGET = $$qtLibraryTarget(arthurplugin) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer + +contains(QT_CONFIG, opengl) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +SHARED_FOLDER = ../shared +include(../shared/shared.pri) + +DEMO_DEFORM_DIR = ../deform +DEMO_AFFINE_DIR = ../affine +DEMO_GRADIENT_DIR = ../gradients +DEMO_STROKE_DIR = ../pathstroke +DEMO_COMPOSITION_DIR = ../composition + +INCLUDEPATH += $$DEMO_DEFORM_DIR $$DEMO_AFFINE_DIR $$DEMO_GRADIENT_DIR $$DEMO_STROKE_DIR $$DEMO_COMPOSITION_DIR + +SOURCES = plugin.cpp \ + $$DEMO_COMPOSITION_DIR/composition.cpp \ + $$DEMO_AFFINE_DIR/xform.cpp \ + $$DEMO_DEFORM_DIR/pathdeform.cpp \ + $$DEMO_GRADIENT_DIR/gradients.cpp \ + $$DEMO_STROKE_DIR/pathstroke.cpp \ + + +HEADERS = \ + $$DEMO_COMPOSITION_DIR/composition.h \ + $$DEMO_AFFINE_DIR/xform.h \ + $$DEMO_DEFORM_DIR/pathdeform.h \ + $$DEMO_GRADIENT_DIR/gradients.h \ + $$DEMO_STROKE_DIR/pathstroke.h \ + +RESOURCES += arthur_plugin.qrc + +# install +target.path = $$[QT_INSTALL_PLUGINS]/designer +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.jpg *.png +sources.path = $$[QT_INSTALL_DEMOS]/qttools/arthurplugin +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) + +win32-msvc* { + QMAKE_CFLAGS += /Zm500 + QMAKE_CXXFLAGS += /Zm500 +} + diff --git a/demos/arthurplugin/bg1.jpg b/demos/arthurplugin/bg1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dfc7cee6ad286bbb5c2f6e4c0cf1826e01c0fa55 GIT binary patch literal 23771 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 Z_J-cl?c$4hZJ_t1C~^-M$#}0v|Jm%fyx0H$ literal 0 HcmV?d00001 diff --git a/demos/arthurplugin/flower.jpg b/demos/arthurplugin/flower.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f8e022c98cb28efad3eb8c6ea2b21d7a8b422091 GIT binary patch literal 49616 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

@{TRdGFjVmI60sb_7u4|#N5 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 dnrpBGmYJkfxA9AD(tES-^#7OSoc7MM6t( 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�NSA z12qAJk?DsfGU^eSvozj;UJD4glW-kn0tO5on76Mx^#;yg+0VC_rWfU+h151+K&($w*Z{lJ4rxG|g)7 zTZxw+=r1L6G{n-T(9BJl_9CR)!8NJO++c`cf|pHL`m8#9->awFMc@%L#)EZXaH^hmi?BsMZJ1Ao zik-ajyX;KIN>e{hPxE<9Io`zyY{rE@>7im@_~y1e30wW)NVvl5Df&}&d24LIzrSY= z_8DV-RxcNIDQ|E%%A6$jEE$N1(U@Y$XUCnkM~|hrUp$x_7My8j zg4Jo$&7$m{kZv59X@U)jhwmydk{_fFZB&Q>>y>yMucX+J7UUdfFe$1fW@7{QqEc*J zAD}W31ROZLs0!F*RlckEP#skAvrBrtHs5EH6#YT#-V%k+2i~Gi>-EBWFHb8tD<@r7P?em&NQ-7-GbMT_5D(;W}~Y z!&kxsk`mO?n-EXt6z1`gRmvHe-SI74uU82u@`%4FL)RC8yL^g%-`>3nv&C?nOYacb zs2E~`hXw%Nd_O=Pf~3#atGw^+oG_L zjCmex7HkMVMDuLDiV%m3eRsBA&*Z@GE?{|^IP^rRQxm^(Pgh6x8CnXSo_?nah$(H-A4pCm4%R zcdmjpM(v~tNnMoZ{NMYJw>UF--A;mGRp@5HJ|9V#XFmmRWNI&OcwQT`?`y=j!p!PM z$^1do;?CjNp)Dune6lcYxme6U>Fn!t9+f%NL-ux~{*tS^b}XRDs7s3)syLci=E1g3 z@GY4G?N;+r??t8FFfhjq#M%NTK~1{<2Y5Iv-`nWu_C-tKH#hiUdi>XnrRXVA^u>5S zX`q3cibu1#ZTvD=Mr%w0E@0J`7tU|{;?@H3q7E|heZ0ppV;-nP_t&x8BV|tYH4+fm zS=G~-2wUZR_Pqt438`T3UsZMjl{Gr6#e%v3tXCz&UTiQb?Dt?zLK;I9k~gfPPXP`# zHCAvSI4=}}wN2+oockz#-bh6o`=wA)nCS(xuWpj{iRc+x7}J&kU*ogDC0p zr_UOwYz?n%usCgLxG5g=(IUpewhKyIaxC}}o`WZ{fhsA>9_~4D(AQF?26w(9p+m4));Iq-p z$rA}LCDkRS$}EZO7L^QdHOL~760j3VO^J74@KvDE%=Xf*sKu6`lKG5Qnz8EQ-XB_$ zo`Z5Dh?xe0_^w;%!`Sf-Y{=TE%$u+v)^DelfB$JqvM_mF+3juiWgT70UP;VAr1(yW zL7aamf|>tcOTqu3c+r#$ODY*%P`{idD$3hBr2qGFySplz?)oe|E-wG_aJR$wULJ*=lM~9U)4p%_e@gl10O7{(DP7LN@d4K>^$_A+B26uRH9QbaOs+am=9Myi zjUZ=RfqLe1Uj$Cm>$FvI$l(2;P=K?Y-Wa!dDz5Wjo>IVDo)YHX;FEo2*({T~O`MAV z5AgJ^?bG`Z(Kgx85D^9lo8#UD&psBSI9iZncbt86{O)@b?HwXOJuBrK)u({cO%6rx zSf^X#)tyw<2s-h7+(95&(IS_oj4+)Ay=D4xoRSsd=6H}Z3AQfj_njz5&#Ecl+4p>o z$M0|65X#V_ZUY-zi^~2311~|yX*`>5-<5>rQp(MgI_;2m2R;9Q~iOonWHktu>1=9 z;!8oB{JQ z*!5c8ChGyRlw0Cf)09YFRc?B=)iCJ}_|?a|e$SHl_oV_%+y`8Oh!@H88Q~M=$~2ff zCEpe|n1pf_23AcercwFWg#G+ZvTAJF2V^+)Vb~$n!!blKF$lIp)AHt%v|utkqx|)d zMKYz;q!|lJ>T#|3obReGLwg0H<|aTO%J7xPMH_~yZ}(*$uNpOIsH-O#{Pyp=L(i|9x@%UZE{?& z?8Ni;B5ENa)`k?H_!#KQ2G{a=1!TGIR8mBH_a*YyG%NI9ln~F|Px)8=uGxsQPt?uhy3{H=bJx>v(-l3QpMB6DCdfyc+Jiq zmm>~p&0|sAFI7LEIT_4rH!IUW>t9L!nd~HFG5z)aNs@oo;CgO~+w$AJ8RQ;ghwxDC z_2%ph=Ay>=U(>FA=wlF)v@Nx~S|Xjny@?C(ArIyFnP1&~NtO6Mnm+h!gH z*#{|@#z<@})Y~oexAu3c)PFwt6mQY3r*bG<^@6C6{?G}` z+^}$_Cl2p+`9|f`@0mnGW^`n+vTLg$u-W}YwQOG;qQxL+8>)d{qY;yvr?f-Va0BdA z(Op14Uv~c#pcX8WZ$6b@2sV)D2`@Iau?O>BZKCq9PpKjWt!UE{5;f5l#T0l3QV zq^n>&KmE|I@=|NkRa*;E8^2kn-%Du%W)zKe31?JY1_moX4@y-r!D7|wz`;*WY3F&z zzDw0e=5t-V^t(Lmo4$W_{(0Db@WfWG*kF8ajr~oi5$vAEyxybu#lTG;vyCvGmW!=g zS!x*MAnPcXT&Q3pCwHA?@5hNs#}I?^Lj$eR;Yw!SKk*mB#-=f* zWSsI~XM9DBTF7uGOq-wna?8@Ts38eZ_(1WLp1OUt#l!-?Y{665zTEz-ZuGrtN{zxJ z!NAPaY;2Qg3XDDDay_S3PQ(-pl_MRlX7VEuc-PC&Y_xlvd^{i{$n&V0=5i>z2 zq)#|6ec#G`;;HPb9V?0H0?pmf!0g7_$jrHDdJ1lKa`HC@!|SbCk>8SL=(5p8M+-v{ zo)2_GXd7ZS2@wUhM#!n?p%Vpo=H%cQ0A~&jZz$o{(`eGK)Z+EY$f8Y8Ia`5yV|pOa z;%wdj0P)Pm_n3Whc3LI3)C|S#fgkYU#4k%P2v!8H&4>iP;o(DBsa*9|o zD!^;3fz@u4IZfKXtU;bjs|Hlxs5S>y@BagA>-DW13Vf90S#R^z82Baz`fV3ou(WZ8 z-Wu2a*)q4-Ot=0BwdWC$$OeW!(NLLU;vw!3D}=yG__k{EVVTOjho&kAGwOOFQHM!J ztgiN>RMITSvlKdmQ%F*q67-^F?1Sj$oO>0P6r97vx^c>a9IiWiongCh{ z0TKs2cRmJrC?T8wWD=wL zZA~Ds8?v^1Z{9zmAOi?W8<_qdfc(f+(#^HuYe?0KW&GAp{)a;;>Kf1TOCJI?l$5|q zt8eQbKagHyC!(@6e)OjZ!;@bu>zMYuka&0`b?Z%(xj{RVPc;Vld(QZ%Cel9%stCNK zFKAd{sL2#i=r+;HHmBP*$H7AgPxmbp?dFojNk?0JVsMhyQ9p>g0MlEHI_XD`lyL%P z2@yB$;nxnmyjse<3SBvns+p@F>zTBc@Ka5^#uRjUSNzaZX?4Z`8M7Q3+H5 zCooD?Ml@79|YXQUGi`O^Cf?dc4Zj5jqOj|a-kl-pO+WmTJdpaVn%>Y){k)dm{ z`6mL`91&l5x9T?bgn95~t)v-;MitF}z8V>?%4$)FoOyf0Ei+jogE$MD1=27oa%4K+CSlA0}4OSf1Y*5wl&`F8tqXVu4n|c$7 zdd93opO$e}M&~ajRW*u0hI7$|?{$bjIW#U{c@3xXnrYY%|EFUi(P5^B&6Kcv{atF% z*D}kBhz3e295trD%~JW&t?6bFz0_EX0C+qQZhCX-|^Ofa#6ebhzlyo{N`Bi01 zP?ws&P*N6qChC*h#ipmk zOb*ERbZAK3pun~EY%7+fR^+zh z9M)a0@g@NkqyJ-WkO=sfPnCdj+e|^RX`REq!SPkis_qm#mEZo zE6CS#x^U|Z_)Ek@EkQ#~BqT47pC6q!48dI*EOpjgpATgm&6uP$rWNg!iALS+r!Q7s zA-&YUW(g`JV!FmNd;g(fRRdvEzMB6N*Rx+K$z`w%(=`icS*sf=i2f!;iL>e*PwA7GX7r zB{E%gs-4fYM2hu}C zmut}HFh2h_7)(9k@$IH^rR9CVQB8S3%EbzXVoQtvYIoR2dDhVI(Ve0f7IA<&D&c>1 z_*&c6Z>kh*i+kG_BGd(MbyMoX{_W0?!PbHM2gJd(&-Q(ByJpAT$JC)Oytm#AB%& z!vqkkiz3!tcHap|k|t;`t%$H$5a3PIMNLICJp_EqNwPmyYe_=l6OG=c##NN51WqNaxLL_?F95Km8HZ)|$} zoFexs1oonORbj(r@Bt=eqwEs2{L}K&i|dCed*G0e)Pe9@;~w|w&$H&TYF7C(tsjSb zK0cy5WqtegH~Yr#KeC4Z0p3mt|J4uj=g%XeGPm*t)BM(X?58Yu&7W|dvIX$l_ubftM-8WGknL~#ODKzs-JK9)u}4nITab^E2Xpj&%a^H5W3 z)hBxm!k}{2A0z~d)ozv_`Sc+l_2mcU|2Gnm6^7euF+8eY;vnRr{H>mM^Zu31%gZU% zro|OleHDHT^V4O4+M|Gqmy!v5U)=m3GvpQV?%C{GSuS|txiv221bfqvqrYWsa#E&f z5D+)j?BW>s5swATJ>Y!%zJVJVsr>am2NsVV$7MWwSp+(p#QNkR=>;oa%0ICnQecFU zimp??s1^7d8pnEkCtXwm9#kp5>=N^3`GzO@gvAEksx(OtP}AapZC#pvrIui!{j^Dq`}vYn{+bp zz}4Ghi{LVeZ9_AR_L#maW0LG!h)i0ij&c4q4qN{2N0!@TBbyptH4C-Cq4|eWq`PAy zspgZ6)-sNNA17#4uXyOd1C3ff@+H00CBdy^>gDkrggw5EgIX=)|X_Prjg_vU+Oe~F7Na_#Jh!4XUz*!oUi_^$Vj)@LRNqq{>tB_6@aohwTJ-|)jK_BAV9OoNIDQjll{!eRm*CmjvN z#>E%-wulSwl9*`Z70!gxZAU|TjN{b}g~Gq$>Y*~m&fA$6xk;J{_iiX+#y*!0$~D$w zVcZZ!!A<*8|DeEiEO>PYw|#C*-;tvKbnM9+Dc#Rlbtbc(&Gmt#;&r2iGwKquqS)g` zvRons5BB01SL`ZuiEa)t(eYH6T=CCDB>ub&+oD^@4aQTVmC_q4uiyY>x{^V@X!K@w^im3vAMQWbOg{oL?wKww>>W4NO@|XzU;j5!rCh z8=ALjsozzWd&!I=qf3bMe7d7R9B_YZf>p0SI^`hclmB{PzRlC$my=P>&}Ee-GaVy9 zs$RjgJTh*K z2E6)Rq=?IQ+ypL-n~|?6ks$<{_1(Mf=Lq{-)~R&2R*wE<4|f#lL!i8B#(CBCd$LV0 z?zuaU8+=&<+P~dtIT1!J4fJt?JEYqf7mCAok|8*FRLzWWRf+cET!40+pgy1_MI>LB zF#2|qxcmOtOU&c8%_aP8m*9ow{7G36J7IbrrId7a@(x<#-4sKMsArPUFRfSs4!Hfs z(y7@c=;0^UusE7Y0RgyJ(rWn)nS+am6H4cE#371F!qLLVX2}0PfTl5?LWvj(DW|fd zt=(KNhHxvf>7Cc)bI~A7+IUu`nNj?j?8=2C46&xnH_9)YM6iI)df=UraamsJ4@XZI zI!Tsb3sNitkQg=^JIHS=l9VqRjXQwd^HCj7%|b;A>?&vWt}6>0L$#fikvt0fll-W5rW zNTC-TfBWiRIU4S=CNQGUk49GCTl_`rG*wpd9E1c2QZ^Y6lIh*x^S4;MS}pMMkNc7k zs<{W-m-ZPAEpT1Zeu)WDece3SxUWU=Et1$KQ#1#fhGo(L00M7~-bm!F-tF(0 z3*#o^Av3!4p`+;hquFP_0f?1qsxU4Q1UX}8l3QPWf>@YMJq%!%WA$Rc zhu1AUcJ{ycgiZLmYoTT(OUPUPOjKDe1Ny#QSn|Cux>cEtRATF=mKfprphX!DoTPUj zbu*K&k3MbpteS0DNpF(JABDvXSiH$^s61Fq#c1a?; zPuo3ubjd@_SN;R^E;Uuf>7Y{PRbR^N@~Z2ANDm6C`QKVNP)N|m!~leZWQ`6FZAeKO zdDzfz+hjzgPFcaYeaSngS1$5y(4^1+vIbA;A!V{X{Xcjk?BJGHPGD* zYTjha%Oc^f)VF-R(-)0St`8W7l=ul>lxBG({g`ZZmgc_L&``l4mEQGVPX&~}+v;}p z8*c0qnVz29lB$JG;*3xQ(jhK&`HMxA31r zw-t&apnn6*+lhG|3^V@sd2d(Zr*5E%pKlAYdqZ=owR98?4RomAhqN=%*rI&%N##df z8JBcva($Y{f8DtJVNEN-BFF(Gt9P!1 zlh(ZNygUO4T?VJI7>afs=ov90;4vQSc6!oz1iYQeWkZ7UEAQ2G!U-ge0gL33E+^%^W(VTi)2?N07?FW)R_+ce_H%26n*kF&wpkHhZ&-inR)&tZWxMs1YZ?PX6j_t1MKaEJMBr-5a+6 ze8RYy6Z*`lU_5SmP@&;CA+AU5gI_<|I!vq>AF4ZN%+t+Tm};r(-a<`@6>R?fGKcfMM`)E!li}_0kE?Z zjgSqm#PEBJOY-%XLjSvoG7RBcxy^$A0IyN(krB;`zx4#Me_7X`k5s>WSz%tH&;^}> z6`nQL7nI}pv~{7&x%cS!06!yCrIv%wuVjHy%RTlF#2v#HgZ_)jUGE{X-s%+~m3&IE zRQ?z$yAfFovuxN18tyRV^}z6y6_N+q%>nH4@aX z(2Uww_oQzXM74<8LO+&_UdNlV*kIg~LMO9Wq>s_~St`C8q|%Uxk|l^pz*9n8{?4~D z;3^{jy{mat@Kp@W%;S_*llhB9?i=Y;@3@`5Ox79G0g=7}-rc=}0|rWE18?@`5i zT^$|-J+krn=3K@+InIu` z_^0%CvoEDy=1Z_LAObNP+UVpTSTSG5(H)N}RE&;HIK+Q|n{{lMo!{r>joNBbAt=eh zUC$2Q(ICo2urqa?n&)EB(b{idAMQ$@lPPc6t(GPnaCLqOC- zR!sdxo9W@y5r`%zwN~2~_~>eQji*$!Z4?!gevo>2R?{ZC_DlCrut(^i7xJQJ$Rk1p zmH`hN0<6yT1$i8qpc)H$c#f}4j45Ja{0Is9t#6v_PV#NDI&0=7waQ?T@WBzYsaZw| ztHutiLJeBS?wE}#F{CZOIYg82ZhttiZQ7dsQlqyjA*8P5I6Gtu%t2Q!wg65M5?;Xl z@@)5#1;bLs>spkgOFLh1Z)MYPCqZqWTSS#a;MvN@WEztF6Xjh}MmgyF8C>{Wz*fl2 zhhO8DRngO<#D~VLVGa4xViRBd!w13k_-XRsI_+YVh#+3U)jp&aR-h9BE9AgQb5!is zu1Oea7WMBwRxQ6&I0d#iZa90+Em-c_^6KkD!pG>Jcv(ZIB^?jm-LdXGPVnTyE%alW z^G>K9z#Hx>rrsrs^hnQKvRihN_yNZhFdWJaC^!nmDdvv z5aH8L0nf260&3VvKK$b5P^qq=5Z#WD$&s!jzsl0R=1Y0miVTI>ZKO_57)%NlJ;%(Z z68_3xRkusK%P;46KB!m6^>NstI(^2OGYj)bCWpD_QpydIGy`KnXS znN@uReM94~T}^`kSVkpAO37jjB<)c0C%xaxm(RL=zdd(i$ER}oKY;FhHfUF1Ah-c9 zRmUY}rtqi^eeTCb;XjcTIvmMe7@y5=I_eYkD{pFa3pVlf>X?VAea|IH~Scbap$wyyQ2W|6Z)q@lf=Eaq6m z!*?nI^a4&zt4Toignde!G;NOqS|b4XplgEk*jkdA)LXQ8$uN^dCu@X~-J_-O%FGoGMJl(zovXi2fd^SV<^m8?_mv`BD>okk1duRr zNJZ+#xc;hoiuCBZ$y?%9ZJzFPYX4AK^O%``G`2V-YOAH!a~VBTyMIer9kaRN86{4I z{=8a*S=}Z^*kRkXgF=^fWGB{Mg4`N8DxQ_~;LVsUQ*yz|BUYy}f+jB9dg7QrcLsRm z74kQ_3Qy;{_O5B!vH&%dpAh0Ip)Xl8vhT|sT|Wt6RqQx^3Du8Fbu!QhuI-2Y+5Zn3x zrl^WKXlowbC|D@=h>L04&^#o1y)1A*#7i)6$^HBbzDrWPMz zvt9?^?%DefP#|SaJe#xcxa?)U=;`rA-#fC_jl5W!}jZ)*ic{-2sTLagJ zE?hKANi)q}4|-kX-xu5WG~=$cy|kLVhBS4b{ZynkQxC2t;a8X)frq7ve{THEj}~a& zB4w2Bb2IV3&#ZS{1|Cu1a*)zgL2g^78>d_ZgXiV^X3qPWDN_}(;vDY$-0@IfI{DPP z8v~WZ8%3ep$s6!Cr)H1uqfsuxH<_c-sM~IjbN!~bDa8;z~% z0{M%4o9W^g@vsG}Cx?6Tz{8p_t3MITE)(8UHx;5({s9R|FGqsk+b7*sLd0!0C>k$} zEmModC`Rx1bg0iT+%as2Ia6Q8|Cuxqd$Tt^l~|m!l}I`Z^Rz!JP!SQ<3;5bcdB6XJ zwy>j|oL?1DHk6bWQ}rJp(ysQ__*anCQN`B!3d__@zX6v zblOi1@+Y<`O_LaLKizcWOJKanho__xPE5c<_s1P|=HPM0IVql&55vbJz!`mmZHWsb zN^||J{TKzKqH|Qu$@_C%khJS#KOw;I&sCkt|7sr#fVxv@?oeWqELp=tnz*pF=dkRY zjFhPUYJMQ(|6%DY{F;2jzD+45poD^w0@5fcjfBML(Hk8~!{{z)k=#JSQ5!uAzp(o=6aX%6*a+va~>HYHb`)wXWZdDC`2HCI>0>%-a4@uN-&Tl{7!_Ua|T)e`r;VeUPq zQH-fi!IQg=-WVHltZ`dWuIO4>axAa& zfUc-bAr!Wd??Z9IC50@91!w4LULf*Rr#Y86`ISuw^pA%CKpE-79)J5ztET3c+N$yV z+x&*^4R9DBu>2He!;||b@3jcOq)`LXUjEIAMfHugP@3+SU#78AiU|c0g~ig_jB?>y z7d46!!C=v607h1j-ezB@NvD(LuZGz@Znai=@|v&Eo)HUK z0A|CXbl4Qqat3Ep0tEBJ%oL^SCytj1oa|wrI0pQFV&Tzm4zZA=XD#Z^EPR?ga?8OJ zm5b7dOE5njXC}?>AV^>x+;O|;a}<<<}hEjy+E zgXh=bK392O?-c9~a1sEiR>!$Oi_U*4pmYD&5v&3x7kZA3DpwrVl#VXq7tD+hylE@& z@M>C0PUD|gde}@>2Ak+cAHO&4*zg+DR+-|;YO`bY`H8WUrGfBlI9idpVKsx5jGL0+ zg2eE7eyg?F&KHJ?k|kf{onQ3&U}s)9eXL}m`pk*tyT3>OFdlek4kh*Jyjt_bK0?w% zME{Wl@eP0_J9T{85tH4s)a8keWO;^qo|iOUAUQ2P-VJ4VpAu^W@58uiD?W5DXg+w1 z6$*Bw^ww4-rBKP264k6>c6ZFw-=@05l-^FiOPPot{ugUwLk#}Xd?nzHhEL%e3x3HP zJr6Ed-Y%5C`~&In#%__D>??^<^cy&0lRxAq|BZ0zac}ru@+Uph$Q~`E+^+e_-J3SS zkn-X#H%(mmz(9Drxgk16;)G!IDjE)E~z6a)JtZhikYK;7}h6QBJANeIOd%bOy8TL5L>^z@-s?76@@_cnuKN)|w#SDH7n+#V53 zATRLF%qGYdz`}PmrR2vM*TH6J)(fCLRFr9VdA!iB^kTZ)U6e6lZwh`dUwl?yIk8Xb zdZKv9RYhCOE4N>aSq<2sC*6lqSnJbQW`?Gfi5!nuO-qY#{Lz?D7%j(t?Vfomw(Vhv7}GvPuulN0htBTQHO z!}x$i_{}SyI1EjP)QQQ*Uk5N~XCM8H9DT-f@*e$Cba0TiWrnA(+cddVZKfmWpT9BZs4039vtc@mq=CgR@3Z~q2TXr!rdA5-tVOA znx$RL@^7t%J#V&dXte`Ik02$4*bNGNYZ8!Z|hpS!)^3f322W$}N*s}jVOo|&|! zo{aMIT4+Dj;&cCl0Rt2m2rbsvGYZ9a^TT1qrTx)JBri*7B>a1Xi}qu4w^kEOzAcgs z)|o+6@zXu1U+fu>Sy)PXD26aq+YS?=Y?U}Zk&&HGTx!}d8n(@?&~mAZk#k#B13A1qU=Snl;WjVaIWNT}qd zkryjlJJ3BHxMNf%HyUEh8&A2`@hJ1dLVB(-nS&gRBgT*CxQeApkbyb2j3|R!1)Krg zalGH5m`Om<*=A7)t_E%Zpr7~Z2J`&@rvKx{qMr5Js4{aR^|Oj^X$ns^!puVIl!LKe zN{l0#&%z)r@`bbBcfgUK)AYz9o|yH&{BKEY?9;7XSC|kjQ_Y6C!JnO_B(>?} zvFT{XO(=>d#KzL5MO4W7Uzt=@@T*iRWAz*J`S4lzYh&>u*EWm2>{4Nq#ABhavu1`s zP8l$W?2N=z6{B)=e@e!K_^EY(xsRoDgR<(DX^u7zBk>*NqP(C-eoM#t!noZX)0F8o zVOY0H8=GHOG60A#rD3SeqI&O_++Dh^W3H0;bH|`mVxSu@lHD<3rnELux~NWgOEe_K zCv9?{25m3%?3EcFNR|kH3xam8^>3STvOg+7$(-W$HLhL1nwPYQD?rBMu3953yaa3- zX<|?V3*ZLhr_vBD&Jk5eM(SNLQAh}#rR2=-&IZm5c1wwyXw1h1>#oKIllz1m>f^Un zbzsQKhxg}8gI$s=3?A;M65|y#BAZf0efIzZ2Y6p!>>6j+?sZ-(NO{&HEYGhfjW})2 z6YmPNiX@GaU(nL*sOtrn>kPL;!+&w$i z9YZI+ol&y0D2G^n*18Km8)?^}?&C{cj`h|UBE;!KBl%QT*ywHdH_Os?>Ft-Y94y@2x||3} z=_?8xB_e1je|Klc-BP{C#y%DKG{9TpAmKY7NX1a+D=%+QqVoc>gKRn0!N*YBn&G

ZvFqRcE~BFI}$JK7|upY!zm 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 Knx(Y=-vj^->{NpQ literal 0 HcmV?d00001 diff --git a/demos/arthurplugin/plugin.cpp b/demos/arthurplugin/plugin.cpp new file mode 100644 index 0000000..336e88d --- /dev/null +++ b/demos/arthurplugin/plugin.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "xform.h" +#include "pathdeform.h" +#include "gradients.h" +#include "pathstroke.h" +#include "hoverpoints.h" +#include "composition.h" + +QT_FORWARD_DECLARE_CLASS(QDesignerFormEditorInterface) + +// Specify "text" to be a singleline property (no richtext) +static inline QString textSingleLinePropertyDeclaration(const QString &className) +{ + QString rc = QLatin1String( + "\n" + " \n" + " "); + rc += className; + rc += QLatin1String("\n" + " \n" + " \n" + " \n" + " \n" + "\n"); + return rc; +} + +// Plain XML for a custom widget +static inline QString customWidgetDomXml(const QString &className, + const QString &customSection = QString()) +{ + QString rc = QLatin1String(""); + rc += customSection; + rc += QLatin1String(""); + return rc; +} + +class PathDeformRendererEx : public PathDeformRenderer +{ + Q_OBJECT +public: + PathDeformRendererEx(QWidget *parent) : PathDeformRenderer(parent) { } + QSize sizeHint() const { return QSize(300, 200); } +}; + +class DemoPlugin : public QDesignerCustomWidgetInterface +{ + Q_INTERFACES(QDesignerCustomWidgetInterface) + +protected: + explicit DemoPlugin(const QString &className, const QString &customSection = QString()); + +public: + QString name() const { return m_className; } + bool isContainer() const { return false; } + bool isInitialized() const { return m_initialized; } + QIcon icon() const { return QIcon(); } + QString codeTemplate() const { return QString(); } + QString whatsThis() const { return QString(); } + QString toolTip() const { return QString(); } + QString group() const { return "Arthur Widgets [Demo]"; } + void initialize(QDesignerFormEditorInterface *) + { + if (m_initialized) + return; + m_initialized = true; + } + QString domXml() const { return m_domXml; } + +private: + const QString m_className; + const QString m_domXml; + bool m_initialized; +}; + +DemoPlugin::DemoPlugin(const QString &className, const QString &customSection) : + m_className(className), + m_domXml(customWidgetDomXml(className, customSection)), + m_initialized(false) +{ +} + +class DeformPlugin : public QObject, public DemoPlugin +{ + Q_OBJECT + +public: + explicit DeformPlugin(QObject *parent = 0); + QString includeFile() const { return QLatin1String("deform.h"); } + + QWidget *createWidget(QWidget *parent) + { + PathDeformRenderer *deform = new PathDeformRendererEx(parent); + deform->setRadius(70); + deform->setAnimated(false); + deform->setFontSize(20); + deform->setText(QLatin1String("Arthur Widgets Demo")); + + return deform; + } +}; + +DeformPlugin::DeformPlugin(QObject *parent) : + QObject(parent), + DemoPlugin(QLatin1String("PathDeformRendererEx"), + textSingleLinePropertyDeclaration(QLatin1String("PathDeformRendererEx"))) +{ +} + +class XFormRendererEx : public XFormView +{ + Q_OBJECT +public: + XFormRendererEx(QWidget *parent) : XFormView(parent) {} + QSize sizeHint() const { return QSize(300, 200); } +}; + +class XFormPlugin : public QObject, public DemoPlugin +{ + Q_OBJECT +public: + explicit XFormPlugin(QObject *parent = 0); + QString includeFile() const { return QLatin1String("xform.h"); } + + QWidget *createWidget(QWidget *parent) + { + XFormRendererEx *xform = new XFormRendererEx(parent); + xform->setText(QLatin1String("Qt - Hello World!!")); + xform->setPixmap(QPixmap(QLatin1String(":/trolltech/arthurplugin/bg1.jpg"))); + return xform; + } +}; + +XFormPlugin::XFormPlugin(QObject *parent) : + QObject(parent), + DemoPlugin(QLatin1String("XFormRendererEx"), + textSingleLinePropertyDeclaration(QLatin1String("XFormRendererEx"))) +{ +} + +class GradientEditorPlugin : public QObject, public DemoPlugin +{ + Q_OBJECT +public: + explicit GradientEditorPlugin(QObject *parent = 0) : QObject(parent), DemoPlugin(QLatin1String("GradientEditor")) { } + QString includeFile() const { return "gradients.h"; } + + QWidget *createWidget(QWidget *parent) + { + GradientEditor *editor = new GradientEditor(parent); + return editor; + } +}; + +class GradientRendererEx : public GradientRenderer +{ + Q_OBJECT +public: + GradientRendererEx(QWidget *p) : GradientRenderer(p) { } + QSize sizeHint() const { return QSize(300, 200); } +}; + +class GradientRendererPlugin : public QObject, public DemoPlugin +{ + Q_OBJECT +public: + GradientRendererPlugin(QObject *parent = 0) : QObject(parent), DemoPlugin(QLatin1String("GradientRendererEx")) { } + QString includeFile() const { return QLatin1String("gradients.h"); } + + QWidget *createWidget(QWidget *parent) + { + GradientRenderer *renderer = new GradientRendererEx(parent); + renderer->setConicalGradient(); + return renderer; + } +}; + +class PathStrokeRendererEx : public PathStrokeRenderer +{ + Q_OBJECT +public: + explicit PathStrokeRendererEx(QWidget *p) : PathStrokeRenderer(p) { } + QSize sizeHint() const { return QSize(300, 200); } +}; + +class StrokeRenderPlugin : public QObject, public DemoPlugin +{ + Q_OBJECT +public: + explicit StrokeRenderPlugin(QObject *parent = 0) : QObject(parent), DemoPlugin(QLatin1String("PathStrokeRendererEx")) { } + QString includeFile() const { return QLatin1String("pathstroke.h"); } + + QWidget *createWidget(QWidget *parent) + { + PathStrokeRenderer *stroke = new PathStrokeRendererEx(parent); + return stroke; + } +}; + + +class CompositionModePlugin : public QObject, public DemoPlugin +{ + Q_OBJECT +public: + explicit CompositionModePlugin(QObject *parent = 0) : QObject(parent), DemoPlugin(QLatin1String("CompositionRenderer")) { } + QString includeFile() const { return QLatin1String("composition.h"); } + + QWidget *createWidget(QWidget *parent) + { + CompositionRenderer *renderer = new CompositionRenderer(parent); + renderer->setAnimationEnabled(false); + return renderer; + } +}; + + +class ArthurPlugins : public QObject, public QDesignerCustomWidgetCollectionInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) + +public: + explicit ArthurPlugins(QObject *parent = 0); + QList customWidgets() const { return m_plugins; } + +private: + QList m_plugins; +}; + +ArthurPlugins::ArthurPlugins(QObject *parent) : + QObject(parent) +{ + m_plugins << new DeformPlugin(this) + << new XFormPlugin(this) + << new GradientEditorPlugin(this) + << new GradientRendererPlugin(this) + << new StrokeRenderPlugin(this) + << new CompositionModePlugin(this); +} + +#include "plugin.moc" + +Q_EXPORT_PLUGIN2(ArthurPlugins, ArthurPlugins) diff --git a/demos/shared/arthurstyle.cpp b/demos/shared/arthurstyle.cpp new file mode 100644 index 0000000..e8e8a02 --- /dev/null +++ b/demos/shared/arthurstyle.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "arthurstyle.h" +#include "arthurwidgets.h" +#include +#include +#include +#include +#include +#include +#include +#include + +QPixmap cached(const QString &img) +{ + if (QPixmap *p = QPixmapCache::find(img)) + return *p; + + QPixmap pm; + pm = QPixmap::fromImage(QImage(img), Qt::OrderedDither | Qt::OrderedAlphaDither); + if (pm.isNull()) + return QPixmap(); + + QPixmapCache::insert(img, pm); + return pm; +} + + +ArthurStyle::ArthurStyle() + : QWindowsStyle() +{ + Q_INIT_RESOURCE(shared); +} + + +void ArthurStyle::drawHoverRect(QPainter *painter, const QRect &r) const +{ + qreal h = r.height(); + qreal h2 = r.height() / qreal(2); + QPainterPath path; + path.addRect(r.x() + h2, r.y() + 0, r.width() - h2 * 2, r.height()); + path.addEllipse(r.x(), r.y(), h, h); + path.addEllipse(r.x() + r.width() - h, r.y(), h, h); + path.setFillRule(Qt::WindingFill); + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(191, 215, 191)); + painter->setRenderHint(QPainter::Antialiasing); + painter->drawPath(path); +} + + +void ArthurStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + + Q_ASSERT(option); + switch (element) { + case PE_FrameFocusRect: + break; + + case PE_IndicatorRadioButton: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + bool hover = (button->state & State_Enabled) && (button->state & State_MouseOver); + painter->save(); + QPixmap radio; + if (hover) + drawHoverRect(painter, widget->rect()); + + if (button->state & State_Sunken) + radio = cached(":res/images/radiobutton-on.png"); + else if (button->state & State_On) + radio = cached(":res/images/radiobutton_on.png"); + else + radio = cached(":res/images/radiobutton_off.png"); + painter->drawPixmap(button->rect.topLeft(), radio); + + painter->restore(); + } + break; + + case PE_PanelButtonCommand: + if (const QStyleOptionButton *button = qstyleoption_cast(option)) { + bool hover = (button->state & State_Enabled) && (button->state & State_MouseOver); + + painter->save(); + const QPushButton *pushButton = qobject_cast(widget); + Q_ASSERT(pushButton); + QWidget *parent = pushButton->parentWidget(); + if (parent && qobject_cast(parent)) { + QLinearGradient lg(0, 0, 0, parent->height()); + lg.setColorAt(0, QColor(224,224,224)); + lg.setColorAt(1, QColor(255,255,255)); + painter->setPen(Qt::NoPen); + painter->setBrush(lg); + painter->setBrushOrigin(-widget->mapToParent(QPoint(0,0))); + painter->drawRect(button->rect); + painter->setBrushOrigin(0,0); + } + + bool down = (button->state & State_Sunken) || (button->state & State_On); + + QPixmap left, right, mid; + if (down) { + left = cached(":res/images/button_pressed_cap_left.png"); + right = cached(":res/images/button_pressed_cap_right.png"); + mid = cached(":res/images/button_pressed_stretch.png"); + } else { + left = cached(":res/images/button_normal_cap_left.png"); + right = cached(":res/images/button_normal_cap_right.png"); + mid = cached(":res/images/button_normal_stretch.png"); + } + painter->drawPixmap(button->rect.topLeft(), left); + painter->drawTiledPixmap(QRect(button->rect.x() + left.width(), + button->rect.y(), + button->rect.width() - left.width() - right.width(), + left.height()), + mid); + painter->drawPixmap(button->rect.x() + button->rect.width() - right.width(), + button->rect.y(), + right); + if (hover) + painter->fillRect(widget->rect().adjusted(3,5,-3,-5), QColor(31,127,31,63)); + painter->restore(); + } + break; + + case PE_FrameGroupBox: + if (const QStyleOptionFrameV2 *group + = qstyleoption_cast(option)) { + const QRect &r = group->rect; + + painter->save(); + int radius = 14; + int radius2 = radius*2; + QPainterPath clipPath; + clipPath.moveTo(radius, 0); + clipPath.arcTo(r.right() - radius2, 0, radius2, radius2, 90, -90); + clipPath.arcTo(r.right() - radius2, r.bottom() - radius2, radius2, radius2, 0, -90); + clipPath.arcTo(r.left(), r.bottom() - radius2, radius2, radius2, 270, -90); + clipPath.arcTo(r.left(), r.top(), radius2, radius2, 180, -90); + painter->setClipPath(clipPath); + QPixmap titleStretch = cached(":res/images/title_stretch.png"); + QPixmap topLeft = cached(":res/images/groupframe_topleft.png"); + QPixmap topRight = cached(":res/images/groupframe_topright.png"); + QPixmap bottomLeft = cached(":res/images/groupframe_bottom_left.png"); + QPixmap bottomRight = cached(":res/images/groupframe_bottom_right.png"); + QPixmap leftStretch = cached(":res/images/groupframe_left_stretch.png"); + QPixmap topStretch = cached(":res/images/groupframe_top_stretch.png"); + QPixmap rightStretch = cached(":res/images/groupframe_right_stretch.png"); + QPixmap bottomStretch = cached(":res/images/groupframe_bottom_stretch.png"); + QLinearGradient lg(0, 0, 0, r.height()); + lg.setColorAt(0, QColor(224,224,224)); + lg.setColorAt(1, QColor(255,255,255)); + painter->setPen(Qt::NoPen); + painter->setBrush(lg); + painter->drawRect(r.adjusted(0, titleStretch.height()/2, 0, 0)); + painter->setClipping(false); + + int topFrameOffset = titleStretch.height()/2 - 2; + painter->drawPixmap(r.topLeft() + QPoint(0, topFrameOffset), topLeft); + painter->drawPixmap(r.topRight() - QPoint(topRight.width()-1, 0) + + QPoint(0, topFrameOffset), topRight); + painter->drawPixmap(r.bottomLeft() - QPoint(0, bottomLeft.height()-1), bottomLeft); + painter->drawPixmap(r.bottomRight() - QPoint(bottomRight.width()-1, + bottomRight.height()-1), bottomRight); + + QRect left = r; + left.setY(r.y() + topLeft.height() + topFrameOffset); + left.setWidth(leftStretch.width()); + left.setHeight(r.height() - topLeft.height() - bottomLeft.height() - topFrameOffset); + painter->drawTiledPixmap(left, leftStretch); + + QRect top = r; + top.setX(r.x() + topLeft.width()); + top.setY(r.y() + topFrameOffset); + top.setWidth(r.width() - topLeft.width() - topRight.width()); + top.setHeight(topLeft.height()); + painter->drawTiledPixmap(top, topStretch); + + QRect right = r; + right.setX(r.right() - rightStretch.width()+1); + right.setY(r.y() + topRight.height() + topFrameOffset); + right.setWidth(rightStretch.width()); + right.setHeight(r.height() - topRight.height() + - bottomRight.height() - topFrameOffset); + painter->drawTiledPixmap(right, rightStretch); + + QRect bottom = r; + bottom.setX(r.x() + bottomLeft.width()); + bottom.setY(r.bottom() - bottomStretch.height()+1); + bottom.setWidth(r.width() - bottomLeft.width() - bottomRight.width()); + bottom.setHeight(bottomLeft.height()); + painter->drawTiledPixmap(bottom, bottomStretch); + painter->restore(); + } + break; + + default: + QWindowsStyle::drawPrimitive(element, option, painter, widget); + break; + } + return; +} + + +void ArthurStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const +{ + switch (control) { + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) { + QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget); + + painter->save(); + + bool hover = (slider->state & State_Enabled) && (slider->state & State_MouseOver); + if (hover) { + QRect moderated = widget->rect().adjusted(0, 4, 0, -4); + drawHoverRect(painter, moderated); + } + + if ((option->subControls & SC_SliderGroove) && groove.isValid()) { + QPixmap grv = cached(":res/images/slider_bar.png"); + painter->drawPixmap(QRect(groove.x() + 5, groove.y(), + groove.width() - 10, grv.height()), + grv); + } + if ((option->subControls & SC_SliderHandle) && handle.isValid()) { + QPixmap hndl = cached(":res/images/slider_thumb_on.png"); + painter->drawPixmap(handle.topLeft(), hndl); + } + + painter->restore(); + } + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox + = qstyleoption_cast(option)) { + QStyleOptionGroupBox groupBoxCopy(*groupBox); + groupBoxCopy.subControls &= ~SC_GroupBoxLabel; + QWindowsStyle::drawComplexControl(control, &groupBoxCopy, painter, widget); + + if (groupBox->subControls & SC_GroupBoxLabel) { + const QRect &r = groupBox->rect; + QPixmap titleLeft = cached(":res/images/title_cap_left.png"); + QPixmap titleRight = cached(":res/images/title_cap_right.png"); + QPixmap titleStretch = cached(":res/images/title_stretch.png"); + int txt_width = groupBox->fontMetrics.width(groupBox->text) + 20; + painter->drawPixmap(r.center().x() - txt_width/2, 0, titleLeft); + QRect tileRect = subControlRect(control, groupBox, SC_GroupBoxLabel, widget); + painter->drawTiledPixmap(tileRect, titleStretch); + painter->drawPixmap(tileRect.x() + tileRect.width(), 0, titleRight); + int opacity = 31; + painter->setPen(QColor(0, 0, 0, opacity)); + painter->drawText(tileRect.translated(0, 1), + Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text); + painter->drawText(tileRect.translated(2, 1), + Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text); + painter->setPen(QColor(0, 0, 0, opacity * 2)); + painter->drawText(tileRect.translated(1, 1), + Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text); + painter->setPen(Qt::white); + painter->drawText(tileRect, Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text); + } + } + break; + default: + QWindowsStyle::drawComplexControl(control, option, painter, widget); + break; + } + return; +} + +QRect ArthurStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const +{ + QRect rect; + + switch (control) { + default: + rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + break; + case CC_GroupBox: + if (const QStyleOptionGroupBox *group + = qstyleoption_cast(option)) { + switch (subControl) { + default: + rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + break; + case SC_GroupBoxContents: + rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + rect.adjust(0, -8, 0, 0); + break; + case SC_GroupBoxFrame: + rect = group->rect; + break; + case SC_GroupBoxLabel: + QPixmap titleLeft = cached(":res/images/title_cap_left.png"); + QPixmap titleRight = cached(":res/images/title_cap_right.png"); + QPixmap titleStretch = cached(":res/images/title_stretch.png"); + int txt_width = group->fontMetrics.width(group->text) + 20; + rect = QRect(group->rect.center().x() - txt_width/2 + titleLeft.width(), 0, + txt_width - titleLeft.width() - titleRight.width(), + titleStretch.height()); + break; + } + } + break; + } + + if (control == CC_Slider && subControl == SC_SliderHandle) { + rect.setWidth(13); + rect.setHeight(27); + } else if (control == CC_Slider && subControl == SC_SliderGroove) { + rect.setHeight(9); + rect.moveTop(27/2 - 9/2); + } + return rect; +} + +QSize ArthurStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const +{ + QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + + + switch (type) { + case CT_RadioButton: + newSize += QSize(20, 0); + break; + + case CT_PushButton: + newSize.setHeight(26); + break; + + case CT_Slider: + newSize.setHeight(27); + break; + + default: + break; + } + + return newSize; +} + +int ArthurStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const +{ + if (pm == PM_SliderLength) + return 13; + return QWindowsStyle::pixelMetric(pm, opt, widget); +} + +void ArthurStyle::polish(QWidget *widget) +{ + if (widget->layout() && qobject_cast(widget)) { + if (widget->findChildren().size() == 0) { + widget->layout()->setSpacing(0); + widget->layout()->setMargin(12); + } else { + widget->layout()->setMargin(13); + } + } + + if (qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget)) { + widget->setAttribute(Qt::WA_Hover); + } + + QPalette pal = widget->palette(); + if (widget->isWindow()) { + pal.setColor(QPalette::Background, QColor(241, 241, 241)); + widget->setPalette(pal); + } + +} + +void ArthurStyle::unpolish(QWidget *widget) +{ + if (qobject_cast(widget) + || qobject_cast(widget) + || qobject_cast(widget)) { + widget->setAttribute(Qt::WA_Hover, false); + } +} + +void ArthurStyle::polish(QPalette &palette) +{ + palette.setColor(QPalette::Background, QColor(241, 241, 241)); +} + +QRect ArthurStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const +{ + QRect r; + switch(element) { + case SE_RadioButtonClickRect: + r = widget->rect(); + break; + case SE_RadioButtonContents: + r = widget->rect().adjusted(20, 0, 0, 0); + break; + default: + r = QWindowsStyle::subElementRect(element, option, widget); + break; + } + + if (qobject_cast(widget)) + r = r.adjusted(5, 0, -5, 0); + + return r; +} diff --git a/demos/shared/arthurstyle.h b/demos/shared/arthurstyle.h new file mode 100644 index 0000000..9e3ada9 --- /dev/null +++ b/demos/shared/arthurstyle.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ARTHURSTYLE_H +#define ARTHURSTYLE_H + +#include + +QT_USE_NAMESPACE + +class ArthurStyle : public QWindowsStyle +{ +public: + ArthurStyle(); + + void drawHoverRect(QPainter *painter, const QRect &rect) const; + + void drawPrimitive(PrimitiveElement element, const QStyleOption *option, + QPainter *painter, const QWidget *widget = 0) const; +// void drawControl(ControlElement element, const QStyleOption *option, +// QPainter *painter, const QWidget *widget) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + + QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const; + +// SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, +// const QPoint &pos, const QWidget *widget = 0) const; + + int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const; + + void polish(QPalette &palette); + void polish(QWidget *widget); + void unpolish(QWidget *widget); +}; + +#endif diff --git a/demos/shared/arthurwidgets.cpp b/demos/shared/arthurwidgets.cpp new file mode 100644 index 0000000..d6b8cca --- /dev/null +++ b/demos/shared/arthurwidgets.cpp @@ -0,0 +1,371 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "arthurwidgets.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern QPixmap cached(const QString &img); + +ArthurFrame::ArthurFrame(QWidget *parent) + : QWidget(parent) + , m_prefer_image(false) +{ +#ifdef QT_OPENGL_SUPPORT + glw = 0; + m_use_opengl = false; + QGLFormat f = QGLFormat::defaultFormat(); + f.setSampleBuffers(true); + f.setStencil(true); + f.setAlpha(true); + f.setAlphaBufferSize(8); + QGLFormat::setDefaultFormat(f); +#endif + m_document = 0; + m_show_doc = false; + + m_tile = QPixmap(128, 128); + m_tile.fill(Qt::white); + QPainter pt(&m_tile); + QColor color(230, 230, 230); + pt.fillRect(0, 0, 64, 64, color); + pt.fillRect(64, 64, 64, 64, color); + pt.end(); + +// QPalette pal = palette(); +// pal.setBrush(backgroundRole(), m_tile); +// setPalette(pal); + +#ifdef Q_WS_X11 + QPixmap xRenderPixmap(1, 1); + m_prefer_image = xRenderPixmap.pixmapData()->classId() == QPixmapData::X11Class && !xRenderPixmap.x11PictureHandle(); +#endif +} + + +#ifdef QT_OPENGL_SUPPORT +void ArthurFrame::enableOpenGL(bool use_opengl) +{ + m_use_opengl = use_opengl; + + if (!glw) { + glw = new GLWidget(this); + glw->setAutoFillBackground(false); + glw->disableAutoBufferSwap(); + QApplication::postEvent(this, new QResizeEvent(size(), size())); + } + + if (use_opengl) { + glw->show(); + } else { + glw->hide(); + } + + update(); +} +#endif + +void ArthurFrame::paintEvent(QPaintEvent *e) +{ +#ifdef Q_WS_QWS + static QPixmap *static_image = 0; +#else + static QImage *static_image = 0; +#endif + QPainter painter; + if (preferImage() +#ifdef QT_OPENGL_SUPPORT + && !m_use_opengl +#endif + ) { + if (!static_image || static_image->size() != size()) { + delete static_image; +#ifdef Q_WS_QWS + static_image = new QPixmap(size()); +#else + static_image = new QImage(size(), QImage::Format_RGB32); +#endif + } + painter.begin(static_image); + + int o = 10; + + QBrush bg = palette().brush(QPalette::Background); + painter.fillRect(0, 0, o, o, bg); + painter.fillRect(width() - o, 0, o, o, bg); + painter.fillRect(0, height() - o, o, o, bg); + painter.fillRect(width() - o, height() - o, o, o, bg); + } else { +#ifdef QT_OPENGL_SUPPORT + if (m_use_opengl) { + painter.begin(glw); + painter.fillRect(QRectF(0, 0, glw->width(), glw->height()), palette().color(backgroundRole())); + } else { + painter.begin(this); + } +#else + painter.begin(this); +#endif + } + + painter.setClipRect(e->rect()); + + painter.setRenderHint(QPainter::Antialiasing); + + QPainterPath clipPath; + + QRect r = rect(); + qreal left = r.x() + 1; + qreal top = r.y() + 1; + qreal right = r.right(); + qreal bottom = r.bottom(); + qreal radius2 = 8 * 2; + + clipPath.moveTo(right - radius2, top); + clipPath.arcTo(right - radius2, top, radius2, radius2, 90, -90); + clipPath.arcTo(right - radius2, bottom - radius2, radius2, radius2, 0, -90); + clipPath.arcTo(left, bottom - radius2, radius2, radius2, 270, -90); + clipPath.arcTo(left, top, radius2, radius2, 180, -90); + clipPath.closeSubpath(); + + painter.save(); + painter.setClipPath(clipPath, Qt::IntersectClip); + + painter.drawTiledPixmap(rect(), m_tile); + + // client painting + + paint(&painter); + + painter.restore(); + + painter.save(); + if (m_show_doc) + paintDescription(&painter); + painter.restore(); + + int level = 180; + painter.setPen(QPen(QColor(level, level, level), 2)); + painter.setBrush(Qt::NoBrush); + painter.drawPath(clipPath); + + if (preferImage() +#ifdef QT_OPENGL_SUPPORT + && !m_use_opengl +#endif + ) { + painter.end(); + painter.begin(this); +#ifdef Q_WS_QWS + painter.drawPixmap(e->rect(), *static_image, e->rect()); +#else + painter.drawImage(e->rect(), *static_image, e->rect()); +#endif + } + +#ifdef QT_OPENGL_SUPPORT + if (m_use_opengl && (inherits("PathDeformRenderer") || inherits("PathStrokeRenderer") || inherits("CompositionRenderer") || m_show_doc)) + glw->swapBuffers(); +#endif +} + +void ArthurFrame::resizeEvent(QResizeEvent *e) +{ +#ifdef QT_OPENGL_SUPPORT + if (glw) + glw->setGeometry(0, 0, e->size().width()-1, e->size().height()-1); +#endif + QWidget::resizeEvent(e); +} + +void ArthurFrame::setDescriptionEnabled(bool enabled) +{ + if (m_show_doc != enabled) { + m_show_doc = enabled; + emit descriptionEnabledChanged(m_show_doc); + update(); + } +} + +void ArthurFrame::loadDescription(const QString &fileName) +{ + QFile textFile(fileName); + QString text; + if (!textFile.open(QFile::ReadOnly)) + text = QString("Unable to load resource file: '%1'").arg(fileName); + else + text = textFile.readAll(); + setDescription(text); +} + + +void ArthurFrame::setDescription(const QString &text) +{ + m_document = new QTextDocument(this); + m_document->setHtml(text); +} + +void ArthurFrame::paintDescription(QPainter *painter) +{ + if (!m_document) + return; + + int pageWidth = qMax(width() - 100, 100); + int pageHeight = qMax(height() - 100, 100); + if (pageWidth != m_document->pageSize().width()) { + m_document->setPageSize(QSize(pageWidth, pageHeight)); + } + + QRect textRect(width() / 2 - pageWidth / 2, + height() / 2 - pageHeight / 2, + pageWidth, + pageHeight); + int pad = 10; + QRect clearRect = textRect.adjusted(-pad, -pad, pad, pad); + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(0, 0, 0, 63)); + int shade = 10; + painter->drawRect(clearRect.x() + clearRect.width() + 1, + clearRect.y() + shade, + shade, + clearRect.height() + 1); + painter->drawRect(clearRect.x() + shade, + clearRect.y() + clearRect.height() + 1, + clearRect.width() - shade + 1, + shade); + + painter->setRenderHint(QPainter::Antialiasing, false); + painter->setBrush(QColor(255, 255, 255, 220)); + painter->setPen(Qt::black); + painter->drawRect(clearRect); + + painter->setClipRegion(textRect, Qt::IntersectClip); + painter->translate(textRect.topLeft()); + + QAbstractTextDocumentLayout::PaintContext ctx; + + QLinearGradient g(0, 0, 0, textRect.height()); + g.setColorAt(0, Qt::black); + g.setColorAt(0.9, Qt::black); + g.setColorAt(1, Qt::transparent); + + QPalette pal = palette(); + pal.setBrush(QPalette::Text, g); + + ctx.palette = pal; + ctx.clip = QRect(0, 0, textRect.width(), textRect.height()); + m_document->documentLayout()->draw(painter, ctx); +} + +void ArthurFrame::loadSourceFile(const QString &sourceFile) +{ + m_sourceFileName = sourceFile; +} + +void ArthurFrame::showSource() +{ + // Check for existing source + if (findChild()) + return; + + QString contents; + if (m_sourceFileName.isEmpty()) { + contents = QString("No source for widget: '%1'").arg(objectName()); + } else { + QFile f(m_sourceFileName); + if (!f.open(QFile::ReadOnly)) + contents = QString("Could not open file: '%1'").arg(m_sourceFileName); + else + contents = f.readAll(); + } + + contents.replace('&', "&"); + contents.replace('<', "<"); + contents.replace('>', ">"); + + QStringList keywords; + keywords << "for " << "if " << "switch " << " int " << "#include " << "const" + << "void " << "uint " << "case " << "double " << "#define " << "static" + << "new" << "this"; + + foreach (QString keyword, keywords) + contents.replace(keyword, QLatin1String("") + keyword + QLatin1String("")); + contents.replace("(int ", "(int "); + + QStringList ppKeywords; + ppKeywords << "#ifdef" << "#ifndef" << "#if" << "#endif" << "#else"; + + foreach (QString keyword, ppKeywords) + contents.replace(keyword, QLatin1String("") + keyword + QLatin1String("")); + + contents.replace(QRegExp("(\\d\\d?)"), QLatin1String("\\1")); + + QRegExp commentRe("(//.+)\\n"); + commentRe.setMinimal(true); + contents.replace(commentRe, QLatin1String("\\1\n")); + + QRegExp stringLiteralRe("(\".+\")"); + stringLiteralRe.setMinimal(true); + contents.replace(stringLiteralRe, QLatin1String("\\1")); + + QString html = contents; + html.prepend("

");
+    html.append("
"); + + QTextBrowser *sourceViewer = new QTextBrowser(0); + sourceViewer->setWindowTitle("Source: " + m_sourceFileName.mid(5)); + sourceViewer->setParent(this, Qt::Dialog); + sourceViewer->setAttribute(Qt::WA_DeleteOnClose); + sourceViewer->setLineWrapMode(QTextEdit::NoWrap); + sourceViewer->setHtml(html); + sourceViewer->resize(600, 600); + sourceViewer->show(); +} diff --git a/demos/shared/arthurwidgets.h b/demos/shared/arthurwidgets.h new file mode 100644 index 0000000..6757111 --- /dev/null +++ b/demos/shared/arthurwidgets.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ARTHURWIDGETS_H +#define ARTHURWIDGETS_H + +#include "arthurstyle.h" +#include +#include +#include + +#if defined(QT_OPENGL_SUPPORT) +#include +#include +class GLWidget : public QGLWidget +{ +public: + GLWidget(QWidget *parent) + : QGLWidget(QGLFormat(QGL::SampleBuffers), parent) + { + setAttribute(Qt::WA_AcceptTouchEvents); + } + void disableAutoBufferSwap() { setAutoBufferSwap(false); } + void paintEvent(QPaintEvent *) { parentWidget()->update(); } +protected: + bool event(QEvent *event) + { + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + event->ignore(); + return false; + break; + default: + break; + } + return QGLWidget::event(event); + } +}; +#endif + +QT_FORWARD_DECLARE_CLASS(QTextDocument) +QT_FORWARD_DECLARE_CLASS(QTextEdit) +QT_FORWARD_DECLARE_CLASS(QVBoxLayout) + +class ArthurFrame : public QWidget +{ + Q_OBJECT +public: + ArthurFrame(QWidget *parent); + virtual void paint(QPainter *) {} + + + void paintDescription(QPainter *p); + + void loadDescription(const QString &filename); + void setDescription(const QString &htmlDesc); + + void loadSourceFile(const QString &fileName); + + bool preferImage() const { return m_prefer_image; } + +#if defined(QT_OPENGL_SUPPORT) + QGLWidget *glWidget() const { return glw; } +#endif + +public slots: + void setPreferImage(bool pi) { m_prefer_image = pi; } + void setDescriptionEnabled(bool enabled); + void showSource(); + +#if defined(QT_OPENGL_SUPPORT) + void enableOpenGL(bool use_opengl); + bool usesOpenGL() { return m_use_opengl; } +#endif + +signals: + void descriptionEnabledChanged(bool); + +protected: + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *); + +#if defined(QT_OPENGL_SUPPORT) + GLWidget *glw; + bool m_use_opengl; +#endif + QPixmap m_tile; + + bool m_show_doc; + bool m_prefer_image; + QTextDocument *m_document; + + QString m_sourceFileName; + +}; + +#endif diff --git a/demos/shared/hoverpoints.cpp b/demos/shared/hoverpoints.cpp new file mode 100644 index 0000000..272f895 --- /dev/null +++ b/demos/shared/hoverpoints.cpp @@ -0,0 +1,415 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef QT_OPENGL_SUPPORT +#include +#endif + +#include "arthurwidgets.h" +#include "hoverpoints.h" + +#define printf + +HoverPoints::HoverPoints(QWidget *widget, PointShape shape) + : QObject(widget) +{ + m_widget = widget; + widget->installEventFilter(this); + widget->setAttribute(Qt::WA_AcceptTouchEvents); + + m_connectionType = CurveConnection; + m_sortType = NoSort; + m_shape = shape; + m_pointPen = QPen(QColor(255, 255, 255, 191), 1); + m_connectionPen = QPen(QColor(255, 255, 255, 127), 2); + m_pointBrush = QBrush(QColor(191, 191, 191, 127)); + m_pointSize = QSize(11, 11); + m_currentIndex = -1; + m_editable = true; + m_enabled = true; + + connect(this, SIGNAL(pointsChanged(QPolygonF)), + m_widget, SLOT(update())); +} + + +void HoverPoints::setEnabled(bool enabled) +{ + if (m_enabled != enabled) { + m_enabled = enabled; + m_widget->update(); + } +} + + +bool HoverPoints::eventFilter(QObject *object, QEvent *event) +{ + if (object == m_widget && m_enabled) { + switch (event->type()) { + + case QEvent::MouseButtonPress: + { + if (!m_fingerPointMapping.isEmpty()) + return true; + QMouseEvent *me = (QMouseEvent *) event; + + QPointF clickPos = me->pos(); + int index = -1; + for (int i=0; ibutton() == Qt::LeftButton) { + if (index == -1) { + if (!m_editable) + return false; + int pos = 0; + // Insert sort for x or y + if (m_sortType == XSort) { + for (int i=0; i clickPos.x()) { + pos = i; + break; + } + } else if (m_sortType == YSort) { + for (int i=0; i clickPos.y()) { + pos = i; + break; + } + } + + m_points.insert(pos, clickPos); + m_locks.insert(pos, 0); + m_currentIndex = pos; + firePointChange(); + } else { + m_currentIndex = index; + } + return true; + + } else if (me->button() == Qt::RightButton) { + if (index >= 0 && m_editable) { + if (m_locks[index] == 0) { + m_locks.remove(index); + m_points.remove(index); + } + firePointChange(); + return true; + } + } + + } + break; + + case QEvent::MouseButtonRelease: + if (!m_fingerPointMapping.isEmpty()) + return true; + m_currentIndex = -1; + break; + + case QEvent::MouseMove: + if (!m_fingerPointMapping.isEmpty()) + return true; + if (m_currentIndex >= 0) + movePoint(m_currentIndex, ((QMouseEvent *)event)->pos()); + break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + { + const QTouchEvent *const touchEvent = static_cast(event); + const QList points = touchEvent->touchPoints(); + const qreal pointSize = qMax(m_pointSize.width(), m_pointSize.height()); + foreach (const QTouchEvent::TouchPoint &touchPoint, points) { + const int id = touchPoint.id(); + switch (touchPoint.state()) { + case Qt::TouchPointPressed: + { + // find the point, move it + QSet activePoints = QSet::fromList(m_fingerPointMapping.values()); + int activePoint = -1; + qreal distance = -1; + const int pointsCount = m_points.size(); + const int activePointCount = activePoints.size(); + if (pointsCount == 2 && activePointCount == 1) { // only two points + activePoint = activePoints.contains(0) ? 1 : 0; + } else { + for (int i=0; i::iterator it = m_fingerPointMapping.find(id); + movePoint(it.value(), touchPoint.pos()); + m_fingerPointMapping.erase(it); + } + break; + case Qt::TouchPointMoved: + { + // move the point + const int pointIdx = m_fingerPointMapping.value(id, -1); + if (pointIdx >= 0) // do we track this point? + movePoint(pointIdx, touchPoint.pos()); + } + break; + default: + break; + } + } + if (m_fingerPointMapping.isEmpty()) { + event->ignore(); + return false; + } else { + return true; + } + } + break; + case QEvent::TouchEnd: + if (m_fingerPointMapping.isEmpty()) { + event->ignore(); + return false; + } + return true; + break; + + case QEvent::Resize: + { + QResizeEvent *e = (QResizeEvent *) event; + if (e->oldSize().width() == 0 || e->oldSize().height() == 0) + break; + qreal stretch_x = e->size().width() / qreal(e->oldSize().width()); + qreal stretch_y = e->size().height() / qreal(e->oldSize().height()); + for (int i=0; i(that_widget); + if (af && af->usesOpenGL()) + af->glWidget()->swapBuffers(); +#endif + return true; + } + default: + break; + } + } + + return false; +} + + +void HoverPoints::paintPoints() +{ + QPainter p; +#ifdef QT_OPENGL_SUPPORT + ArthurFrame *af = qobject_cast(m_widget); + if (af && af->usesOpenGL()) + p.begin(af->glWidget()); + else + p.begin(m_widget); +#else + p.begin(m_widget); +#endif + + p.setRenderHint(QPainter::Antialiasing); + + if (m_connectionPen.style() != Qt::NoPen && m_connectionType != NoConnection) { + p.setPen(m_connectionPen); + + if (m_connectionType == CurveConnection) { + QPainterPath path; + path.moveTo(m_points.at(0)); + for (int i=1; i right || (lock & HoverPoints::LockToRight)) p.setX(right); + + if (p.y() < top || (lock & HoverPoints::LockToTop)) p.setY(top); + else if (p.y() > bottom || (lock & HoverPoints::LockToBottom)) p.setY(bottom); + + return p; +} + +void HoverPoints::setPoints(const QPolygonF &points) +{ + if (points.size() != m_points.size()) + m_fingerPointMapping.clear(); + m_points.clear(); + for (int i=0; i 0) { + m_locks.resize(m_points.size()); + + m_locks.fill(0); + } +} + + +void HoverPoints::movePoint(int index, const QPointF &point, bool emitUpdate) +{ + m_points[index] = bound_point(point, boundingRect(), m_locks.at(index)); + if (emitUpdate) + firePointChange(); +} + + +inline static bool x_less_than(const QPointF &p1, const QPointF &p2) +{ + return p1.x() < p2.x(); +} + + +inline static bool y_less_than(const QPointF &p1, const QPointF &p2) +{ + return p1.y() < p2.y(); +} + +void HoverPoints::firePointChange() +{ +// printf("HoverPoints::firePointChange(), current=%d\n", m_currentIndex); + + if (m_sortType != NoSort) { + + QPointF oldCurrent; + if (m_currentIndex != -1) { + oldCurrent = m_points[m_currentIndex]; + } + + if (m_sortType == XSort) + qSort(m_points.begin(), m_points.end(), x_less_than); + else if (m_sortType == YSort) + qSort(m_points.begin(), m_points.end(), y_less_than); + + // Compensate for changed order... + if (m_currentIndex != -1) { + for (int i=0; i + +QT_FORWARD_DECLARE_CLASS(QBypassWidget) + +class HoverPoints : public QObject +{ + Q_OBJECT +public: + enum PointShape { + CircleShape, + RectangleShape + }; + + enum LockType { + LockToLeft = 0x01, + LockToRight = 0x02, + LockToTop = 0x04, + LockToBottom = 0x08 + }; + + enum SortType { + NoSort, + XSort, + YSort + }; + + enum ConnectionType { + NoConnection, + LineConnection, + CurveConnection + }; + + HoverPoints(QWidget *widget, PointShape shape); + + bool eventFilter(QObject *object, QEvent *event); + + void paintPoints(); + + inline QRectF boundingRect() const; + void setBoundingRect(const QRectF &boundingRect) { m_bounds = boundingRect; } + + QPolygonF points() const { return m_points; } + void setPoints(const QPolygonF &points); + + QSizeF pointSize() const { return m_pointSize; } + void setPointSize(const QSizeF &size) { m_pointSize = size; } + + SortType sortType() const { return m_sortType; } + void setSortType(SortType sortType) { m_sortType = sortType; } + + ConnectionType connectionType() const { return m_connectionType; } + void setConnectionType(ConnectionType connectionType) { m_connectionType = connectionType; } + + void setConnectionPen(const QPen &pen) { m_connectionPen = pen; } + void setShapePen(const QPen &pen) { m_pointPen = pen; } + void setShapeBrush(const QBrush &brush) { m_pointBrush = brush; } + + void setPointLock(int pos, LockType lock) { m_locks[pos] = lock; } + + void setEditable(bool editable) { m_editable = editable; } + bool editable() const { return m_editable; } + +public slots: + void setEnabled(bool enabled); + void setDisabled(bool disabled) { setEnabled(!disabled); } + +signals: + void pointsChanged(const QPolygonF &points); + +public: + void firePointChange(); + +private: + inline QRectF pointBoundingRect(int i) const; + void movePoint(int i, const QPointF &newPos, bool emitChange = true); + + QWidget *m_widget; + + QPolygonF m_points; + QRectF m_bounds; + PointShape m_shape; + SortType m_sortType; + ConnectionType m_connectionType; + + QVector m_locks; + + QSizeF m_pointSize; + int m_currentIndex; + bool m_editable; + bool m_enabled; + + QHash m_fingerPointMapping; + + QPen m_pointPen; + QBrush m_pointBrush; + QPen m_connectionPen; +}; + + +inline QRectF HoverPoints::pointBoundingRect(int i) const +{ + QPointF p = m_points.at(i); + qreal w = m_pointSize.width(); + qreal h = m_pointSize.height(); + qreal x = p.x() - w / 2; + qreal y = p.y() - h / 2; + return QRectF(x, y, w, h); +} + +inline QRectF HoverPoints::boundingRect() const +{ + if (m_bounds.isEmpty()) + return m_widget->rect(); + else + return m_bounds; +} + +#endif // HOVERPOINTS_H diff --git a/demos/shared/images/bg_pattern.png b/demos/shared/images/bg_pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..ee670266f03eaab0fb51713b7f8db48e7d5f115d GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xf3?%cF6&=@t|NsB*A85%46p{6G zaSYK2PEKK9`p56kR5-=e`&zxi$H0UsuE}By3Yj^oPTBm^feINsUHx3vIVCg!0OGtG AbpQYW literal 0 HcmV?d00001 diff --git a/demos/shared/images/button_normal_cap_left.png b/demos/shared/images/button_normal_cap_left.png new file mode 100644 index 0000000000000000000000000000000000000000..db31dd971d4a3beea379c56442f365345124ff12 GIT binary patch literal 654 zcmV;90&)F`P)HCDONYhis3ejR zhOf51=k|kPW8ujG`t-eD2U!#a2_X~_b-)n300R&K7g&H~B|QUg!F%u=gur2;z9f}N zobn-xqjy02p)a-8WJ{ZD+a?kx@l~9}Z_$)@}-@hqjNsMAGmM3ckAazd764S5FH%9}PbCu4p@ zf_W^j9)ARjTb2)p10D7N^_U$^8mBgmi{UU=al84uDc0+?c-TD9Zo4BF4PhVAv=$ap zlx^0ZOeXisKg;d%*HYhozcc5{GIvmUI_1d()9Lj0)yJ#*#qGkoac;zZx2JZ}Hci1I zpAL(g@p!yI*L=PHa{YQXpS9+*xiD?!dgkowef$QVjz*);gTbJ+TCMo68zRN#r248? o{R#XS4u?NcUxF_1tNVP3e^F1=53JemivR!s07*qoM6N<$f?qQ$G5`Po literal 0 HcmV?d00001 diff --git a/demos/shared/images/button_normal_cap_right.png b/demos/shared/images/button_normal_cap_right.png new file mode 100644 index 0000000000000000000000000000000000000000..38ead1c719114a63e9a84716483225e3c8f23c30 GIT binary patch literal 674 zcmV;T0$u%yP)0iD|^{H7y61mg*SqzmqJ%jR1&q?PLj2 zUgXq)$W(@+RYcu`E?<_#xjMMlquL4)UzU^Wx;9R~>yy`M^D9)=v5SeuQ9&f7q|V(A zL>{@VR`b4Ed3QWG)*L(uA*ilv8zVdOT+>vm-9k+DMr3L#wWb!FR7;U` zw^UleNs;3^A8OL#WwoW(!xB+6tD7B~34OvHFR zPMSB^UW^Mh>h*dTK@hyb_yd1g0k^k%dEgtyUEal|A)B0-keDLK h{^+`c4-d;KW(MocOgZu$@vlKH@O1TaS?83{1OQ0GQIh}w literal 0 HcmV?d00001 diff --git a/demos/shared/images/button_pressed_cap_left.png b/demos/shared/images/button_pressed_cap_left.png new file mode 100644 index 0000000000000000000000000000000000000000..66bfc13cb4832c01cfc3b4e74e0d2ff09d44a8c4 GIT binary patch literal 710 zcmV;%0y+JOP)X1^@s6*FMFU0007wNkls@5QSfNSC0qBCJKTD9Do&f;0o->A+pOgvdbkn22oHHBo=ItV1W=wI6~HpkV{v)K&)J7_$f9Q1m<{lmi_I6C?%yF2F)$1#jC4B+^0$Yhe? z{QMlp$Gg++sX=<5BCm7I>p3i0IPU_;E;ur;osn~HHBHk{ zL|dUS1-c)*h*lzyCkBYDwGD`Z7)nGW0082mv(`c9QwMP;h9d{(ER3@Z5tuqNcm|3S zc<%!=GFa)XpuO5gyW5s@th1^m&;o>QvKU4Y!N(r0c8k+d2s=`UL}Qz7Xz>U+HQ(|g zfskX6L;+CK5dfYGq>nIU5qSZzBc6*pOX9QvVL{VTfI`^1kHv{X1fY(Llao?6uOZHc z#Xj;Z2B;XIQh-R)*-!{ul^r7oY7wGVBmntMr0J>~J*B1-Lxva2LUGa}b;NK1=xHg4 zN3$lzYF$Dao*I$0+&AiEO(B{iLo^CBl3K}}XaPh|PK+@h7Vg1I!ASdJN%V#j?N(t3 zWdQ~g`olE3Rp%1*0%ng2&tMIafjVo79WO~B)_Z@kwY4RWQ9jF&&vO*>0#y;9byZ8$ zd0p4CVO3VTF)a7V&dyGMb8{2rv_v+@@Q^+P4IYr)XF-D}rOo*$8HFR>-rnBW-Q7j` ztHkx6Yd#fm6?bE~N90K_<6>1pzw}q|V37j_lK=n!07*qoM6N<$f;Y51!TX1^@s6*FMFU0008mNkl15sR-g@JQD_p#B8zMq;#D_k$gZLE7Nz?xdxYGeE%XMxL{3mc zLZPHsb}XxLZON+NLkx0SnhyNDk!SwT|C5=qy12L~@W9YogNRVC*Rip&fz8cLwA<}3 zVHiF)#z38%oH)os@_irc>+9Ir*}=iV0k*fdKebw|*F;4BG!{kSYLX-vjYhb>zD7Dp zQLBY7gCKx9JUrxG4}ly^DFtp}nE>bK=jio%?Q-xdsc*>BfS>%kNC-Fs|2*w&1ZBUNK zoJQN4g)@ZKMfU<%MdTBVX9S{+OVZ(@y}K0AWQO66)99klOZlD zdF0|dlSi(W?*m%tDx{@39{DSqIj)P&CNZ0`Y7M1Vl3eL>L5!LzRo{CyViuufD5Y3? znyGALmEYp#99wQKRLoL@!fW}`GbW}vs*@O2h0u9HE6G)|EYMXU3X2$SIilUO8c`7}qj+r{qgE&%k+UT^Q+ zI39yxNt{6Hu&l8Y#y`dwejj4+ZGf%L7JAQmI668)7>1wK*_*Qh`1@T_?7(#IDK)-?R;E%Ua8B=%m2Bk1+2A3qtW31oFC0*^TQJGmY076%1ot0`8CYW P00000NkvXXu0mjfj6i3? literal 0 HcmV?d00001 diff --git a/demos/shared/images/button_pressed_stretch.png b/demos/shared/images/button_pressed_stretch.png new file mode 100644 index 0000000000000000000000000000000000000000..4dd4ad11e6f0d2b50e9ea04ebca6b7e19b383d45 GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+p!3-pCwzvEPQh@ z{qp>x8lwVB0xw*+P`bP{x+%K)L#;N@aA!{!#}J9B$s%bEj6FUpYQ)S;D$`6V-Tu_D z1-iMp3A%A`G6iXDs+ZX5Y21IS#?9={rxy(qCpXxL&#L^B@u&XBTV@6`J!ZbuJKr7z P8pq)2>gTe~DWM4f(8*HF literal 0 HcmV?d00001 diff --git a/demos/shared/images/curve_thing_edit-6.png b/demos/shared/images/curve_thing_edit-6.png new file mode 100644 index 0000000000000000000000000000000000000000..034b474d02e5264ef677f96aadc07f8b428d471d GIT binary patch literal 58097 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 literal 0 HcmV?d00001 diff --git a/demos/shared/images/frame_bottom.png b/demos/shared/images/frame_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..889b40d3044f9c6c897604a00f053f187ebd386a GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^oIq^E!3HGzbUxMrDVB6cUq=RpYd5a=M;HP5k|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5XEIeHtLo7}wzp?(%&?u0Qq`=gp zB^7G2Dno>){s70(X3dKm1sl0Ee9H?d(e0GV5Qx^kM5Yz8%+vNWN&0z3! L^>bP0l+XkKcU&^S literal 0 HcmV?d00001 diff --git a/demos/shared/images/frame_bottomleft.png b/demos/shared/images/frame_bottomleft.png new file mode 100644 index 0000000000000000000000000000000000000000..0b3023f3975b2301f47fbd216e8f2aae891a742b GIT binary patch literal 602 zcmeAS@N?(olHy`uVBq!ia0vp^hCpn@!3HG1au{y{QY`6?zK#qG*KS<#k1zuAB}-f* zN`mv#O3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrIztFuw70aSX}0_jZQ0-%$er*Z!9p zHyA|c&k_w#_WIWm?|CpQLfAWzIix|M@*H=sa<5z2n-7x~v>%(4>h5LeZv6e63ZDg| z)&uDkhxhVTE0!_;D9}54vu$$0`)x75EO*a~kL$i)%9bdA9R)HhWR~YKOquFb!T7-W zLech#I%oI-)fHZqHd?$rd1QZUMvI)6q8jT-#|+;erHvC5G&^QkXEsDCo?~)QZIWkB z+Lp6K!OQfb28WTVDW?Z};L5wK@!}@CXQ-vMTZAw2E6vH>xU%Tf)GIFx_;v_94M|rB zdN)P*+Y$v?7g51)N{c#Y=-pzPt;@MBmi5u514&EOf}Tz(Ug4?xO=}Y8%-%U_MUUpy zuoNEH$`O}-xP5oHHS0#172Ow23O{=%n$L8cAliPgjN{1LhN4ds)3*P~UR`>ic1g0n zl0dIT^39C@SwNk0Id(0XvqUZE(Y&w4R~h-al*0XFUEVxiu|A&X>=6ZD8>acTz3alB zUYXuG<*HxScD@Rxd&-wrw|w*xu5;}u%PGIb-q*ODqeEZD_KSzzvFrB~I(Q#2Snw#s zJ1Osbp6;k6Y}wdv*R`V{k74(Lzzw(g7f$wK@aVoecXwyX!uRJNWK4T~<+Iub-ZzZa e2gI^B)G;(vHM#teVDknh4hBzGKbLh*2~7Y|hVgCy literal 0 HcmV?d00001 diff --git a/demos/shared/images/frame_bottomright.png b/demos/shared/images/frame_bottomright.png new file mode 100644 index 0000000000000000000000000000000000000000..0021e35864ca0cb2dbedc95c6f20454dadae2910 GIT binary patch literal 553 zcmeAS@N?(olHy`uVBq!ia0vp^hCpn@!3HG1au{y{QY`6?zK#qG*KS<#k1zuAB}-f* zN`mv#O3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrIztFz)traSX}0_jZP_-(dp*xBC{$ z*0Kn3>m3NR2Hjcxb$U?hPdH2K_?~h$-G09l;B*(kt zjsWLOgQZ0R>mH>1m@0nz;2h0W!Ec|h(D2)JW`_zx{qbupB4UPt3`GHjC45Rx-0#?X zK0P$8`Nfpq7k*Z}TV*;o>-+EH4m{78mj@@)hJ%ExE5Pd4zcn|{Fd!v*ln?xJ m>r30$Ap3!_hUxy{1M(|c1W&B%=(qulYX(nOKbLh*2~7atlJRT+ literal 0 HcmV?d00001 diff --git a/demos/shared/images/frame_left.png b/demos/shared/images/frame_left.png new file mode 100644 index 0000000000000000000000000000000000000000..40f331c2931fa636a73479233a689462f20d8032 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^hCs~4!3HE{6}J@uDVB6cUq=RpYd5a=M;HP5k|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5XJUm?-Lo7}wrz9kNV1G2<;SY01 zz2nXO3x1dj{o_7Tzu=3#$}jsVX$_kaB_tPo=4{%>%-<1q+TvAbpnp$Q(iP#w^CZ3= dDfrI9V0-!b^%=p@6M<$jc)I$ztaD0e0s!^&KcoNv literal 0 HcmV?d00001 diff --git a/demos/shared/images/frame_right.png b/demos/shared/images/frame_right.png new file mode 100644 index 0000000000000000000000000000000000000000..023af8c700bd5993ab2a02c6a6760209ed1deb3e GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^hCs~4!3HE{6}J@uDVB6cUq=RpYd5a=M;HP5k|nMY zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5X96eneLo7}wzp?(%&=?W$WWfOk zwuB>x(p`kon>IO`7z>?cS{gagKw4z8b0(j_?7}O;i|0vvJ+eaG&DQW$=fiiL3=>}| VD*pG+P6Hao;OXk;vd$@?2>_E5IG+Fj literal 0 HcmV?d00001 diff --git a/demos/shared/images/frame_top.png b/demos/shared/images/frame_top.png new file mode 100644 index 0000000000000000000000000000000000000000..001f3a71440bdfd8b692646e0f52d16e69e9e71c GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^oIq^I!2%=~ZS;-?QY`6?zK#qG*KS<#k1zuAB}-f* zN`mv#O3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrH1%`FXlHhG?8mPK-Fvz!o7RR icQae_1$(y=MTXt1N=LK~HcJ6bX7F_Nb6Mw<&;$UUK|Ff^ literal 0 HcmV?d00001 diff --git a/demos/shared/images/frame_topleft.png b/demos/shared/images/frame_topleft.png new file mode 100644 index 0000000000000000000000000000000000000000..58c68d407ad92e90784f5a1c5daccbc1d3184f69 GIT binary patch literal 801 zcmV++1K#|JP)@aZn)zwUh#xK*ff-YHE;`&19B7P6llXUUhxYr5Re9C z1(GQjS%Y}P1HU!ARCjxtLj(%7;VWK18jebE)-Qe0co2opAs+Yy((nfqX>bGd?XN?I zSbPV8z#z@tSWsy`yZq1COdy_+KoBGiEBYo5&NGpcyF?51Sy?0q$T5<_Ok7u_^GSe3 zauBoFQTXAEG8d$(L{v>G?pTC-VH`Xg`_k?j_2>xg-8=yC zZ+^e%M_|YoK2vJOUp;C4l&uwY0U;VJm2hUdc5{`k51~Sl+Yf35ao35~5fWp;E_d!S zAGbQpzzSu@8o$G}TI&5EF$jN7;-)|{IYY_HKa8z8_0<=j0EC=vEYKbK`}0P>UxyV{ zhnw-i%7I`G(F(H;?pquVZx9$3q=v!Ce7zWh7&NkHFe^@g&%MjI)=uA8Sp$In5pH`h z){LxbDYL+!tJ}$(j<=U#A)&b)M{Un zw*KtT;Tl1A;UzqTH}Ir~;96Qw*o2Ij)q`BJ zXK)Q~CsF9(L?m*Rn#-q zkS;IK)V6Glu%(x-3OP={D|?c95|I9tOn!$wv*>gS=T=Q-Q;_9^oTkDhhc&FeDlUs& zR|R*!H}r9(IXv{#pHG38MQL8F(99CmlK3jn* zO+vQ{vgJ|gMaVva&{RofIVeh~n<})R#WtQCQs!<43g14K3mStwQihM?Fo+OUj2u!0 zu%145fgM9g6*aalij5=ssg@WzHTOz5dn($XvJ6^90i(I7+dCVPbyg@F&BZQULeb;n zGAD3Zx?5mEa!77nR#B}!rJ1ACahZxb5B=x=B2W_7syet-MIWma`K5?FdgVl|`D*T1!wPstqW_mgMd3!f*xz?;nhpVqjpD@^oP|MBqSm`qJ#y3iyEn@{ zLPH-_#@#pJm1<)Q^wJNSrfS5)tf=X9ds}d!VWRE4)W|ZuxYOSzPrgxlcWL*j`APS` zUqAA6O@;SNrz@qkBGb(~-((*Ta-6p1*Yu1?F-tjnh4aM;ZyA1mJ#|KU>dGIx?!P}! z8hcM@!Ql@oDGMggJGAqJ+QXaMa+^MiH7PXgTIZU!&2M@`-TUJWF){9eUy3aD)F<`0 zK3k-*V3n4hzKZs-wvPvxi*{5T-{F6`MEtm+MIZB;8if`HXFdgVl|`DLnRijWr6N#>Ey>&6h2abc-ai;G#lXPGSuu2a)#Wye+!L zZ88d}dKC|8P{&(G~Rntv;<9QD^Y{-pHi7X3^I$A9>f91E{Bj@WUn;bT< z33wYk@A)>bJ+4W|3io8sdbUxc>#^Fz%-d!0)1LlLE1ad4_cmkJGqZ^cS9(dkc;-?u zkNtXSzWDP>x9g?yeUC#N1?F5)oc3Cr;r{PgW*>zw9n@khVSK+!g3B-IkU`57b`{S_ znt|dmPDT>H4AcE41u6ACHujGCvvq~|h3if4e=nGK#X#fb5>?et$#I9?A5l(kWNVz? b^o)D&^?>B$6!9ovNHKW2`njxgN@xNALcE#g literal 0 HcmV?d00001 diff --git a/demos/shared/images/groupframe_bottom_stretch.png b/demos/shared/images/groupframe_bottom_stretch.png new file mode 100644 index 0000000000000000000000000000000000000000..f47b67d7c0966bd4115d3c6cf9dc2b5528e5c1fd GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrC!2%>*y!KrOQk(@Ik;M!Q+`=Ht$S`Y;1W=H@ z#M9T6{VIzzw}RaK#N|#vA*Lj6cNd2L?fqx=19@_uE{-7_*OO jFY~(}{;zL)_MhQZBhSx@?K@XXNJ|hA@MULUp3d;| TY50>Gpd5pztDnm{r-UW|E5R2Cc}sM`G4=A6_u_U)l- zy}h}(c57`1AfxZzY?fDxmEMRX0kYEU*Ya#J2uCWFECAWd&FON%u~uuURtP}$;_6*( zW^Qi!ss390OxrXw_-m4HzWngqGjr4T<+pf{{jo7fnta`zm}@=$Sf0h&L{hsqVwZ1U zKXvTUd3he4QmAxF(8PN6MDwBg9N!fVMx7)il}X;sj#R6-Oryru9Y$NpK@P97_!ool zpjRp+j7BMwBuebD2f$tUjeDgL1t7@^0@QlFWB|!%5aK_w@=^d?8;gPf0000r zI?r%AGuYA=Q8RFv&3yNqbMF*dtrq^5BuVJ?dax`DaU8paOQ%w);CGcuB@~NAl*?ss z90#7~S%WOg{x(ol6^g1rRmlCJpxf<2Y`2+mycGcsiXz*L4QpR6WD}?RJYG2$=F{G-B3o zg6G_0nt48-GnnrAF7S9fKJRurYq?y)aU8a)yTJ3XUcxYR>DqFEBRwm>CDV_kI5ZC|z{{xv2@S}&x7sz5R z3GxeOXka+_HD)T1Ywqdd7{U>qyaK3{={M^)AXRkLsKMg&K^e9-AgBJp{{#F>!v3-s m)~#hP{@|g|leEJ183TjGO{c@(qW&xaneFN7=d#Wzp$P!VC^bU> literal 0 HcmV?d00001 diff --git a/demos/shared/images/line_dash_dot_dot.png b/demos/shared/images/line_dash_dot_dot.png new file mode 100644 index 0000000000000000000000000000000000000000..0d9bb972f9e231b0e2369b01e94878bdaddebc68 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^aX`$%#0(^>Rwm>CDV_kI5ZC|z{{xv2@S}&x7sz5R z3GxeOU}z9O=l&1Kwf1yz4B?1Qz5!JFznzopr0D7Y@mH+?% literal 0 HcmV?d00001 diff --git a/demos/shared/images/line_dashed.png b/demos/shared/images/line_dashed.png new file mode 100644 index 0000000000000000000000000000000000000000..d5bc7ea5fe5ac42897401bbf46164749a8af52f4 GIT binary patch literal 121 zcmeAS@N?(olHy`uVBq!ia0vp^F+j}1#0(_sVm1TqyaK57KQo(;kjJ0@4osbgWf)#CdpREavDpx$+tbz0 JWt~$(69A?cA^iXV literal 0 HcmV?d00001 diff --git a/demos/shared/images/line_dotted.png b/demos/shared/images/line_dotted.png new file mode 100644 index 0000000000000000000000000000000000000000..a2f9a359257736f9971eca57f5acce547eb03515 GIT binary patch literal 116 zcmeAS@N?(olHy`uVBq!ia0vp^aX`$%#0(^>Rwm>CDb4_&5ZC|z{{xvoP#3r|7DzFb z1o;IsG|blalK}E0JY5_^IHHqJq$JEf(9j!k^uX2z6Q=2b3>`bg?c=s3o&xFgboFyt I=akR{0P>C>MF0Q* literal 0 HcmV?d00001 diff --git a/demos/shared/images/line_solid.png b/demos/shared/images/line_solid.png new file mode 100644 index 0000000000000000000000000000000000000000..60ef3f948570798163771489332d9b5022fff4ec GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^F+j}1$P6Sc|D0+BQfvV}A+A6g2$rVrJP)K8OM?7@ z8`j1}y8$_3o-U3d9MQ=u{`0f*O9;IAFCSoe;uOP{O?st*x{|>lZJw@vF6*2UngH_l B8sPu{ literal 0 HcmV?d00001 diff --git a/demos/shared/images/radiobutton-off.png b/demos/shared/images/radiobutton-off.png new file mode 100644 index 0000000000000000000000000000000000000000..af1753a3e7158aff0f70048ffd29570cf66ea72c GIT binary patch literal 442 zcmV;r0Y(0aP)JP00004XF*Lt007q5 z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzOi4sRR47wz zkg;mQP!xs}a4M7zT`Tknx^)mrq0q&(@8DRMVsYv-SV$L12Ptu>af^_kILak7;E+kT zOrm?n)AL`jY{nJDDxoe8zN1`Z_(P(r;G#*P)6oP}x!s}!*sgh)7 zZ?sI^H=f$>EJ*|hmxa(6Q)gKw^ZEQFbU3&yd@dG?dbL_fp64f_!@*_YZ7>*AdV_2> zo0HJt;Ii^T| zW9#4B#A*6k6zu$7!;%zP-@kT8*pDu8=9ztO?-wWC{#L#JzW=x1wX;$q`BJRR=EUDz zHsfrX{Oz}4ReR^{Shrg7^2V9Uf0s(1|2#>9>*>0iQ@oZcotvrL_xQz~kXVVfrsmTJ zA7^d#s=YrwYpd4M_DLd-7q$5uZvzV3cuv}LHOq7P<%u7^MX2xf655D?FJP00004XF*Lt007q5 z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzOi4sRR47w@ zk+Dj{P!xs}=p=}Ps|BCH&7mNI;L_E1$k;4W>Ett1=p;H+yP1?`ZbB$=xn$|mW{9*y zrb73Q$MeN2QYc>d$l?FLL(*Hv`8%$1t=ucm7G^TKy>sHa?nk%VHEEhw+wFD-%w%*p zzp_g(7z`Hc^;%St(P&h|Oh#vy>NnkVeBYF1DU)a-!{N~KRzIUCk}vK2j&E>TcnE@^ z%CbztFqH8)ln|K1pJ(=&2@Wm`FUAH62ptYC3$IC%?D9O9|G>dz;j!QESM&K? z_#KC!!@*_YPLG+*X0lqXWV6}qK}Lsz%R-YY^E_`coyM{(3eo?drdSpdYer|UwaLP% z(jsWL+osp+ReJ9`U?#J2%eu~ya;97=zVf8JTbRk{aB!W5a%_VO)Ylw*R4c#Osd%LdGH2?qr07*qoM6N<$f*K{wzyJUM literal 0 HcmV?d00001 diff --git a/demos/shared/images/radiobutton_on.png b/demos/shared/images/radiobutton_on.png new file mode 100644 index 0000000000000000000000000000000000000000..50a049ec56c7a9c5d90318453d5559fd3c0db8d5 GIT binary patch literal 499 zcmVJP00004XF*Lt007q5 z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzg-Jv~R47wb zkg-bwVH}3Vv`}{aK%ldn^BC9x7G!0}rwtsKbw(XZnr4sgfz5ZY@ zh=5GThVv`i6pcpX`}Olx{3BlyiwO;xj?EnDFD)GgLD+e3%Y120V!4=1tUBVXIXcgk z=B4w|k>D^0aXC0`x7+>glWmD_#3iwtl+=DoF)7L2gzngIa5;Dg!!VlJoRO)6DRIwT znZ26Tkm=ZPa5-poyWPm$b0u9%OSYMn+;dJtrenjw<>0JdulKhuwj^_#k-}R+ioK$S zOvi?U%Rx!K@aFMGylYSLFL_!2TGx>2*l=(;aQJ2Aa{2qRRTKZ-mzCy<#=qZ@n(Elh zZ*@2rQ)DPS&kL*7YG3{L2*`9s&KTDkR*Wmsia>FvcruXb*l=*IA;pL(rWFf{WdoUx p4F^|00@r+!F>WB!u?>lc^#cp_+@YdX%_{%^002ovPDHLkV1jWl>PG+o literal 0 HcmV?d00001 diff --git a/demos/shared/images/slider_bar.png b/demos/shared/images/slider_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3d62c0079ac3d0b9b19fdfc15456503a41682f GIT binary patch literal 748 zcmVT`=gCq&KOtO$9V_{BhpVQ7@=k4w7 z>h<;Y@W{HmyEAaz0l>(3V{>GrfNYkwKLhm)9NFGX)-t}vxY`hS1uP~Yod6g0e1r|* zdg=q%0G}qdGhj)*uawfy2_p&$k+DLCy`;}0a9!IX_3Z24zqH#uk7TXa>nq!lElaX} zZu?YqF53%Rmy$Io#lErK6(ZX!+sD;rftR+=dNQ_)?JtwHFkg)`0pP;+$pEUo09Jb- z4M}!eP1v%dWWGmGNtxX(DHXH^OiB@90I~WQZGjp19pKVz`)jaBY5pwI2yAiK9^x8v zsKTkS)AF(YdU?^$rzd&6Ucb`<_J94FT4Yz&rz(}I3ij-SqC!&>!l`R}qNovofEfN8 zV2nvl6cT&wX15evH`)bAjj|LaXyy zAc)lc-SbY{?RKoJ+uPeKS;6$GIJbT3P6jM&U+xidGbP6M3OMeqB()`+O$aH#mkvg1 zpkILu$&!mCCuAUG0j!dYD*so2x)7pLMunD=HZLk=PL_>IsYLDj4UNDsBWtLf7E75_ z+q}v;PBl+4w9~;}vFmFM`WhF?W38!@!B4MSI z*g6-zvar$!+wFGR{@5NKS%)+pA0LnVd)uq2l-$f)V=mo3Y}#{lN^%av$5USZe7So1 e`Sd~7A&uWkFI3KH8n3_r0000(R2Ufr z!B1`*WgGy|_ZyEr_WW^dCn`b&1tCKl5*1~~CAbGSfLwtEyY?QOqGZ)YOVvVzK(s1_ zHnCzSj_rv*-iwqHfQa}M5AYd=xWb=!nNs>2KuQS$4-XFyAD^C{J~=x(yJ*`s{c?78 zae8|CBRz0Y-ZA(f3GJuE>*xTK+H{LTDO-x1;a)vwQ_b za+DZjf*!8%7H{w$u5zq#g?E4(4AI2~SNIq2aD{b_4HkekW*8txizVi`!UCH>po1=Y zD9}S7VT~2m*x)WwN+Kcv9c0K5NZ4YFJ4h*|{{gZq2Mw~1?yLX+002ovPDHLkV1oJG BZnOXZ literal 0 HcmV?d00001 diff --git a/demos/shared/images/slider_thumb_on.png b/demos/shared/images/slider_thumb_on.png new file mode 100644 index 0000000000000000000000000000000000000000..8e1f510813e7fdd0a435651d33b5132c6d9760bb GIT binary patch literal 798 zcmV+(1L6FMP)_6P! zefREP^ZESei1@q20DGgpf83_D`}F9kUrv6tu2<@HZL-{Pr~7QT@B7E|`Fsy21%|j+ z*Uf#x@rPqqw@brz=xTfA^@n3n*Uf$0!>~k!ZcxNjWK~ybb{c7#xC!fa&4NKuOwpk# zQ9}k)ZKa!b+B>aSh3j<10y02dqJoGZ(=?4y+v~?8@rldo5@Z2Tl_(+0a?lQ1eKj(v zCbs3)r(%ID04PfoAQM80WNd62Q=8amB^g-;C`trCMyoZpV`^$;C20`=5G6neA!~JZ zj7>}|Ep1K*8ygu((EtD_07M|9qBR#@G-rC}nFGk^jhA_V%>>zYp2blTKu>lRs#08jvAWLZi{+q9ah(bh?uS|Dct z1z@wiy*&#dHAywBRAr^98mUQOo404!K!J?&)oOJFRaqGfN>G-iR3&m)U9XOCj$B}i z)ARH5=gZ~tWV2jL!`j_1?rQ7K?Rx9-YI$;Taq%3d*p|4#$N7Bz>g9`8U}fi7AzZCsS>Jid;Qi978y+Cucm5eO{pPI>6R>p|f|b z+unNH=JGJ7z19Lo7R;3iZOk(ku^!%bkM)qj=}nCWTVzaL={7Fn$=c(@Hz#t=R|ciM WX14Lx|26{+WbkzLb6Mw<&;$V2fjX7| literal 0 HcmV?d00001 diff --git a/demos/shared/images/title_cap_right.png b/demos/shared/images/title_cap_right.png new file mode 100644 index 0000000000000000000000000000000000000000..dc3ff8536c7e6e772ad552bf734c1a88ec18cd14 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^EI=&80V1!JZ!ZQ3q&xaL0(m#C_(vE4`I05B5hcO- zX(i=}MX3yqDfvmM3ZA)%>8U}fi7AzZCsS>Jio85s978y+C)lFz;gC%(NKjyrV&F_+I5=aTO$Jbc!PC{xWt~$(699M8 B7^46H literal 0 HcmV?d00001 diff --git a/demos/shared/shared.pri b/demos/shared/shared.pri new file mode 100644 index 0000000..fb7b04c --- /dev/null +++ b/demos/shared/shared.pri @@ -0,0 +1,21 @@ +INCLUDEPATH += $$SHARED_FOLDER + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} +contains(CONFIG, debug_and_release_target) { + CONFIG(debug, debug|release) { + QMAKE_LIBDIR += $$SHARED_FOLDER/debug + } else { + QMAKE_LIBDIR += $$SHARED_FOLDER/release + } +} else { + QMAKE_LIBDIR += $$SHARED_FOLDER +} + +hpux-acc*:LIBS += $$SHARED_FOLDER/libdemo_shared.a +hpuxi-acc*:LIBS += $$SHARED_FOLDER/libdemo_shared.a +symbian:LIBS += -ldemo_shared.lib +!hpuxi-acc*:!hpux-acc*:!symbian:LIBS += -ldemo_shared + diff --git a/demos/shared/shared.pro b/demos/shared/shared.pro new file mode 100644 index 0000000..ab31b32 --- /dev/null +++ b/demos/shared/shared.pro @@ -0,0 +1,38 @@ +TEMPLATE = lib +CONFIG += static + +contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2) { + DEFINES += QT_OPENGL_SUPPORT + QT += opengl +} + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} +TARGET = demo_shared + +SOURCES += \ + arthurstyle.cpp\ + arthurwidgets.cpp \ + hoverpoints.cpp + +HEADERS += \ + arthurstyle.h \ + arthurwidgets.h \ + hoverpoints.h + +RESOURCES += shared.qrc + +# install +target.path = $$[QT_INSTALL_DEMOS]/qttools/shared +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.pri images +sources.path = $$[QT_INSTALL_DEMOS]/qttools/shared +INSTALLS += sources + +!cross_compile:INSTALLS += target + +symbian { + TARGET.UID3 = 0xA000A63C + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) +} diff --git a/demos/shared/shared.qrc b/demos/shared/shared.qrc new file mode 100644 index 0000000..17336ec --- /dev/null +++ b/demos/shared/shared.qrc @@ -0,0 +1,39 @@ + + + images/button_normal_cap_left.png + images/button_normal_cap_right.png + images/button_normal_stretch.png + images/button_pressed_cap_left.png + images/button_pressed_cap_right.png + images/button_pressed_stretch.png + images/radiobutton-on.png + images/radiobutton_on.png + images/radiobutton_off.png + images/slider_bar.png + images/slider_thumb_on.png + images/groupframe_topleft.png + images/groupframe_topright.png + images/groupframe_bottom_left.png + images/groupframe_bottom_right.png + images/groupframe_top_stretch.png + images/groupframe_bottom_stretch.png + images/groupframe_left_stretch.png + images/groupframe_right_stretch.png + images/frame_topleft.png + images/frame_topright.png + images/frame_bottomleft.png + images/frame_bottomright.png + images/frame_left.png + images/frame_top.png + images/frame_right.png + images/frame_bottom.png + images/title_cap_left.png + images/title_cap_right.png + images/title_stretch.png + images/line_dash_dot.png + images/line_dotted.png + images/line_dashed.png + images/line_solid.png + images/line_dash_dot_dot.png + + diff --git a/examples/designer/README b/examples/designer/README new file mode 100644 index 0000000..fb9443c --- /dev/null +++ b/examples/designer/README @@ -0,0 +1,37 @@ +Qt Designer is a capable graphical user interface designer that lets you +create and configure forms without writing code. GUIs created with +Qt Designer can be compiled into an application or created at run-time. + + +Some of the examples in this directory can be run from the example launcher; +others can only be used from within Qt Designer. + +Documentation for these examples can be found via the "Tutorial and Examples" +link in the main Qt documentation. + +Finding the Qt Examples and Demos launcher +========================================== + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Qt Examples and Demos" entry in the submenu containing +the Qt tools. + +On Mac OS X: + +For the binary distribution, the qtdemo executable is installed in the +/Developer/Applications/Qt directory. For the source distribution, it is +installed alongside the other Qt tools on the path specified when Qt is +configured. + +On Unix/Linux: + +The qtdemo executable is installed alongside the other Qt tools on the path +specified when Qt is configured. + +On all platforms: + +The source code for the launcher can be found in the demos/qtdemo directory +in the Qt package. This example is built at the same time as the Qt libraries, +tools, examples, and demonstrations. diff --git a/examples/designer/calculatorbuilder/calculatorbuilder.pro b/examples/designer/calculatorbuilder/calculatorbuilder.pro new file mode 100644 index 0000000..ca4a3ea --- /dev/null +++ b/examples/designer/calculatorbuilder/calculatorbuilder.pro @@ -0,0 +1,16 @@ +#! [0] +CONFIG += uitools + +HEADERS = calculatorform.h +RESOURCES = calculatorbuilder.qrc +SOURCES = calculatorform.cpp \ + main.cpp +#! [0] + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/calculatorbuilder +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.ui *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/calculatorbuilder +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/designer/calculatorbuilder/calculatorbuilder.qrc b/examples/designer/calculatorbuilder/calculatorbuilder.qrc new file mode 100644 index 0000000..19b3905 --- /dev/null +++ b/examples/designer/calculatorbuilder/calculatorbuilder.qrc @@ -0,0 +1,5 @@ + + + calculatorform.ui + + diff --git a/examples/designer/calculatorbuilder/calculatorform.cpp b/examples/designer/calculatorbuilder/calculatorform.cpp new file mode 100644 index 0000000..e14efa4 --- /dev/null +++ b/examples/designer/calculatorbuilder/calculatorform.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#include +//! [0] +#include + +#include "calculatorform.h" + +//! [1] +CalculatorForm::CalculatorForm(QWidget *parent) + : QWidget(parent) +{ + QUiLoader loader; + + QFile file(":/forms/calculatorform.ui"); + file.open(QFile::ReadOnly); + QWidget *formWidget = loader.load(&file, this); + file.close(); +//! [1] + +//! [2] + ui_inputSpinBox1 = findChild("inputSpinBox1"); + ui_inputSpinBox2 = findChild("inputSpinBox2"); + ui_outputWidget = findChild("outputWidget"); +//! [2] + +//! [3] + QMetaObject::connectSlotsByName(this); +//! [3] + +//! [4] + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(formWidget); + setLayout(layout); + + setWindowTitle(tr("Calculator Builder")); +} +//! [4] + +//! [5] +void CalculatorForm::on_inputSpinBox1_valueChanged(int value) +{ + ui_outputWidget->setText(QString::number(value + ui_inputSpinBox2->value())); +} +//! [5] //! [6] + +//! [6] //! [7] +void CalculatorForm::on_inputSpinBox2_valueChanged(int value) +{ + ui_outputWidget->setText(QString::number(value + ui_inputSpinBox1->value())); +} +//! [7] diff --git a/examples/designer/calculatorbuilder/calculatorform.h b/examples/designer/calculatorbuilder/calculatorform.h new file mode 100644 index 0000000..f891823 --- /dev/null +++ b/examples/designer/calculatorbuilder/calculatorform.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CALCULATORFORM_H +#define CALCULATORFORM_H + +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QSpinBox; +QT_END_NAMESPACE + +//! [0] +class CalculatorForm : public QWidget +{ + Q_OBJECT + +public: + CalculatorForm(QWidget *parent = 0); + +private slots: + void on_inputSpinBox1_valueChanged(int value); + void on_inputSpinBox2_valueChanged(int value); + +private: + QSpinBox *ui_inputSpinBox1; + QSpinBox *ui_inputSpinBox2; + QLabel *ui_outputWidget; +}; +//! [0] + +#endif diff --git a/examples/designer/calculatorbuilder/calculatorform.ui b/examples/designer/calculatorbuilder/calculatorform.ui new file mode 100644 index 0000000..dda0e62 --- /dev/null +++ b/examples/designer/calculatorbuilder/calculatorform.ui @@ -0,0 +1,303 @@ + + + + + CalculatorForm + + + CalculatorForm + + + + 0 + 0 + 276 + 98 + + + + + 5 + 5 + 0 + 0 + + + + Calculator Builder + + + + + + + 9 + + + 6 + + + + + + + + 1 + + + 6 + + + + + + + + 1 + + + 6 + + + + + label + + + + 1 + 1 + 45 + 19 + + + + Input 1 + + + + + + + inputSpinBox1 + + + + 1 + 26 + 45 + 25 + + + + true + + + + + + + + + label_3 + + + + 54 + 1 + 7 + 52 + + + + + + + + Qt::AlignCenter + + + + + + + + + + 1 + + + 6 + + + + + label_2 + + + + 1 + 1 + 45 + 19 + + + + Input 2 + + + + + + + inputSpinBox2 + + + + 1 + 26 + 45 + 25 + + + + true + + + + + + + + + label_3_2 + + + + 120 + 1 + 7 + 52 + + + + = + + + Qt::AlignCenter + + + + + + + + + + 1 + + + 6 + + + + + label_2_2_2 + + + + 1 + 1 + 37 + 17 + + + + Output + + + + + + + outputWidget + + + + 1 + 24 + 37 + 27 + + + + QFrame::Box + + + QFrame::Sunken + + + 0 + + + Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask + + + + + + + + + + + verticalSpacer + + + + 85 + 69 + 20 + 20 + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + horizontalSpacer + + + + 188 + 26 + 79 + 20 + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + diff --git a/examples/designer/calculatorbuilder/main.cpp b/examples/designer/calculatorbuilder/main.cpp new file mode 100644 index 0000000..b5cab6b --- /dev/null +++ b/examples/designer/calculatorbuilder/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "calculatorform.h" + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(calculatorbuilder); + + QApplication app(argc, argv); + CalculatorForm calculator; + calculator.show(); + return app.exec(); +} diff --git a/examples/designer/calculatorform/calculatorform.cpp b/examples/designer/calculatorform/calculatorform.cpp new file mode 100644 index 0000000..ef9022f --- /dev/null +++ b/examples/designer/calculatorform/calculatorform.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "calculatorform.h" + +//! [0] +CalculatorForm::CalculatorForm(QWidget *parent) + : QWidget(parent) +{ + ui.setupUi(this); +} +//! [0] + +//! [1] +void CalculatorForm::on_inputSpinBox1_valueChanged(int value) +{ + ui.outputWidget->setText(QString::number(value + ui.inputSpinBox2->value())); +} +//! [1] + +//! [2] +void CalculatorForm::on_inputSpinBox2_valueChanged(int value) +{ + ui.outputWidget->setText(QString::number(value + ui.inputSpinBox1->value())); +} +//! [2] diff --git a/examples/designer/calculatorform/calculatorform.h b/examples/designer/calculatorform/calculatorform.h new file mode 100644 index 0000000..9406995 --- /dev/null +++ b/examples/designer/calculatorform/calculatorform.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CALCULATORFORM_H +#define CALCULATORFORM_H + +//! [0] +#include "ui_calculatorform.h" +//! [0] + +//! [1] +class CalculatorForm : public QWidget +{ + Q_OBJECT + +public: + CalculatorForm(QWidget *parent = 0); + +private slots: + void on_inputSpinBox1_valueChanged(int value); + void on_inputSpinBox2_valueChanged(int value); + +private: + Ui::CalculatorForm ui; +}; +//! [1] + +#endif diff --git a/examples/designer/calculatorform/calculatorform.pro b/examples/designer/calculatorform/calculatorform.pro new file mode 100644 index 0000000..65a8cfe --- /dev/null +++ b/examples/designer/calculatorform/calculatorform.pro @@ -0,0 +1,15 @@ +#! [0] +HEADERS = calculatorform.h +#! [0] #! [1] +FORMS = calculatorform.ui +#! [1] +SOURCES = calculatorform.cpp \ + main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/calculatorform +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/calculatorform +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/designer/calculatorform/calculatorform.ui b/examples/designer/calculatorform/calculatorform.ui new file mode 100644 index 0000000..3a95639 --- /dev/null +++ b/examples/designer/calculatorform/calculatorform.ui @@ -0,0 +1,284 @@ + + + + + CalculatorForm + + + CalculatorForm + + + + 0 + 0 + 400 + 300 + + + + + 5 + 5 + 0 + 0 + + + + Calculator Form + + + + + + + 9 + + + 6 + + + + + horizontalSpacer + + + + 239 + 9 + 152 + 52 + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + label_3_2 + + + + 169 + 9 + 20 + 52 + + + + = + + + Qt::AlignCenter + + + + + + + + + + 1 + + + 6 + + + + + label_2_2_2 + + + + 1 + 1 + 36 + 17 + + + + Output + + + + + + + outputWidget + + + + 1 + 24 + 36 + 27 + + + + QFrame::Box + + + QFrame::Sunken + + + 0 + + + Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask + + + + + + + + + verticalSpacer + + + + 89 + 67 + 20 + 224 + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 1 + + + 6 + + + + + label_2 + + + + 1 + 1 + 46 + 19 + + + + Input 2 + + + + + + + inputSpinBox2 + + + + 1 + 26 + 46 + 25 + + + + + + + + + + label_3 + + + + 63 + 9 + 20 + 52 + + + + + + + + Qt::AlignCenter + + + + + + + + + + 1 + + + 6 + + + + + label + + + + 1 + 1 + 46 + 19 + + + + Input 1 + + + + + + + inputSpinBox1 + + + + 1 + 26 + 46 + 25 + + + + + + + + + + + + diff --git a/examples/designer/calculatorform/main.cpp b/examples/designer/calculatorform/main.cpp new file mode 100644 index 0000000..2dd1fc1 --- /dev/null +++ b/examples/designer/calculatorform/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "calculatorform.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + CalculatorForm calculator; + calculator.show(); + return app.exec(); +} + diff --git a/examples/designer/containerextension/containerextension.pro b/examples/designer/containerextension/containerextension.pro new file mode 100644 index 0000000..6ded917 --- /dev/null +++ b/examples/designer/containerextension/containerextension.pro @@ -0,0 +1,28 @@ +#! [0] +TEMPLATE = lib +#! [0] +TARGET = $$qtLibraryTarget($$TARGET) +#! [1] +CONFIG += designer plugin +#! [1] +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer + +#! [2] +HEADERS += multipagewidget.h \ + multipagewidgetplugin.h \ + multipagewidgetcontainerextension.h \ + multipagewidgetextensionfactory.h + +SOURCES += multipagewidget.cpp \ + multipagewidgetplugin.cpp \ + multipagewidgetcontainerextension.cpp \ + multipagewidgetextensionfactory.cpp +#! [2] + +# install +target.path = $$[QT_INSTALL_PLUGINS]/designer +sources.files = $$SOURCES $$HEADERS *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/containerextension +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/designer/containerextension/multipagewidget.cpp b/examples/designer/containerextension/multipagewidget.cpp new file mode 100644 index 0000000..5b44f36 --- /dev/null +++ b/examples/designer/containerextension/multipagewidget.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "multipagewidget.h" + +MultiPageWidget::MultiPageWidget(QWidget *parent) + : QWidget(parent) +{ + comboBox = new QComboBox(); + comboBox->setObjectName("__qt__passive_comboBox"); + stackWidget = new QStackedWidget(); + + connect(comboBox, SIGNAL(activated(int)), + this, SLOT(setCurrentIndex(int))); + + layout = new QVBoxLayout(); + layout->addWidget(comboBox); + layout->addWidget(stackWidget); + setLayout(layout); +} + +QSize MultiPageWidget::sizeHint() const +{ + return QSize(200, 150); +} + +void MultiPageWidget::addPage(QWidget *page) +{ + insertPage(count(), page); +} + +void MultiPageWidget::removePage(int index) +{ + QWidget *widget = stackWidget->widget(index); + stackWidget->removeWidget(widget); + + comboBox->removeItem(index); +} + +int MultiPageWidget::count() const +{ + return stackWidget->count(); +} + +int MultiPageWidget::currentIndex() const +{ + return stackWidget->currentIndex(); +} + +void MultiPageWidget::insertPage(int index, QWidget *page) +{ + page->setParent(stackWidget); + + stackWidget->insertWidget(index, page); + + QString title = page->windowTitle(); + if (title.isEmpty()) { + title = tr("Page %1").arg(comboBox->count() + 1); + page->setWindowTitle(title); + } + comboBox->insertItem(index, title); +} + +void MultiPageWidget::setCurrentIndex(int index) +{ + if (index != currentIndex()) { + stackWidget->setCurrentIndex(index); + comboBox->setCurrentIndex(index); + emit currentIndexChanged(index); + } +} + +QWidget* MultiPageWidget::widget(int index) +{ + return stackWidget->widget(index); +} + +QString MultiPageWidget::pageTitle() const +{ + if (const QWidget *currentWidget = stackWidget->currentWidget()) + return currentWidget->windowTitle(); + return QString(); +} + +void MultiPageWidget::setPageTitle(QString const &newTitle) +{ + comboBox->setItemText(currentIndex(), newTitle); + if (QWidget *currentWidget = stackWidget->currentWidget()) + currentWidget->setWindowTitle(newTitle); + emit pageTitleChanged(newTitle); +} diff --git a/examples/designer/containerextension/multipagewidget.h b/examples/designer/containerextension/multipagewidget.h new file mode 100644 index 0000000..b2f3b7d --- /dev/null +++ b/examples/designer/containerextension/multipagewidget.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MULTIPAGEWIDGET_H +#define MULTIPAGEWIDGET_H + +#include + +QT_BEGIN_NAMESPACE +class QComboBox; +class QStackedWidget; +class QVBoxLayout; +QT_END_NAMESPACE + +//! [0] +class MultiPageWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex) + Q_PROPERTY(QString pageTitle READ pageTitle WRITE setPageTitle STORED false) + +public: + MultiPageWidget(QWidget *parent = 0); + + QSize sizeHint() const; + + int count() const; + int currentIndex() const; + QWidget *widget(int index); + QString pageTitle() const; + +public slots: + void addPage(QWidget *page); + void insertPage(int index, QWidget *page); + void removePage(int index); + void setPageTitle(QString const &newTitle); + void setCurrentIndex(int index); + +signals: + void currentIndexChanged(int index); + void pageTitleChanged(const QString &title); + +private: + QStackedWidget *stackWidget; + QComboBox *comboBox; + QVBoxLayout *layout; +}; +//! [0] + +#endif diff --git a/examples/designer/containerextension/multipagewidgetcontainerextension.cpp b/examples/designer/containerextension/multipagewidgetcontainerextension.cpp new file mode 100644 index 0000000..fe81534 --- /dev/null +++ b/examples/designer/containerextension/multipagewidgetcontainerextension.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "multipagewidgetcontainerextension.h" +#include "multipagewidget.h" + +//! [0] +MultiPageWidgetContainerExtension::MultiPageWidgetContainerExtension(MultiPageWidget *widget, + QObject *parent) + :QObject(parent) +{ + myWidget = widget; +} +//! [0] + +//! [1] +void MultiPageWidgetContainerExtension::addWidget(QWidget *widget) +{ + myWidget->addPage(widget); +} +//! [1] + +//! [2] +int MultiPageWidgetContainerExtension::count() const +{ + return myWidget->count(); +} +//! [2] + +//! [3] +int MultiPageWidgetContainerExtension::currentIndex() const +{ + return myWidget->currentIndex(); +} +//! [3] + +//! [4] +void MultiPageWidgetContainerExtension::insertWidget(int index, QWidget *widget) +{ + myWidget->insertPage(index, widget); +} +//! [4] + +//! [5] +void MultiPageWidgetContainerExtension::remove(int index) +{ + myWidget->removePage(index); +} +//! [5] + +//! [6] +void MultiPageWidgetContainerExtension::setCurrentIndex(int index) +{ + myWidget->setCurrentIndex(index); +} +//! [6] + +//! [7] +QWidget* MultiPageWidgetContainerExtension::widget(int index) const +{ + return myWidget->widget(index); +} +//! [7] diff --git a/examples/designer/containerextension/multipagewidgetcontainerextension.h b/examples/designer/containerextension/multipagewidgetcontainerextension.h new file mode 100644 index 0000000..dfb10c6 --- /dev/null +++ b/examples/designer/containerextension/multipagewidgetcontainerextension.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MULTIPAGEWIDGETCONTAINEREXTENSION_H +#define MULTIPAGEWIDGETCONTAINEREXTENSION_H + +#include + +QT_BEGIN_NAMESPACE +class QExtensionManager; +QT_END_NAMESPACE +class MultiPageWidget; + +//! [0] +class MultiPageWidgetContainerExtension: public QObject, + public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) + +public: + MultiPageWidgetContainerExtension(MultiPageWidget *widget, QObject *parent); + + void addWidget(QWidget *widget); + int count() const; + int currentIndex() const; + void insertWidget(int index, QWidget *widget); + void remove(int index); + void setCurrentIndex(int index); + QWidget *widget(int index) const; + +private: + MultiPageWidget *myWidget; +}; +//! [0] + +#endif diff --git a/examples/designer/containerextension/multipagewidgetextensionfactory.cpp b/examples/designer/containerextension/multipagewidgetextensionfactory.cpp new file mode 100644 index 0000000..36f3c8f --- /dev/null +++ b/examples/designer/containerextension/multipagewidgetextensionfactory.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "multipagewidgetextensionfactory.h" +#include "multipagewidgetcontainerextension.h" +#include "multipagewidget.h" + +//! [0] +MultiPageWidgetExtensionFactory::MultiPageWidgetExtensionFactory(QExtensionManager *parent) + : QExtensionFactory(parent) +{} +//! [0] + +//! [1] +QObject *MultiPageWidgetExtensionFactory::createExtension(QObject *object, + const QString &iid, + QObject *parent) const +{ + MultiPageWidget *widget = qobject_cast(object); + + if (widget && (iid == Q_TYPEID(QDesignerContainerExtension))) { + return new MultiPageWidgetContainerExtension(widget, parent); + } else { + return 0; + } +} +//! [1] diff --git a/examples/designer/containerextension/multipagewidgetextensionfactory.h b/examples/designer/containerextension/multipagewidgetextensionfactory.h new file mode 100644 index 0000000..2ed2946 --- /dev/null +++ b/examples/designer/containerextension/multipagewidgetextensionfactory.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MULTIPAGEWIDGETEXTENSIONFACTORY_H +#define MULTIPAGEWIDGETEXTENSIONFACTORY_H + +#include + +QT_BEGIN_NAMESPACE +class QExtensionManager; +QT_END_NAMESPACE + +//! [0] +class MultiPageWidgetExtensionFactory: public QExtensionFactory +{ + Q_OBJECT + +public: + MultiPageWidgetExtensionFactory(QExtensionManager *parent = 0); + +protected: + QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const; +}; +//! [0] + +#endif diff --git a/examples/designer/containerextension/multipagewidgetplugin.cpp b/examples/designer/containerextension/multipagewidgetplugin.cpp new file mode 100644 index 0000000..60aab4f --- /dev/null +++ b/examples/designer/containerextension/multipagewidgetplugin.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "multipagewidget.h" +#include "multipagewidgetplugin.h" +#include "multipagewidgetextensionfactory.h" + +//! [0] +MultiPageWidgetPlugin::MultiPageWidgetPlugin(QObject *parent) + :QObject(parent) +{ + initialized = false; +} + +QString MultiPageWidgetPlugin::name() const +{ + return QLatin1String("MultiPageWidget"); +} + +QString MultiPageWidgetPlugin::group() const +{ + return QLatin1String("Display Widgets [Examples]"); +} + +QString MultiPageWidgetPlugin::toolTip() const +{ + return QString(); +} + +QString MultiPageWidgetPlugin::whatsThis() const +{ + return QString(); +} + +QString MultiPageWidgetPlugin::includeFile() const +{ + return QLatin1String("multipagewidget.h"); +} + +QIcon MultiPageWidgetPlugin::icon() const +{ + return QIcon(); +} + +//! [0] //! [1] +bool MultiPageWidgetPlugin::isContainer() const +{ + return true; +} + +//! [1] //! [2] +QWidget *MultiPageWidgetPlugin::createWidget(QWidget *parent) +{ + MultiPageWidget *widget = new MultiPageWidget(parent); + connect(widget, SIGNAL(currentIndexChanged(int)), + this, SLOT(currentIndexChanged(int))); + connect(widget, SIGNAL(pageTitleChanged(QString)), + this, SLOT(pageTitleChanged(QString))); + return widget; +} + +//! [2] //! [3] +bool MultiPageWidgetPlugin::isInitialized() const +{ + return initialized; +} +//! [3] + +//! [4] +void MultiPageWidgetPlugin::initialize(QDesignerFormEditorInterface *formEditor) +{ + if (initialized) + return; +//! [4] + +//! [5] + QExtensionManager *manager = formEditor->extensionManager(); +//! [5] //! [6] + QExtensionFactory *factory = new MultiPageWidgetExtensionFactory(manager); + + Q_ASSERT(manager != 0); + manager->registerExtensions(factory, Q_TYPEID(QDesignerContainerExtension)); + + initialized = true; +} +//! [6] + +//! [7] +QString MultiPageWidgetPlugin::domXml() const +{ + return QLatin1String("\ +\ + \ + \ + \ + \ + \ + MultiPageWidget\ + QWidget\ + addPage\ + \ + \ +"); +} +//! [7] + +//! [8] +void MultiPageWidgetPlugin::currentIndexChanged(int index) +{ + Q_UNUSED(index); + MultiPageWidget *widget = qobject_cast(sender()); +//! [8] //! [9] + if (widget) { + QDesignerFormWindowInterface *form = QDesignerFormWindowInterface::findFormWindow(widget); + if (form) + form->emitSelectionChanged(); + } +} +//! [9] + +//! [10] +void MultiPageWidgetPlugin::pageTitleChanged(const QString &title) +{ + Q_UNUSED(title); + MultiPageWidget *widget = qobject_cast(sender()); +//! [10] //! [11] + if (widget) { + QWidget *page = widget->widget(widget->currentIndex()); + QDesignerFormWindowInterface *form; + form = QDesignerFormWindowInterface::findFormWindow(widget); +//! [11] + if (form) { +//! [12] + QDesignerFormEditorInterface *editor = form->core(); + QExtensionManager *manager = editor->extensionManager(); +//! [12] //! [13] + QDesignerPropertySheetExtension *sheet; + sheet = qt_extension(manager, page); + const int propertyIndex = sheet->indexOf(QLatin1String("windowTitle")); + sheet->setChanged(propertyIndex, true); + } + } +} + +//! [13] + +//! [14] +Q_EXPORT_PLUGIN2(containerextension, MultiPageWidgetPlugin) +//! [14] diff --git a/examples/designer/containerextension/multipagewidgetplugin.h b/examples/designer/containerextension/multipagewidgetplugin.h new file mode 100644 index 0000000..3d9ac52 --- /dev/null +++ b/examples/designer/containerextension/multipagewidgetplugin.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#ifndef MULTIPAGEWIDGETPLUGIN_H +#define MULTIPAGEWIDGETPLUGIN_H + +#include + +QT_BEGIN_NAMESPACE +class QIcon; +class QWidget; +QT_END_NAMESPACE + +class MultiPageWidgetPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) +public: + MultiPageWidgetPlugin(QObject *parent = 0); + + QString name() const; + QString group() const; + QString toolTip() const; + QString whatsThis() const; + QString includeFile() const; + QIcon icon() const; + bool isContainer() const; + QWidget *createWidget(QWidget *parent); + bool isInitialized() const; + void initialize(QDesignerFormEditorInterface *formEditor); + QString domXml() const; + +private slots: + void currentIndexChanged(int index); + void pageTitleChanged(const QString &title); + +private: + bool initialized; +}; + +#endif +//! [0] diff --git a/examples/designer/customwidgetplugin/analogclock.cpp b/examples/designer/customwidgetplugin/analogclock.cpp new file mode 100644 index 0000000..4a91e0d --- /dev/null +++ b/examples/designer/customwidgetplugin/analogclock.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "analogclock.h" + +AnalogClock::AnalogClock(QWidget *parent) + : QWidget(parent) +{ + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(update())); + timer->start(1000); + + setWindowTitle(tr("Analog Clock")); + resize(200, 200); +} + +void AnalogClock::paintEvent(QPaintEvent *) +{ + static const QPoint hourHand[3] = { + QPoint(7, 8), + QPoint(-7, 8), + QPoint(0, -40) + }; + static const QPoint minuteHand[3] = { + QPoint(7, 8), + QPoint(-7, 8), + QPoint(0, -70) + }; + + QColor hourColor(127, 0, 127); + QColor minuteColor(0, 127, 127, 191); + + int side = qMin(width(), height()); + QTime time = QTime::currentTime(); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.translate(width() / 2, height() / 2); + painter.scale(side / 200.0, side / 200.0); + + painter.setPen(Qt::NoPen); + painter.setBrush(hourColor); + + painter.save(); + painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); + painter.drawConvexPolygon(hourHand, 3); + painter.restore(); + + painter.setPen(hourColor); + + for (int i = 0; i < 12; ++i) { + painter.drawLine(88, 0, 96, 0); + painter.rotate(30.0); + } + + painter.setPen(Qt::NoPen); + painter.setBrush(minuteColor); + + painter.save(); + painter.rotate(6.0 * (time.minute() + time.second() / 60.0)); + painter.drawConvexPolygon(minuteHand, 3); + painter.restore(); + + painter.setPen(minuteColor); + + for (int j = 0; j < 60; ++j) { + if ((j % 5) != 0) + painter.drawLine(92, 0, 96, 0); + painter.rotate(6.0); + } +} diff --git a/examples/designer/customwidgetplugin/analogclock.h b/examples/designer/customwidgetplugin/analogclock.h new file mode 100644 index 0000000..db42d5a --- /dev/null +++ b/examples/designer/customwidgetplugin/analogclock.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ANALOGCLOCK_H +#define ANALOGCLOCK_H + +#include +#include + +class QDESIGNER_WIDGET_EXPORT AnalogClock : public QWidget +{ + Q_OBJECT + +public: + AnalogClock(QWidget *parent = 0); + +protected: + void paintEvent(QPaintEvent *event); +}; + +#endif diff --git a/examples/designer/customwidgetplugin/customwidgetplugin.cpp b/examples/designer/customwidgetplugin/customwidgetplugin.cpp new file mode 100644 index 0000000..d6ab592 --- /dev/null +++ b/examples/designer/customwidgetplugin/customwidgetplugin.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "analogclock.h" +#include "customwidgetplugin.h" + +#include + +//! [0] +AnalogClockPlugin::AnalogClockPlugin(QObject *parent) + : QObject(parent) +{ + initialized = false; +} +//! [0] + +//! [1] +void AnalogClockPlugin::initialize(QDesignerFormEditorInterface * /* core */) +{ + if (initialized) + return; + + initialized = true; +} +//! [1] + +//! [2] +bool AnalogClockPlugin::isInitialized() const +{ + return initialized; +} +//! [2] + +//! [3] +QWidget *AnalogClockPlugin::createWidget(QWidget *parent) +{ + return new AnalogClock(parent); +} +//! [3] + +//! [4] +QString AnalogClockPlugin::name() const +{ + return "AnalogClock"; +} +//! [4] + +//! [5] +QString AnalogClockPlugin::group() const +{ + return "Display Widgets [Examples]"; +} +//! [5] + +//! [6] +QIcon AnalogClockPlugin::icon() const +{ + return QIcon(); +} +//! [6] + +//! [7] +QString AnalogClockPlugin::toolTip() const +{ + return ""; +} +//! [7] + +//! [8] +QString AnalogClockPlugin::whatsThis() const +{ + return ""; +} +//! [8] + +//! [9] +bool AnalogClockPlugin::isContainer() const +{ + return false; +} +//! [9] + +//! [10] +QString AnalogClockPlugin::domXml() const +{ + return "\n" + " \n" +//! [11] + " \n" + " \n" + " 0\n" + " 0\n" + " 100\n" + " 100\n" + " \n" + " \n" +//! [11] + " \n" + " The current time\n" + " \n" + " \n" + " The analog clock widget displays the current time.\n" + " \n" + " \n" + "\n"; +} +//! [10] + +//! [12] +QString AnalogClockPlugin::includeFile() const +{ + return "analogclock.h"; +} +//! [12] + +//! [13] +Q_EXPORT_PLUGIN2(customwidgetplugin, AnalogClockPlugin) +//! [13] diff --git a/examples/designer/customwidgetplugin/customwidgetplugin.h b/examples/designer/customwidgetplugin/customwidgetplugin.h new file mode 100644 index 0000000..72f916b --- /dev/null +++ b/examples/designer/customwidgetplugin/customwidgetplugin.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMWIDGETPLUGIN_H +#define CUSTOMWIDGETPLUGIN_H + +#include + +//! [0] +class AnalogClockPlugin : public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + AnalogClockPlugin(QObject *parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget *createWidget(QWidget *parent); + void initialize(QDesignerFormEditorInterface *core); + +private: + bool initialized; +}; +//! [0] + +#endif diff --git a/examples/designer/customwidgetplugin/customwidgetplugin.pro b/examples/designer/customwidgetplugin/customwidgetplugin.pro new file mode 100644 index 0000000..0d37874 --- /dev/null +++ b/examples/designer/customwidgetplugin/customwidgetplugin.pro @@ -0,0 +1,23 @@ +#! [0] #! [1] +CONFIG += designer plugin +#! [0] +TARGET = $$qtLibraryTarget($$TARGET) +#! [2] +TEMPLATE = lib +#! [1] #! [2] +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer + +#! [3] +HEADERS = analogclock.h \ + customwidgetplugin.h +SOURCES = analogclock.cpp \ + customwidgetplugin.cpp +#! [3] + +# install +target.path = $$[QT_INSTALL_PLUGINS]/designer +sources.files = $$SOURCES $$HEADERS *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/customwidgetplugin +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/designer/designer.pro b/examples/designer/designer.pro new file mode 100644 index 0000000..0c1d637 --- /dev/null +++ b/examples/designer/designer.pro @@ -0,0 +1,21 @@ +TEMPLATE = subdirs +SUBDIRS = calculatorform + +!static:SUBDIRS += calculatorbuilder \ + containerextension \ + customwidgetplugin \ + taskmenuextension \ + worldtimeclockbuilder \ + worldtimeclockplugin + +# the sun cc compiler has a problem with the include lines for the form.prf +solaris-cc*:SUBDIRS -= calculatorbuilder \ + worldtimeclockbuilder + + +# install +sources.files = README *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer +INSTALLS += sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/designer/taskmenuextension/taskmenuextension.pro b/examples/designer/taskmenuextension/taskmenuextension.pro new file mode 100644 index 0000000..ab0b36d --- /dev/null +++ b/examples/designer/taskmenuextension/taskmenuextension.pro @@ -0,0 +1,27 @@ +#! [0] +TEMPLATE = lib +#! [0] +TARGET = $$qtLibraryTarget($$TARGET) +#! [1] +CONFIG += designer plugin +#! [1] +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer + +#! [2] +HEADERS += tictactoe.h \ + tictactoedialog.h \ + tictactoeplugin.h \ + tictactoetaskmenu.h +SOURCES += tictactoe.cpp \ + tictactoedialog.cpp \ + tictactoeplugin.cpp \ + tictactoetaskmenu.cpp +#! [2] + +# install +target.path = $$[QT_INSTALL_PLUGINS]/designer +sources.files = $$SOURCES $$HEADERS *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/taskmenuextension +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/designer/taskmenuextension/tictactoe.cpp b/examples/designer/taskmenuextension/tictactoe.cpp new file mode 100644 index 0000000..6a25893 --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoe.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "tictactoe.h" + +TicTacToe::TicTacToe(QWidget *parent) + : QWidget(parent) +{ +} + +QSize TicTacToe::minimumSizeHint() const +{ + return QSize(200, 200); +} + +QSize TicTacToe::sizeHint() const +{ + return QSize(200, 200); +} + +void TicTacToe::setState(const QString &newState) +{ + turnNumber = 0; + myState = "---------"; + int position = 0; + while (position < 9 && position < newState.length()) { + QChar mark = newState.at(position); + if (mark == Cross || mark == Nought) { + ++turnNumber; + myState.replace(position, 1, mark); + } + position++; + } + update(); +} + +QString TicTacToe::state() const +{ + return myState; +} + +void TicTacToe::clearBoard() +{ + myState = "---------"; + turnNumber = 0; + update(); +} + +void TicTacToe::mousePressEvent(QMouseEvent *event) +{ + if (turnNumber == 9) { + clearBoard(); + update(); + } else { + for (int position = 0; position < 9; ++position) { + QRect cell = cellRect(position / 3, position % 3); + if (cell.contains(event->pos())) { + if (myState.at(position) == Empty) { + if (turnNumber % 2 == 0) + myState.replace(position, 1, Cross); + else + myState.replace(position, 1, Nought); + ++turnNumber; + update(); + } + } + } + } +} + +void TicTacToe::paintEvent(QPaintEvent * /* event */) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + painter.setPen(QPen(Qt::darkGreen, 1)); + painter.drawLine(cellWidth(), 0, cellWidth(), height()); + painter.drawLine(2 * cellWidth(), 0, 2 * cellWidth(), height()); + painter.drawLine(0, cellHeight(), width(), cellHeight()); + painter.drawLine(0, 2 * cellHeight(), width(), 2 * cellHeight()); + + painter.setPen(QPen(Qt::darkBlue, 2)); + + for (int position = 0; position < 9; ++position) { + QRect cell = cellRect(position / 3, position % 3); + + if (myState.at(position) == Cross) { + painter.drawLine(cell.topLeft(), cell.bottomRight()); + painter.drawLine(cell.topRight(), cell.bottomLeft()); + } else if (myState.at(position) == Nought) { + painter.drawEllipse(cell); + } + } + + painter.setPen(QPen(Qt::yellow, 3)); + + for (int position = 0; position < 9; position = position + 3) { + if (myState.at(position) != Empty + && myState.at(position + 1) == myState.at(position) + && myState.at(position + 2) == myState.at(position)) { + int y = cellRect((position / 3), 0).center().y(); + painter.drawLine(0, y, width(), y); + turnNumber = 9; + } + } + + for (int position = 0; position < 3; ++position) { + if (myState.at(position) != Empty + && myState.at(position + 3) == myState.at(position) + && myState.at(position + 6) == myState.at(position)) { + int x = cellRect(0, position).center().x(); + painter.drawLine(x, 0, x, height()); + turnNumber = 9; + } + } + if (myState.at(0) != Empty && myState.at(4) == myState.at(0) + && myState.at(8) == myState.at(0)) { + painter.drawLine(0, 0, width(), height()); + turnNumber = 9; + } + if (myState.at(2) != Empty && myState.at(4) == myState.at(2) + && myState.at(6) == myState.at(2)) { + painter.drawLine(0, height(), width(), 0); + turnNumber = 9; + } +} + +QRect TicTacToe::cellRect(int row, int column) const +{ + const int HMargin = width() / 30; + const int VMargin = height() / 30; + return QRect(column * cellWidth() + HMargin, + row * cellHeight() + VMargin, + cellWidth() - 2 * HMargin, + cellHeight() - 2 * VMargin); +} diff --git a/examples/designer/taskmenuextension/tictactoe.h b/examples/designer/taskmenuextension/tictactoe.h new file mode 100644 index 0000000..53ccf04 --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoe.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TICTACTOE_H +#define TICTACTOE_H + +#include + +QT_BEGIN_NAMESPACE +class QRect; +class QSize; +QT_END_NAMESPACE + +//! [0] +class TicTacToe : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString state READ state WRITE setState) + +public: + TicTacToe(QWidget *parent = 0); + + QSize minimumSizeHint() const; + QSize sizeHint() const; + void setState(const QString &newState); + QString state() const; + void clearBoard(); + +protected: + void mousePressEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event); + +private: + enum { Empty = '-', Cross = 'X', Nought = 'O' }; + + QRect cellRect(int row, int col) const; + int cellWidth() const { return width() / 3; } + int cellHeight() const { return height() / 3; } + + QString myState; + int turnNumber; +}; +//! [0] + +#endif diff --git a/examples/designer/taskmenuextension/tictactoedialog.cpp b/examples/designer/taskmenuextension/tictactoedialog.cpp new file mode 100644 index 0000000..5af3c6f --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoedialog.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "tictactoe.h" +#include "tictactoedialog.h" + +//! [0] +TicTacToeDialog::TicTacToeDialog(TicTacToe *tic, QWidget *parent) + : QDialog(parent) +{ + ticTacToe = tic; + editor = new TicTacToe; + editor->setState(ticTacToe->state()); + + buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel + | QDialogButtonBox::Reset); + + connect(buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()), + this, SLOT(resetState())); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(saveState())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(editor); + mainLayout->addWidget(buttonBox); + + setLayout(mainLayout); + setWindowTitle(tr("Edit State")); +} +//! [0] + +//! [1] +QSize TicTacToeDialog::sizeHint() const +{ + return QSize(250, 250); +} +//! [1] + +//! [2] +void TicTacToeDialog::resetState() +{ + editor->clearBoard(); +} +//! [2] + +//! [3] +void TicTacToeDialog::saveState() +{ +//! [3] //! [4] + if (QDesignerFormWindowInterface *formWindow + = QDesignerFormWindowInterface::findFormWindow(ticTacToe)) { + formWindow->cursor()->setProperty("state", editor->state()); + } +//! [4] //! [5] + accept(); +} +//! [5] diff --git a/examples/designer/taskmenuextension/tictactoedialog.h b/examples/designer/taskmenuextension/tictactoedialog.h new file mode 100644 index 0000000..163ab89 --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoedialog.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TICTACTOEDIALOG_H +#define TICTACTOEDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +class QDialogButtonBox; +QT_END_NAMESPACE +class TicTacToe; + +//! [0] +class TicTacToeDialog : public QDialog +{ + Q_OBJECT + +public: + explicit TicTacToeDialog(TicTacToe *plugin = 0, QWidget *parent = 0); + + QSize sizeHint() const; + +private slots: + void resetState(); + void saveState(); + +private: + TicTacToe *editor; + TicTacToe *ticTacToe; + QDialogButtonBox *buttonBox; +}; +//! [0] + +#endif diff --git a/examples/designer/taskmenuextension/tictactoeplugin.cpp b/examples/designer/taskmenuextension/tictactoeplugin.cpp new file mode 100644 index 0000000..45c078c --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoeplugin.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "tictactoe.h" +#include "tictactoeplugin.h" +#include "tictactoetaskmenu.h" + +//! [0] +TicTacToePlugin::TicTacToePlugin(QObject *parent) + : QObject(parent) +{ + initialized = false; +} + +QString TicTacToePlugin::name() const +{ + return "TicTacToe"; +} + +QString TicTacToePlugin::group() const +{ + return "Display Widgets [Examples]"; +} + +QString TicTacToePlugin::toolTip() const +{ + return ""; +} + +QString TicTacToePlugin::whatsThis() const +{ + return ""; +} + +QString TicTacToePlugin::includeFile() const +{ + return "tictactoe.h"; +} + +QIcon TicTacToePlugin::icon() const +{ + return QIcon(); +} + +bool TicTacToePlugin::isContainer() const +{ + return false; +} + +QWidget *TicTacToePlugin::createWidget(QWidget *parent) +{ + TicTacToe *ticTacToe = new TicTacToe(parent); + ticTacToe->setState("-X-XO----"); + return ticTacToe; +} + +bool TicTacToePlugin::isInitialized() const +{ + return initialized; +} + +//! [0] //! [1] +void TicTacToePlugin::initialize(QDesignerFormEditorInterface *formEditor) +{ +//! [1] //! [2] + if (initialized) + return; + + QExtensionManager *manager = formEditor->extensionManager(); + Q_ASSERT(manager != 0); +//! [2] + +//! [3] + manager->registerExtensions(new TicTacToeTaskMenuFactory(manager), + Q_TYPEID(QDesignerTaskMenuExtension)); + + initialized = true; +} + +QString TicTacToePlugin::domXml() const +{ + return QLatin1String("\ +\ + \ + \ + \ + TicTacToe\ + \ + \ + \ + \ + \ +"); +} + +//! [3] + +//! [4] +Q_EXPORT_PLUGIN2(taskmenuextension, TicTacToePlugin) +//! [4] diff --git a/examples/designer/taskmenuextension/tictactoeplugin.h b/examples/designer/taskmenuextension/tictactoeplugin.h new file mode 100644 index 0000000..6bd6065 --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoeplugin.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#ifndef TICTACTOEPLUGIN_H +#define TICTACTOEPLUGIN_H + +#include + +QT_BEGIN_NAMESPACE +class QIcon; +class QWidget; +QT_END_NAMESPACE + +class TicTacToePlugin : public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + TicTacToePlugin(QObject *parent = 0); + + QString name() const; + QString group() const; + QString toolTip() const; + QString whatsThis() const; + QString includeFile() const; + QIcon icon() const; + bool isContainer() const; + QWidget *createWidget(QWidget *parent); + bool isInitialized() const; + void initialize(QDesignerFormEditorInterface *formEditor); + QString domXml() const; + +private: + bool initialized; +}; + +#endif +//! [0] diff --git a/examples/designer/taskmenuextension/tictactoetaskmenu.cpp b/examples/designer/taskmenuextension/tictactoetaskmenu.cpp new file mode 100644 index 0000000..79fe88e --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoetaskmenu.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "tictactoe.h" +#include "tictactoedialog.h" +#include "tictactoetaskmenu.h" + +//! [0] +TicTacToeTaskMenu::TicTacToeTaskMenu(TicTacToe *tic, QObject *parent) + : QObject(parent) +{ + ticTacToe = tic; + + editStateAction = new QAction(tr("Edit State..."), this); + connect(editStateAction, SIGNAL(triggered()), this, SLOT(editState())); +} +//! [0] + +//! [1] +void TicTacToeTaskMenu::editState() +{ + TicTacToeDialog dialog(ticTacToe); + dialog.exec(); +} +//! [1] + +//! [2] +QAction *TicTacToeTaskMenu::preferredEditAction() const +{ + return editStateAction; +} +//! [2] + +//! [3] +QList TicTacToeTaskMenu::taskActions() const +{ + QList list; + list.append(editStateAction); + return list; +} +//! [3] + +//! [4] +TicTacToeTaskMenuFactory::TicTacToeTaskMenuFactory(QExtensionManager *parent) + : QExtensionFactory(parent) +{ +} +//! [4] + +//! [5] +QObject *TicTacToeTaskMenuFactory::createExtension(QObject *object, + const QString &iid, + QObject *parent) const +{ + if (iid != Q_TYPEID(QDesignerTaskMenuExtension)) + return 0; + + if (TicTacToe *tic = qobject_cast(object)) + return new TicTacToeTaskMenu(tic, parent); + + return 0; +} +//! [5] diff --git a/examples/designer/taskmenuextension/tictactoetaskmenu.h b/examples/designer/taskmenuextension/tictactoetaskmenu.h new file mode 100644 index 0000000..8e203d0 --- /dev/null +++ b/examples/designer/taskmenuextension/tictactoetaskmenu.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TICTACTOETASKMENU_H +#define TICTACTOETASKMENU_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QExtensionManager; +QT_END_NAMESPACE +class TicTacToe; + +//! [0] +class TicTacToeTaskMenu : public QObject, public QDesignerTaskMenuExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerTaskMenuExtension) + +public: + TicTacToeTaskMenu(TicTacToe *tic, QObject *parent); + + QAction *preferredEditAction() const; + QList taskActions() const; + +private slots: + void editState(); + +private: + QAction *editStateAction; + TicTacToe *ticTacToe; +}; +//! [0] + +//! [1] +class TicTacToeTaskMenuFactory : public QExtensionFactory +{ + Q_OBJECT + +public: + TicTacToeTaskMenuFactory(QExtensionManager *parent = 0); + +protected: + QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const; +}; +//! [1] + +#endif diff --git a/examples/designer/worldtimeclockbuilder/form.ui b/examples/designer/worldtimeclockbuilder/form.ui new file mode 100644 index 0000000..e5be1d9 --- /dev/null +++ b/examples/designer/worldtimeclockbuilder/form.ui @@ -0,0 +1,162 @@ + + + + + WorldTimeForm + + + + 0 + 0 + 400 + 300 + + + + World Time Clock + + + + 9 + + + 6 + + + + + + + + 1 + + + 6 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 1 + + + 6 + + + + + Current time: + + + + + + + true + + + + + + + + + 1 + + + 6 + + + + + Set time zone: + + + + + + + 12 + + + -12 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + WorldTimeClock + +

worldtimeclock.h
+ 0 + + + + + + + spinBox + valueChanged(int) + worldTimeClock + setTimeZone(int) + + + 339 + 166 + + + 157 + 230 + + + + + worldTimeClock + updated(QTime) + timeEdit + setTime(QTime) + + + 141 + 59 + + + 291 + 133 + + + + + diff --git a/examples/designer/worldtimeclockbuilder/main.cpp b/examples/designer/worldtimeclockbuilder/main.cpp new file mode 100644 index 0000000..6803941 --- /dev/null +++ b/examples/designer/worldtimeclockbuilder/main.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#include +//! [0] +#include + +//! [1] +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(worldtimeclockbuilder); + + QApplication app(argc, argv); + + QUiLoader loader; +//! [1] + +//! [2] + QFile file(":/forms/form.ui"); + file.open(QFile::ReadOnly); + + QWidget *widget = loader.load(&file); + + file.close(); + widget->show(); +//! [2] + +//! [3] + return app.exec(); +} +//! [3] diff --git a/examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.pro b/examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.pro new file mode 100644 index 0000000..94fa497 --- /dev/null +++ b/examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.pro @@ -0,0 +1,13 @@ +#! [0] +CONFIG += uitools +SOURCES = main.cpp +RESOURCES = worldtimeclockbuilder.qrc +#! [0] + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/worldtimeclockbuilder +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.ui *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/worldtimeclockbuilder +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.qrc b/examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.qrc new file mode 100644 index 0000000..89d5ac3 --- /dev/null +++ b/examples/designer/worldtimeclockbuilder/worldtimeclockbuilder.qrc @@ -0,0 +1,5 @@ + + + form.ui + + diff --git a/examples/designer/worldtimeclockplugin/worldtimeclock.cpp b/examples/designer/worldtimeclockplugin/worldtimeclock.cpp new file mode 100644 index 0000000..088c6e9 --- /dev/null +++ b/examples/designer/worldtimeclockplugin/worldtimeclock.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "worldtimeclock.h" + +WorldTimeClock::WorldTimeClock(QWidget *parent) + : QWidget(parent) +{ + timeZoneOffset = 0; + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(update())); + timer->start(1000); + + setWindowTitle(tr("World Time Clock")); + resize(200, 200); +} + +void WorldTimeClock::paintEvent(QPaintEvent *) +{ + static const QPoint hourHand[3] = { + QPoint(7, 8), + QPoint(-7, 8), + QPoint(0, -40) + }; + static const QPoint minuteHand[3] = { + QPoint(7, 8), + QPoint(-7, 8), + QPoint(0, -70) + }; + + QColor hourColor(127, 0, 127); + QColor minuteColor(0, 127, 127, 191); + + int side = qMin(width(), height()); + QTime time = QTime::currentTime(); + time = time.addSecs(timeZoneOffset); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.translate(width() / 2, height() / 2); + painter.scale(side / 200.0, side / 200.0); + + painter.setPen(Qt::NoPen); + painter.setBrush(hourColor); + + painter.save(); + painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); + painter.drawConvexPolygon(hourHand, 3); + painter.restore(); + + painter.setPen(hourColor); + + for (int i = 0; i < 12; ++i) { + painter.drawLine(88, 0, 96, 0); + painter.rotate(30.0); + } + + painter.setPen(Qt::NoPen); + painter.setBrush(minuteColor); + + painter.save(); + painter.rotate(6.0 * (time.minute() + time.second() / 60.0)); + painter.drawConvexPolygon(minuteHand, 3); + painter.restore(); + + painter.setPen(minuteColor); + + for (int j = 0; j < 60; ++j) { + if ((j % 5) != 0) + painter.drawLine(92, 0, 96, 0); + painter.rotate(6.0); + } + + emit updated(time); +} + +void WorldTimeClock::setTimeZone(int hourOffset) +{ + timeZoneOffset = qMin(qMax(-12, hourOffset), 12) * 3600; + update(); +} diff --git a/examples/designer/worldtimeclockplugin/worldtimeclock.h b/examples/designer/worldtimeclockplugin/worldtimeclock.h new file mode 100644 index 0000000..dc5933c --- /dev/null +++ b/examples/designer/worldtimeclockplugin/worldtimeclock.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WORLDTIMECLOCK_H +#define WORLDTIMECLOCK_H + +#include +#include +#include + +//! [0] //! [1] +class QDESIGNER_WIDGET_EXPORT WorldTimeClock : public QWidget +{ + Q_OBJECT +//! [0] + +public: + WorldTimeClock(QWidget *parent = 0); + +public slots: + void setTimeZone(int hourOffset); + +signals: + void updated(QTime currentTime); + +protected: + void paintEvent(QPaintEvent *event); + +private: + int timeZoneOffset; +//! [2] +}; +//! [1] //! [2] + +#endif diff --git a/examples/designer/worldtimeclockplugin/worldtimeclockplugin.cpp b/examples/designer/worldtimeclockplugin/worldtimeclockplugin.cpp new file mode 100644 index 0000000..88b8d45 --- /dev/null +++ b/examples/designer/worldtimeclockplugin/worldtimeclockplugin.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "worldtimeclock.h" +#include "worldtimeclockplugin.h" + +#include + +WorldTimeClockPlugin::WorldTimeClockPlugin(QObject *parent) + : QObject(parent) +{ + initialized = false; +} + +void WorldTimeClockPlugin::initialize(QDesignerFormEditorInterface * /* core */) +{ + if (initialized) + return; + + initialized = true; +} + +bool WorldTimeClockPlugin::isInitialized() const +{ + return initialized; +} + +QWidget *WorldTimeClockPlugin::createWidget(QWidget *parent) +{ + return new WorldTimeClock(parent); +} + +QString WorldTimeClockPlugin::name() const +{ + return "WorldTimeClock"; +} + +QString WorldTimeClockPlugin::group() const +{ + return "Display Widgets [Examples]"; +} + +QIcon WorldTimeClockPlugin::icon() const +{ + return QIcon(); +} + +QString WorldTimeClockPlugin::toolTip() const +{ + return ""; +} + +QString WorldTimeClockPlugin::whatsThis() const +{ + return ""; +} + +bool WorldTimeClockPlugin::isContainer() const +{ + return false; +} + +QString WorldTimeClockPlugin::domXml() const +{ + return "\n" + " \n" + " \n" + " \n" + " 0\n" + " 0\n" + " 100\n" + " 100\n" + " \n" + " \n" + " \n" + ""; +} + +QString WorldTimeClockPlugin::includeFile() const +{ + return "worldtimeclock.h"; +} + +//! [0] +Q_EXPORT_PLUGIN2(worldtimeclockplugin, WorldTimeClockPlugin) +//! [0] diff --git a/examples/designer/worldtimeclockplugin/worldtimeclockplugin.h b/examples/designer/worldtimeclockplugin/worldtimeclockplugin.h new file mode 100644 index 0000000..91c4b52 --- /dev/null +++ b/examples/designer/worldtimeclockplugin/worldtimeclockplugin.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WORLDTIMECLOCKPLUGIN_H +#define WORLDTIMECLOCKPLUGIN_H + +#include + +//! [0] +class WorldTimeClockPlugin : public QObject, + public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) + +public: + WorldTimeClockPlugin(QObject *parent = 0); + + bool isContainer() const; + bool isInitialized() const; + QIcon icon() const; + QString domXml() const; + QString group() const; + QString includeFile() const; + QString name() const; + QString toolTip() const; + QString whatsThis() const; + QWidget *createWidget(QWidget *parent); + void initialize(QDesignerFormEditorInterface *core); + +private: + bool initialized; +}; +//! [0] + +#endif diff --git a/examples/designer/worldtimeclockplugin/worldtimeclockplugin.pro b/examples/designer/worldtimeclockplugin/worldtimeclockplugin.pro new file mode 100644 index 0000000..01340e8 --- /dev/null +++ b/examples/designer/worldtimeclockplugin/worldtimeclockplugin.pro @@ -0,0 +1,23 @@ +#! [0] +CONFIG += designer plugin +#! [0] +TARGET = $$qtLibraryTarget($$TARGET) +#! [1] +TEMPLATE = lib +#! [1] +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer + +#! [2] +HEADERS = worldtimeclock.h \ + worldtimeclockplugin.h +SOURCES = worldtimeclock.cpp \ + worldtimeclockplugin.cpp +#! [2] + +# install +target.path = $$[QT_INSTALL_PLUGINS]/designer +sources.files = $$SOURCES $$HEADERS *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/designer/worldtimeclockplugin +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/examples.pro b/examples/examples.pro new file mode 100644 index 0000000..e2f2c61 --- /dev/null +++ b/examples/examples.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS += help designer diff --git a/examples/help/README b/examples/help/README new file mode 100644 index 0000000..85f5a43 --- /dev/null +++ b/examples/help/README @@ -0,0 +1,38 @@ +Support for interactive help is provided by the Qt Assistant application. +Developers can take advantages of the facilities it offers to display +specially-prepared documentation to users of their applications. + + +The example launcher provided with Qt can be used to explore each of the +examples in this directory. + +Documentation for these examples can be found via the Tutorial and Examples +link in the main Qt documentation. + + +Finding the Qt Examples and Demos launcher +========================================== + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Qt Examples and Demos" entry in the submenu containing +the Qt tools. + +On Mac OS X: + +For the binary distribution, the qtdemo executable is installed in the +/Developer/Applications/Qt directory. For the source distribution, it is +installed alongside the other Qt tools on the path specified when Qt is +configured. + +On Unix/Linux: + +The qtdemo executable is installed alongside the other Qt tools on the path +specified when Qt is configured. + +On all platforms: + +The source code for the launcher can be found in the demos/qtdemo directory +in the Qt package. This example is built at the same time as the Qt libraries, +tools, examples, and demonstrations. diff --git a/examples/help/contextsensitivehelp/contextsensitivehelp.pro b/examples/help/contextsensitivehelp/contextsensitivehelp.pro new file mode 100644 index 0000000..ef85c84 --- /dev/null +++ b/examples/help/contextsensitivehelp/contextsensitivehelp.pro @@ -0,0 +1,20 @@ +TEMPLATE = app + +CONFIG += help + +SOURCES += main.cpp \ + wateringconfigdialog.cpp \ + helpbrowser.cpp + +HEADERS += wateringconfigdialog.h \ + helpbrowser.h + +FORMS += wateringconfigdialog.ui + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qttools/help/contextsensitivehelp +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro *.png *.doc doc +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/help/contextsensitivehelp +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/help/contextsensitivehelp/doc/amount.html b/examples/help/contextsensitivehelp/doc/amount.html new file mode 100644 index 0000000..7a02a6f --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/amount.html @@ -0,0 +1,11 @@ + + + + Water amount + + + Depending on the plant, temperature and rain fall the amount needs to be larger + or smaller. On a really hot day without rain, the suggested
amount + can be increased by about 10%. + + diff --git a/examples/help/contextsensitivehelp/doc/filter.html b/examples/help/contextsensitivehelp/doc/filter.html new file mode 100644 index 0000000..6486112 --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/filter.html @@ -0,0 +1,12 @@ + + + +Filter + + +Depending on the source of water, it needs to be filtered or not. Filtering +is strongly recommened for the river and lake. + + + + diff --git a/examples/help/contextsensitivehelp/doc/plants.html b/examples/help/contextsensitivehelp/doc/plants.html new file mode 100644 index 0000000..2d2bb67 --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/plants.html @@ -0,0 +1,44 @@ + + + + Plants + + + Different kind of plants need different amounts of water. Here's a short + overview over the most common grown plants and their avarage need of water: +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KindAmount
Squash2000
Bean1500
Carrot1200
Strawberry1300
Raspberry1000
Blueberry1100
+

+ Warning: Watering them too much or too little will + cause irreversible damage! + + diff --git a/examples/help/contextsensitivehelp/doc/rain.html b/examples/help/contextsensitivehelp/doc/rain.html new file mode 100644 index 0000000..1ffe452 --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/rain.html @@ -0,0 +1,11 @@ + + + + Rain + + + Depending on the rain fall, the automated watering system should not be + switched on at all. Also, the temperature should be + considered. + + diff --git a/examples/help/contextsensitivehelp/doc/source.html b/examples/help/contextsensitivehelp/doc/source.html new file mode 100644 index 0000000..68b2f8c --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/source.html @@ -0,0 +1,33 @@ + + + + Water Source + + + The current pipe system connects to four different sources. Be aware + that only a limited amount of water can be taken from some sources. +
+ + + + + + + + + + + + + + + + + + + + + +
SourceAmount
Fountain4000
River6000
Lake10000
Public Water Systemunlimited
+ + diff --git a/examples/help/contextsensitivehelp/doc/temperature.html b/examples/help/contextsensitivehelp/doc/temperature.html new file mode 100644 index 0000000..4145ed7 --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/temperature.html @@ -0,0 +1,13 @@ + + + + Temperature + + + Depending on the temperature, the plants need more or less water. The higher + the temperature the higher the need for water. If the temperature does not + reach a certain level, maybe no automatic watering should be done at all.
+ Before setting this parameter for good, you should also take the amount of + rain into account. + + diff --git a/examples/help/contextsensitivehelp/doc/time.html b/examples/help/contextsensitivehelp/doc/time.html new file mode 100644 index 0000000..0cc81f4 --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/time.html @@ -0,0 +1,11 @@ + + + +Starting time + + +Starting the watering too early may be ineffective since most water +will evaporate. + + + diff --git a/examples/help/contextsensitivehelp/doc/wateringmachine.qch b/examples/help/contextsensitivehelp/doc/wateringmachine.qch new file mode 100644 index 0000000000000000000000000000000000000000..35d29be2263032c1aa0bb640003771b42f8b05cb GIT binary patch literal 25600 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 literal 0 HcmV?d00001 diff --git a/examples/help/contextsensitivehelp/doc/wateringmachine.qhc b/examples/help/contextsensitivehelp/doc/wateringmachine.qhc new file mode 100644 index 0000000000000000000000000000000000000000..b5653c3ff7bbf252b7865a0ddc282746c36a0240 GIT binary patch literal 8192 zcmeI1&rcIU6vt=!w!3PA7%kZtBN>APHvJI@A<B zl#>ahA&k*WLJ&fC#aAx6FtF4h*QMt3)js?U890aFGxTQ;Gf(k%oWlp_oqtF zlQ~LNJvBqgK}MIT&*o}mZpn3CJCy?IIBm{DZ!6-Gi&zcKF!Oob?w6F}?vmPxneCx? z;v}P|ifJx!NC%g70ERg^iQ5k)wUcQ{lIb?Bhi*FJQsPmj19iM3-fYy4p`KPDEp_U+ zSfRB;s}j}%k=DG24b!r4JD0d>s{J?;!(oz6N!&1 zihv?;EeSls8d{$CK*cLSysD~Ae}@M9CGlGtFOC(*N;@I*y~sZf@M*Q~1+27Nt#{7< z5rU&@xo|aUML-d_6oH(`5jc;}{|(%9wPZ!0OF*4}^(ZI; zH7x)D4g`tWfpa@)nzylqIwV9An?ll9~^VvLp@oOLp*1#LD#_U=x zWUW@2hCGazsX=kT3F6zOwBreY-F3WbRwJJUJQ;7126USxeFrlzl?>Ury_t=IYOF}b zUDAF$Ho-969pWDmcf=}n2oMBt2w&k3d{j39SJ-&fRS~#=z&#koa$3;ugN4&6A)A9D fKAR4-L9n}xy;1=@f~jPf9)~>h7^b^jdwB6**3yT) literal 0 HcmV?d00001 diff --git a/examples/help/contextsensitivehelp/doc/wateringmachine.qhcp b/examples/help/contextsensitivehelp/doc/wateringmachine.qhcp new file mode 100644 index 0000000..eebf652 --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/wateringmachine.qhcp @@ -0,0 +1,14 @@ + + + + + + wateringmachine.qhp + wateringmachine.qch + + + + wateringmachine.qch + + + \ No newline at end of file diff --git a/examples/help/contextsensitivehelp/doc/wateringmachine.qhp b/examples/help/contextsensitivehelp/doc/wateringmachine.qhp new file mode 100644 index 0000000..6dd08e7 --- /dev/null +++ b/examples/help/contextsensitivehelp/doc/wateringmachine.qhp @@ -0,0 +1,25 @@ + + + wateringmachine + wateringcompany.com.1-0-0.premium + + + + + + + + + + + + plants.html + temperature.html + rain.html + time.html + amount.html + source.html + filter.html + + + diff --git a/examples/help/contextsensitivehelp/helpbrowser.cpp b/examples/help/contextsensitivehelp/helpbrowser.cpp new file mode 100644 index 0000000..d37a72f --- /dev/null +++ b/examples/help/contextsensitivehelp/helpbrowser.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "helpbrowser.h" + +HelpBrowser::HelpBrowser(QWidget *parent) + : QTextBrowser(parent) +{ + QString collectionFile = QLibraryInfo::location(QLibraryInfo::ExamplesPath) + + QLatin1String("/help/contextsensitivehelp/doc/wateringmachine.qhc"); + + m_helpEngine = new QHelpEngineCore(collectionFile, this); + if (!m_helpEngine->setupData()) { + delete m_helpEngine; + m_helpEngine = 0; + } +} + +void HelpBrowser::showHelpForKeyword(const QString &id) +{ + if (m_helpEngine) { + QMap links = m_helpEngine->linksForIdentifier(id); + if (links.count()) + setSource(links.constBegin().value()); + } +} + +QVariant HelpBrowser::loadResource(int type, const QUrl &name) +{ + QByteArray ba; + if (type < 4 && m_helpEngine) { + QUrl url(name); + if (name.isRelative()) + url = source().resolved(url); + ba = m_helpEngine->fileData(url); + } + return ba; +} + diff --git a/examples/help/contextsensitivehelp/helpbrowser.h b/examples/help/contextsensitivehelp/helpbrowser.h new file mode 100644 index 0000000..684ed68 --- /dev/null +++ b/examples/help/contextsensitivehelp/helpbrowser.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HELPBROWSER_H +#define HELPBROWSER_H + +#include + +QT_BEGIN_NAMESPACE +class QHelpEngineCore; +QT_END_NAMESPACE; + +class HelpBrowser : public QTextBrowser +{ + Q_OBJECT + +public: + HelpBrowser(QWidget *parent); + void showHelpForKeyword(const QString &id); + +private: + QVariant loadResource(int type, const QUrl &name); + + QHelpEngineCore *m_helpEngine; +}; + +#endif diff --git a/examples/help/contextsensitivehelp/main.cpp b/examples/help/contextsensitivehelp/main.cpp new file mode 100644 index 0000000..ca15d9f --- /dev/null +++ b/examples/help/contextsensitivehelp/main.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "wateringconfigdialog.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + WateringConfigDialog dia; + return dia.exec(); +} diff --git a/examples/help/contextsensitivehelp/wateringconfigdialog.cpp b/examples/help/contextsensitivehelp/wateringconfigdialog.cpp new file mode 100644 index 0000000..0529bfc --- /dev/null +++ b/examples/help/contextsensitivehelp/wateringconfigdialog.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "wateringconfigdialog.h" + +WateringConfigDialog::WateringConfigDialog() +{ + m_ui.setupUi(this); + m_widgetInfo.insert(m_ui.plantComboBox, tr("plants")); + m_widgetInfo.insert(m_ui.temperatureCheckBox, tr("temperature")); + m_widgetInfo.insert(m_ui.temperatureSpinBox, tr("temperature")); + m_widgetInfo.insert(m_ui.rainCheckBox, tr("rain")); + m_widgetInfo.insert(m_ui.rainSpinBox, tr("rain")); + m_widgetInfo.insert(m_ui.startTimeEdit, tr("starting time")); + m_widgetInfo.insert(m_ui.amountSpinBox, tr("water amount")); + m_widgetInfo.insert(m_ui.sourceComboBox, tr("water source")); + m_widgetInfo.insert(m_ui.filterCheckBox, tr("water filtering")); + + connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), + this, SLOT(focusChanged(QWidget*,QWidget*))); +} + +void WateringConfigDialog::focusChanged(QWidget *, QWidget *now) +{ + if (m_widgetInfo.contains(now)) { + m_ui.helpLabel->setText(tr("Information about %1:").arg(m_widgetInfo.value(now))); + QStringList lst = m_widgetInfo.value(now).split(QLatin1Char(' ')); + m_ui.helpBrowser->showHelpForKeyword(lst.last()); + } +} + diff --git a/examples/help/contextsensitivehelp/wateringconfigdialog.h b/examples/help/contextsensitivehelp/wateringconfigdialog.h new file mode 100644 index 0000000..d1fd986 --- /dev/null +++ b/examples/help/contextsensitivehelp/wateringconfigdialog.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WATERINGCONFIGDIALOG_H +#define WATERINGCONFIGDIALOG_H + +#include +#include "ui_wateringconfigdialog.h" + +class WateringConfigDialog : public QDialog +{ + Q_OBJECT +public: + WateringConfigDialog(); + +private slots: + void focusChanged(QWidget *old, QWidget *now); + +private: + Ui::WateringConfigDialog m_ui; + QMap m_widgetInfo; +}; + +#endif diff --git a/examples/help/contextsensitivehelp/wateringconfigdialog.ui b/examples/help/contextsensitivehelp/wateringconfigdialog.ui new file mode 100644 index 0000000..d7a473a --- /dev/null +++ b/examples/help/contextsensitivehelp/wateringconfigdialog.ui @@ -0,0 +1,446 @@ + + WateringConfigDialog + + + + 0 + 0 + 334 + 550 + + + + Watering Configuration + + + + + + + + Plant: + + + + + + + + 0 + 0 + + + + + Squash + + + + + Bean + + + + + Carrot + + + + + Strawberry + + + + + Raspberry + + + + + Blueberry + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 67 + 16 + + + + + + + + Water when: + + + + + + + Temperature is higher than: + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 16 + 20 + + + + + + + + false + + + + + + C + + + 10 + + + 60 + + + 20 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Rain less than: + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 16 + 20 + + + + + + + + false + + + + + + mm + + + 1 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Starting Time: + + + + + + + + + + Amount: + + + + + + + l + + + 100 + + + 10000 + + + 100 + + + 1000 + + + + + + + Source: + + + + + + + + Fountain + + + + + River + + + + + Lake + + + + + Public Water System + + + + + + + + Filter: + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + <a href="test">Show Details</a> + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + HelpBrowser + QTextBrowser +
helpbrowser.h
+
+
+ + + + buttonBox + accepted() + WateringConfigDialog + accept() + + + 227 + 372 + + + 157 + 274 + + + + + buttonBox + rejected() + WateringConfigDialog + reject() + + + 286 + 378 + + + 286 + 274 + + + + + temperatureCheckBox + toggled(bool) + temperatureSpinBox + setEnabled(bool) + + + 132 + 101 + + + 132 + 125 + + + + + rainCheckBox + toggled(bool) + rainSpinBox + setEnabled(bool) + + + 110 + 154 + + + 113 + 169 + + + + +
diff --git a/examples/help/help.pro b/examples/help/help.pro new file mode 100644 index 0000000..f03ec01 --- /dev/null +++ b/examples/help/help.pro @@ -0,0 +1,13 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS += contextsensitivehelp \ + remotecontrol \ + simpletextviewer + +# install +sources.files = README *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/help +INSTALLS += sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/help/remotecontrol/enter.png b/examples/help/remotecontrol/enter.png new file mode 100644 index 0000000000000000000000000000000000000000..f397f4b9c421c1fbdf714b7c914e28d9797a96fc GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#I-3}epz!kr59)wIvL&t&CC>S|xv6<249-QVi6yBi3gww4844j8sS56%z5(x3 zRP%re*^<27T^Rm@;DWu&Cj&+1d%8G=Se#ByP>?fVGBg&L&0r|cEXlB>QcvJKbCPNi z55vu0@?Bp~8ajw|{CDL2pnRO6OyM85sltRtABN9P8h3dnEIh(6VNvOYAL=(75)}S1 z9+`cz&{4urj!?7eIcyB%~I za~OoDO{nMDnkl;TBd>AG1jZhNCc$>a+Ljz9hIcZiYx8O!`vING;OXk;vd$@?2>=~N BWt#v1 literal 0 HcmV?d00001 diff --git a/examples/help/remotecontrol/main.cpp b/examples/help/remotecontrol/main.cpp new file mode 100644 index 0000000..ad561ce --- /dev/null +++ b/examples/help/remotecontrol/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "remotecontrol.h" + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(remotecontrol); + + QApplication a(argc, argv); + RemoteControl w; + w.show(); + a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); + return a.exec(); +} diff --git a/examples/help/remotecontrol/remotecontrol.cpp b/examples/help/remotecontrol/remotecontrol.cpp new file mode 100644 index 0000000..45d3fde --- /dev/null +++ b/examples/help/remotecontrol/remotecontrol.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "remotecontrol.h" + +RemoteControl::RemoteControl(QWidget *parent, Qt::WFlags flags) + : QMainWindow(parent, flags) +{ + ui.setupUi(this); + connect(ui.indexLineEdit, SIGNAL(returnPressed()), + this, SLOT(on_indexButton_clicked())); + connect(ui.identifierLineEdit, SIGNAL(returnPressed()), + this, SLOT(on_identifierButton_clicked())); + connect(ui.urlLineEdit, SIGNAL(returnPressed()), + this, SLOT(on_urlButton_clicked())); + + QString rc; + QTextStream(&rc) << QLatin1String("qthelp://com.trolltech.qt.") + << (QT_VERSION >> 16) << ((QT_VERSION >> 8) & 0xFF) + << (QT_VERSION & 0xFF) + << QLatin1String("/qdoc/index.html"); + + ui.startUrlLineEdit->setText(rc); + + process = new QProcess(this); + connect(process, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(helpViewerClosed())); +} + +RemoteControl::~RemoteControl() +{ + if (process->state() == QProcess::Running) { + process->terminate(); + process->waitForFinished(3000); + } +} + +void RemoteControl::on_actionQuit_triggered() +{ + close(); +} + +void RemoteControl::on_launchButton_clicked() +{ + if (process->state() == QProcess::Running) + return; + + QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator(); +#if !defined(Q_OS_MAC) + app += QLatin1String("assistant"); +#else + app += QLatin1String("Assistant.app/Contents/MacOS/Assistant"); +#endif + + ui.contentsCheckBox->setChecked(true); + ui.indexCheckBox->setChecked(true); + ui.bookmarksCheckBox->setChecked(true); + + QStringList args; + args << QLatin1String("-enableRemoteControl"); + process->start(app, args); + if (!process->waitForStarted()) { + QMessageBox::critical(this, tr("Remote Control"), + tr("Could not start Qt Assistant from %1.").arg(app)); + return; + } + + if (!ui.startUrlLineEdit->text().isEmpty()) + sendCommand(QLatin1String("SetSource ") + + ui.startUrlLineEdit->text()); + + ui.launchButton->setEnabled(false); + ui.startUrlLineEdit->setEnabled(false); + ui.actionGroupBox->setEnabled(true); +} + +void RemoteControl::sendCommand(const QString &cmd) +{ + if (process->state() != QProcess::Running) + return; + process->write(cmd.toLocal8Bit() + '\n'); +} + +void RemoteControl::on_indexButton_clicked() +{ + sendCommand(QLatin1String("ActivateKeyword ") + + ui.indexLineEdit->text()); +} + +void RemoteControl::on_identifierButton_clicked() +{ + sendCommand(QLatin1String("ActivateIdentifier ") + + ui.identifierLineEdit->text()); +} + +void RemoteControl::on_urlButton_clicked() +{ + sendCommand(QLatin1String("SetSource ") + + ui.urlLineEdit->text()); +} + +void RemoteControl::on_syncContentsButton_clicked() +{ + sendCommand(QLatin1String("SyncContents")); +} + +void RemoteControl::on_contentsCheckBox_toggled(bool checked) +{ + sendCommand(checked ? + QLatin1String("Show Contents") : QLatin1String("Hide Contents")); +} + +void RemoteControl::on_indexCheckBox_toggled(bool checked) +{ + sendCommand(checked ? + QLatin1String("Show Index") : QLatin1String("Hide Index")); +} + +void RemoteControl::on_bookmarksCheckBox_toggled(bool checked) +{ + sendCommand(checked ? + QLatin1String("Show Bookmarks") : QLatin1String("Hide Bookmarks")); +} + +void RemoteControl::helpViewerClosed() +{ + ui.launchButton->setEnabled(true); + ui.startUrlLineEdit->setEnabled(true); + ui.actionGroupBox->setEnabled(false); +} diff --git a/examples/help/remotecontrol/remotecontrol.h b/examples/help/remotecontrol/remotecontrol.h new file mode 100644 index 0000000..e440add --- /dev/null +++ b/examples/help/remotecontrol/remotecontrol.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef REMOTECONTROL_H +#define REMOTECONTROL_H + +#include +#include "ui_remotecontrol.h" + +QT_BEGIN_NAMESPACE +class QProcess; +QT_END_NAMESPACE; + +class RemoteControl : public QMainWindow +{ + Q_OBJECT + +public: + RemoteControl(QWidget *parent = 0, Qt::WFlags flags = 0); + ~RemoteControl(); + +private: + Ui::RemoteControlClass ui; + QProcess *process; + +private slots: + void on_launchButton_clicked(); + void on_actionQuit_triggered(); + void on_indexButton_clicked(); + void on_identifierButton_clicked(); + void on_urlButton_clicked(); + void on_syncContentsButton_clicked(); + void on_contentsCheckBox_toggled(bool checked); + void on_indexCheckBox_toggled(bool checked); + void on_bookmarksCheckBox_toggled(bool checked); + void helpViewerClosed(); + + void sendCommand(const QString &cmd); +}; + +#endif // REMOTECONTROL_H diff --git a/examples/help/remotecontrol/remotecontrol.pro b/examples/help/remotecontrol/remotecontrol.pro new file mode 100644 index 0000000..f080b3c --- /dev/null +++ b/examples/help/remotecontrol/remotecontrol.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +HEADERS += remotecontrol.h +SOURCES += main.cpp \ + remotecontrol.cpp +FORMS += remotecontrol.ui +RESOURCES += remotecontrol.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qttools/help/remotecontrol +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro *.png *.doc doc +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/help/remotecontrol +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) diff --git a/examples/help/remotecontrol/remotecontrol.qrc b/examples/help/remotecontrol/remotecontrol.qrc new file mode 100644 index 0000000..9b4299d --- /dev/null +++ b/examples/help/remotecontrol/remotecontrol.qrc @@ -0,0 +1,5 @@ + + + enter.png + + diff --git a/examples/help/remotecontrol/remotecontrol.ui b/examples/help/remotecontrol/remotecontrol.ui new file mode 100644 index 0000000..1cfc7f5 --- /dev/null +++ b/examples/help/remotecontrol/remotecontrol.ui @@ -0,0 +1,228 @@ + + RemoteControlClass + + + + 0 + 0 + 344 + 364 + + + + RemoteControl + + + + + + + Start URL: + + + + + + + + + + Launch Qt HelpViewer + + + + + + + Qt::Horizontal + + + + 101 + 20 + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 113 + 16 + + + + + + + + false + + + Actions + + + + + + Search in Index: + + + + + + + 0 + + + + + + + + + + + :/remotecontrol/enter.png + + + + + + + + + Identifier: + + + + + + + 0 + + + + + + + + + + + :/remotecontrol/enter.png + + + + + + + + + Show URL: + + + + + + + 0 + + + + + + + + + + + :/remotecontrol/enter.png + + + + + + + + + Sync Contents + + + + + + + Qt::Horizontal + + + + 81 + 20 + + + + + + + + Show Contents + + + + + + + Show Index + + + + + + + Show Bookmarks + + + + + + + + + + + + 0 + 0 + 344 + 21 + + + + + File + + + + + + + + + Quit + + + + + + + + + diff --git a/examples/help/simpletextviewer/assistant.cpp b/examples/help/simpletextviewer/assistant.cpp new file mode 100644 index 0000000..2223b4b --- /dev/null +++ b/examples/help/simpletextviewer/assistant.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "assistant.h" + +Assistant::Assistant() + : proc(0) +{ +} + +//! [0] +Assistant::~Assistant() +{ + if (proc && proc->state() == QProcess::Running) { + proc->terminate(); + proc->waitForFinished(3000); + } + delete proc; +} +//! [0] + +//! [1] +void Assistant::showDocumentation(const QString &page) +{ + if (!startAssistant()) + return; + + QByteArray ba("SetSource "); + ba.append("qthelp://com.trolltech.examples.simpletextviewer/doc/"); + + proc->write(ba + page.toLocal8Bit() + '\n'); +} +//! [1] + +//! [2] +bool Assistant::startAssistant() +{ + if (!proc) + proc = new QProcess(); + + if (proc->state() != QProcess::Running) { + QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator(); +#if !defined(Q_OS_MAC) + app += QLatin1String("assistant"); +#else + app += QLatin1String("Assistant.app/Contents/MacOS/Assistant"); +#endif + + QStringList args; + args << QLatin1String("-collectionFile") + << QLibraryInfo::location(QLibraryInfo::ExamplesPath) + + QLatin1String("/help/simpletextviewer/documentation/simpletextviewer.qhc") + << QLatin1String("-enableRemoteControl"); + + proc->start(app, args); + + if (!proc->waitForStarted()) { + QMessageBox::critical(0, QObject::tr("Simple Text Viewer"), + QObject::tr("Unable to launch Qt Assistant (%1)").arg(app)); + return false; + } + } + return true; +} +//! [2] diff --git a/examples/help/simpletextviewer/assistant.h b/examples/help/simpletextviewer/assistant.h new file mode 100644 index 0000000..3f508dd --- /dev/null +++ b/examples/help/simpletextviewer/assistant.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ASSISTANT_H +#define ASSISTANT_H + +#include + +QT_BEGIN_NAMESPACE +class QProcess; +QT_END_NAMESPACE + +class Assistant +{ +public: + Assistant(); + ~Assistant(); + void showDocumentation(const QString &file); + +private: + bool startAssistant(); + QProcess *proc; +}; + +#endif diff --git a/examples/help/simpletextviewer/documentation/about.txt b/examples/help/simpletextviewer/documentation/about.txt new file mode 100644 index 0000000..eeab35f --- /dev/null +++ b/examples/help/simpletextviewer/documentation/about.txt @@ -0,0 +1,9 @@ +The Simple Text Viewer enables the user to select and view existing +files. + +HTML files is displayed using rich text, while other files are +presented as plain text. The application provides a file dialog +allowing the user to search for files using wildcard matching. The +search is performed within in the specified directory, and the user is +given an option to browse the existing file system to find the +relevant directory. diff --git a/examples/help/simpletextviewer/documentation/browse.html b/examples/help/simpletextviewer/documentation/browse.html new file mode 100644 index 0000000..987abf3 --- /dev/null +++ b/examples/help/simpletextviewer/documentation/browse.html @@ -0,0 +1,34 @@ + + + + Browse + + + +

Browse

+ +

+ The file dialog let you browse the current file system to + specify the directory in which the file you want to open + resides. + Note that only the specified directory will be searched, any + subdirectories will simply be ignored. +

+ +
+
+ + + + +
+ +
+
+

+ See also: File Dialog, Wildcard Matching, + Find File +

+ + + diff --git a/examples/help/simpletextviewer/documentation/filedialog.html b/examples/help/simpletextviewer/documentation/filedialog.html new file mode 100644 index 0000000..afa65ed --- /dev/null +++ b/examples/help/simpletextviewer/documentation/filedialog.html @@ -0,0 +1,48 @@ + + + + File Dialog + + + +

File Dialog

+ +

+ In the file dialog you can name a particular file name, or + search for files using wildcard matching, i.e. specify a + file name containing wildcards. In addition you must specify + the directory in which the file you search for resides. +

+ +
+
+ + + + +
+ +
+
+

+ By default the dialog will search for all files (*) in the + current directory (the directory the application is run from). +

+ +

+ When editing the file name and directory parameters, an + overview of the matching files are displayed in the + dialog. The overview is updated whenever the parameters + change. +

+ +
+
+

+ See also: Browse, Wildcard Matching, + Find File +

+ + + + diff --git a/examples/help/simpletextviewer/documentation/findfile.html b/examples/help/simpletextviewer/documentation/findfile.html new file mode 100644 index 0000000..32e0147 --- /dev/null +++ b/examples/help/simpletextviewer/documentation/findfile.html @@ -0,0 +1,32 @@ + + + + Find File + + + +

Find File

+ +

+ To open and view a file in the Simple Text Viewer, select the + 'Open...' option in the 'File' menu. The application will then + provide you with a file dialog that you can use to search for + any existing file. +

+ +
+
+ + + + +
+ +
+
+

+ See also: Open File, File Dialog +

+ + + diff --git a/examples/help/simpletextviewer/documentation/images/browse.png b/examples/help/simpletextviewer/documentation/images/browse.png new file mode 100644 index 0000000000000000000000000000000000000000..86db6b19ebcd8907470b45853a536891ba210bb0 GIT binary patch literal 21553 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 literal 0 HcmV?d00001 diff --git a/examples/help/simpletextviewer/documentation/images/fadedfilemenu.png b/examples/help/simpletextviewer/documentation/images/fadedfilemenu.png new file mode 100644 index 0000000000000000000000000000000000000000..fde0e43f674ebce4564b3372c69c74b63f4467a8 GIT binary patch literal 9589 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 AjQ{`u literal 0 HcmV?d00001 diff --git a/examples/help/simpletextviewer/documentation/images/handbook.png b/examples/help/simpletextviewer/documentation/images/handbook.png new file mode 100644 index 0000000000000000000000000000000000000000..3bd2b928b083296cb9b85d0b5fb07106e1fd6f48 GIT binary patch literal 1060 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 literal 0 HcmV?d00001 diff --git a/examples/help/simpletextviewer/documentation/images/mainwindow.png b/examples/help/simpletextviewer/documentation/images/mainwindow.png new file mode 100644 index 0000000000000000000000000000000000000000..c28d5e9ffe12dc4a390b569097d79d352df5e769 GIT binary patch literal 12769 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 J1o#d7{{ZSp6FdL_ literal 0 HcmV?d00001 diff --git a/examples/help/simpletextviewer/documentation/images/open.png b/examples/help/simpletextviewer/documentation/images/open.png new file mode 100644 index 0000000000000000000000000000000000000000..1e5bba3c8cdd96c0beb244bf535a94cfb8b69fbf GIT binary patch literal 11697 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
~V`SRk8N!XaLrInSS=`iWM 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 + + + Manual + + + +

Simple Text Viewer

+ +

+ The Simple Text Viewer enables the user to select and view + existing files. +

+ +

+ +

+ +

+ HTML files is displayed using rich text, while + other files are presented as plain text. The application + provides a file dialog allowing the user to search for files + using wildcard matching. The search is performed within in the + specified directory, and the user is given an option to browse + the existing file system to find the relevant directory. +

+ + + + + + + diff --git a/examples/help/simpletextviewer/documentation/intro.html b/examples/help/simpletextviewer/documentation/intro.html new file mode 100644 index 0000000..2e2aa40 --- /dev/null +++ b/examples/help/simpletextviewer/documentation/intro.html @@ -0,0 +1,28 @@ + + + + Manual + + + +

Simple Text Viewer

+ +

+ The Simple Text Viewer enables the user to select and view + existing files. +

+ +

+ +

+ +

+ The application provides its own custom documentation that is + available through the Help menu in the main window's menubar + and through the Help button in the application's find file + dialog. +

+ + + + diff --git a/examples/help/simpletextviewer/documentation/openfile.html b/examples/help/simpletextviewer/documentation/openfile.html new file mode 100644 index 0000000..e172de9 --- /dev/null +++ b/examples/help/simpletextviewer/documentation/openfile.html @@ -0,0 +1,36 @@ + + + + Open File + + + +

Open File

+ +

+ Once the file you want to view appears in the dialog's + display, you can open it in two different ways. +

+ +

+ By pressing the 'Open' button the currently selected file will + be opened. By default, the first file in the list of matching + files is selected. Another way of opening a file is to simply + double click the displayed file name. +

+ +
+
+ + + + +
+ +
+
+

+ See also: Find File +

+ + diff --git a/examples/help/simpletextviewer/documentation/simpletextviewer.qch b/examples/help/simpletextviewer/documentation/simpletextviewer.qch new file mode 100644 index 0000000000000000000000000000000000000000..c40132803ef645ade5634ed17c2358170e439ac6 GIT binary patch literal 108544 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

W{Juedn5dU`97?QI}D;cMyQz*Gs< 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 + + + Simple Text Viewer + images/handbook.png + Trolltech/SimpleTextViewer + qthelp://com.trolltech.examples.simpletextviewer/doc/index.html + + About Simple Text Viewer + + + about.txt + images/icon.png + + false + false + false + + + + + simpletextviewer.qhp + simpletextviewer.qch + + + + simpletextviewer.qch + + + diff --git a/examples/help/simpletextviewer/documentation/simpletextviewer.qhp b/examples/help/simpletextviewer/documentation/simpletextviewer.qhp new file mode 100644 index 0000000..4cb83a5 --- /dev/null +++ b/examples/help/simpletextviewer/documentation/simpletextviewer.qhp @@ -0,0 +1,49 @@ + + + com.trolltech.examples.simpletextviewer + doc + + +

+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + browse.html + filedialog.html + findfile.html + index.html + intro.html + openfile.html + wildcardmatching.html + images/browse.png + images/fadedfilemenu.png + images/filedialog.png + images/handbook.png + images/mainwindow.png + images/open.png + images/wildcard.png + + + diff --git a/examples/help/simpletextviewer/documentation/wildcardmatching.html b/examples/help/simpletextviewer/documentation/wildcardmatching.html new file mode 100644 index 0000000..eb1839a --- /dev/null +++ b/examples/help/simpletextviewer/documentation/wildcardmatching.html @@ -0,0 +1,57 @@ + + + + Wildcard Matching + + + +

Wildcard Matching

+ +

+ Most command shells such as bash or cmd.exe support "file + globbing", the ability to identify a group of files by using + wildcards. + +
+
+ + + + +
+ +
+
+

+ Wildcard matching provides four features: +

+ +
    +
  • Any character represents itself apart from those + mentioned below. Thus 'c' matches the character 'c'. +
  • +
  • The '?' character matches any single character.
  • +
  • The '*' matches zero or more of any characters.
  • +
  • Sets of characters can be represented in square brackets. + Within the character class, like outside, backslash + has no special meaning. +
  • +
+ +

+ For example we could identify HTML files with + *.html. This will match zero or more characters + followed by a dot followed by 'h', 't', 'm' and 'l'. +

+ +
+
+

+ See also: Browse, File Dialog, + Find File +

+ + + + + diff --git a/examples/help/simpletextviewer/findfiledialog.cpp b/examples/help/simpletextviewer/findfiledialog.cpp new file mode 100644 index 0000000..086be96 --- /dev/null +++ b/examples/help/simpletextviewer/findfiledialog.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "findfiledialog.h" +#include "assistant.h" +#include "textedit.h" + +//! [0] +FindFileDialog::FindFileDialog(TextEdit *editor, Assistant *assistant) + : QDialog(editor) +{ + currentAssistant = assistant; + currentEditor = editor; +//! [0] + + createButtons(); + createComboBoxes(); + createFilesTree(); + createLabels(); + createLayout(); + + directoryComboBox->addItem(QDir::toNativeSeparators(QDir::currentPath())); + fileNameComboBox->addItem("*"); + findFiles(); + + setWindowTitle(tr("Find File")); +//! [1] +} +//! [1] + +void FindFileDialog::browse() +{ + QString currentDirectory = directoryComboBox->currentText(); + QString newDirectory = QFileDialog::getExistingDirectory(this, + tr("Select Directory"), currentDirectory); + if (!newDirectory.isEmpty()) { + directoryComboBox->addItem(QDir::toNativeSeparators(newDirectory)); + directoryComboBox->setCurrentIndex(directoryComboBox->count() - 1); + update(); + } +} + +//! [2] +void FindFileDialog::help() +{ + currentAssistant->showDocumentation("filedialog.html"); +} +//! [2] + +void FindFileDialog::openFile(QTreeWidgetItem *item) +{ + if (!item) { + item = foundFilesTree->currentItem(); + if (!item) + return; + } + + QString fileName = item->text(0); + QString path = directoryComboBox->currentText() + QDir::separator(); + + currentEditor->setContents(path + fileName); + close(); +} + +void FindFileDialog::update() +{ + findFiles(); + buttonBox->button(QDialogButtonBox::Open)->setEnabled( + foundFilesTree->topLevelItemCount() > 0); +} + +void FindFileDialog::findFiles() +{ + QRegExp filePattern(fileNameComboBox->currentText() + "*"); + filePattern.setPatternSyntax(QRegExp::Wildcard); + + QDir directory(directoryComboBox->currentText()); + + QStringList allFiles = directory.entryList(QDir::Files | QDir::NoSymLinks); + QStringList matchingFiles; + + foreach (QString file, allFiles) { + if (filePattern.exactMatch(file)) + matchingFiles << file; + } + showFiles(matchingFiles); +} + +void FindFileDialog::showFiles(const QStringList &files) +{ + foundFilesTree->clear(); + + for (int i = 0; i < files.count(); ++i) { + QTreeWidgetItem *item = new QTreeWidgetItem(foundFilesTree); + item->setText(0, files[i]); + } + + if (files.count() > 0) + foundFilesTree->setCurrentItem(foundFilesTree->topLevelItem(0)); +} + +void FindFileDialog::createButtons() +{ + browseButton = new QToolButton; + browseButton->setText(tr("...")); + connect(browseButton, SIGNAL(clicked()), this, SLOT(browse())); + + buttonBox = new QDialogButtonBox(QDialogButtonBox::Open + | QDialogButtonBox::Cancel + | QDialogButtonBox::Help); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(openFile())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(help())); +} + +void FindFileDialog::createComboBoxes() +{ + directoryComboBox = new QComboBox; + fileNameComboBox = new QComboBox; + + fileNameComboBox->setEditable(true); + fileNameComboBox->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Preferred); + + directoryComboBox->setMinimumContentsLength(30); + directoryComboBox->setSizeAdjustPolicy( + QComboBox::AdjustToMinimumContentsLength); + directoryComboBox->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Preferred); + + connect(fileNameComboBox, SIGNAL(editTextChanged(QString)), + this, SLOT(update())); + connect(directoryComboBox, SIGNAL(currentIndexChanged(QString)), + this, SLOT(update())); +} + +void FindFileDialog::createFilesTree() +{ + foundFilesTree = new QTreeWidget; + foundFilesTree->setColumnCount(1); + foundFilesTree->setHeaderLabels(QStringList(tr("Matching Files"))); + foundFilesTree->setRootIsDecorated(false); + foundFilesTree->setSelectionMode(QAbstractItemView::SingleSelection); + + connect(foundFilesTree, SIGNAL(itemActivated(QTreeWidgetItem*,int)), + this, SLOT(openFile(QTreeWidgetItem*))); +} + +void FindFileDialog::createLabels() +{ + directoryLabel = new QLabel(tr("Search in:")); + fileNameLabel = new QLabel(tr("File name (including wildcards):")); +} + +void FindFileDialog::createLayout() +{ + QHBoxLayout *fileLayout = new QHBoxLayout; + fileLayout->addWidget(fileNameLabel); + fileLayout->addWidget(fileNameComboBox); + + QHBoxLayout *directoryLayout = new QHBoxLayout; + directoryLayout->addWidget(directoryLabel); + directoryLayout->addWidget(directoryComboBox); + directoryLayout->addWidget(browseButton); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(fileLayout); + mainLayout->addLayout(directoryLayout); + mainLayout->addWidget(foundFilesTree); + mainLayout->addStretch(); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); +} diff --git a/examples/help/simpletextviewer/findfiledialog.h b/examples/help/simpletextviewer/findfiledialog.h new file mode 100644 index 0000000..71abd4a --- /dev/null +++ b/examples/help/simpletextviewer/findfiledialog.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FINDFILEDIALOG_H +#define FINDFILEDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +class QComboBox; +class QDialogButtonBox; +class QLabel; +class QToolButton; +class QTreeWidget; +class QTreeWidgetItem; +QT_END_NAMESPACE + +class Assistant; +class TextEdit; + +//! [0] +class FindFileDialog : public QDialog +{ + Q_OBJECT + +public: + FindFileDialog(TextEdit *editor, Assistant *assistant); + +private slots: + void browse(); + void help(); + void openFile(QTreeWidgetItem *item = 0); + void update(); + +private: + void findFiles(); + void showFiles(const QStringList &files); + + void createButtons(); + void createComboBoxes(); + void createFilesTree(); + void createLabels(); + void createLayout(); + + Assistant *currentAssistant; + TextEdit *currentEditor; + QTreeWidget *foundFilesTree; + + QComboBox *directoryComboBox; + QComboBox *fileNameComboBox; + + QLabel *directoryLabel; + QLabel *fileNameLabel; + + QDialogButtonBox *buttonBox; + + QToolButton *browseButton; +}; +//! [0] + +#endif diff --git a/examples/help/simpletextviewer/main.cpp b/examples/help/simpletextviewer/main.cpp new file mode 100644 index 0000000..4c8aab9 --- /dev/null +++ b/examples/help/simpletextviewer/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWindow window; + window.show(); + return app.exec(); +} diff --git a/examples/help/simpletextviewer/mainwindow.cpp b/examples/help/simpletextviewer/mainwindow.cpp new file mode 100644 index 0000000..61fbdf3 --- /dev/null +++ b/examples/help/simpletextviewer/mainwindow.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "findfiledialog.h" +#include "assistant.h" +#include "textedit.h" + +// ![0] +MainWindow::MainWindow() +{ + assistant = new Assistant; +// ![0] + textViewer = new TextEdit; + textViewer->setContents(QLibraryInfo::location(QLibraryInfo::ExamplesPath) + + QLatin1String("/help/simpletextviewer/documentation/intro.html")); + setCentralWidget(textViewer); + + createActions(); + createMenus(); + + setWindowTitle(tr("Simple Text Viewer")); + resize(750, 400); +// ![1] +} +//! [1] + +//! [2] +void MainWindow::closeEvent(QCloseEvent *) +{ + delete assistant; +} +//! [2] + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Simple Text Viewer"), + tr("This example demonstrates how to use\n" + "Qt Assistant as help system for your\n" + "own application.")); +} + +//! [3] +void MainWindow::showDocumentation() +{ + assistant->showDocumentation("index.html"); +} +//! [3] + +void MainWindow::open() +{ + FindFileDialog dialog(textViewer, assistant); + dialog.exec(); +} + +//! [4] +void MainWindow::createActions() +{ + assistantAct = new QAction(tr("Help Contents"), this); + assistantAct->setShortcut(QKeySequence::HelpContents); + connect(assistantAct, SIGNAL(triggered()), this, SLOT(showDocumentation())); +//! [4] + + openAct = new QAction(tr("&Open..."), this); + openAct->setShortcut(QKeySequence::Open); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); + + clearAct = new QAction(tr("&Clear"), this); + clearAct->setShortcut(tr("Ctrl+C")); + connect(clearAct, SIGNAL(triggered()), textViewer, SLOT(clear())); + + exitAct = new QAction(tr("E&xit"), this); + exitAct->setShortcuts(QKeySequence::Quit); + connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); + + aboutAct = new QAction(tr("&About"), this); + connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + + aboutQtAct = new QAction(tr("About &Qt"), this); + connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); +//! [5] +} +//! [5] + +void MainWindow::createMenus() +{ + fileMenu = new QMenu(tr("&File"), this); + fileMenu->addAction(openAct); + fileMenu->addAction(clearAct); + fileMenu->addSeparator(); + fileMenu->addAction(exitAct); + + helpMenu = new QMenu(tr("&Help"), this); + helpMenu->addAction(assistantAct); + helpMenu->addSeparator(); + helpMenu->addAction(aboutAct); + helpMenu->addAction(aboutQtAct); + + + menuBar()->addMenu(fileMenu); + menuBar()->addMenu(helpMenu); +} diff --git a/examples/help/simpletextviewer/mainwindow.h b/examples/help/simpletextviewer/mainwindow.h new file mode 100644 index 0000000..4fab382 --- /dev/null +++ b/examples/help/simpletextviewer/mainwindow.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +class Assistant; +class TextEdit; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + void showDocumentation(const QString &file); + +private slots: + void about(); + void showDocumentation(); + void open(); + +protected: + void closeEvent(QCloseEvent *event); + +private: + void createActions(); + void createMenus(); + + Assistant *assistant; + TextEdit *textViewer; + + QMenu *fileMenu; + QMenu *helpMenu; + + QAction *assistantAct; + QAction *clearAct; + QAction *openAct; + QAction *exitAct; + QAction *aboutAct; + QAction *aboutQtAct; +}; + +#endif diff --git a/examples/help/simpletextviewer/simpletextviewer.pro b/examples/help/simpletextviewer/simpletextviewer.pro new file mode 100644 index 0000000..46bda4c --- /dev/null +++ b/examples/help/simpletextviewer/simpletextviewer.pro @@ -0,0 +1,18 @@ +HEADERS = mainwindow.h \ + findfiledialog.h \ + assistant.h \ + textedit.h +SOURCES = main.cpp \ + mainwindow.cpp \ + findfiledialog.cpp \ + assistant.cpp \ + textedit.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qttools/help/simpletextviewer +sources.files = $$SOURCES $$HEADERS $$RESOURCES documentation *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qttools/help/simpletextviewer +INSTALLS += target sources + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) + diff --git a/examples/help/simpletextviewer/textedit.cpp b/examples/help/simpletextviewer/textedit.cpp new file mode 100644 index 0000000..52d85b3 --- /dev/null +++ b/examples/help/simpletextviewer/textedit.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "textedit.h" + +TextEdit::TextEdit(QWidget *parent) + : QTextEdit(parent) +{ + setReadOnly(true); +} + +void TextEdit::setContents(const QString &fileName) +{ + QFileInfo fi(fileName); + srcUrl = QUrl::fromLocalFile(fi.absoluteFilePath()); + QFile file(fileName); + if (file.open(QIODevice::ReadOnly)) { + QString data(file.readAll()); + if (fileName.endsWith(".html")) + setHtml(data); + else + setPlainText(data); + } +} + +QVariant TextEdit::loadResource(int type, const QUrl &name) +{ + if (type == QTextDocument::ImageResource) { + QFile file(srcUrl.resolved(name).toLocalFile()); + if (file.open(QIODevice::ReadOnly)) + return file.readAll(); + } + return QTextEdit::loadResource(type, name); +} diff --git a/examples/help/simpletextviewer/textedit.h b/examples/help/simpletextviewer/textedit.h new file mode 100644 index 0000000..b9ecabd --- /dev/null +++ b/examples/help/simpletextviewer/textedit.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TEXTEDIT_H +#define TEXTEDIT_H + +#include +#include + +class TextEdit : public QTextEdit +{ + Q_OBJECT + +public: + TextEdit(QWidget *parent = 0); + void setContents(const QString &fileName); + +private: + QVariant loadResource(int type, const QUrl &name); + QUrl srcUrl; +}; + +#endif diff --git a/qttools.pro b/qttools.pro new file mode 100644 index 0000000..871d8cc --- /dev/null +++ b/qttools.pro @@ -0,0 +1,12 @@ +TEMPLATE = subdirs + +module_qttools_src.subdir = src +module_qttools_src.target = module-qttools-src + +module_qttools_tests.subdir = tests +module_qttools_tests.target = module-qttools-tests +module_qttools_tests.depends = module_qttools_src +module_qttools_tests.CONFIG = no_default_target no_default_install + +SUBDIRS += module_qttools_src \ + module_qttools_tests \ diff --git a/src/assistant/assistant.pro b/src/assistant/assistant.pro new file mode 100644 index 0000000..97196b2 --- /dev/null +++ b/src/assistant/assistant.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS += lib/fulltextsearch \ + lib \ + tools diff --git a/src/assistant/lib/fulltextsearch/fulltextsearch.pri b/src/assistant/lib/fulltextsearch/fulltextsearch.pri new file mode 100644 index 0000000..134678f --- /dev/null +++ b/src/assistant/lib/fulltextsearch/fulltextsearch.pri @@ -0,0 +1,161 @@ +DEFINES += _BUILD_FOR_QT_ LUCENE_DISABLE_MEMTRACKING +win32:DEFINES += _CRT_SECURE_NO_DEPRECATE _MT + +CLUCENEDIR = ../../../../src/3rdparty/clucene/src/CLucene + +INCLUDEPATH += . .. \ + $$CLUCENEDIR \ + $$CLUCENEDIR/../ \ + $$CLUCENEDIR/analysis \ + $$CLUCENEDIR/analysis/standard \ + $$CLUCENEDIR/config \ + $$CLUCENEDIR/debug \ + $$CLUCENEDIR/document \ + $$CLUCENEDIR/index \ + $$CLUCENEDIR/queryParser \ + $$CLUCENEDIR/search \ + $$CLUCENEDIR/store \ + $$CLUCENEDIR/util + + +SOURCES += $$CLUCENEDIR/StdHeader.cpp \ + $$CLUCENEDIR/analysis/AnalysisHeader.cpp \ + $$CLUCENEDIR/analysis/Analyzers.cpp \ + $$CLUCENEDIR/config/gunichartables.cpp \ + $$CLUCENEDIR/config/repl_lltot.cpp \ + $$CLUCENEDIR/config/repl_tcscasecmp.cpp \ + $$CLUCENEDIR/config/repl_tcslwr.cpp \ + $$CLUCENEDIR/config/repl_tcstod.cpp \ + $$CLUCENEDIR/config/repl_tcstoll.cpp \ + $$CLUCENEDIR/config/repl_tprintf.cpp \ + $$CLUCENEDIR/config/threads.cpp \ + $$CLUCENEDIR/config/utf8.cpp \ + $$CLUCENEDIR/debug/condition.cpp \ + $$CLUCENEDIR/debug/error.cpp \ + $$CLUCENEDIR/debug/memtracking.cpp \ + $$CLUCENEDIR/document/DateField.cpp \ + $$CLUCENEDIR/document/Document.cpp \ + $$CLUCENEDIR/document/Field.cpp \ + $$CLUCENEDIR/index/CompoundFile.cpp \ + $$CLUCENEDIR/index/DocumentWriter.cpp \ + $$CLUCENEDIR/index/FieldInfos.cpp \ + $$CLUCENEDIR/index/FieldsReader.cpp \ + $$CLUCENEDIR/index/FieldsWriter.cpp \ + $$CLUCENEDIR/index/IndexModifier.cpp \ + $$CLUCENEDIR/index/IndexReader.cpp \ + $$CLUCENEDIR/index/IndexWriter.cpp \ + $$CLUCENEDIR/index/MultiReader.cpp \ + $$CLUCENEDIR/index/SegmentInfos.cpp \ + $$CLUCENEDIR/index/SegmentMergeInfo.cpp \ + $$CLUCENEDIR/index/SegmentMergeQueue.cpp \ + $$CLUCENEDIR/index/SegmentMerger.cpp \ + $$CLUCENEDIR/index/SegmentReader.cpp \ + $$CLUCENEDIR/index/SegmentTermDocs.cpp \ + $$CLUCENEDIR/index/SegmentTermEnum.cpp \ + $$CLUCENEDIR/index/SegmentTermPositions.cpp \ + $$CLUCENEDIR/index/SegmentTermVector.cpp \ + $$CLUCENEDIR/index/Term.cpp \ + $$CLUCENEDIR/index/TermInfo.cpp \ + $$CLUCENEDIR/index/TermInfosReader.cpp \ + $$CLUCENEDIR/index/TermInfosWriter.cpp \ + $$CLUCENEDIR/index/TermVectorReader.cpp \ + $$CLUCENEDIR/index/TermVectorWriter.cpp \ + $$CLUCENEDIR/queryParser/Lexer.cpp \ + $$CLUCENEDIR/queryParser/MultiFieldQueryParser.cpp \ + $$CLUCENEDIR/queryParser/QueryParser.cpp \ + $$CLUCENEDIR/queryParser/QueryParserBase.cpp \ + $$CLUCENEDIR/queryParser/QueryToken.cpp \ + $$CLUCENEDIR/queryParser/TokenList.cpp \ + $$CLUCENEDIR/search/BooleanQuery.cpp \ + $$CLUCENEDIR/search/BooleanScorer.cpp \ + $$CLUCENEDIR/search/CachingWrapperFilter.cpp \ + $$CLUCENEDIR/search/ChainedFilter.cpp \ + $$CLUCENEDIR/search/ConjunctionScorer.cpp \ + $$CLUCENEDIR/search/DateFilter.cpp \ + $$CLUCENEDIR/search/ExactPhraseScorer.cpp \ + $$CLUCENEDIR/search/Explanation.cpp \ + $$CLUCENEDIR/search/FieldCache.cpp \ + $$CLUCENEDIR/search/FieldCacheImpl.cpp \ + $$CLUCENEDIR/search/FieldDocSortedHitQueue.cpp \ + $$CLUCENEDIR/search/FieldSortedHitQueue.cpp \ + $$CLUCENEDIR/search/FilteredTermEnum.cpp \ + $$CLUCENEDIR/search/FuzzyQuery.cpp \ + $$CLUCENEDIR/search/HitQueue.cpp \ + $$CLUCENEDIR/search/Hits.cpp \ + $$CLUCENEDIR/search/IndexSearcher.cpp \ + $$CLUCENEDIR/search/MultiSearcher.cpp \ + $$CLUCENEDIR/search/MultiTermQuery.cpp \ + $$CLUCENEDIR/search/PhrasePositions.cpp \ + $$CLUCENEDIR/search/PhraseQuery.cpp \ + $$CLUCENEDIR/search/PhraseScorer.cpp \ + $$CLUCENEDIR/search/PrefixQuery.cpp \ + $$CLUCENEDIR/search/QueryFilter.cpp \ + $$CLUCENEDIR/search/RangeFilter.cpp \ + $$CLUCENEDIR/search/RangeQuery.cpp \ + $$CLUCENEDIR/search/SearchHeader.cpp \ + $$CLUCENEDIR/search/Similarity.cpp \ + $$CLUCENEDIR/search/SloppyPhraseScorer.cpp \ + $$CLUCENEDIR/search/Sort.cpp \ + $$CLUCENEDIR/search/TermQuery.cpp \ + $$CLUCENEDIR/search/TermScorer.cpp \ + $$CLUCENEDIR/search/WildcardQuery.cpp \ + $$CLUCENEDIR/search/WildcardTermEnum.cpp \ + $$CLUCENEDIR/store/FSDirectory.cpp \ + $$CLUCENEDIR/store/IndexInput.cpp \ + $$CLUCENEDIR/store/IndexOutput.cpp \ + $$CLUCENEDIR/store/Lock.cpp \ + $$CLUCENEDIR/store/MMapInput.cpp \ + $$CLUCENEDIR/store/RAMDirectory.cpp \ + $$CLUCENEDIR/store/TransactionalRAMDirectory.cpp \ + $$CLUCENEDIR/util/BitSet.cpp \ + $$CLUCENEDIR/util/Equators.cpp \ + $$CLUCENEDIR/util/FastCharStream.cpp \ + $$CLUCENEDIR/util/fileinputstream.cpp \ + $$CLUCENEDIR/util/Misc.cpp \ + $$CLUCENEDIR/util/Reader.cpp \ + $$CLUCENEDIR/util/StringBuffer.cpp \ + $$CLUCENEDIR/util/StringIntern.cpp \ + $$CLUCENEDIR/util/ThreadLocal.cpp \ + $$CLUCENEDIR/analysis/standard/StandardAnalyzer.cpp \ + $$CLUCENEDIR/analysis/standard/StandardFilter.cpp \ + $$CLUCENEDIR/analysis/standard/StandardTokenizer.cpp + + +#Header files +HEADERS += qclucene_global_p.h \ + qclucene-config_p.h \ + qanalyzer_p.h \ + qtokenizer_p.h \ + qtoken_p.h \ + qtokenstream_p.h \ + qdocument_p.h \ + qfield_p.h \ + qindexreader_p.h \ + qindexwriter_p.h \ + qterm_p.h \ + qqueryparser_p.h \ + qfilter_p.h \ + qhits_p.h \ + qsearchable_p.h \ + qsort_p.h \ + qquery_p.h \ + qreader_p.h + + +#Source files +SOURCES += qanalyzer.cpp \ + qtokenizer.cpp \ + qtoken.cpp \ + qtokenstream.cpp \ + qdocument.cpp \ + qfield.cpp \ + qindexreader.cpp \ + qindexwriter.cpp \ + qterm.cpp \ + qqueryparser.cpp \ + qfilter.cpp \ + qhits.cpp \ + qsearchable.cpp \ + qsort.cpp \ + qquery.cpp \ + qreader.cpp diff --git a/src/assistant/lib/fulltextsearch/fulltextsearch.pro b/src/assistant/lib/fulltextsearch/fulltextsearch.pro new file mode 100644 index 0000000..d0e7a87 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/fulltextsearch.pro @@ -0,0 +1,50 @@ + +QMAKE_TARGET_PRODUCT = QtCLucene +QMAKE_TARGET_DESCRIPTION = QtCLucene full text search library wrapper. +#if qt is built with frameworks in debug, we must build QtCLucene in debug and release +#that's a similar logic as in qbase.pri +mac:!static:contains(QT_CONFIG, qt_framework) { + CONFIG(debug, debug|release) { + !build_pass:CONFIG += build_all + } +} +QT_CONFIG -= qt_framework +QT -= gui +TEMPLATE = lib +TARGET = QtCLucene +DEFINES += QHELP_LIB +include(../../../../src/qbase.pri) +include(fulltextsearch.pri) + +CONFIG += qt warn_off +contains(QT_CONFIG, reduce_exports) { + CONFIG += hide_symbols + # workaround for compiler errors on Ubuntu + linux*-g++*:DEFINES += _GLIBCXX_EXTERN_TEMPLATE=0 +} + +unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES = QtCore + +# impossible to disable exceptions in clucene atm +CONFIG(exceptions_off) { + CONFIG -= exceptions_off + CONFIG += exceptions + !win32|win32-g++* { + QMAKE_CFLAGS -= -fno-exceptions + QMAKE_CXXFLAGS -= -fno-exceptions + QMAKE_LFLAGS -= -fno-exceptions + QMAKE_CFLAGS += -fexceptions + QMAKE_CXXFLAGS += -fexceptions + QMAKE_LFLAGS += -fexceptions + } +} + +win32-msvc.net | win32-msvc2* { + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE -= -O2 +} + +# the following define could be set globally in case we need it elsewhere +solaris* { + DEFINES += Q_SOLARIS_VERSION=$$system(uname -r | sed -e 's/5\\.//') +} diff --git a/src/assistant/lib/fulltextsearch/license.txt b/src/assistant/lib/fulltextsearch/license.txt new file mode 100644 index 0000000..9ef3d70 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/license.txt @@ -0,0 +1,503 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + diff --git a/src/assistant/lib/fulltextsearch/qanalyzer.cpp b/src/assistant/lib/fulltextsearch/qanalyzer.cpp new file mode 100644 index 0000000..71dd2c9 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qanalyzer.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qanalyzer_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneAnalyzerPrivate::QCLuceneAnalyzerPrivate() + : QSharedData() +{ + analyzer = 0; + deleteCLuceneAnalyzer = true; +} + +QCLuceneAnalyzerPrivate::QCLuceneAnalyzerPrivate(const QCLuceneAnalyzerPrivate &other) + : QSharedData() +{ + analyzer = _CL_POINTER(other.analyzer); + deleteCLuceneAnalyzer = other.deleteCLuceneAnalyzer; +} + +QCLuceneAnalyzerPrivate::~QCLuceneAnalyzerPrivate() +{ + if (deleteCLuceneAnalyzer) + _CLDECDELETE(analyzer); +} + + +QCLuceneAnalyzer::QCLuceneAnalyzer() + : d(new QCLuceneAnalyzerPrivate()) +{ + //nothing todo, private +} + +QCLuceneAnalyzer::~QCLuceneAnalyzer() +{ + // nothing todo +} + +qint32 QCLuceneAnalyzer::positionIncrementGap(const QString &fieldName) const +{ + Q_UNUSED(fieldName); + return 0; +} + +QCLuceneTokenStream QCLuceneAnalyzer::tokenStream(const QString &fieldName, + const QCLuceneReader &reader) const +{ + TCHAR *fName = QStringToTChar(fieldName); + QCLuceneTokenStream tokenStream; + tokenStream.d->tokenStream = d->analyzer->tokenStream(fName, reader.d->reader); + delete [] fName; + + return tokenStream; +} + + +QCLuceneStandardAnalyzer::QCLuceneStandardAnalyzer() + : QCLuceneAnalyzer() +{ + d->analyzer = new lucene::analysis::standard::StandardAnalyzer(); +} + +QCLuceneStandardAnalyzer::~QCLuceneStandardAnalyzer() +{ + // nothing todo +} + +QCLuceneStandardAnalyzer::QCLuceneStandardAnalyzer(const QStringList &stopWords) +{ + const TCHAR **tArray = new const TCHAR*[stopWords.count() +1]; + + for(int i = 0; i < stopWords.count(); ++i) { + TCHAR *stopWord = QStringToTChar(stopWords.at(i)); + tArray[i] = STRDUP_TtoT(stopWord); + delete [] stopWord; + } + tArray[stopWords.count()] = 0; + + d->analyzer = new lucene::analysis::standard::StandardAnalyzer(tArray); + + for (int i = 0; i < stopWords.count(); ++i) + delete [] tArray[i]; + + delete [] tArray; +} + + +QCLuceneWhitespaceAnalyzer::QCLuceneWhitespaceAnalyzer() + : QCLuceneAnalyzer() +{ + d->analyzer = new lucene::analysis::WhitespaceAnalyzer(); +} + +QCLuceneWhitespaceAnalyzer::~QCLuceneWhitespaceAnalyzer() +{ + // nothing todo +} + + +QCLuceneSimpleAnalyzer::QCLuceneSimpleAnalyzer() + : QCLuceneAnalyzer() +{ + d->analyzer = new lucene::analysis::SimpleAnalyzer(); +} + +QCLuceneSimpleAnalyzer::~QCLuceneSimpleAnalyzer() +{ + // nothing todo +} + + +QCLuceneStopAnalyzer::QCLuceneStopAnalyzer() + : QCLuceneAnalyzer() +{ + d->analyzer = new lucene::analysis::StopAnalyzer(); +} + +QCLuceneStopAnalyzer::~QCLuceneStopAnalyzer() +{ + // nothing todo +} + +QCLuceneStopAnalyzer::QCLuceneStopAnalyzer(const QStringList &stopWords) + : QCLuceneAnalyzer() +{ + const TCHAR **tArray = new const TCHAR*[stopWords.count() +1]; + + for(int i = 0; i < stopWords.count(); ++i) { + TCHAR *stopWord = QStringToTChar(stopWords.at(i)); + tArray[i] = STRDUP_TtoT(stopWord); + delete [] stopWord; + } + tArray[stopWords.count()] = 0; + + d->analyzer = new lucene::analysis::StopAnalyzer(tArray); + + for (int i = 0; i < stopWords.count(); ++i) + delete [] tArray[i]; + + delete [] tArray; +} + +QStringList QCLuceneStopAnalyzer::englishStopWords() const +{ + QStringList stopWordList; + + const TCHAR** stopWords = lucene::analysis::StopAnalyzer::ENGLISH_STOP_WORDS; + for (qint32 i = 0; stopWords[i] != 0; ++i) + stopWordList.append(TCharToQString(stopWords[i])); + + return stopWordList; +} + + +QCLuceneKeywordAnalyzer::QCLuceneKeywordAnalyzer() + : QCLuceneAnalyzer() +{ + d->analyzer = new lucene::analysis::KeywordAnalyzer(); +} + +QCLuceneKeywordAnalyzer::~QCLuceneKeywordAnalyzer() +{ + // nothing todo +} + + +QCLucenePerFieldAnalyzerWrapper::QCLucenePerFieldAnalyzerWrapper( + QCLuceneAnalyzer *defaultAnalyzer) + : QCLuceneAnalyzer() +{ + d->analyzer = new + lucene::analysis::PerFieldAnalyzerWrapper(defaultAnalyzer->d->analyzer); + + analyzers.append(defaultAnalyzer); + defaultAnalyzer->d->deleteCLuceneAnalyzer = false; +} + +QCLucenePerFieldAnalyzerWrapper::~QCLucenePerFieldAnalyzerWrapper() +{ + qDeleteAll(analyzers); +} + +void QCLucenePerFieldAnalyzerWrapper::addAnalyzer(const QString &fieldName, + QCLuceneAnalyzer *analyzer) +{ + lucene::analysis::PerFieldAnalyzerWrapper *analyzerWrapper = + static_cast (d->analyzer); + + if (analyzerWrapper == 0) + return; + + analyzers.append(analyzer); + analyzer->d->deleteCLuceneAnalyzer = false; + + TCHAR *fName = QStringToTChar(fieldName); + analyzerWrapper->addAnalyzer(fName, analyzer->d->analyzer); + delete [] fName; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qanalyzer_p.h b/src/assistant/lib/fulltextsearch/qanalyzer_p.h new file mode 100644 index 0000000..162d679 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qanalyzer_p.h @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QANALYZER_P_H +#define QANALYZER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qreader_p.h" +#include "qtokenstream_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include +#include +#include + +CL_NS_DEF(analysis) + class Analyzer; +CL_NS_END +CL_NS_USE(analysis) + +QT_BEGIN_NAMESPACE + +class QCLuceneIndexWriter; +class QCLuceneQueryParser; +class QCLuceneStopAnalyzer; +class QCLuceneSimpleAnalyzer; +class QCLuceneKeywordAnalyzer; +class QCLuceneStandardAnalyzer; +class QCLuceneWhitespaceAnalyzer; +class QCLucenePerFieldAnalyzerWrapper; + +class QHELP_EXPORT QCLuceneAnalyzerPrivate : public QSharedData +{ +public: + QCLuceneAnalyzerPrivate(); + QCLuceneAnalyzerPrivate(const QCLuceneAnalyzerPrivate &other); + + ~QCLuceneAnalyzerPrivate(); + + Analyzer *analyzer; + bool deleteCLuceneAnalyzer; + +private: + QCLuceneAnalyzerPrivate &operator=(const QCLuceneAnalyzerPrivate &other); +}; + +class QHELP_EXPORT QCLuceneAnalyzer +{ +public: + virtual ~QCLuceneAnalyzer(); + + qint32 positionIncrementGap(const QString &fieldName) const; + QCLuceneTokenStream tokenStream(const QString &fieldName, + const QCLuceneReader &reader) const; + +protected: + friend class QCLuceneIndexWriter; + friend class QCLuceneQueryParser; + friend class QCLuceneStopAnalyzer; + friend class QCLuceneSimpleAnalyzer; + friend class QCLuceneKeywordAnalyzer; + friend class QCLuceneStandardAnalyzer; + friend class QCLuceneWhitespaceAnalyzer; + friend class QCLucenePerFieldAnalyzerWrapper; + QSharedDataPointer d; + +private: + QCLuceneAnalyzer(); +}; + +class QHELP_EXPORT QCLuceneStandardAnalyzer : public QCLuceneAnalyzer +{ +public: + QCLuceneStandardAnalyzer(); + QCLuceneStandardAnalyzer(const QStringList &stopWords); + + ~QCLuceneStandardAnalyzer(); +}; + +class QHELP_EXPORT QCLuceneWhitespaceAnalyzer : public QCLuceneAnalyzer +{ +public: + QCLuceneWhitespaceAnalyzer(); + ~QCLuceneWhitespaceAnalyzer(); +}; + +class QHELP_EXPORT QCLuceneSimpleAnalyzer : public QCLuceneAnalyzer +{ +public: + QCLuceneSimpleAnalyzer(); + ~QCLuceneSimpleAnalyzer(); +}; + +class QHELP_EXPORT QCLuceneStopAnalyzer : public QCLuceneAnalyzer +{ +public: + QCLuceneStopAnalyzer(); + QCLuceneStopAnalyzer(const QStringList &stopWords); + + ~QCLuceneStopAnalyzer(); + + QStringList englishStopWords() const; +}; + +class QHELP_EXPORT QCLuceneKeywordAnalyzer : public QCLuceneAnalyzer +{ +public: + QCLuceneKeywordAnalyzer(); + ~QCLuceneKeywordAnalyzer(); +}; + +class QHELP_EXPORT QCLucenePerFieldAnalyzerWrapper : public QCLuceneAnalyzer +{ +public: + QCLucenePerFieldAnalyzerWrapper(QCLuceneAnalyzer *defaultAnalyzer); + ~QCLucenePerFieldAnalyzerWrapper(); + + void addAnalyzer(const QString &fieldName, QCLuceneAnalyzer *analyzer); + +private: + QList analyzers; +}; + +QT_END_NAMESPACE + +#endif // QANALYZER_P_H diff --git a/src/assistant/lib/fulltextsearch/qclucene-config_p.h b/src/assistant/lib/fulltextsearch/qclucene-config_p.h new file mode 100644 index 0000000..476296c --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qclucene-config_p.h @@ -0,0 +1,557 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QCLUCENE_CONFIG_P_H +#define QCLUCENE_CONFIG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include + +#ifndef _SRC_CLUCENE_CLUCENE_CONFIG_H +#define _SRC_CLUCENE_CLUCENE_CONFIG_H 1 + +/* +src/CLucene/clucene-config.h. +Generated +automatically +at +end +of +configure. +*/ +/* config.h.tmp. Generated by configure. */ +/* config.h.tmp.in. Generated from configure.ac by autoheader. */ + +/* Disable multithreading */ +/* #undef _CL_DISABLE_MULTITHREADING */ + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_ALGORITHM +#define _CL_HAVE_ALGORITHM 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_CTYPE_H +#define _CL_HAVE_CTYPE_H 1 +#endif + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#ifndef _CL_HAVE_DIRENT_H +#define _CL_HAVE_DIRENT_H 1 +#endif + +#if !defined (__MINGW32__) + /* Define to 1 if you have the header file. */ +# ifndef _CL_HAVE_DLFCN_H +# define _CL_HAVE_DLFCN_H 1 +# endif +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_ERRNO_H +#define _CL_HAVE_ERRNO_H 1 +#endif + +#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) + /* Define to 1 if you have the header file. */ +# ifndef _CL_HAVE_EXT_HASH_MAP +# define _CL_HAVE_EXT_HASH_MAP 1 +# endif + + /* Define to 1 if you have the header file. */ +# ifndef _CL_HAVE_EXT_HASH_SET +# define _CL_HAVE_EXT_HASH_SET 1 +# endif +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_FCNTL_H +#define _CL_HAVE_FCNTL_H 1 +#endif + +#if !defined(__xlC__) && !defined(__xlc__) && !defined (__MINGW32__) && \ + !defined(__HP_aCC) && !defined(__SUNPRO_C) && !defined(__SUNPRO_CC) || \ + defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x550) || (defined(__HP_aCC) && defined(__ia64)) + /* Define to 1 if the system has the type `float_t'. */ +# ifndef _CL_HAVE_FLOAT_T +# define _CL_HAVE_FLOAT_T 1 +# endif +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_FUNCTIONAL +#define _CL_HAVE_FUNCTIONAL 1 +#endif + +/* Does not support new float byte<->float conversions */ +#ifndef _CL_HAVE_FUNCTIONING_FLOAT_BYTE +#define _CL_HAVE_FUNCTIONING_FLOAT_BYTE +#endif + +/* Define to 1 if you have the `getpagesize' function. */ +#ifndef _CL_HAVE_GETPAGESIZE +#define _CL_HAVE_GETPAGESIZE 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef _CL_HAVE_HASH_MAP */ + +/* Define to 1 if you have the header file. */ +/* #undef _CL_HAVE_HASH_SET */ + +/* Define to 1 if the system has the type `intptr_t'. */ +#ifndef _CL_HAVE_INTPTR_T +#define _CL_HAVE_INTPTR_T 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_INTTYPES_H +#define _CL_HAVE_INTTYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_LIST +#define _CL_HAVE_LIST 1 +#endif + +/* Define to 1 if you have the `lltoa' function. */ +/* #undef _CL_HAVE_LLTOA */ + +#if defined(__MINGW32__) + /* Define to 1 if you have the `lltow' function. */ +# ifndef _CL_HAVE_LLTOW +# define _CL_HAVE_LLTOW 1 +# endif +#endif + +#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__xlC__) && !defined(__xlc__) + /* Define to 1 if long double works and has more range or precision than double. */ +# ifndef _CL_HAVE_LONG_DOUBLE +# define _CL_HAVE_LONG_DOUBLE 1 +# endif +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_MAP +#define _CL_HAVE_MAP 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_MATH_H +#define _CL_HAVE_MATH_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_MEMORY_H +#define _CL_HAVE_MEMORY_H 1 +#endif + +#if !defined(__MINGW32__) && !defined(__HP_aCC) && !defined(__xlC__) && !defined(__xlc__) + /* Define to 1 if you have a working `mmap' system call. */ +# ifndef _CL_HAVE_MMAP +# define _CL_HAVE_MMAP 1 +# endif +#endif + +/* define if the compiler implements namespaces */ +#ifndef _CL_HAVE_NAMESPACES +#define _CL_HAVE_NAMESPACES +#endif + +#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) || defined(__HP_aCC) || defined(__xlC__) || defined(__xlc__) + /* Define if you have the nanosleep function */ +# ifndef _CL_HAVE_NANOSLEEP +# define _CL_HAVE_NANOSLEEP 1 +# endif +#endif + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef _CL_HAVE_NDIR_H */ + +/* Does not support new float byte<->float conversions */ +/* #undef _CL_HAVE_NO_FLOAT_BYTE */ + +/* Does not support try/catch blocks */ +/* #undef _CL_HAVE_NO_FUNCTION_TRY_BLOCKS */ + +/* Define to 1 if you have the `printf' function. */ +#ifndef _CL_HAVE_PRINTF +#define _CL_HAVE_PRINTF 1 +#endif + +#if !defined(__MINGW32__) + /* Define if you have POSIX threads libraries and header files. */ +# ifndef _CL_HAVE_PTHREAD +# define _CL_HAVE_PTHREAD 1 +# endif +#endif + +/* Define if recursive pthread mutexes are available */ +/* #undef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE */ + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_SET +#define _CL_HAVE_SET 1 +#endif + +/* Define to 1 if you have the `snprintf' function. */ +#ifndef _CL_HAVE_SNPRINTF +#define _CL_HAVE_SNPRINTF 1 +#endif + +/* Defined if the snprintf overflow test fails */ +/* #undef _CL_HAVE_SNPRINTF_BUG */ + +/* Define to 1 if you have the `snwprintf' function. */ +/* #undef _CL_HAVE_SNWPRINTF */ + +#if !defined(__HP_aCC) && !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) + /* define if the compiler supports ISO C++ standard library */ +# ifndef _CL_HAVE_STD +# define _CL_HAVE_STD +# endif +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_STDARG_H +#define _CL_HAVE_STDARG_H 1 +#endif + +/* x */ +#ifndef _CL_HAVE_STDEXCEPT +#define _CL_HAVE_STDEXCEPT +#endif + +#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__HP_aCC) && \ + !defined(__xlC__) && !defined(__xlc__) + /* Define to 1 if you have the header file. */ +# ifndef _CL_HAVE_STDINT_H +# define _CL_HAVE_STDINT_H 1 +# endif +#endif + +#if !defined(__HP_aCC) + /* Define to 1 if you have the header file. */ +# ifndef _CL_HAVE_STDLIB_H +# define _CL_HAVE_STDLIB_H 1 +# endif + + /* define if the compiler supports Standard Template Library */ +# ifndef _CL_HAVE_STL +# define _CL_HAVE_STL +# endif +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_STRINGS_H +#define _CL_HAVE_STRINGS_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_STRING_H +#define _CL_HAVE_STRING_H 1 +#endif + +/* Define to 1 if you have the `strlwr' function. */ +/* #undef _CL_HAVE_STRLWR */ + +/* Define to 1 if you have the `strtoll' function. */ +/* #undef _CL_HAVE_STRTOLL */ + +/* Define to 1 if you have the `strupr' function. */ +/* #undef _CL_HAVE_STRUPR */ + +/* Defined if the swprintf test fails */ +#ifndef _CL_HAVE_SWPRINTF_BUG +#define _CL_HAVE_SWPRINTF_BUG +#endif + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef _CL_HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef _CL_HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_SYS_STAT_H +#define _CL_HAVE_SYS_STAT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_SYS_TIMEB_H +#define _CL_HAVE_SYS_TIMEB_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_SYS_TYPES_H +#define _CL_HAVE_SYS_TYPES_H 1 +#endif + +#if defined(__MINGW32__) + /* Define to 1 if you have the header file. */ + # ifndef _CL_HAVE_TCHAR_H + # define _CL_HAVE_TCHAR_H 1 + # endif +#endif + +#if defined(__MINGW32__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C) + /* Define to 1 if you have the `tell' function. */ +# ifndef _CL_HAVE_TELL +# define _CL_HAVE_TELL 1 +# endif +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_UNISTD_H +#define _CL_HAVE_UNISTD_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_VECTOR +#define _CL_HAVE_VECTOR 1 +#endif + +/* Define to 1 if you have the `vsnwprintf' function. */ +/* #undef _CL_HAVE_VSNWPRINTF */ + +/* Define to 1 if you have the header file. */ +#ifndef _CL_HAVE_WCHAR_H +#define _CL_HAVE_WCHAR_H 1 +#endif + +/* Define to 1 if the system has the type `wchar_t'. */ +#ifndef _CL_HAVE_WCHAR_T +#define _CL_HAVE_WCHAR_T 1 +#endif + +#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__MINGW32__) && \ + !defined(Q_OS_MAC) && !defined(__HP_aCC) + /* Define to 1 if you have the `wcscasecmp' function. */ +# ifndef _CL_HAVE_WCSCASECMP +# define _CL_HAVE_WCSCASECMP 1 +# endif +#endif + +/* Define to 1 if you have the `wcscat' function. */ +#ifndef _CL_HAVE_WCSCAT +#define _CL_HAVE_WCSCAT 1 +#endif + +/* Define to 1 if you have the `wcschr' function. */ +#ifndef _CL_HAVE_WCSCHR +#define _CL_HAVE_WCSCHR 1 +#endif + +/* Define to 1 if you have the `wcscmp' function. */ +#ifndef _CL_HAVE_WCSCMP +#define _CL_HAVE_WCSCMP 1 +#endif + +/* Define to 1 if you have the `wcscpy' function. */ +#ifndef _CL_HAVE_WCSCPY +#define _CL_HAVE_WCSCPY 1 +#endif + +/* Define to 1 if you have the `wcscspn' function. */ +#ifndef _CL_HAVE_WCSCSPN +#define _CL_HAVE_WCSCSPN 1 +#endif + +#if defined(__MINGW32__) + /* Define to 1 if you have the `wcsicmp' function. */ +# ifndef _CL_HAVE_WCSICMP +# define _CL_HAVE_WCSICMP 1 +# endif +#endif + +/* Define to 1 if you have the `wcslen' function. */ +#ifndef _CL_HAVE_WCSLEN +#define _CL_HAVE_WCSLEN 1 +#endif + +/* Define to 1 if you have the `wcsncmp' function. */ +#ifndef _CL_HAVE_WCSNCMP +#define _CL_HAVE_WCSNCMP 1 +#endif + +/* Define to 1 if you have the `wcsncpy' function. */ +#ifndef _CL_HAVE_WCSNCPY +#define _CL_HAVE_WCSNCPY 1 +#endif + +/* Define to 1 if you have the `wcsstr' function. */ +#ifndef _CL_HAVE_WCSSTR +#define _CL_HAVE_WCSSTR 1 +#endif + +/* Define to 1 if you have the `wcstod' function. */ +#ifndef _CL_HAVE_WCSTOD +#define _CL_HAVE_WCSTOD 1 +#endif + +#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__HP_aCC) + /* Define to 1 if you have the `wcstoll' function. */ +# ifndef _CL_HAVE_WCSTOLL +# define _CL_HAVE_WCSTOLL 1 +# endif +#endif + +#if defined(__MINGW32__) + /* Define to 1 if you have the `wcsupr' function. */ +# ifndef _CL_HAVE_WCSUPR +# define _CL_HAVE_WCSUPR 1 +# endif +#endif + +#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) || defined(__HP_aCC) + /* Define to 1 if you have a functioning header file. */ +# ifndef _CL_HAVE_WCTYPE_H +# define _CL_HAVE_WCTYPE_H +# endif +#endif + +/* Define to 1 if you have the `wprintf' function. */ +/* #undef _CL_HAVE_WPRINTF */ + +#if defined(__MINGW32__) + /* Define to 1 if you have the `_filelength' function. */ +# ifndef _CL_HAVE__FILELENGTH +# define _CL_HAVE__FILELENGTH 1 +# endif +#endif + +/* How to define a static const in a class */ +#ifndef LUCENE_STATIC_CONSTANT_SYNTAX +#define LUCENE_STATIC_CONSTANT_SYNTAX 1 +#endif + +/* Name of package */ +#ifndef _CL_PACKAGE +#define _CL_PACKAGE "clucene-core" +#endif + +/* Define to the address where bug reports for this package should be sent. */ +#ifndef _CL_PACKAGE_BUGREPORT +#define _CL_PACKAGE_BUGREPORT "" +#endif + +/* Define to the full name of this package. */ +#ifndef _CL_PACKAGE_NAME +#define _CL_PACKAGE_NAME "" +#endif + +/* Define to the full name and version of this package. */ +#ifndef _CL_PACKAGE_STRING +#define _CL_PACKAGE_STRING "" +#endif + +/* Define to the one symbol short name of this package. */ +#ifndef _CL_PACKAGE_TARNAME +#define _CL_PACKAGE_TARNAME "" +#endif + +/* Define to the version of this package. */ +#ifndef _CL_PACKAGE_VERSION +#define _CL_PACKAGE_VERSION "" +#endif + +/* Define to the necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef _CL_PTHREAD_CREATE_JOINABLE */ + +/* The size of a `unsigned char', as computed by sizeof. */ +/* #undef _CL_SIZEOF_UNSIGNED_CHAR */ + +/* The size of a `unsigned int', as computed by sizeof. */ +/* #undef _CL_SIZEOF_UNSIGNED_INT */ + +/* The size of a `unsigned long', as computed by sizeof. */ +/* #undef _CL_SIZEOF_UNSIGNED_LONG */ + +/* The size of a `unsigned long long', as computed by sizeof. */ +/* #undef _CL_SIZEOF_UNSIGNED_LONG_LONG */ + +/* The size of a `unsigned __int64', as computed by sizeof. */ +/* #undef _CL_SIZEOF_UNSIGNED___INT64 */ + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +/* #undef _CL_STAT_MACROS_BROKEN */ + +#if !defined(__HP_aCC) + /* Define to 1 if you have the ANSI C header files. */ +# ifndef _CL_STDC_HEADERS +# define _CL_STDC_HEADERS 1 +# endif + +/* Define to 1 if you can safely include both and . */ +# ifndef _CL_TIME_WITH_SYS_TIME +# define _CL_TIME_WITH_SYS_TIME 1 +# endif +#endif + +/* Version number of package */ +#ifndef _CL_VERSION +#define _CL_VERSION "0.9.17" +#endif + +/* Forces into Ascii mode */ +/* #undef _ASCII */ + +/* Conditional Debugging */ +/* #undef _CL__CND_DEBUG */ + +/* debugging option */ +/* #undef _DEBUG */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* If not already defined, then define as a datatype of *exactly* 32 bits. */ +/* #undef uint32_t */ + +/* If not already defined, then define as a datatype of *exactly* 64 bits. */ +/* #undef uint64_t */ + +/* If not already defined, then define as a datatype of *exactly* 8 bits. */ +/* #undef uint8_t */ + +/* once: +_SRC_CLUCENE_CLUCENE_CONFIG_H +*/ +#endif + + +#if defined Q_CC_MSVC && _MSC_VER < 1300 +# define LUCENE_NO_STDC_NAMESPACE +#endif + + +#endif // QCLUCENE_CONFIG_P_H + diff --git a/src/assistant/lib/fulltextsearch/qclucene_global_p.h b/src/assistant/lib/fulltextsearch/qclucene_global_p.h new file mode 100644 index 0000000..887b113 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qclucene_global_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QCLUCENE_GLOBAL_P_H +#define QCLUCENE_GLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#if !defined(_MSC_VER) +# include "qclucene-config_p.h" +#endif + +#include +#include + +#if !defined(_MSC_VER) && !defined(__MINGW32__) && defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T) +# if !defined(TCHAR) +# define TCHAR wchar_t +# endif +#else +# include +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#if !defined(QT_SHARED) && !defined(QT_DLL) +# define QHELP_EXPORT +#elif defined(QHELP_LIB) +# define QHELP_EXPORT Q_DECL_EXPORT +#else +# define QHELP_EXPORT Q_DECL_IMPORT +#endif + +// +// W A R N I N G +// ------------- +// +// adjustments here, need to be done in +// QTDIR/src/3rdparty/clucene/src/CLucene/StdHeader.h as well +// +#if defined(_LUCENE_DONTIMPLEMENT_NS_MACROS) + +#elif !defined(DISABLE_NAMESPACE) +# ifdef QT_NAMESPACE +# define CL_NS_DEF(sub) namespace QT_NAMESPACE { namespace lucene{ namespace sub{ +# define CL_NS_DEF2(sub,sub2) namespace QT_NAMESPACE { namespace lucene{ namespace sub{ namespace sub2 { + +# define CL_NS_END }}} +# define CL_NS_END2 }}}} + +# define CL_NS_USE(sub) using namespace QT_NAMESPACE::lucene::sub; +# define CL_NS_USE2(sub,sub2) using namespace QT_NAMESPACE::lucene::sub::sub2; + +# define CL_NS(sub) QT_NAMESPACE::lucene::sub +# define CL_NS2(sub,sub2) QT_NAMESPACE::lucene::sub::sub2 +# else +# define CL_NS_DEF(sub) namespace lucene{ namespace sub{ +# define CL_NS_DEF2(sub,sub2) namespace lucene{ namespace sub{ namespace sub2 { + +# define CL_NS_END }} +# define CL_NS_END2 }}} + +# define CL_NS_USE(sub) using namespace lucene::sub; +# define CL_NS_USE2(sub,sub2) using namespace lucene::sub::sub2; + +# define CL_NS(sub) lucene::sub +# define CL_NS2(sub,sub2) lucene::sub::sub2 +# endif +#else +# define CL_NS_DEF(sub) +# define CL_NS_DEF2(sub, sub2) +# define CL_NS_END +# define CL_NS_END2 +# define CL_NS_USE(sub) +# define CL_NS_USE2(sub,sub2) +# define CL_NS(sub) +# define CL_NS2(sub,sub2) +#endif + +namespace { + TCHAR* QStringToTChar(const QString &str) + { + TCHAR *string = new TCHAR[(str.length() +1) * sizeof(TCHAR)]; + memset(string, 0, (str.length() +1) * sizeof(TCHAR)); + #if defined(UNICODE) || defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T) + str.toWCharArray(string); + #else + const QByteArray ba = str.toAscii(); + strcpy(string, ba.constData()); + #endif + return string; + } + + QString TCharToQString(const TCHAR *string) + { + #if defined(UNICODE) || defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T) + QString retValue = QString::fromWCharArray(string); + return retValue; + #else + return QString(QLatin1String(string)); + #endif + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCLUCENE_GLOBAL_P_H diff --git a/src/assistant/lib/fulltextsearch/qdocument.cpp b/src/assistant/lib/fulltextsearch/qdocument.cpp new file mode 100644 index 0000000..3c4cc06 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qdocument.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qdocument_p.h" +#include "qreader_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneDocumentPrivate::QCLuceneDocumentPrivate() + : QSharedData() +{ + document = 0; + deleteCLuceneDocument = true; +} + +QCLuceneDocumentPrivate::QCLuceneDocumentPrivate(const QCLuceneDocumentPrivate &other) + : QSharedData() +{ + document = _CL_POINTER(other.document); + deleteCLuceneDocument = other.deleteCLuceneDocument; +} + +QCLuceneDocumentPrivate::~QCLuceneDocumentPrivate() +{ + if (deleteCLuceneDocument) + _CLDECDELETE(document); +} + + +QCLuceneDocument::QCLuceneDocument() + : d(new QCLuceneDocumentPrivate()) +{ + // nothing todo + d->document = new lucene::document::Document(); +} + +QCLuceneDocument::~QCLuceneDocument() +{ + qDeleteAll(fieldList); + fieldList.clear(); +} + +void QCLuceneDocument::add(QCLuceneField *field) +{ + field->d->deleteCLuceneField = false; + d->document->add(*field->d->field); + fieldList.append(field); +} + +QCLuceneField* QCLuceneDocument::getField(const QString &name) const +{ + QCLuceneField* field = 0; + foreach (field, fieldList) { + if (field->name() == name && field->d->field != 0) + return field; + } + + field = 0; + TCHAR *fieldName = QStringToTChar(name); + lucene::document::Field *f = d->document->getField(fieldName); + if (f) { + field = new QCLuceneField(); + field->d->field = f; + fieldList.append(field); + field->d->deleteCLuceneField = false; + + lucene::util::Reader *r = f->readerValue(); + if (r) { + field->reader->d->reader = r; + field->reader->d->deleteCLuceneReader = false; + } + } + delete [] fieldName; + + return field; +} + +QString QCLuceneDocument::get(const QString &name) const +{ + QCLuceneField* field = getField(name); + if (field) + return field->stringValue(); + + return QString(); +} + +QString QCLuceneDocument::toString() const +{ + return TCharToQString(d->document->toString()); +} + +void QCLuceneDocument::setBoost(qreal boost) +{ + d->document->setBoost(qreal(boost)); +} + +qreal QCLuceneDocument::getBoost() const +{ + return qreal(d->document->getBoost()); +} + +void QCLuceneDocument::removeField(const QString &name) +{ + TCHAR *fieldName = QStringToTChar(name); + d->document->removeField(fieldName); + delete [] fieldName; + + QList tmp; + lucene::document::DocumentFieldEnumeration *dfe = d->document->fields(); + while (dfe->hasMoreElements()) { + const lucene::document::Field* f = dfe->nextElement(); + foreach (QCLuceneField* field, fieldList) { + if (f == field->d->field) { + tmp.append(field); + break; + } + } + } + _CLDELETE(dfe); + fieldList = tmp; +} + +void QCLuceneDocument::removeFields(const QString &name) +{ + for (qint32 i = fieldList.count() -1; i >= 0; --i) { + QCLuceneField* field = fieldList.at(i); + if (field->name() == name) + delete fieldList.takeAt(i); + } + + TCHAR *fieldName = QStringToTChar(name); + d->document->removeFields(fieldName); + delete [] fieldName; +} + +QStringList QCLuceneDocument::getValues(const QString &name) const +{ + TCHAR *fieldName = QStringToTChar(name); + TCHAR **values = d->document->getValues(fieldName); + + QStringList retValue; + if (values) { + for (qint32 i = 0; 0 != values[i]; ++i) { + retValue.append(TCharToQString((const TCHAR*)values[i])); + delete [] values[i]; values[i] = 0; + } + delete values; + } + + delete [] fieldName; + return retValue; +} + +void QCLuceneDocument::clear() +{ + d->document->clear(); + qDeleteAll(fieldList); + fieldList.clear(); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qdocument_p.h b/src/assistant/lib/fulltextsearch/qdocument_p.h new file mode 100644 index 0000000..31369af --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qdocument_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QDOCUMENT_P_H +#define QDOCUMENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qfield_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include +#include +#include + +CL_NS_DEF(document) + class Document; +CL_NS_END +CL_NS_USE(document) + +QT_BEGIN_NAMESPACE + +class QCLuceneHits; +class QCLuceneIndexReader; +class QCLuceneIndexWriter; +class QCLuceneIndexSearcher; +class QCLuceneMultiSearcher; + +class QHELP_EXPORT QCLuceneDocumentPrivate : public QSharedData +{ +public: + QCLuceneDocumentPrivate(); + QCLuceneDocumentPrivate(const QCLuceneDocumentPrivate &other); + + ~QCLuceneDocumentPrivate(); + + Document *document; + bool deleteCLuceneDocument; + +private: + QCLuceneDocumentPrivate &operator=(const QCLuceneDocumentPrivate &other); +}; + +class QHELP_EXPORT QCLuceneDocument +{ +public: + QCLuceneDocument(); + ~QCLuceneDocument(); + + void add(QCLuceneField *field); + QCLuceneField* getField(const QString &name) const; + QString get(const QString &name) const; + QString toString() const; + void setBoost(qreal boost); + qreal getBoost() const; + void removeField(const QString &name); + void removeFields(const QString &name); + QStringList getValues(const QString &name) const; + void clear(); + +protected: + friend class QCLuceneHits; + friend class QCLuceneIndexReader; + friend class QCLuceneIndexWriter; + friend class QCLuceneIndexSearcher; + friend class QCLuceneMultiSearcher; + QSharedDataPointer d; + +private: + mutable QList fieldList; +}; + +QT_END_NAMESPACE + +#endif // QDOCUMENT_P_H diff --git a/src/assistant/lib/fulltextsearch/qfield.cpp b/src/assistant/lib/fulltextsearch/qfield.cpp new file mode 100644 index 0000000..448acf0 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qfield.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qfield_p.h" +#include "qreader_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneFieldPrivate::QCLuceneFieldPrivate() + : QSharedData() +{ + field = 0; + deleteCLuceneField = true; +} + +QCLuceneFieldPrivate::QCLuceneFieldPrivate(const QCLuceneFieldPrivate &other) + : QSharedData() +{ + field = _CL_POINTER(other.field); + deleteCLuceneField = other.deleteCLuceneField; +} + +QCLuceneFieldPrivate::~QCLuceneFieldPrivate() +{ + if (deleteCLuceneField) + _CLDECDELETE(field); +} + + +QCLuceneField::QCLuceneField() + : d(new QCLuceneFieldPrivate()) + , reader(0) +{ + // nothing todo +} + +QCLuceneField::QCLuceneField(const QString &name, const QString &value, int configs) + : d(new QCLuceneFieldPrivate()) + , reader(0) +{ + TCHAR* fieldName = QStringToTChar(name); + TCHAR* fieldValue = QStringToTChar(value); + + d->field = new lucene::document::Field(fieldName, fieldValue, configs); + + delete [] fieldName; + delete [] fieldValue; +} + +QCLuceneField::QCLuceneField(const QString &name, QCLuceneReader *reader, + int configs) + : d(new QCLuceneFieldPrivate()) + , reader(reader) +{ + TCHAR* fieldName = QStringToTChar(name); + + reader->d->deleteCLuceneReader = false; // clucene takes ownership + d->field = new lucene::document::Field(fieldName, reader->d->reader, configs); + + delete [] fieldName; +} + +QCLuceneField::~QCLuceneField() +{ + delete reader; +} + +QString QCLuceneField::name() const +{ + return TCharToQString(d->field->name()); +} + +QString QCLuceneField::stringValue() const +{ + return TCharToQString((const TCHAR*)d->field->stringValue()); +} + +QCLuceneReader* QCLuceneField::readerValue() const +{ + return reader; +} + +bool QCLuceneField::isStored() const +{ + return d->field->isStored(); +} + +bool QCLuceneField::isIndexed() const +{ + return d->field->isIndexed(); +} + +bool QCLuceneField::isTokenized() const +{ + return d->field->isTokenized(); +} + +bool QCLuceneField::isCompressed() const +{ + return d->field->isCompressed(); +} + +void QCLuceneField::setConfig(int termVector) +{ + d->field->setConfig(termVector); +} + +bool QCLuceneField::isTermVectorStored() const +{ + return d->field->isTermVectorStored(); +} + +bool QCLuceneField::isStoreOffsetWithTermVector() const +{ + return d->field->isStoreOffsetWithTermVector(); +} + +bool QCLuceneField::isStorePositionWithTermVector() const +{ + return d->field->isStorePositionWithTermVector(); +} + +qreal QCLuceneField::getBoost() const +{ + return qreal(d->field->getBoost()); +} + +void QCLuceneField::setBoost(qreal value) +{ + d->field->setBoost(qreal(value)); +} + +bool QCLuceneField::isBinary() const +{ + return d->field->isBinary(); +} + +bool QCLuceneField::getOmitNorms() const +{ + return d->field->getOmitNorms(); +} + +void QCLuceneField::setOmitNorms(bool omitNorms) +{ + d->field->setOmitNorms(omitNorms); +} + +QString QCLuceneField::toString() const +{ + return TCharToQString(d->field->toString()); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qfield_p.h b/src/assistant/lib/fulltextsearch/qfield_p.h new file mode 100644 index 0000000..39f2ff3 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qfield_p.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QFIELD_P_H +#define QFIELD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qclucene_global_p.h" + +#include +#include +#include + +CL_NS_DEF(document) + class Field; +CL_NS_END +CL_NS_USE(document) + +QT_BEGIN_NAMESPACE + +class QCLuceneReader; +class QCLuceneDocument; + +class QHELP_EXPORT QCLuceneFieldPrivate : public QSharedData +{ +public: + QCLuceneFieldPrivate(); + QCLuceneFieldPrivate(const QCLuceneFieldPrivate &other); + + ~QCLuceneFieldPrivate(); + + Field *field; + bool deleteCLuceneField; + +private: + QCLuceneFieldPrivate &operator=(const QCLuceneFieldPrivate &other); +}; + +class QHELP_EXPORT QCLuceneField +{ +public: + enum Store { + STORE_YES = 1, + STORE_NO = 2, + STORE_COMPRESS = 4 + }; + + enum Index { + INDEX_NO = 16, + INDEX_TOKENIZED = 32, + INDEX_UNTOKENIZED = 64, + INDEX_NONORMS = 128 + }; + + enum TermVector { + TERMVECTOR_NO = 256, + TERMVECTOR_YES = 512, + TERMVECTOR_WITH_POSITIONS = 1024, + TERMVECTOR_WITH_OFFSETS = 2048 + }; + + QCLuceneField(const QString &name, const QString &value, int configs); + QCLuceneField(const QString &name, QCLuceneReader *reader, int configs); + ~QCLuceneField(); + + QString name() const; + QString stringValue() const; + QCLuceneReader* readerValue() const; + bool isStored() const; + bool isIndexed() const; + bool isTokenized() const; + bool isCompressed() const; + void setConfig(int termVector); + bool isTermVectorStored() const; + bool isStoreOffsetWithTermVector() const; + bool isStorePositionWithTermVector() const; + qreal getBoost() const; + void setBoost(qreal value); + bool isBinary() const; + bool getOmitNorms() const; + void setOmitNorms(bool omitNorms); + QString toString() const; + +protected: + QCLuceneField(); + friend class QCLuceneDocument; + QSharedDataPointer d; + +private: + QCLuceneReader* reader; +}; + +QT_END_NAMESPACE + +#endif // QFIELD_P_H diff --git a/src/assistant/lib/fulltextsearch/qfilter.cpp b/src/assistant/lib/fulltextsearch/qfilter.cpp new file mode 100644 index 0000000..4807193 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qfilter.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qfilter_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneFilterPrivate::QCLuceneFilterPrivate() + : QSharedData() +{ + filter = 0; + deleteCLuceneFilter = true; +} + +QCLuceneFilterPrivate::QCLuceneFilterPrivate(const QCLuceneFilterPrivate &other) + : QSharedData() +{ + filter = _CL_POINTER(other.filter); + deleteCLuceneFilter = other.deleteCLuceneFilter; +} + +QCLuceneFilterPrivate::~QCLuceneFilterPrivate () +{ + if (deleteCLuceneFilter) + _CLDECDELETE(filter); +} + + +QCLuceneFilter::QCLuceneFilter() + : d(new QCLuceneFilterPrivate()) +{ + // nothing todo +} + +QCLuceneFilter::~QCLuceneFilter() +{ + // nothing todo +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qfilter_p.h b/src/assistant/lib/fulltextsearch/qfilter_p.h new file mode 100644 index 0000000..67f6615 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qfilter_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QFilter_P_H +#define QFilter_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qclucene_global_p.h" + +#include +#include + +CL_NS_DEF(search) + class Filter; +CL_NS_END +CL_NS_USE(search) + +QT_BEGIN_NAMESPACE + +class QCLuceneHits; +class QCLuceneSearcher; + +class QHELP_EXPORT QCLuceneFilterPrivate : public QSharedData +{ +public: + QCLuceneFilterPrivate(); + QCLuceneFilterPrivate(const QCLuceneFilterPrivate &other); + + ~QCLuceneFilterPrivate (); + + Filter *filter; + bool deleteCLuceneFilter; + +private: + QCLuceneFilterPrivate &operator=(const QCLuceneFilterPrivate &other); +}; + +class QHELP_EXPORT QCLuceneFilter +{ + QCLuceneFilter(); + virtual ~QCLuceneFilter(); + +protected: + friend class QCLuceneHits; + friend class QCLuceneSearcher; + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +#endif // QFilter_P_H diff --git a/src/assistant/lib/fulltextsearch/qhits.cpp b/src/assistant/lib/fulltextsearch/qhits.cpp new file mode 100644 index 0000000..5223a74 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qhits.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qhits_p.h" +#include "qsearchable_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneHitsPrivate::QCLuceneHitsPrivate() + : QSharedData() +{ + hits = 0; + deleteCLuceneHits = true; +} + +QCLuceneHitsPrivate::QCLuceneHitsPrivate(const QCLuceneHitsPrivate &other) + : QSharedData() +{ + hits = _CL_POINTER(other.hits); + deleteCLuceneHits = other.deleteCLuceneHits; +} + +QCLuceneHitsPrivate::~QCLuceneHitsPrivate() +{ + if (deleteCLuceneHits) + _CLDECDELETE(hits); +} + + +QCLuceneHits::QCLuceneHits(const QCLuceneSearcher &searcher, + const QCLuceneQuery &query, const QCLuceneFilter &filter) + : d(new QCLuceneHitsPrivate()) +{ + d->hits = new lucene::search::Hits(searcher.d->searchable, query.d->query, + filter.d->filter); +} + +QCLuceneHits::QCLuceneHits(const QCLuceneSearcher &searcher, const QCLuceneQuery &query, + const QCLuceneFilter &filter, const QCLuceneSort &sort) + : d(new QCLuceneHitsPrivate()) +{ + d->hits = new lucene::search::Hits(searcher.d->searchable, query.d->query, + filter.d->filter, sort.d->sort); +} + +QCLuceneHits::~QCLuceneHits() +{ + // nothing todo +} + +QCLuceneDocument QCLuceneHits::document(const qint32 index) +{ + // TODO: check this + QCLuceneDocument document; + document.d->deleteCLuceneDocument = false; + lucene::document::Document &doc = d->hits->doc(int32_t(index)); + document.d->document = &doc; + + return document; +} + +qint32 QCLuceneHits::length() const +{ + return qint32(d->hits->length()); +} + +qint32 QCLuceneHits::id(const qint32 index) +{ + return qint32(d->hits->id(int32_t(index))); +} + +qreal QCLuceneHits::score(const qint32 index) +{ + return qreal(d->hits->score(int32_t(index))); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qhits_p.h b/src/assistant/lib/fulltextsearch/qhits_p.h new file mode 100644 index 0000000..98cd702 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qhits_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QHITS_P_H +#define QHITS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qsort_p.h" +#include "qquery_p.h" +#include "qfilter_p.h" +#include "qdocument_p.h" +#include "qclucene_global_p.h" + +#include +#include + +CL_NS_DEF(search) + class Hits; +CL_NS_END +CL_NS_USE(search) + +QT_BEGIN_NAMESPACE + +class QCLuceneSearcher; + +class QHELP_EXPORT QCLuceneHitsPrivate : public QSharedData +{ +public: + QCLuceneHitsPrivate(); + QCLuceneHitsPrivate(const QCLuceneHitsPrivate &other); + + ~QCLuceneHitsPrivate(); + + Hits *hits; + bool deleteCLuceneHits; + +private: + QCLuceneHitsPrivate &operator=(const QCLuceneHitsPrivate &other); +}; + +class QHELP_EXPORT QCLuceneHits +{ +public: + QCLuceneHits(const QCLuceneSearcher &searcher, const QCLuceneQuery &query, + const QCLuceneFilter &filter); + QCLuceneHits(const QCLuceneSearcher &searcher, const QCLuceneQuery &query, + const QCLuceneFilter &filter, const QCLuceneSort &sort); + virtual ~QCLuceneHits(); + + QCLuceneDocument document(const qint32 index); + qint32 length() const; + qint32 id (const qint32 index); + qreal score(const qint32 index); + +protected: + friend class QCLuceneSearcher; + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +#endif // QHITS_P_H diff --git a/src/assistant/lib/fulltextsearch/qindexreader.cpp b/src/assistant/lib/fulltextsearch/qindexreader.cpp new file mode 100644 index 0000000..285a963 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qindexreader.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qindexreader_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneIndexReaderPrivate::QCLuceneIndexReaderPrivate() + : QSharedData() +{ + reader = 0; + deleteCLuceneIndexReader = true; +} + +QCLuceneIndexReaderPrivate::QCLuceneIndexReaderPrivate(const QCLuceneIndexReaderPrivate &other) + : QSharedData() +{ + reader = _CL_POINTER(other.reader); + deleteCLuceneIndexReader = other.deleteCLuceneIndexReader; +} + +QCLuceneIndexReaderPrivate::~QCLuceneIndexReaderPrivate() +{ + if (deleteCLuceneIndexReader) + _CLDECDELETE(reader); +} + + +QCLuceneIndexReader::QCLuceneIndexReader() + : d(new QCLuceneIndexReaderPrivate()) +{ + // nothing todo, private +} + +QCLuceneIndexReader::~QCLuceneIndexReader() +{ + // nothing todo +} + +bool QCLuceneIndexReader::isLuceneFile(const QString &filename) +{ + using namespace lucene::index; + + return IndexReader::isLuceneFile(filename); +} + +bool QCLuceneIndexReader::indexExists(const QString &directory) +{ + using namespace lucene::index; + return IndexReader::indexExists(directory); +} + +QCLuceneIndexReader QCLuceneIndexReader::open(const QString &path) +{ + using namespace lucene::index; + + QCLuceneIndexReader indexReader; + indexReader.d->reader = IndexReader::open(path); + + return indexReader; +} + +void QCLuceneIndexReader::unlock(const QString &path) +{ + using namespace lucene::index; + IndexReader::unlock(path); +} + +bool QCLuceneIndexReader::isLocked(const QString &directory) +{ + using namespace lucene::index; + return IndexReader::isLocked(directory); +} + +quint64 QCLuceneIndexReader::lastModified(const QString &directory) +{ + using namespace lucene::index; + return quint64(IndexReader::lastModified(directory)); +} + +qint64 QCLuceneIndexReader::getCurrentVersion(const QString &directory) +{ + using namespace lucene::index; + return qint64(IndexReader::getCurrentVersion(directory)); +} + +void QCLuceneIndexReader::close() +{ + d->reader->close(); +} + +bool QCLuceneIndexReader::isCurrent() +{ + return d->reader->isCurrent(); +} + +void QCLuceneIndexReader::undeleteAll() +{ + d->reader->undeleteAll(); +} + +qint64 QCLuceneIndexReader::getVersion() +{ + return qint64(d->reader->getVersion()); +} + +void QCLuceneIndexReader::deleteDocument(qint32 docNum) +{ + d->reader->deleteDocument(int32_t(docNum)); +} + +bool QCLuceneIndexReader::hasNorms(const QString &field) +{ + TCHAR *fieldName = QStringToTChar(field); + bool retValue = d->reader->hasNorms(fieldName); + delete [] fieldName; + + return retValue; +} + +qint32 QCLuceneIndexReader::deleteDocuments(const QCLuceneTerm &term) +{ + return d->reader->deleteDocuments(term.d->term); +} + +bool QCLuceneIndexReader::document(qint32 index, QCLuceneDocument &document) +{ + if (!document.d->document) + document.d->document = new lucene::document::Document(); + + if (d->reader->document(int32_t(index), document.d->document)) + return true; + + return false; +} + +void QCLuceneIndexReader::setNorm(qint32 doc, const QString &field, qreal value) +{ + TCHAR *fieldName = QStringToTChar(field); + d->reader->setNorm(int32_t(doc), fieldName, qreal(value)); + delete [] fieldName; +} + +void QCLuceneIndexReader::setNorm(qint32 doc, const QString &field, quint8 value) +{ + TCHAR *fieldName = QStringToTChar(field); + d->reader->setNorm(int32_t(doc), fieldName, uint8_t(value)); + delete [] fieldName; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qindexreader_p.h b/src/assistant/lib/fulltextsearch/qindexreader_p.h new file mode 100644 index 0000000..7421daa --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qindexreader_p.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QINDEXREADER_P_H +#define QINDEXREADER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qterm_p.h" +#include "qdocument_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include +#include + +CL_NS_DEF(index) + class IndexReader; +CL_NS_END +CL_NS_USE(index) + +QT_BEGIN_NAMESPACE + +class QCLuceneIndexWriter; +class QCLuceneIndexSearcher; + +class QHELP_EXPORT QCLuceneIndexReaderPrivate : public QSharedData +{ +public: + QCLuceneIndexReaderPrivate(); + QCLuceneIndexReaderPrivate(const QCLuceneIndexReaderPrivate &other); + + ~QCLuceneIndexReaderPrivate(); + + IndexReader *reader; + bool deleteCLuceneIndexReader; + +private: + QCLuceneIndexReaderPrivate &operator=(const QCLuceneIndexReaderPrivate &other); +}; + +class QHELP_EXPORT QCLuceneIndexReader +{ +public: + enum FieldOption { + ALL = 1, + INDEXED = 2, + UNINDEXED = 4, + INDEXED_WITH_TERMVECTOR = 8, + INDEXED_NO_TERMVECTOR = 16, + TERMVECTOR = 32, + TERMVECTOR_WITH_POSITION = 64, + TERMVECTOR_WITH_OFFSET = 128, + TERMVECTOR_WITH_POSITION_OFFSET = 256 + }; + + virtual ~QCLuceneIndexReader(); + + static bool isLuceneFile(const QString &filename); + static bool indexExists(const QString &directory); + static QCLuceneIndexReader open(const QString &path); + + static void unlock(const QString &path); + static bool isLocked(const QString &directory); + + static quint64 lastModified(const QString &directory); + static qint64 getCurrentVersion(const QString &directory); + + void close(); + bool isCurrent(); + void undeleteAll(); + qint64 getVersion(); + void deleteDocument(qint32 docNum); + bool hasNorms(const QString &field); + qint32 deleteDocuments(const QCLuceneTerm &term); + bool document(qint32 index, QCLuceneDocument &document); + void setNorm(qint32 doc, const QString &field, qreal value); + void setNorm(qint32 doc, const QString &field, quint8 value); + +protected: + friend class QCLuceneIndexWriter; + friend class QCLuceneIndexSearcher; + QSharedDataPointer d; + +private: + QCLuceneIndexReader(); +}; + +QT_END_NAMESPACE + +#endif // QINDEXREADER_P_H diff --git a/src/assistant/lib/fulltextsearch/qindexwriter.cpp b/src/assistant/lib/fulltextsearch/qindexwriter.cpp new file mode 100644 index 0000000..1f579eb --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qindexwriter.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qindexwriter_p.h" +#include "qindexreader_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneIndexWriterPrivate::QCLuceneIndexWriterPrivate() + : QSharedData() +{ + writer = 0; + deleteCLuceneIndexWriter = true; +} + +QCLuceneIndexWriterPrivate::QCLuceneIndexWriterPrivate(const QCLuceneIndexWriterPrivate &other) + : QSharedData() +{ + writer = _CL_POINTER(other.writer); + deleteCLuceneIndexWriter = other.deleteCLuceneIndexWriter; +} + +QCLuceneIndexWriterPrivate::~QCLuceneIndexWriterPrivate() +{ + if (deleteCLuceneIndexWriter) + _CLDECDELETE(writer); +} + + +QCLuceneIndexWriter::QCLuceneIndexWriter(const QString &path, + QCLuceneAnalyzer &analyzer, + bool create, bool closeDir) + : d(new QCLuceneIndexWriterPrivate()) + , analyzer(analyzer) +{ + d->writer = new lucene::index::IndexWriter(path, + analyzer.d->analyzer, create, closeDir); +} + +QCLuceneIndexWriter::~QCLuceneIndexWriter() +{ + // nothing todo +} + +void QCLuceneIndexWriter::close() +{ + d->writer->close(); +} + +void QCLuceneIndexWriter::optimize() +{ + d->writer->optimize(); +} + +qint32 QCLuceneIndexWriter::docCount() +{ + return qint32(d->writer->docCount()); +} + +QCLuceneAnalyzer QCLuceneIndexWriter::getAnalyzer() +{ + return analyzer; +} + +void QCLuceneIndexWriter::addIndexes(const QList &readers) +{ + using namespace lucene::index; + IndexReader** readerArray = new IndexReader*[readers.count()]; + + for (int i = 0; i < readers.count(); ++i) + readerArray[i] = (readers.at(i))->d->reader; + + d->writer->addIndexes(readerArray); + delete [] readerArray; +} + +void QCLuceneIndexWriter::addDocument(QCLuceneDocument &doc, + QCLuceneAnalyzer &analyzer) +{ + if (doc.d->document) + d->writer->addDocument(doc.d->document, analyzer.d->analyzer); +} + +qint32 QCLuceneIndexWriter::getMaxFieldLength() const +{ + return qint32(d->writer->getMaxFieldLength()); +} + +void QCLuceneIndexWriter::setMaxFieldLength(qint32 value) +{ + d->writer->setMaxFieldLength(int32_t(value)); +} + +qint32 QCLuceneIndexWriter::getMaxBufferedDocs() const +{ + return qint32(d->writer->getMaxBufferedDocs()); +} + +void QCLuceneIndexWriter::setMaxBufferedDocs(qint32 value) +{ + d->writer->setMaxBufferedDocs(int32_t(value)); +} + +qint64 QCLuceneIndexWriter::getWriteLockTimeout() const +{ + return qint64(d->writer->getWriteLockTimeout()); +} + +void QCLuceneIndexWriter::setWriteLockTimeout(qint64 writeLockTimeout) +{ + d->writer->setWriteLockTimeout(int64_t(writeLockTimeout)); +} + +qint64 QCLuceneIndexWriter::getCommitLockTimeout() const +{ + return qint64(d->writer->getCommitLockTimeout()); +} + +void QCLuceneIndexWriter::setCommitLockTimeout(qint64 commitLockTimeout) +{ + d->writer->setCommitLockTimeout(int64_t(commitLockTimeout)); +} + +qint32 QCLuceneIndexWriter::getMergeFactor() const +{ + return qint32(d->writer->getMergeFactor()); +} + +void QCLuceneIndexWriter::setMergeFactor(qint32 value) +{ + d->writer->setMergeFactor(int32_t(value)); +} + +qint32 QCLuceneIndexWriter::getTermIndexInterval() const +{ + return qint32(d->writer->getTermIndexInterval()); +} + +void QCLuceneIndexWriter::setTermIndexInterval(qint32 interval) +{ + d->writer->setTermIndexInterval(int32_t(interval)); +} + +qint32 QCLuceneIndexWriter::getMinMergeDocs() const +{ + return qint32(d->writer->getMinMergeDocs()); +} + +void QCLuceneIndexWriter::setMinMergeDocs(qint32 value) +{ + d->writer->setMinMergeDocs(int32_t(value)); +} + +qint32 QCLuceneIndexWriter::getMaxMergeDocs() const +{ + return qint32(d->writer->getMaxMergeDocs()); +} + +void QCLuceneIndexWriter::setMaxMergeDocs(qint32 value) +{ + d->writer->setMaxMergeDocs(int32_t(value)); +} + +bool QCLuceneIndexWriter::getUseCompoundFile() const +{ + return d->writer->getUseCompoundFile(); +} + +void QCLuceneIndexWriter::setUseCompoundFile(bool value) +{ + d->writer->setUseCompoundFile(value); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qindexwriter_p.h b/src/assistant/lib/fulltextsearch/qindexwriter_p.h new file mode 100644 index 0000000..1f9c861 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qindexwriter_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QINDEXWRITER_P_H +#define QINDEXWRITER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qanalyzer_p.h" +#include "qdocument_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include + +CL_NS_DEF(index) + class IndexWriter; +CL_NS_END +CL_NS_USE(index) + +QT_BEGIN_NAMESPACE + +class QCLuceneIndexReader; + +class QHELP_EXPORT QCLuceneIndexWriterPrivate : public QSharedData +{ +public: + QCLuceneIndexWriterPrivate(); + QCLuceneIndexWriterPrivate(const QCLuceneIndexWriterPrivate &other); + + ~QCLuceneIndexWriterPrivate(); + + IndexWriter *writer; + bool deleteCLuceneIndexWriter; + +private: + QCLuceneIndexWriterPrivate &operator=(const QCLuceneIndexWriterPrivate &other); +}; + +class QHELP_EXPORT QCLuceneIndexWriter +{ +public: + enum { + DEFAULT_MERGE_FACTOR = 10, + COMMIT_LOCK_TIMEOUT = 10000, + DEFAULT_MAX_BUFFERED_DOCS = 10, + DEFAULT_MAX_FIELD_LENGTH = 10000, + DEFAULT_TERM_INDEX_INTERVAL = 128, + DEFAULT_MAX_MERGE_DOCS = 0x7FFFFFFFL + }; + + QCLuceneIndexWriter(const QString &path, QCLuceneAnalyzer &analyzer, + bool create, bool closeDir = true); + virtual ~QCLuceneIndexWriter(); + + void close(); + void optimize(); + qint32 docCount(); + QCLuceneAnalyzer getAnalyzer(); + + void addIndexes(const QList &readers); + void addDocument(QCLuceneDocument &doc, QCLuceneAnalyzer &analyzer); + + qint32 getMaxFieldLength() const; + void setMaxFieldLength(qint32 value); + + qint32 getMaxBufferedDocs() const; + void setMaxBufferedDocs(qint32 value); + + qint64 getWriteLockTimeout() const; + void setWriteLockTimeout(qint64 writeLockTimeout); + + qint64 getCommitLockTimeout() const; + void setCommitLockTimeout(qint64 commitLockTimeout); + + qint32 getMergeFactor() const; + void setMergeFactor(qint32 value); + + qint32 getTermIndexInterval() const; + void setTermIndexInterval(qint32 interval); + + qint32 getMinMergeDocs() const; + void setMinMergeDocs(qint32 value); + + qint32 getMaxMergeDocs() const; + void setMaxMergeDocs(qint32 value); + + bool getUseCompoundFile() const; + void setUseCompoundFile(bool value); + +protected: + QSharedDataPointer d; + +private: + QCLuceneAnalyzer analyzer; +}; + +QT_END_NAMESPACE + +#endif // QINDEXWRITER_P_H diff --git a/src/assistant/lib/fulltextsearch/qquery.cpp b/src/assistant/lib/fulltextsearch/qquery.cpp new file mode 100644 index 0000000..170341c --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qquery.cpp @@ -0,0 +1,358 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qquery_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneQueryPrivate::QCLuceneQueryPrivate() + : QSharedData() +{ + query = 0; + deleteCLuceneQuery = true; +} + +QCLuceneQueryPrivate::QCLuceneQueryPrivate(const QCLuceneQueryPrivate &other) + : QSharedData() +{ + query = _CL_POINTER(other.query); + deleteCLuceneQuery = other.deleteCLuceneQuery; +} + +QCLuceneQueryPrivate::~QCLuceneQueryPrivate() +{ + if (deleteCLuceneQuery) + _CLDECDELETE(query); +} + + +QCLuceneQuery::QCLuceneQuery() + : d(new QCLuceneQueryPrivate()) +{ + // nothing todo, private +} + +QCLuceneQuery::~QCLuceneQuery() +{ + // nothing todo +} + +void QCLuceneQuery::setBoost(qreal boost) +{ + d->query->setBoost(qreal(boost)); +} + +qreal QCLuceneQuery::getBoost() const +{ + return qreal(d->query->getBoost()); +} + +QString QCLuceneQuery::getQueryName() const +{ + return TCharToQString(d->query->getQueryName()); +} + +bool QCLuceneQuery::instanceOf(const QString &other) const +{ + if (other == getQueryName()) + return true; + + return false; +} + +QString QCLuceneQuery::toString(const QString &field) const +{ + TCHAR *fieldName = QStringToTChar(field); + QString retValue = TCharToQString(d->query->toString(fieldName)); + delete [] fieldName; + + return retValue; +} + +quint32 QCLuceneQuery::hashCode() const +{ + return quint32(d->query->hashCode()); +} + +QString QCLuceneQuery::toString() const +{ + return TCharToQString(d->query->toString()); +} + +bool QCLuceneQuery::equals(const QCLuceneQuery &other) const +{ + return d->query->equals(other.d->query); +} + + +QCLucenePrefixQuery::QCLucenePrefixQuery(const QCLuceneTerm &prefix) + : QCLuceneQuery() + , prefix(prefix) +{ + d->query = new lucene::search::PrefixQuery(prefix.d->term); +} + +QCLucenePrefixQuery::~QCLucenePrefixQuery() +{ + // nothing todo +} + +QString QCLucenePrefixQuery::getClassName() +{ + return TCharToQString(lucene::search::PrefixQuery::getClassName()); +} + +QCLuceneTerm QCLucenePrefixQuery::getPrefix() const +{ + return prefix; +} + + +QCLuceneRangeQuery::QCLuceneRangeQuery(const QCLuceneTerm &lowerTerm, + const QCLuceneTerm &upperTerm, + bool inclusive) + : QCLuceneQuery() + , lowerTerm(lowerTerm) + , upperTerm(upperTerm) +{ + d->query = new lucene::search::RangeQuery(lowerTerm.d->term, + upperTerm.d->term, inclusive); +} + +QCLuceneRangeQuery::~QCLuceneRangeQuery() +{ + // nothing todo +} + +QString QCLuceneRangeQuery::getClassName() +{ + return TCharToQString(lucene::search::RangeQuery::getClassName()); +} + +QCLuceneTerm QCLuceneRangeQuery::getLowerTerm() const +{ + return lowerTerm; +} + +QCLuceneTerm QCLuceneRangeQuery::getUpperTerm() const +{ + return upperTerm; +} + +bool QCLuceneRangeQuery::isInclusive() const +{ + lucene::search::RangeQuery *query = + static_cast (d->query); + + if (query == 0) + return false; + + return query->isInclusive(); +} + +QString QCLuceneRangeQuery::getField() const +{ + lucene::search::RangeQuery *query = + static_cast (d->query); + + if (query == 0) + return QString(); + + return TCharToQString(query->getField()); +} + + +QCLuceneTermQuery::QCLuceneTermQuery(const QCLuceneTerm &term) + : QCLuceneQuery() + , term(term) +{ + d->query = new lucene::search::TermQuery(term.d->term); +} + +QCLuceneTermQuery::~QCLuceneTermQuery() +{ + // nothing todo +} + +QString QCLuceneTermQuery::getClassName() +{ + return TCharToQString(lucene::search::TermQuery::getClassName()); +} + +QCLuceneTerm QCLuceneTermQuery::getTerm() const +{ + return term; +} + + +QCLuceneBooleanQuery::QCLuceneBooleanQuery() + : QCLuceneQuery() +{ + d->query = new lucene::search::BooleanQuery(); +} + +QCLuceneBooleanQuery::~QCLuceneBooleanQuery() +{ + qDeleteAll(queries); +} + +QString QCLuceneBooleanQuery::getClassName() +{ + return TCharToQString(lucene::search::BooleanQuery::getClassName()); +} + +quint32 QCLuceneBooleanQuery::getClauseCount() const +{ + lucene::search::BooleanQuery *query = + static_cast (d->query); + + if (query == 0) + return 1024; + + return quint32(query->getClauseCount()); +} + +quint32 QCLuceneBooleanQuery::getMaxClauseCount() const +{ + lucene::search::BooleanQuery *query = + static_cast (d->query); + + if (query == 0) + return 1024; + + return quint32(query->getMaxClauseCount()); +} + +void QCLuceneBooleanQuery::setMaxClauseCount(quint32 maxClauseCount) +{ + lucene::search::BooleanQuery *query = + static_cast (d->query); + + if (query == 0) + return; + + query->setMaxClauseCount(size_t(maxClauseCount)); +} + +void QCLuceneBooleanQuery::add(QCLuceneQuery *query, bool required, bool prohibited) +{ + add(query, false, required, prohibited); +} + +void QCLuceneBooleanQuery::add(QCLuceneQuery *query, bool delQuery, + bool required, bool prohibited) +{ + lucene::search::BooleanQuery *booleanQuery = + static_cast (d->query); + + if (booleanQuery == 0) + return; + + booleanQuery->add(query->d->query, delQuery, required, prohibited); + + if (delQuery) { + queries.append(query); + query->d->deleteCLuceneQuery = false; + } +} + + +QCLucenePhraseQuery::QCLucenePhraseQuery() + : QCLuceneQuery() +{ + d->query = new lucene::search::PhraseQuery(); +} + +QCLucenePhraseQuery::~QCLucenePhraseQuery() +{ + termList.clear(); +} + +QString QCLucenePhraseQuery::getClassName() +{ + return TCharToQString(lucene::search::RangeQuery::getClassName()); +} + +qint32 QCLucenePhraseQuery::getSlop() const +{ + lucene::search::PhraseQuery *phraseQuery = + static_cast (d->query); + + if (phraseQuery == 0) + return 0; + + return qint32(phraseQuery->getSlop()); +} + +void QCLucenePhraseQuery::setSlop(const qint32 slop) +{ + lucene::search::PhraseQuery *phraseQuery = + static_cast (d->query); + + if (phraseQuery == 0) + return; + + phraseQuery->setSlop(int32_t(slop)); +} + +void QCLucenePhraseQuery::addTerm(const QCLuceneTerm &term) +{ + lucene::search::PhraseQuery *phraseQuery = + static_cast (d->query); + + if (phraseQuery == 0) + return; + + termList.append(term); + phraseQuery->add(term.d->term); +} + +void QCLucenePhraseQuery::addTerm(const QCLuceneTerm &term, qint32 position) +{ + lucene::search::PhraseQuery *phraseQuery = + static_cast (d->query); + + if (phraseQuery == 0) + return; + + termList.insert(position, term); + phraseQuery->add(term.d->term, int32_t(position)); + +} + +QString QCLucenePhraseQuery::getFieldName() const +{ + lucene::search::PhraseQuery *phraseQuery = + static_cast (d->query); + + if (phraseQuery == 0) + return QString(); + + return TCharToQString(phraseQuery->getFieldName()); +} + +QList QCLucenePhraseQuery::getTerms() const +{ + return termList; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qquery_p.h b/src/assistant/lib/fulltextsearch/qquery_p.h new file mode 100644 index 0000000..3268b7c --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qquery_p.h @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QQUERY_P_H +#define QQUERY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qterm_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include +#include + +CL_NS_DEF(search) + class Query; +CL_NS_END +CL_NS_USE(search) + +QT_BEGIN_NAMESPACE + +class QCLuceneHits; +class QCLuceneTermQuery; +class QCLuceneRangeQuery; +class QCLuceneQueryParser; +class QCLucenePrefixQuery; +class QCLuceneBooleanQuery; +class QCLucenePhraseQuery; + +class QHELP_EXPORT QCLuceneQueryPrivate : public QSharedData +{ +public: + QCLuceneQueryPrivate(); + QCLuceneQueryPrivate(const QCLuceneQueryPrivate &other); + + ~QCLuceneQueryPrivate(); + + Query *query; + bool deleteCLuceneQuery; + +private: + QCLuceneQueryPrivate &operator=(const QCLuceneQueryPrivate &other); +}; + +class QHELP_EXPORT QCLuceneQuery +{ +public: + virtual ~QCLuceneQuery(); + + void setBoost(qreal boost); + qreal getBoost() const; + QString getQueryName() const; + bool instanceOf(const QString &other) const; + QString toString(const QString &field) const; + quint32 hashCode() const; + QString toString() const; + bool equals(const QCLuceneQuery &other) const; + +protected: + friend class QCLuceneHits; + friend class QCLuceneTermQuery; + friend class QCLuceneRangeQuery; + friend class QCLucenePrefixQuery; + friend class QCLuceneQueryParser; + friend class QCLuceneBooleanQuery; + friend class QCLucenePhraseQuery; + QSharedDataPointer d; + +private: + QCLuceneQuery(); +}; + +class QHELP_EXPORT QCLucenePrefixQuery : public QCLuceneQuery +{ +public: + QCLucenePrefixQuery(const QCLuceneTerm &prefix); + ~QCLucenePrefixQuery(); + + static QString getClassName(); + + QCLuceneTerm getPrefix() const; + +private: + QCLuceneTerm prefix; +}; + +class QHELP_EXPORT QCLuceneRangeQuery : public QCLuceneQuery +{ +public: + QCLuceneRangeQuery(const QCLuceneTerm &lowerTerm, + const QCLuceneTerm &upperTerm, bool inclusive); + ~QCLuceneRangeQuery(); + + static QString getClassName(); + + QCLuceneTerm getLowerTerm() const; + QCLuceneTerm getUpperTerm() const; + + bool isInclusive() const; + QString getField() const; + +private: + QCLuceneTerm lowerTerm; + QCLuceneTerm upperTerm; +}; + +class QHELP_EXPORT QCLuceneTermQuery : public QCLuceneQuery +{ +public: + QCLuceneTermQuery(const QCLuceneTerm &term); + ~QCLuceneTermQuery(); + + static QString getClassName(); + + QCLuceneTerm getTerm() const; + +private: + QCLuceneTerm term; +}; + +class QHELP_EXPORT QCLuceneBooleanQuery : public QCLuceneQuery +{ +public: + QCLuceneBooleanQuery(); + ~QCLuceneBooleanQuery(); + + static QString getClassName(); + + quint32 getClauseCount() const; + quint32 getMaxClauseCount() const; + void setMaxClauseCount(quint32 maxClauseCount); + + void add(QCLuceneQuery *query, bool required, bool prohibited); + void add(QCLuceneQuery *query, bool delQuery, bool required, bool prohibited); + +private: + QList queries; +}; + +class QHELP_EXPORT QCLucenePhraseQuery : public QCLuceneQuery +{ +public: + QCLucenePhraseQuery(); + ~QCLucenePhraseQuery(); + + static QString getClassName(); + + qint32 getSlop() const; + void setSlop(const qint32 slop); + + void addTerm(const QCLuceneTerm &term); + void addTerm(const QCLuceneTerm &term, qint32 position); + + QString getFieldName() const; + QList getTerms() const; + +private: + QList termList; +}; + +QT_END_NAMESPACE + +#endif // QQUERY_P_H diff --git a/src/assistant/lib/fulltextsearch/qqueryparser.cpp b/src/assistant/lib/fulltextsearch/qqueryparser.cpp new file mode 100644 index 0000000..f306a04 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qqueryparser.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qqueryparser_p.h" +#include "qquery_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneQueryParserPrivate::QCLuceneQueryParserPrivate() + : QSharedData() +{ + queryParser = 0; + deleteCLuceneQueryParser = true; +} + +QCLuceneQueryParserPrivate::QCLuceneQueryParserPrivate(const QCLuceneQueryParserPrivate &other) + : QSharedData() +{ + queryParser = _CL_POINTER(other.queryParser); + deleteCLuceneQueryParser = other.deleteCLuceneQueryParser; +} + +QCLuceneQueryParserPrivate::~QCLuceneQueryParserPrivate() +{ + if (deleteCLuceneQueryParser) + _CLDECDELETE(queryParser); +} + + +QCLuceneQueryParser::QCLuceneQueryParser(const QString &field, + QCLuceneAnalyzer &analyzer) + : d(new QCLuceneQueryParserPrivate()) + , field(field) + , analyzer(analyzer) +{ + TCHAR *fieldName = QStringToTChar(field); + + d->queryParser = new lucene::queryParser::QueryParser(fieldName, + analyzer.d->analyzer); + + delete [] fieldName; +} + +QCLuceneQueryParser::~QCLuceneQueryParser() +{ + // nothing todo +} + +QCLuceneQuery* QCLuceneQueryParser::parse(const QString &query) +{ + TCHAR *string = QStringToTChar(query); + + QCLuceneQuery *retValue = 0; + lucene::search::Query* q = d->queryParser->parse(string); + if (q) { + retValue = new QCLuceneQuery(); + retValue->d->query = q; + } + + delete [] string; + return retValue; +} + +QCLuceneQuery* QCLuceneQueryParser::parse(QCLuceneReader &reader) +{ + QCLuceneQuery *retValue = 0; + lucene::search::Query* q = d->queryParser->parse(reader.d->reader); + if (q) { + retValue = new QCLuceneQuery(); + retValue->d->query = q; + } + + return retValue; +} + +QCLuceneQuery* QCLuceneQueryParser::parse(const QString &query, const QString &field, + QCLuceneAnalyzer &analyzer) +{ + QCLuceneQueryParser parser(field, analyzer); + return parser.parse(query); +} + +QCLuceneAnalyzer QCLuceneQueryParser::getAnalyzer() +{ + return analyzer; +} + +QString QCLuceneQueryParser::getField() +{ + return field; +} + + +QCLuceneMultiFieldQueryParser::QCLuceneMultiFieldQueryParser( + const QStringList &fieldList, QCLuceneAnalyzer &analyzer) + : QCLuceneQueryParser(QLatin1String(""), analyzer) +{ + Q_UNUSED(fieldList) +} + +QCLuceneMultiFieldQueryParser::~QCLuceneMultiFieldQueryParser() +{ + // nothing todo +} + +QCLuceneQuery* QCLuceneMultiFieldQueryParser::parse(const QString &query, + const QStringList &fieldList, + QCLuceneAnalyzer &analyzer) +{ + QCLuceneBooleanQuery *retValue = new QCLuceneBooleanQuery(); + foreach (const QString &field, fieldList) { + QCLuceneQuery *q = QCLuceneQueryParser::parse(query, field, analyzer); + if (!q) { + delete retValue; + retValue = 0; break; + } else { + retValue->add(q, true, false, false); + } + } + + return retValue; +} + +QCLuceneQuery* QCLuceneMultiFieldQueryParser::parse(const QString &query, + const QStringList &fieldList, + QList flags, + QCLuceneAnalyzer &analyzer) +{ + QCLuceneBooleanQuery *retValue = new QCLuceneBooleanQuery(); + qint32 i = 0; + foreach (const QString &field, fieldList) { + QCLuceneQuery *q = QCLuceneQueryParser::parse(query, field, analyzer); + if (q) { + qint32 flag = flags.at(i); + switch (flag) { + case QCLuceneMultiFieldQueryParser::REQUIRED_FIELD: { + retValue->add(q, true, true, false); + } break; + + case QCLuceneMultiFieldQueryParser::PROHIBITED_FIELD: { + retValue->add(q, true, false, true); + } break; + + default: { + retValue->add(q, true, false, false); + } break; + } + + ++i; + } else { + delete retValue; + retValue = 0; break; + } + } + return retValue; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qqueryparser_p.h b/src/assistant/lib/fulltextsearch/qqueryparser_p.h new file mode 100644 index 0000000..e1b8c74 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qqueryparser_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QQUERYPARSER_P_H +#define QQUERYPARSER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qreader_p.h" +#include "qanalyzer_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include +#include + +CL_NS_DEF(queryParser) + class QueryParser; +CL_NS_END +CL_NS_USE(queryParser) + +QT_BEGIN_NAMESPACE + +class QCLuceneQuery; +class QCLuceneMultiFieldQueryParser; + +class QHELP_EXPORT QCLuceneQueryParserPrivate : public QSharedData +{ +public: + QCLuceneQueryParserPrivate(); + QCLuceneQueryParserPrivate(const QCLuceneQueryParserPrivate &other); + + ~QCLuceneQueryParserPrivate(); + + QueryParser *queryParser; + bool deleteCLuceneQueryParser; + +private: + QCLuceneQueryParserPrivate &operator=(const QCLuceneQueryParserPrivate &other); +}; + +class QHELP_EXPORT QCLuceneQueryParser +{ +public: + QCLuceneQueryParser(const QString &field, QCLuceneAnalyzer &analyzer); + virtual ~QCLuceneQueryParser(); + + QCLuceneQuery* parse(const QString &query); + QCLuceneQuery* parse(QCLuceneReader &reader); + static QCLuceneQuery* parse(const QString &query, const QString &field, + QCLuceneAnalyzer &analyzer); + QCLuceneAnalyzer getAnalyzer(); + QString getField(); + +protected: + friend class QCLuceneMultiFieldQueryParser; + QSharedDataPointer d; + +private: + QString field; + QCLuceneAnalyzer analyzer; +}; + +class QHELP_EXPORT QCLuceneMultiFieldQueryParser : public QCLuceneQueryParser +{ +public: + enum FieldFlags { + NORMAL_FIELD = 0, + REQUIRED_FIELD = 1, + PROHIBITED_FIELD = 2 + }; + + QCLuceneMultiFieldQueryParser(const QStringList &fieldList, + QCLuceneAnalyzer &analyzer); + ~QCLuceneMultiFieldQueryParser(); + + static QCLuceneQuery *parse(const QString &query, const QStringList &fieldList, + QCLuceneAnalyzer &analyzer); + static QCLuceneQuery *parse(const QString &query, const QStringList &fieldList, + QList flags, QCLuceneAnalyzer &analyzer); +}; + +QT_END_NAMESPACE + +#endif // QQUERYPARSER_P_H diff --git a/src/assistant/lib/fulltextsearch/qreader.cpp b/src/assistant/lib/fulltextsearch/qreader.cpp new file mode 100644 index 0000000..0a8b7ac --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qreader.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qreader_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneReaderPrivate::QCLuceneReaderPrivate() + : QSharedData() +{ + reader = 0; + deleteCLuceneReader = true; +} + +QCLuceneReaderPrivate::QCLuceneReaderPrivate(const QCLuceneReaderPrivate &other) + : QSharedData() +{ + reader = _CL_POINTER(other.reader); + deleteCLuceneReader = other.deleteCLuceneReader; +} + +QCLuceneReaderPrivate::~QCLuceneReaderPrivate() +{ + if (deleteCLuceneReader) + _CLDECDELETE(reader); +} + +QCLuceneReader::QCLuceneReader() + : d(new QCLuceneReaderPrivate()) +{ + // nothing todo +} + +QCLuceneReader::~QCLuceneReader() +{ + // nothing todo +} + + +QCLuceneStringReader::QCLuceneStringReader(const QString &value) + : QCLuceneReader() + , string(QStringToTChar(value)) +{ + d->reader = new lucene::util::StringReader(string); +} + +QCLuceneStringReader::QCLuceneStringReader(const QString &value, qint32 length) + : QCLuceneReader() + , string(QStringToTChar(value)) +{ + d->reader = new lucene::util::StringReader(string, int32_t(length)); +} + +QCLuceneStringReader::QCLuceneStringReader(const QString &value, qint32 length, + bool copyData) + : QCLuceneReader() + , string(QStringToTChar(value)) +{ + d->reader = new lucene::util::StringReader(string, int32_t(length), copyData); +} + +QCLuceneStringReader::~QCLuceneStringReader() +{ + delete [] string; +} + + +QCLuceneFileReader::QCLuceneFileReader(const QString &path, const QString &encoding, + qint32 cacheLength, qint32 cacheBuffer) + : QCLuceneReader() +{ + const QByteArray tmpPath = path.toLocal8Bit(); + const QByteArray tmpEncoding = encoding.toAscii(); + d->reader = new lucene::util::FileReader(tmpPath.constData(), + tmpEncoding.constData(), int32_t(cacheLength), int32_t(cacheBuffer)); +} + +QCLuceneFileReader::~QCLuceneFileReader() +{ + // nothing todo +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qreader_p.h b/src/assistant/lib/fulltextsearch/qreader_p.h new file mode 100644 index 0000000..e24e9d8 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qreader_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QREADER_P_H +#define QREADER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qclucene_global_p.h" + +#include +#include +#include + +CL_NS_DEF(util) + class Reader; +CL_NS_END +CL_NS_USE(util) + +QT_BEGIN_NAMESPACE + +class QCLuceneField; +class QCLuceneAnalyzer; +class QCLuceneDocument; +class QCLuceneQueryParser; +class QCLuceneStandardTokenizer; + +class QHELP_EXPORT QCLuceneReaderPrivate : public QSharedData +{ +public: + QCLuceneReaderPrivate(); + QCLuceneReaderPrivate(const QCLuceneReaderPrivate &other); + + ~QCLuceneReaderPrivate(); + + Reader* reader; + bool deleteCLuceneReader; + +private: + QCLuceneReaderPrivate &operator=(const QCLuceneReaderPrivate &other); +}; + +class QHELP_EXPORT QCLuceneReader +{ +public: + QCLuceneReader(); + virtual ~QCLuceneReader(); + +protected: + friend class QCLuceneField; + friend class QCLuceneAnalyzer; + friend class QCLuceneDocument; + friend class QCLuceneQueryParser; + friend class QCLuceneStandardTokenizer; + QSharedDataPointer d; +}; + +class QCLuceneStringReader : public QCLuceneReader +{ +public: + QCLuceneStringReader(const QString &value); + QCLuceneStringReader(const QString &value, qint32 length); + QCLuceneStringReader(const QString &value, qint32 length, bool copyData); + + ~QCLuceneStringReader(); + +private: + TCHAR *string; +}; + +class QHELP_EXPORT QCLuceneFileReader : public QCLuceneReader +{ +public: + QCLuceneFileReader(const QString &path, const QString &encoding, + qint32 cacheLength = 13, qint32 cacheBuffer = 14); + ~QCLuceneFileReader(); +}; + +QT_END_NAMESPACE + +#endif // QREADER_P_H diff --git a/src/assistant/lib/fulltextsearch/qsearchable.cpp b/src/assistant/lib/fulltextsearch/qsearchable.cpp new file mode 100644 index 0000000..508fc05 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qsearchable.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qsearchable_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneSearchablePrivate::QCLuceneSearchablePrivate() + : QSharedData() +{ + searchable = 0; + deleteCLuceneSearchable = true; +} + +QCLuceneSearchablePrivate::QCLuceneSearchablePrivate(const QCLuceneSearchablePrivate &other) + : QSharedData() +{ + searchable = _CL_POINTER(other.searchable); + deleteCLuceneSearchable = other.deleteCLuceneSearchable; +} + +QCLuceneSearchablePrivate::~QCLuceneSearchablePrivate() +{ + if (deleteCLuceneSearchable) + _CLDECDELETE(searchable); +} + + +QCLuceneSearchable::QCLuceneSearchable() + : d(new QCLuceneSearchablePrivate()) +{ + // nothing todo +} + +QCLuceneSearchable::~QCLuceneSearchable() +{ + // nothing todo +} + + +QCLuceneSearcher::QCLuceneSearcher() + : QCLuceneSearchable() +{ + // nothing todo +} + +QCLuceneSearcher::~QCLuceneSearcher() +{ + // nothing todo; +} + +QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query) +{ + return search(query, QCLuceneFilter()); +} + +QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query, + const QCLuceneFilter &filter) +{ + return QCLuceneHits(*this, query, filter); +} + +QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query, + const QCLuceneSort &sort) +{ + return QCLuceneHits(*this, query, QCLuceneFilter(), sort); +} + +QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query, + const QCLuceneFilter &filter, + const QCLuceneSort &sort) +{ + return QCLuceneHits(*this, query, filter, sort); +} + + +QCLuceneIndexSearcher::QCLuceneIndexSearcher(const QString &path) + : QCLuceneSearcher() +{ + lucene::search::IndexSearcher *searcher = + new lucene::search::IndexSearcher(path); + + reader.d->reader = searcher->getReader(); + reader.d->deleteCLuceneIndexReader = false; + + d->searchable = searcher; +} + +QCLuceneIndexSearcher::QCLuceneIndexSearcher(const QCLuceneIndexReader &reader) + : QCLuceneSearcher() + , reader(reader) +{ + d->searchable = new lucene::search::IndexSearcher(reader.d->reader); +} + +QCLuceneIndexSearcher::~QCLuceneIndexSearcher() +{ + // nothing todo +} + +void QCLuceneIndexSearcher::close() +{ + d->searchable->close(); +} + +qint32 QCLuceneIndexSearcher::maxDoc() const +{ + return qint32(d->searchable->maxDoc()); +} + +QCLuceneIndexReader QCLuceneIndexSearcher::getReader() +{ + return reader; +} + +bool QCLuceneIndexSearcher::doc(qint32 i, QCLuceneDocument &document) +{ + return d->searchable->doc(int32_t(i), document.d->document); +} + + +QCLuceneMultiSearcher::QCLuceneMultiSearcher(const QList searchables) +: QCLuceneSearcher() +{ + lucene::search::Searchable** list= + _CL_NEWARRAY(lucene::search::Searchable*, searchables.count()); + + d->searchable = new lucene::search::MultiSearcher(list); + + _CLDELETE_ARRAY(list); +} + +QCLuceneMultiSearcher::~QCLuceneMultiSearcher() +{ + // nothing todo +} + +void QCLuceneMultiSearcher::close() +{ + d->searchable->close(); +} + +qint32 QCLuceneMultiSearcher::maxDoc() const +{ + return qint32(d->searchable->maxDoc()); +} + +qint32 QCLuceneMultiSearcher::subDoc(qint32 index) const +{ + lucene::search::MultiSearcher *searcher = + static_cast (d->searchable); + + if (searcher == 0) + return 0; + + return qint32(searcher->subDoc(int32_t(index))); +} + +qint32 QCLuceneMultiSearcher::subSearcher(qint32 index) const +{ + lucene::search::MultiSearcher *searcher = + static_cast (d->searchable); + + if (searcher == 0) + return 0; + + return qint32(searcher->subSearcher(int32_t(index))); +} + +qint32 QCLuceneMultiSearcher::searcherIndex(qint32 index) const +{ + lucene::search::MultiSearcher *searcher = + static_cast (d->searchable); + + if (searcher == 0) + return 0; + + return qint32(searcher->searcherIndex(int32_t(index))); +} + +bool QCLuceneMultiSearcher::doc(qint32 i, QCLuceneDocument &document) +{ + return d->searchable->doc(int32_t(i), document.d->document); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qsearchable_p.h b/src/assistant/lib/fulltextsearch/qsearchable_p.h new file mode 100644 index 0000000..149cfb0 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qsearchable_p.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QSEARCHABLE_P_H +#define QSEARCHABLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhits_p.h" +#include "qsort_p.h" +#include "qquery_p.h" +#include "qfilter_p.h" +#include "qdocument_p.h" +#include "qindexreader_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include +#include + +CL_NS_DEF(search) + class Searcher; +CL_NS_END +CL_NS_USE(search) + +QT_BEGIN_NAMESPACE + +class QCLuceneHits; +class QCLuceneSearcher; +class QCLuceneIndexSearcher; +class QCLuceneMultiSearcher; + +class QHELP_EXPORT QCLuceneSearchablePrivate : public QSharedData +{ +public: + QCLuceneSearchablePrivate(); + QCLuceneSearchablePrivate(const QCLuceneSearchablePrivate &other); + + ~QCLuceneSearchablePrivate(); + + Searcher *searchable; + bool deleteCLuceneSearchable; + +private: + QCLuceneSearchablePrivate &operator=(const QCLuceneSearchablePrivate &other); +}; + +class QHELP_EXPORT QCLuceneSearchable +{ +public: + virtual ~QCLuceneSearchable(); + +protected: + friend class QCLuceneSearcher; + friend class QCLuceneIndexSearcher; + friend class QCLuceneMultiSearcher; + QSharedDataPointer d; + +private: + QCLuceneSearchable(); +}; + +class QHELP_EXPORT QCLuceneSearcher : public QCLuceneSearchable +{ +public: + QCLuceneSearcher(); + virtual ~QCLuceneSearcher(); + + QCLuceneHits search(const QCLuceneQuery &query); + QCLuceneHits search(const QCLuceneQuery &query, const QCLuceneFilter &filter); + QCLuceneHits search(const QCLuceneQuery &query, const QCLuceneSort &sort); + QCLuceneHits search(const QCLuceneQuery &query, const QCLuceneFilter &filter, + const QCLuceneSort &sort); + +protected: + friend class QCLuceneHits; +}; + +class QHELP_EXPORT QCLuceneIndexSearcher : public QCLuceneSearcher +{ +public: + QCLuceneIndexSearcher(const QString &path); + QCLuceneIndexSearcher(const QCLuceneIndexReader &reader); + ~QCLuceneIndexSearcher(); + + void close(); + qint32 maxDoc() const; + QCLuceneIndexReader getReader(); + bool doc(qint32 i, QCLuceneDocument &document); + +private: + QCLuceneIndexReader reader; +}; + +class QHELP_EXPORT QCLuceneMultiSearcher : public QCLuceneSearcher +{ +public: + QCLuceneMultiSearcher(const QList searchables); + ~QCLuceneMultiSearcher(); + + void close(); + qint32 maxDoc() const; + qint32 subDoc(qint32 index) const; + qint32 subSearcher(qint32 index) const; + qint32 searcherIndex(qint32 index) const; + bool doc(qint32 i, QCLuceneDocument &document); +}; + +QT_END_NAMESPACE + +#endif // QSEARCHABLE_P_H diff --git a/src/assistant/lib/fulltextsearch/qsort.cpp b/src/assistant/lib/fulltextsearch/qsort.cpp new file mode 100644 index 0000000..4dface0 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qsort.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qsort_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneSortPrivate::QCLuceneSortPrivate() + : QSharedData() +{ + sort = 0; + deleteCLuceneSort = true; +} + +QCLuceneSortPrivate::QCLuceneSortPrivate (const QCLuceneSortPrivate &other) + : QSharedData() +{ + sort = _CL_POINTER(other.sort); + deleteCLuceneSort = other.deleteCLuceneSort; +} + +QCLuceneSortPrivate::~QCLuceneSortPrivate() +{ + if (deleteCLuceneSort) + _CLDECDELETE(sort); +} + + +QCLuceneSort::QCLuceneSort() + : d(new QCLuceneSortPrivate()) +{ + d->sort = new lucene::search::Sort(); +} + +QCLuceneSort::QCLuceneSort(const QStringList &fieldNames) + : d(new QCLuceneSortPrivate()) +{ + d->sort = new lucene::search::Sort(); + setSort(fieldNames); +} + +QCLuceneSort::QCLuceneSort(const QString &field, bool reverse) + : d(new QCLuceneSortPrivate()) +{ + d->sort = new lucene::search::Sort(); + setSort(field, reverse); +} + +QCLuceneSort::~QCLuceneSort() +{ + // nothing todo +} + +QString QCLuceneSort::toString() const +{ + return TCharToQString(d->sort->toString()); +} + +void QCLuceneSort::setSort(const QStringList &fieldNames) +{ + TCHAR **nameArray = new TCHAR*[fieldNames.count()]; + for (int i = 0; i < fieldNames.count(); ++i) + nameArray[i] = QStringToTChar(fieldNames.at(i)); + + d->sort->setSort((const TCHAR**)nameArray); + + for (int i = 0; i < fieldNames.count(); ++i) + delete [] nameArray[i]; + delete [] nameArray; +} + +void QCLuceneSort::setSort(const QString &field, bool reverse) +{ + TCHAR *name = QStringToTChar(field); + d->sort->setSort(name, reverse); + delete [] name; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qsort_p.h b/src/assistant/lib/fulltextsearch/qsort_p.h new file mode 100644 index 0000000..5d9372b --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qsort_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QSORT_P_H +#define QSORT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qclucene_global_p.h" + +#include +#include +#include +#include + +CL_NS_DEF(search) + class Sort; +CL_NS_END +CL_NS_USE(search) + +QT_BEGIN_NAMESPACE + +class QCLuceneHits; +class QCLuceneField; + +class QHELP_EXPORT QCLuceneSortPrivate : public QSharedData +{ +public: + QCLuceneSortPrivate(); + QCLuceneSortPrivate (const QCLuceneSortPrivate &other); + + ~QCLuceneSortPrivate(); + + Sort *sort; + bool deleteCLuceneSort; + +private: + QCLuceneSortPrivate &operator=(const QCLuceneSortPrivate &other); +}; + +class QHELP_EXPORT QCLuceneSort +{ +public: + QCLuceneSort(); + explicit QCLuceneSort(const QStringList &fieldNames); + explicit QCLuceneSort(const QString &field, bool reverse = false); + + virtual ~QCLuceneSort(); + + QString toString() const; + void setSort(const QStringList &fieldNames); + void setSort(const QString &field, bool reverse = false); + +protected: + friend class QCLuceneHits; + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +#endif // QSORT_P_H diff --git a/src/assistant/lib/fulltextsearch/qterm.cpp b/src/assistant/lib/fulltextsearch/qterm.cpp new file mode 100644 index 0000000..eeebf53 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qterm.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qterm_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneTermPrivate::QCLuceneTermPrivate() + : QSharedData() +{ + term = 0; + deleteCLuceneTerm = true; +} + +QCLuceneTermPrivate::QCLuceneTermPrivate(const QCLuceneTermPrivate &other) + : QSharedData() +{ + term = _CL_POINTER(other.term); + deleteCLuceneTerm = other.deleteCLuceneTerm; +} + +QCLuceneTermPrivate::~QCLuceneTermPrivate() +{ + if (deleteCLuceneTerm) + _CLDECDELETE(term); +} + + +QCLuceneTerm::QCLuceneTerm() + : d(new QCLuceneTermPrivate()) +{ + d->term = new lucene::index::Term(); +} + +QCLuceneTerm::QCLuceneTerm(const QString &field, const QString &text) + : d(new QCLuceneTermPrivate()) +{ + TCHAR *fieldName = QStringToTChar(field); + TCHAR *termText = QStringToTChar(text); + + d->term = new lucene::index::Term(fieldName, termText); + + delete [] fieldName; + delete [] termText; +} + +QCLuceneTerm::QCLuceneTerm(const QCLuceneTerm &fieldTerm, const QString &text) + : d(new QCLuceneTermPrivate()) +{ + TCHAR *termText = QStringToTChar(text); + d->term = new lucene::index::Term(fieldTerm.d->term, termText); + delete [] termText; +} + +QCLuceneTerm::~QCLuceneTerm() +{ + // nothing todo +} + +QString QCLuceneTerm::field() const +{ + return TCharToQString(d->term->field()); +} + +QString QCLuceneTerm::text() const +{ + return TCharToQString(d->term->text()); +} + +void QCLuceneTerm::set(const QString &field, const QString &text) +{ + set(field, text, true); +} + +void QCLuceneTerm::set(const QCLuceneTerm &fieldTerm, const QString &text) +{ + set(fieldTerm.field(), text, false); +} + +void QCLuceneTerm::set(const QString &field, const QString &text, bool internField) +{ + TCHAR *fieldName = QStringToTChar(field); + TCHAR *termText = QStringToTChar(text); + + d->term->set(fieldName, termText, internField); + + delete [] fieldName; + delete [] termText; +} + +bool QCLuceneTerm::equals(const QCLuceneTerm &other) const +{ + return d->term->equals(other.d->term); +} + +qint32 QCLuceneTerm::compareTo(const QCLuceneTerm &other) const +{ + return quint32(d->term->compareTo(other.d->term)); +} + +QString QCLuceneTerm::toString() const +{ + return TCharToQString(d->term->toString()); +} + +quint32 QCLuceneTerm::hashCode() const +{ + return quint32(d->term->hashCode()); +} + +quint32 QCLuceneTerm::textLength() const +{ + return quint32(d->term->textLength()); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qterm_p.h b/src/assistant/lib/fulltextsearch/qterm_p.h new file mode 100644 index 0000000..5b981dc --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qterm_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QTERM_P_H +#define QTERM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qclucene_global_p.h" + +#include +#include +#include + +CL_NS_DEF(index) + class Term; +CL_NS_END +CL_NS_USE(index) + +QT_BEGIN_NAMESPACE + +class QCLuceneTermQuery; +class QCLuceneRangeQuery; +class QCLucenePrefixQuery; +class QCLuceneIndexReader; +class QCLucenePhraseQuery; + +class QHELP_EXPORT QCLuceneTermPrivate : public QSharedData +{ +public: + QCLuceneTermPrivate(); + QCLuceneTermPrivate(const QCLuceneTermPrivate &other); + + ~QCLuceneTermPrivate(); + + Term *term; + bool deleteCLuceneTerm; + +private: + QCLuceneTermPrivate &operator=(const QCLuceneTermPrivate &other); +}; + +class QHELP_EXPORT QCLuceneTerm +{ +public: + QCLuceneTerm(); + QCLuceneTerm(const QString &field, const QString &text); + QCLuceneTerm(const QCLuceneTerm &fieldTerm, const QString &text); + + virtual ~QCLuceneTerm(); + + QString field() const; + QString text() const; + + void set(const QString &field, const QString &text); + void set(const QCLuceneTerm &fieldTerm, const QString &text); + void set(const QString &field, const QString &text, bool internField); + + bool equals(const QCLuceneTerm &other) const; + qint32 compareTo(const QCLuceneTerm &other) const; + + QString toString() const; + quint32 hashCode() const; + quint32 textLength() const; + +protected: + friend class QCLuceneTermQuery; + friend class QCLuceneRangeQuery; + friend class QCLucenePrefixQuery; + friend class QCLuceneIndexReader; + friend class QCLucenePhraseQuery; + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +#endif // QTERM_P_H diff --git a/src/assistant/lib/fulltextsearch/qtoken.cpp b/src/assistant/lib/fulltextsearch/qtoken.cpp new file mode 100644 index 0000000..537d9e6 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qtoken.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qtoken_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneTokenPrivate::QCLuceneTokenPrivate() + : QSharedData() +{ + token = 0; + deleteCLuceneToken = true; +} + +QCLuceneTokenPrivate::QCLuceneTokenPrivate(const QCLuceneTokenPrivate &other) + : QSharedData() +{ + token = _CL_POINTER(other.token); + deleteCLuceneToken = other.deleteCLuceneToken; +} + +QCLuceneTokenPrivate::~QCLuceneTokenPrivate() +{ + if (deleteCLuceneToken) + _CLDECDELETE(token); +} + + +QCLuceneToken::QCLuceneToken() + : d(new QCLuceneTokenPrivate()) + , tokenText(0) + , tokenType(0) +{ + d->token = new lucene::analysis::Token(); +} + +QCLuceneToken::QCLuceneToken(const QString &text, qint32 startOffset, + qint32 endOffset, const QString &defaultTyp) + : d(new QCLuceneTokenPrivate()) + , tokenText(QStringToTChar(text)) + , tokenType(QStringToTChar(defaultTyp)) +{ + d->token = new lucene::analysis::Token(tokenText, int32_t(startOffset), + int32_t(endOffset), tokenType); +} + +QCLuceneToken::~QCLuceneToken() +{ + delete [] tokenText; + delete [] tokenType; +} + +quint32 QCLuceneToken::bufferLength() const +{ + return quint32(d->token->bufferLength()); +} + +void QCLuceneToken::growBuffer(quint32 size) +{ + d->token->growBuffer(size_t(size)); +} + +qint32 QCLuceneToken::positionIncrement() const +{ + return qint32(d->token->getPositionIncrement()); +} + +void QCLuceneToken::setPositionIncrement(qint32 positionIncrement) +{ + d->token->setPositionIncrement(int32_t(positionIncrement)); +} + +QString QCLuceneToken::termText() const +{ + return TCharToQString(d->token->termText()); +} + +void QCLuceneToken::setTermText(const QString &text) +{ + delete [] tokenText; + tokenText = QStringToTChar(text); + d->token->setText(tokenText); +} + +quint32 QCLuceneToken::termTextLength() const +{ + return quint32(d->token->termTextLength()); +} + +void QCLuceneToken::resetTermTextLength() const +{ + d->token->resetTermTextLen(); +} + +qint32 QCLuceneToken::startOffset() const +{ + return quint32(d->token->startOffset()); +} + +void QCLuceneToken::setStartOffset(qint32 value) +{ + d->token->setStartOffset(int32_t(value)); +} + +qint32 QCLuceneToken::endOffset() const +{ + return quint32(d->token->endOffset()); +} + +void QCLuceneToken::setEndOffset(qint32 value) +{ + d->token->setEndOffset(int32_t(value)); +} + +QString QCLuceneToken::type() const +{ + return TCharToQString(d->token->type()); +} + +void QCLuceneToken::setType(const QString &type) +{ + delete [] tokenType; + tokenType = QStringToTChar(type); + d->token->setType(tokenType); +} + +QString QCLuceneToken::toString() const +{ + return TCharToQString(d->token->toString()); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qtoken_p.h b/src/assistant/lib/fulltextsearch/qtoken_p.h new file mode 100644 index 0000000..f3d25c4 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qtoken_p.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QTOKEN_P_H +#define QTOKEN_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qclucene_global_p.h" + +#include +#include +#include + +CL_NS_DEF(analysis) + class Token; +CL_NS_END +CL_NS_USE(analysis) + +QT_BEGIN_NAMESPACE + +class QCLuceneTokenizer; +class QCLuceneTokenStream; +class QCLuceneStandardTokenizer; + +class QHELP_EXPORT QCLuceneTokenPrivate : public QSharedData +{ +public: + QCLuceneTokenPrivate(); + QCLuceneTokenPrivate(const QCLuceneTokenPrivate &other); + + ~QCLuceneTokenPrivate(); + + Token *token; + bool deleteCLuceneToken; + +private: + QCLuceneTokenPrivate &operator=(const QCLuceneTokenPrivate &other); +}; + +class QHELP_EXPORT QCLuceneToken +{ +public: + QCLuceneToken(); + QCLuceneToken(const QString &text, qint32 startOffset, + qint32 endOffset, const QString &defaultTyp = QLatin1String("word")); + + virtual ~QCLuceneToken(); + + void set(const QString &text, qint32 startOffset, + qint32 endOffset, const QString &defaultTyp = QLatin1String("word")); + + quint32 bufferLength() const; + void growBuffer(quint32 size); + + qint32 positionIncrement() const; + void setPositionIncrement(qint32 positionIncrement); + + QString termText() const; + void setTermText(const QString &text); + + quint32 termTextLength() const; + void resetTermTextLength() const; + + qint32 startOffset() const; + void setStartOffset(qint32 value); + + qint32 endOffset() const; + void setEndOffset(qint32 value); + + QString type() const; + void setType(const QString &type); + + QString toString() const; + +protected: + friend class QCLuceneTokenizer; + friend class QCLuceneTokenStream; + friend class QCLuceneStandardTokenizer; + QSharedDataPointer d; + +private: + TCHAR *tokenText; + TCHAR *tokenType; +}; + +QT_END_NAMESPACE + +#endif // QTOKEN_P_H diff --git a/src/assistant/lib/fulltextsearch/qtokenizer.cpp b/src/assistant/lib/fulltextsearch/qtokenizer.cpp new file mode 100644 index 0000000..8a79b21 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qtokenizer.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qtokenizer_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneTokenizer::QCLuceneTokenizer() + : QCLuceneTokenStream() +{ + // nothing todo +} + +QCLuceneTokenizer::QCLuceneTokenizer(const QCLuceneReader &reader) + : QCLuceneTokenStream() + , reader(reader) +{ + // nothing todo +} + +QCLuceneTokenizer::~QCLuceneTokenizer() +{ + close(); +} + +void QCLuceneTokenizer::close() +{ + d->tokenStream->close(); +} + +bool QCLuceneTokenizer::next(QCLuceneToken &token) +{ + return d->tokenStream->next(token.d->token); +} + + +QCLuceneStandardTokenizer::QCLuceneStandardTokenizer(const QCLuceneReader &reader) + : QCLuceneTokenizer(reader) +{ + d->tokenStream = + new lucene::analysis::standard::StandardTokenizer(reader.d->reader); +} + +QCLuceneStandardTokenizer::~QCLuceneStandardTokenizer() +{ + // nothing todo +} + +bool QCLuceneStandardTokenizer::readApostrophe(const QString &string, + QCLuceneToken &token) +{ + lucene::analysis::standard::StandardTokenizer *stdTokenizer = + static_cast (d->tokenStream); + + if (stdTokenizer == 0) + return false; + + TCHAR* value = QStringToTChar(string); + lucene::util::StringBuffer buffer(value); + bool retValue = stdTokenizer->ReadApostrophe(&buffer, token.d->token); + delete [] value; + + return retValue; +} + +bool QCLuceneStandardTokenizer::readAt(const QString &string, QCLuceneToken &token) +{ + lucene::analysis::standard::StandardTokenizer *stdTokenizer = + static_cast (d->tokenStream); + + if (stdTokenizer == 0) + return false; + + TCHAR* value = QStringToTChar(string); + lucene::util::StringBuffer buffer(value); + bool retValue = stdTokenizer->ReadAt(&buffer, token.d->token); + delete [] value; + + return retValue; +} + +bool QCLuceneStandardTokenizer::readCompany(const QString &string, + QCLuceneToken &token) +{ + lucene::analysis::standard::StandardTokenizer *stdTokenizer = + static_cast (d->tokenStream); + + if (stdTokenizer == 0) + return false; + + TCHAR* value = QStringToTChar(string); + lucene::util::StringBuffer buffer(value); + bool retValue = stdTokenizer->ReadCompany(&buffer, token.d->token); + delete [] value; + + return retValue; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qtokenizer_p.h b/src/assistant/lib/fulltextsearch/qtokenizer_p.h new file mode 100644 index 0000000..0c6e8ea --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qtokenizer_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QTOKENIZER_P_H +#define QTOKENIZER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qtoken_p.h" +#include "qreader_p.h" +#include "qtokenstream_p.h" +#include "qclucene_global_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QHELP_EXPORT QCLuceneTokenizer : public QCLuceneTokenStream +{ +public: + QCLuceneTokenizer(const QCLuceneReader &reader); + virtual ~QCLuceneTokenizer(); + + void close(); + bool next(QCLuceneToken &token); + +protected: + friend class QCLuceneStandardTokenizer; + +private: + QCLuceneTokenizer(); + QCLuceneReader reader; +}; + +class QHELP_EXPORT QCLuceneStandardTokenizer : public QCLuceneTokenizer +{ +public: + QCLuceneStandardTokenizer(const QCLuceneReader &reader); + ~QCLuceneStandardTokenizer(); + + bool readApostrophe(const QString &string, QCLuceneToken &token); + bool readAt(const QString &string, QCLuceneToken &token); + bool readCompany(const QString &string, QCLuceneToken &token); +}; + +class QCLuceneCharTokenizer : public QCLuceneTokenizer +{ + +}; + +class QCLuceneLetterTokenizer : public QCLuceneCharTokenizer +{ + +}; + +class QCLuceneLowerCaseTokenizer : public QCLuceneLetterTokenizer +{ + +}; + +class QCLuceneWhitespaceTokenizer : public QCLuceneCharTokenizer +{ + +}; + +class QCLuceneKeywordTokenizer : public QCLuceneTokenizer +{ + +}; + +QT_END_NAMESPACE + +#endif // QTOKENIZER_P_H diff --git a/src/assistant/lib/fulltextsearch/qtokenstream.cpp b/src/assistant/lib/fulltextsearch/qtokenstream.cpp new file mode 100644 index 0000000..337ebf1 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qtokenstream.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#include "qtokenstream_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QCLuceneTokenStreamPrivate::QCLuceneTokenStreamPrivate() + : QSharedData() +{ + tokenStream = 0; + deleteCLuceneTokenStream = true; +} + +QCLuceneTokenStreamPrivate::QCLuceneTokenStreamPrivate(const QCLuceneTokenStreamPrivate &other) + : QSharedData() +{ + tokenStream = _CL_POINTER(other.tokenStream); + deleteCLuceneTokenStream = other.deleteCLuceneTokenStream; +} + +QCLuceneTokenStreamPrivate::~QCLuceneTokenStreamPrivate() +{ + if (deleteCLuceneTokenStream) + _CLDECDELETE(tokenStream); +} + + +QCLuceneTokenStream::QCLuceneTokenStream() + : d(new QCLuceneTokenStreamPrivate()) +{ + // nothing todo +} + +QCLuceneTokenStream::~QCLuceneTokenStream() +{ + // nothing todo +} + +void QCLuceneTokenStream::close() +{ + d->tokenStream->close(); +} + +bool QCLuceneTokenStream::next(QCLuceneToken &token) +{ + return d->tokenStream->next(token.d->token); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/fulltextsearch/qtokenstream_p.h b/src/assistant/lib/fulltextsearch/qtokenstream_p.h new file mode 100644 index 0000000..8f4b9d0 --- /dev/null +++ b/src/assistant/lib/fulltextsearch/qtokenstream_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team. +** All rights reserved. +** +** Portion Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +****************************************************************************/ + +#ifndef QTOKENSTREAM_P_H +#define QTOKENSTREAM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qtoken_p.h" +#include "qclucene_global_p.h" + +#include +#include +#include + +CL_NS_DEF(analysis) + class TokenStream; +CL_NS_END +CL_NS_USE(analysis) + +QT_BEGIN_NAMESPACE + +class QCLuceneAnalyzer; +class QCLuceneTokenizer; +class QCLuceneStopAnalyzer; +class QCLuceneSimpleAnalyzer; +class QCLuceneKeywordAnalyzer; +class QCLuceneStandardAnalyzer; +class QCLuceneWhitespaceAnalyzer; +class QCLucenePerFieldAnalyzerWrapper; + +class QHELP_EXPORT QCLuceneTokenStreamPrivate : public QSharedData +{ +public: + QCLuceneTokenStreamPrivate(); + QCLuceneTokenStreamPrivate(const QCLuceneTokenStreamPrivate &other); + + ~QCLuceneTokenStreamPrivate(); + + TokenStream *tokenStream; + bool deleteCLuceneTokenStream; + +private: + QCLuceneTokenStreamPrivate &operator=(const QCLuceneTokenStreamPrivate &other); +}; + +class QHELP_EXPORT QCLuceneTokenStream +{ +public: + virtual ~QCLuceneTokenStream(); + + void close(); + bool next(QCLuceneToken &token); + +protected: + friend class QCLuceneAnalyzer; + friend class QCLuceneTokenizer; + friend class QCLuceneStopAnalyzer; + friend class QCLuceneSimpleAnalyzer; + friend class QCLuceneKeywordAnalyzer; + friend class QCLuceneStandardAnalyzer; + friend class QCLuceneWhitespaceAnalyzer; + friend class QCLucenePerFieldAnalyzerWrapper; + QSharedDataPointer d; + +private: + QCLuceneTokenStream(); +}; + +QT_END_NAMESPACE + +#endif // QTOKENSTREAM_P_H diff --git a/src/assistant/lib/helpsystem.qrc b/src/assistant/lib/helpsystem.qrc new file mode 100644 index 0000000..10efc6d --- /dev/null +++ b/src/assistant/lib/helpsystem.qrc @@ -0,0 +1,8 @@ + + + images/1leftarrow.png + images/1rightarrow.png + images/3leftarrow.png + images/3rightarrow.png + + diff --git a/src/assistant/lib/images/1leftarrow.png b/src/assistant/lib/images/1leftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..bd1a5a2499af38761bd8db135b4c0ea537789bb5 GIT binary patch literal 669 zcmeAS@N?(olHy`uVBq!ia0vp^0w65F1|^Y9 z4OYz%b8PKlAcrl<+uh|q7;r{>zr(=5_{-D9F~s9|a>4?k58u9h;^J^vesi7E3kFM$ zy+6cS%r>{IT)gS1&l-VS6ZoCZ-{o0of2aAv|NqV}g2Xn-HarWi$FbGJSt_*tP;dx)$nsaKWpZQ~+Khi}F$ z_x3QoN?ze?cii!@nYhzxx%R9a#j}hXZ(or4AYse3U<-qKi{E|zh3hMwP4_ilC|}4X z;`r3{oq#y2A%CE3!2W&*rIw3a7p~k9WbGA7<@l@5<|N;IEZ4v!x1cD&T)j>HDkJY_ z&S}gUsxg*ZIDA_#Xd5YfDbLlo%W_sUp!8YaieHQWEw);)ao(Y(4(3_D%~uvaWxA61 z-)EuXRyn8bpPaar)I-=!js~sPXuG7eP+(Vqk;&Q{jXKdWqb_sJ0ICNGToB{rVFL2kcg7t z{Irtt#G+INhKgI-`uf*TpE<4P=cnUw^|ZbhJA>H`wg`dXQ!zl*44$rjF6*2UngG*7 B3pfA( literal 0 HcmV?d00001 diff --git a/src/assistant/lib/images/1rightarrow.png b/src/assistant/lib/images/1rightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..0c0c44ae6ffdf8c7cf75664b16388bf18fc8f699 GIT binary patch literal 706 zcmV;z0zLhSP)8wDn%-V5Q7wjD2g_vcv)zpEfSh3Fi-uuuk#)M6HdKO1IRJutVe~sron3TC{ zsr1E|n(&#nct0L!4V|!ZpwvoiQK_b$s&_i^%}Fd#z_`KX|24PD`%wX!(BTNTg=P@@ z4$P=lN&B>;e{e1vyXr9hiS-Ansdu9SXzLxnBMV@ebPO9u(LZROE}v85eAYxwxV;Y- z(=h+xzm*`q7Ee{-uoe!+;^Yl%y^d+V&=TnQ^%N_>87wGYdBNC3Jgn0)(5!iFI<9KY zp52(PCbcK5)`ZfdCt2)QfC=;WtQ4IV^^9L#zR-X#%J7hC91|DzqA~|`-&BBZ9kWY# zSqsc4KtRWANcYF_fNsXoh;K%7Lf2WdS-$C zUX8yH<(HA=5!KGCdmuj<*BAV+*YRK7E!{y~a)){V001I-R9JLVZ)S9NVRB^v0C?If oFE7{2%*!rLPAo{(%P&d?05;eLSP)anTmS$707*qoM6N<$g03ApKmY&$ literal 0 HcmV?d00001 diff --git a/src/assistant/lib/images/3leftarrow.png b/src/assistant/lib/images/3leftarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..8d38b0f5782eb432de9890e0c4a7c806290697ca GIT binary patch literal 832 zcmV-G1Hb%)+51es$zUMqI zM`Da~AtWi;LM_Z|Q~#gok8{QpCGHV&TkN`OVCgCBsD<`urUA(VYP4|U8Q7W&t>@AN z$g7~|1#CC`EkN~zEWSlo^5 z5??M_`d)H{?Ne-5n{Y$u3H;IzZ&t!Bw5m0Z)KjFR0Vf_qmyZID#{&)o%n!=n%X-$! zJ_xtd%MGkv*%bA2GczgHxiZ`^Os{(PNto@8ujW54PThG5SOfcdD4;75FlD}1J}v9n z9X2VPP9HB}4a$aS9R<*h_m{w(HkegC&j8wv{ub!IKmq>56c~AhFv)t%z1z;3dA_*f z`btv}zztIt_?h;zBM8@a(ty>er(nf(_+}D%D(C_7)9(T-!ZBsQ7_<#aR9@Nu2WsHV zU0PfR;i*?J@0}{3kOJrd`qxo_vcPS)s0~(ahTa+Y(+!`6p!i6;q5zH?D1Z*8toHwO z5b5ZZ+BuzkbP`7B;2ENGA>^Wf4hrz816EVO2nDRq@F{oBVVdk&U8qP1g(jo~yOqnIVFuxNOppX1b1l}m3z+a0_93kvr>Fx650 zumAu6B6?I2D?NY%?PN(TTo*alb-Q_5Tb0000< KMNUMnLSTY|=Wf0L literal 0 HcmV?d00001 diff --git a/src/assistant/lib/images/3rightarrow.png b/src/assistant/lib/images/3rightarrow.png new file mode 100644 index 0000000000000000000000000000000000000000..c2faf501ccf7bd265ef8d99367a6eba02839701e GIT binary patch literal 820 zcmV-41Izr0P)HqSe~k;sVXVg)9sH$yEN zO$sl}iy)>K%^-s6YD$!*7EVO_Fhkizk+2XlANC+t-&Hf2DD53F)iIZ-?O99yS1?FGnx?_JED12h|9CTV> zeQlfo>F?pI8W;@1w*#3N8qDTn7b9)9>Nb==(oZ+;8fu|dx zH%pkPT(K-}7aD3;^h=p^MWo1U_UGg!w|p1%M`?WiC)UCztx&It*X`lYYk9>=xHmkj z5Fi*7dDNif2ZPi_3({q87HQO^WJCvO=dQ1Y163S=V!yGv85Z7z&KCH!63$yh8C58z zj%Kn6gSvLT&_$HOD=?}Gzlwbh*s>39uK&-g_*t9)+UtDd-Gd!F;qD%8 zx~zZu7-@{Kdj{GHe+P(toHRV4rg3FI$2&ekLm)K%3p`CV)wnDoDgXcgB6?I2D?NY%?PN(TTo*alb-Q_5Tb0000 +#include + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace clucene { + extern const QString AttributeField; + extern const QString ContentField; + extern const QString NamespaceField; + extern const QString PathField; + extern const QString TitleField; + extern const QString TitleTokenizedField; +} // namespace clucene +} // namespace fulltextsearch + +QT_END_NAMESPACE + +#endif // QCLUCENEFIELDNAMES_P_H diff --git a/src/assistant/lib/qhelp_global.cpp b/src/assistant/lib/qhelp_global.cpp new file mode 100644 index 0000000..2c7ca62 --- /dev/null +++ b/src/assistant/lib/qhelp_global.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "qhelp_global.h" + +QString QHelpGlobal::uniquifyConnectionName(const QString &name, void *pointer) +{ + static int counter = 0; + static QMutex mutex; + + QMutexLocker locker(&mutex); + if (++counter > 1000) + counter = 0; + + return QString::fromLatin1("%1-%2-%3"). + arg(name).arg(quintptr(pointer)).arg(counter); +} + +QString QHelpGlobal::documentTitle(const QString &content) +{ + QString title = QCoreApplication::translate("QHelp", "Untitled"); + if (!content.isEmpty()) { + int start = content.indexOf(QLatin1String(""), 0, Qt::CaseInsensitive) + 7; + int end = content.indexOf(QLatin1String(""), 0, Qt::CaseInsensitive); + if ((end - start) > 0) { + title = content.mid(start, end - start); + if (Qt::mightBeRichText(title) || title.contains(QLatin1Char('&'))) { + QTextDocument doc; + doc.setHtml(title); + title = doc.toPlainText(); + } + } + } + return title; +} + +QString QHelpGlobal::codecFromData(const QByteArray &data) +{ + QString codec = codecFromXmlData(data); + if (codec.isEmpty()) + codec = codecFromHtmlData(data); + return codec.isEmpty() ? QLatin1String("utf-8") : codec; +} + +QString QHelpGlobal::codecFromHtmlData(const QByteArray &data) +{ + QString head = QString::fromUtf8(data.constData(), qMin(1000, data.size())); + int start = head.indexOf(QLatin1String(" 0) { + QRegExp r(QLatin1String("charset=([^\"\\s]+)")); + while (start != -1) { + const int end = head.indexOf(QLatin1Char('>'), start) + 1; + if (end <= start) + break; + const QString &meta = head.mid(start, end - start).toLower(); + if (r.indexIn(meta) != -1) + return r.cap(1); + start = head.indexOf(QLatin1String(".*")); + return encodingExp.exactMatch(head) ? encodingExp.cap(1) : QString(); +} diff --git a/src/assistant/lib/qhelp_global.h b/src/assistant/lib/qhelp_global.h new file mode 100644 index 0000000..182298f --- /dev/null +++ b/src/assistant/lib/qhelp_global.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELP_GLOBAL_H +#define QHELP_GLOBAL_H + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +#if !defined(QT_SHARED) && !defined(QT_DLL) +# define QHELP_EXPORT +#elif defined(QHELP_LIB) +# define QHELP_EXPORT Q_DECL_EXPORT +#else +# define QHELP_EXPORT Q_DECL_IMPORT +#endif + +class QHelpGlobal { +public: + static QString uniquifyConnectionName(const QString &name, void *pointer); + static QString documentTitle(const QString &content); + static QString codecFromData(const QByteArray &data); + +private: + static QString codecFromHtmlData(const QByteArray &data); + static QString codecFromXmlData(const QByteArray &data); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHELP_GLOBAL_H diff --git a/src/assistant/lib/qhelpcollectionhandler.cpp b/src/assistant/lib/qhelpcollectionhandler.cpp new file mode 100644 index 0000000..169d37e --- /dev/null +++ b/src/assistant/lib/qhelpcollectionhandler.cpp @@ -0,0 +1,603 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpcollectionhandler_p.h" +#include "qhelp_global.h" +#include "qhelpdbreader_p.h" + +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +QHelpCollectionHandler::QHelpCollectionHandler(const QString &collectionFile, QObject *parent) + : QObject(parent) + , m_dbOpened(false) + , m_collectionFile(collectionFile) + , m_connectionName(QString()) +{ + QFileInfo fi(m_collectionFile); + if (!fi.isAbsolute()) + m_collectionFile = fi.absoluteFilePath(); + m_query.clear(); +} + +QHelpCollectionHandler::~QHelpCollectionHandler() +{ + m_query.clear(); + if (m_dbOpened) + QSqlDatabase::removeDatabase(m_connectionName); +} + +bool QHelpCollectionHandler::isDBOpened() +{ + if (m_dbOpened) + return true; + emit error(tr("The collection file '%1' is not set up yet!"). + arg(m_collectionFile)); + return false; +} + +QString QHelpCollectionHandler::collectionFile() const +{ + return m_collectionFile; +} + +bool QHelpCollectionHandler::openCollectionFile() +{ + if (m_dbOpened) + return m_dbOpened; + + m_connectionName = QHelpGlobal::uniquifyConnectionName( + QLatin1String("QHelpCollectionHandler"), this); + bool openingOk = true; + { + QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), + m_connectionName); + if (db.driver() + && db.driver()->lastError().type() == QSqlError::ConnectionError) { + emit error(tr("Cannot load sqlite database driver!")); + return false; + } + + db.setDatabaseName(collectionFile()); + openingOk = db.open(); + if (openingOk) + m_query = QSqlQuery(db); + } + if (!openingOk) { + QSqlDatabase::removeDatabase(m_connectionName); + emit error(tr("Cannot open collection file: %1").arg(collectionFile())); + return false; + } + + m_query.exec(QLatin1String("PRAGMA synchronous=OFF")); + m_query.exec(QLatin1String("PRAGMA cache_size=3000")); + + m_query.exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'" + "AND Name=\'NamespaceTable\'")); + m_query.next(); + if (m_query.value(0).toInt() < 1) { + if (!createTables(&m_query)) { + emit error(tr("Cannot create tables in file %1!").arg(collectionFile())); + return false; + } + } + + m_dbOpened = true; + return m_dbOpened; +} + +bool QHelpCollectionHandler::copyCollectionFile(const QString &fileName) +{ + if (!m_dbOpened) + return false; + + QFileInfo fi(fileName); + if (fi.exists()) { + emit error(tr("The collection file '%1' already exists!"). + arg(fileName)); + return false; + } + + if (!fi.absoluteDir().exists() && !QDir().mkpath(fi.absolutePath())) { + emit error(tr("Cannot create directory: %1").arg(fi.absolutePath())); + return false; + } + + QString colFile = fi.absoluteFilePath(); + QString connectionName = QHelpGlobal::uniquifyConnectionName( + QLatin1String("QHelpCollectionHandlerCopy"), this); + QSqlQuery *copyQuery = 0; + bool openingOk = true; + { + QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), connectionName); + db.setDatabaseName(colFile); + openingOk = db.open(); + if (openingOk) + copyQuery = new QSqlQuery(db); + } + + if (!openingOk) { + emit error(tr("Cannot open collection file: %1").arg(colFile)); + return false; + } + + copyQuery->exec(QLatin1String("PRAGMA synchronous=OFF")); + copyQuery->exec(QLatin1String("PRAGMA cache_size=3000")); + + if (!createTables(copyQuery)) { + emit error(tr("Cannot copy collection file: %1").arg(colFile)); + return false; + } + + QString oldBaseDir = QFileInfo(collectionFile()).absolutePath(); + QString oldFilePath; + QFileInfo newColFi(colFile); + m_query.exec(QLatin1String("SELECT Name, FilePath FROM NamespaceTable")); + while (m_query.next()) { + copyQuery->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)")); + copyQuery->bindValue(0, m_query.value(0).toString()); + oldFilePath = m_query.value(1).toString(); + if (!QDir::isAbsolutePath(oldFilePath)) + oldFilePath = oldBaseDir + QDir::separator() + oldFilePath; + copyQuery->bindValue(1, newColFi.absoluteDir().relativeFilePath(oldFilePath)); + copyQuery->exec(); + } + + m_query.exec(QLatin1String("SELECT NamespaceId, Name FROM FolderTable")); + while (m_query.next()) { + copyQuery->prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)")); + copyQuery->bindValue(0, m_query.value(0).toString()); + copyQuery->bindValue(1, m_query.value(1).toString()); + copyQuery->exec(); + } + + m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable")); + while (m_query.next()) { + copyQuery->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); + copyQuery->bindValue(0, m_query.value(0).toString()); + copyQuery->exec(); + } + + m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable")); + while (m_query.next()) { + copyQuery->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)")); + copyQuery->bindValue(0, m_query.value(0).toString()); + copyQuery->exec(); + } + + m_query.exec(QLatin1String("SELECT NameId, FilterAttributeId FROM FilterTable")); + while (m_query.next()) { + copyQuery->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)")); + copyQuery->bindValue(0, m_query.value(0).toInt()); + copyQuery->bindValue(1, m_query.value(1).toInt()); + copyQuery->exec(); + } + + m_query.exec(QLatin1String("SELECT Key, Value FROM SettingsTable")); + while (m_query.next()) { + if (m_query.value(0).toString() == QLatin1String("CluceneSearchNamespaces")) + continue; + copyQuery->prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)")); + copyQuery->bindValue(0, m_query.value(0).toString()); + copyQuery->bindValue(1, m_query.value(1)); + copyQuery->exec(); + } + + copyQuery->clear(); + delete copyQuery; + QSqlDatabase::removeDatabase(connectionName); + return true; +} + +bool QHelpCollectionHandler::createTables(QSqlQuery *query) +{ + QStringList tables; + tables << QLatin1String("CREATE TABLE NamespaceTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT, " + "FilePath TEXT )") + << QLatin1String("CREATE TABLE FolderTable (" + "Id INTEGER PRIMARY KEY, " + "NamespaceId INTEGER, " + "Name TEXT )") + << QLatin1String("CREATE TABLE FilterAttributeTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT )") + << QLatin1String("CREATE TABLE FilterNameTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT )") + << QLatin1String("CREATE TABLE FilterTable (" + "NameId INTEGER, " + "FilterAttributeId INTEGER )") + << QLatin1String("CREATE TABLE SettingsTable (" + "Key TEXT PRIMARY KEY, " + "Value BLOB )"); + + foreach (const QString &q, tables) { + if (!query->exec(q)) + return false; + } + return true; +} + +QStringList QHelpCollectionHandler::customFilters() const +{ + QStringList list; + if (m_dbOpened) { + m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable")); + while (m_query.next()) + list.append(m_query.value(0).toString()); + } + return list; +} + +bool QHelpCollectionHandler::removeCustomFilter(const QString &filterName) +{ + if (!isDBOpened() || filterName.isEmpty()) + return false; + + int filterNameId = -1; + m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?")); + m_query.bindValue(0, filterName); + m_query.exec(); + if (m_query.next()) + filterNameId = m_query.value(0).toInt(); + + if (filterNameId < 0) { + emit error(tr("Unknown filter '%1'!").arg(filterName)); + return false; + } + + m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?")); + m_query.bindValue(0, filterNameId); + m_query.exec(); + + m_query.prepare(QLatin1String("DELETE FROM FilterNameTable WHERE Id=?")); + m_query.bindValue(0, filterNameId); + m_query.exec(); + + return true; +} + +bool QHelpCollectionHandler::addCustomFilter(const QString &filterName, + const QStringList &attributes) +{ + if (!isDBOpened() || filterName.isEmpty()) + return false; + + int nameId = -1; + m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?")); + m_query.bindValue(0, filterName); + m_query.exec(); + if (m_query.next()) + nameId = m_query.value(0).toInt(); + + m_query.exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable")); + QStringList idsToInsert = attributes; + QMap attributeMap; + while (m_query.next()) { + attributeMap.insert(m_query.value(1).toString(), + m_query.value(0).toInt()); + if (idsToInsert.contains(m_query.value(1).toString())) + idsToInsert.removeAll(m_query.value(1).toString()); + } + + foreach (const QString &id, idsToInsert) { + m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); + m_query.bindValue(0, id); + m_query.exec(); + attributeMap.insert(id, m_query.lastInsertId().toInt()); + } + + if (nameId < 0) { + m_query.prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)")); + m_query.bindValue(0, filterName); + if (m_query.exec()) + nameId = m_query.lastInsertId().toInt(); + } + + if (nameId < 0) { + emit error(tr("Cannot register filter %1!").arg(filterName)); + return false; + } + + m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?")); + m_query.bindValue(0, nameId); + m_query.exec(); + + foreach (const QString &att, attributes) { + m_query.prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)")); + m_query.bindValue(0, nameId); + m_query.bindValue(1, attributeMap[att]); + if (!m_query.exec()) + return false; + } + return true; +} + +QHelpCollectionHandler::DocInfoList QHelpCollectionHandler::registeredDocumentations() const +{ + DocInfoList list; + if (m_dbOpened) { + m_query.exec(QLatin1String("SELECT a.Name, a.FilePath, b.Name " + "FROM NamespaceTable a, FolderTable b WHERE a.Id=b.NamespaceId")); + + while (m_query.next()) { + DocInfo info; + info.fileName = m_query.value(1).toString(); + info.folderName = m_query.value(2).toString(); + info.namespaceName = m_query.value(0).toString(); + list.append(info); + } + } + return list; +} + +bool QHelpCollectionHandler::registerDocumentation(const QString &fileName) +{ + if (!isDBOpened()) + return false; + + QHelpDBReader reader(fileName, QHelpGlobal::uniquifyConnectionName( + QLatin1String("QHelpCollectionHandler"), this), 0); + if (!reader.init()) { + emit error(tr("Cannot open documentation file %1!").arg(fileName)); + return false; + } + + QString ns = reader.namespaceName(); + if (ns.isEmpty()) { + emit error(tr("Invalid documentation file '%1'!").arg(fileName)); + return false; + } + + int nsId = registerNamespace(ns, fileName); + if (nsId < 1) + return false; + + if (!registerVirtualFolder(reader.virtualFolder(), nsId)) + return false; + + addFilterAttributes(reader.filterAttributes()); + foreach (const QString &filterName, reader.customFilters()) + addCustomFilter(filterName, reader.filterAttributes(filterName)); + + optimizeDatabase(fileName); + + return true; +} + +bool QHelpCollectionHandler::unregisterDocumentation(const QString &namespaceName) +{ + if (!isDBOpened()) + return false; + + m_query.prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name=?")); + m_query.bindValue(0, namespaceName); + m_query.exec(); + + int nsId = -1; + if (m_query.next()) + nsId = m_query.value(0).toInt(); + + if (nsId < 0) { + emit error(tr("The namespace %1 was not registered!").arg(namespaceName)); + return false; + } + + m_query.prepare(QLatin1String("DELETE FROM NamespaceTable WHERE Id=?")); + m_query.bindValue(0, nsId); + m_query.exec(); + + m_query.prepare(QLatin1String("DELETE FROM FolderTable WHERE NamespaceId=?")); + m_query.bindValue(0, nsId); + return m_query.exec(); +} + +bool QHelpCollectionHandler::removeCustomValue(const QString &key) +{ + if (!isDBOpened()) + return false; + + m_query.prepare(QLatin1String("DELETE FROM SettingsTable WHERE Key=?")); + m_query.bindValue(0, key); + return m_query.exec(); +} + +QVariant QHelpCollectionHandler::customValue(const QString &key, + const QVariant &defaultValue) const +{ + QVariant value = defaultValue; + if (m_dbOpened) { + m_query.prepare(QLatin1String("SELECT COUNT(Key) FROM SettingsTable WHERE Key=?")); + m_query.bindValue(0, key); + if (!m_query.exec() || !m_query.next() || !m_query.value(0).toInt()) { + m_query.clear(); + return defaultValue; + } + + m_query.clear(); + m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?")); + m_query.bindValue(0, key); + if (m_query.exec() && m_query.next()) + value = m_query.value(0); + m_query.clear(); + } + return value; +} + +bool QHelpCollectionHandler::setCustomValue(const QString &key, + const QVariant &value) +{ + if (!isDBOpened()) + return false; + + m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?")); + m_query.bindValue(0, key); + m_query.exec(); + if (m_query.next()) { + m_query.prepare(QLatin1String("UPDATE SettingsTable SET Value=? where Key=?")); + m_query.bindValue(0, value); + m_query.bindValue(1, key); + } + else { + m_query.prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)")); + m_query.bindValue(0, key); + m_query.bindValue(1, value); + } + return m_query.exec(); +} + +bool QHelpCollectionHandler::addFilterAttributes(const QStringList &attributes) +{ + if (!isDBOpened()) + return false; + + m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable")); + QSet atts; + while (m_query.next()) + atts.insert(m_query.value(0).toString()); + + foreach (const QString &s, attributes) { + if (!atts.contains(s)) { + m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); + m_query.bindValue(0, s); + m_query.exec(); + } + } + return true; +} + +QStringList QHelpCollectionHandler::filterAttributes() const +{ + QStringList list; + if (m_dbOpened) { + m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable")); + while (m_query.next()) + list.append(m_query.value(0).toString()); + } + return list; +} + +QStringList QHelpCollectionHandler::filterAttributes(const QString &filterName) const +{ + QStringList list; + if (m_dbOpened) { + m_query.prepare(QLatin1String("SELECT a.Name FROM FilterAttributeTable a, " + "FilterTable b, FilterNameTable c WHERE a.Id=b.FilterAttributeId " + "AND b.NameId=c.Id AND c.Name=?")); + m_query.bindValue(0, filterName); + m_query.exec(); + while (m_query.next()) + list.append(m_query.value(0).toString()); + } + return list; +} + +int QHelpCollectionHandler::registerNamespace(const QString &nspace, const QString &fileName) +{ + m_query.prepare(QLatin1String("SELECT COUNT(Id) FROM NamespaceTable WHERE Name=?")); + m_query.bindValue(0, nspace); + m_query.exec(); + while (m_query.next()) { + if (m_query.value(0).toInt() > 0) { + emit error(tr("Namespace %1 already exists!").arg(nspace)); + return -1; + } + } + + QFileInfo fi(m_collectionFile); + m_query.prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)")); + m_query.bindValue(0, nspace); + m_query.bindValue(1, fi.absoluteDir().relativeFilePath(fileName)); + int namespaceId = -1; + if (m_query.exec()) + namespaceId = m_query.lastInsertId().toInt(); + if (namespaceId < 1) { + emit error(tr("Cannot register namespace '%1'!").arg(nspace)); + return -1; + } + return namespaceId; +} + +bool QHelpCollectionHandler::registerVirtualFolder(const QString &folderName, int namespaceId) +{ + m_query.prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)")); + m_query.bindValue(0, namespaceId); + m_query.bindValue(1, folderName); + return m_query.exec(); +} + +void QHelpCollectionHandler::optimizeDatabase(const QString &fileName) +{ + if (!QFile::exists(fileName)) + return; + + { // according to removeDatabase() documentation + QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("optimize")); + db.setDatabaseName(fileName); + if (!db.open()) { + QSqlDatabase::removeDatabase(QLatin1String("optimize")); + emit error(tr("Cannot open database '%1' to optimize!").arg(fileName)); + return; + } + + QSqlQuery query(db); + db.exec(QLatin1String("PRAGMA synchronous=OFF")); + db.exec(QLatin1String("PRAGMA cache_size=3000")); + db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS NameIndex ON IndexTable(Name)")); + db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileNameIndex ON FileNameTable(Name)")); + db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileIdIndex ON FileNameTable(FileId)")); + + db.close(); + } + + QSqlDatabase::removeDatabase(QLatin1String("optimize")); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpcollectionhandler_p.h b/src/assistant/lib/qhelpcollectionhandler_p.h new file mode 100644 index 0000000..a97af8f --- /dev/null +++ b/src/assistant/lib/qhelpcollectionhandler_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPCOLLECTIONHANDLER_H +#define QHELPCOLLECTIONHANDLER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QHelpCollectionHandler : public QObject +{ + Q_OBJECT + +public: + struct DocInfo + { + QString fileName; + QString folderName; + QString namespaceName; + }; + typedef QList DocInfoList; + + explicit QHelpCollectionHandler(const QString &collectionFile, + QObject *parent = 0); + ~QHelpCollectionHandler(); + + QString collectionFile() const; + + bool openCollectionFile(); + bool copyCollectionFile(const QString &fileName); + + QStringList customFilters() const; + bool removeCustomFilter(const QString &filterName); + bool addCustomFilter(const QString &filterName, + const QStringList &attributes); + + DocInfoList registeredDocumentations() const; + bool registerDocumentation(const QString &fileName); + bool unregisterDocumentation(const QString &namespaceName); + + bool removeCustomValue(const QString &key); + QVariant customValue(const QString &key, const QVariant &defaultValue) const; + bool setCustomValue(const QString &key, const QVariant &value); + + bool addFilterAttributes(const QStringList &attributes); + QStringList filterAttributes() const; + QStringList filterAttributes(const QString &filterName) const; + + int registerNamespace(const QString &nspace, const QString &fileName); + bool registerVirtualFolder(const QString &folderName, int namespaceId); + void optimizeDatabase(const QString &fileName); + +signals: + void error(const QString &msg); + +private: + bool isDBOpened(); + bool createTables(QSqlQuery *query); + + bool m_dbOpened; + QString m_collectionFile; + QString m_connectionName; + mutable QSqlQuery m_query; +}; + +QT_END_NAMESPACE + +#endif //QHELPCOLLECTIONHANDLER_H diff --git a/src/assistant/lib/qhelpcontentwidget.cpp b/src/assistant/lib/qhelpcontentwidget.cpp new file mode 100644 index 0000000..988a909 --- /dev/null +++ b/src/assistant/lib/qhelpcontentwidget.cpp @@ -0,0 +1,586 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpcontentwidget.h" +#include "qhelpenginecore.h" +#include "qhelpengine_p.h" +#include "qhelpdbreader_p.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QHelpContentItemPrivate +{ +public: + QHelpContentItemPrivate(const QString &t, const QString &l, + QHelpDBReader *r, QHelpContentItem *p) + { + parent = p; + title = t; + link = l; + helpDBReader = r; + } + + QList childItems; + QHelpContentItem *parent; + QString title; + QString link; + QHelpDBReader *helpDBReader; +}; + +class QHelpContentProvider : public QThread +{ +public: + QHelpContentProvider(QHelpEnginePrivate *helpEngine); + ~QHelpContentProvider(); + void collectContents(const QString &customFilterName); + void stopCollecting(); + QHelpContentItem *rootItem(); + int nextChildCount() const; + +private: + void run(); + + QHelpEnginePrivate *m_helpEngine; + QHelpContentItem *m_rootItem; + QStringList m_filterAttributes; + QQueue m_rootItems; + QMutex m_mutex; + bool m_abort; +}; + +class QHelpContentModelPrivate +{ +public: + QHelpContentItem *rootItem; + QHelpContentProvider *qhelpContentProvider; +}; + + + +/*! + \class QHelpContentItem + \inmodule QtHelp + \brief The QHelpContentItem class provides an item for use with QHelpContentModel. + \since 4.4 +*/ + +QHelpContentItem::QHelpContentItem(const QString &name, const QString &link, + QHelpDBReader *reader, QHelpContentItem *parent) +{ + d = new QHelpContentItemPrivate(name, link, reader, parent); +} + +/*! + Destroys the help content item. +*/ +QHelpContentItem::~QHelpContentItem() +{ + qDeleteAll(d->childItems); + delete d; +} + +void QHelpContentItem::appendChild(QHelpContentItem *item) +{ + d->childItems.append(item); +} + +/*! + Returns the child of the content item in the give \a row. + + \sa parent() +*/ +QHelpContentItem *QHelpContentItem::child(int row) const +{ + if (row >= childCount()) + return 0; + return d->childItems.value(row); +} + +/*! + Returns the number of child items. +*/ +int QHelpContentItem::childCount() const +{ + return d->childItems.count(); +} + +/*! + Returns the row of this item from its parents view. +*/ +int QHelpContentItem::row() const +{ + if (d->parent) + return d->parent->d->childItems.indexOf(const_cast(this)); + return 0; +} + +/*! + Returns the title of the content item. +*/ +QString QHelpContentItem::title() const +{ + return d->title; +} + +/*! + Returns the URL of this content item. +*/ +QUrl QHelpContentItem::url() const +{ + return d->helpDBReader->urlOfPath(d->link); +} + +/*! + Returns the parent content item. +*/ +QHelpContentItem *QHelpContentItem::parent() const +{ + return d->parent; +} + +/*! + Returns the position of a given \a child. +*/ +int QHelpContentItem::childPosition(QHelpContentItem *child) const +{ + return d->childItems.indexOf(child); +} + + + +QHelpContentProvider::QHelpContentProvider(QHelpEnginePrivate *helpEngine) + : QThread(helpEngine) +{ + m_helpEngine = helpEngine; + m_rootItem = 0; + m_abort = false; +} + +QHelpContentProvider::~QHelpContentProvider() +{ + stopCollecting(); +} + +void QHelpContentProvider::collectContents(const QString &customFilterName) +{ + m_mutex.lock(); + m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName); + m_mutex.unlock(); + if (!isRunning()) { + start(LowPriority); + } else { + stopCollecting(); + start(LowPriority); + } +} + +void QHelpContentProvider::stopCollecting() +{ + if (!isRunning()) + return; + m_mutex.lock(); + m_abort = true; + m_mutex.unlock(); + wait(); +} + +QHelpContentItem *QHelpContentProvider::rootItem() +{ + QMutexLocker locker(&m_mutex); + return m_rootItems.dequeue(); +} + +int QHelpContentProvider::nextChildCount() const +{ + return m_rootItems.head()->childCount(); +} + +void QHelpContentProvider::run() +{ + QString title; + QString link; + int depth = 0; + QHelpContentItem *item = 0; + + m_mutex.lock(); + m_rootItem = new QHelpContentItem(QString(), QString(), 0); + m_rootItems.enqueue(m_rootItem); + QStringList atts = m_filterAttributes; + const QStringList fileNames = m_helpEngine->orderedFileNameList; + m_mutex.unlock(); + + foreach (const QString &dbFileName, fileNames) { + m_mutex.lock(); + if (m_abort) { + m_abort = false; + m_mutex.unlock(); + break; + } + m_mutex.unlock(); + QHelpDBReader reader(dbFileName, + QHelpGlobal::uniquifyConnectionName(dbFileName + + QLatin1String("FromQHelpContentProvider"), + QThread::currentThread()), 0); + if (!reader.init()) + continue; + foreach (const QByteArray& ba, reader.contentsForFilter(atts)) { + if (ba.size() < 1) + continue; + + int _depth = 0; + bool _root = false; + QStack stack; + + QDataStream s(ba); + for (;;) { + s >> depth; + s >> link; + s >> title; + if (title.isEmpty()) + break; +CHECK_DEPTH: + if (depth == 0) { + m_mutex.lock(); + item = new QHelpContentItem(title, link, + m_helpEngine->fileNameReaderMap.value(dbFileName), m_rootItem); + m_rootItem->appendChild(item); + m_mutex.unlock(); + stack.push(item); + _depth = 1; + _root = true; + } else { + if (depth > _depth && _root) { + _depth = depth; + stack.push(item); + } + if (depth == _depth) { + item = new QHelpContentItem(title, link, + m_helpEngine->fileNameReaderMap.value(dbFileName), stack.top()); + stack.top()->appendChild(item); + } else if (depth < _depth) { + stack.pop(); + --_depth; + goto CHECK_DEPTH; + } + } + } + } + } + m_mutex.lock(); + m_abort = false; + m_mutex.unlock(); +} + + + +/*! + \class QHelpContentModel + \inmodule QtHelp + \brief The QHelpContentModel class provides a model that supplies content to views. + \since 4.4 +*/ + +/*! + \fn void QHelpContentModel::contentsCreationStarted() + + This signal is emitted when the creation of the contents has + started. The current contents are invalid from this point on + until the signal contentsCreated() is emitted. + + \sa isCreatingContents() +*/ + +/*! + \fn void QHelpContentModel::contentsCreated() + + This signal is emitted when the contents have been created. +*/ + +QHelpContentModel::QHelpContentModel(QHelpEnginePrivate *helpEngine) + : QAbstractItemModel(helpEngine) +{ + d = new QHelpContentModelPrivate(); + d->rootItem = 0; + d->qhelpContentProvider = new QHelpContentProvider(helpEngine); + + connect(d->qhelpContentProvider, SIGNAL(finished()), + this, SLOT(insertContents()), Qt::QueuedConnection); + connect(helpEngine->q, SIGNAL(setupStarted()), this, SLOT(invalidateContents())); +} + +/*! + Destroys the help content model. +*/ +QHelpContentModel::~QHelpContentModel() +{ + delete d->rootItem; + delete d; +} + +void QHelpContentModel::invalidateContents(bool onShutDown) +{ + if (onShutDown) + disconnect(this, SLOT(insertContents())); + d->qhelpContentProvider->stopCollecting(); + if (d->rootItem) { + delete d->rootItem; + d->rootItem = 0; + } + if (!onShutDown) + reset(); +} + +/*! + Creates new contents by querying the help system + for contents specified for the \a customFilterName. +*/ +void QHelpContentModel::createContents(const QString &customFilterName) +{ + d->qhelpContentProvider->collectContents(customFilterName); + emit contentsCreationStarted(); +} + +void QHelpContentModel::insertContents() +{ + int count; + if (d->rootItem) { + count = d->rootItem->childCount() - 1; + beginRemoveRows(QModelIndex(), 0, count > 0 ? count : 0); + delete d->rootItem; + d->rootItem = 0; + endRemoveRows(); + } + + count = d->qhelpContentProvider->nextChildCount() - 1; + beginInsertRows(QModelIndex(), 0, count > 0 ? count : 0); + d->rootItem = d->qhelpContentProvider->rootItem(); + endInsertRows(); + reset(); + emit contentsCreated(); +} + +/*! + Returns true if the contents are currently rebuilt, otherwise + false. +*/ +bool QHelpContentModel::isCreatingContents() const +{ + return d->qhelpContentProvider->isRunning(); +} + +/*! + Returns the help content item at the model index position + \a index. +*/ +QHelpContentItem *QHelpContentModel::contentItemAt(const QModelIndex &index) const +{ + if (index.isValid()) + return static_cast(index.internalPointer()); + else + return d->rootItem; +} + +/*! + Returns the index of the item in the model specified by + the given \a row, \a column and \a parent index. +*/ +QModelIndex QHelpContentModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!d->rootItem) + return QModelIndex(); + + QHelpContentItem *parentItem = contentItemAt(parent); + QHelpContentItem *item = parentItem->child(row); + if (!item) + return QModelIndex(); + return createIndex(row, column, item); +} + +/*! + Returns the parent of the model item with the given + \a index, or QModelIndex() if it has no parent. +*/ +QModelIndex QHelpContentModel::parent(const QModelIndex &index) const +{ + QHelpContentItem *item = contentItemAt(index); + if (!item) + return QModelIndex(); + + QHelpContentItem *parentItem = static_cast(item->parent()); + if (!parentItem) + return QModelIndex(); + + QHelpContentItem *grandparentItem = static_cast(parentItem->parent()); + if (!grandparentItem) + return QModelIndex(); + + int row = grandparentItem->childPosition(parentItem); + return createIndex(row, index.column(), parentItem); +} + +/*! + Returns the number of rows under the given \a parent. +*/ +int QHelpContentModel::rowCount(const QModelIndex &parent) const +{ + QHelpContentItem *parentItem = contentItemAt(parent); + if (!parentItem) + return 0; + return parentItem->childCount(); +} + +/*! + Returns the number of columns under the given \a parent. Currently returns always 1. +*/ +int QHelpContentModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 1; +} + +/*! + Returns the data stored under the given \a role for + the item referred to by the \a index. +*/ +QVariant QHelpContentModel::data(const QModelIndex &index, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + QHelpContentItem *item = contentItemAt(index); + if (!item) + return QVariant(); + return item->title(); +} + + + +/*! + \class QHelpContentWidget + \inmodule QtHelp + \brief The QHelpContentWidget class provides a tree view for displaying help content model items. + \since 4.4 +*/ + +/*! + \fn void QHelpContentWidget::linkActivated(const QUrl &link) + + This signal is emitted when a content item is activated and + its associated \a link should be shown. +*/ + +QHelpContentWidget::QHelpContentWidget() + : QTreeView(0) +{ + header()->hide(); + setUniformRowHeights(true); + connect(this, SIGNAL(activated(QModelIndex)), + this, SLOT(showLink(QModelIndex))); +} + +/*! + Returns the index of the content item with the \a link. + An invalid index is returned if no such an item exists. +*/ +QModelIndex QHelpContentWidget::indexOf(const QUrl &link) +{ + QHelpContentModel *contentModel = + qobject_cast(model()); + if (!contentModel || link.scheme() != QLatin1String("qthelp")) + return QModelIndex(); + + m_syncIndex = QModelIndex(); + for (int i=0; irowCount(); ++i) { + QHelpContentItem *itm = + contentModel->contentItemAt(contentModel->index(i, 0)); + if (itm && itm->url().host() == link.host()) { + QString path = link.path(); + if (path.startsWith(QLatin1Char('/'))) + path = path.mid(1); + if (searchContentItem(contentModel, contentModel->index(i, 0), path)) { + return m_syncIndex; + } + } + } + return QModelIndex(); +} + +bool QHelpContentWidget::searchContentItem(QHelpContentModel *model, + const QModelIndex &parent, const QString &path) +{ + QHelpContentItem *parentItem = model->contentItemAt(parent); + if (!parentItem) + return false; + + if (QDir::cleanPath(parentItem->url().path()) == path) { + m_syncIndex = parent; + return true; + } + + for (int i=0; ichildCount(); ++i) { + if (searchContentItem(model, model->index(i, 0, parent), path)) + return true; + } + return false; +} + +void QHelpContentWidget::showLink(const QModelIndex &index) +{ + QHelpContentModel *contentModel = qobject_cast(model()); + if (!contentModel) + return; + + QHelpContentItem *item = contentModel->contentItemAt(index); + if (!item) + return; + QUrl url = item->url(); + if (url.isValid()) + emit linkActivated(url); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpcontentwidget.h b/src/assistant/lib/qhelpcontentwidget.h new file mode 100644 index 0000000..0e7567e --- /dev/null +++ b/src/assistant/lib/qhelpcontentwidget.h @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPCONTENTWIDGET_H +#define QHELPCONTENTWIDGET_H + +#include + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +class QHelpEnginePrivate; +class QHelpDBReader; +class QHelpContentItemPrivate; +class QHelpContentModelPrivate; +class QHelpEngine; +class QHelpContentProvider; + +class QHELP_EXPORT QHelpContentItem +{ +public: + ~QHelpContentItem(); + + QHelpContentItem *child(int row) const; + int childCount() const; + QString title() const; + QUrl url() const; + int row() const; + QHelpContentItem *parent() const; + int childPosition(QHelpContentItem *child) const; + +private: + QHelpContentItem(const QString &name, const QString &link, + QHelpDBReader *reader, QHelpContentItem *parent = 0); + void appendChild(QHelpContentItem *child); + + QHelpContentItemPrivate *d; + friend class QHelpContentProvider; +}; + +class QHELP_EXPORT QHelpContentModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + ~QHelpContentModel(); + + void createContents(const QString &customFilterName); + QHelpContentItem *contentItemAt(const QModelIndex &index) const; + + QVariant data(const QModelIndex &index, int role) const; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + bool isCreatingContents() const; + +Q_SIGNALS: + void contentsCreationStarted(); + void contentsCreated(); + +private Q_SLOTS: + void insertContents(); + void invalidateContents(bool onShutDown = false); + +private: + QHelpContentModel(QHelpEnginePrivate *helpEngine); + QHelpContentModelPrivate *d; + friend class QHelpEnginePrivate; +}; + +class QHELP_EXPORT QHelpContentWidget : public QTreeView +{ + Q_OBJECT + +public: + QModelIndex indexOf(const QUrl &link); + +Q_SIGNALS: + void linkActivated(const QUrl &link); + +private Q_SLOTS: + void showLink(const QModelIndex &index); + +private: + bool searchContentItem(QHelpContentModel *model, + const QModelIndex &parent, const QString &path); + QModelIndex m_syncIndex; + +private: + QHelpContentWidget(); + friend class QHelpEngine; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + diff --git a/src/assistant/lib/qhelpdatainterface.cpp b/src/assistant/lib/qhelpdatainterface.cpp new file mode 100644 index 0000000..d3f07c7 --- /dev/null +++ b/src/assistant/lib/qhelpdatainterface.cpp @@ -0,0 +1,273 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpdatainterface_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \internal + \class QHelpDataContentItem + \since 4.4 + \brief The QHelpDataContentItem class provides an item which represents + a topic or section of the contents. + + Every item holds several pieces of information, most notably the title + which can later be displayed in a contents overview. The reference is used + to store a relative file link to the corresponding section in the + documentation. +*/ + +/*! + Constructs a new content item with \a parent as parent item. + The constucted item has the title \a title and links to the + location specified by \a reference. +*/ +QHelpDataContentItem::QHelpDataContentItem(QHelpDataContentItem *parent, + const QString &title, const QString &reference) + : m_title(title), m_reference(reference) +{ + if (parent) + parent->m_children.append(this); +} + +/*! + Destructs the item and its children. +*/ +QHelpDataContentItem::~QHelpDataContentItem() +{ + qDeleteAll(m_children); +} + +/*! + Returns the title of the item. +*/ +QString QHelpDataContentItem::title() const +{ + return m_title; +} + +/*! + Returns the file reference of the item. +*/ +QString QHelpDataContentItem::reference() const +{ + return m_reference; +} + +/*! + Returns a list of all its child items. +*/ +QList QHelpDataContentItem::children() const +{ + return m_children; +} + +bool QHelpDataIndexItem::operator==(const QHelpDataIndexItem & other) const +{ + return (other.name == name) + && (other.reference == reference); +} + + + +/*! + \internal + \class QHelpDataFilterSection + \since 4.4 +*/ + +/*! + Constructs a help data filter section. +*/ +QHelpDataFilterSection::QHelpDataFilterSection() +{ + d = new QHelpDataFilterSectionData(); +} + +/*! + Adds the filter attribute \a filter to the filter attributes of + this section. +*/ +void QHelpDataFilterSection::addFilterAttribute(const QString &filter) +{ + d->filterAttributes.append(filter); +} + +/*! + Returns a list of all filter attributes defined for this section. +*/ +QStringList QHelpDataFilterSection::filterAttributes() const +{ + return d->filterAttributes; +} + +/*! + Adds the index item \a index to the list of indices. +*/ +void QHelpDataFilterSection::addIndex(const QHelpDataIndexItem &index) +{ + d->indices.append(index); +} + +/*! + Sets the filter sections list of indices to \a indices. +*/ +void QHelpDataFilterSection::setIndices(const QList &indices) +{ + d->indices = indices; +} + +/*! + Returns the list of indices. +*/ +QList QHelpDataFilterSection::indices() const +{ + return d->indices; +} + +/*! + Adds the top level content item \a content to the filter section. +*/ +void QHelpDataFilterSection::addContent(QHelpDataContentItem *content) +{ + d->contents.append(content); +} + +/*! + Sets the list of top level content items of the filter section to + \a contents. +*/ +void QHelpDataFilterSection::setContents(const QList &contents) +{ + qDeleteAll(d->contents); + d->contents = contents; +} + +/*! + Returns a list of top level content items. +*/ +QList QHelpDataFilterSection::contents() const +{ + return d->contents; +} + +/*! + Adds the file \a file to the filter section. +*/ +void QHelpDataFilterSection::addFile(const QString &file) +{ + d->files.append(file); +} + +/*! + Set the list of files to \a files. +*/ +void QHelpDataFilterSection::setFiles(const QStringList &files) +{ + d->files = files; +} + +/*! + Returns the list of files. +*/ +QStringList QHelpDataFilterSection::files() const +{ + return d->files; +} + +/*! + \internal + \class QHelpDataInterface + \since 4.4 +*/ + +/*! + \fn QHelpDataInterface::QHelpDataInterface() + + Constructs a new help data interface. +*/ + +/*! + \fn QHelpDataInterface::~QHelpDataInterface() + + Destroys the help data interface. +*/ + +/*! + \fn QString QHelpDataInterface::namespaceName() const = 0 + + Returns the namespace name of the help data set. +*/ + +/*! + \fn QString QHelpDataInterface::virtualFolder() const = 0 + + Returns the virtual folder of the help data set. +*/ + +/*! + \fn QList QHelpDataInterface::customFilters () const = 0 + + Returns a list of custom filters. Defining custom filters is optional. +*/ + +/*! + \fn QList QHelpDataInterface::filterSections() const = 0 + + Returns a list of filter sections. +*/ + +/*! + \fn QMap QHelpDataInterface::metaData() const = 0 + + Returns a map of meta data. A meta data item can hold almost any data + and is identified by its name. +*/ + +/*! + \fn QString QHelpDataInterface::rootPath() const = 0 + + Returns the root file path of the documentation data. All referenced file + path or links of content items are relative to this path. +*/ + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpdatainterface_p.h b/src/assistant/lib/qhelpdatainterface_p.h new file mode 100644 index 0000000..886d686 --- /dev/null +++ b/src/assistant/lib/qhelpdatainterface_p.h @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPDATAINTERFACE_H +#define QHELPDATAINTERFACE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelp_global.h" + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QHELP_EXPORT QHelpDataContentItem +{ +public: + QHelpDataContentItem(QHelpDataContentItem *parent, const QString &title, + const QString &reference); + ~QHelpDataContentItem(); + + QString title() const; + QString reference() const; + QList children() const; + +private: + QString m_title; + QString m_reference; + QList m_children; +}; + +struct QHELP_EXPORT QHelpDataIndexItem { + QHelpDataIndexItem() {} + QHelpDataIndexItem(const QString &n, const QString &id, const QString &r) + : name(n), identifier(id), reference(r) {} + + QString name; + QString identifier; + QString reference; + + bool operator==(const QHelpDataIndexItem & other) const; +}; + +class QHelpDataFilterSectionData : public QSharedData +{ +public: + ~QHelpDataFilterSectionData() + { + qDeleteAll(contents); + } + + QStringList filterAttributes; + QList indices; + QList contents; + QStringList files; +}; + +class QHELP_EXPORT QHelpDataFilterSection +{ +public: + QHelpDataFilterSection(); + + void addFilterAttribute(const QString &filter); + QStringList filterAttributes() const; + + void addIndex(const QHelpDataIndexItem &index); + void setIndices(const QList &indices); + QList indices() const; + + void addContent(QHelpDataContentItem *content); + void setContents(const QList &contents); + QList contents() const; + + void addFile(const QString &file); + void setFiles(const QStringList &files); + QStringList files() const; + +private: + QSharedDataPointer d; +}; + +struct QHELP_EXPORT QHelpDataCustomFilter { + QStringList filterAttributes; + QString name; +}; + +class QHELP_EXPORT QHelpDataInterface +{ +public: + QHelpDataInterface() {} + virtual ~QHelpDataInterface() {} + + virtual QString namespaceName() const = 0; + virtual QString virtualFolder() const = 0; + virtual QList customFilters() const = 0; + virtual QList filterSections() const = 0; + virtual QMap metaData() const = 0; + virtual QString rootPath() const = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHELPDATAINTERFACE_H diff --git a/src/assistant/lib/qhelpdbreader.cpp b/src/assistant/lib/qhelpdbreader.cpp new file mode 100644 index 0000000..c4735f8 --- /dev/null +++ b/src/assistant/lib/qhelpdbreader.cpp @@ -0,0 +1,583 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpdbreader_p.h" +#include "qhelp_global.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QHelpDBReader::QHelpDBReader(const QString &dbName) + : QObject(0) +{ + initObject(dbName, + QHelpGlobal::uniquifyConnectionName(QLatin1String("QHelpDBReader"), + this)); +} + +QHelpDBReader::QHelpDBReader(const QString &dbName, const QString &uniqueId, + QObject *parent) + : QObject(parent) +{ + initObject(dbName, uniqueId); +} + +void QHelpDBReader::initObject(const QString &dbName, const QString &uniqueId) +{ + m_dbName = dbName; + m_uniqueId = uniqueId; + m_initDone = false; + m_query = 0; + m_useAttributesCache = false; +} + +QHelpDBReader::~QHelpDBReader() +{ + if (m_initDone) { + delete m_query; + QSqlDatabase::removeDatabase(m_uniqueId); + } +} + +bool QHelpDBReader::init() +{ + if (m_initDone) + return true; + + if (!QFile::exists(m_dbName)) + return false; + + QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), m_uniqueId); + db.setDatabaseName(m_dbName); + if (!db.open()) { + /*: The placeholders are: %1 - The name of the database which cannot be opened + %2 - The unique id for the connection + %3 - The actual error string */ + m_error = tr("Cannot open database '%1' '%2': %3").arg(m_dbName, m_uniqueId, db.lastError().text()); + QSqlDatabase::removeDatabase(m_uniqueId); + return false; + } + + m_initDone = true; + m_query = new QSqlQuery(db); + + return true; +} + +QString QHelpDBReader::databaseName() const +{ + return m_dbName; +} + +QString QHelpDBReader::errorMessage() const +{ + return m_error; +} + +QString QHelpDBReader::namespaceName() const +{ + if (!m_namespace.isEmpty()) + return m_namespace; + if (m_query) { + m_query->exec(QLatin1String("SELECT Name FROM NamespaceTable")); + if (m_query->next()) + m_namespace = m_query->value(0).toString(); + } + return m_namespace; +} + +QString QHelpDBReader::virtualFolder() const +{ + if (m_query) { + m_query->exec(QLatin1String("SELECT Name FROM FolderTable WHERE Id=1")); + if (m_query->next()) + return m_query->value(0).toString(); + } + return QString(); +} + +QList QHelpDBReader::filterAttributeSets() const +{ + QList result; + if (m_query) { + m_query->exec(QLatin1String("SELECT a.Id, b.Name FROM FileAttributeSetTable a, " + "FilterAttributeTable b WHERE a.FilterAttributeId=b.Id ORDER BY a.Id")); + int oldId = -1; + while (m_query->next()) { + int id = m_query->value(0).toInt(); + if (id != oldId) { + result.append(QStringList()); + oldId = id; + } + result.last().append(m_query->value(1).toString()); + } + } + return result; +} + +bool QHelpDBReader::fileExists(const QString &virtualFolder, + const QString &filePath, + const QStringList &filterAttributes) const +{ + if (virtualFolder.isEmpty() || filePath.isEmpty() || !m_query) + return false; + +//SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b, FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id AND b.Name='qtdoc' AND a.Name='qstring.html' AND a.FileId=c.FileId AND c.FilterAttributeId=d.Id AND d.Name='qtrefdoc' + + QString query; + namespaceName(); + if (filterAttributes.isEmpty()) { + query = QString(QLatin1String("SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b " + "WHERE a.FolderId=b.Id AND b.Name=\'%1\' AND a.Name=\'%2\'")).arg(quote(virtualFolder)).arg(quote(filePath)); + } else { + query = QString(QLatin1String("SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b, " + "FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id " + "AND b.Name=\'%1\' AND a.Name=\'%2\' AND a.FileId=c.FileId AND " + "c.FilterAttributeId=d.Id AND d.Name=\'%3\'")) + .arg(quote(virtualFolder)).arg(quote(filePath)) + .arg(quote(filterAttributes.first())); + for (int i=1; iexec(query); + if (m_query->next() && m_query->isValid() && m_query->value(0).toInt()) + return true; + return false; +} + +QByteArray QHelpDBReader::fileData(const QString &virtualFolder, + const QString &filePath) const +{ + QByteArray ba; + if (virtualFolder.isEmpty() || filePath.isEmpty() || !m_query) + return ba; + + namespaceName(); + m_query->prepare(QLatin1String("SELECT a.Data FROM FileDataTable a, FileNameTable b, FolderTable c, " + "NamespaceTable d WHERE a.Id=b.FileId AND (b.Name=? OR b.Name=?) AND b.FolderId=c.Id " + "AND c.Name=? AND c.NamespaceId=d.Id AND d.Name=?")); + m_query->bindValue(0, filePath); + m_query->bindValue(1, QString(QLatin1String("./") + filePath)); + m_query->bindValue(2, virtualFolder); + m_query->bindValue(3, m_namespace); + m_query->exec(); + if (m_query->next() && m_query->isValid()) + ba = qUncompress(m_query->value(0).toByteArray()); + return ba; +} + +QStringList QHelpDBReader::customFilters() const +{ + QStringList lst; + if (m_query) { + m_query->exec(QLatin1String("SELECT Name FROM FilterNameTable")); + while (m_query->next()) + lst.append(m_query->value(0).toString()); + } + return lst; +} + +QStringList QHelpDBReader::filterAttributes(const QString &filterName) const +{ + QStringList lst; + if (m_query) { + if (filterName.isEmpty()) { + m_query->prepare(QLatin1String("SELECT Name FROM FilterAttributeTable")); + } else { + m_query->prepare(QLatin1String("SELECT a.Name FROM FilterAttributeTable a, " + "FilterTable b, FilterNameTable c WHERE c.Name=? " + "AND c.Id=b.NameId AND b.FilterAttributeId=a.Id")); + m_query->bindValue(0, filterName); + } + m_query->exec(); + while (m_query->next()) + lst.append(m_query->value(0).toString()); + } + return lst; +} + +QStringList QHelpDBReader::indicesForFilter(const QStringList &filterAttributes) const +{ + QStringList indices; + if (!m_query) + return indices; + + //SELECT DISTINCT a.Name FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId AND b.FilterAttributeId=c.Id AND c.Name in ('4.2.3', 'qt') + + QString query; + if (filterAttributes.isEmpty()) { + query = QLatin1String("SELECT DISTINCT Name FROM IndexTable"); + } else { + query = QString(QLatin1String("SELECT DISTINCT a.Name FROM IndexTable a, " + "IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId " + "AND b.FilterAttributeId=c.Id AND c.Name='%1'")).arg(quote(filterAttributes.first())); + for (int i=1; iexec(query); + while (m_query->next()) { + if (!m_query->value(0).toString().isEmpty()) + indices.append(m_query->value(0).toString()); + } + return indices; +} + +void QHelpDBReader::linksForKeyword(const QString &keyword, const QStringList &filterAttributes, + QMap &linkMap) const +{ + if (!m_query) + return; + + QString query; + if (filterAttributes.isEmpty()) { + query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor " + "FROM IndexTable a, FileNameTable d, " + "FolderTable e, NamespaceTable f WHERE " + "a.FileId=d.FileId AND d.FolderId=e.Id AND a.NamespaceId=f.Id " + "AND a.Name='%1'")).arg(quote(keyword)); + } else if (m_useAttributesCache) { + query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor, a.Id " + "FROM IndexTable a, " + "FileNameTable d, FolderTable e, NamespaceTable f WHERE " + "a.FileId=d.FileId AND d.FolderId=e.Id " + "AND a.NamespaceId=f.Id AND a.Name='%1'")) + .arg(quote(keyword)); + m_query->exec(query); + while (m_query->next()) { + if (m_indicesCache.contains(m_query->value(5).toInt())) { + linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(), + m_query->value(2).toString(), m_query->value(3).toString(), + m_query->value(4).toString())); + } + } + return; + } else { + query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor " + "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, " + "FileNameTable d, FolderTable e, NamespaceTable f " + "WHERE a.FileId=d.FileId AND d.FolderId=e.Id " + "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id " + "AND a.Name='%1' AND c.Name='%2'")).arg(quote(keyword)) + .arg(quote(filterAttributes.first())); + for (int i=1; iexec(query); + while (m_query->next()) { + title = m_query->value(0).toString(); + if (title.isEmpty()) // generate a title + corresponding path + title = keyword + QLatin1String(" : ") + m_query->value(3).toString(); + linkMap.insertMulti(title, buildQUrl(m_query->value(1).toString(), + m_query->value(2).toString(), m_query->value(3).toString(), + m_query->value(4).toString())); + } +} + +void QHelpDBReader::linksForIdentifier(const QString &id, + const QStringList &filterAttributes, + QMap &linkMap) const +{ + if (!m_query) + return; + + QString query; + if (filterAttributes.isEmpty()) { + query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor " + "FROM IndexTable a, FileNameTable d, FolderTable e, " + "NamespaceTable f WHERE a.FileId=d.FileId AND " + "d.FolderId=e.Id AND a.NamespaceId=f.Id AND a.Identifier='%1'")) + .arg(quote(id)); + } else if (m_useAttributesCache) { + query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor, a.Id " + "FROM IndexTable a," + "FileNameTable d, FolderTable e, NamespaceTable f WHERE " + "a.FileId=d.FileId AND d.FolderId=e.Id " + "AND a.NamespaceId=f.Id AND a.Identifier='%1'")) + .arg(quote(id)); + m_query->exec(query); + while (m_query->next()) { + if (m_indicesCache.contains(m_query->value(5).toInt())) { + linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(), + m_query->value(2).toString(), m_query->value(3).toString(), + m_query->value(4).toString())); + } + } + return; + } else { + query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor " + "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, " + "FileNameTable d, FolderTable e, NamespaceTable f " + "WHERE a.FileId=d.FileId AND d.FolderId=e.Id " + "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id " + "AND a.Identifier='%1' AND c.Name='%2'")).arg(quote(id)) + .arg(quote(filterAttributes.first())); + for (int i=0; iexec(query); + while (m_query->next()) { + linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(), + m_query->value(2).toString(), m_query->value(3).toString(), + m_query->value(4).toString())); + } +} + +QUrl QHelpDBReader::buildQUrl(const QString &ns, const QString &folder, + const QString &relFileName, const QString &anchor) const +{ + QUrl url; + url.setScheme(QLatin1String("qthelp")); + url.setAuthority(ns); + url.setPath(folder + QLatin1Char('/') + relFileName); + url.setFragment(anchor); + return url; +} + +QList QHelpDBReader::contentsForFilter(const QStringList &filterAttributes) const +{ + QList contents; + if (!m_query) + return contents; + + //SELECT DISTINCT a.Data FROM ContentsTable a, ContentsFilterTable b, FilterAttributeTable c WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id AND c.Name='qt' INTERSECT SELECT DISTINCT a.Data FROM ContentsTable a, ContentsFilterTable b, FilterAttributeTable c WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id AND c.Name='3.3.8'; + + QString query; + if (filterAttributes.isEmpty()) { + query = QLatin1String("SELECT Data from ContentsTable"); + } else { + query = QString(QLatin1String("SELECT a.Data FROM ContentsTable a, " + "ContentsFilterTable b, FilterAttributeTable c " + "WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id " + "AND c.Name='%1'")).arg(quote(filterAttributes.first())); + for (int i=1; iexec(query); + while (m_query->next()) { + contents.append(m_query->value(0).toByteArray()); + } + return contents; +} + +QUrl QHelpDBReader::urlOfPath(const QString &relativePath) const +{ + QUrl url; + if (!m_query) + return url; + + m_query->exec(QLatin1String("SELECT a.Name, b.Name FROM NamespaceTable a, " + "FolderTable b WHERE a.id=b.NamespaceId and a.Id=1")); + if (m_query->next()) { + QString rp = relativePath; + QString anchor; + int i = rp.indexOf(QLatin1Char('#')); + if (i > -1) { + rp = relativePath.left(i); + anchor = relativePath.mid(i+1); + } + url = buildQUrl(m_query->value(0).toString(), + m_query->value(1).toString(), rp, anchor); + } + return url; +} + +QStringList QHelpDBReader::files(const QStringList &filterAttributes, + const QString &extensionFilter) const +{ + QStringList lst; + if (!m_query) + return lst; + + QString query; + QString extension; + if (!extensionFilter.isEmpty()) + extension = QString(QLatin1String("AND b.Name like \'%.%1\'")).arg(extensionFilter); + + if (filterAttributes.isEmpty()) { + query = QString(QLatin1String("SELECT a.Name, b.Name FROM FolderTable a, " + "FileNameTable b WHERE b.FolderId=a.Id %1")) + .arg(extension); + } else { + query = QString(QLatin1String("SELECT a.Name, b.Name FROM FolderTable a, " + "FileNameTable b, FileFilterTable c, FilterAttributeTable d " + "WHERE b.FolderId=a.Id AND b.FileId=c.FileId " + "AND c.FilterAttributeId=d.Id AND d.Name=\'%1\' %2")) + .arg(quote(filterAttributes.first())).arg(extension); + for (int i=1; iexec(query); + while (m_query->next()) { + lst.append(m_query->value(0).toString() + QLatin1Char('/') + + m_query->value(1).toString()); + } + + return lst; +} + +QVariant QHelpDBReader::metaData(const QString &name) const +{ + QVariant v; + if (!m_query) + return v; + + m_query->prepare(QLatin1String("SELECT COUNT(Value), Value FROM MetaDataTable " + "WHERE Name=?")); + m_query->bindValue(0, name); + if (m_query->exec() && m_query->next() + && m_query->value(0).toInt() == 1) + v = m_query->value(1); + return v; +} + +QString QHelpDBReader::mergeList(const QStringList &list) const +{ + QString str; + foreach (const QString &s, list) + str.append(QLatin1Char('\'') + quote(s) + QLatin1String("\', ")); + if (str.endsWith(QLatin1String(", "))) + str = str.left(str.length()-2); + return str; +} + +QString QHelpDBReader::quote(const QString &string) const +{ + QString s = string; + s.replace(QLatin1Char('\''), QLatin1String("\'\'")); + return s; +} + +QSet QHelpDBReader::indexIds(const QStringList &attributes) const +{ + QSet ids; + + if (attributes.isEmpty()) + return ids; + + QString query = QString(QLatin1String("SELECT a.IndexId FROM IndexFilterTable a, " + "FilterAttributeTable b WHERE a.FilterAttributeId=b.Id " + "AND b.Name='%1'")).arg(attributes.first()); + for (int i=0; iexec(query)) + return ids; + + while (m_query->next()) + ids.insert(m_query->value(0).toInt()); + + return ids; +} + +bool QHelpDBReader::createAttributesCache(const QStringList &attributes, + const QSet &indexIds) +{ + m_useAttributesCache = false; + + if (attributes.count() < 2) { + m_viewAttributes.clear(); + return true; + } + + bool needUpdate = !m_viewAttributes.count(); + + foreach (const QString &s, attributes) + m_viewAttributes.remove(s); + + if (m_viewAttributes.count() || needUpdate) { + m_viewAttributes.clear(); + m_indicesCache = indexIds; + } + foreach (const QString &s, attributes) + m_viewAttributes.insert(s); + m_useAttributesCache = true; + return true; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpdbreader_p.h b/src/assistant/lib/qhelpdbreader_p.h new file mode 100644 index 0000000..5fdf2e9 --- /dev/null +++ b/src/assistant/lib/qhelpdbreader_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPDBREADER_H +#define QHELPDBREADER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QSqlQuery; + +class QHelpDBReader : public QObject +{ + Q_OBJECT + +public: + QHelpDBReader(const QString &dbName); + QHelpDBReader(const QString &dbName, const QString &uniqueId, + QObject *parent); + ~QHelpDBReader(); + + bool init(); + + QString errorMessage() const; + + QString databaseName() const; + QString namespaceName() const; + QString virtualFolder() const; + QList filterAttributeSets() const; + QStringList files(const QStringList &filterAttributes, + const QString &extensionFilter = QString()) const; + bool fileExists(const QString &virtualFolder, const QString &filePath, + const QStringList &filterAttributes = QStringList()) const; + QByteArray fileData(const QString &virtualFolder, + const QString &filePath) const; + + QStringList customFilters() const; + QStringList filterAttributes(const QString &filterName = QString()) const; + QStringList indicesForFilter(const QStringList &filterAttributes) const; + void linksForKeyword(const QString &keyword, const QStringList &filterAttributes, + QMap &linkMap) const; + + void linksForIdentifier(const QString &id, const QStringList &filterAttributes, + QMap &linkMap) const; + + QList contentsForFilter(const QStringList &filterAttributes) const; + QUrl urlOfPath(const QString &relativePath) const; + + QSet indexIds(const QStringList &attributes) const; + bool createAttributesCache(const QStringList &attributes, + const QSet &indexIds); + QVariant metaData(const QString &name) const; + +private: + void initObject(const QString &dbName, const QString &uniqueId); + QUrl buildQUrl(const QString &ns, const QString &folder, + const QString &relFileName, const QString &anchor) const; + QString mergeList(const QStringList &list) const; + QString quote(const QString &string) const; + + bool m_initDone; + QString m_dbName; + QString m_uniqueId; + QString m_error; + QSqlQuery *m_query; + mutable QString m_namespace; + QSet m_viewAttributes; + bool m_useAttributesCache; + QSet m_indicesCache; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/assistant/lib/qhelpengine.cpp b/src/assistant/lib/qhelpengine.cpp new file mode 100644 index 0000000..f11b52a --- /dev/null +++ b/src/assistant/lib/qhelpengine.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpengine.h" +#include "qhelpengine_p.h" +#include "qhelpdbreader_p.h" +#include "qhelpcontentwidget.h" +#include "qhelpindexwidget.h" +#include "qhelpsearchengine.h" +#include "qhelpcollectionhandler_p.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QHelpEnginePrivate::QHelpEnginePrivate() + : QHelpEngineCorePrivate() + , contentModel(0) + , contentWidget(0) + , indexModel(0) + , indexWidget(0) + , searchEngine(0) +{ +} + +QHelpEnginePrivate::~QHelpEnginePrivate() +{ +} + +void QHelpEnginePrivate::init(const QString &collectionFile, + QHelpEngineCore *helpEngineCore) +{ + QHelpEngineCorePrivate::init(collectionFile, helpEngineCore); + + if (!contentModel) + contentModel = new QHelpContentModel(this); + if (!indexModel) + indexModel = new QHelpIndexModel(this); + + connect(helpEngineCore, SIGNAL(setupFinished()), this, + SLOT(applyCurrentFilter())); + connect(helpEngineCore, SIGNAL(currentFilterChanged(QString)), this, + SLOT(applyCurrentFilter())); +} + +void QHelpEnginePrivate::applyCurrentFilter() +{ + if (!error.isEmpty()) + return; + contentModel->createContents(currentFilter); + indexModel->createIndex(currentFilter); +} + +void QHelpEnginePrivate::setContentsWidgetBusy() +{ + contentWidget->setCursor(Qt::WaitCursor); +} + +void QHelpEnginePrivate::unsetContentsWidgetBusy() +{ + contentWidget->unsetCursor(); +} + +void QHelpEnginePrivate::setIndexWidgetBusy() +{ + indexWidget->setCursor(Qt::WaitCursor); +} + +void QHelpEnginePrivate::unsetIndexWidgetBusy() +{ + indexWidget->unsetCursor(); +} + +void QHelpEnginePrivate::stopDataCollection() +{ + contentModel->invalidateContents(true); + indexModel->invalidateIndex(true); +} + + + +/*! + \class QHelpEngine + \since 4.4 + \inmodule QtHelp + \brief The QHelpEngine class provides access to contents and + indices of the help engine. + + +*/ + +/*! + Constructs a new help engine with the given \a parent. The help + engine uses the information stored in the \a collectionFile for + providing help. If the collection file does not already exist, + it will be created. +*/ +QHelpEngine::QHelpEngine(const QString &collectionFile, QObject *parent) + : QHelpEngineCore(d = new QHelpEnginePrivate(), parent) +{ + d->init(collectionFile, this); +} + +/*! + Destroys the help engine object. +*/ +QHelpEngine::~QHelpEngine() +{ + d->stopDataCollection(); +} + +/*! + Returns the content model. +*/ +QHelpContentModel *QHelpEngine::contentModel() const +{ + return d->contentModel; +} + +/*! + Returns the index model. +*/ +QHelpIndexModel *QHelpEngine::indexModel() const +{ + return d->indexModel; +} + +/*! + Returns the content widget. +*/ +QHelpContentWidget *QHelpEngine::contentWidget() +{ + if (!d->contentWidget) { + d->contentWidget = new QHelpContentWidget(); + d->contentWidget->setModel(d->contentModel); + connect(d->contentModel, SIGNAL(contentsCreationStarted()), + d, SLOT(setContentsWidgetBusy())); + connect(d->contentModel, SIGNAL(contentsCreated()), + d, SLOT(unsetContentsWidgetBusy())); + } + return d->contentWidget; +} + +/*! + Returns the index widget. +*/ +QHelpIndexWidget *QHelpEngine::indexWidget() +{ + if (!d->indexWidget) { + d->indexWidget = new QHelpIndexWidget(); + d->indexWidget->setModel(d->indexModel); + connect(d->indexModel, SIGNAL(indexCreationStarted()), + d, SLOT(setIndexWidgetBusy())); + connect(d->indexModel, SIGNAL(indexCreated()), + d, SLOT(unsetIndexWidgetBusy())); + } + return d->indexWidget; +} + +/*! + Returns the default search engine. +*/ +QHelpSearchEngine* QHelpEngine::searchEngine() +{ + if (!d->searchEngine) + d->searchEngine = new QHelpSearchEngine(this, this); + return d->searchEngine; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpengine.h b/src/assistant/lib/qhelpengine.h new file mode 100644 index 0000000..cc0bca2 --- /dev/null +++ b/src/assistant/lib/qhelpengine.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPENGINE_H +#define QHELPENGINE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +class QHelpContentModel; +class QHelpContentWidget; +class QHelpIndexModel; +class QHelpIndexWidget; +class QHelpEnginePrivate; +class QHelpSearchEngine; + +class QHELP_EXPORT QHelpEngine : public QHelpEngineCore +{ + Q_OBJECT + +public: + explicit QHelpEngine(const QString &collectionFile, QObject *parent = 0); + ~QHelpEngine(); + + QHelpContentModel *contentModel() const; + QHelpIndexModel *indexModel() const; + + QHelpContentWidget *contentWidget(); + QHelpIndexWidget *indexWidget(); + + QHelpSearchEngine *searchEngine(); + +private: + QHelpEnginePrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/assistant/lib/qhelpengine_p.h b/src/assistant/lib/qhelpengine_p.h new file mode 100644 index 0000000..5a7c301 --- /dev/null +++ b/src/assistant/lib/qhelpengine_p.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPENGINE_P_H +#define QHELPENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QSqlQuery; + +class QHelpEngineCore; +class QHelpDBReader; +class QHelpContentModel; +class QHelpContentWidget; +class QHelpIndexModel; +class QHelpIndexWidget; +class QHelpSearchEngine; +class QHelpCollectionHandler; + +class QHelpEngineCorePrivate : public QObject +{ + Q_OBJECT + +public: + QHelpEngineCorePrivate(); + virtual ~QHelpEngineCorePrivate(); + + virtual void init(const QString &collectionFile, + QHelpEngineCore *helpEngineCore); + + void clearMaps(); + bool setup(); + + QMap readerMap; + QMap fileNameReaderMap; + QMultiMap virtualFolderMap; + QStringList orderedFileNameList; + + QHelpCollectionHandler *collectionHandler; + QString currentFilter; + QString error; + bool needsSetup; + bool autoSaveFilter; + +protected: + QHelpEngineCore *q; + +private slots: + void errorReceived(const QString &msg); +}; + + +class QHelpEnginePrivate : public QHelpEngineCorePrivate +{ + Q_OBJECT + +public: + QHelpEnginePrivate(); + ~QHelpEnginePrivate(); + + void init(const QString &collectionFile, + QHelpEngineCore *helpEngineCore); + + QHelpContentModel *contentModel; + QHelpContentWidget *contentWidget; + + QHelpIndexModel *indexModel; + QHelpIndexWidget *indexWidget; + + QHelpSearchEngine *searchEngine; + + void stopDataCollection(); + + friend class QHelpContentProvider; + friend class QHelpContentModel; + friend class QHelpIndexProvider; + friend class QHelpIndexModel; + +public slots: + void setContentsWidgetBusy(); + void unsetContentsWidgetBusy(); + void setIndexWidgetBusy(); + void unsetIndexWidgetBusy(); + +private slots: + void applyCurrentFilter(); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/assistant/lib/qhelpenginecore.cpp b/src/assistant/lib/qhelpenginecore.cpp new file mode 100644 index 0000000..1fd2242 --- /dev/null +++ b/src/assistant/lib/qhelpenginecore.cpp @@ -0,0 +1,737 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpenginecore.h" +#include "qhelpengine_p.h" +#include "qhelpdbreader_p.h" +#include "qhelpcollectionhandler_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QHelpEngineCorePrivate::QHelpEngineCorePrivate() +{ + QHelpGlobal::uniquifyConnectionName(QString(), this); + autoSaveFilter = true; +} + +void QHelpEngineCorePrivate::init(const QString &collectionFile, + QHelpEngineCore *helpEngineCore) +{ + q = helpEngineCore; + collectionHandler = new QHelpCollectionHandler(collectionFile, helpEngineCore); + connect(collectionHandler, SIGNAL(error(QString)), + this, SLOT(errorReceived(QString))); + needsSetup = true; +} + +QHelpEngineCorePrivate::~QHelpEngineCorePrivate() +{ + delete collectionHandler; + clearMaps(); +} + +void QHelpEngineCorePrivate::clearMaps() +{ + QMap::iterator it = readerMap.begin(); + while (it != readerMap.end()) { + delete it.value(); + ++it; + } + readerMap.clear(); + fileNameReaderMap.clear(); + virtualFolderMap.clear(); + orderedFileNameList.clear(); +} + +bool QHelpEngineCorePrivate::setup() +{ + error.clear(); + if (!needsSetup) + return true; + + needsSetup = false; + emit q->setupStarted(); + clearMaps(); + + if (!collectionHandler->openCollectionFile()) { + emit q->setupFinished(); + return false; + } + + const QHelpCollectionHandler::DocInfoList docList = + collectionHandler->registeredDocumentations(); + QFileInfo fi(collectionHandler->collectionFile()); + QString absFileName; + foreach(const QHelpCollectionHandler::DocInfo &info, docList) { + if (QDir::isAbsolutePath(info.fileName)) { + absFileName = info.fileName; + } else { + absFileName = QFileInfo(fi.absolutePath() + QDir::separator() + info.fileName) + .absoluteFilePath(); + } + QHelpDBReader *reader = new QHelpDBReader(absFileName, + QHelpGlobal::uniquifyConnectionName(info.fileName, this), this); + if (!reader->init()) { + emit q->warning(QHelpEngineCore::tr("Cannot open documentation file %1: %2!") + .arg(absFileName, reader->errorMessage())); + continue; + } + + readerMap.insert(info.namespaceName, reader); + fileNameReaderMap.insert(absFileName, reader); + virtualFolderMap.insert(info.folderName, reader); + orderedFileNameList.append(absFileName); + } + q->currentFilter(); + emit q->setupFinished(); + return true; +} + +void QHelpEngineCorePrivate::errorReceived(const QString &msg) +{ + error = msg; +} + + + +/*! + \class QHelpEngineCore + \since 4.4 + \inmodule QtHelp + \brief The QHelpEngineCore class provides the core functionality + of the help system. + + Before the help engine can be used, it must be initialized by + calling setupData(). At the beginning of the setup process the + signal setupStarted() is emitted. From this point on until + the signal setupFinished() is emitted, is the help data in an + undefined meaning unusable state. + + The core help engine can be used to perform different tasks. + By calling linksForIdentifier() the engine returns + urls specifying the file locations inside the help system. The + actual file data can then be retrived by calling fileData(). In + contrast to all other functions in this class, linksForIdentifier() + depends on the currently set custom filter. Depending on the filter, + the function may return different hits. + + Every help engine can contain any number of custom filters. A custom + filter is defined by a name and set of filter attributes and can be + added to the help engine by calling addCustomFilter(). Analogous, + it is removed by calling removeCustomFilter(). customFilters() returns + all defined filters. + + The help engine also offers the possibility to set and read values + in a persistant way comparable to ini files or Windows registry + entries. For more information see setValue() or value(). + + This class does not offer any GUI components or functionality for + indices or contents. If you need one of those use QHelpEngine + instead. + + When creating a custom help viewer the viewer can be + configured by writing a custom collection file which could contain various + keywords to be used to configure the help engine. These keywords and values + and their meaning can be found in the help information for + \l{assistant-custom-help-viewer.html#creating-a-custom-help-collection-file} + {creating a custom help collection file} for Assistant. +*/ + +/*! + \fn void QHelpEngineCore::setupStarted() + + This signal is emitted when setup is started. +*/ + +/*! + \fn void QHelpEngineCore::setupFinished() + + This signal is emitted when the setup is complete. +*/ + +/*! + \fn void QHelpEngineCore::currentFilterChanged(const QString &newFilter) + + This signal is emitted when the current filter is changed to + \a newFilter. +*/ + +/*! + \fn void QHelpEngineCore::warning(const QString &msg) + + This signal is emitted when a non critical error occurs. + The warning message is stored in \a msg. +*/ + +/*! + Constructs a new core help engine with a \a parent. The help engine + uses the information stored in the \a collectionFile to provide help. + If the collection file does not exist yet, it'll be created. +*/ +QHelpEngineCore::QHelpEngineCore(const QString &collectionFile, QObject *parent) + : QObject(parent) +{ + d = new QHelpEngineCorePrivate(); + d->init(collectionFile, this); +} + +/*! + \internal +*/ +QHelpEngineCore::QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, + QObject *parent) + : QObject(parent) +{ + d = helpEngineCorePrivate; +} + +/*! + Destructs the help engine. +*/ +QHelpEngineCore::~QHelpEngineCore() +{ + delete d; +} + +/*! + \property QHelpEngineCore::collectionFile + \brief the absolute file name of the collection file currently used. + \since 4.5 + + Setting this property leaves the help engine in an invalid state. It is + important to invoke setupData() or any getter function in order to setup + the help engine again. +*/ +QString QHelpEngineCore::collectionFile() const +{ + return d->collectionHandler->collectionFile(); +} + +void QHelpEngineCore::setCollectionFile(const QString &fileName) +{ + if (fileName == collectionFile()) + return; + + if (d->collectionHandler) { + delete d->collectionHandler; + d->collectionHandler = 0; + d->clearMaps(); + } + d->init(fileName, this); + d->needsSetup = true; +} + +/*! + Sets up the help engine by processing the information found + in the collection file and returns true if successful; otherwise + returns false. + + By calling the function, the help + engine is forced to initialize itself immediately. Most of + the times, this function does not have to be called + explicitly because getter functions which depend on a correctly + set up help engine do that themselves. + + \note \c{qsqlite4.dll} needs to be deployed with the application as the + help system uses the sqlite driver when loading help collections. +*/ +bool QHelpEngineCore::setupData() +{ + d->needsSetup = true; + return d->setup(); +} + +/*! + Creates the file \a fileName and copies all contents from + the current collection file into the newly created file, + and returns true if successful; otherwise returns false. + + The copying process makes sure that file references to Qt + Collection files (\c{.qch}) files are updated accordingly. +*/ +bool QHelpEngineCore::copyCollectionFile(const QString &fileName) +{ + if (!d->setup()) + return false; + return d->collectionHandler->copyCollectionFile(fileName); +} + +/*! + Returns the namespace name defined for the Qt compressed help file (.qch) + specified by its \a documentationFileName. If the file is not valid, an + empty string is returned. + + \sa documentationFileName() +*/ +QString QHelpEngineCore::namespaceName(const QString &documentationFileName) +{ + QHelpDBReader reader(documentationFileName, + QHelpGlobal::uniquifyConnectionName(QLatin1String("GetNamespaceName"), + QThread::currentThread()), 0); + if (reader.init()) + return reader.namespaceName(); + return QString(); +} + +/*! + Registers the Qt compressed help file (.qch) contained in the file + \a documentationFileName. One compressed help file, uniquely + identified by its namespace can only be registered once. + True is returned if the registration was successful, otherwise + false. + + \sa unregisterDocumentation(), error() +*/ +bool QHelpEngineCore::registerDocumentation(const QString &documentationFileName) +{ + d->error.clear(); + d->needsSetup = true; + return d->collectionHandler->registerDocumentation(documentationFileName); +} + +/*! + Unregisters the Qt compressed help file (.qch) identified by its + \a namespaceName from the help collection. Returns true + on success, otherwise false. + + \sa registerDocumentation(), error() +*/ +bool QHelpEngineCore::unregisterDocumentation(const QString &namespaceName) +{ + d->error.clear(); + d->needsSetup = true; + return d->collectionHandler->unregisterDocumentation(namespaceName); +} + +/*! + Returns the absolute file name of the Qt compressed help file (.qch) + identified by the \a namespaceName. If there is no Qt compressed help file + with the specified namespace registered, an empty string is returned. + + \sa namespaceName() +*/ +QString QHelpEngineCore::documentationFileName(const QString &namespaceName) +{ + if (d->setup()) { + const QHelpCollectionHandler::DocInfoList docList = + d->collectionHandler->registeredDocumentations(); + foreach(const QHelpCollectionHandler::DocInfo &info, docList) { + if (info.namespaceName == namespaceName) { + if (QDir::isAbsolutePath(info.fileName)) + return QDir::cleanPath(info.fileName); + + QFileInfo fi(d->collectionHandler->collectionFile()); + fi.setFile(fi.absolutePath() + QDir::separator() + info.fileName); + return QDir::cleanPath(fi.absoluteFilePath()); + } + } + } + return QString(); +} + +/*! + Returns a list of all registered Qt compressed help files of the current collection file. + The returned names are the namespaces of the registered Qt compressed help files (.qch). +*/ +QStringList QHelpEngineCore::registeredDocumentations() const +{ + QStringList list; + if (!d->setup()) + return list; + const QHelpCollectionHandler::DocInfoList docList = d->collectionHandler->registeredDocumentations(); + foreach(const QHelpCollectionHandler::DocInfo &info, docList) { + list.append(info.namespaceName); + } + return list; +} + +/*! + Returns a list of custom filters. + + \sa addCustomFilter(), removeCustomFilter() +*/ +QStringList QHelpEngineCore::customFilters() const +{ + if (!d->setup()) + return QStringList(); + return d->collectionHandler->customFilters(); +} + +/*! + Adds the new custom filter \a filterName. The filter attributes + are specified by \a attributes. If the filter already exists, + its attribute set is replaced. The function returns true if + the operation succeeded, otherwise it returns false. + + \sa customFilters(), removeCustomFilter() +*/ +bool QHelpEngineCore::addCustomFilter(const QString &filterName, + const QStringList &attributes) +{ + d->error.clear(); + d->needsSetup = true; + return d->collectionHandler->addCustomFilter(filterName, + attributes); +} + +/*! + Returns true if the filter \a filterName was removed successfully, + otherwise false. + + \sa addCustomFilter(), customFilters() +*/ +bool QHelpEngineCore::removeCustomFilter(const QString &filterName) +{ + d->error.clear(); + d->needsSetup = true; + return d->collectionHandler->removeCustomFilter(filterName); +} + +/*! + Returns a list of all defined filter attributes. +*/ +QStringList QHelpEngineCore::filterAttributes() const +{ + if (!d->setup()) + return QStringList(); + return d->collectionHandler->filterAttributes(); +} + +/*! + Returns a list of filter attributes used by the custom + filter \a filterName. +*/ +QStringList QHelpEngineCore::filterAttributes(const QString &filterName) const +{ + if (!d->setup()) + return QStringList(); + return d->collectionHandler->filterAttributes(filterName); +} + +/*! + \property QHelpEngineCore::currentFilter + \brief the name of the custom filter currently applied. + \since 4.5 + + Setting this property will save the new custom filter permanently in the + help collection file. To set a custom filter without saving it + permanently, disable the auto save filter mode. + + \sa autoSaveFilter() +*/ +QString QHelpEngineCore::currentFilter() const +{ + if (!d->setup()) + return QString(); + + if (d->currentFilter.isEmpty()) { + QString filter = + d->collectionHandler->customValue(QLatin1String("CurrentFilter"), + QString()).toString(); + if (!filter.isEmpty() + && d->collectionHandler->customFilters().contains(filter)) + d->currentFilter = filter; + } + return d->currentFilter; +} + +void QHelpEngineCore::setCurrentFilter(const QString &filterName) +{ + if (!d->setup() || filterName == d->currentFilter) + return; + d->currentFilter = filterName; + if (d->autoSaveFilter) { + d->collectionHandler->setCustomValue(QLatin1String("CurrentFilter"), + d->currentFilter); + } + emit currentFilterChanged(d->currentFilter); +} + +/*! + Returns a list of filter attributes for the different filter sections + defined in the Qt compressed help file with the given namespace + \a namespaceName. +*/ +QList QHelpEngineCore::filterAttributeSets(const QString &namespaceName) const +{ + if (d->setup()) { + QHelpDBReader *reader = d->readerMap.value(namespaceName); + if (reader) + return reader->filterAttributeSets(); + } + return QList(); +} + +/*! + Returns a list of files contained in the Qt compressed help file \a + namespaceName. The files can be filtered by \a filterAttributes as + well as by their extension \a extensionFilter (e.g. 'html'). +*/ +QList QHelpEngineCore::files(const QString namespaceName, + const QStringList &filterAttributes, + const QString &extensionFilter) +{ + QList res; + if (!d->setup()) + return res; + QHelpDBReader *reader = d->readerMap.value(namespaceName); + if (!reader) { + d->error = tr("The specified namespace does not exist!"); + return res; + } + + QUrl url; + url.setScheme(QLatin1String("qthelp")); + url.setAuthority(namespaceName); + + const QStringList files = reader->files(filterAttributes, extensionFilter); + foreach (const QString &file, files) { + url.setPath(QLatin1String("/") + file); + res.append(url); + } + return res; +} + +/*! + Returns an invalid URL if the file \a url cannot be found. + If the file exists, either the same url is returned or a + different url if the file is located in a different namespace + which is merged via a common virtual folder. +*/ +QUrl QHelpEngineCore::findFile(const QUrl &url) const +{ + QUrl res; + if (!d->setup() || !url.isValid() || url.toString().count(QLatin1Char('/')) < 4 + || url.scheme() != QLatin1String("qthelp")) + return res; + + QString ns = url.authority(); + QString filePath = QDir::cleanPath(url.path()); + if (filePath.startsWith(QLatin1Char('/'))) + filePath = filePath.mid(1); + QString virtualFolder = filePath.mid(0, filePath.indexOf(QLatin1Char('/'), 1)); + filePath = filePath.mid(virtualFolder.length()+1); + + QHelpDBReader *defaultReader = 0; + if (d->readerMap.contains(ns)) { + defaultReader = d->readerMap.value(ns); + if (defaultReader->fileExists(virtualFolder, filePath)) + return url; + } + + QStringList filterAtts = filterAttributes(currentFilter()); + foreach (QHelpDBReader *reader, d->virtualFolderMap.values(virtualFolder)) { + if (reader == defaultReader) + continue; + if (reader->fileExists(virtualFolder, filePath, filterAtts)) { + res = url; + res.setAuthority(reader->namespaceName()); + return res; + } + } + + foreach (QHelpDBReader *reader, d->virtualFolderMap.values(virtualFolder)) { + if (reader == defaultReader) + continue; + if (reader->fileExists(virtualFolder, filePath)) { + res = url; + res.setAuthority(reader->namespaceName()); + break; + } + } + + return res; +} + +/*! + Returns the data of the file specified by \a url. If the + file does not exist, an empty QByteArray is returned. + + \sa findFile() +*/ +QByteArray QHelpEngineCore::fileData(const QUrl &url) const +{ + if (!d->setup() || !url.isValid() || url.toString().count(QLatin1Char('/')) < 4 + || url.scheme() != QLatin1String("qthelp")) + return QByteArray(); + + QString ns = url.authority(); + QString filePath = QDir::cleanPath(url.path()); + if (filePath.startsWith(QLatin1Char('/'))) + filePath = filePath.mid(1); + QString virtualFolder = filePath.mid(0, filePath.indexOf(QLatin1Char('/'), 1)); + filePath = filePath.mid(virtualFolder.length()+1); + + QByteArray ba; + QHelpDBReader *defaultReader = 0; + if (d->readerMap.contains(ns)) { + defaultReader = d->readerMap.value(ns); + ba = defaultReader->fileData(virtualFolder, filePath); + } + + if (ba.isEmpty()) { + foreach (QHelpDBReader *reader, d->virtualFolderMap.values(virtualFolder)) { + if (reader == defaultReader) + continue; + ba = reader->fileData(virtualFolder, filePath); + if (!ba.isEmpty()) + return ba; + } + } + return ba; +} + +/*! + Returns a map of hits found for the \a id. A hit contains the + title of the document and the url where the keyword is located. + The result depends on the current filter, meaning only the keywords + registered for the current filter will be returned. +*/ +QMap QHelpEngineCore::linksForIdentifier(const QString &id) const +{ + QMap linkMap; + if (!d->setup()) + return linkMap; + + QStringList atts = filterAttributes(d->currentFilter); + foreach (QHelpDBReader *reader, d->readerMap) + reader->linksForIdentifier(id, atts, linkMap); + + return linkMap; +} + +/*! + Removes the \a key from the settings section in the + collection file. Returns true if the value was removed + successfully, otherwise false. + + \sa customValue(), setCustomValue() +*/ +bool QHelpEngineCore::removeCustomValue(const QString &key) +{ + d->error.clear(); + return d->collectionHandler->removeCustomValue(key); +} + +/*! + Returns the value assigned to the \a key. If the requested + key does not exist, the specified \a defaultValue is + returned. + + \sa setCustomValue(), removeCustomValue() +*/ +QVariant QHelpEngineCore::customValue(const QString &key, const QVariant &defaultValue) const +{ + if (!d->setup()) + return QVariant(); + return d->collectionHandler->customValue(key, defaultValue); +} + +/*! + Save the \a value under the \a key. If the key already exist, + the value will be overwritten. Returns true if the value was + saved successfully, otherwise false. + + \sa customValue(), removeCustomValue() +*/ +bool QHelpEngineCore::setCustomValue(const QString &key, const QVariant &value) +{ + d->error.clear(); + return d->collectionHandler->setCustomValue(key, value); +} + +/*! + Returns the meta data for the Qt compressed help file \a + documentationFileName. If there is no data available for + \a name, an invalid QVariant() is returned. The meta + data is defined when creating the Qt compressed help file and + cannot be modified later. Common meta data includes e.g. + the author of the documentation. +*/ +QVariant QHelpEngineCore::metaData(const QString &documentationFileName, + const QString &name) +{ + QHelpDBReader reader(documentationFileName, QLatin1String("GetMetaData"), 0); + + if (reader.init()) + return reader.metaData(name); + return QVariant(); +} + +/*! + Returns a description of the last error that occurred. +*/ +QString QHelpEngineCore::error() const +{ + return d->error; +} + +/*! + \property QHelpEngineCore::autoSaveFilter + \brief whether QHelpEngineCore is in auto save filter mode or not. + \since 4.5 + + If QHelpEngineCore is in auto save filter mode, the current filter is + automatically saved when it is changed by the setCurrentFilter() + function. The filter is saved persistently in the help collection file. + + By default, this mode is on. +*/ +void QHelpEngineCore::setAutoSaveFilter(bool save) +{ + d->autoSaveFilter = save; +} + +bool QHelpEngineCore::autoSaveFilter() const +{ + return d->autoSaveFilter; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpenginecore.h b/src/assistant/lib/qhelpenginecore.h new file mode 100644 index 0000000..fbfb8a0 --- /dev/null +++ b/src/assistant/lib/qhelpenginecore.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPENGINECORE_H +#define QHELPENGINECORE_H + +#include + +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +class QHelpEngineCorePrivate; + +class QHELP_EXPORT QHelpEngineCore : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool autoSaveFilter READ autoSaveFilter WRITE setAutoSaveFilter) + Q_PROPERTY(QString collectionFile READ collectionFile WRITE setCollectionFile) + Q_PROPERTY(QString currentFilter READ currentFilter WRITE setCurrentFilter) + +public: + explicit QHelpEngineCore(const QString &collectionFile, QObject *parent = 0); + virtual ~QHelpEngineCore(); + + bool setupData(); + + QString collectionFile() const; + void setCollectionFile(const QString &fileName); + + bool copyCollectionFile(const QString &fileName); + + static QString namespaceName(const QString &documentationFileName); + bool registerDocumentation(const QString &documentationFileName); + bool unregisterDocumentation(const QString &namespaceName); + QString documentationFileName(const QString &namespaceName); + + QStringList customFilters() const; + bool removeCustomFilter(const QString &filterName); + bool addCustomFilter(const QString &filterName, + const QStringList &attributes); + + QStringList filterAttributes() const; + QStringList filterAttributes(const QString &filterName) const; + + QString currentFilter() const; + void setCurrentFilter(const QString &filterName); + + QStringList registeredDocumentations() const; + QList filterAttributeSets(const QString &namespaceName) const; + QList files(const QString namespaceName, + const QStringList &filterAttributes, + const QString &extensionFilter = QString()); + QUrl findFile(const QUrl &url) const; + QByteArray fileData(const QUrl &url) const; + + QMap linksForIdentifier(const QString &id) const; + + bool removeCustomValue(const QString &key); + QVariant customValue(const QString &key, + const QVariant &defaultValue = QVariant()) const; + bool setCustomValue(const QString &key, const QVariant &value); + + static QVariant metaData(const QString &documentationFileName, + const QString &name); + + QString error() const; + + void setAutoSaveFilter(bool save); + bool autoSaveFilter() const; + +Q_SIGNALS: + void setupStarted(); + void setupFinished(); + void currentFilterChanged(const QString &newFilter); + void warning(const QString &msg); + +protected: + QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, + QObject *parent); + +private: + QHelpEngineCorePrivate *d; + friend class QHelpEngineCorePrivate; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHELPENGINECORE_H diff --git a/src/assistant/lib/qhelpgenerator.cpp b/src/assistant/lib/qhelpgenerator.cpp new file mode 100644 index 0000000..ce9c856 --- /dev/null +++ b/src/assistant/lib/qhelpgenerator.cpp @@ -0,0 +1,909 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpgenerator_p.h" +#include "qhelpdatainterface_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QHelpGeneratorPrivate +{ +public: + QHelpGeneratorPrivate(); + ~QHelpGeneratorPrivate(); + + QString error; + QSqlQuery *query; + + int namespaceId; + int virtualFolderId; + + QMap fileMap; + QMap > fileFilterMap; + + double progress; + double oldProgress; + double contentStep; + double fileStep; + double indexStep; +}; + +QHelpGeneratorPrivate::QHelpGeneratorPrivate() +{ + query = 0; + namespaceId = -1; + virtualFolderId = -1; +} + +QHelpGeneratorPrivate::~QHelpGeneratorPrivate() +{ +} + + + +/*! + \internal + \class QHelpGenerator + \since 4.4 + \brief The QHelpGenerator class generates a new + Qt compressed help file (.qch). + + The help generator takes a help data structure as + input for generating a new Qt compressed help files. Since + the generation may takes some time, the generator emits + various signals to inform about its current state. +*/ + +/*! + \fn void QHelpGenerator::statusChanged(const QString &msg) + + This signal is emitted when the generation status changes. + The status is basically a specific task like inserting + files or building up the keyword index. The parameter + \a msg contains the detailed status description. +*/ + +/*! + \fn void QHelpGenerator::progressChanged(double progress) + + This signal is emitted when the progress changes. The + \a progress ranges from 0 to 100. +*/ + +/*! + \fn void QHelpGenerator::warning(const QString &msg) + + This signal is emitted when a non critical error occurs, + e.g. when a referenced file cannot be found. \a msg + contains the exact warning message. +*/ + +/*! + Constructs a new help generator with the give \a parent. +*/ +QHelpGenerator::QHelpGenerator(QObject *parent) + : QObject(parent) +{ + d = new QHelpGeneratorPrivate; +} + +/*! + Destructs the help generator. +*/ +QHelpGenerator::~QHelpGenerator() +{ + delete d; +} + +/*! + Takes the \a helpData and generates a new documentation + set from it. The Qt compressed help file is written to \a + outputFileName. Returns true on success, otherwise false. +*/ +bool QHelpGenerator::generate(QHelpDataInterface *helpData, + const QString &outputFileName) +{ + emit progressChanged(0); + d->error.clear(); + if (!helpData || helpData->namespaceName().isEmpty()) { + d->error = tr("Invalid help data!"); + return false; + } + + QString outFileName = outputFileName; + if (outFileName.isEmpty()) { + d->error = tr("No output file name specified!"); + return false; + } + + QFileInfo fi(outFileName); + if (fi.exists()) { + if (!fi.dir().remove(fi.fileName())) { + d->error = tr("The file %1 cannot be overwritten!").arg(outFileName); + return false; + } + } + + setupProgress(helpData); + + emit statusChanged(tr("Building up file structure...")); + bool openingOk = true; + { + QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("builder")); + db.setDatabaseName(outFileName); + openingOk = db.open(); + if (openingOk) + d->query = new QSqlQuery(db); + } + + if (!openingOk) { + d->error = tr("Cannot open data base file %1!").arg(outFileName); + cleanupDB(); + return false; + } + + d->query->exec(QLatin1String("PRAGMA synchronous=OFF")); + d->query->exec(QLatin1String("PRAGMA cache_size=3000")); + + addProgress(1.0); + createTables(); + insertFileNotFoundFile(); + insertMetaData(helpData->metaData()); + + if (!registerVirtualFolder(helpData->virtualFolder(), helpData->namespaceName())) { + d->error = tr("Cannot register namespace %1!").arg(helpData->namespaceName()); + cleanupDB(); + return false; + } + addProgress(1.0); + + emit statusChanged(tr("Insert custom filters...")); + foreach (const QHelpDataCustomFilter &f, helpData->customFilters()) { + if (!registerCustomFilter(f.name, f.filterAttributes, true)) { + cleanupDB(); + return false; + } + } + addProgress(1.0); + + int i = 1; + QList::const_iterator it = helpData->filterSections().constBegin(); + while (it != helpData->filterSections().constEnd()) { + emit statusChanged(tr("Insert help data for filter section (%1 of %2)...") + .arg(i++).arg(helpData->filterSections().count())); + insertFilterAttributes((*it).filterAttributes()); + QByteArray ba; + QDataStream s(&ba, QIODevice::WriteOnly); + foreach (QHelpDataContentItem *itm, (*it).contents()) + writeTree(s, itm, 0); + if (!insertFiles((*it).files(), helpData->rootPath(), (*it).filterAttributes()) + || !insertContents(ba, (*it).filterAttributes()) + || !insertKeywords((*it).indices(), (*it).filterAttributes())) { + cleanupDB(); + return false; + } + ++it; + } + + cleanupDB(); + emit progressChanged(100); + emit statusChanged(tr("Documentation successfully generated.")); + return true; +} + +void QHelpGenerator::setupProgress(QHelpDataInterface *helpData) +{ + d->progress = 0; + d->oldProgress = 0; + + int numberOfFiles = 0; + int numberOfIndices = 0; + QList::const_iterator it = helpData->filterSections().constBegin(); + while (it != helpData->filterSections().constEnd()) { + numberOfFiles += (*it).files().count(); + numberOfIndices += (*it).indices().count(); + ++it; + } + // init 2% + // filters 1% + // contents 10% + // files 60% + // indices 27% + d->contentStep = 10.0/(double)helpData->customFilters().count(); + d->fileStep = 60.0/(double)numberOfFiles; + d->indexStep = 27.0/(double)numberOfIndices; +} + +void QHelpGenerator::addProgress(double step) +{ + d->progress += step; + if ((d->progress-d->oldProgress) >= 1.0 && d->progress <= 100.0) { + d->oldProgress = d->progress; + emit progressChanged(ceil(d->progress)); + } +} + +void QHelpGenerator::cleanupDB() +{ + if (d->query) { + d->query->clear(); + delete d->query; + d->query = 0; + } + QSqlDatabase::removeDatabase(QLatin1String("builder")); +} + +void QHelpGenerator::writeTree(QDataStream &s, QHelpDataContentItem *item, int depth) +{ + QString fReference = QDir::cleanPath(item->reference()); + if (fReference.startsWith(QLatin1String("./"))) + fReference = fReference.mid(2); + + s << depth; + s << fReference; + s << item->title(); + foreach (QHelpDataContentItem *i, item->children()) + writeTree(s, i, depth+1); +} + +/*! + Returns the last error message. +*/ +QString QHelpGenerator::error() const +{ + return d->error; +} + +bool QHelpGenerator::createTables() +{ + if (!d->query) + return false; + + d->query->exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'" + "AND Name=\'NamespaceTable\'")); + d->query->next(); + if (d->query->value(0).toInt() > 0) { + d->error = tr("Some tables already exist!"); + return false; + } + + QStringList tables; + tables << QLatin1String("CREATE TABLE NamespaceTable (" + "Id INTEGER PRIMARY KEY," + "Name TEXT )") + << QLatin1String("CREATE TABLE FilterAttributeTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT )") + << QLatin1String("CREATE TABLE FilterNameTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT )") + << QLatin1String("CREATE TABLE FilterTable (" + "NameId INTEGER, " + "FilterAttributeId INTEGER )") + << QLatin1String("CREATE TABLE IndexTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT, " + "Identifier TEXT, " + "NamespaceId INTEGER, " + "FileId INTEGER, " + "Anchor TEXT )") + << QLatin1String("CREATE TABLE IndexItemTable (" + "Id INTEGER, " + "IndexId INTEGER )") + << QLatin1String("CREATE TABLE IndexFilterTable (" + "FilterAttributeId INTEGER, " + "IndexId INTEGER )") + << QLatin1String("CREATE TABLE ContentsTable (" + "Id INTEGER PRIMARY KEY, " + "NamespaceId INTEGER, " + "Data BLOB )") + << QLatin1String("CREATE TABLE ContentsFilterTable (" + "FilterAttributeId INTEGER, " + "ContentsId INTEGER )") + << QLatin1String("CREATE TABLE FileAttributeSetTable (" + "Id INTEGER, " + "FilterAttributeId INTEGER )") + << QLatin1String("CREATE TABLE FileDataTable (" + "Id INTEGER PRIMARY KEY, " + "Data BLOB )") + << QLatin1String("CREATE TABLE FileFilterTable (" + "FilterAttributeId INTEGER, " + "FileId INTEGER )") + << QLatin1String("CREATE TABLE FileNameTable (" + "FolderId INTEGER, " + "Name TEXT, " + "FileId INTEGER, " + "Title TEXT )") + << QLatin1String("CREATE TABLE FolderTable(" + "Id INTEGER PRIMARY KEY, " + "Name Text, " + "NamespaceID INTEGER )") + << QLatin1String("CREATE TABLE MetaDataTable(" + "Name Text, " + "Value BLOB )"); + + foreach (const QString &q, tables) { + if (!d->query->exec(q)) { + d->error = tr("Cannot create tables!"); + return false; + } + } + + d->query->exec(QLatin1String("INSERT INTO MetaDataTable VALUES('qchVersion', '1.0')")); + + d->query->prepare(QLatin1String("INSERT INTO MetaDataTable VALUES('CreationDate', ?)")); + d->query->bindValue(0, QDateTime::currentDateTime().toString(Qt::ISODate)); + d->query->exec(); + + return true; +} + +bool QHelpGenerator::insertFileNotFoundFile() +{ + if (!d->query) + return false; + + d->query->exec(QLatin1String("SELECT id FROM FileNameTable WHERE Name=\'\'")); + if (d->query->next() && d->query->isValid()) + return true; + + d->query->prepare(QLatin1String("INSERT INTO FileDataTable VALUES (Null, ?)")); + d->query->bindValue(0, QByteArray()); + if (!d->query->exec()) + return false; + + int fileId = d->query->lastInsertId().toInt(); + d->query->prepare(QLatin1String("INSERT INTO FileNameTable (FolderId, Name, FileId, Title) " + " VALUES (0, '', ?, '')")); + d->query->bindValue(0, fileId); + if (fileId > -1 && d->query->exec()) { + d->fileMap.insert(QString(), fileId); + return true; + } + return false; +} + +bool QHelpGenerator::registerVirtualFolder(const QString &folderName, const QString &ns) +{ + if (!d->query || folderName.isEmpty() || ns.isEmpty()) + return false; + + d->query->prepare(QLatin1String("SELECT Id FROM FolderTable WHERE Name=?")); + d->query->bindValue(0, folderName); + d->query->exec(); + d->query->next(); + if (d->query->isValid() && d->query->value(0).toInt() > 0) + return true; + + d->namespaceId = -1; + d->query->prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name=?")); + d->query->bindValue(0, ns); + d->query->exec(); + while (d->query->next()) { + d->namespaceId = d->query->value(0).toInt(); + break; + } + + if (d->namespaceId < 0) { + d->query->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?)")); + d->query->bindValue(0, ns); + if (d->query->exec()) + d->namespaceId = d->query->lastInsertId().toInt(); + } + + if (d->namespaceId > 0) { + d->query->prepare(QLatin1String("SELECT Id FROM FolderTable WHERE Name=?")); + d->query->bindValue(0, folderName); + d->query->exec(); + while (d->query->next()) + d->virtualFolderId = d->query->value(0).toInt(); + + if (d->virtualFolderId > 0) + return true; + + d->query->prepare(QLatin1String("INSERT INTO FolderTable (NamespaceId, Name) " + "VALUES (?, ?)")); + d->query->bindValue(0, d->namespaceId); + d->query->bindValue(1, folderName); + if (d->query->exec()) { + d->virtualFolderId = d->query->lastInsertId().toInt(); + return d->virtualFolderId > 0; + } + } + d->error = tr("Cannot register virtual folder!"); + return false; +} + +bool QHelpGenerator::insertFiles(const QStringList &files, const QString &rootPath, + const QStringList &filterAttributes) +{ + if (!d->query) + return false; + + emit statusChanged(tr("Insert files...")); + QList filterAtts; + foreach (const QString &filterAtt, filterAttributes) { + d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable " + "WHERE Name=?")); + d->query->bindValue(0, filterAtt); + d->query->exec(); + if (d->query->next()) + filterAtts.append(d->query->value(0).toInt()); + } + + int filterSetId = -1; + d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileAttributeSetTable")); + if (d->query->next()) + filterSetId = d->query->value(0).toInt(); + if (filterSetId < 0) + return false; + ++filterSetId; + foreach (const int &attId, filterAtts) { + d->query->prepare(QLatin1String("INSERT INTO FileAttributeSetTable " + "VALUES(?, ?)")); + d->query->bindValue(0, filterSetId); + d->query->bindValue(1, attId); + d->query->exec(); + } + + int tableFileId = 1; + d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable")); + if (d->query->next()) + tableFileId = d->query->value(0).toInt() + 1; + + QString title; + QString charSet; + FileNameTableData fileNameData; + QList fileDataList; + QMap > tmpFileFilterMap; + QList fileNameDataList; + + int i = 0; + foreach (const QString &file, files) { + const QString fileName = QDir::cleanPath(file); + if (fileName.startsWith(QLatin1String("../"))) { + emit warning(tr("The referenced file %1 must be inside or within a " + "subdirectory of (%2). Skipping it.").arg(fileName).arg(rootPath)); + continue; + } + + QFile fi(rootPath + QDir::separator() + fileName); + if (!fi.exists()) { + emit warning(tr("The file %1 does not exist! Skipping it.") + .arg(QDir::cleanPath(rootPath + QDir::separator() + fileName))); + continue; + } + + if (!fi.open(QIODevice::ReadOnly)) { + emit warning(tr("Cannot open file %1! Skipping it.") + .arg(QDir::cleanPath(rootPath + QDir::separator() + fileName))); + continue; + } + + QByteArray data = fi.readAll(); + if (fileName.endsWith(QLatin1String(".html")) + || fileName.endsWith(QLatin1String(".htm"))) { + charSet = QHelpGlobal::codecFromData(data); + QTextStream stream(&data); + stream.setCodec(QTextCodec::codecForName(charSet.toLatin1().constData())); + title = QHelpGlobal::documentTitle(stream.readAll()); + } else { + title = fileName.mid(fileName.lastIndexOf(QLatin1Char('/')) + 1); + } + + int fileId = -1; + QMap::Iterator fileMapIt = d->fileMap.find(fileName); + if (fileMapIt == d->fileMap.end()) { + fileDataList.append(qCompress(data)); + + fileNameData.name = fileName; + fileNameData.fileId = tableFileId; + fileNameData.title = title; + fileNameDataList.append(fileNameData); + + d->fileMap.insert(fileName, tableFileId); + d->fileFilterMap.insert(tableFileId, filterAtts.toSet()); + tmpFileFilterMap.insert(tableFileId, filterAtts.toSet()); + + ++tableFileId; + } else { + fileId = fileMapIt.value(); + QSet &fileFilterSet = d->fileFilterMap[fileId]; + QSet &tmpFileFilterSet = tmpFileFilterMap[fileId]; + foreach (const int &filter, filterAtts) { + if (!fileFilterSet.contains(filter) + && !tmpFileFilterSet.contains(filter)) { + fileFilterSet.insert(filter); + tmpFileFilterSet.insert(filter); + } + } + } + } + + if (!tmpFileFilterMap.isEmpty()) { + d->query->exec(QLatin1String("BEGIN")); + QMap >::const_iterator it = tmpFileFilterMap.constBegin(); + while (it != tmpFileFilterMap.constEnd()) { + QSet::const_iterator si = it.value().constBegin(); + while (si != it.value().constEnd()) { + d->query->prepare(QLatin1String("INSERT INTO FileFilterTable " + "VALUES(?, ?)")); + d->query->bindValue(0, *si); + d->query->bindValue(1, it.key()); + d->query->exec(); + ++si; + } + ++it; + } + + QList::const_iterator fileIt = fileDataList.constBegin(); + while (fileIt != fileDataList.constEnd()) { + d->query->prepare(QLatin1String("INSERT INTO FileDataTable VALUES " + "(Null, ?)")); + d->query->bindValue(0, *fileIt); + d->query->exec(); + ++fileIt; + if (++i%20 == 0) + addProgress(d->fileStep*20.0); + } + + QList::const_iterator fileNameIt = + fileNameDataList.constBegin(); + while (fileNameIt != fileNameDataList.constEnd()) { + d->query->prepare(QLatin1String("INSERT INTO FileNameTable " + "(FolderId, Name, FileId, Title) VALUES (?, ?, ?, ?)")); + d->query->bindValue(0, 1); + d->query->bindValue(1, (*fileNameIt).name); + d->query->bindValue(2, (*fileNameIt).fileId); + d->query->bindValue(3, (*fileNameIt).title); + d->query->exec(); + ++fileNameIt; + } + d->query->exec(QLatin1String("COMMIT")); + } + + d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable")); + if (d->query->next() + && d->query->value(0).toInt() == tableFileId-1) { + addProgress(d->fileStep*(i%20)); + return true; + } + return false; +} + +bool QHelpGenerator::registerCustomFilter(const QString &filterName, + const QStringList &filterAttribs, bool forceUpdate) +{ + if (!d->query) + return false; + + d->query->exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable")); + QStringList idsToInsert = filterAttribs; + QMap attributeMap; + while (d->query->next()) { + attributeMap.insert(d->query->value(1).toString(), + d->query->value(0).toInt()); + idsToInsert.removeAll(d->query->value(1).toString()); + } + + foreach (const QString &id, idsToInsert) { + d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); + d->query->bindValue(0, id); + d->query->exec(); + attributeMap.insert(id, d->query->lastInsertId().toInt()); + } + + int nameId = -1; + d->query->prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?")); + d->query->bindValue(0, filterName); + d->query->exec(); + while (d->query->next()) { + nameId = d->query->value(0).toInt(); + break; + } + + if (nameId < 0) { + d->query->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)")); + d->query->bindValue(0, filterName); + if (d->query->exec()) + nameId = d->query->lastInsertId().toInt(); + } else if (!forceUpdate) { + d->error = tr("The filter %1 is already registered!").arg(filterName); + return false; + } + + if (nameId < 0) { + d->error = tr("Cannot register filter %1!").arg(filterName); + return false; + } + + d->query->prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?")); + d->query->bindValue(0, nameId); + d->query->exec(); + + foreach (const QString &att, filterAttribs) { + d->query->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)")); + d->query->bindValue(0, nameId); + d->query->bindValue(1, attributeMap[att]); + if (!d->query->exec()) + return false; + } + return true; +} + +bool QHelpGenerator::insertKeywords(const QList &keywords, + const QStringList &filterAttributes) +{ + if (!d->query) + return false; + + emit statusChanged(tr("Insert indices...")); + int indexId = 1; + d->query->exec(QLatin1String("SELECT MAX(Id) FROM IndexTable")); + if (d->query->next()) + indexId = d->query->value(0).toInt() + 1; + + QList filterAtts; + foreach (const QString &filterAtt, filterAttributes) { + d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable WHERE Name=?")); + d->query->bindValue(0, filterAtt); + d->query->exec(); + if (d->query->next()) + filterAtts.append(d->query->value(0).toInt()); + } + + int pos = -1; + QString fileName; + QString anchor; + QString fName; + int fileId = 1; + QList indexFilterTable; + + int i = 0; + d->query->exec(QLatin1String("BEGIN")); + QSet indices; + foreach (const QHelpDataIndexItem &itm, keywords) { + // Identical ids make no sense and just confuse the Assistant user, + // so we ignore all repetitions. + if (indices.contains(itm.identifier)) + continue; + + // Still empty ids should be ignored, as otherwise we will include only + // the first keyword with an empty id. + if (!itm.identifier.isEmpty()) + indices.insert(itm.identifier); + + pos = itm.reference.indexOf(QLatin1Char('#')); + fileName = itm.reference.left(pos); + if (pos > -1) + anchor = itm.reference.mid(pos+1); + else + anchor.clear(); + + fName = QDir::cleanPath(fileName); + if (fName.startsWith(QLatin1String("./"))) + fName = fName.mid(2); + + QMap::ConstIterator it = d->fileMap.find(fName); + if (it != d->fileMap.end()) + fileId = it.value(); + else + fileId = 1; + + d->query->prepare(QLatin1String("INSERT INTO IndexTable (Name, Identifier, NamespaceId, FileId, Anchor) " + "VALUES(?, ?, ?, ?, ?)")); + d->query->bindValue(0, itm.name); + d->query->bindValue(1, itm.identifier); + d->query->bindValue(2, d->namespaceId); + d->query->bindValue(3, fileId); + d->query->bindValue(4, anchor); + d->query->exec(); + + indexFilterTable.append(indexId++); + if (++i%100 == 0) + addProgress(d->indexStep*100.0); + } + d->query->exec(QLatin1String("COMMIT")); + + d->query->exec(QLatin1String("BEGIN")); + foreach (int idx, indexFilterTable) { + foreach (int a, filterAtts) { + d->query->prepare(QLatin1String("INSERT INTO IndexFilterTable (FilterAttributeId, IndexId) " + "VALUES(?, ?)")); + d->query->bindValue(0, a); + d->query->bindValue(1, idx); + d->query->exec(); + } + } + d->query->exec(QLatin1String("COMMIT")); + + d->query->exec(QLatin1String("SELECT COUNT(Id) FROM IndexTable")); + if (d->query->next() && d->query->value(0).toInt() >= indices.count()) + return true; + return false; +} + +bool QHelpGenerator::insertContents(const QByteArray &ba, + const QStringList &filterAttributes) +{ + if (!d->query) + return false; + + emit statusChanged(tr("Insert contents...")); + d->query->prepare(QLatin1String("INSERT INTO ContentsTable (NamespaceId, Data) " + "VALUES(?, ?)")); + d->query->bindValue(0, d->namespaceId); + d->query->bindValue(1, ba); + d->query->exec(); + int contentId = d->query->lastInsertId().toInt(); + if (contentId < 1) { + d->error = tr("Cannot insert contents!"); + return false; + } + + // associate the filter attributes + foreach (const QString &filterAtt, filterAttributes) { + d->query->prepare(QLatin1String("INSERT INTO ContentsFilterTable (FilterAttributeId, ContentsId) " + "SELECT Id, ? FROM FilterAttributeTable WHERE Name=?")); + d->query->bindValue(0, contentId); + d->query->bindValue(1, filterAtt); + d->query->exec(); + if (!d->query->isActive()) { + d->error = tr("Cannot register contents!"); + return false; + } + } + addProgress(d->contentStep); + return true; +} + +bool QHelpGenerator::insertFilterAttributes(const QStringList &attributes) +{ + if (!d->query) + return false; + + d->query->exec(QLatin1String("SELECT Name FROM FilterAttributeTable")); + QSet atts; + while (d->query->next()) + atts.insert(d->query->value(0).toString()); + + foreach (const QString &s, attributes) { + if (!atts.contains(s)) { + d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); + d->query->bindValue(0, s); + d->query->exec(); + } + } + return true; +} + +bool QHelpGenerator::insertMetaData(const QMap &metaData) +{ + if (!d->query) + return false; + + QMap::const_iterator it = metaData.constBegin(); + while (it != metaData.constEnd()) { + d->query->prepare(QLatin1String("INSERT INTO MetaDataTable VALUES(?, ?)")); + d->query->bindValue(0, it.key()); + d->query->bindValue(1, it.value()); + d->query->exec(); + ++it; + } + return true; +} + +bool QHelpGenerator::checkLinks(const QHelpDataInterface &helpData) +{ + /* + * Step 1: Gather the canoncal file paths of all files in the project. + * We use a set, because there will be a lot of look-ups. + */ + QSet files; + foreach (const QHelpDataFilterSection &filterSection, helpData.filterSections()) { + foreach (const QString &file, filterSection.files()) { + QFileInfo fileInfo(helpData.rootPath() + QDir::separator() + file); + const QString &canonicalFileName = fileInfo.canonicalFilePath(); + if (!fileInfo.exists()) + emit warning(tr("File '%1' does not exist.").arg(file)); + else + files.insert(canonicalFileName); + } + } + + /* + * Step 2: Check the hypertext and image references of all HTML files. + * Note that we don't parse the files, but simply grep for the + * respective HTML elements. Therefore. contents that are e.g. + * commented out can cause false warning. + */ + bool allLinksOk = true; + foreach (const QString &fileName, files) { + if (!fileName.endsWith(QLatin1String("html")) + && !fileName.endsWith(QLatin1String("htm"))) + continue; + QFile htmlFile(fileName); + if (!htmlFile.open(QIODevice::ReadOnly)) { + emit warning(tr("File '%1' cannot be opened.").arg(fileName)); + continue; + } + const QRegExp linkPattern(QLatin1String("<(?:a href|img src)=\"?([^#\">]+)[#\">]")); + QTextStream stream(&htmlFile); + const QString codec = QHelpGlobal::codecFromData(htmlFile.read(1000)); + stream.setCodec(QTextCodec::codecForName(codec.toLatin1().constData())); + const QString &content = stream.readAll(); + QStringList invalidLinks; + for (int pos = linkPattern.indexIn(content); pos != -1; + pos = linkPattern.indexIn(content, pos + 1)) { + const QString& linkedFileName = linkPattern.cap(1); + if (linkedFileName.contains(QLatin1String("://"))) + continue; + const QString curDir = QFileInfo(fileName).dir().path(); + const QString &canonicalLinkedFileName = + QFileInfo(curDir + QDir::separator() + linkedFileName).canonicalFilePath(); + if (!files.contains(canonicalLinkedFileName) + && !invalidLinks.contains(canonicalLinkedFileName)) { + emit warning(tr("File '%1' contains an invalid link to file '%2'"). + arg(fileName).arg(linkedFileName)); + allLinksOk = false; + invalidLinks.append(canonicalLinkedFileName); + } + } + } + + if (!allLinksOk) + d->error = tr("Invalid links in HTML files."); + return allLinksOk; +} + +QT_END_NAMESPACE + diff --git a/src/assistant/lib/qhelpgenerator_p.h b/src/assistant/lib/qhelpgenerator_p.h new file mode 100644 index 0000000..ad32c05 --- /dev/null +++ b/src/assistant/lib/qhelpgenerator_p.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPGENERATOR_H +#define QHELPGENERATOR_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelp_global.h" +#include "qhelpdatainterface_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QHelpGeneratorPrivate; + +class QHELP_EXPORT QHelpGenerator : public QObject +{ + Q_OBJECT + +public: + QHelpGenerator(QObject *parent = 0); + ~QHelpGenerator(); + + bool generate(QHelpDataInterface *helpData, + const QString &outputFileName); + bool checkLinks(const QHelpDataInterface &helpData); + QString error() const; + +Q_SIGNALS: + void statusChanged(const QString &msg); + void progressChanged(double progress); + void warning(const QString &msg); + +private: + struct FileNameTableData + { + QString name; + int fileId; + QString title; + }; + + void writeTree(QDataStream &s, QHelpDataContentItem *item, int depth); + bool createTables(); + bool insertFileNotFoundFile(); + bool registerCustomFilter(const QString &filterName, + const QStringList &filterAttribs, bool forceUpdate = false); + bool registerVirtualFolder(const QString &folderName, const QString &ns); + bool insertFilterAttributes(const QStringList &attributes); + bool insertKeywords(const QList &keywords, + const QStringList &filterAttributes); + bool insertFiles(const QStringList &files, const QString &rootPath, + const QStringList &filterAttributes); + bool insertContents(const QByteArray &ba, + const QStringList &filterAttributes); + bool insertMetaData(const QMap &metaData); + void cleanupDB(); + void setupProgress(QHelpDataInterface *helpData); + void addProgress(double step); + + QHelpGeneratorPrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/assistant/lib/qhelpindexwidget.cpp b/src/assistant/lib/qhelpindexwidget.cpp new file mode 100644 index 0000000..82d4024 --- /dev/null +++ b/src/assistant/lib/qhelpindexwidget.cpp @@ -0,0 +1,444 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpindexwidget.h" +#include "qhelpenginecore.h" +#include "qhelpengine_p.h" +#include "qhelpdbreader_p.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QHelpIndexProvider : public QThread +{ +public: + QHelpIndexProvider(QHelpEnginePrivate *helpEngine); + ~QHelpIndexProvider(); + void collectIndices(const QString &customFilterName); + void stopCollecting(); + QStringList indices() const; + QList activeReaders() const; + QSet indexIds(QHelpDBReader *reader) const; + +private: + void run(); + + QHelpEnginePrivate *m_helpEngine; + QStringList m_indices; + QList m_activeReaders; + QMap > m_indexIds; + QStringList m_filterAttributes; + mutable QMutex m_mutex; + bool m_abort; +}; + +class QHelpIndexModelPrivate +{ +public: + QHelpIndexModelPrivate(QHelpEnginePrivate *hE) + { + helpEngine = hE; + indexProvider = new QHelpIndexProvider(helpEngine); + insertedRows = 0; + } + + QHelpEnginePrivate *helpEngine; + QHelpIndexProvider *indexProvider; + QStringList indices; + int insertedRows; + QString currentFilter; + QList activeReaders; +}; + +static bool caseInsensitiveLessThan(const QString &as, const QString &bs) +{ + return QString::compare(as, bs, Qt::CaseInsensitive) < 0; +} + +QHelpIndexProvider::QHelpIndexProvider(QHelpEnginePrivate *helpEngine) + : QThread(helpEngine) +{ + m_helpEngine = helpEngine; + m_abort = false; +} + +QHelpIndexProvider::~QHelpIndexProvider() +{ + stopCollecting(); +} + +void QHelpIndexProvider::collectIndices(const QString &customFilterName) +{ + m_mutex.lock(); + m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName); + m_mutex.unlock(); + if (!isRunning()) { + start(LowPriority); + } else { + stopCollecting(); + start(LowPriority); + } +} + +void QHelpIndexProvider::stopCollecting() +{ + if (!isRunning()) + return; + m_mutex.lock(); + m_abort = true; + m_mutex.unlock(); + wait(); + m_abort = false; +} + +QStringList QHelpIndexProvider::indices() const +{ + QMutexLocker lck(&m_mutex); + return m_indices; +} + +QList QHelpIndexProvider::activeReaders() const +{ + QMutexLocker lck(&m_mutex); + return m_activeReaders; +} + +QSet QHelpIndexProvider::indexIds(QHelpDBReader *reader) const +{ + QMutexLocker lck(&m_mutex); + if (m_indexIds.contains(reader)) + return m_indexIds.value(reader); + return QSet(); +} + +void QHelpIndexProvider::run() +{ + m_mutex.lock(); + QStringList atts = m_filterAttributes; + m_indices.clear(); + m_activeReaders.clear(); + QSet indicesSet; + m_mutex.unlock(); + + foreach (const QString &dbFileName, m_helpEngine->fileNameReaderMap.keys()) { + m_mutex.lock(); + if (m_abort) { + m_mutex.unlock(); + return; + } + m_mutex.unlock(); + QHelpDBReader reader(dbFileName, + QHelpGlobal::uniquifyConnectionName(dbFileName + + QLatin1String("FromIndexProvider"), + QThread::currentThread()), 0); + if (!reader.init()) + continue; + QStringList lst = reader.indicesForFilter(atts); + if (!lst.isEmpty()) { + m_mutex.lock(); + foreach (const QString &s, lst) + indicesSet.insert(s); + if (m_abort) { + m_mutex.unlock(); + return; + } + QHelpDBReader *orgReader = m_helpEngine->fileNameReaderMap.value(dbFileName); + m_indexIds.insert(orgReader, reader.indexIds(atts)); + m_activeReaders.append(orgReader); + m_mutex.unlock(); + } + } + m_mutex.lock(); + m_indices = indicesSet.values(); + qSort(m_indices.begin(), m_indices.end(), caseInsensitiveLessThan); + m_mutex.unlock(); +} + + + +/*! + \class QHelpIndexModel + \since 4.4 + \inmodule QtHelp + \brief The QHelpIndexModel class provides a model that + supplies index keywords to views. + + +*/ + +/*! + \fn void QHelpIndexModel::indexCreationStarted() + + This signal is emitted when the creation of a new index + has started. The current index is invalid from this + point on until the signal indexCreated() is emitted. + + \sa isCreatingIndex() +*/ + +/*! + \fn void QHelpIndexModel::indexCreated() + + This signal is emitted when the index has been created. +*/ + +QHelpIndexModel::QHelpIndexModel(QHelpEnginePrivate *helpEngine) + : QStringListModel(helpEngine) +{ + d = new QHelpIndexModelPrivate(helpEngine); + + connect(d->indexProvider, SIGNAL(finished()), this, SLOT(insertIndices())); + connect(helpEngine->q, SIGNAL(setupStarted()), this, SLOT(invalidateIndex())); +} + +QHelpIndexModel::~QHelpIndexModel() +{ + delete d; +} + +void QHelpIndexModel::invalidateIndex(bool onShutDown) +{ + if (onShutDown) + disconnect(this, SLOT(insertIndices())); + d->indexProvider->stopCollecting(); + d->indices.clear(); + if (!onShutDown) + filter(QString()); +} + +/*! + Creates a new index by querying the help system for + keywords for the specified \a customFilterName. +*/ +void QHelpIndexModel::createIndex(const QString &customFilterName) +{ + d->currentFilter = customFilterName; + d->indexProvider->collectIndices(customFilterName); + emit indexCreationStarted(); +} + +void QHelpIndexModel::insertIndices() +{ + d->indices = d->indexProvider->indices(); + d->activeReaders = d->indexProvider->activeReaders(); + QStringList attributes = d->helpEngine->q->filterAttributes(d->currentFilter); + if (attributes.count() > 1) { + foreach (QHelpDBReader *r, d->activeReaders) + r->createAttributesCache(attributes, d->indexProvider->indexIds(r)); + } + filter(QString()); + emit indexCreated(); +} + +/*! + Returns true if the index is currently built up, otherwise + false. +*/ +bool QHelpIndexModel::isCreatingIndex() const +{ + return d->indexProvider->isRunning(); +} + +/*! + Returns all hits found for the \a keyword. A hit consists of + the URL and the document title. +*/ +QMap QHelpIndexModel::linksForKeyword(const QString &keyword) const +{ + QMap linkMap; + QStringList filterAttributes = d->helpEngine->q->filterAttributes(d->currentFilter); + foreach (QHelpDBReader *reader, d->activeReaders) + reader->linksForKeyword(keyword, filterAttributes, linkMap); + return linkMap; +} + +/*! + Filters the indices and returns the model index of the best + matching keyword. In a first step, only the keywords containing + \a filter are kept in the model's index list. Analogously, if + \a wildcard is not empty, only the keywords matched are left + in the index list. In a second step, the best match is + determined and its index model returned. When specifying a + wildcard expression, the \a filter string is used to + search for the best match. +*/ +QModelIndex QHelpIndexModel::filter(const QString &filter, const QString &wildcard) +{ + if (filter.isEmpty()) { + setStringList(d->indices); + return index(-1, 0, QModelIndex()); + } + + QStringList lst; + int goodMatch = -1; + int perfectMatch = -1; + + if (!wildcard.isEmpty()) { + QRegExp regExp(wildcard, Qt::CaseInsensitive); + regExp.setPatternSyntax(QRegExp::Wildcard); + foreach (const QString &index, d->indices) { + if (index.contains(regExp)) { + lst.append(index); + if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) { + if (goodMatch == -1) + goodMatch = lst.count()-1; + if (filter.length() == index.length()){ + perfectMatch = lst.count()-1; + } + } else if (perfectMatch > -1 && index == filter) { + perfectMatch = lst.count()-1; + } + } + } + } else { + foreach (const QString &index, d->indices) { + if (index.contains(filter, Qt::CaseInsensitive)) { + lst.append(index); + if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) { + if (goodMatch == -1) + goodMatch = lst.count()-1; + if (filter.length() == index.length()){ + perfectMatch = lst.count()-1; + } + } else if (perfectMatch > -1 && index == filter) { + perfectMatch = lst.count()-1; + } + } + } + + } + + if (perfectMatch == -1) + perfectMatch = qMax(0, goodMatch); + + setStringList(lst); + return index(perfectMatch, 0, QModelIndex()); +} + + + +/*! + \class QHelpIndexWidget + \inmodule QtHelp + \since 4.4 + \brief The QHelpIndexWidget class provides a list view + displaying the QHelpIndexModel. +*/ + +/*! + \fn void QHelpIndexWidget::linkActivated(const QUrl &link, + const QString &keyword) + + This signal is emitted when an item is activated and its + associated \a link should be shown. To know where the link + belongs to, the \a keyword is given as a second paremeter. +*/ + +/*! + \fn void QHelpIndexWidget::linksActivated(const QMap &links, + const QString &keyword) + + This signal is emitted when the item representing the \a keyword + is activated and the item has more than one link associated. + The \a links consist of the document title and their URL. +*/ + +QHelpIndexWidget::QHelpIndexWidget() + : QListView(0) +{ + setEditTriggers(QAbstractItemView::NoEditTriggers); + setUniformItemSizes(true); + connect(this, SIGNAL(activated(QModelIndex)), + this, SLOT(showLink(QModelIndex))); +} + +void QHelpIndexWidget::showLink(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + QHelpIndexModel *indexModel = qobject_cast(model()); + if (!indexModel) + return; + QVariant v = indexModel->data(index, Qt::DisplayRole); + QString name; + if (v.isValid()) + name = v.toString(); + + QMap links = indexModel->linksForKeyword(name); + if (links.count() == 1) { + emit linkActivated(links.constBegin().value(), name); + } else if (links.count() > 1) { + emit linksActivated(links, name); + } +} + +/*! + Activates the current item which will result eventually in + the emitting of a linkActivated() or linksActivated() + signal. +*/ +void QHelpIndexWidget::activateCurrentItem() +{ + showLink(currentIndex()); +} + +/*! + Filters the indices according to \a filter or \a wildcard. + The item with the best match is set as current item. + + \sa QHelpIndexModel::filter() +*/ +void QHelpIndexWidget::filterIndices(const QString &filter, const QString &wildcard) +{ + QHelpIndexModel *indexModel = qobject_cast(model()); + if (!indexModel) + return; + QModelIndex idx = indexModel->filter(filter, wildcard); + if (idx.isValid()) + setCurrentIndex(idx); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpindexwidget.h b/src/assistant/lib/qhelpindexwidget.h new file mode 100644 index 0000000..0c4d307 --- /dev/null +++ b/src/assistant/lib/qhelpindexwidget.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPINDEXWIDGET_H +#define QHELPINDEXWIDGET_H + +#include + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +class QHelpEnginePrivate; +class QHelpIndexModelPrivate; + +class QHELP_EXPORT QHelpIndexModel : public QStringListModel +{ + Q_OBJECT + +public: + void createIndex(const QString &customFilterName); + QModelIndex filter(const QString &filter, + const QString &wildcard = QString()); + + QMap linksForKeyword(const QString &keyword) const; + bool isCreatingIndex() const; + +Q_SIGNALS: + void indexCreationStarted(); + void indexCreated(); + +private Q_SLOTS: + void insertIndices(); + void invalidateIndex(bool onShutDown = false); + +private: + QHelpIndexModel(QHelpEnginePrivate *helpEngine); + ~QHelpIndexModel(); + + QHelpIndexModelPrivate *d; + friend class QHelpEnginePrivate; +}; + +class QHELP_EXPORT QHelpIndexWidget : public QListView +{ + Q_OBJECT + +Q_SIGNALS: + void linkActivated(const QUrl &link, const QString &keyword); + void linksActivated(const QMap &links, + const QString &keyword); + +public Q_SLOTS: + void filterIndices(const QString &filter, + const QString &wildcard = QString()); + void activateCurrentItem(); + +private Q_SLOTS: + void showLink(const QModelIndex &index); + +private: + QHelpIndexWidget(); + friend class QHelpEngine; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/assistant/lib/qhelpprojectdata.cpp b/src/assistant/lib/qhelpprojectdata.cpp new file mode 100644 index 0000000..bd59e28 --- /dev/null +++ b/src/assistant/lib/qhelpprojectdata.cpp @@ -0,0 +1,450 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpprojectdata_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QHelpProjectDataPrivate : public QXmlStreamReader +{ +public: + void readData(const QByteArray &contents); + + QString virtualFolder; + QString namespaceName; + QString rootPath; + + QStringList fileList; + QList customFilterList; + QList filterSectionList; + QMap metaData; + + QString errorMsg; + +private: + void readProject(); + void readCustomFilter(); + void readFilterSection(); + void readTOC(); + void readKeywords(); + void readFiles(); + void raiseUnknownTokenError(); + void addMatchingFiles(const QString &pattern); + bool hasValidSyntax(const QString &nameSpace, const QString &vFolder) const; + + QMap dirEntriesCache; +}; + +void QHelpProjectDataPrivate::raiseUnknownTokenError() +{ + raiseError(QCoreApplication::translate("QHelpProject", "Unknown token.")); +} + +void QHelpProjectDataPrivate::readData(const QByteArray &contents) +{ + addData(contents); + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("QtHelpProject") + && attributes().value(QLatin1String("version")) == QLatin1String("1.0")) + readProject(); + else + raiseError(QCoreApplication::translate("QHelpProject", + "Unknown token. Expected \"QtHelpProject\"!")); + } + } + + if (hasError()) { + raiseError(QCoreApplication::translate("QHelpProject", + "Error in line %1: %2").arg(lineNumber()) + .arg(errorString())); + } +} + +void QHelpProjectDataPrivate::readProject() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("virtualFolder")) { + virtualFolder = readElementText(); + if (!hasValidSyntax(QLatin1String("test"), virtualFolder)) + raiseError(QCoreApplication::translate("QHelpProject", + "Virtual folder has invalid syntax.")); + } else if (name() == QLatin1String("namespace")) { + namespaceName = readElementText(); + if (!hasValidSyntax(namespaceName, QLatin1String("test"))) + raiseError(QCoreApplication::translate("QHelpProject", + "Namespace has invalid syntax.")); + } else if (name() == QLatin1String("customFilter")) { + readCustomFilter(); + } else if (name() == QLatin1String("filterSection")) { + readFilterSection(); + } else if (name() == QLatin1String("metaData")) { + QString n = attributes().value(QLatin1String("name")).toString(); + if (!metaData.contains(n)) + metaData[n] + = attributes().value(QLatin1String("value")).toString(); + else + metaData.insert(n, attributes(). + value(QLatin1String("value")).toString()); + } else { + raiseUnknownTokenError(); + } + } else if (isEndElement() && name() == QLatin1String("QtHelpProject")) { + if (namespaceName.isEmpty()) + raiseError(QCoreApplication::translate("QHelpProject", + "Missing namespace in QtHelpProject.")); + else if (virtualFolder.isEmpty()) + raiseError(QCoreApplication::translate("QHelpProject", + "Missing virtual folder in QtHelpProject")); + break; + } + } +} + +void QHelpProjectDataPrivate::readCustomFilter() +{ + QHelpDataCustomFilter filter; + filter.name = attributes().value(QLatin1String("name")).toString(); + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("filterAttribute")) + filter.filterAttributes.append(readElementText()); + else + raiseUnknownTokenError(); + } else if (isEndElement() && name() == QLatin1String("customFilter")) { + break; + } + } + customFilterList.append(filter); +} + +void QHelpProjectDataPrivate::readFilterSection() +{ + filterSectionList.append(QHelpDataFilterSection()); + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("filterAttribute")) + filterSectionList.last().addFilterAttribute(readElementText()); + else if (name() == QLatin1String("toc")) + readTOC(); + else if (name() == QLatin1String("keywords")) + readKeywords(); + else if (name() == QLatin1String("files")) + readFiles(); + else + raiseUnknownTokenError(); + } else if (isEndElement() && name() == QLatin1String("filterSection")) { + break; + } + } +} + +void QHelpProjectDataPrivate::readTOC() +{ + QStack contentStack; + QHelpDataContentItem *itm = 0; + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("section")) { + QString title = attributes().value(QLatin1String("title")).toString(); + QString ref = attributes().value(QLatin1String("ref")).toString(); + if (contentStack.isEmpty()) { + itm = new QHelpDataContentItem(0, title, ref); + filterSectionList.last().addContent(itm); + } else { + itm = new QHelpDataContentItem(contentStack.top(), title, ref); + } + contentStack.push(itm); + } else { + raiseUnknownTokenError(); + } + } else if (isEndElement()) { + if (name() == QLatin1String("section")) { + contentStack.pop(); + continue; + } else if (name() == QLatin1String("toc") && contentStack.isEmpty()) { + break; + } else { + raiseUnknownTokenError(); + } + } + } +} + +void QHelpProjectDataPrivate::readKeywords() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("keyword")) { + if (attributes().value(QLatin1String("ref")).toString().isEmpty() + || (attributes().value(QLatin1String("name")).toString().isEmpty() + && attributes().value(QLatin1String("id")).toString().isEmpty())) + raiseError(QCoreApplication::translate("QHelpProject", + "Missing attribute in keyword at line %1.") + .arg(lineNumber())); + filterSectionList.last() + .addIndex(QHelpDataIndexItem(attributes(). + value(QLatin1String("name")).toString(), + attributes().value(QLatin1String("id")).toString(), + attributes().value(QLatin1String("ref")).toString())); + } else { + raiseUnknownTokenError(); + } + } else if (isEndElement()) { + if (name() == QLatin1String("keyword")) + continue; + else if (name() == QLatin1String("keywords")) + break; + else + raiseUnknownTokenError(); + } + } +} + +void QHelpProjectDataPrivate::readFiles() +{ + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == QLatin1String("file")) + addMatchingFiles(readElementText()); + else + raiseUnknownTokenError(); + } else if (isEndElement()) { + if (name() == QLatin1String("file")) + continue; + else if (name() == QLatin1String("files")) + break; + else + raiseUnknownTokenError(); + } + } +} + +// Expand file pattern and add matches into list. If the pattern does not match +// any files, insert the pattern itself so the QHelpGenerator will emit a +// meaningful warning later. +void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern) +{ + // The pattern matching is expensive, so we skip it if no + // wildcard symbols occur in the string. + if (!pattern.contains('?') && !pattern.contains('*') + && !pattern.contains('[') && !pattern.contains(']')) { + filterSectionList.last().addFile(pattern); + return; + } + + QFileInfo fileInfo(rootPath + '/' + pattern); + const QDir &dir = fileInfo.dir(); + const QString &path = dir.canonicalPath(); + + // QDir::entryList() is expensive, so we cache the results. + QMap::ConstIterator it = dirEntriesCache.find(path); + const QStringList &entries = it != dirEntriesCache.constEnd() ? + it.value() : dir.entryList(QDir::Files); + if (it == dirEntriesCache.constEnd()) + dirEntriesCache.insert(path, entries); + + bool matchFound = false; +#ifdef Q_OS_WIN + Qt::CaseSensitivity cs = Qt::CaseInsensitive; +#else + Qt::CaseSensitivity cs = Qt::CaseSensitive; +#endif + QRegExp regExp(fileInfo.fileName(), cs, QRegExp::Wildcard); + foreach (const QString &file, entries) { + if (regExp.exactMatch(file)) { + matchFound = true; + filterSectionList.last(). + addFile(QFileInfo(pattern).dir().path() + '/' + file); + } + } + if (!matchFound) + filterSectionList.last().addFile(pattern); +} + +bool QHelpProjectDataPrivate::hasValidSyntax(const QString &nameSpace, + const QString &vFolder) const +{ + const QLatin1Char slash('/'); + if (nameSpace.contains(slash) || vFolder.contains(slash)) + return false; + QUrl url; + const QLatin1String scheme("qthelp"); + url.setScheme(scheme); + const QString canonicalNamespace = nameSpace.toLower(); + url.setHost(canonicalNamespace); + url.setPath(vFolder); + + const QString expectedUrl(scheme + QLatin1String("://") + + canonicalNamespace + slash + vFolder); + return url.isValid() && url.toString() == expectedUrl; +} + +/*! + \internal + \class QHelpProjectData + \since 4.4 + \brief The QHelpProjectData class stores all information found + in a Qt help project file. + + The structure is filled with data by calling readData(). The + specified file has to have the Qt help project file format in + order to be read successfully. Possible reading errors can be + retrieved by calling errorMessage(). +*/ + +/*! + Constructs a Qt help project data structure. +*/ +QHelpProjectData::QHelpProjectData() +{ + d = new QHelpProjectDataPrivate; +} + +/*! + Destroys the help project data. +*/ +QHelpProjectData::~QHelpProjectData() +{ + delete d; +} + +/*! + Reads the file \a fileName and stores the help data. The file has to + have the Qt help project file format. Returns true if the file + was successfully read, otherwise false. + + \sa errorMessage() +*/ +bool QHelpProjectData::readData(const QString &fileName) +{ + d->rootPath = QFileInfo(fileName).absolutePath(); + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + d->errorMsg = QCoreApplication::translate("QHelpProject", + "The input file %1 could not be opened!").arg(fileName); + return false; + } + + d->readData(file.readAll()); + return !d->hasError(); +} + +/*! + Returns an error message if the reading of the Qt help project + file failed. Otherwise, an empty QString is returned. + + \sa readData() +*/ +QString QHelpProjectData::errorMessage() const +{ + if (d->hasError()) + return d->errorString(); + return d->errorMsg; +} + +/*! + \internal +*/ +QString QHelpProjectData::namespaceName() const +{ + return d->namespaceName; +} + +/*! + \internal +*/ +QString QHelpProjectData::virtualFolder() const +{ + return d->virtualFolder; +} + +/*! + \internal +*/ +QList QHelpProjectData::customFilters() const +{ + return d->customFilterList; +} + +/*! + \internal +*/ +QList QHelpProjectData::filterSections() const +{ + return d->filterSectionList; +} + +/*! + \internal +*/ +QMap QHelpProjectData::metaData() const +{ + return d->metaData; +} + +/*! + \internal +*/ +QString QHelpProjectData::rootPath() const +{ + return d->rootPath; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpprojectdata_p.h b/src/assistant/lib/qhelpprojectdata_p.h new file mode 100644 index 0000000..64ae325 --- /dev/null +++ b/src/assistant/lib/qhelpprojectdata_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPPROJECTDATA_H +#define QHELPPROJECTDATA_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelp_global.h" +#include "qhelpdatainterface_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QHelpProjectDataPrivate; + +class QHELP_EXPORT QHelpProjectData : public QHelpDataInterface +{ +public: + QHelpProjectData(); + ~QHelpProjectData(); + + bool readData(const QString &fileName); + QString errorMessage() const; + + QString namespaceName() const; + QString virtualFolder() const; + QList customFilters() const; + QList filterSections() const; + QMap metaData() const; + QString rootPath() const; + +private: + QHelpProjectDataPrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/assistant/lib/qhelpsearchengine.cpp b/src/assistant/lib/qhelpsearchengine.cpp new file mode 100644 index 0000000..f8f8acf --- /dev/null +++ b/src/assistant/lib/qhelpsearchengine.cpp @@ -0,0 +1,450 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpenginecore.h" +#include "qhelpsearchengine.h" +#include "qhelpsearchquerywidget.h" +#include "qhelpsearchresultwidget.h" + +#include "qhelpsearchindexreader_p.h" +#if defined(QT_CLUCENE_SUPPORT) +# include "qhelpsearchindexreader_clucene_p.h" +# include "qhelpsearchindexwriter_clucene_p.h" +#else +# include "qhelpsearchindexreader_default_p.h" +# include "qhelpsearchindexwriter_default_p.h" +#endif + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#if defined(QT_CLUCENE_SUPPORT) + using namespace fulltextsearch::clucene; +#else + using namespace fulltextsearch::std; +#endif + +class QHelpSearchEnginePrivate : public QObject +{ + Q_OBJECT + +signals: + void indexingStarted(); + void indexingFinished(); + + void searchingStarted(); + void searchingFinished(int hits); + +private: + QHelpSearchEnginePrivate(QHelpEngineCore *helpEngine) + : queryWidget(0) + , resultWidget(0) + , helpEngine(helpEngine) + { + indexReader = 0; + indexWriter = 0; + } + + ~QHelpSearchEnginePrivate() + { + delete indexReader; + delete indexWriter; + } + + int hitCount() const + { + int count = 0; + if (indexReader) + count = indexReader->hitCount(); + + return count; + } + + QList hits(int start, int end) const + { + return indexReader ? + indexReader->hits(start, end) : + QList(); + } + + void updateIndex(bool reindex = false) + { + if (helpEngine.isNull()) + return; + + if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path())) + return; + + if (!indexWriter) { + indexWriter = new QHelpSearchIndexWriter(); + + connect(indexWriter, SIGNAL(indexingStarted()), this, SIGNAL(indexingStarted())); + connect(indexWriter, SIGNAL(indexingFinished()), this, SIGNAL(indexingFinished())); + connect(indexWriter, SIGNAL(indexingFinished()), this, SLOT(optimizeIndex())); + } + + indexWriter->cancelIndexing(); + indexWriter->updateIndex(helpEngine->collectionFile(), + indexFilesFolder(), reindex); + } + + void cancelIndexing() + { + if (indexWriter) + indexWriter->cancelIndexing(); + } + + void search(const QList &queryList) + { + if (helpEngine.isNull()) + return; + + if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path())) + return; + + if (!indexReader) { +#if defined(QT_CLUCENE_SUPPORT) + indexReader = new QHelpSearchIndexReaderClucene(); +#else + indexReader = new QHelpSearchIndexReaderDefault(); +#endif // QT_CLUCENE_SUPPORT + connect(indexReader, SIGNAL(searchingStarted()), this, SIGNAL(searchingStarted())); + connect(indexReader, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int))); + } + + m_queryList = queryList; + indexReader->cancelSearching(); + indexReader->search(helpEngine->collectionFile(), indexFilesFolder(), queryList); + } + + void cancelSearching() + { + if (indexReader) + indexReader->cancelSearching(); + } + + QString indexFilesFolder() const + { + QString indexFilesFolder = QLatin1String(".fulltextsearch"); + if (helpEngine && !helpEngine->collectionFile().isEmpty()) { + QFileInfo fi(helpEngine->collectionFile()); + indexFilesFolder = fi.absolutePath() + QDir::separator() + + QLatin1Char('.') + + fi.fileName().left(fi.fileName().lastIndexOf(QLatin1String(".qhc"))); + } + return indexFilesFolder; + } + +private slots: + void optimizeIndex() + { +#if defined(QT_CLUCENE_SUPPORT) + if (indexWriter && !helpEngine.isNull()) { + indexWriter->optimizeIndex(); + } +#endif + } + +private: + friend class QHelpSearchEngine; + + QHelpSearchQueryWidget *queryWidget; + QHelpSearchResultWidget *resultWidget; + + fulltextsearch::QHelpSearchIndexReader *indexReader; + QHelpSearchIndexWriter *indexWriter; + + QPointer helpEngine; + + QList m_queryList; +}; + +#include "qhelpsearchengine.moc" + + +/*! + \class QHelpSearchQuery + \since 4.4 + \inmodule QtHelp + \brief The QHelpSearchQuery class contains the field name and the associated + search term + + The QHelpSearchQuery class contains the field name and the associated search + term. Depending on the field the search term might get split up into separate + terms to be parsed differently by the search engine. + + \sa QHelpSearchQueryWidget +*/ + +/*! + \fn QHelpSearchQuery::QHelpSearchQuery() + + Constructs a new empty QHelpSearchQuery. +*/ + +/*! + \fn QHelpSearchQuery::QHelpSearchQuery(FieldName field, const QStringList &wordList) + + Constructs a new QHelpSearchQuery and initializes it with the given \a field and \a wordList. +*/ + +/*! + \enum QHelpSearchQuery::FieldName + This enum type specifies the field names that are handled by the search engine. + + \value DEFAULT the default field provided by the search widget, several terms should be + split and stored in the word list except search terms enclosed in quotes. + \value FUZZY a field only provided in use with clucene. Terms should be split in separate + words and passed to the search engine. + \value WITHOUT a field only provided in use with clucene. Terms should be split in separate + words and passed to the search engine. + \value PHRASE a field only provided in use with clucene. Terms should not be split in separate + words. + \value ALL a field only provided in use with clucene. Terms should be split in separate + words and passed to the search engine + \value ATLEAST a field only provided in use with clucene. Terms should be split in separate + words and passed to the search engine +*/ + +/*! + \class QHelpSearchEngine + \since 4.4 + \inmodule QtHelp + \brief The QHelpSearchEngine class provides access to widgets reusable + to integrate fulltext search as well as to index and search documentation. + + Before the search engine can be used, one has to instantiate at least a + QHelpEngineCore object that needs to be passed to the search engines constructor. + This is required as the search engine needs to be connected to the help + engines setupFinished() signal to know when it can start to index documentation. + + After starting the indexing process the signal indexingStarted() is emitted and + on the end of the indexing process the indexingFinished() is emitted. To stop + the indexing one can call cancelIndexing(). + + While the indexing process has finished, the search engine can now be used to search + thru its index for a given term. To do this one may use the possibility of creating the + QHelpSearchQuery list by self or reuse the QHelpSearchQueryWidget which has the inbuild + functionality to set up a proper search queries list that get's passed to the search engines + search() function. + + After the list of querys has been passed to the search engine, the signal searchingStarted() + is emitted and after the search has finished the searchingFinished() signal is emitted. The + search process can be stopped by calling cancelSearching(). + + If the search succeeds, the searchingFinished() will be called with the search hits count, + which can be reused to fetch the search hits from the search engine. Calling the hits() + function with the range of hits you would like to get will return a list of the requested + SearchHits. They basically constist at the moment of a pair of strings where the values + of that pair are the documentation file path and the page title. + + To display the given hits use the QHelpSearchResultWidget or build up your own one if you need + more advanced functionality. Note that the QHelpSearchResultWidget can not be instantiated + directly, you must retrieve the widget from the search engine in use as all connections will be + established for you by the widget itself. +*/ + +/*! + \fn void QHelpSearchEngine::indexingStarted() + + This signal is emitted when indexing process is started. +*/ + +/*! + \fn void QHelpSearchEngine::indexingFinished() + + This signal is emitted when the indexing process is complete. +*/ + +/*! + \fn void QHelpSearchEngine::searchingStarted() + + This signal is emitted when the search process is started. +*/ + +/*! + \fn void QHelpSearchEngine::searchingFinished(int hits) + + This signal is emitted when the search process is complete. + The hit count is stored in \a hits. +*/ + +/*! + Constructs a new search engine with the given \a parent. The search engine + uses the given \a helpEngine to access the documentation that needs to be indexed. + The QHelpEngine's setupFinished() signal is automatically connected to the + QHelpSearchEngine's indexing function, so that new documentation will be indexed + after the signal is emitted. +*/ +QHelpSearchEngine::QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *parent) + : QObject(parent) +{ + d = new QHelpSearchEnginePrivate(helpEngine); + + connect(helpEngine, SIGNAL(setupFinished()), this, SLOT(indexDocumentation())); + + connect(d, SIGNAL(indexingStarted()), this, SIGNAL(indexingStarted())); + connect(d, SIGNAL(indexingFinished()), this, SIGNAL(indexingFinished())); + connect(d, SIGNAL(searchingStarted()), this, SIGNAL(searchingStarted())); + connect(d, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int))); +} + +/*! + Destructs the search engine. +*/ +QHelpSearchEngine::~QHelpSearchEngine() +{ + delete d; +} + +/*! + Returns a widget to use as input widget. Depending on your search engine + configuration you will get a different widget with more or less subwidgets. +*/ +QHelpSearchQueryWidget* QHelpSearchEngine::queryWidget() +{ + if (!d->queryWidget) + d->queryWidget = new QHelpSearchQueryWidget(); + + return d->queryWidget; +} + +/*! + Returns a widget that can hold and display the search results. +*/ +QHelpSearchResultWidget* QHelpSearchEngine::resultWidget() +{ + if (!d->resultWidget) + d->resultWidget = new QHelpSearchResultWidget(this); + + return d->resultWidget; +} + +/*! + \obsolete + Returns the amount of hits the search engine found. + \sa hitCount() +*/ +int QHelpSearchEngine::hitsCount() const +{ + return d->hitCount(); +} + +/*! + \since 4.6 + Returns the amount of hits the search engine found. +*/ +int QHelpSearchEngine::hitCount() const +{ + return d->hitCount(); +} + +/*! + \typedef QHelpSearchEngine::SearchHit + + Typedef for QPair. + The values of that pair are the documentation file path and the page title. + + \sa hits() +*/ + +/*! + Returns a list of search hits within the range of \a start \a end. +*/ +QList QHelpSearchEngine::hits(int start, int end) const +{ + return d->hits(start, end); +} + +/*! + Returns the list of queries last searched for. + \since 4.5 +*/ +QList QHelpSearchEngine::query() const +{ + return d->m_queryList; +} + +/*! + Forces the search engine to reindex all documentation files. +*/ +void QHelpSearchEngine::reindexDocumentation() +{ + d->updateIndex(true); +} + +/*! + Stops the indexing process. +*/ +void QHelpSearchEngine::cancelIndexing() +{ + d->cancelIndexing(); +} + +/*! + Stops the search process. +*/ +void QHelpSearchEngine::cancelSearching() +{ + d->cancelSearching(); +} + +/*! + Starts the search process using the given list of queries \a queryList + build by the search field name and the values to search for. +*/ +void QHelpSearchEngine::search(const QList &queryList) +{ + d->search(queryList); +} + +void QHelpSearchEngine::indexDocumentation() +{ + d->updateIndex(); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchengine.h b/src/assistant/lib/qhelpsearchengine.h new file mode 100644 index 0000000..baceb70 --- /dev/null +++ b/src/assistant/lib/qhelpsearchengine.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHENGINE_H +#define QHELPSEARCHENGINE_H + +#include + +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +class QHelpEngineCore; +class QHelpSearchQueryWidget; +class QHelpSearchResultWidget; +class QHelpSearchEnginePrivate; + +class QHELP_EXPORT QHelpSearchQuery +{ +public: + enum FieldName { DEFAULT = 0, FUZZY, WITHOUT, PHRASE, ALL, ATLEAST }; + + QHelpSearchQuery() + : fieldName(DEFAULT) { wordList.clear(); } + QHelpSearchQuery(FieldName field, const QStringList &wordList) + : fieldName(field), wordList(wordList) {} + + FieldName fieldName; + QStringList wordList; +}; + +class QHELP_EXPORT QHelpSearchEngine : public QObject +{ + Q_OBJECT + +public: + explicit QHelpSearchEngine(QHelpEngineCore *helpEngine, + QObject *parent = 0); + ~QHelpSearchEngine(); + + QHelpSearchQueryWidget* queryWidget(); + QHelpSearchResultWidget* resultWidget(); + +#ifdef QT_DEPRECATED + QT_DEPRECATED int hitsCount() const; +#endif + int hitCount() const; + + typedef QPair SearchHit; + QList hits(int start, int end) const; + + QList query() const; + +public Q_SLOTS: + void reindexDocumentation(); + void cancelIndexing(); + + void search(const QList &queryList); + void cancelSearching(); + +Q_SIGNALS: + void indexingStarted(); + void indexingFinished(); + + void searchingStarted(); + void searchingFinished(int hits); + +private Q_SLOTS: + void indexDocumentation(); + +private: + QHelpSearchEnginePrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHELPSEARCHENGINE_H diff --git a/src/assistant/lib/qhelpsearchindex_default.cpp b/src/assistant/lib/qhelpsearchindex_default.cpp new file mode 100644 index 0000000..9974f61 --- /dev/null +++ b/src/assistant/lib/qhelpsearchindex_default.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpsearchindex_default_p.h" + +QT_BEGIN_NAMESPACE + +QDataStream &operator>>(QDataStream &s, Document &l) +{ + s >> l.docNumber; + s >> l.frequency; + return s; +} + +QDataStream &operator<<(QDataStream &s, const Document &l) +{ + s << qint16(l.docNumber); + s << qint16(l.frequency); + return s; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchindex_default_p.h b/src/assistant/lib/qhelpsearchindex_default_p.h new file mode 100644 index 0000000..8686099 --- /dev/null +++ b/src/assistant/lib/qhelpsearchindex_default_p.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHINDEXDEFAULT_H +#define QHELPSEARCHINDEXDEFAULT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QtHelpInternal { + +struct Document { + Document(qint16 d, qint16 f) + : docNumber(d), frequency(f) {} + + Document() + : docNumber(-1), frequency(0) {} + + bool operator==(const Document &doc) const { + return docNumber == doc.docNumber; + } + bool operator<(const Document &doc) const { + return frequency > doc.frequency; + } + bool operator<=(const Document &doc) const { + return frequency >= doc.frequency; + } + bool operator>(const Document &doc) const { + return frequency < doc.frequency; + } + + qint16 docNumber; + qint16 frequency; +}; + +struct DocumentInfo : public Document { + DocumentInfo() + : Document(-1, 0), documentTitle(QString()), documentUrl(QString()) {} + + DocumentInfo(qint16 d, qint16 f, const QString &title, const QString &url) + : Document(d, f), documentTitle(title), documentUrl(url) {} + + DocumentInfo(const Document &document, const QString &title, const QString &url) + : Document(document.docNumber, document.frequency), documentTitle(title), documentUrl(url) {} + + QString documentTitle; + QString documentUrl; +}; + +struct Entry { + Entry(qint16 d) { documents.append(Document(d, 1)); } + Entry(QVector l) : documents(l) {} + + QVector documents; +}; + +struct PosEntry { + PosEntry(int p) { positions.append(p); } + QList positions; +}; + +struct Term { + Term() : frequency(-1) {} + Term(const QString &t, int f, QVector l) : term(t), frequency(f), documents(l) {} + QString term; + int frequency; + QVectordocuments; + bool operator<(const Term &i2) const { return frequency < i2.frequency; } +}; + +struct TermInfo { + TermInfo() : frequency(-1) {} + TermInfo(const QString &t, int f, QVector l) + : term(t), frequency(f), documents(l) {} + + bool operator<(const TermInfo &i2) const { return frequency < i2.frequency; } + + QString term; + int frequency; + QVectordocuments; +}; + +} // namespace QtHelpInternal + +using QtHelpInternal::Document; +using QtHelpInternal::DocumentInfo; +using QtHelpInternal::Entry; +using QtHelpInternal::PosEntry; +using QtHelpInternal::Term; +using QtHelpInternal::TermInfo; + +QDataStream &operator>>(QDataStream &s, Document &l); +QDataStream &operator<<(QDataStream &s, const Document &l); + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXDEFAULT_H diff --git a/src/assistant/lib/qhelpsearchindexreader.cpp b/src/assistant/lib/qhelpsearchindexreader.cpp new file mode 100644 index 0000000..1ee356d --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexreader.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpsearchindexreader_p.h" + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { + +QHelpSearchIndexReader::QHelpSearchIndexReader() + : QThread() + , m_cancel(false) +{ + // nothing todo +} + +QHelpSearchIndexReader::~QHelpSearchIndexReader() +{ + mutex.lock(); + this->m_cancel = true; + mutex.unlock(); + + wait(); +} + +void QHelpSearchIndexReader::cancelSearching() +{ + mutex.lock(); + this->m_cancel = true; + mutex.unlock(); +} + +void QHelpSearchIndexReader::search(const QString &collectionFile, const QString &indexFilesFolder, + const QList &queryList) +{ + wait(); + + this->hitList.clear(); + this->m_cancel = false; + this->m_query = queryList; + this->m_collectionFile = collectionFile; + this->m_indexFilesFolder = indexFilesFolder; + + start(QThread::NormalPriority); +} + +int QHelpSearchIndexReader::hitCount() const +{ + QMutexLocker lock(&mutex); + return hitList.count(); +} + +QList QHelpSearchIndexReader::hits(int start, + int end) const +{ + QList hits; + QMutexLocker lock(&mutex); + for (int i = start; i < end && i < hitList.count(); ++i) + hits.append(hitList.at(i)); + return hits; +} + + +} // namespace fulltextsearch + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchindexreader_clucene.cpp b/src/assistant/lib/qhelpsearchindexreader_clucene.cpp new file mode 100644 index 0000000..537e1d7 --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexreader_clucene.cpp @@ -0,0 +1,481 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "fulltextsearch/qindexreader_p.h" +#include "fulltextsearch/qqueryparser_p.h" +#include "fulltextsearch/qsearchable_p.h" +#include "qclucenefieldnames_p.h" +#include "qhelpenginecore.h" + +#include "qhelpsearchindexreader_clucene_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace clucene { + +QHelpSearchIndexReaderClucene::QHelpSearchIndexReaderClucene() + : QHelpSearchIndexReader() +{ + // nothing todo +} + +QHelpSearchIndexReaderClucene::~QHelpSearchIndexReaderClucene() +{ +} + + +void QHelpSearchIndexReaderClucene::run() +{ + mutex.lock(); + + if (m_cancel) { + mutex.unlock(); + return; + } + + const QString collectionFile(this->m_collectionFile); + const QList &queryList = this->m_query; + const QString indexPath(m_indexFilesFolder); + + mutex.unlock(); + + QHelpEngineCore engine(collectionFile, 0); + if (!engine.setupData()) + return; + + QFileInfo fInfo(indexPath); + if (fInfo.exists() && !fInfo.isWritable()) { + qWarning("Full Text Search, could not read index (missing permissions)."); + return; + } + + if(QCLuceneIndexReader::indexExists(indexPath)) { + mutex.lock(); + if (m_cancel) { + mutex.unlock(); + return; + } + mutex.unlock(); + + emit searchingStarted(); + +#if !defined(QT_NO_EXCEPTIONS) + try { +#endif + QCLuceneBooleanQuery booleanQueryTitle; + QCLuceneBooleanQuery booleanQueryContent; + QCLuceneStandardAnalyzer analyzer; + const QStringList& attribList = + engine.filterAttributes(engine.currentFilter()); + bool titleQueryIsValid = buildQuery(queryList, TitleTokenizedField, + attribList, booleanQueryTitle, analyzer); + bool contentQueryIsValid = buildQuery(queryList, ContentField, + attribList, booleanQueryContent, analyzer); + if (!titleQueryIsValid && !contentQueryIsValid) { + emit searchingFinished(0); + return; + } + + QCLuceneIndexSearcher indexSearcher(indexPath); + + // QCLuceneHits object must be allocated on the heap, because + // there is no default constructor. + QSharedPointer titleHits; + QSharedPointer contentHits; + if (titleQueryIsValid) { + titleHits = QSharedPointer(new QCLuceneHits( + indexSearcher.search(booleanQueryTitle))); + } + if (contentQueryIsValid) { + contentHits = QSharedPointer(new QCLuceneHits( + indexSearcher.search(booleanQueryContent))); + } + bool boost = true; + if ((titleHits.isNull() || titleHits->length() == 0) + && (contentHits.isNull() || contentHits->length() == 0)) { + booleanQueryTitle = QCLuceneBooleanQuery(); + booleanQueryContent = QCLuceneBooleanQuery(); + titleQueryIsValid = + buildTryHarderQuery(queryList, TitleTokenizedField, + attribList, booleanQueryTitle, analyzer); + contentQueryIsValid = + buildTryHarderQuery(queryList, ContentField, attribList, + booleanQueryContent, analyzer); + if (!titleQueryIsValid && !contentQueryIsValid) { + emit searchingFinished(0); + return; + } + if (titleQueryIsValid) { + titleHits = QSharedPointer(new QCLuceneHits( + indexSearcher.search(booleanQueryTitle))); + } + if (contentQueryIsValid) { + contentHits = QSharedPointer(new QCLuceneHits( + indexSearcher.search(booleanQueryContent))); + } + boost = false; + } + QList > cluceneHitsList; + if (!titleHits.isNull()) + cluceneHitsList.append(titleHits); + if (!contentHits.isNull()) + cluceneHitsList.append(contentHits); + + QSet pathSet; + QCLuceneDocument document; + const QStringList namespaceList = engine.registeredDocumentations(); + + foreach (const QSharedPointer &hits, cluceneHitsList) { + for (qint32 i = 0; i < hits->length(); i++) { + document = hits->document(i); + const QString path = document.get(PathField); + if (!pathSet.contains(path) && namespaceList.contains( + document.get(NamespaceField), Qt::CaseInsensitive)) { + pathSet.insert(path); + hitList.append(qMakePair(path, document.get(TitleField))); + } + document.clear(); + + mutex.lock(); + if (m_cancel) { + mutex.unlock(); + emit searchingFinished(0); + return; + } + mutex.unlock(); + } + } + + indexSearcher.close(); + const int count = hitList.count(); + if ((count > 0) && boost) + boostSearchHits(engine, hitList, queryList); + emit searchingFinished(hitList.count()); + +#if !defined(QT_NO_EXCEPTIONS) + } catch(...) { + mutex.lock(); + hitList.clear(); + mutex.unlock(); + emit searchingFinished(0); + } +#endif + } +} + +bool QHelpSearchIndexReaderClucene::buildQuery( + const QList &queries, const QString &fieldName, + const QStringList &filterAttributes, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + bool queryIsValid = false; + foreach (const QHelpSearchQuery &query, queries) { + if (fieldName != ContentField && isNegativeQuery(query)) { + queryIsValid = false; + break; + } + switch (query.fieldName) { + case QHelpSearchQuery::FUZZY: + if (addFuzzyQuery(query, fieldName, booleanQuery, analyzer)) + queryIsValid = true; + break; + case QHelpSearchQuery::WITHOUT: + if (fieldName != ContentField) + return false; + if (addWithoutQuery(query, fieldName, booleanQuery)) + queryIsValid = true; + break; + case QHelpSearchQuery::PHRASE: + if (addPhraseQuery(query, fieldName, booleanQuery)) + queryIsValid = true; + break; + case QHelpSearchQuery::ALL: + if (addAllQuery(query, fieldName, booleanQuery)) + queryIsValid = true; + break; + case QHelpSearchQuery::DEFAULT: + if (addDefaultQuery(query, fieldName, true, booleanQuery, analyzer)) + queryIsValid = true; + break; + case QHelpSearchQuery::ATLEAST: + if (addAtLeastQuery(query, fieldName, booleanQuery, analyzer)) + queryIsValid = true; + break; + default: + Q_ASSERT(!"Invalid field name"); + } + } + + if (queryIsValid && !filterAttributes.isEmpty()) { + queryIsValid = + addAttributesQuery(filterAttributes, booleanQuery, analyzer); + } + + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::buildTryHarderQuery( + const QList &queries, const QString &fieldName, + const QStringList &filterAttributes, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + if (queries.isEmpty()) + return false; + const QHelpSearchQuery &query = queries.front(); + if (query.fieldName != QHelpSearchQuery::DEFAULT) + return false; + if (isNegativeQuery(query)) + return false; + if (!addDefaultQuery(query, fieldName, false, booleanQuery, analyzer)) + return false; + if (filterAttributes.isEmpty()) + return true; + return addAttributesQuery(filterAttributes, booleanQuery, analyzer); +} + +bool QHelpSearchIndexReaderClucene::isNegativeQuery(const QHelpSearchQuery &query) const +{ + const QString &search = query.wordList.join(" "); + return search.contains('!') || search.contains('-') + || search.contains(QLatin1String(" NOT ")); +} + +bool QHelpSearchIndexReaderClucene::addFuzzyQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + bool queryIsValid = false; + const QLatin1String fuzzy("~"); + foreach (const QString &term, query.wordList) { + if (!term.isEmpty()) { + QCLuceneQuery *lQuery = + QCLuceneQueryParser::parse(term + fuzzy, fieldName, analyzer); + if (lQuery != 0) { + booleanQuery.add(lQuery, true, false, false); + queryIsValid = true; + } + } + } + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::addWithoutQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery) +{ + bool queryIsValid = false; + const QStringList &stopWords = QCLuceneStopAnalyzer().englishStopWords(); + foreach (const QString &term, query.wordList) { + if (stopWords.contains(term, Qt::CaseInsensitive)) + continue; + QCLuceneQuery *lQuery = new QCLuceneTermQuery(QCLuceneTerm( + fieldName, term.toLower())); + booleanQuery.add(lQuery, true, false, true); + queryIsValid = true; + } + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::addPhraseQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery) +{ + bool queryIsValid = false; + const QString &term = query.wordList.at(0).toLower(); + if (term.contains(QLatin1Char(' '))) { + const QStringList termList = term.split(QLatin1String(" ")); + QCLucenePhraseQuery *q = new QCLucenePhraseQuery(); + const QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords(); + foreach (const QString &term, termList) { + if (!stopWords.contains(term, Qt::CaseInsensitive)) + q->addTerm(QCLuceneTerm(fieldName, term.toLower())); + } + if (!q->getTerms().isEmpty()) { + booleanQuery.add(q, true, true, false); + queryIsValid = true; + } + } else { + QCLuceneQuery *lQuery = new QCLuceneTermQuery(QCLuceneTerm( + fieldName, term.toLower())); + booleanQuery.add(lQuery, true, true, false); + queryIsValid = true; + } + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::addAllQuery(const QHelpSearchQuery &query, + const QString &fieldName, QCLuceneBooleanQuery &booleanQuery) +{ + bool queryIsValid = false; + const QStringList &stopWords = QCLuceneStopAnalyzer().englishStopWords(); + foreach (const QString &term, query.wordList) { + if (stopWords.contains(term, Qt::CaseInsensitive)) + continue; + QCLuceneQuery *lQuery = new QCLuceneTermQuery(QCLuceneTerm( + fieldName, term.toLower())); + booleanQuery.add(lQuery, true, true, false); + queryIsValid = true; + } + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::addDefaultQuery(const QHelpSearchQuery &query, + const QString &fieldName, bool allTermsRequired, + QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + bool queryIsValid = false; + foreach (const QString &term, query.wordList) { + QCLuceneQuery *lQuery = + QCLuceneQueryParser::parse(term.toLower(), fieldName, analyzer); + if (lQuery) { + booleanQuery.add(lQuery, true, allTermsRequired, false); + queryIsValid = true; + } + } + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::addAtLeastQuery( + const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer) +{ + bool queryIsValid = false; + foreach (const QString &term, query.wordList) { + if (!term.isEmpty()) { + QCLuceneQuery *lQuery = + QCLuceneQueryParser::parse(term, fieldName, analyzer); + if (lQuery) { + booleanQuery.add(lQuery, true, false, false); + queryIsValid = true; + } + } + } + return queryIsValid; +} + +bool QHelpSearchIndexReaderClucene::addAttributesQuery( + const QStringList &filterAttributes, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer) +{ + QCLuceneQuery* lQuery = QCLuceneQueryParser::parse(QLatin1String("+") + + filterAttributes.join(QLatin1String(" +")), AttributeField, analyzer); + if (!lQuery) + return false; + booleanQuery.add(lQuery, true, true, false); + return true; +} + +void QHelpSearchIndexReaderClucene::boostSearchHits(const QHelpEngineCore &engine, + QList &hitList, const QList &queryList) +{ + foreach (const QHelpSearchQuery &query, queryList) { + if (query.fieldName != QHelpSearchQuery::DEFAULT) + continue; + + QString joinedQuery = query.wordList.join(QLatin1String(" ")); + + QCLuceneStandardAnalyzer analyzer; + QCLuceneQuery *parsedQuery = QCLuceneQueryParser::parse( + joinedQuery, ContentField, analyzer); + + if (parsedQuery) { + joinedQuery = parsedQuery->toString(); + delete parsedQuery; + } + + const QString contentString(ContentField + QLatin1String(":")); + int length = contentString.length(); + int index = joinedQuery.indexOf(contentString); + + QString term; + int nextIndex = 0; + QStringList searchTerms; + while (index != -1) { + nextIndex = joinedQuery.indexOf(contentString, index + 1); + term = joinedQuery.mid(index + length, nextIndex - (length + index)).simplified(); + if (term.startsWith(QLatin1String("\"")) + && term.endsWith(QLatin1String("\""))) { + searchTerms.append(term.remove(QLatin1String("\""))); + } else { + searchTerms += term.split(QLatin1Char(' ')); + } + index = nextIndex; + } + searchTerms.removeDuplicates(); + + int count = qMin(75, hitList.count()); + QMap hitMap; + for (int i = 0; i < count; ++i) { + const QHelpSearchEngine::SearchHit &hit = hitList.at(i); + QString data = QString::fromUtf8(engine.fileData(hit.first)); + + int counter = 0; + foreach (const QString &term, searchTerms) + counter += data.count(term, Qt::CaseInsensitive); + hitMap.insertMulti(counter, hit); + } + + QList boostedList; + QMap::const_iterator it = hitMap.constEnd(); + do { + --it; + boostedList.append(it.value()); + } while (it != hitMap.constBegin()); + boostedList += hitList.mid(count, hitList.count()); + mutex.lock(); + hitList = boostedList; + mutex.unlock(); + } +} + +} // namespace clucene +} // namespace fulltextsearch + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchindexreader_clucene_p.h b/src/assistant/lib/qhelpsearchindexreader_clucene_p.h new file mode 100644 index 0000000..dec18a0 --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexreader_clucene_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHINDEXREADERCLUCENE_H +#define QHELPSEARCHINDEXREADERCLUCENE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include "fulltextsearch/qanalyzer_p.h" +#include "fulltextsearch/qquery_p.h" +#include "qhelpsearchindexreader_p.h" + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace clucene { + +class QHelpSearchIndexReaderClucene : public QHelpSearchIndexReader +{ + Q_OBJECT + +public: + QHelpSearchIndexReaderClucene(); + ~QHelpSearchIndexReaderClucene(); + +private: + void run(); + void boostSearchHits(const QHelpEngineCore &engine, QList &hitList, + const QList &queryList); + bool buildQuery(const QList &queries, + const QString &fieldName, + const QStringList &filterAttributes, + QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer); + bool buildTryHarderQuery(const QList &queries, + const QString &fieldName, + const QStringList &filterAttributes, + QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer); + bool addFuzzyQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer); + bool addWithoutQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery); + bool addPhraseQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery); + bool addAllQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery); + bool addDefaultQuery(const QHelpSearchQuery &query, const QString &fieldName, + bool allTermsRequired, QCLuceneBooleanQuery &booleanQuery, + QCLuceneAnalyzer &analyzer); + bool addAtLeastQuery(const QHelpSearchQuery &query, const QString &fieldName, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer); + bool addAttributesQuery(const QStringList &filterAttributes, + QCLuceneBooleanQuery &booleanQuery, QCLuceneAnalyzer &analyzer); + bool isNegativeQuery(const QHelpSearchQuery &query) const; +}; + +} // namespace clucene +} // namespace fulltextsearch + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXREADERCLUCENE_H diff --git a/src/assistant/lib/qhelpsearchindexreader_default.cpp b/src/assistant/lib/qhelpsearchindexreader_default.cpp new file mode 100644 index 0000000..e49fdfc --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexreader_default.cpp @@ -0,0 +1,612 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpenginecore.h" +#include "qhelpsearchindexreader_default_p.h" + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace std { + +namespace { + QStringList split( const QString &str ) + { + QStringList lst; + int j = 0; + int i = str.indexOf(QLatin1Char('*'), j ); + + if (str.startsWith(QLatin1String("*"))) + lst << QLatin1String("*"); + + while ( i != -1 ) { + if ( i > j && i <= (int)str.length() ) { + lst << str.mid( j, i - j ); + lst << QLatin1String("*"); + } + j = i + 1; + i = str.indexOf(QLatin1Char('*'), j ); + } + + int l = str.length() - 1; + if ( str.mid( j, l - j + 1 ).length() > 0 ) + lst << str.mid( j, l - j + 1 ); + + return lst; + } +} + + +Reader::Reader() + : indexPath(QString()) + , indexFile(QString()) + , documentFile(QString()) +{ + termList.clear(); + indexTable.clear(); + searchIndexTable.clear(); +} + +Reader::~Reader() +{ + reset(); + searchIndexTable.clear(); +} + +bool Reader::readIndex() +{ + if (indexTable.contains(indexFile)) + return true; + + QFile idxFile(indexFile); + if (!idxFile.open(QFile::ReadOnly)) + return false; + + QString key; + int numOfDocs; + EntryTable entryTable; + QVector docs; + QDataStream dictStream(&idxFile); + while (!dictStream.atEnd()) { + dictStream >> key; + dictStream >> numOfDocs; + docs.resize(numOfDocs); + dictStream >> docs; + entryTable.insert(key, new Entry(docs)); + } + idxFile.close(); + + if (entryTable.isEmpty()) + return false; + + QFile docFile(documentFile); + if (!docFile.open(QFile::ReadOnly)) + return false; + + QString title, url; + DocumentList documentList; + QDataStream docStream(&docFile); + while (!docStream.atEnd()) { + docStream >> title; + docStream >> url; + documentList.append(QStringList(title) << url); + } + docFile.close(); + + if (documentList.isEmpty()) { + cleanupIndex(entryTable); + return false; + } + + indexTable.insert(indexFile, Index(entryTable, documentList)); + return true; +} + +bool Reader::initCheck() const +{ + return !searchIndexTable.isEmpty(); +} + +void Reader::setIndexPath(const QString &path) +{ + indexPath = path; +} + +void Reader::filterFilesForAttributes(const QStringList &attributes) +{ + searchIndexTable.clear(); + for(IndexTable::ConstIterator it = indexTable.begin(); it != indexTable.end(); ++it) { + const QString fileName = it.key(); + bool containsAll = true; + QStringList split = fileName.split(QLatin1String("@")); + foreach (const QString &attribute, attributes) { + if (!split.contains(attribute, Qt::CaseInsensitive)) { + containsAll = false; + break; + } + } + + if (containsAll) + searchIndexTable.insert(fileName, it.value()); + } +} + +void Reader::setIndexFile(const QString &namespaceName, const QString &attributes) +{ + QString extension = namespaceName + QLatin1String("@") + attributes; + indexFile = indexPath + QLatin1String("/indexdb40.") + extension; + documentFile = indexPath + QLatin1String("/indexdoc40.") + extension; +} + +bool Reader::splitSearchTerm(const QString &searchTerm, QStringList *terms, + QStringList *termSeq, QStringList *seqWords) +{ + QString term = searchTerm; + + term = term.simplified(); + term = term.replace(QLatin1String("\'"), QLatin1String("\"")); + term = term.replace(QLatin1String("`"), QLatin1String("\"")); + term = term.replace(QLatin1String("-"), QLatin1String(" ")); + term = term.replace(QRegExp(QLatin1String("\\s[\\S]?\\s")), QLatin1String(" ")); + + *terms = term.split(QLatin1Char(' ')); + QStringList::iterator it = terms->begin(); + for (; it != terms->end(); ++it) { + (*it) = (*it).simplified(); + (*it) = (*it).toLower(); + (*it) = (*it).replace(QLatin1String("\""), QLatin1String("")); + } + + if (term.contains(QLatin1Char('\"'))) { + if ((term.count(QLatin1Char('\"')))%2 == 0) { + int beg = 0; + int end = 0; + QString s; + beg = term.indexOf(QLatin1Char('\"'), beg); + while (beg != -1) { + beg++; + end = term.indexOf(QLatin1Char('\"'), beg); + s = term.mid(beg, end - beg); + s = s.toLower(); + s = s.simplified(); + if (s.contains(QLatin1Char('*'))) { + qWarning("Full Text Search, using a wildcard within phrases is not allowed."); + return false; + } + *seqWords += s.split(QLatin1Char(' ')); + *termSeq << s; + beg = term.indexOf(QLatin1Char('\"'), end + 1); + } + } else { + qWarning("Full Text Search, the closing quotation mark is missing."); + return false; + } + } + + return true; +} + +void Reader::searchInIndex(const QStringList &terms) +{ + foreach (const QString &term, terms) { + QVector documents; + + for(IndexTable::ConstIterator it = searchIndexTable.begin(); + it != searchIndexTable.end(); ++it) { + EntryTable entryTable = it.value().first; + DocumentList documentList = it.value().second; + + if (term.contains(QLatin1Char('*'))) + documents = setupDummyTerm(getWildcardTerms(term, entryTable), entryTable); + else if (entryTable.value(term)) + documents = entryTable.value(term)->documents; + else + continue; + + if (!documents.isEmpty()) { + DocumentInfo info; + QString title, url; + QVector documentsInfo; + foreach(const Document &doc, documents) { + info.docNumber = doc.docNumber; + info.frequency = doc.frequency; + info.documentUrl = documentList.at(doc.docNumber).at(1); + info.documentTitle = documentList.at(doc.docNumber).at(0); + documentsInfo.append(info); + } + + bool found = false; + for(QList::Iterator tit = termList.begin(); + tit != termList.end(); ++tit) { + TermInfo *t = &(*tit); + if(t->term == term) { + t->documents += documentsInfo; + t->frequency += documentsInfo.count(); + found = true; break; + } + } + if (!found) + termList.append(TermInfo(term, documentsInfo.count(), documentsInfo)); + } + } + } + qSort(termList); +} + +QVector Reader::hits() +{ + QVector documents; + if (!termList.count()) + return documents; + + documents = termList.takeFirst().documents; + for(QList::Iterator it = termList.begin(); it != termList.end(); ++it) { + TermInfo *t = &(*it); + QVector docs = t->documents; + for(QVector::Iterator minDoc_it = documents.begin(); + minDoc_it != documents.end(); ) { + bool found = false; + for (QVector::ConstIterator doc_it = docs.constBegin(); + doc_it != docs.constEnd(); ++doc_it ) { + if ( (*minDoc_it).docNumber == (*doc_it).docNumber ) { + (*minDoc_it).frequency += (*doc_it).frequency; + found = true; + break; + } + } + if (!found) + minDoc_it = documents.erase(minDoc_it); + else + ++minDoc_it; + } + } + + qSort(documents); + return documents; +} + +bool Reader::searchForPattern(const QStringList &patterns, const QStringList &words, + const QByteArray &data) +{ + if (data.isEmpty()) + return false; + + for(QHash::ConstIterator mit = + miniIndex.begin(); mit != miniIndex.end(); ++mit) { + delete mit.value(); + } + miniIndex.clear(); + + wordNum = 3; + QStringList::ConstIterator cIt = words.begin(); + for ( ; cIt != words.end(); ++cIt ) + miniIndex.insert(*cIt, new PosEntry(0)); + + QTextStream s(data); + QString text = s.readAll(); + bool valid = true; + const QChar *buf = text.unicode(); + QChar str[64]; + QChar c = buf[0]; + int j = 0; + int i = 0; + while ( j < text.length() ) { + if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) { + valid = false; + if ( i > 1 ) + buildMiniIndex( QString(str,i) ); + i = 0; + c = buf[++j]; + continue; + } + if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) { + valid = true; + c = buf[++j]; + continue; + } + if ( !valid ) { + c = buf[++j]; + continue; + } + if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) { + str[i] = c.toLower(); + ++i; + } else { + if ( i > 1 ) + buildMiniIndex( QString(str,i) ); + i = 0; + } + c = buf[++j]; + } + if ( i > 1 ) + buildMiniIndex( QString(str,i) ); + + QStringList::ConstIterator patIt = patterns.begin(); + QStringList wordLst; + QList a, b; + QList::iterator aIt; + for ( ; patIt != patterns.end(); ++patIt ) { + wordLst = (*patIt).split(QLatin1Char(' ')); + a = miniIndex[ wordLst[0] ]->positions; + for ( int j = 1; j < (int)wordLst.count(); ++j ) { + b = miniIndex[ wordLst[j] ]->positions; + aIt = a.begin(); + while ( aIt != a.end() ) { + if ( b.contains( *aIt + 1 )) { + (*aIt)++; + ++aIt; + } else { + aIt = a.erase( aIt ); + } + } + } + } + if ( a.count() ) + return true; + return false; +} + +QVector Reader::setupDummyTerm(const QStringList &terms, + const EntryTable &entryTable) +{ + QList termList; + for (QStringList::ConstIterator it = terms.begin(); it != terms.end(); ++it) { + if (entryTable.value(*it)) { + Entry *e = entryTable.value(*it); + termList.append(Term(*it, e->documents.count(), e->documents ) ); + } + } + QVector maxList(0); + if ( !termList.count() ) + return maxList; + qSort(termList); + + maxList = termList.takeLast().documents; + for(QList::Iterator it = termList.begin(); it != termList.end(); ++it) { + Term *t = &(*it); + QVector docs = t->documents; + for (QVector::iterator docIt = docs.begin(); docIt != docs.end(); ++docIt ) { + if ( maxList.indexOf( *docIt ) == -1 ) + maxList.append( *docIt ); + } + } + return maxList; +} + +QStringList Reader::getWildcardTerms(const QString &term, + const EntryTable &entryTable) +{ + QStringList lst; + QStringList terms = split(term); + QStringList::Iterator iter; + + for(EntryTable::ConstIterator it = entryTable.begin(); + it != entryTable.end(); ++it) { + int index = 0; + bool found = false; + QString text( it.key() ); + for ( iter = terms.begin(); iter != terms.end(); ++iter ) { + if ( *iter == QLatin1String("*") ) { + found = true; + continue; + } + if ( iter == terms.begin() && (*iter)[0] != text[0] ) { + found = false; + break; + } + index = text.indexOf( *iter, index ); + if ( *iter == terms.last() && index != (int)text.length()-1 ) { + index = text.lastIndexOf( *iter ); + if ( index != (int)text.length() - (int)(*iter).length() ) { + found = false; + break; + } + } + if ( index != -1 ) { + found = true; + index += (*iter).length(); + continue; + } else { + found = false; + break; + } + } + if (found) + lst << text; + } + + return lst; +} + +void Reader::buildMiniIndex(const QString &string) +{ + if (miniIndex[string]) + miniIndex[string]->positions.append(wordNum); + ++wordNum; +} + +void Reader::reset() +{ + for(IndexTable::Iterator it = indexTable.begin(); + it != indexTable.end(); ++it) { + cleanupIndex(it.value().first); + it.value().second.clear(); + } +} + +void Reader::cleanupIndex(EntryTable &entryTable) +{ + for(EntryTable::ConstIterator it = + entryTable.begin(); it != entryTable.end(); ++it) { + delete it.value(); + } + + entryTable.clear(); +} + + +QHelpSearchIndexReaderDefault::QHelpSearchIndexReaderDefault() + : QHelpSearchIndexReader() +{ + // nothing todo +} + +QHelpSearchIndexReaderDefault::~QHelpSearchIndexReaderDefault() +{ +} + +void QHelpSearchIndexReaderDefault::run() +{ + mutex.lock(); + + if (m_cancel) { + mutex.unlock(); + return; + } + + const QList &queryList = this->m_query; + const QLatin1String key("DefaultSearchNamespaces"); + const QString collectionFile(this->m_collectionFile); + const QString indexPath = m_indexFilesFolder; + + mutex.unlock(); + + QString queryTerm; + foreach (const QHelpSearchQuery &query, queryList) { + if (query.fieldName == QHelpSearchQuery::DEFAULT) { + queryTerm = query.wordList.at(0); + break; + } + } + + if (queryTerm.isEmpty()) + return; + + QHelpEngineCore engine(collectionFile, 0); + if (!engine.setupData()) + return; + + const QStringList registeredDocs = engine.registeredDocumentations(); + const QStringList indexedNamespaces = engine.customValue(key).toString(). + split(QLatin1String("|"), QString::SkipEmptyParts); + + emit searchingStarted(); + + // setup the reader + m_reader.setIndexPath(indexPath); + foreach(const QString &namespaceName, registeredDocs) { + mutex.lock(); + if (m_cancel) { + mutex.unlock(); + searchingFinished(0); // TODO: check this ??? + return; + } + mutex.unlock(); + + const QList attributeSets = + engine.filterAttributeSets(namespaceName); + + foreach (const QStringList &attributes, attributeSets) { + // read all index files + m_reader.setIndexFile(namespaceName, attributes.join(QLatin1String("@"))); + if (!m_reader.readIndex()) { + qWarning("Full Text Search, could not read file for namespace: %s.", + namespaceName.toUtf8().constData()); + } + } + } + + // get the current filter attributes and minimize the index files table + m_reader.filterFilesForAttributes(engine.filterAttributes(engine.currentFilter())); + + hitList.clear(); + QStringList terms, termSeq, seqWords; + if (m_reader.initCheck() && // check if we could read anything + m_reader.splitSearchTerm(queryTerm, &terms, &termSeq, &seqWords) ) { + + // search for term(s) + m_reader.searchInIndex(terms); // TODO: should this be interruptible as well ??? + + QVector hits = m_reader.hits(); + if (!hits.isEmpty()) { + if (termSeq.isEmpty()) { + foreach (const DocumentInfo &docInfo, hits) { + mutex.lock(); + if (m_cancel) { + mutex.unlock(); + searchingFinished(0); // TODO: check this, speed issue while locking??? + return; + } + mutex.unlock(); + hitList.append(qMakePair(docInfo.documentTitle, docInfo.documentUrl)); + } + } else { + foreach (const DocumentInfo &docInfo, hits) { + mutex.lock(); + if (m_cancel) { + mutex.unlock(); + searchingFinished(0); // TODO: check this, speed issue while locking??? + return; + } + mutex.unlock(); + + if (m_reader.searchForPattern(termSeq, seqWords, engine.fileData(docInfo.documentUrl))) // TODO: should this be interruptible as well ??? + hitList.append(qMakePair(docInfo.documentTitle, docInfo.documentUrl)); + } + } + } + } + + emit searchingFinished(hitList.count()); +} + +} // namespace std +} // namespace fulltextsearch + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchindexreader_default_p.h b/src/assistant/lib/qhelpsearchindexreader_default_p.h new file mode 100644 index 0000000..30dfe1e --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexreader_default_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHINDEXREADERDEFAULT_H +#define QHELPSEARCHINDEXREADERDEFAULT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelpsearchindex_default_p.h" +#include "qhelpsearchindexreader_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace std { + +class Reader +{ + typedef QList DocumentList; + typedef QHash EntryTable; + typedef QPair Index; + typedef QHash IndexTable; + +public: + Reader(); + ~Reader(); + + bool readIndex(); + bool initCheck() const; + void setIndexPath(const QString &path); + void filterFilesForAttributes(const QStringList &attributes); + void setIndexFile(const QString &namespaceName, const QString &attributes); + bool splitSearchTerm(const QString &searchTerm, QStringList *terms, + QStringList *termSeq, QStringList *seqWords); + + void searchInIndex(const QStringList &terms); + QVector hits(); + bool searchForPattern(const QStringList &patterns, + const QStringList &words, const QByteArray &data); + +private: + QVector setupDummyTerm(const QStringList &terms, const EntryTable &entryTable); + QStringList getWildcardTerms(const QString &term, const EntryTable &entryTable); + void buildMiniIndex(const QString &string); + void reset(); + void cleanupIndex(EntryTable &entryTable); + +private: + uint wordNum; + QString indexPath; + QString indexFile; + QString documentFile; + + IndexTable indexTable; + QList termList; + IndexTable searchIndexTable; + QHash miniIndex; +}; + + +class QHelpSearchIndexReaderDefault : public QHelpSearchIndexReader +{ + Q_OBJECT + +public: + QHelpSearchIndexReaderDefault(); + ~QHelpSearchIndexReaderDefault(); + +private: + void run(); + +private: + Reader m_reader; +}; + +} // namespace std +} // namespace fulltextsearch + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXREADERDEFAULT_H diff --git a/src/assistant/lib/qhelpsearchindexreader_p.h b/src/assistant/lib/qhelpsearchindexreader_p.h new file mode 100644 index 0000000..0d7518a --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexreader_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHINDEXREADER_H +#define QHELPSEARCHINDEXREADER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelpsearchengine.h" + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QHelpEngineCore; + +namespace fulltextsearch { + +class QHelpSearchIndexReader : public QThread +{ + Q_OBJECT + +public: + QHelpSearchIndexReader(); + ~QHelpSearchIndexReader(); + + void cancelSearching(); + void search(const QString &collectionFile, + const QString &indexFilesFolder, + const QList &queryList); + int hitCount() const; + QList hits(int start, int end) const; + +signals: + void searchingStarted(); + void searchingFinished(int hits); + +protected: + mutable QMutex mutex; + QList hitList; + bool m_cancel; + QString m_collectionFile; + QList m_query; + QString m_indexFilesFolder; + +private: + virtual void run()=0; +}; + +} // namespace fulltextsearch + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXREADER_H diff --git a/src/assistant/lib/qhelpsearchindexwriter_clucene.cpp b/src/assistant/lib/qhelpsearchindexwriter_clucene.cpp new file mode 100644 index 0000000..f3d5e4f --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexwriter_clucene.cpp @@ -0,0 +1,898 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qclucenefieldnames_p.h" +#include "qhelpenginecore.h" +#include "qhelp_global.h" +#include "fulltextsearch/qhits_p.h" +#include "fulltextsearch/qquery_p.h" +#include "fulltextsearch/qanalyzer_p.h" +#include "fulltextsearch/qdocument_p.h" +#include "fulltextsearch/qsearchable_p.h" +#include "fulltextsearch/qindexreader_p.h" +#include "fulltextsearch/qindexwriter_p.h" +#include "qhelpsearchindexwriter_clucene_p.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include "private/qfunctions_p.h" + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace clucene { + +// taken from qtexthtmlparser +static const struct QTextHtmlEntity +{ + const char *name; + quint16 code; +} entities[] = { + { "AElig", 0x00c6 }, + { "AMP", 38 }, + { "Aacute", 0x00c1 }, + { "Acirc", 0x00c2 }, + { "Agrave", 0x00c0 }, + { "Alpha", 0x0391 }, + { "Aring", 0x00c5 }, + { "Atilde", 0x00c3 }, + { "Auml", 0x00c4 }, + { "Beta", 0x0392 }, + { "Ccedil", 0x00c7 }, + { "Chi", 0x03a7 }, + { "Dagger", 0x2021 }, + { "Delta", 0x0394 }, + { "ETH", 0x00d0 }, + { "Eacute", 0x00c9 }, + { "Ecirc", 0x00ca }, + { "Egrave", 0x00c8 }, + { "Epsilon", 0x0395 }, + { "Eta", 0x0397 }, + { "Euml", 0x00cb }, + { "GT", 62 }, + { "Gamma", 0x0393 }, + { "Iacute", 0x00cd }, + { "Icirc", 0x00ce }, + { "Igrave", 0x00cc }, + { "Iota", 0x0399 }, + { "Iuml", 0x00cf }, + { "Kappa", 0x039a }, + { "LT", 60 }, + { "Lambda", 0x039b }, + { "Mu", 0x039c }, + { "Ntilde", 0x00d1 }, + { "Nu", 0x039d }, + { "OElig", 0x0152 }, + { "Oacute", 0x00d3 }, + { "Ocirc", 0x00d4 }, + { "Ograve", 0x00d2 }, + { "Omega", 0x03a9 }, + { "Omicron", 0x039f }, + { "Oslash", 0x00d8 }, + { "Otilde", 0x00d5 }, + { "Ouml", 0x00d6 }, + { "Phi", 0x03a6 }, + { "Pi", 0x03a0 }, + { "Prime", 0x2033 }, + { "Psi", 0x03a8 }, + { "QUOT", 34 }, + { "Rho", 0x03a1 }, + { "Scaron", 0x0160 }, + { "Sigma", 0x03a3 }, + { "THORN", 0x00de }, + { "Tau", 0x03a4 }, + { "Theta", 0x0398 }, + { "Uacute", 0x00da }, + { "Ucirc", 0x00db }, + { "Ugrave", 0x00d9 }, + { "Upsilon", 0x03a5 }, + { "Uuml", 0x00dc }, + { "Xi", 0x039e }, + { "Yacute", 0x00dd }, + { "Yuml", 0x0178 }, + { "Zeta", 0x0396 }, + { "aacute", 0x00e1 }, + { "acirc", 0x00e2 }, + { "acute", 0x00b4 }, + { "aelig", 0x00e6 }, + { "agrave", 0x00e0 }, + { "alefsym", 0x2135 }, + { "alpha", 0x03b1 }, + { "amp", 38 }, + { "and", 0x22a5 }, + { "ang", 0x2220 }, + { "apos", 0x0027 }, + { "aring", 0x00e5 }, + { "asymp", 0x2248 }, + { "atilde", 0x00e3 }, + { "auml", 0x00e4 }, + { "bdquo", 0x201e }, + { "beta", 0x03b2 }, + { "brvbar", 0x00a6 }, + { "bull", 0x2022 }, + { "cap", 0x2229 }, + { "ccedil", 0x00e7 }, + { "cedil", 0x00b8 }, + { "cent", 0x00a2 }, + { "chi", 0x03c7 }, + { "circ", 0x02c6 }, + { "clubs", 0x2663 }, + { "cong", 0x2245 }, + { "copy", 0x00a9 }, + { "crarr", 0x21b5 }, + { "cup", 0x222a }, + { "curren", 0x00a4 }, + { "dArr", 0x21d3 }, + { "dagger", 0x2020 }, + { "darr", 0x2193 }, + { "deg", 0x00b0 }, + { "delta", 0x03b4 }, + { "diams", 0x2666 }, + { "divide", 0x00f7 }, + { "eacute", 0x00e9 }, + { "ecirc", 0x00ea }, + { "egrave", 0x00e8 }, + { "empty", 0x2205 }, + { "emsp", 0x2003 }, + { "ensp", 0x2002 }, + { "epsilon", 0x03b5 }, + { "equiv", 0x2261 }, + { "eta", 0x03b7 }, + { "eth", 0x00f0 }, + { "euml", 0x00eb }, + { "euro", 0x20ac }, + { "exist", 0x2203 }, + { "fnof", 0x0192 }, + { "forall", 0x2200 }, + { "frac12", 0x00bd }, + { "frac14", 0x00bc }, + { "frac34", 0x00be }, + { "frasl", 0x2044 }, + { "gamma", 0x03b3 }, + { "ge", 0x2265 }, + { "gt", 62 }, + { "hArr", 0x21d4 }, + { "harr", 0x2194 }, + { "hearts", 0x2665 }, + { "hellip", 0x2026 }, + { "iacute", 0x00ed }, + { "icirc", 0x00ee }, + { "iexcl", 0x00a1 }, + { "igrave", 0x00ec }, + { "image", 0x2111 }, + { "infin", 0x221e }, + { "int", 0x222b }, + { "iota", 0x03b9 }, + { "iquest", 0x00bf }, + { "isin", 0x2208 }, + { "iuml", 0x00ef }, + { "kappa", 0x03ba }, + { "lArr", 0x21d0 }, + { "lambda", 0x03bb }, + { "lang", 0x2329 }, + { "laquo", 0x00ab }, + { "larr", 0x2190 }, + { "lceil", 0x2308 }, + { "ldquo", 0x201c }, + { "le", 0x2264 }, + { "lfloor", 0x230a }, + { "lowast", 0x2217 }, + { "loz", 0x25ca }, + { "lrm", 0x200e }, + { "lsaquo", 0x2039 }, + { "lsquo", 0x2018 }, + { "lt", 60 }, + { "macr", 0x00af }, + { "mdash", 0x2014 }, + { "micro", 0x00b5 }, + { "middot", 0x00b7 }, + { "minus", 0x2212 }, + { "mu", 0x03bc }, + { "nabla", 0x2207 }, + { "nbsp", 0x00a0 }, + { "ndash", 0x2013 }, + { "ne", 0x2260 }, + { "ni", 0x220b }, + { "not", 0x00ac }, + { "notin", 0x2209 }, + { "nsub", 0x2284 }, + { "ntilde", 0x00f1 }, + { "nu", 0x03bd }, + { "oacute", 0x00f3 }, + { "ocirc", 0x00f4 }, + { "oelig", 0x0153 }, + { "ograve", 0x00f2 }, + { "oline", 0x203e }, + { "omega", 0x03c9 }, + { "omicron", 0x03bf }, + { "oplus", 0x2295 }, + { "or", 0x22a6 }, + { "ordf", 0x00aa }, + { "ordm", 0x00ba }, + { "oslash", 0x00f8 }, + { "otilde", 0x00f5 }, + { "otimes", 0x2297 }, + { "ouml", 0x00f6 }, + { "para", 0x00b6 }, + { "part", 0x2202 }, + { "percnt", 0x0025 }, + { "permil", 0x2030 }, + { "perp", 0x22a5 }, + { "phi", 0x03c6 }, + { "pi", 0x03c0 }, + { "piv", 0x03d6 }, + { "plusmn", 0x00b1 }, + { "pound", 0x00a3 }, + { "prime", 0x2032 }, + { "prod", 0x220f }, + { "prop", 0x221d }, + { "psi", 0x03c8 }, + { "quot", 34 }, + { "rArr", 0x21d2 }, + { "radic", 0x221a }, + { "rang", 0x232a }, + { "raquo", 0x00bb }, + { "rarr", 0x2192 }, + { "rceil", 0x2309 }, + { "rdquo", 0x201d }, + { "real", 0x211c }, + { "reg", 0x00ae }, + { "rfloor", 0x230b }, + { "rho", 0x03c1 }, + { "rlm", 0x200f }, + { "rsaquo", 0x203a }, + { "rsquo", 0x2019 }, + { "sbquo", 0x201a }, + { "scaron", 0x0161 }, + { "sdot", 0x22c5 }, + { "sect", 0x00a7 }, + { "shy", 0x00ad }, + { "sigma", 0x03c3 }, + { "sigmaf", 0x03c2 }, + { "sim", 0x223c }, + { "spades", 0x2660 }, + { "sub", 0x2282 }, + { "sube", 0x2286 }, + { "sum", 0x2211 }, + { "sup", 0x2283 }, + { "sup1", 0x00b9 }, + { "sup2", 0x00b2 }, + { "sup3", 0x00b3 }, + { "supe", 0x2287 }, + { "szlig", 0x00df }, + { "tau", 0x03c4 }, + { "there4", 0x2234 }, + { "theta", 0x03b8 }, + { "thetasym", 0x03d1 }, + { "thinsp", 0x2009 }, + { "thorn", 0x00fe }, + { "tilde", 0x02dc }, + { "times", 0x00d7 }, + { "trade", 0x2122 }, + { "uArr", 0x21d1 }, + { "uacute", 0x00fa }, + { "uarr", 0x2191 }, + { "ucirc", 0x00fb }, + { "ugrave", 0x00f9 }, + { "uml", 0x00a8 }, + { "upsih", 0x03d2 }, + { "upsilon", 0x03c5 }, + { "uuml", 0x00fc }, + { "weierp", 0x2118 }, + { "xi", 0x03be }, + { "yacute", 0x00fd }, + { "yen", 0x00a5 }, + { "yuml", 0x00ff }, + { "zeta", 0x03b6 }, + { "zwj", 0x200d }, + { "zwnj", 0x200c } +}; + +Q_STATIC_GLOBAL_OPERATOR bool operator<(const QString &entityStr, const QTextHtmlEntity &entity) +{ + return entityStr < QLatin1String(entity.name); +} + +Q_STATIC_GLOBAL_OPERATOR bool operator<(const QTextHtmlEntity &entity, const QString &entityStr) +{ + return QLatin1String(entity.name) < entityStr; +} + +static QChar resolveEntity(const QString &entity) +{ + const QTextHtmlEntity *start = &entities[0]; + const QTextHtmlEntity *end = &entities[(sizeof(entities) / sizeof(entities[0]))]; + const QTextHtmlEntity *e = qBinaryFind(start, end, entity); + if (e == end) + return QChar(); + return e->code; +} + +static const uint latin1Extended[0xA0 - 0x80] = { + 0x20ac, // 0x80 + 0x0081, // 0x81 direct mapping + 0x201a, // 0x82 + 0x0192, // 0x83 + 0x201e, // 0x84 + 0x2026, // 0x85 + 0x2020, // 0x86 + 0x2021, // 0x87 + 0x02C6, // 0x88 + 0x2030, // 0x89 + 0x0160, // 0x8A + 0x2039, // 0x8B + 0x0152, // 0x8C + 0x008D, // 0x8D direct mapping + 0x017D, // 0x8E + 0x008F, // 0x8F directmapping + 0x0090, // 0x90 directmapping + 0x2018, // 0x91 + 0x2019, // 0x92 + 0x201C, // 0x93 + 0X201D, // 0x94 + 0x2022, // 0x95 + 0x2013, // 0x96 + 0x2014, // 0x97 + 0x02DC, // 0x98 + 0x2122, // 0x99 + 0x0161, // 0x9A + 0x203A, // 0x9B + 0x0153, // 0x9C + 0x009D, // 0x9D direct mapping + 0x017E, // 0x9E + 0x0178 // 0x9F +}; +// end taken from qtexthtmlparser + +class DocumentHelper +{ +public: + DocumentHelper(const QString &fileName, const QByteArray &data) + : fileName(fileName) , data(readData(data)) {} + ~DocumentHelper() {} + + bool addFieldsToDocument(QCLuceneDocument *document, + const QString &namespaceName, const QString &attributes = QString()) + { + if (!document) + return false; + + if(!data.isEmpty()) { + QString parsedData = parseData(); + QString parsedTitle = QHelpGlobal::documentTitle(data); + + if(!parsedData.isEmpty()) { + document->add(new QCLuceneField(ContentField, + parsedData,QCLuceneField::INDEX_TOKENIZED)); + document->add(new QCLuceneField(PathField, fileName, + QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED)); + document->add(new QCLuceneField(TitleField, parsedTitle, + QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED)); + document->add(new QCLuceneField(TitleTokenizedField, parsedTitle, + QCLuceneField::STORE_YES | QCLuceneField::INDEX_TOKENIZED)); + document->add(new QCLuceneField(NamespaceField, namespaceName, + QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED)); + document->add(new QCLuceneField(AttributeField, attributes, + QCLuceneField::STORE_YES | QCLuceneField::INDEX_TOKENIZED)); + return true; + } + } + + return false; + } + +private: + QString readData(const QByteArray &data) + { + QTextStream textStream(data); + const QByteArray &codec = QHelpGlobal::codecFromData(data).toLatin1(); + textStream.setCodec(QTextCodec::codecForName(codec.constData())); + + QString stream = textStream.readAll(); + if (stream.isNull() || stream.isEmpty()) + return QString(); + + return stream; + } + + QString parseData() const + { + const int length = data.length(); + const QChar *buf = data.unicode(); + + QString parsedContent; + parsedContent.reserve(length); + + bool valid = true; + int j = 0, count = 0; + + QChar c; + while (j < length) { + c = buf[j++]; + if (c == QLatin1Char('<') || c == QLatin1Char('&')) { + if (count > 1 && c != QLatin1Char('&')) + parsedContent.append(QLatin1Char(' ')); + else if (c == QLatin1Char('&')) { + // Note: this will modify the counter j, in case we sucessful parsed the entity + // we will have modified the counter to stay 1 before the closing ';', so + // the following if condition will be met with if (c == QLatin1Char(';')) + parsedContent.append(parseEntity(length, buf, j)); + } + + count = 0; + valid = false; + continue; + } + if ((c == QLatin1Char('>') || c == QLatin1Char(';')) && !valid) { + valid = true; + continue; + } + if (!valid) + continue; + + if (c.isLetterOrNumber() || c.isPrint()) { + ++count; + parsedContent.append(c.toLower()); + } else { + if (count > 1) + parsedContent.append(QLatin1Char(' ')); + count = 0; + } + } + + return parsedContent; + } + + // taken from qtexthtmlparser + // parses an entity after "&", and returns it + QString parseEntity(int len, const QChar *buf, int &pos) const + { + int recover = pos; + QString entity; + while (pos < len) { + QChar c = buf[pos++]; + if (c.isSpace() || pos - recover > 9) { + goto error; + } + if (c == QLatin1Char(';')) { + pos--; + break; + } + entity += c; + } + { + QChar resolved = resolveEntity(entity); + if (!resolved.isNull()) + return QString(resolved); + } + if (entity.length() > 1 && entity.at(0) == QLatin1Char('#')) { + entity.remove(0, 1); // removing leading # + + int base = 10; + bool ok = false; + + if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity? + entity.remove(0, 1); + base = 16; + } + + uint uc = entity.toUInt(&ok, base); + if (ok) { + if (uc >= 0x80 && uc < 0x80 + (sizeof(latin1Extended) / sizeof(latin1Extended[0]))) + uc = latin1Extended[uc - 0x80]; // windows latin 1 extended + QString str; + if (uc > 0xffff) { + // surrogate pair + uc -= 0x10000; + ushort high = uc/0x400 + 0xd800; + ushort low = uc%0x400 + 0xdc00; + str.append(QChar(high)); + str.append(QChar(low)); + } else { + str.append(QChar(uc)); + } + return str; + } + } + error: + pos = recover; + return QLatin1String(" "); + } + // end taken from qtexthtmlparser + +private: + QString fileName; + QString data; +}; + + +QHelpSearchIndexWriter::QHelpSearchIndexWriter() + : QThread(0) + , m_cancel(false) +{ + // nothing todo +} + +QHelpSearchIndexWriter::~QHelpSearchIndexWriter() +{ + mutex.lock(); + this->m_cancel = true; + waitCondition.wakeOne(); + mutex.unlock(); + + wait(); +} + +void QHelpSearchIndexWriter::cancelIndexing() +{ + mutex.lock(); + this->m_cancel = true; + mutex.unlock(); +} + +void QHelpSearchIndexWriter::updateIndex(const QString &collectionFile, + const QString &indexFilesFolder, bool reindex) +{ + wait(); + mutex.lock(); + this->m_cancel = false; + this->m_reindex = reindex; + this->m_collectionFile = collectionFile; + this->m_indexFilesFolder = indexFilesFolder; + mutex.unlock(); + + start(QThread::LowestPriority); +} + +void QHelpSearchIndexWriter::optimizeIndex() +{ +#if !defined(QT_NO_EXCEPTIONS) + try { +#endif + if (QCLuceneIndexReader::indexExists(m_indexFilesFolder)) { + if (QCLuceneIndexReader::isLocked(m_indexFilesFolder)) + return; + + QCLuceneStandardAnalyzer analyzer; + QCLuceneIndexWriter writer(m_indexFilesFolder, analyzer, false); + writer.optimize(); + writer.close(); + } +#if !defined(QT_NO_EXCEPTIONS) + } catch (...) { + qWarning("Full Text Search, could not optimize index."); + return; + } +#endif +} + +void QHelpSearchIndexWriter::run() +{ +#if !defined(QT_NO_EXCEPTIONS) + try { +#endif + QMutexLocker mutexLocker(&mutex); + + if (m_cancel) + return; + + const bool reindex = this->m_reindex; + const QString collectionFile(this->m_collectionFile); + + mutexLocker.unlock(); + + QHelpEngineCore engine(collectionFile, 0); + if (!engine.setupData()) + return; + + const QLatin1String key("CluceneIndexedNamespaces"); + if (reindex) + engine.setCustomValue(key, QLatin1String("")); + + QMap indexMap; + const QLatin1String oldKey("CluceneSearchNamespaces"); + if (!engine.customValue(oldKey, QString()).isNull()) { + // old style qhc file < 4.4.2, need to convert... + const QStringList indexedNamespaces + = engine.customValue(oldKey).toString() + .split(QLatin1String("|"), QString::SkipEmptyParts); + foreach (const QString &nameSpace, indexedNamespaces) + indexMap.insert(nameSpace, QDateTime()); + engine.removeCustomValue(oldKey); + } else { + QDataStream dataStream(engine.customValue(key).toByteArray()); + dataStream >> indexMap; + } + + QString indexPath = m_indexFilesFolder; + + QFileInfo fInfo(indexPath); + if (fInfo.exists() && !fInfo.isWritable()) { + qWarning("Full Text Search, could not create index (missing permissions for '%s').", + qPrintable(indexPath)); + return; + } + + emit indexingStarted(); + + QCLuceneIndexWriter *writer = 0; + QCLuceneStandardAnalyzer analyzer; + const QStringList registeredDocs = engine.registeredDocumentations(); + + QLocalSocket localSocket; + localSocket.connectToServer(QString(QLatin1String("QtAssistant%1")) + .arg(QLatin1String(QT_VERSION_STR))); + + QLocalServer localServer; + bool otherInstancesRunning = true; + if (!localSocket.waitForConnected()) { + otherInstancesRunning = false; + localServer.listen(QString(QLatin1String("QtAssistant%1")) + .arg(QLatin1String(QT_VERSION_STR))); + } + + // check if it's locked, and if the other instance is running + if (!otherInstancesRunning && QCLuceneIndexReader::isLocked(indexPath)) + QCLuceneIndexReader::unlock(indexPath); + + if (QCLuceneIndexReader::isLocked(indexPath)) { + // poll unless indexing finished to fake progress + while (QCLuceneIndexReader::isLocked(indexPath)) { + mutexLocker.relock(); + if (m_cancel) + break; + mutexLocker.unlock(); + this->sleep(1); + } + emit indexingFinished(); + return; + } + + if (QCLuceneIndexReader::indexExists(indexPath) && !reindex) { + foreach(const QString &namespaceName, registeredDocs) { + mutexLocker.relock(); + if (m_cancel) { + emit indexingFinished(); + return; + } + mutexLocker.unlock(); + + if (!indexMap.contains(namespaceName)) { + // make sure we remove some partly indexed stuff + removeDocuments(indexPath, namespaceName); + } else { + QString path = engine.documentationFileName(namespaceName); + if (indexMap.value(namespaceName) + < QFileInfo(path).lastModified()) { + // make sure we remove some outdated indexed stuff + indexMap.remove(namespaceName); + removeDocuments(indexPath, namespaceName); + } + + if (indexMap.contains(namespaceName)) { + // make sure we really have content indexed for namespace + QCLuceneTermQuery query(QCLuceneTerm(NamespaceField, namespaceName)); + QCLuceneIndexSearcher indexSearcher(indexPath); + QCLuceneHits hits = indexSearcher.search(query); + if (hits.length() <= 0) + indexMap.remove(namespaceName); + } + } + } + writer = new QCLuceneIndexWriter(indexPath, analyzer, false); + } else { + indexMap.clear(); + writer = new QCLuceneIndexWriter(indexPath, analyzer, true); + } + + writer->setMergeFactor(100); + writer->setMinMergeDocs(1000); + writer->setMaxFieldLength(QCLuceneIndexWriter::DEFAULT_MAX_FIELD_LENGTH); + + QStringList namespaces; + foreach(const QString &namespaceName, registeredDocs) { + mutexLocker.relock(); + if (m_cancel) { + closeIndexWriter(writer); + emit indexingFinished(); + return; + } + mutexLocker.unlock(); + + namespaces.append(namespaceName); + if (indexMap.contains(namespaceName)) + continue; + + const QList attributeSets = + engine.filterAttributeSets(namespaceName); + + if (attributeSets.isEmpty()) { + const QList docFiles = indexableFiles(&engine, namespaceName, + QStringList()); + if (!addDocuments(docFiles, engine, QStringList(), namespaceName, + writer, analyzer)) + break; + } else { + bool bail = false; + foreach (const QStringList &attributes, attributeSets) { + const QList docFiles = indexableFiles(&engine, + namespaceName, attributes); + if (!addDocuments(docFiles, engine, attributes, namespaceName, + writer, analyzer)) { + bail = true; + break; + } + } + if (bail) + break; + } + + mutexLocker.relock(); + if (!m_cancel) { + QString path(engine.documentationFileName(namespaceName)); + indexMap.insert(namespaceName, QFileInfo(path).lastModified()); + writeIndexMap(engine, indexMap); + } + mutexLocker.unlock(); + } + + closeIndexWriter(writer); + + mutexLocker.relock(); + if (!m_cancel) { + mutexLocker.unlock(); + + QStringList indexedNamespaces = indexMap.keys(); + foreach(const QString &namespaceName, indexedNamespaces) { + mutexLocker.relock(); + if (m_cancel) + break; + mutexLocker.unlock(); + + if (!namespaces.contains(namespaceName)) { + indexMap.remove(namespaceName); + writeIndexMap(engine, indexMap); + removeDocuments(indexPath, namespaceName); + } + } + } + +#if !defined(QT_NO_EXCEPTIONS) + } catch (...) { + qWarning("%s: Failed because of CLucene exception.", Q_FUNC_INFO); + } +#endif + + emit indexingFinished(); +} + +bool QHelpSearchIndexWriter::addDocuments(const QList docFiles, + const QHelpEngineCore &engine, const QStringList &attributes, + const QString &namespaceName, QCLuceneIndexWriter *writer, + QCLuceneAnalyzer &analyzer) +{ + QMutexLocker locker(&mutex); + const QString attrList = attributes.join(QLatin1String(" ")); + + locker.unlock(); + foreach(const QUrl &url, docFiles) { + QCLuceneDocument document; + DocumentHelper helper(url.toString(), engine.fileData(url)); + if (helper.addFieldsToDocument(&document, namespaceName, attrList)) { +#if !defined(QT_NO_EXCEPTIONS) + try { +#endif + writer->addDocument(document, analyzer); +#if !defined(QT_NO_EXCEPTIONS) + } catch (...) { + qWarning("Full Text Search, could not properly add documents."); + return false; + } +#endif + } + locker.relock(); + if (m_cancel) + return false; + locker.unlock(); + } + return true; +} + +void QHelpSearchIndexWriter::removeDocuments(const QString &indexPath, + const QString &namespaceName) +{ + if (namespaceName.isEmpty() || QCLuceneIndexReader::isLocked(indexPath)) + return; + + QCLuceneIndexReader reader = QCLuceneIndexReader::open(indexPath); + reader.deleteDocuments(QCLuceneTerm(NamespaceField, namespaceName)); + + reader.close(); +} + +bool QHelpSearchIndexWriter::writeIndexMap(QHelpEngineCore &engine, + const QMap &indexMap) +{ + QByteArray bArray; + + QDataStream data(&bArray, QIODevice::ReadWrite); + data << indexMap; + + return engine.setCustomValue(QLatin1String("CluceneIndexedNamespaces"), + bArray); +} + +QList QHelpSearchIndexWriter::indexableFiles(QHelpEngineCore *helpEngine, + const QString &namespaceName, const QStringList &attributes) const +{ + QList docFiles = helpEngine->files(namespaceName, attributes, + QLatin1String("html")); + docFiles += helpEngine->files(namespaceName, attributes, QLatin1String("htm")); + docFiles += helpEngine->files(namespaceName, attributes, QLatin1String("txt")); + + return docFiles; +} + +void QHelpSearchIndexWriter::closeIndexWriter(QCLuceneIndexWriter *writer) +{ +#if !defined(QT_NO_EXCEPTIONS) + try { +#endif + writer->close(); + delete writer; +#if !defined(QT_NO_EXCEPTIONS) + } catch (...) { + qWarning("Full Text Search, could not properly close index writer."); + } +#endif +} + +} // namespace clucene +} // namespace fulltextsearch + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchindexwriter_clucene_p.h b/src/assistant/lib/qhelpsearchindexwriter_clucene_p.h new file mode 100644 index 0000000..89146f5 --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexwriter_clucene_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHINDEXWRITERCLUCENE_H +#define QHELPSEARCHINDEXWRITERCLUCENE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelpenginecore.h" +#include "fulltextsearch/qanalyzer_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QCLuceneIndexWriter; + +namespace fulltextsearch { +namespace clucene { + +class QHelpSearchIndexWriter : public QThread +{ + Q_OBJECT + +public: + QHelpSearchIndexWriter(); + ~QHelpSearchIndexWriter(); + + void cancelIndexing(); + void updateIndex(const QString &collectionFile, + const QString &indexFilesFolder, bool reindex); + void optimizeIndex(); + +signals: + void indexingStarted(); + void indexingFinished(); + +private: + void run(); + + bool addDocuments(const QList docFiles, const QHelpEngineCore &engine, + const QStringList &attributes, const QString &namespaceName, + QCLuceneIndexWriter *writer, QCLuceneAnalyzer &analyzer); + void removeDocuments(const QString &indexPath, const QString &namespaceName); + + bool writeIndexMap(QHelpEngineCore& engine, + const QMap& indexMap); + + QList indexableFiles(QHelpEngineCore *helpEngine, + const QString &namespaceName, const QStringList &attributes) const; + + void closeIndexWriter(QCLuceneIndexWriter *writer); + +private: + QMutex mutex; + QWaitCondition waitCondition; + + bool m_cancel; + bool m_reindex; + QString m_collectionFile; + QString m_indexFilesFolder; +}; + +} // namespace clucene +} // namespace fulltextsearch + + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXWRITERCLUCENE_H diff --git a/src/assistant/lib/qhelpsearchindexwriter_default.cpp b/src/assistant/lib/qhelpsearchindexwriter_default.cpp new file mode 100644 index 0000000..db7f6ba --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexwriter_default.cpp @@ -0,0 +1,384 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpsearchindexwriter_default_p.h" +#include "qhelp_global.h" +#include "qhelpenginecore.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace std { + +Writer::Writer(const QString &path) + : indexPath(path) + , indexFile(QString()) + , documentFile(QString()) +{ + // nothing todo +} + +Writer::~Writer() +{ + reset(); +} + +void Writer::reset() +{ + for(QHash::ConstIterator it = + index.begin(); it != index.end(); ++it) { + delete it.value(); + } + + index.clear(); + documentList.clear(); +} + +bool Writer::writeIndex() const +{ + bool status; + QFile idxFile(indexFile); + if (!(status = idxFile.open(QFile::WriteOnly))) + return status; + + QDataStream indexStream(&idxFile); + for(QHash::ConstIterator it = + index.begin(); it != index.end(); ++it) { + indexStream << it.key(); + indexStream << it.value()->documents.count(); + indexStream << it.value()->documents; + } + idxFile.close(); + + QFile docFile(documentFile); + if (!(status = docFile.open(QFile::WriteOnly))) + return status; + + QDataStream docStream(&docFile); + foreach(const QStringList &list, documentList) { + docStream << list.at(0); + docStream << list.at(1); + } + docFile.close(); + + return status; +} + +void Writer::removeIndex() const +{ + QFile idxFile(indexFile); + if (idxFile.exists()) + idxFile.remove(); + + QFile docFile(documentFile); + if (docFile.exists()) + docFile.remove(); +} + +void Writer::setIndexFile(const QString &namespaceName, const QString &attributes) +{ + QString extension = namespaceName + QLatin1String("@") + attributes; + indexFile = indexPath + QLatin1String("/indexdb40.") + extension; + documentFile = indexPath + QLatin1String("/indexdoc40.") + extension; +} + +void Writer::insertInIndex(const QString &string, int docNum) +{ + if (string == QLatin1String("amp") || string == QLatin1String("nbsp")) + return; + + Entry *entry = 0; + if (index.count()) + entry = index[string]; + + if (entry) { + if (entry->documents.last().docNumber != docNum) + entry->documents.append(Document(docNum, 1)); + else + entry->documents.last().frequency++; + } else { + index.insert(string, new Entry(docNum)); + } +} + +void Writer::insertInDocumentList(const QString &title, const QString &url) +{ + documentList.append(QStringList(title) << url); +} + + +QHelpSearchIndexWriter::QHelpSearchIndexWriter() + : QThread() + , m_cancel(false) +{ + // nothing todo +} + +QHelpSearchIndexWriter::~QHelpSearchIndexWriter() +{ + mutex.lock(); + this->m_cancel = true; + waitCondition.wakeOne(); + mutex.unlock(); + + wait(); +} + +void QHelpSearchIndexWriter::cancelIndexing() +{ + mutex.lock(); + this->m_cancel = true; + mutex.unlock(); +} + +void QHelpSearchIndexWriter::updateIndex(const QString &collectionFile, + const QString &indexFilesFolder, + bool reindex) +{ + wait(); + QMutexLocker lock(&mutex); + + this->m_cancel = false; + this->m_reindex = reindex; + this->m_collectionFile = collectionFile; + this->m_indexFilesFolder = indexFilesFolder; + + start(QThread::LowestPriority); +} + +void QHelpSearchIndexWriter::run() +{ + mutex.lock(); + + if (m_cancel) { + mutex.unlock(); + return; + } + + const bool reindex(this->m_reindex); + const QLatin1String key("DefaultSearchNamespaces"); + const QString collectionFile(this->m_collectionFile); + const QString indexPath = m_indexFilesFolder; + + mutex.unlock(); + + QHelpEngineCore engine(collectionFile, 0); + if (!engine.setupData()) + return; + + if (reindex) + engine.setCustomValue(key, QLatin1String("")); + + const QStringList registeredDocs = engine.registeredDocumentations(); + const QStringList indexedNamespaces = engine.customValue(key).toString(). + split(QLatin1String("|"), QString::SkipEmptyParts); + + emit indexingStarted(); + + QStringList namespaces; + Writer writer(indexPath); + foreach(const QString &namespaceName, registeredDocs) { + mutex.lock(); + if (m_cancel) { + mutex.unlock(); + return; + } + mutex.unlock(); + + // if indexed, continue + namespaces.append(namespaceName); + if (indexedNamespaces.contains(namespaceName)) + continue; + + const QList attributeSets = + engine.filterAttributeSets(namespaceName); + + foreach (const QStringList &attributes, attributeSets) { + // cleanup maybe old or unfinished files + writer.setIndexFile(namespaceName, attributes.join(QLatin1String("@"))); + writer.removeIndex(); + + QSet documentsSet; + const QList docFiles = engine.files(namespaceName, attributes); + foreach(QUrl url, docFiles) { + if (m_cancel) + return; + + // get rid of duplicated files + if (url.hasFragment()) + url.setFragment(QString()); + + QString s = url.toString(); + if (s.endsWith(QLatin1String(".html")) + || s.endsWith(QLatin1String(".htm")) + || s.endsWith(QLatin1String(".txt"))) + documentsSet.insert(s); + } + + int docNum = 0; + const QStringList documentsList(documentsSet.toList()); + foreach(const QString &url, documentsList) { + if (m_cancel) + return; + + QByteArray data(engine.fileData(url)); + if (data.isEmpty()) + continue; + + QTextStream s(data); + QString en = QHelpGlobal::codecFromData(data); + s.setCodec(QTextCodec::codecForName(en.toLatin1().constData())); + + QString text = s.readAll(); + if (text.isNull()) + continue; + + QString title = QHelpGlobal::documentTitle(text); + + int j = 0; + int i = 0; + bool valid = true; + const QChar *buf = text.unicode(); + QChar str[64]; + QChar c = buf[0]; + + while ( j < text.length() ) { + if (m_cancel) + return; + + if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) { + valid = false; + if ( i > 1 ) + writer.insertInIndex(QString(str,i), docNum); + i = 0; + c = buf[++j]; + continue; + } + if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) { + valid = true; + c = buf[++j]; + continue; + } + if ( !valid ) { + c = buf[++j]; + continue; + } + if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) { + str[i] = c.toLower(); + ++i; + } else { + if ( i > 1 ) + writer.insertInIndex(QString(str,i), docNum); + i = 0; + } + c = buf[++j]; + } + if ( i > 1 ) + writer.insertInIndex(QString(str,i), docNum); + + docNum++; + writer.insertInDocumentList(title, url); + } + + if (writer.writeIndex()) { + engine.setCustomValue(key, addNamespace( + engine.customValue(key).toString(), namespaceName)); + } + + writer.reset(); + } + } + + QStringListIterator qsli(indexedNamespaces); + while (qsli.hasNext()) { + const QString namespaceName = qsli.next(); + if (namespaces.contains(namespaceName)) + continue; + + const QList attributeSets = + engine.filterAttributeSets(namespaceName); + + foreach (const QStringList &attributes, attributeSets) { + writer.setIndexFile(namespaceName, attributes.join(QLatin1String("@"))); + writer.removeIndex(); + } + + engine.setCustomValue(key, removeNamespace( + engine.customValue(key).toString(), namespaceName)); + } + + emit indexingFinished(); +} + +QString QHelpSearchIndexWriter::addNamespace(const QString namespaces, + const QString &namespaceName) +{ + QString value = namespaces; + if (!value.contains(namespaceName)) + value.append(namespaceName).append(QLatin1String("|")); + + return value; +} + +QString QHelpSearchIndexWriter::removeNamespace(const QString namespaces, + const QString &namespaceName) +{ + QString value = namespaces; + if (value.contains(namespaceName)) + value.remove(namespaceName + QLatin1String("|")); + + return value; +} + +} // namespace std +} // namespace fulltextsearch + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchindexwriter_default_p.h b/src/assistant/lib/qhelpsearchindexwriter_default_p.h new file mode 100644 index 0000000..d510fbc --- /dev/null +++ b/src/assistant/lib/qhelpsearchindexwriter_default_p.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHINDEXWRITERDEFAULT_H +#define QHELPSEARCHINDEXWRITERDEFAULT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include "qhelpsearchindex_default_p.h" + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace fulltextsearch { +namespace std { + +class Writer +{ +public: + Writer(const QString &path); + ~Writer(); + + void reset(); + bool writeIndex() const; + void removeIndex() const; + void setIndexFile(const QString &namespaceName, const QString &attributes); + void insertInIndex(const QString &string, int docNum); + void insertInDocumentList(const QString &title, const QString &url); + +private: + QString indexPath; + QString indexFile; + QString documentFile; + + QHash index; + QList documentList; +}; + + +class QHelpSearchIndexWriter : public QThread +{ + Q_OBJECT + +public: + QHelpSearchIndexWriter(); + ~QHelpSearchIndexWriter(); + + void cancelIndexing(); + void updateIndex(const QString &collectionFile, + const QString &indexFilesFolder, bool reindex); + +signals: + void indexingStarted(); + void indexingFinished(); + +private: + void run(); + QString addNamespace(const QString namespaces, const QString &namespaceName); + QString removeNamespace(const QString namespaces, const QString &namespaceName); + +private: + QMutex mutex; + QWaitCondition waitCondition; + + bool m_cancel; + bool m_reindex; + QString m_collectionFile; + QString m_indexFilesFolder; +}; + +} // namespace std +} // namespace fulltextsearch + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXWRITERDEFAULT_H diff --git a/src/assistant/lib/qhelpsearchquerywidget.cpp b/src/assistant/lib/qhelpsearchquerywidget.cpp new file mode 100644 index 0000000..e6a789a --- /dev/null +++ b/src/assistant/lib/qhelpsearchquerywidget.cpp @@ -0,0 +1,587 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpsearchquerywidget.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QHelpSearchQueryWidgetPrivate : public QObject +{ + Q_OBJECT + +private: + struct QueryHistory { + explicit QueryHistory() : curQuery(-1) {} + QList > queries; + int curQuery; + }; + + class CompleterModel : public QAbstractListModel + { + public: + explicit CompleterModel(QObject *parent) + : QAbstractListModel(parent) {} + + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + return parent.isValid() ? 0 : termList.size(); + } + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + if (!index.isValid() || index.row() >= termList.count()|| + (role != Qt::EditRole && role != Qt::DisplayRole)) + return QVariant(); + return termList.at(index.row()); + } + + void addTerm(const QString &term) + { + if (!termList.contains(term)) { + termList.append(term); + reset(); + } + } + + private: + QStringList termList; + }; + + QHelpSearchQueryWidgetPrivate() + : QObject() + , simpleSearch(true) + , searchCompleter(new CompleterModel(this), this) + { + searchButton = 0; + advancedSearchWidget = 0; + showHideAdvancedSearchButton = 0; + defaultQuery = 0; + exactQuery = 0; + similarQuery = 0; + withoutQuery = 0; + allQuery = 0; + atLeastQuery = 0; + } + + ~QHelpSearchQueryWidgetPrivate() + { + // nothing todo + } + + void retranslate() + { + simpleSearchLabel->setText(QHelpSearchQueryWidget::tr("Search for:")); + prevQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Previous search")); + nextQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Next search")); + searchButton->setText(QHelpSearchQueryWidget::tr("Search")); +#ifdef QT_CLUCENE_SUPPORT + advancedSearchLabel->setText(QHelpSearchQueryWidget::tr("Advanced search")); + similarLabel->setText(QHelpSearchQueryWidget::tr("words similar to:")); + withoutLabel->setText(QHelpSearchQueryWidget::tr("without the words:")); + exactLabel->setText(QHelpSearchQueryWidget::tr("with exact phrase:")); + allLabel->setText(QHelpSearchQueryWidget::tr("with all of the words:")); + atLeastLabel->setText(QHelpSearchQueryWidget::tr("with at least one of the words:")); +#endif + } + + QStringList buildTermList(const QString query) + { + bool s = false; + QString phrase; + QStringList wordList; + QString searchTerm = query; + + for (int i = 0; i < searchTerm.length(); ++i) { + if (searchTerm[i] == QLatin1Char('\"') && !s) { + s = true; + phrase = searchTerm[i]; + continue; + } + if (searchTerm[i] != QLatin1Char('\"') && s) + phrase += searchTerm[i]; + if (searchTerm[i] == QLatin1Char('\"') && s) { + s = false; + phrase += searchTerm[i]; + wordList.append(phrase); + searchTerm.remove(phrase); + } + } + if (s) + searchTerm.replace(phrase, phrase.mid(1)); + + const QRegExp exp(QLatin1String("\\s+")); + wordList += searchTerm.split(exp, QString::SkipEmptyParts); + return wordList; + } + + void saveQuery(const QList &query, QueryHistory &queryHist) + { + // We only add the query to the list if it is different from the last one. + bool insert = false; + if (queryHist.queries.empty()) + insert = true; + else { + const QList &lastQuery = queryHist.queries.last(); + if (lastQuery.size() != query.size()) { + insert = true; + } else { + for (int i = 0; i < query.size(); ++i) { + if (query.at(i).fieldName != lastQuery.at(i).fieldName + || query.at(i).wordList != lastQuery.at(i).wordList) { + insert = true; + break; + } + } + } + } + if (insert) { + queryHist.queries.append(query); + foreach (const QHelpSearchQuery &queryPart, query) { + static_cast(searchCompleter.model())-> + addTerm(queryPart.wordList.join(" ")); + } + } + } + + void nextOrPrevQuery(int maxOrMinIndex, int addend, QToolButton *thisButton, + QToolButton *otherButton) + { + QueryHistory *queryHist; + QList lineEdits; + if (simpleSearch) { + queryHist = &simpleQueries; + lineEdits << defaultQuery; + } else { + queryHist = &complexQueries; + lineEdits << allQuery << atLeastQuery << similarQuery + << withoutQuery << exactQuery; + } + foreach (QLineEdit *lineEdit, lineEdits) + lineEdit->clear(); + + // Otherwise, the respective button would be disabled. + Q_ASSERT(queryHist->curQuery != maxOrMinIndex); + + queryHist->curQuery += addend; + const QList &query = + queryHist->queries.at(queryHist->curQuery); + foreach (const QHelpSearchQuery &queryPart, query) { + if (QLineEdit *lineEdit = lineEditFor(queryPart.fieldName)) + lineEdit->setText(queryPart.wordList.join(" ")); + } + + if (queryHist->curQuery == maxOrMinIndex) + thisButton->setEnabled(false); + otherButton->setEnabled(true); + } + + QLineEdit* lineEditFor(const QHelpSearchQuery::FieldName &fieldName) const + { + switch (fieldName) { + case QHelpSearchQuery::DEFAULT: + return defaultQuery; + case QHelpSearchQuery::ALL: + return allQuery; + case QHelpSearchQuery::ATLEAST: + return atLeastQuery; + case QHelpSearchQuery::FUZZY: + return similarQuery; + case QHelpSearchQuery::WITHOUT: + return withoutQuery; + case QHelpSearchQuery::PHRASE: + return exactQuery; + default: + Q_ASSERT(0); + } + return 0; + } + + void enableOrDisableToolButtons() + { + const QueryHistory &queryHist = simpleSearch ? simpleQueries + : complexQueries; + prevQueryButton->setEnabled(queryHist.curQuery > 0); + nextQueryButton->setEnabled(queryHist.curQuery + < queryHist.queries.size() - 1); + } + +private slots: + void showHideAdvancedSearch() + { + if (simpleSearch) { + advancedSearchWidget->show(); + showHideAdvancedSearchButton->setText((QLatin1String("-"))); + } else { + advancedSearchWidget->hide(); + showHideAdvancedSearchButton->setText((QLatin1String("+"))); + } + + simpleSearch = !simpleSearch; + defaultQuery->setEnabled(simpleSearch); + enableOrDisableToolButtons(); + } + + void searchRequested() + { + QList queryList; +#if !defined(QT_CLUCENE_SUPPORT) + queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT, + QStringList(defaultQuery->text()))); + +#else + if (defaultQuery->isEnabled()) { + queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT, + buildTermList(defaultQuery->text()))); + } else { + const QRegExp exp(QLatin1String("\\s+")); + QStringList lst = similarQuery->text().split(exp, + QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList fuzzy; + foreach (const QString &term, lst) + fuzzy += buildTermList(term); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, + fuzzy)); + } + + lst = withoutQuery->text().split(exp, QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList without; + foreach (const QString &term, lst) + without.append(term); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, + without)); + } + + if (!exactQuery->text().isEmpty()) { + QString phrase = exactQuery->text().remove(QLatin1Char('\"')); + phrase = phrase.simplified(); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, + QStringList(phrase))); + } + + lst = allQuery->text().split(exp, QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList all; + foreach (const QString &term, lst) + all.append(term); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all)); + } + + lst = atLeastQuery->text().split(exp, QString::SkipEmptyParts); + if (!lst.isEmpty()) { + QStringList atLeast; + foreach (const QString &term, lst) + atLeast += buildTermList(term); + queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, + atLeast)); + } + } +#endif + QueryHistory &queryHist = simpleSearch ? simpleQueries : complexQueries; + saveQuery(queryList, queryHist); + queryHist.curQuery = queryHist.queries.size() - 1; + if (queryHist.curQuery > 0) + prevQueryButton->setEnabled(true); + nextQueryButton->setEnabled(false); + } + + void nextQuery() + { + nextOrPrevQuery((simpleSearch ? simpleQueries + : complexQueries).queries.size() - 1, 1, nextQueryButton, + prevQueryButton); + } + + void prevQuery() + { + nextOrPrevQuery(0, -1, prevQueryButton, nextQueryButton); + } + +private: + friend class QHelpSearchQueryWidget; + + bool simpleSearch; + QLabel *simpleSearchLabel; + QLabel *advancedSearchLabel; + QLabel *similarLabel; + QLabel *withoutLabel; + QLabel *exactLabel; + QLabel *allLabel; + QLabel *atLeastLabel; + QPushButton *searchButton; + QWidget* advancedSearchWidget; + QToolButton *showHideAdvancedSearchButton; + QLineEdit *defaultQuery; + QLineEdit *exactQuery; + QLineEdit *similarQuery; + QLineEdit *withoutQuery; + QLineEdit *allQuery; + QLineEdit *atLeastQuery; + QToolButton *nextQueryButton; + QToolButton *prevQueryButton; + QueryHistory simpleQueries; + QueryHistory complexQueries; + QCompleter searchCompleter; +}; + +#include "qhelpsearchquerywidget.moc" + + +/*! + \class QHelpSearchQueryWidget + \since 4.4 + \inmodule QtHelp + \brief The QHelpSearchQueryWidget class provides a simple line edit or + an advanced widget to enable the user to input a search term in a + standardized input mask. +*/ + +/*! + \fn void QHelpSearchQueryWidget::search() + + This signal is emitted when a the user has the search button invoked. + After reciving the signal you can ask the QHelpSearchQueryWidget for the + build list of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's + search() function. +*/ + +/*! + Constructs a new search query widget with the given \a parent. +*/ +QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent) + : QWidget(parent) +{ + d = new QHelpSearchQueryWidgetPrivate(); + + QVBoxLayout *vLayout = new QVBoxLayout(this); + vLayout->setMargin(0); + + QHBoxLayout* hBoxLayout = new QHBoxLayout(); + d->simpleSearchLabel = new QLabel(this); + d->defaultQuery = new QLineEdit(this); + d->defaultQuery->setCompleter(&d->searchCompleter); + d->prevQueryButton = new QToolButton(this); + d->prevQueryButton->setArrowType(Qt::LeftArrow); + d->prevQueryButton->setEnabled(false); + d->nextQueryButton = new QToolButton(this); + d->nextQueryButton->setArrowType(Qt::RightArrow); + d->nextQueryButton->setEnabled(false); + d->searchButton = new QPushButton(this); + hBoxLayout->addWidget(d->simpleSearchLabel); + hBoxLayout->addWidget(d->defaultQuery); + hBoxLayout->addWidget(d->prevQueryButton); + hBoxLayout->addWidget(d->nextQueryButton); + hBoxLayout->addWidget(d->searchButton); + + vLayout->addLayout(hBoxLayout); + + connect(d->prevQueryButton, SIGNAL(clicked()), d, SLOT(prevQuery())); + connect(d->nextQueryButton, SIGNAL(clicked()), d, SLOT(nextQuery())); + connect(d->searchButton, SIGNAL(clicked()), this, SIGNAL(search())); + connect(d->defaultQuery, SIGNAL(returnPressed()), this, SIGNAL(search())); + +#if defined(QT_CLUCENE_SUPPORT) + hBoxLayout = new QHBoxLayout(); + d->showHideAdvancedSearchButton = new QToolButton(this); + d->showHideAdvancedSearchButton->setText(QLatin1String("+")); + d->showHideAdvancedSearchButton->setMinimumSize(25, 20); + + d->advancedSearchLabel = new QLabel(this); + QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + sizePolicy.setHeightForWidth(d->advancedSearchLabel->sizePolicy().hasHeightForWidth()); + d->advancedSearchLabel->setSizePolicy(sizePolicy); + + QFrame* hLine = new QFrame(this); + hLine->setFrameStyle(QFrame::HLine); + hBoxLayout->addWidget(d->showHideAdvancedSearchButton); + hBoxLayout->addWidget(d->advancedSearchLabel); + hBoxLayout->addWidget(hLine); + + vLayout->addLayout(hBoxLayout); + + // setup advanced search layout + d->advancedSearchWidget = new QWidget(this); + QGridLayout *gLayout = new QGridLayout(d->advancedSearchWidget); + gLayout->setMargin(0); + + d->similarLabel = new QLabel(this); + gLayout->addWidget(d->similarLabel, 0, 0); + d->similarQuery = new QLineEdit(this); + d->similarQuery->setCompleter(&d->searchCompleter); + gLayout->addWidget(d->similarQuery, 0, 1); + + d->withoutLabel = new QLabel(this); + gLayout->addWidget(d->withoutLabel, 1, 0); + d->withoutQuery = new QLineEdit(this); + d->withoutQuery->setCompleter(&d->searchCompleter); + gLayout->addWidget(d->withoutQuery, 1, 1); + + d->exactLabel = new QLabel(this); + gLayout->addWidget(d->exactLabel, 2, 0); + d->exactQuery = new QLineEdit(this); + d->exactQuery->setCompleter(&d->searchCompleter); + gLayout->addWidget(d->exactQuery, 2, 1); + + d->allLabel = new QLabel(this); + gLayout->addWidget(d->allLabel, 3, 0); + d->allQuery = new QLineEdit(this); + d->allQuery->setCompleter(&d->searchCompleter); + gLayout->addWidget(d->allQuery, 3, 1); + + d->atLeastLabel = new QLabel(this); + gLayout->addWidget(d->atLeastLabel, 4, 0); + d->atLeastQuery = new QLineEdit(this); + d->atLeastQuery->setCompleter(&d->searchCompleter); + gLayout->addWidget(d->atLeastQuery, 4, 1); + + vLayout->addWidget(d->advancedSearchWidget); + d->advancedSearchWidget->hide(); + + d->retranslate(); + + connect(d->exactQuery, SIGNAL(returnPressed()), this, SIGNAL(search())); + connect(d->similarQuery, SIGNAL(returnPressed()), this, SIGNAL(search())); + connect(d->withoutQuery, SIGNAL(returnPressed()), this, SIGNAL(search())); + connect(d->allQuery, SIGNAL(returnPressed()), this, SIGNAL(search())); + connect(d->atLeastQuery, SIGNAL(returnPressed()), this, SIGNAL(search())); + connect(d->showHideAdvancedSearchButton, SIGNAL(clicked()), + d, SLOT(showHideAdvancedSearch())); +#endif + connect(this, SIGNAL(search()), d, SLOT(searchRequested())); +} + +/*! + Destroys the search query widget. +*/ +QHelpSearchQueryWidget::~QHelpSearchQueryWidget() +{ + delete d; +} + +/*! + Expands the search query widget so that the extended search fields are shown. +*/ +void QHelpSearchQueryWidget::expandExtendedSearch() +{ + if (d->simpleSearch) + d->showHideAdvancedSearch(); +} + +/*! + Collapses the search query widget so that only the default search field is + shown. +*/ +void QHelpSearchQueryWidget::collapseExtendedSearch() +{ + if (!d->simpleSearch) + d->showHideAdvancedSearch(); +} + +/*! + Returns a list of queries to use in combination with the search engines + search(QList &queryList) function. +*/ +QList QHelpSearchQueryWidget::query() const +{ + const QHelpSearchQueryWidgetPrivate::QueryHistory &queryHist = + d->simpleSearch ? d->simpleQueries : d->complexQueries; + return queryHist.queries.isEmpty() ? + QList() : queryHist.queries.last(); +} + +/*! + Sets the QHelpSearchQueryWidget input fields to the values specified by + \a queryList search field name. Please note that one has to call the search + engine's search(QList &queryList) function to perform the + actual search. +*/ +void QHelpSearchQueryWidget::setQuery(const QList &queryList) +{ + QList lineEdits; + lineEdits << d->defaultQuery << d->allQuery << d->atLeastQuery + << d->similarQuery << d->withoutQuery << d->exactQuery; + foreach (QLineEdit *lineEdit, lineEdits) + lineEdit->clear(); + + const QLatin1String space(" "); + foreach (const QHelpSearchQuery &q, queryList) { + if (QLineEdit *lineEdit = d->lineEditFor(q.fieldName)) + lineEdit->setText(lineEdit->text() + q.wordList.join(space) + space); + } + d->searchRequested(); +} + +/*! + \reimp +*/ +void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent) +{ + if (focusEvent->reason() != Qt::MouseFocusReason) { + d->defaultQuery->selectAll(); + d->defaultQuery->setFocus(); + } +} + +/*! \reimp +*/ +void QHelpSearchQueryWidget::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) + d->retranslate(); + else + QWidget::changeEvent(event); +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchquerywidget.h b/src/assistant/lib/qhelpsearchquerywidget.h new file mode 100644 index 0000000..e9fb61c --- /dev/null +++ b/src/assistant/lib/qhelpsearchquerywidget.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHQUERYWIDGET_H +#define QHELPSEARCHQUERYWIDGET_H + +#include +#include + +#include +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +class QFocusEvent; +class QHelpSearchQueryWidgetPrivate; + +class QHELP_EXPORT QHelpSearchQueryWidget : public QWidget +{ + Q_OBJECT + +public: + QHelpSearchQueryWidget(QWidget *parent = 0); + ~QHelpSearchQueryWidget(); + + void expandExtendedSearch(); + void collapseExtendedSearch(); + + QList query() const; + void setQuery(const QList &queryList); + +Q_SIGNALS: + void search(); + +private: + virtual void focusInEvent(QFocusEvent *focusEvent); + virtual void changeEvent(QEvent *event); + +private: + QHelpSearchQueryWidgetPrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHELPSEARCHQUERYWIDGET_H diff --git a/src/assistant/lib/qhelpsearchresultwidget.cpp b/src/assistant/lib/qhelpsearchresultwidget.cpp new file mode 100644 index 0000000..2b58450 --- /dev/null +++ b/src/assistant/lib/qhelpsearchresultwidget.cpp @@ -0,0 +1,447 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpsearchresultwidget.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDefaultResultWidget : public QTreeWidget +{ + Q_OBJECT + +public: + QDefaultResultWidget(QWidget *parent = 0) + : QTreeWidget(parent) + { + header()->hide(); + connect(this, SIGNAL(itemActivated(QTreeWidgetItem*,int)), + this, SLOT(itemActivated(QTreeWidgetItem*,int))); + } + + void showResultPage(const QList hits) + { + foreach (const QHelpSearchEngine::SearchHit &hit, hits) + new QTreeWidgetItem(this, QStringList(hit.first) << hit.second); + } + +signals: + void requestShowLink(const QUrl &url); + +private slots: + void itemActivated(QTreeWidgetItem *item, int /* column */) + { + if (item) { + QString data = item->data(1, Qt::DisplayRole).toString(); + emit requestShowLink(data); + } + } +}; + + +class QCLuceneResultWidget : public QTextBrowser +{ + Q_OBJECT + +public: + QCLuceneResultWidget(QWidget *parent = 0) + : QTextBrowser(parent) + { + connect(this, SIGNAL(anchorClicked(QUrl)), + this, SIGNAL(requestShowLink(QUrl))); + setContextMenuPolicy(Qt::NoContextMenu); + } + + void showResultPage(const QList hits, bool isIndexing) + { + QString htmlFile = QString(QLatin1String("%1")) + .arg(tr("Search Results")); + + int count = hits.count(); + if (count != 0) { + if (isIndexing) + htmlFile += QString(QLatin1String("
" + "%1 " + "%2

")).arg(tr("Note:")) + .arg(tr("The search results may not be complete since the " + "documentation is still being indexed!")); + + foreach (const QHelpSearchEngine::SearchHit &hit, hits) { + htmlFile += QString(QLatin1String("
%2
%1

")) + .arg(hit.first).arg(hit.second); + } + } else { + htmlFile += QLatin1String("


") + + tr("Your search did not match any documents.") + + QLatin1String("

"); + if (isIndexing) + htmlFile += QLatin1String("

") + + tr("(The reason for this might be that the documentation " + "is still being indexed.)") + + QLatin1String("

"); + } + + htmlFile += QLatin1String(""); + + setHtml(htmlFile); + } + +signals: + void requestShowLink(const QUrl &url); + +private slots: + void setSource(const QUrl & /* name */) {} +}; + + +class QHelpSearchResultWidgetPrivate : public QObject +{ + Q_OBJECT + +private slots: + void setResults(int hitsCount) + { + if (!searchEngine.isNull()) { +#if defined(QT_CLUCENE_SUPPORT) + showFirstResultPage(); + updateNextButtonState(((hitsCount > 20) ? true : false)); +#else + resultTreeWidget->clear(); + resultTreeWidget->showResultPage(searchEngine->hits(0, hitsCount)); +#endif + } + } + + void showNextResultPage() + { + if (!searchEngine.isNull() + && resultLastToShow < searchEngine->hitCount()) { + resultLastToShow += 20; + resultFirstToShow += 20; + + resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow, + resultLastToShow), isIndexing); + if (resultLastToShow >= searchEngine->hitCount()) + updateNextButtonState(false); + } + updateHitRange(); + } + + void showLastResultPage() + { + if (!searchEngine.isNull()) { + resultLastToShow = searchEngine->hitCount(); + resultFirstToShow = resultLastToShow - (resultLastToShow % 20); + + if (resultFirstToShow == resultLastToShow) + resultFirstToShow -= 20; + + resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow, + resultLastToShow), isIndexing); + updateNextButtonState(false); + } + updateHitRange(); + } + + void showFirstResultPage() + { + if (!searchEngine.isNull()) { + resultLastToShow = 20; + resultFirstToShow = 0; + + resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow, + resultLastToShow), isIndexing); + updatePrevButtonState(false); + } + updateHitRange(); + } + + void showPreviousResultPage() + { + if (!searchEngine.isNull()) { + int count = resultLastToShow % 20; + if (count == 0 || resultLastToShow != searchEngine->hitCount()) + count = 20; + + resultLastToShow -= count; + resultFirstToShow = resultLastToShow -20; + + resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow, + resultLastToShow), isIndexing); + if (resultFirstToShow == 0) + updatePrevButtonState(false); + } + updateHitRange(); + } + + void updatePrevButtonState(bool state = true) + { + firstResultPage->setEnabled(state); + previousResultPage->setEnabled(state); + } + + void updateNextButtonState(bool state = true) + { + nextResultPage->setEnabled(state); + lastResultPage->setEnabled(state); + } + + void indexingStarted() + { + isIndexing = true; + } + + void indexingFinished() + { + isIndexing = false; + } + +private: + QHelpSearchResultWidgetPrivate(QHelpSearchEngine *engine) + : QObject() + , searchEngine(engine) + , isIndexing(false) + { + resultTreeWidget = 0; + resultTextBrowser = 0; + + resultLastToShow = 20; + resultFirstToShow = 0; + + firstResultPage = 0; + previousResultPage = 0; + hitsLabel = 0; + nextResultPage = 0; + lastResultPage = 0; + + connect(searchEngine, SIGNAL(indexingStarted()), + this, SLOT(indexingStarted())); + connect(searchEngine, SIGNAL(indexingFinished()), + this, SLOT(indexingFinished())); + } + + ~QHelpSearchResultWidgetPrivate() + { + delete searchEngine; + } + + QToolButton* setupToolButton(const QString &iconPath) + { + QToolButton *button = new QToolButton(); + button->setEnabled(false); + button->setAutoRaise(true); + button->setIcon(QIcon(iconPath)); + button->setIconSize(QSize(12, 12)); + button->setMaximumSize(QSize(16, 16)); + + return button; + } + + void updateHitRange() + { + int last = 0; + int first = 0; + int count = 0; + + if (!searchEngine.isNull()) { + count = searchEngine->hitCount(); + if (count > 0) { + first = resultFirstToShow +1; + last = resultLastToShow > count ? count : resultLastToShow; + } + } + hitsLabel->setText(QHelpSearchResultWidget::tr("%1 - %2 of %n Hits", 0, count).arg(first).arg(last)); + } + +private: + friend class QHelpSearchResultWidget; + + QPointer searchEngine; + + QDefaultResultWidget *resultTreeWidget; + QCLuceneResultWidget *resultTextBrowser; + + int resultLastToShow; + int resultFirstToShow; + bool isIndexing; + + QToolButton *firstResultPage; + QToolButton *previousResultPage; + QLabel *hitsLabel; + QToolButton *nextResultPage; + QToolButton *lastResultPage; +}; + +#include "qhelpsearchresultwidget.moc" + + +/*! + \class QHelpSearchResultWidget + \since 4.4 + \inmodule QtHelp + \brief The QHelpSearchResultWidget class provides either a tree + widget or a text browser depending on the used search engine to display + the hits found by the search. +*/ + +/*! + \fn void QHelpSearchResultWidget::requestShowLink(const QUrl &link) + + This signal is emitted when a item is activated and its associated + \a link should be shown. +*/ + +QHelpSearchResultWidget::QHelpSearchResultWidget(QHelpSearchEngine *engine) + : QWidget(0) + , d(new QHelpSearchResultWidgetPrivate(engine)) +{ + QVBoxLayout *vLayout = new QVBoxLayout(this); + vLayout->setMargin(0); + vLayout->setSpacing(0); + +#if defined(QT_CLUCENE_SUPPORT) + QHBoxLayout *hBoxLayout = new QHBoxLayout(); +#ifndef Q_OS_MAC + hBoxLayout->setMargin(0); + hBoxLayout->setSpacing(0); +#endif + hBoxLayout->addWidget(d->firstResultPage = d->setupToolButton( + QString::fromUtf8(":/trolltech/assistant/images/3leftarrow.png"))); + + hBoxLayout->addWidget(d->previousResultPage = d->setupToolButton( + QString::fromUtf8(":/trolltech/assistant/images/1leftarrow.png"))); + + d->hitsLabel = new QLabel(tr("0 - 0 of 0 Hits"), this); + d->hitsLabel->setEnabled(false); + hBoxLayout->addWidget(d->hitsLabel); + d->hitsLabel->setAlignment(Qt::AlignCenter); + d->hitsLabel->setMinimumSize(QSize(150, d->hitsLabel->height())); + + hBoxLayout->addWidget(d->nextResultPage = d->setupToolButton( + QString::fromUtf8(":/trolltech/assistant/images/1rightarrow.png"))); + + hBoxLayout->addWidget(d->lastResultPage = d->setupToolButton( + QString::fromUtf8(":/trolltech/assistant/images/3rightarrow.png"))); + + QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + hBoxLayout->addItem(spacer); + + vLayout->addLayout(hBoxLayout); + + d->resultTextBrowser = new QCLuceneResultWidget(this); + vLayout->addWidget(d->resultTextBrowser); + + connect(d->resultTextBrowser, SIGNAL(requestShowLink(QUrl)), this, + SIGNAL(requestShowLink(QUrl))); + + connect(d->nextResultPage, SIGNAL(clicked()), d, SLOT(showNextResultPage())); + connect(d->lastResultPage, SIGNAL(clicked()), d, SLOT(showLastResultPage())); + connect(d->firstResultPage, SIGNAL(clicked()), d, SLOT(showFirstResultPage())); + connect(d->previousResultPage, SIGNAL(clicked()), d, SLOT(showPreviousResultPage())); + + connect(d->firstResultPage, SIGNAL(clicked()), d, SLOT(updateNextButtonState())); + connect(d->previousResultPage, SIGNAL(clicked()), d, SLOT(updateNextButtonState())); + connect(d->nextResultPage, SIGNAL(clicked()), d, SLOT(updatePrevButtonState())); + connect(d->lastResultPage, SIGNAL(clicked()), d, SLOT(updatePrevButtonState())); + +#else + d->resultTreeWidget = new QDefaultResultWidget(this); + vLayout->addWidget(d->resultTreeWidget); + connect(d->resultTreeWidget, SIGNAL(requestShowLink(QUrl)), this, + SIGNAL(requestShowLink(QUrl))); +#endif + + connect(engine, SIGNAL(searchingFinished(int)), d, SLOT(setResults(int))); +} + +/*! \reimp +*/ +void QHelpSearchResultWidget::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) + d->setResults(d->searchEngine->hitCount()); +} + +/*! + Destroys the search result widget. +*/ +QHelpSearchResultWidget::~QHelpSearchResultWidget() +{ + delete d; +} + +/*! + Returns a reference of the URL that the item at \a point owns, or an + empty URL if no item exists at that point. +*/ +QUrl QHelpSearchResultWidget::linkAt(const QPoint &point) +{ + QUrl url; +#if defined(QT_CLUCENE_SUPPORT) + if (d->resultTextBrowser) + url = d->resultTextBrowser->anchorAt(point); +#else + if (d->resultTreeWidget) { + QTreeWidgetItem *item = d->resultTreeWidget->itemAt(point); + if (item) + url = item->data(1, Qt::DisplayRole).toString(); + } +#endif + return url; +} + +QT_END_NAMESPACE diff --git a/src/assistant/lib/qhelpsearchresultwidget.h b/src/assistant/lib/qhelpsearchresultwidget.h new file mode 100644 index 0000000..cd6ac10 --- /dev/null +++ b/src/assistant/lib/qhelpsearchresultwidget.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPSEARCHRESULTWIDGET_H +#define QHELPSEARCHRESULTWIDGET_H + +#include +#include + +#include +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Help) + +class QHelpSearchResultWidgetPrivate; + +class QHELP_EXPORT QHelpSearchResultWidget : public QWidget +{ + Q_OBJECT + +public: + ~QHelpSearchResultWidget(); + QUrl linkAt(const QPoint &point); + +Q_SIGNALS: + void requestShowLink(const QUrl &url); + +private: + friend class QHelpSearchEngine; + + QHelpSearchResultWidgetPrivate *d; + QHelpSearchResultWidget(QHelpSearchEngine *engine); + virtual void changeEvent(QEvent *event); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHELPSEARCHRESULTWIDGET_H diff --git a/src/assistant/tools/assistant/Info_mac.plist b/src/assistant/tools/assistant/Info_mac.plist new file mode 100644 index 0000000..76369a1 --- /dev/null +++ b/src/assistant/tools/assistant/Info_mac.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIconFile + @ICON@ + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + ???? + CFBundleIdentifier + com.trolltech.assistant + CFBundleExecutable + @EXECUTABLE@ + + diff --git a/src/assistant/tools/assistant/aboutdialog.cpp b/src/assistant/tools/assistant/aboutdialog.cpp new file mode 100644 index 0000000..b4c390e --- /dev/null +++ b/src/assistant/tools/assistant/aboutdialog.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "aboutdialog.h" + +#include "helpviewer.h" +#include "tracer.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +AboutLabel::AboutLabel(QWidget *parent) + : QTextBrowser(parent) +{ + TRACE_OBJ + setFrameStyle(QFrame::NoFrame); + QPalette p; + p.setColor(QPalette::Base, p.color(QPalette::Background)); + setPalette(p); +} + +void AboutLabel::setText(const QString &text, const QByteArray &resources) +{ + TRACE_OBJ + QDataStream in(resources); + in >> m_resourceMap; + + QTextBrowser::setText(text); +} + +QSize AboutLabel::minimumSizeHint() const +{ + TRACE_OBJ + QTextDocument *doc = document(); + doc->adjustSize(); + return QSize(int(doc->size().width()), int(doc->size().height())); +} + +QVariant AboutLabel::loadResource(int type, const QUrl &name) +{ + TRACE_OBJ + if (type == 2 || type == 3) { + if (m_resourceMap.contains(name.toString())) { + return m_resourceMap.value(name.toString()); + } + } + return QVariant(); +} + +void AboutLabel::setSource(const QUrl &url) +{ + TRACE_OBJ + if (url.isValid() && (!HelpViewer::isLocalUrl(url) + || !HelpViewer::canOpenPage(url.path()))) { + if (!QDesktopServices::openUrl(url)) { + QMessageBox::warning(this, tr("Warning"), + tr("Unable to launch external application.\n"), tr("OK")); + } + } +} + +AboutDialog::AboutDialog(QWidget *parent) + : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint | + Qt::WindowTitleHint|Qt::WindowSystemMenuHint) +{ + TRACE_OBJ + m_pixmapLabel = 0; + m_aboutLabel = new AboutLabel(); + + m_closeButton = new QPushButton(); + m_closeButton->setText(tr("&Close")); + connect(m_closeButton, SIGNAL(clicked()), this, SLOT(close())); + + m_layout = new QGridLayout(this); + m_layout->addWidget(m_aboutLabel, 1, 0, 1, -1); + m_layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, + QSizePolicy::Fixed), 2, 1, 1, 1); + m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding), 3, 0, 1, 1); + m_layout->addWidget(m_closeButton, 3, 1, 1, 1); + m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding), 3, 2, 1, 1); +} + +void AboutDialog::setText(const QString &text, const QByteArray &resources) +{ + TRACE_OBJ + m_aboutLabel->setText(text, resources); + updateSize(); +} + +void AboutDialog::setPixmap(const QPixmap &pixmap) +{ + TRACE_OBJ + if (!m_pixmapLabel) { + m_pixmapLabel = new QLabel(); + m_layout->addWidget(m_pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter); + } + m_pixmapLabel->setPixmap(pixmap); + updateSize(); +} + +QString AboutDialog::documentTitle() const +{ + TRACE_OBJ + return m_aboutLabel->documentTitle(); +} + +void AboutDialog::updateSize() +{ + TRACE_OBJ + QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()) + .size(); + int limit = qMin(screenSize.width()/2, 500); + +#ifdef Q_WS_MAC + limit = qMin(screenSize.width()/2, 420); +#endif + + layout()->activate(); + int width = layout()->totalMinimumSize().width(); + + if (width > limit) + width = limit; + + QFontMetrics fm(qApp->font("QWorkspaceTitleBar")); + int windowTitleWidth = qMin(fm.width(windowTitle()) + 50, limit); + if (windowTitleWidth > width) + width = windowTitleWidth; + + layout()->activate(); + int height = (layout()->hasHeightForWidth()) + ? layout()->totalHeightForWidth(width) + : layout()->totalMinimumSize().height(); + setFixedSize(width, height); + QCoreApplication::removePostedEvents(this, QEvent::LayoutRequest); +} + +QT_END_NAMESPACE diff --git a/src/assistant/tools/assistant/aboutdialog.h b/src/assistant/tools/assistant/aboutdialog.h new file mode 100644 index 0000000..292312d --- /dev/null +++ b/src/assistant/tools/assistant/aboutdialog.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QLabel; +class QPushButton; +class QGridLayout; + +class AboutLabel : public QTextBrowser +{ + Q_OBJECT + +public: + AboutLabel(QWidget *parent = 0); + void setText(const QString &text, const QByteArray &resources); + QSize minimumSizeHint() const; + +private: + QVariant loadResource(int type, const QUrl &name); + void setSource(const QUrl &url); + + QMap m_resourceMap; +}; + +class AboutDialog : public QDialog +{ + Q_OBJECT + +public: + AboutDialog(QWidget *parent = 0); + void setText(const QString &text, const QByteArray &resources); + void setPixmap(const QPixmap &pixmap); + QString documentTitle() const; + +private: + void updateSize(); + + QLabel *m_pixmapLabel; + AboutLabel *m_aboutLabel; + QPushButton *m_closeButton; + QGridLayout *m_layout; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/assistant/tools/assistant/assistant.icns b/src/assistant/tools/assistant/assistant.icns new file mode 100644 index 0000000000000000000000000000000000000000..6291dd3975a034ef2f052fb6a68dd377fab00238 GIT binary patch literal 162568 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