summaryrefslogtreecommitdiffstats
path: root/tqtinterface/qt4/src/kernel/tqtranslator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tqtinterface/qt4/src/kernel/tqtranslator.cpp')
-rw-r--r--tqtinterface/qt4/src/kernel/tqtranslator.cpp2438
1 files changed, 0 insertions, 2438 deletions
diff --git a/tqtinterface/qt4/src/kernel/tqtranslator.cpp b/tqtinterface/qt4/src/kernel/tqtranslator.cpp
deleted file mode 100644
index 4a3e34e..0000000
--- a/tqtinterface/qt4/src/kernel/tqtranslator.cpp
+++ /dev/null
@@ -1,2438 +0,0 @@
-/****************************************************************************
-**
-** Localization database support.
-**
-** Created : 980906
-**
-** Copyright (C) 1998-2008 Trolltech ASA. All rights reserved.
-**
-** This file is part of the kernel module of the TQt GUI Toolkit.
-**
-** This file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free
-** Software Foundation and appearing in the files LICENSE.GPL2
-** and LICENSE.GPL3 included in the packaging of this file.
-** Alternatively you may (at your option) use any later version
-** of the GNU General Public License if such license has been
-** publicly approved by Trolltech ASA (or its successors, if any)
-** and the KDE Free TQt Foundation.
-**
-** Please review the following information to ensure GNU General
-** Public Licensing requirements will be met:
-** http://trolltech.com/products/qt/licenses/licensing/opensource/.
-** If you are unsure which license is appropriate for your use, please
-** review the following information:
-** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
-** or contact the sales department at sales@trolltech.com.
-**
-** This file may be used under the terms of the Q Public License as
-** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
-** included in the packaging of this file. Licensees holding valid TQt
-** Commercial licenses may use this file in accordance with the TQt
-** Commercial License Agreement provided with the Software.
-**
-** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
-** herein.
-**
-**********************************************************************/
-
-#include "tqplatformdefs.h"
-
-// POSIX Large File Support redefines open -> open64
-static inline int qt_open(const char *pathname, int flags, mode_t mode)
-{ return ::open(pathname, flags, mode); }
-#if defined(open)
-# undef open
-#endif
-
-// POSIX Large File Support redefines truncate -> truncate64
-#if defined(truncate)
-# undef truncate
-#endif
-
-#include "tqtranslator.h"
-
-#ifndef TQT_NO_TRANSLATION
-
-#include "tqfileinfo.h"
-#include "tqwidgetlist.h"
-#include "tqintdict.h"
-#include "tqstring.h"
-#include "tqapplication.h"
-#include "tqfile.h"
-#include "tqbuffer.h"
-#include "tqdatastream.h"
-#include "tqmap.h"
-#include "tqtl.h"
-
-#if defined(TQ_OS_UNIX)
-#define TQT_USE_MMAP
-#endif
-
-// most of the headers below are already included in qplatformdefs.h
-// also this lacks Large File support but that's probably irrelevant
-#if defined(TQT_USE_MMAP)
-// for mmap
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <errno.h>
-// for htonl
-#include <netinet/in.h>
-#endif
-
-#include <stdlib.h>
-
-#ifdef USE_QT4
-
-// magic number for the file
-static const int MagicLength = 16;
-static const uchar magic[MagicLength] = {
- 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
- 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
-};
-
-static bool match( const char* found, const char* target )
-{
- // 0 means anything, "" means empty
- return found == 0 || qstrcmp( found, target ) == 0;
-}
-
-#if defined(TQ_C_CALLBACKS)
-extern "C" {
-#endif
-
-/*
- Yes, unfortunately, we have code here that depends on endianness.
- The candidate is big endian (it comes from a .qm file) whereas the
- target endianness depends on the system TQt is running on.
-*/
-#ifdef TQ_OS_TEMP
-static int __cdecl cmp_uint32_little( const void* target, const void* candidate )
-#else
-static int cmp_uint32_little( const void* target, const void* candidate )
-#endif
-{
- const uchar* t = (const uchar*) target;
- const uchar* c = (const uchar*) candidate;
- return t[3] != c[0] ? (int) t[3] - (int) c[0]
- : t[2] != c[1] ? (int) t[2] - (int) c[1]
- : t[1] != c[2] ? (int) t[1] - (int) c[2]
- : (int) t[0] - (int) c[3];
-}
-
-#ifdef TQ_OS_TEMP
-static int __cdecl cmp_uint32_big( const void* target, const void* candidate )
-#else
-static int cmp_uint32_big( const void* target, const void* candidate )
-#endif
-{
- const uchar* t = (const uchar*) target;
- const uchar* c = (const uchar*) candidate;
- return t[0] != c[0] ? (int) t[0] - (int) c[0]
- : t[1] != c[1] ? (int) t[1] - (int) c[1]
- : t[2] != c[2] ? (int) t[2] - (int) c[2]
- : (int) t[3] - (int) c[3];
-}
-
-#if defined(TQ_C_CALLBACKS)
-}
-#endif
-
-static int systemWordSize = 0;
-static bool systemBigEndian;
-
-static uint elfHash( const char * name )
-{
- const uchar *k;
- uint h = 0;
- uint g;
-
- if ( name ) {
- k = (const uchar *) name;
- while ( *k ) {
- h = ( h << 4 ) + *k++;
- if ( (g = (h & 0xf0000000)) != 0 )
- h ^= g >> 24;
- h &= ~g;
- }
- }
- if ( !h )
- h = 1;
- return h;
-}
-
-extern bool qt_detectRTLLanguage();
-
-class TQTranslatorPrivate {
-public:
- struct Offset {
- Offset()
- : h( 0 ), o( 0 ) { }
- Offset( const TQTranslatorMessage& m, int offset )
- : h( m.hash() ), o( offset ) { }
-
- bool operator<( const Offset&k ) const {
- return ( h != k.h ) ? h < k.h : o < k.o;
- }
- TQ_DUMMY_COMPARISON_OPERATOR(TQTranslatorPrivate::Offset)
- uint h;
- uint o;
- };
-
- enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69 };
-
- TQTranslatorPrivate() :
- unmapPointer( 0 ), unmapLength( 0 ),
- messageArray( 0 ), offsetArray( 0 ), contextArray( 0 )
-#ifndef TQT_NO_TRANSLATION_BUILDER
- , messages( 0 )
-#endif
- { }
- // TQTranslator must finalize this before deallocating it
-
- // for mmap'ed files, this is what needs to be unmapped.
- char * unmapPointer;
- unsigned int unmapLength;
-
- // for squeezed but non-file data, this is what needs to be deleted
- TQByteArray * messageArray;
- TQByteArray * offsetArray;
- TQByteArray * contextArray;
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
- TQMap<TQTranslatorMessage, void *> * messages;
-#endif
-#ifdef TQ_WS_WIN
- int oldPermissionLookup;
-#endif
-};
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
-
-/*!
- Returns a list of the messages in the translator. This function is
- rather slow. Because it is seldom called, it's optimized for
- simplicity and small size, rather than speed.
-
- If you want to iterate over the list, you should iterate over a
- copy, e.g.
- \code
- TQValueList<TQTranslatorMessage> list = myTranslator.messages();
- TQValueList<TQTranslatorMessage>::Iterator it = list.begin();
- while ( it != list.end() ) {
- process_message( *it );
- ++it;
- }
- \endcode
-*/
-
-TQValueList<TQTranslatorMessage> TQTranslator::messages() const
-{
- if ( d->messages )
- return d->messages->keys();
-
- ((TQTranslator *) this)->unsqueeze();
- TQValueList<TQTranslatorMessage> result = d->messages->keys();
- delete d->messages;
- d->messages = 0;
- return result;
-}
-
-/*!
- Saves this message file to \a filename, overwriting the previous
- contents of \a filename. If \a mode is \c Everything (the
- default), all the information is preserved. If \a mode is \c
- Stripped, any information that is not necessary for findMessage()
- is stripped away.
-
- \sa load()
-*/
-
-bool TQTranslator::save( const TQString & filename, SaveMode mode )
-{
- TQFile f( filename );
- if ( f.open( IO_WriteOnly ) ) {
- squeeze( mode );
-
- TQDataStream s( &f );
- s.writeRawBytes( (const char *)magic, MagicLength );
- TQ_UINT8 tag;
-
- if ( d->offsetArray != 0 ) {
- tag = (TQ_UINT8) TQTranslatorPrivate::Hashes;
- TQ_UINT32 oas = (TQ_UINT32) d->offsetArray->size();
- s << tag << oas;
- s.writeRawBytes( d->offsetArray->data(), oas );
- }
- if ( d->messageArray != 0 ) {
- tag = (TQ_UINT8) TQTranslatorPrivate::Messages;
- TQ_UINT32 mas = (TQ_UINT32) d->messageArray->size();
- s << tag << mas;
- s.writeRawBytes( d->messageArray->data(), mas );
- }
- if ( d->contextArray != 0 ) {
- tag = (TQ_UINT8) TQTranslatorPrivate::Contexts;
- TQ_UINT32 cas = (TQ_UINT32) d->contextArray->size();
- s << tag << cas;
- s.writeRawBytes( d->contextArray->data(), cas );
- }
- return TRUE;
- }
- return FALSE;
-}
-
-/*!
- Empties this translator of all contents.
-
- This function works with stripped translator files.
-*/
-
-void TQTranslator::clear()
-{
- if ( d->unmapPointer && d->unmapLength ) {
-#if defined(TQT_USE_MMAP)
- munmap( d->unmapPointer, d->unmapLength );
-#else
- delete [] d->unmapPointer;
-#endif
- d->unmapPointer = 0;
- d->unmapLength = 0;
- }
-
- if ( d->messageArray ) {
- d->messageArray->resetRawData( d->messageArray->data(),
- d->messageArray->size() );
- delete d->messageArray;
- d->messageArray = 0;
- }
- if ( d->offsetArray ) {
- d->offsetArray->resetRawData( d->offsetArray->data(),
- d->offsetArray->size() );
- delete d->offsetArray;
- d->offsetArray = 0;
- }
- if ( d->contextArray ) {
- d->contextArray->resetRawData( d->contextArray->data(),
- d->contextArray->size() );
- delete d->contextArray;
- d->contextArray = 0;
- }
-#ifndef TQT_NO_TRANSLATION_BUILDER
- delete d->messages;
- d->messages = 0;
-#endif
-
- if ( tqApp ) {
- tqApp->setReverseLayout( qt_detectRTLLanguage() );
-
- TQWidgetList *list = TQApplication::tqtopLevelWidgets();
- TQWidgetListIt it( *list );
- TQWidget *w;
- while ( ( w=it.current() ) != 0 ) {
- ++it;
- if (!w->isDesktop())
- tqApp->postEvent( w, new TQEvent( TQEvent::LanguageChange ) );
- }
- delete list;
- }
-}
-
-/*!
- Converts this message file to the compact format used to store
- message files on disk.
-
- You should never need to call this directly; save() and other
- functions call it as necessary. \a mode is for internal use.
-
- \sa save() unsqueeze()
-*/
-
-void TQTranslator::squeeze( SaveMode mode )
-{
- if ( !d->messages ) {
- if ( mode == Stripped )
- unsqueeze();
- else
- return;
- }
-
- TQMap<TQTranslatorMessage, void *> * messages = d->messages;
-
- d->messages = 0;
- clear();
-
- d->messageArray = new TQByteArray;
- d->offsetArray = new TQByteArray;
-
- TQMap<TQTranslatorPrivate::Offset, void *> offsets;
-
- TQDataStream ms( *d->messageArray, IO_WriteOnly );
- TQMap<TQTranslatorMessage, void *>::Iterator it = messages->begin(), next;
- int cpPrev = 0, cpNext = 0;
- for ( it = messages->begin(); it != messages->end(); ++it ) {
- cpPrev = cpNext;
- next = it;
- ++next;
- if ( next == messages->end() )
- cpNext = 0;
- else
- cpNext = (int) it.key().commonPrefix( next.key() );
- offsets.replace( TQTranslatorPrivate::Offset(it.key(),
- ms.tqdevice()->at()), (void*)0 );
- it.key().write( ms, mode == Stripped,
- (TQTranslatorMessage::Prefix) TQMAX(cpPrev, cpNext + 1) );
- }
-
- d->offsetArray->resize( 0 );
- TQMap<TQTranslatorPrivate::Offset, void *>::Iterator offset;
- offset = offsets.begin();
- TQDataStream ds( *d->offsetArray, IO_WriteOnly );
- while ( offset != offsets.end() ) {
- TQTranslatorPrivate::Offset k = offset.key();
- ++offset;
- ds << (TQ_UINT32)k.h << (TQ_UINT32)k.o;
- }
-
- if ( mode == Stripped ) {
- TQAsciiDict<int> contextSet( 1511 );
- int baudelaire;
-
- for ( it = messages->begin(); it != messages->end(); ++it )
- contextSet.replace( it.key().context(), &baudelaire );
-
- TQ_UINT16 hTableSize;
- if ( contextSet.count() < 200 )
- hTableSize = ( contextSet.count() < 60 ) ? 151 : 503;
- else if ( contextSet.count() < 2500 )
- hTableSize = ( contextSet.count() < 750 ) ? 1511 : 5003;
- else
- hTableSize = 15013;
-
- TQIntDict<char> hDict( hTableSize );
- TQAsciiDictIterator<int> c = contextSet;
- while ( c.current() != 0 ) {
- hDict.insert( (long) (elfHash(c.currentKey()) % hTableSize),
- c.currentKey() );
- ++c;
- }
-
- /*
- The contexts found in this translator are stored in a hash
- table to provide fast lookup. The context array has the
- following format:
-
- TQ_UINT16 hTableSize;
- TQ_UINT16 hTable[hTableSize];
- TQ_UINT8 contextPool[...];
-
- The context pool stores the contexts as Pascal strings:
-
- TQ_UINT8 len;
- TQ_UINT8 data[len];
-
- Let's consider the look-up of context "FunnyDialog". A
- hash value between 0 and hTableSize - 1 is computed, say h.
- If hTable[h] is 0, "FunnyDialog" is not covered by this
- translator. Else, we check in the contextPool at offset
- 2 * hTable[h] to see if "FunnyDialog" is one of the
- contexts stored there, until we find it or we meet the
- empty string.
- */
- d->contextArray = new TQByteArray;
- d->contextArray->resize( 2 + (hTableSize << 1) );
- TQDataStream t( *d->contextArray, IO_WriteOnly );
- TQ_UINT16 *hTable = new TQ_UINT16[hTableSize];
- memset( hTable, 0, hTableSize * sizeof(TQ_UINT16) );
-
- t << hTableSize;
- t.tqdevice()->at( 2 + (hTableSize << 1) );
- t << (TQ_UINT16) 0; // the entry at offset 0 cannot be used
- uint upto = 2;
-
- for ( int i = 0; i < hTableSize; i++ ) {
- const char *con = hDict.find( i );
- if ( con == 0 ) {
- hTable[i] = 0;
- } else {
- hTable[i] = (TQ_UINT16) ( upto >> 1 );
- do {
- uint len = (uint) tqstrlen( con );
- len = TQMIN( len, 255 );
- t << (TQ_UINT8) len;
- t.writeRawBytes( con, len );
- upto += 1 + len;
- hDict.remove( i );
- } while ( (con = hDict.find(i)) != 0 );
- do {
- t << (TQ_UINT8) 0; // empty string (at least one)
- upto++;
- } while ( (upto & 0x1) != 0 ); // offsets have to be even
- }
- }
- t.tqdevice()->at( 2 );
- for ( int j = 0; j < hTableSize; j++ )
- t << hTable[j];
- delete [] hTable;
-
- if ( upto > 131072 ) {
- qWarning( "TQTranslator::squeeze: Too many contexts" );
- delete d->contextArray;
- d->contextArray = 0;
- }
- }
- delete messages;
-}
-
-
-/*!
- Converts this message file into an easily modifiable data
- structure, less compact than the format used in the files.
-
- You should never need to call this function; it is called by
- insert() and friends as necessary.
-
- \sa squeeze()
-*/
-
-void TQTranslator::unsqueeze()
-{
- if ( d->messages )
- return;
-
- d->messages = new TQMap<TQTranslatorMessage, void *>;
- if ( !d->messageArray )
- return;
-
- TQDataStream s( *d->messageArray, IO_ReadOnly );
- for ( ;; ) {
- TQTranslatorMessage m( s );
- if ( m.hash() == 0 )
- break;
- d->messages->insert( m, (void *) 0 );
- }
-}
-
-/*!
- Returns TRUE if this message file contains a message with the key
- (\a context, \a sourceText, \a comment); otherwise returns FALSE.
-
- This function works with stripped translator files.
-
- (This is is a one-liner that calls findMessage().)
-*/
-
-bool TQTranslator::contains( const char* context, const char* sourceText,
- const char* comment ) const
-{
- return !findMessage( context, sourceText, comment ).translation().isNull();
-}
-
-/*!
- Inserts \a message into this message file.
-
- This function does \e not work with stripped translator files. It
- may appear to, but that is not dependable.
-
- \sa remove()
-*/
-
-void TQTranslator::insert( const TQTranslatorMessage& message )
-{
- unsqueeze();
- d->messages->remove( message ); // safer
- d->messages->insert( message, (void *) 0 );
-}
-
-
-/*!
- \fn void TQTranslator::insert( const char *, const char *, const TQString & )
- \overload
- \obsolete
-*/
-
-/*!
- Removes \a message from this translator.
-
- This function works with stripped translator files.
-
- \sa insert()
-*/
-
-void TQTranslator::remove( const TQTranslatorMessage& message )
-{
- unsqueeze();
- d->messages->remove( message );
-}
-
-/*! Returns the TQTranslatorMessage for the key
- (\a context, \a sourceText, \a comment). If none is found,
- also tries (\a context, \a sourceText, "").
-*/
-
-#endif
-
-TQTranslatorMessage TQTranslator::findMessage( const char* context,
- const char* sourceText,
- const char* comment ) const
-{
- if ( context == 0 )
- context = "";
- if ( sourceText == 0 )
- sourceText = "";
- if ( comment == 0 )
- comment = "";
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
- if ( d->messages ) {
- TQMap<TQTranslatorMessage, void *>::ConstIterator it;
-
- it = d->messages->find( TQTranslatorMessage(context, sourceText,
- comment) );
- if ( it != d->messages->end() )
- return it.key();
-
- if ( comment[0] ) {
- it = d->messages->find( TQTranslatorMessage(context, sourceText,
- "") );
- if ( it != d->messages->end() )
- return it.key();
- }
- return TQTranslatorMessage();
- }
-#endif
-
- if ( !d->offsetArray )
- return TQTranslatorMessage();
-
- /*
- Check if the context belongs to this TQTranslator. If many translators are
- installed, this step is necessary.
- */
- if ( d->contextArray ) {
- TQ_UINT16 hTableSize = 0;
- TQDataStream t( *d->contextArray, IO_ReadOnly );
- t >> hTableSize;
- uint g = elfHash( context ) % hTableSize;
- t.tqdevice()->at( 2 + (g << 1) );
- TQ_UINT16 off;
- t >> off;
- if ( off == 0 )
- return TQTranslatorMessage();
- t.tqdevice()->at( 2 + (hTableSize << 1) + (off << 1) );
-
- TQ_UINT8 len;
- char con[256];
- for ( ;; ) {
- t >> len;
- if ( len == 0 )
- return TQTranslatorMessage();
- t.readRawBytes( con, len );
- con[len] = '\0';
- if ( qstrcmp(con, context) == 0 )
- break;
- }
- }
-
- size_t numItems = d->offsetArray->size() / ( 2 * sizeof(TQ_UINT32) );
- if ( !numItems )
- return TQTranslatorMessage();
-
- if ( systemWordSize == 0 )
- qSysInfo( &systemWordSize, &systemBigEndian );
-
- for ( ;; ) {
- TQ_UINT32 h = elfHash( TQCString(sourceText) + comment );
-
- char *r = (char *) bsearch( &h, d->offsetArray->data(), numItems,
- 2 * sizeof(TQ_UINT32),
- systemBigEndian ? cmp_uint32_big
- : cmp_uint32_little );
- if ( r != 0 ) {
- // go back on equal key
- while ( r != d->offsetArray->data() &&
- cmp_uint32_big(r - 8, r) == 0 )
- r -= 8;
-
- TQDataStream s( *d->offsetArray, IO_ReadOnly );
- s.tqdevice()->at( r - d->offsetArray->data() );
-
- TQ_UINT32 rh, ro;
- s >> rh >> ro;
-
- TQDataStream ms( *d->messageArray, IO_ReadOnly );
- while ( rh == h ) {
- ms.tqdevice()->at( ro );
- TQTranslatorMessage m( ms );
- if ( match(m.context(), context)
- && match(m.sourceText(), sourceText)
- && match(m.comment(), comment) )
- return m;
- if ( s.atEnd() )
- break;
- s >> rh >> ro;
- }
- }
- if ( !comment[0] )
- break;
- comment = "";
- }
- return TQTranslatorMessage();
-}
-
-// The functions below handle TQTranslatorMessage [USE_QT4]
-
-/*!
- \class TQTranslatorMessage
-
- \brief The TQTranslatorMessage class contains a translator message and its
- properties.
-
- \ingroup i18n
- \ingroup environment
-
- This class is of no interest to most applications. It is useful
- for translation tools such as \link linguist-manual.book TQt
- Linguist\endlink. It is provided simply to make the API complete
- and regular.
-
- For a TQTranslator object, a lookup key is a triple (\e context, \e
- {source text}, \e comment) that uniquely identifies a message. An
- extended key is a quadruple (\e hash, \e context, \e {source
- text}, \e comment), where \e hash is computed from the source text
- and the comment. Unless you plan to read and write messages
- yourself, you need not worry about the hash value.
-
- TQTranslatorMessage stores this triple or quadruple and the relevant
- translation if there is any.
-
- \sa TQTranslator
-*/
-
-/*!
- Constructs a translator message with the extended key (0, 0, 0, 0)
- and TQString::null as translation.
-*/
-
-TQTranslatorMessage::TQTranslatorMessage()
- : h( 0 ), cx( 0 ), st( 0 ), cm( 0 )
-{
-}
-
-
-/*!
- Constructs an translator message with the extended key (\e h, \a
- context, \a sourceText, \a comment), where \e h is computed from
- \a sourceText and \a comment, and possibly with a \a translation.
-*/
-
-TQTranslatorMessage::TQTranslatorMessage( const char * context,
- const char * sourceText,
- const char * comment,
- const TQString& translation )
- : cx( context ), st( sourceText ), cm( comment ), tn( translation )
-{
- // 0 means we don't know, "" means empty
- if ( cx == (const char*)0 )
- cx = "";
- if ( st == (const char*)0 )
- st = "";
- if ( cm == (const char*)0 )
- cm = "";
- h = elfHash( st + cm );
-}
-
-
-/*!
- Constructs a translator message read from the \a stream. The
- resulting message may have any combination of content.
-
- \sa TQTranslator::save()
-*/
-
-TQTranslatorMessage::TQTranslatorMessage( TQDataStream & stream )
- : cx( 0 ), st( 0 ), cm( 0 )
-{
- TQString str16;
- char tag;
- TQ_UINT8 obs1;
-
- for ( ;; ) {
- tag = 0;
- if ( !stream.atEnd() )
- stream.readRawBytes( &tag, 1 );
- switch( (Tag)tag ) {
- case Tag_End:
- if ( h == 0 )
- h = elfHash( st + cm );
- return;
- case Tag_SourceText16: // obsolete
- stream >> str16;
- st = str16.latin1();
- break;
- case Tag_Translation:
- stream >> tn;
- break;
- case Tag_Context16: // obsolete
- stream >> str16;
- cx = str16.latin1();
- break;
- case Tag_Hash:
- stream >> h;
- break;
- case Tag_SourceText:
- stream >> st;
- break;
- case Tag_Context:
- stream >> cx;
- if ( cx == "" ) // for compatibility
- cx = 0;
- break;
- case Tag_Comment:
- stream >> cm;
- break;
- case Tag_Obsolete1: // obsolete
- stream >> obs1;
- break;
- default:
- h = 0;
- st = 0;
- cx = 0;
- cm = 0;
- tn = TQString::null;
- return;
- }
- }
-}
-
-
-/*!
- Constructs a copy of translator message \a m.
-*/
-
-TQTranslatorMessage::TQTranslatorMessage( const TQTranslatorMessage & m )
- : cx( m.cx ), st( m.st ), cm( m.cm ), tn( m.tn )
-{
- h = m.h;
-}
-
-
-/*!
- Assigns message \a m to this translator message and returns a
- reference to this translator message.
-*/
-
-TQTranslatorMessage & TQTranslatorMessage::operator=(
- const TQTranslatorMessage & m )
-{
- h = m.h;
- cx = m.cx;
- st = m.st;
- cm = m.cm;
- tn = m.tn;
- return *this;
-}
-
-
-/*!
- \fn uint TQTranslatorMessage::hash() const
-
- Returns the hash value used internally to represent the lookup
- key. This value is zero only if this translator message was
- constructed from a stream containing invalid data.
-
- The hashing function is unspecified, but it will remain unchanged
- in future versions of TQt.
-*/
-
-/*!
- \fn const char *TQTranslatorMessage::context() const
-
- Returns the context for this message (e.g. "MyDialog").
-
- \warning This may return 0 if the TQTranslator object is stripped
- (compressed).
-*/
-
-/*!
- \fn const char *TQTranslatorMessage::sourceText() const
-
- Returns the source text of this message (e.g. "&Save").
-
- \warning This may return 0 if the TQTranslator object is stripped
- (compressed).
-*/
-
-/*!
- \fn const char *TQTranslatorMessage::comment() const
-
- Returns the comment for this message (e.g. "File|Save").
-
- \warning This may return 0 if the TQTranslator object is stripped
- (compressed).
-*/
-
-/*!
- \fn void TQTranslatorMessage::setTranslation( const TQString & translation )
-
- Sets the translation of the source text to \a translation.
-
- \sa translation()
-*/
-
-/*!
- \fn TQString TQTranslatorMessage::translation() const
-
- Returns the translation of the source text (e.g., "&Sauvegarder").
-
- \sa setTranslation()
-*/
-
-/*!
- \enum TQTranslatorMessage::Prefix
-
- Let (\e h, \e c, \e s, \e m) be the extended key. The possible
- prefixes are
-
- \value NoPrefix no prefix
- \value Hash only (\e h)
- \value HashContext only (\e h, \e c)
- \value HashContextSourceText only (\e h, \e c, \e s)
- \value HashContextSourceTextComment the whole extended key, (\e
- h, \e c, \e s, \e m)
-
- \sa write() commonPrefix()
-*/
-
-/*!
- Writes this translator message to the \a stream. If \a strip is
- FALSE (the default), all the information in the message is
- written. If \a strip is TRUE, only the part of the extended key
- specified by \a prefix is written with the translation (\c
- HashContextSourceTextComment by default).
-
- \sa commonPrefix()
-*/
-
-void TQTranslatorMessage::write( TQDataStream & stream, bool strip,
- Prefix prefix ) const
-{
- char tag;
-
- tag = (char)Tag_Translation;
- stream.writeRawBytes( &tag, 1 );
- stream << tn;
-
- bool mustWriteHash = TRUE;
- if ( !strip )
- prefix = HashContextSourceTextComment;
-
- switch ( prefix ) {
- case HashContextSourceTextComment:
- tag = (char)Tag_Comment;
- stream.writeRawBytes( &tag, 1 );
- stream << cm;
- // fall through
- case HashContextSourceText:
- tag = (char)Tag_SourceText;
- stream.writeRawBytes( &tag, 1 );
- stream << st;
- // fall through
- case HashContext:
- tag = (char)Tag_Context;
- stream.writeRawBytes( &tag, 1 );
- stream << cx;
- // fall through
- default:
- if ( mustWriteHash ) {
- tag = (char)Tag_Hash;
- stream.writeRawBytes( &tag, 1 );
- stream << h;
- }
- }
-
- tag = (char)Tag_End;
- stream.writeRawBytes( &tag, 1 );
-}
-
-
-/*!
- Returns the widest lookup prefix that is common to this translator
- message and to message \a m.
-
- For example, if the extended key is for this message is (71,
- "PrintDialog", "Yes", "Print?") and that for \a m is (71,
- "PrintDialog", "No", "Print?"), this function returns \c
- HashContext.
-
- \sa write()
-*/
-
-TQTranslatorMessage::Prefix TQTranslatorMessage::commonPrefix(
- const TQTranslatorMessage& m ) const
-{
- if ( h != m.h )
- return NoPrefix;
- if ( cx != m.cx )
- return Hash;
- if ( st != m.st )
- return HashContext;
- if ( cm != m.cm )
- return HashContextSourceText;
- return HashContextSourceTextComment;
-}
-
-
-/*!
- Returns TRUE if the extended key of this object is equal to that of
- \a m; otherwise returns FALSE.
-*/
-
-bool TQTranslatorMessage::operator==( const TQTranslatorMessage& m ) const
-{
- return h == m.h && cx == m.cx && st == m.st && cm == m.cm;
-}
-
-
-/*!
- \fn bool TQTranslatorMessage::operator!=( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is different from
- that of \a m; otherwise returns FALSE.
-*/
-
-
-/*!
- Returns TRUE if the extended key of this object is
- lexicographically before than that of \a m; otherwise returns
- FALSE.
-*/
-
-bool TQTranslatorMessage::operator<( const TQTranslatorMessage& m ) const
-{
- return h != m.h ? h < m.h
- : ( cx != m.cx ? cx < m.cx
- : (st != m.st ? st < m.st : cm < m.cm) );
-}
-
-
-/*!
- \fn bool TQTranslatorMessage::operator<=( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is
- lexicographically before that of \a m or if they are equal;
- otherwise returns FALSE.
-*/
-
-/*!
- \fn bool TQTranslatorMessage::operator>( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is
- lexicographically after that of \a m; otherwise returns FALSE.
-*/
-
-/*!
- \fn bool TQTranslatorMessage::operator>=( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is
- lexicographically after that of \a m or if they are equal;
- otherwise returns FALSE.
-*/
-
-#else // USE_QT4
-
-/*
-$ mcookie
-3cb86418caef9c95cd211cbf60a1bddd
-$
-*/
-
-// magic number for the file
-static const int MagicLength = 16;
-static const uchar magic[MagicLength] = {
- 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
- 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
-};
-
-static bool match( const char* found, const char* target )
-{
- // 0 means anything, "" means empty
- return found == 0 || qstrcmp( found, target ) == 0;
-}
-
-#if defined(TQ_C_CALLBACKS)
-extern "C" {
-#endif
-
-/*
- Yes, unfortunately, we have code here that depends on endianness.
- The candidate is big endian (it comes from a .qm file) whereas the
- target endianness depends on the system TQt is running on.
-*/
-#ifdef TQ_OS_TEMP
-static int __cdecl cmp_uint32_little( const void* target, const void* candidate )
-#else
-static int cmp_uint32_little( const void* target, const void* candidate )
-#endif
-{
- const uchar* t = (const uchar*) target;
- const uchar* c = (const uchar*) candidate;
- return t[3] != c[0] ? (int) t[3] - (int) c[0]
- : t[2] != c[1] ? (int) t[2] - (int) c[1]
- : t[1] != c[2] ? (int) t[1] - (int) c[2]
- : (int) t[0] - (int) c[3];
-}
-
-#ifdef TQ_OS_TEMP
-static int __cdecl cmp_uint32_big( const void* target, const void* candidate )
-#else
-static int cmp_uint32_big( const void* target, const void* candidate )
-#endif
-{
- const uchar* t = (const uchar*) target;
- const uchar* c = (const uchar*) candidate;
- return t[0] != c[0] ? (int) t[0] - (int) c[0]
- : t[1] != c[1] ? (int) t[1] - (int) c[1]
- : t[2] != c[2] ? (int) t[2] - (int) c[2]
- : (int) t[3] - (int) c[3];
-}
-
-#if defined(TQ_C_CALLBACKS)
-}
-#endif
-
-static int systemWordSize = 0;
-static bool systemBigEndian;
-
-static uint elfHash( const char * name )
-{
- const uchar *k;
- uint h = 0;
- uint g;
-
- if ( name ) {
- k = (const uchar *) name;
- while ( *k ) {
- h = ( h << 4 ) + *k++;
- if ( (g = (h & 0xf0000000)) != 0 )
- h ^= g >> 24;
- h &= ~g;
- }
- }
- if ( !h )
- h = 1;
- return h;
-}
-
-extern bool qt_detectRTLLanguage();
-
-class TQTranslatorPrivate {
-public:
- struct Offset {
- Offset()
- : h( 0 ), o( 0 ) { }
- Offset( const TQTranslatorMessage& m, int offset )
- : h( m.hash() ), o( offset ) { }
-
- bool operator<( const Offset&k ) const {
- return ( h != k.h ) ? h < k.h : o < k.o;
- }
- TQ_DUMMY_COMPARISON_OPERATOR(TQTranslatorPrivate::Offset)
- uint h;
- uint o;
- };
-
- enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69 };
-
- TQTranslatorPrivate() :
- unmapPointer( 0 ), unmapLength( 0 ),
- messageArray( 0 ), offsetArray( 0 ), contextArray( 0 )
-#ifndef TQT_NO_TRANSLATION_BUILDER
- , messages( 0 )
-#endif
- { }
- // TQTranslator must finalize this before deallocating it
-
- // for mmap'ed files, this is what needs to be unmapped.
- char * unmapPointer;
- unsigned int unmapLength;
-
- // for squeezed but non-file data, this is what needs to be deleted
- TQByteArray * messageArray;
- TQByteArray * offsetArray;
- TQByteArray * contextArray;
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
- TQMap<TQTranslatorMessage, void *> * messages;
-#endif
-#ifdef TQ_WS_WIN
- int oldPermissionLookup;
-#endif
-};
-
-
-/*!
- \class TQTranslator
-
- \brief The TQTranslator class provides internationalization support for text
- output.
-
- \ingroup i18n
- \ingroup environment
- \mainclass
-
- An object of this class contains a set of TQTranslatorMessage
- objects, each of which specifies a translation from a source
- language to a target language. TQTranslator provides functions to
- look up translations, add new ones, remove them, load and save
- them, etc.
-
- The most common use of TQTranslator is to: load a translator file
- created with \link linguist-manual.book TQt Linguist\endlink,
- install it using TQApplication::installTranslator(), and use it via
- TQObject::tr(). For example:
-
- \code
- int main( int argc, char ** argv )
- {
- TQApplication app( argc, argv );
-
- TQTranslator translator( 0 );
- translator.load( "french.qm", "." );
- app.installTranslator( &translator );
-
- MyWidget m;
- app.setMainWidget( &m );
- m.show();
-
- return app.exec();
- }
- \endcode
- Note that the translator must be created \e before the
- application's main window.
-
- Most applications will never need to do anything else with this
- class. The other functions provided by this class are useful for
- applications that work on translator files.
-
- We call a translation a "messsage". For this reason, translation
- files are sometimes referred to as "message files".
-
- It is possible to lookup a translation using findMessage() (as
- tr() and TQApplication::translate() do) and contains(), to insert a
- new translation messsage using insert(), and to remove one using
- remove().
-
- Translation tools often need more information than the bare source
- text and translation, for example, context information to help
- the translator. But end-user programs that are using translations
- usually only need lookup. To cater for these different needs,
- TQTranslator can use stripped translator files that use the minimum
- of memory and which support little more functionality than
- findMessage().
-
- Thus, load() may not load enough information to make anything more
- than findMessage() work. save() has an argument indicating
- whether to save just this minimum of information or to save
- everything.
-
- "Everything" means that for each translation item the following
- information is kept:
-
- \list
- \i The \e {translated text} - the return value from tr().
- \i The input key:
- \list
- \i The \e {source text} - usually the argument to tr().
- \i The \e context - usually the class name for the tr() caller.
- \i The \e comment - a comment that helps disambiguate different uses
- of the same text in the same context.
- \endlist
- \endlist
-
- The minimum for each item is just the information necessary for
- findMessage() to return the right text. This may include the
- source, context and comment, but usually it is just a hash value
- and the translated text.
-
- For example, the "Cancel" in a dialog might have "Anuluj" when the
- program runs in Polish (in this case the source text would be
- "Cancel"). The context would (normally) be the dialog's class
- name; there would normally be no comment, and the translated text
- would be "Anuluj".
-
- But it's not always so simple. The Spanish version of a printer
- dialog with settings for two-sided printing and binding would
- probably require both "Activado" and "Activada" as translations
- for "Enabled". In this case the source text would be "Enabled" in
- both cases, and the context would be the dialog's class name, but
- the two items would have disambiguating comments such as
- "two-sided printing" for one and "binding" for the other. The
- comment enables the translator to choose the appropriate gender
- for the Spanish version, and enables TQt to distinguish between
- translations.
-
- Note that when TQTranslator loads a stripped file, most functions
- do not work. The functions that do work with stripped files are
- explicitly documented as such.
-
- \sa TQTranslatorMessage TQApplication::installTranslator()
- TQApplication::removeTranslator() TQObject::tr() TQApplication::translate()
-*/
-
-/*!
- \enum TQTranslator::SaveMode
-
- This enum type defines how TQTranslator writes translation
- files. There are two modes:
-
- \value Everything files are saved with all available information
- \value Stripped files are saved with just enough information for
- end-user applications
-
- Note that when TQTranslator loads a stripped file, most functions do
- not work. The functions that do work with stripped files are
- explicitly documented as such.
-*/
-
-#if defined(TQ_WS_WIN)
-extern int qt_ntfs_permission_lookup;
-#endif
-
-/*!
- Constructs an empty message file object that is not connected to
- any file. The object is called \a name with parent \a parent.
-*/
-
-TQTranslator::TQTranslator( TQObject * parent, const char * name )
- : TQObject( parent, name )
-{
- d = new TQTranslatorPrivate;
-#if defined(TQ_WS_WIN)
- d->oldPermissionLookup = qt_ntfs_permission_lookup;
-#endif
-}
-
-
-/*!
- Destroys the object and frees any allocated resources.
-*/
-
-TQTranslator::~TQTranslator()
-{
- if ( tqApp )
- tqApp->removeTranslator( this );
- clear();
- delete d;
-}
-
-
-extern bool qt_detectRTLLanguage();
-
-/*!
- Loads \a filename, which may be an absolute file name or relative
- to \a directory. The previous contents of this translator object
- is discarded. Returns TRUE if the file is loaded successfully;
- otherwise returns FALSE.
-
- If the full file name does not exist, other file names are tried
- in the following order:
-
- \list 1
- \i File name with \a suffix appended (".qm" if the \a suffix is
- TQString::null).
- \i File name with text after a character in \a search_delimiters
- stripped ("_." is the default for \a search_delimiters if it is
- TQString::null).
- \i File name stripped and \a suffix appended.
- \i File name stripped further, etc.
- \endlist
-
- For example, an application running in the fr_CA locale
- (French-speaking Canada) might call load("foo.fr_ca",
- "/opt/foolib"). load() would then try to open the first existing
- readable file from this list:
-
- \list 1
- \i /opt/foolib/foo.fr_ca
- \i /opt/foolib/foo.fr_ca.qm
- \i /opt/foolib/foo.fr
- \i /opt/foolib/foo.fr.qm
- \i /opt/foolib/foo
- \i /opt/foolib/foo.qm
- \endlist
-
- \sa save()
-*/
-
-bool TQTranslator::load( const TQString & filename, const TQString & directory,
- const TQString & search_delimiters,
- const TQString & suffix )
-{
- clear();
-
- TQString prefix;
-
- if ( filename[0] == '/'
-#ifdef TQ_WS_WIN
- || (filename[0] && filename[1] == ':') || filename[0] == '\\'
-#endif
- )
- prefix = TQString::tqfromLatin1( "" );
- else
- prefix = directory;
-
- if ( prefix.length() ) {
- if ( prefix[int(prefix.length()-1)] != '/' )
- prefix += TQChar( '/' );
- }
-
- TQString fname = filename;
- TQString realname;
- TQString delims;
- delims = search_delimiters.isNull() ?
- TQString::tqfromLatin1( "_." ) : search_delimiters;
-
-#if defined(TQ_WS_WIN)
- qt_ntfs_permission_lookup--;
-#endif
- for ( ;; ) {
- TQFileInfo fi;
-
- realname = prefix + fname;
- fi.setFile( realname );
- if ( fi.isReadable() )
- break;
-
- realname += suffix.isNull() ? TQString::tqfromLatin1( ".qm" ) : suffix;
- fi.setFile( realname );
- if ( fi.isReadable() )
- break;
-
- int rightmost = 0;
- for ( int i = 0; i < (int)delims.length(); i++ ) {
- int k = fname.findRev( delims[i] );
- if ( k > rightmost )
- rightmost = k;
- }
-
- // no truncations? fail
- if ( rightmost == 0 ) {
-#if defined(TQ_WS_WIN)
- if (d->oldPermissionLookup != qt_ntfs_permission_lookup)
- qt_ntfs_permission_lookup++;
-#endif
- return FALSE;
- }
-
- fname.truncate( rightmost );
- }
-#if defined(TQ_WS_WIN)
- if (d->oldPermissionLookup != qt_ntfs_permission_lookup)
- qt_ntfs_permission_lookup++;
-#endif
-
- // realname is now the fully qualified name of a readable file.
-
-#if defined(TQT_USE_MMAP)
-
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-#ifndef MAP_FAILED
-#define MAP_FAILED -1
-#endif
-
- int f;
-
- f = qt_open( TQFile::encodeName(realname), O_RDONLY, 0666 );
- if ( f < 0 ) {
- // qDebug( "can't open %s: %s", realname.ascii(), strerror( errno ) );
- return FALSE;
- }
-
- struct stat st;
- if ( fstat( f, &st ) ) {
- // qDebug( "can't stat %s: %s", realname.ascii(), strerror( errno ) );
- return FALSE;
- }
- char * tmp;
- tmp = (char*)mmap( 0, st.st_size, // any address, whole file
- PROT_READ, // read-only memory
- MAP_FILE | MAP_PRIVATE, // swap-backed map from file
- f, 0 ); // from offset 0 of f
- if ( !tmp || tmp == (char*)MAP_FAILED ) {
- // qDebug( "can't mmap %s: %s", filename.ascii(), strerror( errno ) );
- return FALSE;
- }
-
- ::close( f );
-
- d->unmapPointer = tmp;
- d->unmapLength = st.st_size;
-#else
- TQFile f( realname );
- if ( !f.exists() )
- return FALSE;
- d->unmapLength = f.size();
- d->unmapPointer = new char[d->unmapLength];
- bool ok = FALSE;
- if ( f.open(IO_ReadOnly) ) {
- ok = d->unmapLength ==
- (uint)f.readBlock( d->unmapPointer, d->unmapLength );
- f.close();
- }
- if ( !ok ) {
- delete [] d->unmapPointer;
- d->unmapPointer = 0;
- return FALSE;
- }
-#endif
-
- return do_load( (const uchar *) d->unmapPointer, d->unmapLength );
-}
-
-/*!
- \overload
- \fn bool TQTranslator::load( const uchar *data, int len )
-
- Loads the .qm file data \a data of length \a len into the
- translator. Returns TRUE if the data is loaded successfully;
- otherwise returns FALSE.
-
- The data is not copied. The caller must be able to guarantee that \a data
- will not be deleted or modified.
-*/
-
-bool TQTranslator::do_load( const uchar *data, int len )
-{
- if ( len < MagicLength || memcmp( data, magic, MagicLength ) != 0 ) {
- clear();
- return FALSE;
- }
-
- TQByteArray array;
- array.setRawData( (const char *) data, len );
- TQDataStream s( array, IO_ReadOnly );
- bool ok = TRUE;
-
- s.tqdevice()->at( MagicLength );
-
- TQ_UINT8 tag = 0;
- TQ_UINT32 blockLen = 0;
- s >> tag >> blockLen;
- while ( tag && blockLen ) {
- if ( (TQ_UINT32) s.tqdevice()->at() + blockLen > (TQ_UINT32) len ) {
- ok = FALSE;
- break;
- }
-
- if ( tag == TQTranslatorPrivate::Contexts && !d->contextArray ) {
- d->contextArray = new TQByteArray;
- d->contextArray->setRawData( array.data() + s.tqdevice()->at(),
- blockLen );
- } else if ( tag == TQTranslatorPrivate::Hashes && !d->offsetArray ) {
- d->offsetArray = new TQByteArray;
- d->offsetArray->setRawData( array.data() + s.tqdevice()->at(),
- blockLen );
- } else if ( tag == TQTranslatorPrivate::Messages && !d->messageArray ) {
- d->messageArray = new TQByteArray;
- d->messageArray->setRawData( array.data() + s.tqdevice()->at(),
- blockLen );
- }
-
- if ( !s.tqdevice()->at(s.tqdevice()->at() + blockLen) ) {
- ok = FALSE;
- break;
- }
- tag = 0;
- blockLen = 0;
- if ( !s.atEnd() )
- s >> tag >> blockLen;
- }
- array.resetRawData( (const char *) data, len );
-
- if ( tqApp && tqApp->translators && tqApp->translators->contains(this) )
- tqApp->setReverseLayout( qt_detectRTLLanguage() );
- return ok;
-}
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
-
-/*!
- Saves this message file to \a filename, overwriting the previous
- contents of \a filename. If \a mode is \c Everything (the
- default), all the information is preserved. If \a mode is \c
- Stripped, any information that is not necessary for findMessage()
- is stripped away.
-
- \sa load()
-*/
-
-bool TQTranslator::save( const TQString & filename, SaveMode mode )
-{
- TQFile f( filename );
- if ( f.open( IO_WriteOnly ) ) {
- squeeze( mode );
-
- TQDataStream s( &f );
- s.writeRawBytes( (const char *)magic, MagicLength );
- TQ_UINT8 tag;
-
- if ( d->offsetArray != 0 ) {
- tag = (TQ_UINT8) TQTranslatorPrivate::Hashes;
- TQ_UINT32 oas = (TQ_UINT32) d->offsetArray->size();
- s << tag << oas;
- s.writeRawBytes( d->offsetArray->data(), oas );
- }
- if ( d->messageArray != 0 ) {
- tag = (TQ_UINT8) TQTranslatorPrivate::Messages;
- TQ_UINT32 mas = (TQ_UINT32) d->messageArray->size();
- s << tag << mas;
- s.writeRawBytes( d->messageArray->data(), mas );
- }
- if ( d->contextArray != 0 ) {
- tag = (TQ_UINT8) TQTranslatorPrivate::Contexts;
- TQ_UINT32 cas = (TQ_UINT32) d->contextArray->size();
- s << tag << cas;
- s.writeRawBytes( d->contextArray->data(), cas );
- }
- return TRUE;
- }
- return FALSE;
-}
-
-#endif
-
-/*!
- Empties this translator of all contents.
-
- This function works with stripped translator files.
-*/
-
-void TQTranslator::clear()
-{
- if ( d->unmapPointer && d->unmapLength ) {
-#if defined(TQT_USE_MMAP)
- munmap( d->unmapPointer, d->unmapLength );
-#else
- delete [] d->unmapPointer;
-#endif
- d->unmapPointer = 0;
- d->unmapLength = 0;
- }
-
- if ( d->messageArray ) {
- d->messageArray->resetRawData( d->messageArray->data(),
- d->messageArray->size() );
- delete d->messageArray;
- d->messageArray = 0;
- }
- if ( d->offsetArray ) {
- d->offsetArray->resetRawData( d->offsetArray->data(),
- d->offsetArray->size() );
- delete d->offsetArray;
- d->offsetArray = 0;
- }
- if ( d->contextArray ) {
- d->contextArray->resetRawData( d->contextArray->data(),
- d->contextArray->size() );
- delete d->contextArray;
- d->contextArray = 0;
- }
-#ifndef TQT_NO_TRANSLATION_BUILDER
- delete d->messages;
- d->messages = 0;
-#endif
-
- if ( tqApp ) {
- tqApp->setReverseLayout( qt_detectRTLLanguage() );
-
- TQWidgetList *list = TQApplication::tqtopLevelWidgets();
- TQWidgetListIt it( *list );
- TQWidget *w;
- while ( ( w=it.current() ) != 0 ) {
- ++it;
- if (!w->isDesktop())
- tqApp->postEvent( w, new TQEvent( TQEvent::LanguageChange ) );
- }
- delete list;
- }
-}
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
-
-/*!
- Converts this message file to the compact format used to store
- message files on disk.
-
- You should never need to call this directly; save() and other
- functions call it as necessary. \a mode is for internal use.
-
- \sa save() unsqueeze()
-*/
-
-void TQTranslator::squeeze( SaveMode mode )
-{
- if ( !d->messages ) {
- if ( mode == Stripped )
- unsqueeze();
- else
- return;
- }
-
- TQMap<TQTranslatorMessage, void *> * messages = d->messages;
-
- d->messages = 0;
- clear();
-
- d->messageArray = new TQByteArray;
- d->offsetArray = new TQByteArray;
-
- TQMap<TQTranslatorPrivate::Offset, void *> offsets;
-
- TQDataStream ms( *d->messageArray, IO_WriteOnly );
- TQMap<TQTranslatorMessage, void *>::Iterator it = messages->begin(), next;
- int cpPrev = 0, cpNext = 0;
- for ( it = messages->begin(); it != messages->end(); ++it ) {
- cpPrev = cpNext;
- next = it;
- ++next;
- if ( next == messages->end() )
- cpNext = 0;
- else
- cpNext = (int) it.key().commonPrefix( next.key() );
- offsets.replace( TQTranslatorPrivate::Offset(it.key(),
- ms.tqdevice()->at()), (void*)0 );
- it.key().write( ms, mode == Stripped,
- (TQTranslatorMessage::Prefix) TQMAX(cpPrev, cpNext + 1) );
- }
-
- d->offsetArray->resize( 0 );
- TQMap<TQTranslatorPrivate::Offset, void *>::Iterator offset;
- offset = offsets.begin();
- TQDataStream ds( *d->offsetArray, IO_WriteOnly );
- while ( offset != offsets.end() ) {
- TQTranslatorPrivate::Offset k = offset.key();
- ++offset;
- ds << (TQ_UINT32)k.h << (TQ_UINT32)k.o;
- }
-
- if ( mode == Stripped ) {
- TQAsciiDict<int> contextSet( 1511 );
- int baudelaire;
-
- for ( it = messages->begin(); it != messages->end(); ++it )
- contextSet.replace( it.key().context(), &baudelaire );
-
- TQ_UINT16 hTableSize;
- if ( contextSet.count() < 200 )
- hTableSize = ( contextSet.count() < 60 ) ? 151 : 503;
- else if ( contextSet.count() < 2500 )
- hTableSize = ( contextSet.count() < 750 ) ? 1511 : 5003;
- else
- hTableSize = 15013;
-
- TQIntDict<char> hDict( hTableSize );
- TQAsciiDictIterator<int> c = contextSet;
- while ( c.current() != 0 ) {
- hDict.insert( (long) (elfHash(c.currentKey()) % hTableSize),
- c.currentKey() );
- ++c;
- }
-
- /*
- The contexts found in this translator are stored in a hash
- table to provide fast lookup. The context array has the
- following format:
-
- TQ_UINT16 hTableSize;
- TQ_UINT16 hTable[hTableSize];
- TQ_UINT8 contextPool[...];
-
- The context pool stores the contexts as Pascal strings:
-
- TQ_UINT8 len;
- TQ_UINT8 data[len];
-
- Let's consider the look-up of context "FunnyDialog". A
- hash value between 0 and hTableSize - 1 is computed, say h.
- If hTable[h] is 0, "FunnyDialog" is not covered by this
- translator. Else, we check in the contextPool at offset
- 2 * hTable[h] to see if "FunnyDialog" is one of the
- contexts stored there, until we find it or we meet the
- empty string.
- */
- d->contextArray = new TQByteArray;
- d->contextArray->resize( 2 + (hTableSize << 1) );
- TQDataStream t( *d->contextArray, IO_WriteOnly );
- TQ_UINT16 *hTable = new TQ_UINT16[hTableSize];
- memset( hTable, 0, hTableSize * sizeof(TQ_UINT16) );
-
- t << hTableSize;
- t.tqdevice()->at( 2 + (hTableSize << 1) );
- t << (TQ_UINT16) 0; // the entry at offset 0 cannot be used
- uint upto = 2;
-
- for ( int i = 0; i < hTableSize; i++ ) {
- const char *con = hDict.find( i );
- if ( con == 0 ) {
- hTable[i] = 0;
- } else {
- hTable[i] = (TQ_UINT16) ( upto >> 1 );
- do {
- uint len = (uint) tqstrlen( con );
- len = TQMIN( len, 255 );
- t << (TQ_UINT8) len;
- t.writeRawBytes( con, len );
- upto += 1 + len;
- hDict.remove( i );
- } while ( (con = hDict.find(i)) != 0 );
- do {
- t << (TQ_UINT8) 0; // empty string (at least one)
- upto++;
- } while ( (upto & 0x1) != 0 ); // offsets have to be even
- }
- }
- t.tqdevice()->at( 2 );
- for ( int j = 0; j < hTableSize; j++ )
- t << hTable[j];
- delete [] hTable;
-
- if ( upto > 131072 ) {
- qWarning( "TQTranslator::squeeze: Too many contexts" );
- delete d->contextArray;
- d->contextArray = 0;
- }
- }
- delete messages;
-}
-
-
-/*!
- Converts this message file into an easily modifiable data
- structure, less compact than the format used in the files.
-
- You should never need to call this function; it is called by
- insert() and friends as necessary.
-
- \sa squeeze()
-*/
-
-void TQTranslator::unsqueeze()
-{
- if ( d->messages )
- return;
-
- d->messages = new TQMap<TQTranslatorMessage, void *>;
- if ( !d->messageArray )
- return;
-
- TQDataStream s( *d->messageArray, IO_ReadOnly );
- for ( ;; ) {
- TQTranslatorMessage m( s );
- if ( m.hash() == 0 )
- break;
- d->messages->insert( m, (void *) 0 );
- }
-}
-
-
-/*!
- Returns TRUE if this message file contains a message with the key
- (\a context, \a sourceText, \a comment); otherwise returns FALSE.
-
- This function works with stripped translator files.
-
- (This is is a one-liner that calls findMessage().)
-*/
-
-bool TQTranslator::contains( const char* context, const char* sourceText,
- const char* comment ) const
-{
- return !findMessage( context, sourceText, comment ).translation().isNull();
-}
-
-
-/*!
- Inserts \a message into this message file.
-
- This function does \e not work with stripped translator files. It
- may appear to, but that is not dependable.
-
- \sa remove()
-*/
-
-void TQTranslator::insert( const TQTranslatorMessage& message )
-{
- unsqueeze();
- d->messages->remove( message ); // safer
- d->messages->insert( message, (void *) 0 );
-}
-
-
-/*!
- \fn void TQTranslator::insert( const char *, const char *, const TQString & )
- \overload
- \obsolete
-*/
-
-/*!
- Removes \a message from this translator.
-
- This function works with stripped translator files.
-
- \sa insert()
-*/
-
-void TQTranslator::remove( const TQTranslatorMessage& message )
-{
- unsqueeze();
- d->messages->remove( message );
-}
-
-
-/*!
- \fn void TQTranslator::remove( const char *, const char * )
- \overload
- \obsolete
-
- Removes the translation associated to the key (\a context, \a sourceText,
- "") from this translator.
-*/
-#endif
-
-/*!
- \fn TQString TQTranslator::find( const char*, const char*, const char* ) const
- \obsolete
-
- Please use findMessage() instead.
-
- Returns the translation for the key (\a context, \a sourceText,
- \a comment) or TQString::null if there is none in this translator.
-*/
-
-/*! Returns the TQTranslatorMessage for the key
- (\a context, \a sourceText, \a comment). If none is found,
- also tries (\a context, \a sourceText, "").
-*/
-
-TQTranslatorMessage TQTranslator::findMessage( const char* context,
- const char* sourceText,
- const char* comment ) const
-{
- if ( context == 0 )
- context = "";
- if ( sourceText == 0 )
- sourceText = "";
- if ( comment == 0 )
- comment = "";
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
- if ( d->messages ) {
- TQMap<TQTranslatorMessage, void *>::ConstIterator it;
-
- it = d->messages->find( TQTranslatorMessage(context, sourceText,
- comment) );
- if ( it != d->messages->end() )
- return it.key();
-
- if ( comment[0] ) {
- it = d->messages->find( TQTranslatorMessage(context, sourceText,
- "") );
- if ( it != d->messages->end() )
- return it.key();
- }
- return TQTranslatorMessage();
- }
-#endif
-
- if ( !d->offsetArray )
- return TQTranslatorMessage();
-
- /*
- Check if the context belongs to this TQTranslator. If many translators are
- installed, this step is necessary.
- */
- if ( d->contextArray ) {
- TQ_UINT16 hTableSize = 0;
- TQDataStream t( *d->contextArray, IO_ReadOnly );
- t >> hTableSize;
- uint g = elfHash( context ) % hTableSize;
- t.tqdevice()->at( 2 + (g << 1) );
- TQ_UINT16 off;
- t >> off;
- if ( off == 0 )
- return TQTranslatorMessage();
- t.tqdevice()->at( 2 + (hTableSize << 1) + (off << 1) );
-
- TQ_UINT8 len;
- char con[256];
- for ( ;; ) {
- t >> len;
- if ( len == 0 )
- return TQTranslatorMessage();
- t.readRawBytes( con, len );
- con[len] = '\0';
- if ( qstrcmp(con, context) == 0 )
- break;
- }
- }
-
- size_t numItems = d->offsetArray->size() / ( 2 * sizeof(TQ_UINT32) );
- if ( !numItems )
- return TQTranslatorMessage();
-
- if ( systemWordSize == 0 )
- qSysInfo( &systemWordSize, &systemBigEndian );
-
- for ( ;; ) {
- TQ_UINT32 h = elfHash( TQCString(sourceText) + comment );
-
- char *r = (char *) bsearch( &h, d->offsetArray->data(), numItems,
- 2 * sizeof(TQ_UINT32),
- systemBigEndian ? cmp_uint32_big
- : cmp_uint32_little );
- if ( r != 0 ) {
- // go back on equal key
- while ( r != d->offsetArray->data() &&
- cmp_uint32_big(r - 8, r) == 0 )
- r -= 8;
-
- TQDataStream s( *d->offsetArray, IO_ReadOnly );
- s.tqdevice()->at( r - d->offsetArray->data() );
-
- TQ_UINT32 rh, ro;
- s >> rh >> ro;
-
- TQDataStream ms( *d->messageArray, IO_ReadOnly );
- while ( rh == h ) {
- ms.tqdevice()->at( ro );
- TQTranslatorMessage m( ms );
- if ( match(m.context(), context)
- && match(m.sourceText(), sourceText)
- && match(m.comment(), comment) )
- return m;
- if ( s.atEnd() )
- break;
- s >> rh >> ro;
- }
- }
- if ( !comment[0] )
- break;
- comment = "";
- }
- return TQTranslatorMessage();
-}
-
-/*!
- Returns TRUE if this translator is empty, otherwise returns FALSE.
- This function works with stripped and unstripped translation files.
-*/
-bool TQTranslator::isEmpty() const
-{
- return !( d->unmapPointer || d->unmapLength || d->messageArray ||
- d->offsetArray || d->contextArray
-#ifndef TQT_NO_TRANSLATION_BUILDER
- || (d->messages && d->messages->count())
-#endif
- );
-}
-
-
-#ifndef TQT_NO_TRANSLATION_BUILDER
-
-/*!
- Returns a list of the messages in the translator. This function is
- rather slow. Because it is seldom called, it's optimized for
- simplicity and small size, rather than speed.
-
- If you want to iterate over the list, you should iterate over a
- copy, e.g.
- \code
- TQValueList<TQTranslatorMessage> list = myTranslator.messages();
- TQValueList<TQTranslatorMessage>::Iterator it = list.begin();
- while ( it != list.end() ) {
- process_message( *it );
- ++it;
- }
- \endcode
-*/
-
-TQValueList<TQTranslatorMessage> TQTranslator::messages() const
-{
- if ( d->messages )
- return d->messages->keys();
-
- ((TQTranslator *) this)->unsqueeze();
- TQValueList<TQTranslatorMessage> result = d->messages->keys();
- delete d->messages;
- d->messages = 0;
- return result;
-}
-
-#endif
-
-/*!
- \class TQTranslatorMessage
-
- \brief The TQTranslatorMessage class contains a translator message and its
- properties.
-
- \ingroup i18n
- \ingroup environment
-
- This class is of no interest to most applications. It is useful
- for translation tools such as \link linguist-manual.book TQt
- Linguist\endlink. It is provided simply to make the API complete
- and regular.
-
- For a TQTranslator object, a lookup key is a triple (\e context, \e
- {source text}, \e comment) that uniquely identifies a message. An
- extended key is a quadruple (\e hash, \e context, \e {source
- text}, \e comment), where \e hash is computed from the source text
- and the comment. Unless you plan to read and write messages
- yourself, you need not worry about the hash value.
-
- TQTranslatorMessage stores this triple or quadruple and the relevant
- translation if there is any.
-
- \sa TQTranslator
-*/
-
-/*!
- Constructs a translator message with the extended key (0, 0, 0, 0)
- and TQString::null as translation.
-*/
-
-TQTranslatorMessage::TQTranslatorMessage()
- : h( 0 ), cx( 0 ), st( 0 ), cm( 0 )
-{
-}
-
-
-/*!
- Constructs an translator message with the extended key (\e h, \a
- context, \a sourceText, \a comment), where \e h is computed from
- \a sourceText and \a comment, and possibly with a \a translation.
-*/
-
-TQTranslatorMessage::TQTranslatorMessage( const char * context,
- const char * sourceText,
- const char * comment,
- const TQString& translation )
- : cx( context ), st( sourceText ), cm( comment ), tn( translation )
-{
- // 0 means we don't know, "" means empty
- if ( cx == (const char*)0 )
- cx = "";
- if ( st == (const char*)0 )
- st = "";
- if ( cm == (const char*)0 )
- cm = "";
- h = elfHash( st + cm );
-}
-
-
-/*!
- Constructs a translator message read from the \a stream. The
- resulting message may have any combination of content.
-
- \sa TQTranslator::save()
-*/
-
-TQTranslatorMessage::TQTranslatorMessage( TQDataStream & stream )
- : cx( 0 ), st( 0 ), cm( 0 )
-{
- TQString str16;
- char tag;
- TQ_UINT8 obs1;
-
- for ( ;; ) {
- tag = 0;
- if ( !stream.atEnd() )
- stream.readRawBytes( &tag, 1 );
- switch( (Tag)tag ) {
- case Tag_End:
- if ( h == 0 )
- h = elfHash( st + cm );
- return;
- case Tag_SourceText16: // obsolete
- stream >> str16;
- st = str16.latin1();
- break;
- case Tag_Translation:
- stream >> tn;
- break;
- case Tag_Context16: // obsolete
- stream >> str16;
- cx = str16.latin1();
- break;
- case Tag_Hash:
- stream >> h;
- break;
- case Tag_SourceText:
- stream >> st;
- break;
- case Tag_Context:
- stream >> cx;
- if ( cx == "" ) // for compatibility
- cx = 0;
- break;
- case Tag_Comment:
- stream >> cm;
- break;
- case Tag_Obsolete1: // obsolete
- stream >> obs1;
- break;
- default:
- h = 0;
- st = 0;
- cx = 0;
- cm = 0;
- tn = TQString::null;
- return;
- }
- }
-}
-
-
-/*!
- Constructs a copy of translator message \a m.
-*/
-
-TQTranslatorMessage::TQTranslatorMessage( const TQTranslatorMessage & m )
- : cx( m.cx ), st( m.st ), cm( m.cm ), tn( m.tn )
-{
- h = m.h;
-}
-
-
-/*!
- Assigns message \a m to this translator message and returns a
- reference to this translator message.
-*/
-
-TQTranslatorMessage & TQTranslatorMessage::operator=(
- const TQTranslatorMessage & m )
-{
- h = m.h;
- cx = m.cx;
- st = m.st;
- cm = m.cm;
- tn = m.tn;
- return *this;
-}
-
-
-/*!
- \fn uint TQTranslatorMessage::hash() const
-
- Returns the hash value used internally to represent the lookup
- key. This value is zero only if this translator message was
- constructed from a stream containing invalid data.
-
- The hashing function is unspecified, but it will remain unchanged
- in future versions of TQt.
-*/
-
-/*!
- \fn const char *TQTranslatorMessage::context() const
-
- Returns the context for this message (e.g. "MyDialog").
-
- \warning This may return 0 if the TQTranslator object is stripped
- (compressed).
-*/
-
-/*!
- \fn const char *TQTranslatorMessage::sourceText() const
-
- Returns the source text of this message (e.g. "&Save").
-
- \warning This may return 0 if the TQTranslator object is stripped
- (compressed).
-*/
-
-/*!
- \fn const char *TQTranslatorMessage::comment() const
-
- Returns the comment for this message (e.g. "File|Save").
-
- \warning This may return 0 if the TQTranslator object is stripped
- (compressed).
-*/
-
-/*!
- \fn void TQTranslatorMessage::setTranslation( const TQString & translation )
-
- Sets the translation of the source text to \a translation.
-
- \sa translation()
-*/
-
-/*!
- \fn TQString TQTranslatorMessage::translation() const
-
- Returns the translation of the source text (e.g., "&Sauvegarder").
-
- \sa setTranslation()
-*/
-
-/*!
- \enum TQTranslatorMessage::Prefix
-
- Let (\e h, \e c, \e s, \e m) be the extended key. The possible
- prefixes are
-
- \value NoPrefix no prefix
- \value Hash only (\e h)
- \value HashContext only (\e h, \e c)
- \value HashContextSourceText only (\e h, \e c, \e s)
- \value HashContextSourceTextComment the whole extended key, (\e
- h, \e c, \e s, \e m)
-
- \sa write() commonPrefix()
-*/
-
-/*!
- Writes this translator message to the \a stream. If \a strip is
- FALSE (the default), all the information in the message is
- written. If \a strip is TRUE, only the part of the extended key
- specified by \a prefix is written with the translation (\c
- HashContextSourceTextComment by default).
-
- \sa commonPrefix()
-*/
-
-void TQTranslatorMessage::write( TQDataStream & stream, bool strip,
- Prefix prefix ) const
-{
- char tag;
-
- tag = (char)Tag_Translation;
- stream.writeRawBytes( &tag, 1 );
- stream << tn;
-
- bool mustWriteHash = TRUE;
- if ( !strip )
- prefix = HashContextSourceTextComment;
-
- switch ( prefix ) {
- case HashContextSourceTextComment:
- tag = (char)Tag_Comment;
- stream.writeRawBytes( &tag, 1 );
- stream << cm;
- // fall through
- case HashContextSourceText:
- tag = (char)Tag_SourceText;
- stream.writeRawBytes( &tag, 1 );
- stream << st;
- // fall through
- case HashContext:
- tag = (char)Tag_Context;
- stream.writeRawBytes( &tag, 1 );
- stream << cx;
- // fall through
- default:
- if ( mustWriteHash ) {
- tag = (char)Tag_Hash;
- stream.writeRawBytes( &tag, 1 );
- stream << h;
- }
- }
-
- tag = (char)Tag_End;
- stream.writeRawBytes( &tag, 1 );
-}
-
-
-/*!
- Returns the widest lookup prefix that is common to this translator
- message and to message \a m.
-
- For example, if the extended key is for this message is (71,
- "PrintDialog", "Yes", "Print?") and that for \a m is (71,
- "PrintDialog", "No", "Print?"), this function returns \c
- HashContext.
-
- \sa write()
-*/
-
-TQTranslatorMessage::Prefix TQTranslatorMessage::commonPrefix(
- const TQTranslatorMessage& m ) const
-{
- if ( h != m.h )
- return NoPrefix;
- if ( cx != m.cx )
- return Hash;
- if ( st != m.st )
- return HashContext;
- if ( cm != m.cm )
- return HashContextSourceText;
- return HashContextSourceTextComment;
-}
-
-
-/*!
- Returns TRUE if the extended key of this object is equal to that of
- \a m; otherwise returns FALSE.
-*/
-
-bool TQTranslatorMessage::operator==( const TQTranslatorMessage& m ) const
-{
- return h == m.h && cx == m.cx && st == m.st && cm == m.cm;
-}
-
-
-/*!
- \fn bool TQTranslatorMessage::operator!=( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is different from
- that of \a m; otherwise returns FALSE.
-*/
-
-
-/*!
- Returns TRUE if the extended key of this object is
- lexicographically before than that of \a m; otherwise returns
- FALSE.
-*/
-
-bool TQTranslatorMessage::operator<( const TQTranslatorMessage& m ) const
-{
- return h != m.h ? h < m.h
- : ( cx != m.cx ? cx < m.cx
- : (st != m.st ? st < m.st : cm < m.cm) );
-}
-
-
-/*!
- \fn bool TQTranslatorMessage::operator<=( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is
- lexicographically before that of \a m or if they are equal;
- otherwise returns FALSE.
-*/
-
-/*!
- \fn bool TQTranslatorMessage::operator>( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is
- lexicographically after that of \a m; otherwise returns FALSE.
-*/
-
-/*!
- \fn bool TQTranslatorMessage::operator>=( const TQTranslatorMessage& m ) const
-
- Returns TRUE if the extended key of this object is
- lexicographically after that of \a m or if they are equal;
- otherwise returns FALSE.
-*/
-
-#endif // USE_QT4
-
-#endif // TQT_NO_TRANSLATION