summaryrefslogtreecommitdiff
path: root/development/translation/shared
Side-by-side diff
Diffstat (limited to 'development/translation/shared') (more/less context) (ignore whitespace changes)
-rw-r--r--development/translation/shared/metatranslator.cpp34
-rw-r--r--development/translation/shared/metatranslator.h16
-rw-r--r--development/translation/shared/opie.h2
-rw-r--r--development/translation/shared/proparser.cpp111
-rw-r--r--development/translation/shared/proparser.h8
5 files changed, 144 insertions, 27 deletions
diff --git a/development/translation/shared/metatranslator.cpp b/development/translation/shared/metatranslator.cpp
index a01e1eb..51270c5 100644
--- a/development/translation/shared/metatranslator.cpp
+++ b/development/translation/shared/metatranslator.cpp
@@ -1,586 +1,596 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of Qt Linguist.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "metatranslator.h"
#include <qapplication.h>
#include <qcstring.h>
#include <qfile.h>
#include <qmessagebox.h>
#include <qtextcodec.h>
#include <qtextstream.h>
#include <qxml.h>
static bool encodingIsUtf8( const QXmlAttributes& atts )
{
for ( int i = 0; i < atts.length(); i++ ) {
// utf8="true" is a pre-3.0 syntax
if ( atts.qName(i) == QString("utf8") ) {
return ( atts.value(i) == QString("true") );
} else if ( atts.qName(i) == QString("encoding") ) {
return ( atts.value(i) == QString("UTF-8") );
}
}
return FALSE;
}
class TsHandler : public QXmlDefaultHandler
{
public:
TsHandler( MetaTranslator *translator )
: tor( translator ), type( MetaTranslatorMessage::Finished ),
inMessage( FALSE ), ferrorCount( 0 ), contextIsUtf8( FALSE ),
messageIsUtf8( FALSE ) { }
virtual bool startElement( const QString& namespaceURI,
const QString& localName, const QString& qName,
const QXmlAttributes& atts );
virtual bool endElement( const QString& namespaceURI,
const QString& localName, const QString& qName );
virtual bool characters( const QString& ch );
virtual bool fatalError( const QXmlParseException& exception );
private:
MetaTranslator *tor;
MetaTranslatorMessage::Type type;
bool inMessage;
QString context;
QString source;
QString comment;
QString translation;
QString accum;
int ferrorCount;
bool contextIsUtf8;
bool messageIsUtf8;
};
bool TsHandler::startElement( const QString& /* namespaceURI */,
const QString& /* localName */,
const QString& qName,
const QXmlAttributes& atts )
{
if ( qName == QString("byte") ) {
for ( int i = 0; i < atts.length(); i++ ) {
if ( atts.qName(i) == QString("value") ) {
QString value = atts.value( i );
int base = 10;
if ( value.startsWith("x") ) {
base = 16;
value = value.mid( 1 );
}
int n = value.toUInt( 0, base );
if ( n != 0 )
accum += QChar( n );
}
}
} else {
if ( qName == QString("context") ) {
context.truncate( 0 );
source.truncate( 0 );
comment.truncate( 0 );
translation.truncate( 0 );
contextIsUtf8 = encodingIsUtf8( atts );
} else if ( qName == QString("message") ) {
inMessage = TRUE;
type = MetaTranslatorMessage::Finished;
source.truncate( 0 );
comment.truncate( 0 );
translation.truncate( 0 );
messageIsUtf8 = encodingIsUtf8( atts );
} else if ( qName == QString("translation") ) {
for ( int i = 0; i < atts.length(); i++ ) {
if ( atts.qName(i) == QString("type") ) {
if ( atts.value(i) == QString("unfinished") )
type = MetaTranslatorMessage::Unfinished;
else if ( atts.value(i) == QString("obsolete") )
type = MetaTranslatorMessage::Obsolete;
else
type = MetaTranslatorMessage::Finished;
}
}
}
accum.truncate( 0 );
}
return TRUE;
}
bool TsHandler::endElement( const QString& /* namespaceURI */,
const QString& /* localName */,
const QString& qName )
{
if ( qName == QString("codec") || qName == QString("defaultcodec") ) {
// "codec" is a pre-3.0 syntax
tor->setCodec( accum );
} else if ( qName == QString("name") ) {
context = accum;
} else if ( qName == QString("source") ) {
source = accum;
} else if ( qName == QString("comment") ) {
if ( inMessage ) {
comment = accum;
} else {
if ( contextIsUtf8 )
- tor->insert( MetaTranslatorMessage(context.utf8(), "",
+ tor->insert( MetaTranslatorMessage(context.utf8(),
+ ContextComment,
accum.utf8(), QString::null, TRUE,
MetaTranslatorMessage::Unfinished) );
else
- tor->insert( MetaTranslatorMessage(context.ascii(), "",
+ tor->insert( MetaTranslatorMessage(context.ascii(),
+ ContextComment,
accum.ascii(), QString::null, FALSE,
MetaTranslatorMessage::Unfinished) );
}
} else if ( qName == QString("translation") ) {
translation = accum;
} else if ( qName == QString("message") ) {
if ( messageIsUtf8 )
tor->insert( MetaTranslatorMessage(context.utf8(), source.utf8(),
comment.utf8(), translation,
TRUE, type) );
else
tor->insert( MetaTranslatorMessage(context.ascii(), source.ascii(),
comment.ascii(), translation,
FALSE, type) );
inMessage = FALSE;
}
return TRUE;
}
bool TsHandler::characters( const QString& ch )
{
QString t = ch;
t.replace( "\r", "" );
accum += t;
return TRUE;
}
bool TsHandler::fatalError( const QXmlParseException& exception )
{
if ( ferrorCount++ == 0 ) {
QString msg;
msg.sprintf( "Parse error at line %d, column %d (%s).",
exception.lineNumber(), exception.columnNumber(),
exception.message().latin1() );
if ( qApp == 0 )
fprintf( stderr, "XML error: %s\n", msg.latin1() );
else
QMessageBox::information( qApp->mainWidget(),
QObject::tr("Qt Linguist"), msg );
}
return FALSE;
}
static QString numericEntity( int ch )
{
return QString( ch <= 0x20 ? "<byte value=\"x%1\"/>" : "&#x%1;" )
.arg( ch, 0, 16 );
}
static QString protect( const QCString& str )
{
QString result;
int len = (int) str.length();
for ( int k = 0; k < len; k++ ) {
switch( str[k] ) {
case '\"':
result += QString( "&quot;" );
break;
case '&':
result += QString( "&amp;" );
break;
case '>':
result += QString( "&gt;" );
break;
case '<':
result += QString( "&lt;" );
break;
case '\'':
result += QString( "&apos;" );
break;
default:
if ( (uchar) str[k] < 0x20 && str[k] != '\n' )
result += numericEntity( (uchar) str[k] );
else
result += str[k];
}
}
return result;
}
static QString evilBytes( const QCString& str, bool utf8 )
{
if ( utf8 ) {
return protect( str );
} else {
QString result;
QCString t = protect( str ).latin1();
int len = (int) t.length();
for ( int k = 0; k < len; k++ ) {
if ( (uchar) t[k] >= 0x7f )
result += numericEntity( (uchar) t[k] );
else
result += QChar( t[k] );
}
return result;
}
}
MetaTranslatorMessage::MetaTranslatorMessage()
: utfeight( FALSE ), ty( Unfinished )
{
}
MetaTranslatorMessage::MetaTranslatorMessage( const char *context,
const char *sourceText,
const char *comment,
const QString& translation,
bool utf8, Type type )
: QTranslatorMessage( context, sourceText, comment, translation ),
utfeight( FALSE ), ty( type )
{
/*
Don't use UTF-8 if it makes no difference. UTF-8 should be
reserved for the real problematic case: non-ASCII (possibly
non-Latin-1) characters in .ui files.
*/
if ( utf8 ) {
if ( sourceText != 0 ) {
int i = 0;
while ( sourceText[i] != '\0' ) {
if ( (uchar) sourceText[i] >= 0x80 ) {
utfeight = TRUE;
break;
}
i++;
}
}
if ( !utfeight && comment != 0 ) {
int i = 0;
while ( comment[i] != '\0' ) {
if ( (uchar) comment[i] >= 0x80 ) {
utfeight = TRUE;
break;
}
i++;
}
}
}
}
MetaTranslatorMessage::MetaTranslatorMessage( const MetaTranslatorMessage& m )
: QTranslatorMessage( m ), utfeight( m.utfeight ), ty( m.ty )
{
}
MetaTranslatorMessage& MetaTranslatorMessage::operator=(
const MetaTranslatorMessage& m )
{
QTranslatorMessage::operator=( m );
utfeight = m.utfeight;
ty = m.ty;
return *this;
}
bool MetaTranslatorMessage::operator==( const MetaTranslatorMessage& m ) const
{
return qstrcmp( context(), m.context() ) == 0 &&
qstrcmp( sourceText(), m.sourceText() ) == 0 &&
qstrcmp( comment(), m.comment() ) == 0;
}
bool MetaTranslatorMessage::operator<( const MetaTranslatorMessage& m ) const
{
int delta = qstrcmp( context(), m.context() );
if ( delta == 0 )
delta = qstrcmp( sourceText(), m.sourceText() );
if ( delta == 0 )
delta = qstrcmp( comment(), m.comment() );
return delta < 0;
}
MetaTranslator::MetaTranslator()
- : codecName( "ISO-8859-1" ), codec( 0 )
{
+ clear();
}
MetaTranslator::MetaTranslator( const MetaTranslator& tor )
: mm( tor.mm ), codecName( tor.codecName ), codec( tor.codec )
{
-
}
MetaTranslator& MetaTranslator::operator=( const MetaTranslator& tor )
{
mm = tor.mm;
codecName = tor.codecName;
codec = tor.codec;
return *this;
}
-bool MetaTranslator::load( const QString& filename )
+void MetaTranslator::clear()
{
mm.clear();
+ codecName = "ISO-8859-1";
+ codec = 0;
+}
+bool MetaTranslator::load( const QString& filename )
+{
QFile f( filename );
if ( !f.open(IO_ReadOnly) )
return FALSE;
QTextStream t( &f );
QXmlInputSource in( t );
QXmlSimpleReader reader;
- // don't click on these!
reader.setFeature( "http://xml.org/sax/features/namespaces", FALSE );
reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", TRUE );
reader.setFeature( "http://trolltech.com/xml/features/report-whitespace"
"-only-CharData", FALSE );
QXmlDefaultHandler *hand = new TsHandler( this );
reader.setContentHandler( hand );
reader.setErrorHandler( hand );
bool ok = reader.parse( in );
reader.setContentHandler( 0 );
reader.setErrorHandler( 0 );
delete hand;
f.close();
- if ( !ok )
- mm.clear();
return ok;
}
bool MetaTranslator::save( const QString& filename ) const
{
QFile f( filename );
if ( !f.open(IO_WriteOnly) )
return FALSE;
QTextStream t( &f );
t.setCodec( QTextCodec::codecForName("ISO-8859-1") );
t << "<!DOCTYPE TS><TS>\n";
if ( codecName != "ISO-8859-1" )
t << "<defaultcodec>" << codecName << "</defaultcodec>\n";
TMM::ConstIterator m = mm.begin();
while ( m != mm.end() ) {
TMMInv inv;
TMMInv::Iterator i;
bool contextIsUtf8 = m.key().utf8();
QCString context = m.key().context();
QCString comment = "";
do {
- if ( QCString(m.key().sourceText()).isEmpty() ) {
+ if ( QCString(m.key().sourceText()) == ContextComment ) {
if ( m.key().type() != MetaTranslatorMessage::Obsolete ) {
contextIsUtf8 = m.key().utf8();
comment = QCString( m.key().comment() );
}
} else {
inv.insert( *m, m.key() );
}
} while ( ++m != mm.end() && QCString(m.key().context()) == context );
t << "<context";
if ( contextIsUtf8 )
t << " encoding=\"UTF-8\"";
t << ">\n";
t << " <name>" << evilBytes( context, contextIsUtf8 )
<< "</name>\n";
if ( !comment.isEmpty() )
t << " <comment>" << evilBytes( comment, contextIsUtf8 )
<< "</comment>\n";
for ( i = inv.begin(); i != inv.end(); ++i ) {
// no need for such noise
if ( (*i).type() == MetaTranslatorMessage::Obsolete &&
(*i).translation().isEmpty() )
continue;
t << " <message";
if ( (*i).utf8() )
t << " encoding=\"UTF-8\"";
t << ">\n"
<< " <source>" << evilBytes( (*i).sourceText(),
(*i).utf8() )
<< "</source>\n";
if ( !QCString((*i).comment()).isEmpty() )
t << " <comment>" << evilBytes( (*i).comment(),
(*i).utf8() )
<< "</comment>\n";
t << " <translation";
if ( (*i).type() == MetaTranslatorMessage::Unfinished )
t << " type=\"unfinished\"";
else if ( (*i).type() == MetaTranslatorMessage::Obsolete )
t << " type=\"obsolete\"";
t << ">" << protect( (*i).translation().utf8() )
<< "</translation>\n";
t << " </message>\n";
}
t << "</context>\n";
}
t << "</TS>\n";
f.close();
return TRUE;
}
-bool MetaTranslator::release( const QString& filename, bool verbose ) const
+bool MetaTranslator::release( const QString& filename, bool verbose,
+ QTranslator::SaveMode mode ) const
{
QTranslator tor( 0 );
int finished = 0;
int unfinished = 0;
int untranslated = 0;
TMM::ConstIterator m;
for ( m = mm.begin(); m != mm.end(); ++m ) {
if ( m.key().type() != MetaTranslatorMessage::Obsolete ) {
if ( m.key().translation().isEmpty() ) {
untranslated++;
} else {
if ( m.key().type() == MetaTranslatorMessage::Unfinished )
unfinished++;
else
finished++;
QCString context = m.key().context();
QCString sourceText = m.key().sourceText();
QCString comment = m.key().comment();
QString translation = m.key().translation();
/*
Drop the comment in (context, sourceText, comment),
unless (context, sourceText, "") already exists, or
unless we already dropped the comment of (context,
sourceText, comment0).
*/
if ( comment.isEmpty()
|| contains(context, sourceText, "")
|| !tor.findMessage(context, sourceText, "").translation()
.isNull() ) {
tor.insert( m.key() );
} else {
tor.insert( QTranslatorMessage(context, sourceText, "",
translation) );
}
}
}
}
- bool saved = tor.save( filename, QTranslator::Stripped );
+ bool saved = tor.save( filename, mode );
if ( saved && verbose )
fprintf( stderr,
" %d finished, %d unfinished and %d untranslated messages\n",
finished, unfinished, untranslated );
return saved;
}
bool MetaTranslator::contains( const char *context, const char *sourceText,
const char *comment ) const
{
return mm.find( MetaTranslatorMessage(context, sourceText, comment) ) !=
mm.end();
}
void MetaTranslator::insert( const MetaTranslatorMessage& m )
{
int pos = mm.count();
TMM::Iterator n = mm.find( m );
if ( n != mm.end() )
pos = *n;
mm.replace( m, pos );
}
void MetaTranslator::stripObsoleteMessages()
{
TMM newmm;
TMM::Iterator m = mm.begin();
while ( m != mm.end() ) {
if ( m.key().type() != MetaTranslatorMessage::Obsolete )
newmm.insert( m.key(), *m );
++m;
}
mm = newmm;
}
void MetaTranslator::stripEmptyContexts()
{
TMM newmm;
TMM::Iterator m = mm.begin();
while ( m != mm.end() ) {
- if ( QCString(m.key().sourceText()).isEmpty() ) {
+ if ( QCString(m.key().sourceText()) == ContextComment ) {
TMM::Iterator n = m;
++n;
// the context comment is followed by other messages
if ( n != newmm.end() &&
qstrcmp(m.key().context(), n.key().context()) == 0 )
newmm.insert( m.key(), *m );
} else {
newmm.insert( m.key(), *m );
}
++m;
}
mm = newmm;
}
void MetaTranslator::setCodec( const char *name )
{
const int latin1 = 4;
codecName = name;
codec = QTextCodec::codecForName( name );
if ( codec == 0 || codec->mibEnum() == latin1 )
codec = 0;
}
QString MetaTranslator::toUnicode( const char *str, bool utf8 ) const
{
if ( utf8 )
return QString::fromUtf8( str );
else if ( codec == 0 )
return QString( str );
else
return codec->toUnicode( str );
}
QValueList<MetaTranslatorMessage> MetaTranslator::messages() const
{
int n = mm.count();
TMM::ConstIterator *t = new TMM::ConstIterator[n + 1];
TMM::ConstIterator m;
for ( m = mm.begin(); m != mm.end(); ++m )
t[*m] = m;
QValueList<MetaTranslatorMessage> val;
for ( int i = 0; i < n; i++ )
val.append( t[i].key() );
delete[] t;
return val;
}
QValueList<MetaTranslatorMessage> MetaTranslator::translatedMessages() const
{
QValueList<MetaTranslatorMessage> val;
TMM::ConstIterator m;
for ( m = mm.begin(); m != mm.end(); ++m ) {
if ( m.key().type() == MetaTranslatorMessage::Finished )
val.append( m.key() );
}
return val;
}
diff --git a/development/translation/shared/metatranslator.h b/development/translation/shared/metatranslator.h
index d35b202..a13f462 100644
--- a/development/translation/shared/metatranslator.h
+++ b/development/translation/shared/metatranslator.h
@@ -1,99 +1,113 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of Qt Linguist.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef METATRANSLATOR_H
#define METATRANSLATOR_H
#include <qmap.h>
#include <qstring.h>
#include <qtranslator.h>
#include <qvaluelist.h>
class QTextCodec;
class MetaTranslatorMessage : public QTranslatorMessage
{
public:
enum Type { Unfinished, Finished, Obsolete };
MetaTranslatorMessage();
MetaTranslatorMessage( const char *context, const char *sourceText,
const char *comment,
const QString& translation = QString::null,
bool utf8 = FALSE, Type type = Unfinished );
MetaTranslatorMessage( const MetaTranslatorMessage& m );
MetaTranslatorMessage& operator=( const MetaTranslatorMessage& m );
void setType( Type nt ) { ty = nt; }
Type type() const { return ty; }
bool utf8() const { return utfeight; }
bool operator==( const MetaTranslatorMessage& m ) const;
bool operator!=( const MetaTranslatorMessage& m ) const
{ return !operator==( m ); }
bool operator<( const MetaTranslatorMessage& m ) const;
bool operator<=( const MetaTranslatorMessage& m )
{ return !operator>( m ); }
bool operator>( const MetaTranslatorMessage& m ) const
{ return this->operator<( m ); }
bool operator>=( const MetaTranslatorMessage& m ) const
{ return !operator<( m ); }
private:
bool utfeight;
Type ty;
};
class MetaTranslator
{
public:
MetaTranslator();
MetaTranslator( const MetaTranslator& tor );
MetaTranslator& operator=( const MetaTranslator& tor );
+ void clear();
bool load( const QString& filename );
bool save( const QString& filename ) const;
- bool release( const QString& filename, bool verbose = FALSE ) const;
+ bool release( const QString& filename, bool verbose = FALSE,
+ QTranslator::SaveMode mode = QTranslator::Stripped ) const;
bool contains( const char *context, const char *sourceText,
const char *comment ) const;
void insert( const MetaTranslatorMessage& m );
void stripObsoleteMessages();
void stripEmptyContexts();
void setCodec( const char *name );
QString toUnicode( const char *str, bool utf8 ) const;
QValueList<MetaTranslatorMessage> messages() const;
QValueList<MetaTranslatorMessage> translatedMessages() const;
private:
typedef QMap<MetaTranslatorMessage, int> TMM;
typedef QMap<int, MetaTranslatorMessage> TMMInv;
TMM mm;
QCString codecName;
QTextCodec *codec;
};
+/*
+ This is a quick hack. The proper way to handle this would be
+ to extend MetaTranslator's interface.
+*/
+#define ContextComment "QT_LINGUIST_INTERNAL_CONTEXT_COMMENT"
+
#endif
diff --git a/development/translation/shared/opie.h b/development/translation/shared/opie.h
index 4646bb0..28b2a61 100644
--- a/development/translation/shared/opie.h
+++ b/development/translation/shared/opie.h
@@ -1,21 +1,21 @@
#ifndef OPIE_H
#define OPIE_H
#include <qstring.h>
#include <qstringlist.h>
class OPIE {
public:
static OPIE* self();
/** get the list of languages */
QStringList languageList(const QString& opiedir = QString::null)const;
- QString opieDir(const QString& opieDir)const;
+ QString opieDir(const QString& opieDir = QString::null)const;
private:
OPIE();
~OPIE();
static OPIE* m_self;
};
#endif
diff --git a/development/translation/shared/proparser.cpp b/development/translation/shared/proparser.cpp
index 21d2f86..f616c5a 100644
--- a/development/translation/shared/proparser.cpp
+++ b/development/translation/shared/proparser.cpp
@@ -1,87 +1,174 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of Qt Linguist.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "proparser.h"
+#include <qfile.h>
#include <qregexp.h>
#include <qstringlist.h>
+#include <qtextstream.h>
+
+#ifdef Q_OS_UNIX
+#include <unistd.h>
+#endif
+
+#ifdef Q_OS_WIN32
+#define QT_POPEN _popen
+#else
+#define QT_POPEN popen
+#endif
+
+QString loadFile( const QString &fileName )
+{
+ QFile file( fileName );
+ if ( !file.open(IO_ReadOnly) ) {
+ fprintf( stderr, "error: Cannot load '%s': %s\n",
+ file.name().latin1(),
+ file.errorString().latin1() );
+ return QString();
+ }
+
+ QTextStream in( &file );
+ return in.read();
+}
-QMap<QString, QString> proFileTagMap( const QString& text )
+QMap<QString, QString> proFileTagMap( const QString& text, const QString& opieDir )
{
QString t = text;
/*
+ Process include() commands.
+ */
+ QRegExp callToInclude("include\\s*\\(\\s*([^()\\s]+)\\s*\\)");
+ int i = 0;
+ while ( (i = callToInclude.search(t, i)) != -1 ) {
+ QString after = loadFile( callToInclude.cap(1) );
+ t.replace( i, callToInclude.matchedLength(), after );
+ i += after.length();
+ }
+
+ /*
Strip comments, merge lines ending with backslash, add
spaces around '=' and '+=', replace '\n' with ';', and
simplify white spaces.
*/
- t.replace( QRegExp(QString("#[^\n]$")), QString(" ") );
- t.replace( QRegExp(QString("\\\\\\s*\n")), QString(" ") );
+ t.replace( QRegExp(QString("#[^\n]*\n")), QString(" ") );
+ t.replace( QRegExp(QString("\\\\[^\n\\S]*\n")), QString(" ") );
t.replace( "=", QString(" = ") );
t.replace( "+ =", QString(" += ") );
t.replace( "\n", QString(";") );
t = t.simplifyWhiteSpace();
+ /*
+ Populate tagMap with 'key = value' entries.
+ */
QMap<QString, QString> tagMap;
-
QStringList lines = QStringList::split( QChar(';'), t );
QStringList::Iterator line;
for ( line = lines.begin(); line != lines.end(); ++line ) {
QStringList toks = QStringList::split( QChar(' '), *line );
- if ( toks.count() >= 3 &&
+ if ( toks.count() >= 3 &&
(toks[1] == QString("=") || toks[1] == QString("+=")) ) {
QString tag = toks.first();
int k = tag.findRev( QChar(':') ); // as in 'unix:'
if ( k != -1 )
tag = tag.mid( k + 1 );
toks.remove( toks.begin() );
QString action = toks.first();
toks.remove( toks.begin() );
if ( tagMap.contains(tag) ) {
if ( action == QString("=") )
tagMap.replace( tag, toks.join(QChar(' ')) );
else
tagMap[tag] += QChar( ' ' ) + toks.join( QChar(' ') );
} else {
tagMap[tag] = toks.join( QChar(' ') );
}
}
}
- QRegExp var( "\\$\\$[a-zA-Z0-9_]+" );
+ /*
+ Expand $$variables within the 'value' part of a 'key = value'
+ pair.
+ */
+ QRegExp var( "\\$\\$[({]?([a-zA-Z0-9_]+)[)}]?" );
QMap<QString, QString>::Iterator it;
for ( it = tagMap.begin(); it != tagMap.end(); ++it ) {
int i = 0;
-
- while ( (i = var.search(it.data(), i)) != -1 ) {
+ while ( (i = var.search((*it), i)) != -1 ) {
int len = var.matchedLength();
- QString invocation = (*it).mid( i + 2, len - 2 );
+ QString invocation = var.cap(1);
QString after;
- if ( tagMap.contains(invocation) )
- after = tagMap[invocation];
- (*it).replace( i, len, after );
+
+ if ( invocation == "system" ) {
+ // skip system(); it will be handled in the next pass
+ ++i;
+ } else if ( invocation == "OPIEDIR") {
+ (*it).replace( i, len, opieDir );
+ }else {
+ if ( tagMap.contains(invocation) )
+ after = tagMap[invocation];
+ (*it).replace( i, len, after );
+ }
+ }
+ }
+
+ /*
+ Execute system() calls.
+ */
+ QRegExp callToSystem( "\\$\\$system\\s*\\(([^()]*)\\)" );
+ for ( it = tagMap.begin(); it != tagMap.end(); ++it ) {
+ int i = 0;
+ while ( (i = callToSystem.search((*it), i)) != -1 ) {
+ /*
+ This code is stolen from qmake's project.cpp file.
+ Ideally we would use the same parser, so we wouldn't
+ have this code duplication.
+ */
+ QString after;
+ char buff[256];
+ FILE *proc = QT_POPEN( callToSystem.cap(1).latin1(), "r" );
+ while ( proc && !feof(proc) ) {
+ int read_in = fread( buff, 1, 255, proc );
+ if ( !read_in )
+ break;
+ for ( int i = 0; i < read_in; i++ ) {
+ if ( buff[i] == '\n' || buff[i] == '\t' )
+ buff[i] = ' ';
+ }
+ buff[read_in] = '\0';
+ after += buff;
+ }
+ (*it).replace( i, callToSystem.matchedLength(), after );
i += after.length();
}
}
+
return tagMap;
}
diff --git a/development/translation/shared/proparser.h b/development/translation/shared/proparser.h
index 6a61d90..e5678d6 100644
--- a/development/translation/shared/proparser.h
+++ b/development/translation/shared/proparser.h
@@ -1,29 +1,35 @@
/**********************************************************************
** Copyright (C) 2000 Trolltech AS. All rights reserved.
**
** This file is part of Qt Linguist.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
+** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
+** licenses may use this file in accordance with the Qt Commercial License
+** Agreement provided with the Software.
+**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
+** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
+** information about Qt Commercial License Agreements.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef PROPARSER_H
#define PROPARSER_H
#include <qmap.h>
#include <qstring.h>
-QMap<QString, QString> proFileTagMap( const QString& text );
+QMap<QString, QString> proFileTagMap( const QString& text, const QString& = QString::null );
#endif