From d274d6cf193b4e719804965671f23ab9c41f7727 Mon Sep 17 00:00:00 2001 From: Petr Prikryl Date: Tue, 25 Jun 2013 10:42:08 +0200 Subject: src/translator.h simplified, translator.cpp removed, ... winbuild/Doxygen.vcproj removed. The conversion tables/functions from within translator classes not used after conversion to UTF-8. --- src/translator.cpp | 249 -- src/translator.h | 85 +- winbuild/Doxygen.vcproj | 8496 +++++++++++++++++++++++------------------------ 3 files changed, 4259 insertions(+), 4571 deletions(-) delete mode 100644 src/translator.cpp diff --git a/src/translator.cpp b/src/translator.cpp deleted file mode 100644 index b161345..0000000 --- a/src/translator.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/*! \file translator.cpp - * \brief Implementation of generally used translator methods. - * - * This file contains implementation of the translator methods that - * are not expected to be reimplemented by derived translator classes. - * It also contains static data tables used by the methods. - * - */ -#include "translator.h" -#include - -/*! The translation table used by Win1250ToISO88592() method. */ -const char Translator::Win1250ToISO88592Tab[] = -{ - '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', - '\x88', '\x89', '\xA9', '\x8B', '\xA6', '\xAB', '\xAE', '\xAC', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x2E', '\x96', '\x97', - '\x98', '\x99', '\xB9', '\x9B', '\xB6', '\xBB', '\xBE', '\xBC', - '\xA0', '\x20', '\x20', '\xA3', '\xA4', '\xA1', '\xA6', '\xA7', - '\x22', '\xA9', '\xAA', '\x3C', '\xAC', '\x2D', '\xAE', '\xAF', - '\x2E', '\x2B', '\x20', '\xB3', '\x27', '\x75', '\xB6', '\xB7', - '\x20', '\xB1', '\xBA', '\x3E', '\xA5', '\x22', '\xB5', '\xBF', - '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', - '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', - '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', - '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', - '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', - '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', - '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\x2D', - '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', - '\0' -}; - - -/*! The translation table used by ISO88592ToWin1250() method. */ -const char Translator::ISO88592ToWin1250Tab[] = { - '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', - '\x88', '\x89', '\x8A', '\x8B', '\x8C', '\x8D', '\x8E', '\x8F', - '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', - '\x98', '\x99', '\x9A', '\x9B', '\x9C', '\x9D', '\x9E', '\x9F', - '\xA0', '\xA5', '\xA2', '\xA3', '\xA4', '\xBC', '\x8C', '\xA7', - '\xA8', '\x8A', '\xAA', '\x8D', '\x8F', '\xAD', '\x8E', '\xAF', - '\xB0', '\xB9', '\xB2', '\xB3', '\xB4', '\xBE', '\x9C', '\xB7', - '\xB8', '\x9A', '\xBA', '\x9D', '\x9F', '\xBD', '\x9E', '\xBF', - '\xC0', '\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', - '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', '\xCF', - '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', - '\xD8', '\xD9', '\xDA', '\xDB', '\xDC', '\xDD', '\xDE', '\xDF', - '\xE0', '\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', - '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', '\xEF', - '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', - '\xF8', '\xF9', '\xFA', '\xFB', '\xFC', '\xFD', '\xFE', '\xFF', - '\0' -}; - - -/*! The translation table used by Koi8RToWindows1251() method. */ -const unsigned char Translator::Koi8RToWindows1251Tab[128] = -{ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, - 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, - 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, - 254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238, - 239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250, - 222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206, - 207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218 -}; - - -/*! The translation table used by Windows1251ToKoi8R() method. */ -const unsigned char Translator::Windows1251ToKoi8RTab[128] = -{ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, - 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, - 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, - 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240, - 242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241, - 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208, - 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209 -}; - -/*! Returns the string converted from windows-1250 to iso-8859-2. */ -/* The method was designed initially for translator_cz.h. - * It is used for on-line encoding conversion related to - * conditional compilation in Unix/MS Windows environments - * (both use different encoding). Later, the translator_hr.h - * (by Boris Bralo) used and improved the same style. As the - * method with the translation table was the same, the - * decision to move it to this base class was made. The same - * holds for ISO88592ToWin1250() method. - * - * Alexandr Chelpanov used the same approach for - * Koi8RToWindows1251() and Windows1251ToKoi8R() methods. Notice, - * that he uses Unicode tables. - * - * It is recommended for possibly other similar methods in future. - */ -QCString Translator::Win1250ToISO88592(const QCString & sInput) -{ - // The conversion table for characters >127 - // - - QCString result; - int len = sInput.length(); - - for (int i = 0; i < len; ++i) - { - unsigned int c = sInput[i]; - result += (c > 127) ? Win1250ToISO88592Tab[c & 0x7F] : c; - } - return result; -} - - -/*! returns the string converted from iso-8859-2 to windows-1250 */ -/* See the comments of the Win1250ToISO88592() method for details. */ -QCString Translator::ISO88592ToWin1250(const QCString & sInput) -{ - // The conversion table for characters >127 - // - QCString result; - int len = sInput.length(); - - for (int i = 0; i < len; ++i) - { - unsigned int c = sInput[i]; - result += (c > 127) ? ISO88592ToWin1250Tab[c & 0x7F] : c; - } - return result; -} - - -/*! Returns the string converted from koi8-r to windows-1251. */ -/* The method was designed initially for translator_cz.h. - It is used for on-line encoding conversion related to conditional - compilation in Unix/MS Windows environments (both use different - encoding). Encoding table got from QT:qtextcodec.cpp - */ -QCString Translator::Koi8RToWindows1251( const QCString & sInput ) -{ - - QCString result(sInput); - int len = sInput.length(); - - const unsigned char * c = (const unsigned char *)(const char*)sInput; - unsigned char *dc = (unsigned char*)(const char*)result; - for( int i=0; i 127 ) - dc[i] = Koi8RToWindows1251Tab[c[i]-128]; - } - return result; -} - - -/*! returns the string converted from Windows-1251 to koi8-r */ -/* See the comments of the Koi8RToWindows1251() method for details. - Encoding table got from QT:qtextcodec.cpp */ -QCString Translator::Windows1251ToKoi8R( const QCString & sInput ) -{ - QCString result(sInput); - int len = sInput.length(); - - const unsigned char * c = (const unsigned char *)(const char*)sInput; - unsigned char *dc = (unsigned char*)(const char*)result; - for( int i=0; i 127 ) - dc[i] = Windows1251ToKoi8RTab[c[i]-128]; - } - return result; -} - -/*! returns the caracter converted from hankaku-kana to zenkakukana. - Thanks Yongmao Ni http://alfin.mine.utsunomiya-u.ac.jp/~niy/algo/ */ -unsigned int hankaku2zen(int hankaku) -{ - static unsigned int z[64] = { - 0x2121,0x2123,0x2156,0x2157,0x2122,0x2126,0x2572,0x2521, - 0x2523,0x2525,0x2527,0x2529,0x2563,0x2565,0x2567,0x2543, - 0x213c,0x2522,0x2524,0x2526,0x2528,0x252a,0x252b,0x252d, - 0x252f,0x2531,0x2533,0x2535,0x2537,0x2539,0x253b,0x253d, - 0x253f,0x2541,0x2544,0x2546,0x2548,0x254a,0x254b,0x254c, - 0x254d,0x254e,0x254f,0x2552,0x2555,0x2558,0x255b,0x255e, - 0x255f,0x2560,0x2561,0x2562,0x2564,0x2566,0x2568,0x2569, - 0x256a,0x256b,0x256c,0x256d,0x256f,0x2573,0x212b,0x212c }; - - if (hankaku < 0xa0 || hankaku > 0xdf) return 0; - return z[hankaku - 0xa0]; -} - -/*! returns the character converted from japaneseEUC to SJIS - Thanks Yongmao Ni http://alfin.mine.utsunomiya-u.ac.jp/~niy/algo/ */ -unsigned int euc2sjis(unsigned int euc) -{ - unsigned int jis; - unsigned int hib, lob; - - if ((euc & 0xff00) == 0x8e00) - jis = hankaku2zen(euc & 0xff); - else jis = euc & ~0x8080; - - hib = (jis >> 8) & 0xff; - lob = jis & 0xff; - lob += (hib & 1) ? 0x1f : 0x7d; - if (lob >= 0x7f) lob++; - hib = ((hib - 0x21) >> 1) + 0x81; - if (hib > 0x9f) hib += 0x40; - - return (hib << 8) | lob; -} - - -/*! returns the string converted from Japanese-EUC to SJIS */ - -QCString Translator::JapaneseEucToSjis( const QCString & sInput ) -{ - QString result; - int len = sInput.length(); - int c1,c2,sj; - - result.setUnicode(0, len); - QChar* uc = (QChar*)result.unicode(); // const_cast - const unsigned char * c = (const unsigned char *)(const char*)sInput; - - for( int i=0; i> 8; - uc[i+1] = sj & 0xff; - i+=2; - } - } - - return result.latin1(); - -} diff --git a/src/translator.h b/src/translator.h index 4de5da7..da832e3 100644 --- a/src/translator.h +++ b/src/translator.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2013 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -23,45 +23,22 @@ /** Abstract base class for all translatable text fragments. */ class Translator { - private: - /* Tables for encoding conversions. */ - static const char Win1250ToISO88592Tab[]; - static const char ISO88592ToWin1250Tab[]; - static const unsigned char Koi8RToWindows1251Tab[128]; - static const unsigned char Windows1251ToKoi8RTab[128]; - - protected: - /*! Returns the string converted from windows-1250 to iso-8859-2. */ - QCString Win1250ToISO88592(const QCString & sInput); - - /*! Returns the string converted from iso-8859-2 to windows-1250. */ - QCString ISO88592ToWin1250(const QCString & sInput); - - /*! Returns the string converted from koi8-r to windows-1251. */ - QCString Koi8RToWindows1251( const QCString & sInput ); - - /*! Returns the string converted from windows-1251 to koi8-r. */ - QCString Windows1251ToKoi8R( const QCString & sInput ); - - /*! Returns the string converted from Japanese-EUC to SJIS. */ - QCString JapaneseEucToSjis( const QCString & sInput ); - public: /*! This method is used to provide warning message that is displayed - * if the user chooses a language whose translation is not up to date. + * if the user chooses a language whose translation is not up to date. * It is implemented by the adapter classes. */ virtual QCString updateNeededMessage() { return ""; } virtual ~Translator() {} - + // Please, have a look at comments inside the translator_en.h file // to learn the meaning of the following methods. The translator_en.h - // file contains the TranslatorEnglish implementation, which is + // file contains the TranslatorEnglish implementation, which is // always up-to-date (by definition). - + // --- Language control methods ------------------- - + virtual QCString idLanguage() = 0; virtual QCString latexLanguageSupportCommand() = 0; virtual QCString idLanguageCharset() = 0; @@ -107,14 +84,14 @@ class Translator virtual QCString trRelatedPagesDescription() = 0; virtual QCString trModulesDescription() = 0; //virtual QCString trNoDescriptionAvailable() = 0; - - // index titles (the project name is prepended for these) + + // index titles (the project name is prepended for these) virtual QCString trDocumentation() = 0; virtual QCString trModuleIndex() = 0; virtual QCString trHierarchicalIndex() = 0; virtual QCString trCompoundIndex() = 0; - virtual QCString trFileIndex() = 0; + virtual QCString trFileIndex() = 0; virtual QCString trModuleDocumentation() = 0; virtual QCString trClassDocumentation() = 0; virtual QCString trFileDocumentation() = 0; @@ -153,17 +130,17 @@ class Translator ////////////////////////////////////////////////////////////////////////// // new since 0.49-990307 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trNamespaceList() = 0; virtual QCString trNamespaceListDescription(bool extractAll) = 0; virtual QCString trFriends() = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 0.49-990405 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trRelatedFunctionDocumentation() = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 0.49-990425 ////////////////////////////////////////////////////////////////////////// @@ -174,7 +151,7 @@ class Translator virtual QCString trFileReference(const char *fileName) = 0; virtual QCString trNamespaceReference(const char *namespaceName) = 0; - + virtual QCString trPublicMembers() = 0; virtual QCString trPublicSlots() = 0; virtual QCString trSignals() = 0; @@ -254,7 +231,7 @@ class Translator ////////////////////////////////////////////////////////////////////////// // new since 1.1.0 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trNote() = 0; virtual QCString trPublicTypes() = 0; virtual QCString trPublicAttribs() = 0; @@ -282,7 +259,7 @@ class Translator virtual QCString trAttention() = 0; virtual QCString trInclByDepGraph() = 0; virtual QCString trSince() = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 1.1.5 ////////////////////////////////////////////////////////////////////////// @@ -290,11 +267,11 @@ class Translator virtual QCString trLegendTitle() = 0; virtual QCString trLegendDocs() = 0; virtual QCString trLegend() = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 1.2.0 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trTest() = 0; virtual QCString trTestList() = 0; @@ -323,11 +300,11 @@ class Translator virtual QCString trPackages() = 0; //virtual QCString trPackageDocumentation() = 0; virtual QCString trDefineValue() = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 1.2.5 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trBug() = 0; virtual QCString trBugList() = 0; @@ -388,12 +365,12 @@ class Translator * 222 — Thai * 238 — Eastern European * 254 — PC 437 - * 255 — OEM + * 255 — OEM * */ virtual QCString trRTFCharSet() = 0; virtual QCString trRTFGeneralIndex() = 0; - + // Translation of the word virtual QCString trClass(bool first_capital, bool singular) = 0; @@ -408,7 +385,7 @@ class Translator ////////////////////////////////////////////////////////////////////////// // new since 1.2.7 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trAuthor(bool first_capital, bool singular) = 0; ////////////////////////////////////////////////////////////////////////// @@ -423,7 +400,7 @@ class Translator virtual QCString trImplementedFromList(int numEntries) = 0; virtual QCString trImplementedInList(int numEntries) = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 1.2.16 ////////////////////////////////////////////////////////////////////////// @@ -435,7 +412,7 @@ class Translator ////////////////////////////////////////////////////////////////////////// virtual QCString trDeprecatedList() = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 1.2.18 ////////////////////////////////////////////////////////////////////////// @@ -452,7 +429,7 @@ class Translator virtual QCString trStaticPackageMembers() = 0; virtual QCString trPackageAttribs() = 0; virtual QCString trStaticPackageAttribs() = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 1.3.1 ////////////////////////////////////////////////////////////////////////// @@ -495,14 +472,14 @@ class Translator ////////////////////////////////////////////////////////////////////////// // new since 1.4.6 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trCallerGraph() = 0; virtual QCString trEnumerationValueDocumentation() = 0; ////////////////////////////////////////////////////////////////////////// // new since 1.5.4 ////////////////////////////////////////////////////////////////////////// - + virtual QCString trMemberFunctionDocumentationFortran() = 0; virtual QCString trCompoundListFortran() = 0; virtual QCString trCompoundMembersFortran() = 0; @@ -549,7 +526,7 @@ class Translator virtual QCString trDateTime(int year,int month,int day,int dayOfWeek, int hour,int minutes,int seconds, bool includeTime) = 0; - + ////////////////////////////////////////////////////////////////////////// // new since 1.7.5 ////////////////////////////////////////////////////////////////////////// diff --git a/winbuild/Doxygen.vcproj b/winbuild/Doxygen.vcproj index 7ab4653..5d53e04 100644 --- a/winbuild/Doxygen.vcproj +++ b/winbuild/Doxygen.vcproj @@ -1,4268 +1,4228 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v0.12