2014-05-30 08:53:19 +00:00
/*
This file is part of Telegram Desktop ,
2014-12-01 10:47:38 +00:00
the official desktop version of Telegram messaging app , see https : //telegram.org
2014-05-30 08:53:19 +00:00
Telegram Desktop is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
It is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2014-12-01 10:47:38 +00:00
Copyright ( c ) 2014 John Preston , https : //desktop.telegram.org
2014-05-30 08:53:19 +00:00
*/
# include "genlang.h"
# include <QtCore/QtPlugin>
2014-07-09 06:10:55 +00:00
# ifdef Q_OS_WIN
2014-05-30 08:53:19 +00:00
Q_IMPORT_PLUGIN ( QWindowsIntegrationPlugin )
2014-06-14 19:32:11 +00:00
# endif
2014-05-30 08:53:19 +00:00
2014-07-09 06:10:55 +00:00
# ifdef Q_OS_MAC
Q_IMPORT_PLUGIN ( QCocoaIntegrationPlugin )
Q_IMPORT_PLUGIN ( QDDSPlugin )
Q_IMPORT_PLUGIN ( QICNSPlugin )
Q_IMPORT_PLUGIN ( QICOPlugin )
Q_IMPORT_PLUGIN ( QJp2Plugin )
Q_IMPORT_PLUGIN ( QMngPlugin )
Q_IMPORT_PLUGIN ( QTgaPlugin )
Q_IMPORT_PLUGIN ( QTiffPlugin )
Q_IMPORT_PLUGIN ( QWbmpPlugin )
Q_IMPORT_PLUGIN ( QWebpPlugin )
# endif
2014-05-30 08:53:19 +00:00
typedef unsigned int uint32 ;
QString layoutDirection ;
2014-12-18 18:40:49 +00:00
typedef QMap < QByteArray , QString > LangKeys ;
2014-05-30 08:53:19 +00:00
LangKeys keys ;
2014-12-18 18:40:49 +00:00
typedef QMap < QByteArray , ushort > LangTags ;
LangTags tags ;
typedef QMap < QByteArray , QVector < QByteArray > > LangKeysTags ;
LangKeysTags keysTags ;
typedef QVector < QByteArray > KeysOrder ;
2014-05-30 08:53:19 +00:00
KeysOrder keysOrder ;
2014-12-18 18:40:49 +00:00
KeysOrder tagsOrder ;
typedef QMap < QByteArray , QMap < QByteArray , QVector < QString > > > LangKeysCounted ;
LangKeysCounted keysCounted ;
static const QChar TextCommand ( 0x0010 ) ;
static const QChar TextCommandLangTag ( 0x0020 ) ;
2014-05-30 08:53:19 +00:00
bool skipWhitespaces ( const char * & from , const char * end ) {
while ( from < end & & ( * from = = ' ' | | * from = = ' \n ' | | * from = = ' \t ' | | * from = = ' \r ' ) ) {
+ + from ;
}
return ( from < end ) ;
}
bool skipComment ( const char * & from , const char * end ) {
if ( from > = end ) return false ;
if ( * from = = ' / ' ) {
if ( from + 1 > = end ) return true ;
if ( * ( from + 1 ) = = ' * ' ) {
from + = 2 ;
while ( from + 1 < end & & ( * from ! = ' * ' | | * ( from + 1 ) ! = ' / ' ) ) {
+ + from ;
}
from + = 2 ;
return ( from < end ) ;
} else if ( * ( from + 1 ) = = ' / ' ) {
from + = 2 ;
while ( from < end & & * from ! = ' \n ' & & * from ! = ' \r ' ) {
+ + from ;
}
2014-06-18 18:37:44 +00:00
if ( from < end ) + + from ;
return true ;
2014-05-30 08:53:19 +00:00
} else {
return true ;
}
}
return true ;
}
bool skipJunk ( const char * & from , const char * end ) {
const char * start ;
do {
start = from ;
if ( ! skipWhitespaces ( from , end ) ) return false ;
2014-06-14 19:32:11 +00:00
if ( ! skipComment ( from , end ) ) throw Exception ( " Unexpected end of comment! " ) ;
2014-05-30 08:53:19 +00:00
} while ( start ! = from ) ;
return true ;
}
2014-12-18 18:40:49 +00:00
inline bool _lngEquals ( const QByteArray & key , int from , int len , const char * value , int size ) {
if ( size ! = len | | from + len > key . size ( ) ) return false ;
for ( const char * v = key . constData ( ) + from , * e = v + len ; v ! = e ; + + v , + + value ) {
if ( * v ! = * value ) return false ;
}
return true ;
}
# define LNG_EQUALS_PART(key, from, len, value) _lngEquals(key, from, len, value, sizeof(value) - 1)
# define LNG_EQUALS_TAIL(key, from, value) _lngEquals(key, from, key.size() - from, value, sizeof(value) - 1)
# define LNG_EQUALS(key, value) _lngEquals(key, 0, key.size(), value, sizeof(value) - 1)
static const int MaxCountedValues = 6 ;
2014-05-30 08:53:19 +00:00
void readKeyValue ( const char * & from , const char * end ) {
if ( ! skipJunk ( from , end ) ) return ;
2014-12-18 18:40:49 +00:00
if ( * from ! = ' " ' ) throw Exception ( QString ( " Expected quote before key name! " ) ) ;
const char * nameStart = + + from ;
2014-06-14 19:32:11 +00:00
while ( from < end & & ( ( * from > = ' a ' & & * from < = ' z ' ) | | ( * from > = ' A ' & & * from < = ' Z ' ) | | * from = = ' _ ' | | ( * from > = ' 0 ' & & * from < = ' 9 ' ) ) ) {
2014-05-30 08:53:19 +00:00
+ + from ;
}
2014-12-18 18:40:49 +00:00
if ( from = = nameStart ) throw Exception ( QString ( " Expected key name! " ) ) ;
QByteArray varName = QByteArray ( nameStart , int ( from - nameStart ) ) ;
for ( const char * t = nameStart ; t + 1 < from ; + + t ) {
if ( * t = = ' _ ' ) {
if ( * ( t + 1 ) = = ' _ ' ) throw Exception ( QString ( " Bad key name: %1 " ) . arg ( QLatin1String ( varName ) ) ) ;
+ + t ;
}
}
if ( from = = end | | * from ! = ' " ' ) throw Exception ( QString ( " Expected quote after key name in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
+ + from ;
2014-05-30 08:53:19 +00:00
2014-12-18 18:40:49 +00:00
if ( ! skipJunk ( from , end ) ) throw Exception ( QString ( " Unexpected end of file in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
if ( * from ! = ' = ' ) throw Exception ( QString ( " '=' expected in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
2014-05-30 08:53:19 +00:00
2014-12-18 18:40:49 +00:00
if ( ! skipJunk ( + + from , end ) ) throw Exception ( QString ( " Unexpected end of file in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
if ( * from ! = ' " ' ) throw Exception ( QString ( " Expected string after '=' in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
2014-05-30 08:53:19 +00:00
QByteArray varValue ;
const char * start = + + from ;
2014-12-18 18:40:49 +00:00
QVector < QByteArray > tagsList ;
2014-05-30 08:53:19 +00:00
while ( from < end & & * from ! = ' " ' ) {
2014-12-18 18:40:49 +00:00
if ( * from = = ' \n ' ) {
throw Exception ( QString ( " Unexpected end of string in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
}
2014-05-30 08:53:19 +00:00
if ( * from = = ' \\ ' ) {
2014-12-18 18:40:49 +00:00
if ( from + 1 > = end ) throw Exception ( QString ( " Unexpected end of file in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
if ( * ( from + 1 ) = = ' " ' | | * ( from + 1 ) = = ' \\ ' | | * ( from + 1 ) = = ' { ' ) {
2014-06-14 19:32:11 +00:00
if ( from > start ) varValue . append ( start , int ( from - start ) ) ;
2014-05-30 08:53:19 +00:00
start = + + from ;
2014-12-18 18:40:49 +00:00
} else if ( * ( from + 1 ) = = ' n ' ) {
if ( from > start ) varValue . append ( start , int ( from - start ) ) ;
varValue . append ( ' \n ' ) ;
start = ( + + from ) + 1 ;
}
} else if ( * from = = ' { ' ) {
if ( from > start ) varValue . append ( start , int ( from - start ) ) ;
const char * tagStart = + + from ;
while ( from < end & & ( ( * from > = ' a ' & & * from < = ' z ' ) | | ( * from > = ' A ' & & * from < = ' Z ' ) | | * from = = ' _ ' | | ( * from > = ' 0 ' & & * from < = ' 9 ' ) ) ) {
+ + from ;
}
if ( from = = tagStart ) throw Exception ( QString ( " Expected tag name in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
QByteArray tagName = QByteArray ( tagStart , int ( from - tagStart ) ) ;
if ( from = = end | | ( * from ! = ' } ' & & * from ! = ' : ' ) ) throw Exception ( QString ( " Expected '}' or ':' after tag name in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
LangTags : : const_iterator i = tags . constFind ( tagName ) ;
if ( i = = tags . cend ( ) ) {
i = tags . insert ( tagName , tagsOrder . size ( ) ) ;
tagsOrder . push_back ( tagName ) ;
}
2014-12-18 20:15:58 +00:00
if ( 0x0020 + * i > 0x007F ) throw Exception ( QString ( " Too many different tags in key '%1' " ) . arg ( QLatin1String ( varName ) ) ) ;
2014-12-18 18:40:49 +00:00
QString tagReplacer ( 4 , TextCommand ) ;
tagReplacer [ 1 ] = TextCommandLangTag ;
tagReplacer [ 2 ] = QChar ( 0x0020 + * i ) ;
varValue . append ( tagReplacer . toUtf8 ( ) ) ;
for ( int j = 0 , s = tagsList . size ( ) ; j < s ; + + j ) {
if ( tagsList . at ( j ) = = tagName ) throw Exception ( QString ( " Tag '%1' double used in key '%2'! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
}
tagsList . push_back ( tagName ) ;
if ( * from = = ' : ' ) {
start = + + from ;
QVector < QString > & counted ( keysCounted [ varName ] [ tagName ] ) ;
QByteArray subvarValue ;
bool foundtag = false ;
while ( from < end & & * from ! = ' " ' & & * from ! = ' } ' ) {
if ( * from = = ' | ' ) {
if ( from > start ) subvarValue . append ( start , int ( from - start ) ) ;
counted . push_back ( QString : : fromUtf8 ( subvarValue ) ) ;
subvarValue = QByteArray ( ) ;
foundtag = false ;
start = from + 1 ;
}
if ( * from = = ' \n ' ) {
throw Exception ( QString ( " Unexpected end of string inside counted tag '%1' in '%2' key! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
}
if ( * from = = ' \\ ' ) {
if ( from + 1 > = end ) throw Exception ( QString ( " Unexpected end of file inside counted tag '%1' in '%2' key! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
if ( * ( from + 1 ) = = ' " ' | | * ( from + 1 ) = = ' \\ ' | | * ( from + 1 ) = = ' { ' | | * ( from + 1 ) = = ' # ' ) {
if ( from > start ) subvarValue . append ( start , int ( from - start ) ) ;
start = + + from ;
} else if ( * ( from + 1 ) = = ' n ' ) {
if ( from > start ) subvarValue . append ( start , int ( from - start ) ) ;
subvarValue . append ( ' \n ' ) ;
start = ( + + from ) + 1 ;
}
} else if ( * from = = ' { ' ) {
throw Exception ( QString ( " Unexpected tag inside counted tag '%1' in '%2' key! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
} else if ( * from = = ' # ' ) {
if ( foundtag ) throw Exception ( QString ( " Replacement '#' double used inside counted tag '%1' in '%2' key! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
foundtag = true ;
if ( from > start ) subvarValue . append ( start , int ( from - start ) ) ;
subvarValue . append ( tagReplacer . toUtf8 ( ) ) ;
start = from + 1 ;
}
+ + from ;
}
if ( from > = end ) throw Exception ( QString ( " Unexpected end of file inside counted tag '%1' in '%2' key! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
if ( * from = = ' " ' ) throw Exception ( QString ( " Unexpected end of string inside counted tag '%1' in '%2' key! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
if ( from > start ) subvarValue . append ( start , int ( from - start ) ) ;
counted . push_back ( QString : : fromUtf8 ( subvarValue ) ) ;
if ( counted . size ( ) > MaxCountedValues ) {
throw Exception ( QString ( " Too many values inside counted tag '%1' in '%2' key! " ) . arg ( QLatin1String ( tagName ) ) . arg ( QLatin1String ( varName ) ) ) ;
}
2014-05-30 08:53:19 +00:00
}
2014-12-18 18:40:49 +00:00
start = from + 1 ;
2014-05-30 08:53:19 +00:00
}
+ + from ;
}
2014-12-18 18:40:49 +00:00
if ( from > = end ) throw Exception ( QString ( " Unexpected end of file in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
2014-06-14 19:32:11 +00:00
if ( from > start ) varValue . append ( start , int ( from - start ) ) ;
2014-05-30 08:53:19 +00:00
2014-12-18 18:40:49 +00:00
if ( ! skipJunk ( + + from , end ) ) throw Exception ( QString ( " Unexpected end of file in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
if ( * from ! = ' ; ' ) throw Exception ( QString ( " ';' expected after \" value \" in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
2014-05-30 08:53:19 +00:00
skipJunk ( + + from , end ) ;
if ( varName = = " direction " ) {
2014-12-18 18:40:49 +00:00
throw Exception ( QString ( " Unexpected value for 'direction' in key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
} else if ( ! LNG_EQUALS_PART ( varName , 0 , 4 , " lng_ " ) ) {
throw Exception ( QString ( " Bad key '%1'! " ) . arg ( QLatin1String ( varName ) ) ) ;
2014-05-30 08:53:19 +00:00
} else if ( keys . constFind ( varName ) ! = keys . cend ( ) ) {
2014-12-18 18:40:49 +00:00
throw Exception ( QString ( " Key '%1' doubled! " ) . arg ( QLatin1String ( varName ) ) ) ;
2014-05-30 08:53:19 +00:00
} else {
keys . insert ( varName , QString : : fromUtf8 ( varValue ) ) ;
2014-12-18 18:40:49 +00:00
keysTags . insert ( varName , tagsList ) ;
2014-05-30 08:53:19 +00:00
keysOrder . push_back ( varName ) ;
}
}
2014-12-18 18:40:49 +00:00
QString escapeCpp ( const QByteArray & key , QString value , bool wideChar ) {
2014-05-30 08:53:19 +00:00
if ( value . isEmpty ( ) ) return " QString() " ;
2014-12-18 18:40:49 +00:00
2014-05-30 08:53:19 +00:00
QString res ;
res . reserve ( value . size ( ) * 10 ) ;
bool instr = false ;
for ( const QChar * ch = value . constData ( ) , * e = value . constData ( ) + value . size ( ) ; ch ! = e ; + + ch ) {
2014-12-18 20:15:58 +00:00
if ( ch - > unicode ( ) > 0x007F ) {
2014-05-30 08:53:19 +00:00
if ( instr ) {
res . append ( ' " ' ) ;
instr = false ;
}
res . append ( ' ' ) ;
if ( wideChar ) {
res . append ( ' L ' ) . append ( ' " ' ) . append ( ' \\ ' ) . append ( ' x ' ) . append ( QString ( " %1 " ) . arg ( ch - > unicode ( ) , 4 , 16 , QChar ( ' 0 ' ) ) ) . append ( ' " ' ) ;
} else {
res . append ( ' " ' ) ;
QByteArray utf ( QString ( * ch ) . toUtf8 ( ) ) ;
for ( const unsigned char * uch = ( const unsigned char * ) utf . constData ( ) , * ue = ( const unsigned char * ) utf . constData ( ) + utf . size ( ) ; uch ! = ue ; + + uch ) {
res . append ( ' \\ ' ) . append ( ' x ' ) . append ( QString ( " %1 " ) . arg ( ushort ( * uch ) , 2 , 16 , QChar ( ' 0 ' ) ) ) ;
}
res . append ( ' " ' ) ;
}
} else {
if ( ! instr ) {
res . append ( ' ' ) ;
if ( wideChar ) res . append ( ' L ' ) ;
res . append ( ' " ' ) ;
instr = true ;
}
2014-12-18 18:40:49 +00:00
if ( ch - > unicode ( ) = = ' \\ ' | | ch - > unicode ( ) = = ' \n ' | | ch - > unicode ( ) = = ' \r ' | | ch - > unicode ( ) = = ' " ' ) {
res . append ( ' \\ ' ) ;
if ( ch - > unicode ( ) = = ' \\ ' | | ch - > unicode ( ) = = ' " ' ) {
res . append ( * ch ) ;
} else if ( ch - > unicode ( ) = = ' \n ' ) {
res . append ( ' n ' ) ;
} else if ( ch - > unicode ( ) = = ' \r ' ) {
res . append ( ' r ' ) ;
}
} else if ( ch - > unicode ( ) < 0x0020 ) {
if ( * ch = = TextCommand ) {
2014-12-18 20:15:58 +00:00
if ( ch + 3 > = e | | ( ch + 1 ) - > unicode ( ) ! = TextCommandLangTag | | ( ch + 2 ) - > unicode ( ) > 0x007F | | ( ch + 2 ) - > unicode ( ) < 0x0020 | | * ( ch + 3 ) ! = TextCommand ) {
2014-12-18 18:40:49 +00:00
throw Exception ( QString ( " Bad value for key '%1' " ) . arg ( QLatin1String ( key ) ) ) ;
} else {
res . append ( ' \\ ' ) . append ( ' x ' ) . append ( QString ( " %1 " ) . arg ( ch - > unicode ( ) , 2 , 16 , QChar ( ' 0 ' ) ) ) ;
res . append ( ' \\ ' ) . append ( ' x ' ) . append ( QString ( " %1 " ) . arg ( ( ch + 1 ) - > unicode ( ) , 2 , 16 , QChar ( ' 0 ' ) ) ) ;
res . append ( ' \\ ' ) . append ( ' x ' ) . append ( QString ( " %1 " ) . arg ( ( ch + 2 ) - > unicode ( ) , 2 , 16 , QChar ( ' 0 ' ) ) ) ;
res . append ( ' \\ ' ) . append ( ' x ' ) . append ( QString ( " %1 " ) . arg ( ( ch + 3 ) - > unicode ( ) , 2 , 16 , QChar ( ' 0 ' ) ) ) ;
ch + = 3 ;
}
} else {
throw Exception ( QString ( " Bad value for key '%1' " ) . arg ( QLatin1String ( key ) ) ) ;
}
} else {
res . append ( * ch ) ;
}
2014-05-30 08:53:19 +00:00
}
}
if ( instr ) res . append ( ' " ' ) ;
return ( wideChar ? " qsl( " : " QString::fromUtf8( " ) + res . mid ( wideChar ? 2 : 1 ) + " ) " ;
}
2014-12-18 18:40:49 +00:00
void writeCppKey ( QTextStream & tcpp , const QByteArray & key , const QString & val ) {
2014-05-30 08:53:19 +00:00
QString wide = escapeCpp ( key , val , true ) , utf = escapeCpp ( key , val , false ) ;
if ( wide . indexOf ( " L \" " ) < 0 ) {
tcpp < < " \t \t \t set( " < < key < < " , " < < wide < < " ); \n " ;
} else {
tcpp < < " #ifdef Q_OS_WIN \n " ;
tcpp < < " \t \t \t set( " < < key < < " , " < < wide < < " ); \n " ;
tcpp < < " #else \n " ;
tcpp < < " \t \t \t set( " < < key < < " , " < < utf < < " ); \n " ;
tcpp < < " #endif \n " ;
}
}
bool genLang ( const QString & lang_in , const QString & lang_out ) {
QString lang_cpp = lang_out + " .cpp " , lang_h = lang_out + " .h " ;
QFile f ( lang_in ) ;
if ( ! f . open ( QIODevice : : ReadOnly ) ) {
2014-12-19 21:20:30 +00:00
cout < < " Could not open lang input file ' " < < lang_in . toUtf8 ( ) . constData ( ) < < " '! \n " ;
2014-05-30 08:53:19 +00:00
QCoreApplication : : exit ( 1 ) ;
return false ;
}
2014-12-19 21:20:30 +00:00
QByteArray checkCodec = f . read ( 3 ) ;
if ( checkCodec . size ( ) < 3 ) {
cout < < " Bad lang input file ' " < < lang_in . toUtf8 ( ) . constData ( ) < < " '! \n " ;
QCoreApplication : : exit ( 1 ) ;
return false ;
}
f . seek ( 0 ) ;
QByteArray data ;
int skip = 0 ;
if ( ( checkCodec . at ( 0 ) = = ' \xFF ' & & checkCodec . at ( 1 ) = = ' \xFE ' ) | | ( checkCodec . at ( 0 ) = = ' \xFE ' & & checkCodec . at ( 1 ) = = ' \xFF ' ) | | ( checkCodec . at ( 1 ) = = 0 ) ) {
QTextStream stream ( & f ) ;
stream . setCodec ( " UTF-16 " ) ;
QString string = stream . readAll ( ) ;
if ( stream . status ( ) ! = QTextStream : : Ok ) {
cout < < " Could not read valid UTF-16 file ' " < < lang_in . toUtf8 ( ) . constData ( ) < < " '! \n " ;
QCoreApplication : : exit ( 1 ) ;
return false ;
}
f . close ( ) ;
data = string . toUtf8 ( ) ;
} else if ( checkCodec . at ( 0 ) = = 0 ) {
QByteArray tmp = " \xFE \xFF " + f . readAll ( ) ; // add fake UTF-16 BOM
f . close ( ) ;
QTextStream stream ( & tmp ) ;
stream . setCodec ( " UTF-16 " ) ;
QString string = stream . readAll ( ) ;
if ( stream . status ( ) ! = QTextStream : : Ok ) {
cout < < " Could not read valid UTF-16 file ' " < < lang_in . toUtf8 ( ) . constData ( ) < < " '! \n " ;
QCoreApplication : : exit ( 1 ) ;
return false ;
}
2014-05-30 08:53:19 +00:00
2014-12-19 21:20:30 +00:00
data = string . toUtf8 ( ) ;
} else {
data = f . readAll ( ) ;
if ( checkCodec . at ( 0 ) = = ' \xEF ' & & checkCodec . at ( 1 ) = = ' \xBB ' & & checkCodec . at ( 2 ) = = ' \xBF ' ) {
skip = 3 ; // skip UTF-8 BOM
}
}
2014-05-30 08:53:19 +00:00
2014-12-19 21:20:30 +00:00
const char * text = data . constData ( ) + skip , * end = text + data . size ( ) - skip ;
2014-05-30 08:53:19 +00:00
try {
2014-12-19 21:20:30 +00:00
while ( text < end ) {
2014-05-30 08:53:19 +00:00
readKeyValue ( text , end ) ;
}
QByteArray cppText , hText ;
{
QTextStream tcpp ( & cppText ) , th ( & hText ) ;
tcpp . setCodec ( " ISO 8859-1 " ) ;
th . setCodec ( " ISO 8859-1 " ) ;
th < < " \
/*\n\
Created from \ ' / Resources / lang . txt \ ' by \ ' / MetaLang \ ' project \ n \
\ n \
WARNING ! All changes made in this file will be lost ! \ n \
\ n \
This file is part of Telegram Desktop , \ n \
2014-12-01 10:47:38 +00:00
the official desktop version of Telegram messaging app , see https : / / telegram . org \ n \
2014-05-30 08:53:19 +00:00
\ n \
Telegram Desktop is free software : you can redistribute it and / or modify \ n \
it under the terms of the GNU General Public License as published by \ n \
the Free Software Foundation , either version 3 of the License , or \ n \
( at your option ) any later version . \ n \
\ n \
It is distributed in the hope that it will be useful , \ n \
but WITHOUT ANY WARRANTY ; without even the implied warranty of \ n \
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the \ n \
GNU General Public License for more details . \ n \
\ n \
Full license : https : / / github . com / telegramdesktop / tdesktop / blob / master / LICENSE \ n \
2014-12-01 10:47:38 +00:00
Copyright ( c ) 2014 John Preston , https : / / desktop . telegram . org \ n \
2014-05-30 08:53:19 +00:00
*/ \ n " ;
th < < " #pragma once \n \n " ;
2014-12-18 18:40:49 +00:00
for ( int i = 0 , l = tagsOrder . size ( ) ; i < l ; + + i ) {
th < < " enum lngtag_ " < < tagsOrder [ i ] < < " { lt_ " < < tagsOrder [ i ] < < " = " < < i < < " }; \n " ;
}
th < < " static const ushort lngtags_cnt = " < < tagsOrder . size ( ) < < " ; \n " ;
th < < " static const ushort lngtags_max_counted_values = " < < MaxCountedValues < < " ; \n " ;
th < < " \n " ;
2014-05-30 08:53:19 +00:00
th < < " enum LangKey { \n " ;
for ( int i = 0 , l = keysOrder . size ( ) ; i < l ; + + i ) {
2014-12-18 18:40:49 +00:00
if ( keysTags [ keysOrder [ i ] ] . isEmpty ( ) ) {
th < < " \t " < < keysOrder [ i ] < < ( i ? " " : " = 0 " ) < < " , \n " ;
} else {
th < < " \t " < < keysOrder [ i ] < < " __tagged " < < ( i ? " " : " = 0 " ) < < " , \n " ;
QMap < QByteArray , QVector < QString > > & countedTags ( keysCounted [ keysOrder [ i ] ] ) ;
if ( ! countedTags . isEmpty ( ) ) {
for ( QMap < QByteArray , QVector < QString > > : : const_iterator j = countedTags . cbegin ( ) , e = countedTags . cend ( ) ; j ! = e ; + + j ) {
const QVector < QString > & counted ( * j ) ;
for ( int k = 0 , s = counted . size ( ) ; k < s ; + + k ) {
th < < " \t " < < keysOrder [ i ] < < " __ " + j . key ( ) + QString : : number ( k ) . toUtf8 ( ) < < " , \n " ;
}
}
}
}
2014-05-30 08:53:19 +00:00
}
2014-12-18 18:40:49 +00:00
th < < " \n \t lngkeys_cnt \n " ;
2014-05-30 08:53:19 +00:00
th < < " }; \n \n " ;
2014-12-18 18:40:49 +00:00
th < < " LangString lang(LangKey key); \n \n " ;
2014-12-19 21:20:30 +00:00
th < < " LangString langOriginal(LangKey key); \n \n " ;
2014-12-18 18:40:49 +00:00
for ( int i = 0 , l = keysOrder . size ( ) ; i < l ; + + i ) {
QVector < QByteArray > & tagsList ( keysTags [ keysOrder [ i ] ] ) ;
if ( tagsList . isEmpty ( ) ) continue ;
QMap < QByteArray , QVector < QString > > & countedTags ( keysCounted [ keysOrder [ i ] ] ) ;
th < < " inline LangString " < < keysOrder [ i ] < < " ( " ;
for ( int j = 0 , s = tagsList . size ( ) ; j < s ; + + j ) {
if ( countedTags [ tagsList [ j ] ] . isEmpty ( ) ) {
th < < " lngtag_ " < < tagsList [ j ] < < " , const QString & " < < tagsList [ j ] < < " __val " ;
} else {
th < < " lngtag_ " < < tagsList [ j ] < < " , float64 " < < tagsList [ j ] < < " __val " ;
}
if ( j + 1 < s ) th < < " , " ;
}
th < < " ) { \n " ;
th < < " \t return lang( " < < keysOrder [ i ] < < " __tagged) " ;
for ( int j = 0 , s = tagsList . size ( ) ; j < s ; + + j ) {
if ( countedTags [ tagsList [ j ] ] . isEmpty ( ) ) {
th < < " .tag(lt_ " < < tagsList [ j ] < < " , " < < tagsList [ j ] < < " __val) " ;
} else {
th < < " .tag(lt_ " < < tagsList [ j ] < < " , langCounted( " < < keysOrder [ i ] < < " __ " < < tagsList [ j ] < < " 0, lt_ " < < tagsList [ j ] < < " , " < < tagsList [ j ] < < " __val)) " ;
}
}
th < < " ; \n " ;
th < < " } \n " ;
}
2014-05-30 08:53:19 +00:00
tcpp < < " \
/*\n\
Created from \ ' / Resources / lang . txt \ ' by \ ' / MetaLang \ ' project \ n \
\ n \
WARNING ! All changes made in this file will be lost ! \ n \
\ n \
This file is part of Telegram Desktop , \ n \
2014-12-01 10:47:38 +00:00
the official desktop version of Telegram messaging app , see https : / / telegram . org \ n \
2014-05-30 08:53:19 +00:00
\ n \
Telegram Desktop is free software : you can redistribute it and / or modify \ n \
it under the terms of the GNU General Public License as published by \ n \
the Free Software Foundation , either version 3 of the License , or \ n \
( at your option ) any later version . \ n \
\ n \
It is distributed in the hope that it will be useful , \ n \
but WITHOUT ANY WARRANTY ; without even the implied warranty of \ n \
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the \ n \
GNU General Public License for more details . \ n \
\ n \
Full license : https : / / github . com / telegramdesktop / tdesktop / blob / master / LICENSE \ n \
2014-12-01 10:47:38 +00:00
Copyright ( c ) 2014 John Preston , https : / / desktop . telegram . org \ n \
2014-05-30 08:53:19 +00:00
*/ \ n " ;
tcpp < < " #include \" stdafx.h \" \n #include \" lang.h \" \n \n " ;
tcpp < < " namespace { \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " \t const char *_langKeyNames[lngkeys_cnt] = { \n " ;
2014-05-30 08:53:19 +00:00
for ( int i = 0 , l = keysOrder . size ( ) ; i < l ; + + i ) {
2015-01-05 20:19:05 +00:00
if ( keysTags [ keysOrder [ i ] ] . isEmpty ( ) ) {
tcpp < < " \t \t \" " < < keysOrder [ i ] < < " \" , \n " ;
} else {
tcpp < < " \t \t \" " < < keysOrder [ i ] < < " __tagged \" , \n " ;
QMap < QByteArray , QVector < QString > > & countedTags ( keysCounted [ keysOrder [ i ] ] ) ;
if ( ! countedTags . isEmpty ( ) ) {
for ( QMap < QByteArray , QVector < QString > > : : const_iterator j = countedTags . cbegin ( ) , e = countedTags . cend ( ) ; j ! = e ; + + j ) {
const QVector < QString > & counted ( * j ) ;
for ( int k = 0 , s = counted . size ( ) ; k < s ; + + k ) {
tcpp < < " \t \t \" " < < keysOrder [ i ] < < " __ " + j . key ( ) + QString : : number ( k ) . toUtf8 ( ) < < " \" , \n " ;
}
}
}
}
2014-05-30 08:53:19 +00:00
}
tcpp < < " \t }; \n \n " ;
2014-12-18 18:40:49 +00:00
2014-12-19 21:20:30 +00:00
tcpp < < " \t LangString _langValues[lngkeys_cnt], _langValuesOriginal[lngkeys_cnt]; \n \n " ;
2014-05-30 08:53:19 +00:00
tcpp < < " \t void set(LangKey key, const QString &val) { \n " ;
tcpp < < " \t \t _langValues[key] = val; \n " ;
tcpp < < " \t } \n \n " ;
2014-12-18 18:40:49 +00:00
2014-05-30 08:53:19 +00:00
tcpp < < " \t class LangInit { \n " ;
tcpp < < " \t public: \n " ;
tcpp < < " \t \t LangInit() { \n " ;
for ( int i = 0 , l = keysOrder . size ( ) ; i < l ; + + i ) {
2014-12-18 18:40:49 +00:00
writeCppKey ( tcpp , keysOrder [ i ] + ( keysTags [ keysOrder [ i ] ] . isEmpty ( ) ? " " : " __tagged " ) , keys [ keysOrder [ i ] ] ) ;
QMap < QByteArray , QVector < QString > > & countedTags ( keysCounted [ keysOrder [ i ] ] ) ;
if ( ! countedTags . isEmpty ( ) ) {
for ( QMap < QByteArray , QVector < QString > > : : const_iterator j = countedTags . cbegin ( ) , e = countedTags . cend ( ) ; j ! = e ; + + j ) {
const QVector < QString > & counted ( * j ) ;
for ( int k = 0 , s = counted . size ( ) ; k < s ; + + k ) {
writeCppKey ( tcpp , keysOrder [ i ] + " __ " + j . key ( ) + QString : : number ( k ) . toUtf8 ( ) , counted [ k ] ) ;
}
}
}
2014-05-30 08:53:19 +00:00
}
tcpp < < " \t \t } \n " ;
tcpp < < " \t }; \n \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " \t LangInit _langInit; \n \n " ;
tcpp < < " \t inline bool _lngEquals(const QByteArray &key, int from, int len, const char *value, int size) { \n " ;
tcpp < < " \t \t if (size != len || from + len > key.size()) return false; \n " ;
tcpp < < " \t \t for (const char *v = key.constData() + from, *e = v + len; v != e; ++v, ++value) { \n " ;
tcpp < < " \t \t \t if (*v != *value) return false; \n " ;
tcpp < < " \t \t } \n " ;
tcpp < < " \t \t return true; \n " ;
tcpp < < " \t } \n " ;
2014-05-30 08:53:19 +00:00
tcpp < < " } \n \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " #define LNG_EQUALS_PART(key, from, len, value) _lngEquals(key, from, len, value, sizeof(value) - 1) \n " ;
tcpp < < " #define LNG_EQUALS_TAIL(key, from, value) _lngEquals(key, from, key.size() - from, value, sizeof(value) - 1) \n " ;
tcpp < < " #define LNG_EQUALS(key, value) _lngEquals(key, 0, key.size(), value, sizeof(value) - 1) \n \n " ;
tcpp < < " LangString lang(LangKey key) { \n " ;
tcpp < < " \t return (key < 0 || key > lngkeys_cnt) ? QString() : _langValues[key]; \n " ;
2014-05-30 08:53:19 +00:00
tcpp < < " } \n \n " ;
2014-12-19 21:20:30 +00:00
tcpp < < " LangString langOriginal(LangKey key) { \n " ;
tcpp < < " \t return (key < 0 || key > lngkeys_cnt || _langValuesOriginal[key] == qsl( \" {} \" )) ? QString() : (_langValuesOriginal[key].isEmpty() ? _langValues[key] : _langValuesOriginal[key]); \n " ;
tcpp < < " } \n \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " const char *langKeyName(LangKey key) { \n " ;
tcpp < < " \t return (key < 0 || key > lngkeys_cnt) ? \" \" : _langKeyNames[key]; \n " ;
2014-05-30 08:53:19 +00:00
tcpp < < " } \n \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " ushort LangLoader::tagIndex(const QByteArray &tag) const { \n " ;
tcpp < < " \t if (tag.isEmpty()) return lngtags_cnt; \n \n " ;
if ( ! tags . isEmpty ( ) ) {
QString tab ( " \t " ) ;
tcpp < < " \t const char *ch = tag.constData(), *e = tag.constData() + tag.size(); \n " ;
QByteArray current ;
int depth = current . size ( ) ;
tcpp < < " \t switch (*ch) { \n " ;
for ( LangTags : : const_iterator i = tags . cbegin ( ) , j = i + 1 , e = tags . cend ( ) ; i ! = e ; + + i ) {
QByteArray tag = i . key ( ) ;
while ( depth > 0 & & tag . mid ( 0 , depth ) ! = current ) {
tcpp < < tab . repeated ( depth + 1 ) < < " } \n " ;
current . chop ( 1 ) ;
- - depth ;
tcpp < < tab . repeated ( depth + 1 ) < < " break; \n " ;
}
do {
if ( tag = = current ) break ;
char ich = i . key ( ) . at ( current . size ( ) ) ;
tcpp < < tab . repeated ( current . size ( ) + 1 ) < < " case ' " < < ich < < " ': \n " ;
if ( j = = e | | ich ! = ( ( j . key ( ) . size ( ) > depth ) ? j . key ( ) . at ( depth ) : 0 ) ) {
if ( tag = = current + ich ) {
tcpp < < tab . repeated ( depth + 1 ) < < " \t if (ch + " < < ( depth + 1 ) < < " == e) return lt_ " < < tag < < " ; \n " ;
} else {
tcpp < < tab . repeated ( depth + 1 ) < < " \t if (LNG_EQUALS_TAIL(tag, " < < ( depth + 1 ) < < " , \" " < < i . key ( ) . mid ( depth + 1 ) < < " \" )) return lt_ " < < tag < < " ; \n " ;
}
tcpp < < tab . repeated ( depth + 1 ) < < " break; \n " ;
break ;
}
+ + depth ;
current + = ich ;
if ( tag = = current ) {
tcpp < < tab . repeated ( depth + 1 ) < < " if (ch + " < < depth < < " == e) { \n " ;
tcpp < < tab . repeated ( depth + 1 ) < < " \t return lt_ " < < tag < < " ; \n " ;
tcpp < < tab . repeated ( depth + 1 ) < < " } \n " ;
}
tcpp < < tab . repeated ( depth + 1 ) < < " if (ch + " < < depth < < " < e) switch (*(ch + " < < depth < < " )) { \n " ;
} while ( true ) ;
+ + j ;
}
while ( QByteArray ( ) ! = current ) {
tcpp < < tab . repeated ( depth + 1 ) < < " } \n " ;
current . chop ( 1 ) ;
- - depth ;
tcpp < < tab . repeated ( depth + 1 ) < < " break; \n " ;
}
tcpp < < " \t } \n \n " ;
}
tcpp < < " \t return lngtags_cnt; \n " ;
tcpp < < " } \n \n " ;
tcpp < < " LangKey LangLoader::keyIndex(const QByteArray &key) const { \n " ;
tcpp < < " \t if (key.size() < 5 || !LNG_EQUALS_PART(key, 0, 4, \" lng_ \" )) return lngkeys_cnt; \n \n " ;
2014-05-30 08:53:19 +00:00
if ( ! keys . isEmpty ( ) ) {
QString tab ( " \t " ) ;
2014-12-18 18:40:49 +00:00
tcpp < < " \t const char *ch = key.constData(), *e = key.constData() + key.size(); \n " ;
QByteArray current ( " lng_ " ) ;
2014-05-30 08:53:19 +00:00
int depth = current . size ( ) ;
2014-12-18 18:40:49 +00:00
tcpp < < " \t switch (*(ch + " < < depth < < " )) { \n " ;
2014-05-30 08:53:19 +00:00
for ( LangKeys : : const_iterator i = keys . cbegin ( ) , j = i + 1 , e = keys . cend ( ) ; i ! = e ; + + i ) {
2014-12-18 18:40:49 +00:00
QByteArray key = i . key ( ) ;
while ( key . mid ( 0 , depth ) ! = current ) {
2014-05-30 08:53:19 +00:00
tcpp < < tab . repeated ( depth - 3 ) < < " } \n " ;
current . chop ( 1 ) ;
- - depth ;
tcpp < < tab . repeated ( depth - 3 ) < < " break; \n " ;
}
do {
if ( key = = current ) break ;
2014-12-18 18:40:49 +00:00
char ich = i . key ( ) . at ( current . size ( ) ) ;
2014-05-30 08:53:19 +00:00
tcpp < < tab . repeated ( current . size ( ) - 3 ) < < " case ' " < < ich < < " ': \n " ;
if ( j = = e | | ich ! = ( ( j . key ( ) . size ( ) > depth ) ? j . key ( ) . at ( depth ) : 0 ) ) {
if ( key = = current + ich ) {
2014-12-18 18:40:49 +00:00
tcpp < < tab . repeated ( depth - 3 ) < < " \t if (ch + " < < ( depth + 1 ) < < " == e) return " < < key < < ( keysTags [ key ] . isEmpty ( ) ? " " : " __tagged " ) < < " ; \n " ;
2014-05-30 08:53:19 +00:00
} else {
2014-12-18 18:40:49 +00:00
tcpp < < tab . repeated ( depth - 3 ) < < " \t if (LNG_EQUALS_TAIL(key, " < < ( depth + 1 ) < < " , \" " < < i . key ( ) . mid ( depth + 1 ) < < " \" )) return " < < key < < ( keysTags [ key ] . isEmpty ( ) ? " " : " __tagged " ) < < " ; \n " ;
2014-05-30 08:53:19 +00:00
}
tcpp < < tab . repeated ( depth - 3 ) < < " break; \n " ;
break ;
}
+ + depth ;
current + = ich ;
if ( key = = current ) {
tcpp < < tab . repeated ( depth - 3 ) < < " if (ch + " < < depth < < " == e) { \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < tab . repeated ( depth - 3 ) < < " \t return " < < key < < ( keysTags [ key ] . isEmpty ( ) ? " " : " __tagged " ) < < " ; \n " ;
2014-05-30 08:53:19 +00:00
tcpp < < tab . repeated ( depth - 3 ) < < " } \n " ;
}
2014-12-18 18:40:49 +00:00
tcpp < < tab . repeated ( depth - 3 ) < < " if (ch + " < < depth < < " < e) switch (*(ch + " < < depth < < " )) { \n " ;
2014-05-30 08:53:19 +00:00
} while ( true ) ;
+ + j ;
}
2014-12-18 18:40:49 +00:00
while ( QByteArray ( " lng_ " ) ! = current ) {
2014-05-30 08:53:19 +00:00
tcpp < < tab . repeated ( depth - 3 ) < < " } \n " ;
current . chop ( 1 ) ;
- - depth ;
tcpp < < tab . repeated ( depth - 3 ) < < " break; \n " ;
}
tcpp < < " \t } \n \n " ;
2014-12-18 18:40:49 +00:00
}
tcpp < < " \t return lngkeys_cnt; \n " ;
tcpp < < " } \n \n " ;
tcpp < < " bool LangLoader::tagReplaced(LangKey key, ushort tag) const { \n " ;
if ( ! tags . isEmpty ( ) ) {
tcpp < < " \t switch (key) { \n " ;
for ( int i = 0 , l = keysOrder . size ( ) ; i < l ; + + i ) {
QVector < QByteArray > & tagsList ( keysTags [ keysOrder [ i ] ] ) ;
if ( tagsList . isEmpty ( ) ) continue ;
tcpp < < " \t case " < < keysOrder [ i ] < < " __tagged: { \n " ;
tcpp < < " \t \t switch (tag) { \n " ;
for ( int j = 0 , s = tagsList . size ( ) ; j < s ; + + j ) {
tcpp < < " \t \t case lt_ " < < tagsList [ j ] < < " : \n " ;
}
tcpp < < " \t \t \t return true; \n " ;
tcpp < < " \t \t } \n " ;
tcpp < < " \t } break; \n " ;
}
2014-05-30 08:53:19 +00:00
tcpp < < " \t } \n \n " ;
}
2014-12-18 18:40:49 +00:00
tcpp < < " \t return false; " ;
2014-05-30 08:53:19 +00:00
tcpp < < " } \n \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " LangKey LangLoader::subkeyIndex(LangKey key, ushort tag, ushort index) const { \n " ;
tcpp < < " \t if (index >= lngtags_max_counted_values) return lngkeys_cnt; \n \n " ;
if ( ! tags . isEmpty ( ) ) {
tcpp < < " \t switch (key) { \n " ;
for ( int i = 0 , l = keysOrder . size ( ) ; i < l ; + + i ) {
QVector < QByteArray > & tagsList ( keysTags [ keysOrder [ i ] ] ) ;
if ( tagsList . isEmpty ( ) ) continue ;
QMap < QByteArray , QVector < QString > > & countedTags ( keysCounted [ keysOrder [ i ] ] ) ;
tcpp < < " \t case " < < keysOrder [ i ] < < " __tagged: { \n " ;
tcpp < < " \t \t switch (tag) { \n " ;
for ( int j = 0 , s = tagsList . size ( ) ; j < s ; + + j ) {
if ( ! countedTags [ tagsList [ j ] ] . isEmpty ( ) ) {
tcpp < < " \t \t case lt_ " < < tagsList [ j ] < < " : return LangKey( " < < keysOrder [ i ] < < " __ " < < tagsList [ j ] < < " 0 + index); \n " ;
}
}
tcpp < < " \t \t } \n " ;
tcpp < < " \t } break; \n " ;
}
tcpp < < " \t } \n \n " ;
}
tcpp < < " \t return lngkeys_cnt; " ;
2014-05-30 08:53:19 +00:00
tcpp < < " } \n \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " bool LangLoader::feedKeyValue(LangKey key, const QString &value) { \n " ;
tcpp < < " \t if (key < lngkeys_cnt) { \n " ;
tcpp < < " \t \t _found[key] = 1; \n " ;
2014-12-19 21:20:30 +00:00
tcpp < < " \t \t if (_langValuesOriginal[key].isEmpty()) { \n " ;
tcpp < < " \t \t \t _langValuesOriginal[key] = _langValues[key].isEmpty() ? qsl( \" {} \" ) : _langValues[key]; \n " ;
tcpp < < " \t \t } \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " \t \t _langValues[key] = value; \n " ;
tcpp < < " \t \t return true; \n " ;
2014-05-30 08:53:19 +00:00
tcpp < < " \t } \n " ;
2014-12-18 18:40:49 +00:00
tcpp < < " \t return false; \n " ;
tcpp < < " } \n \n " ;
2014-05-30 08:53:19 +00:00
}
QFile cpp ( lang_cpp ) , h ( lang_h ) ;
bool write_cpp = true , write_h = true ;
if ( cpp . open ( QIODevice : : ReadOnly ) ) {
QByteArray wasCpp = cpp . readAll ( ) ;
if ( wasCpp . size ( ) = = cppText . size ( ) ) {
if ( ! memcmp ( wasCpp . constData ( ) , cppText . constData ( ) , cppText . size ( ) ) ) {
write_cpp = false ;
}
}
cpp . close ( ) ;
}
if ( write_cpp ) {
cout < < " lang.cpp updated, writing " < < keysOrder . size ( ) < < " rows. \n " ;
2014-06-14 19:32:11 +00:00
if ( ! cpp . open ( QIODevice : : WriteOnly ) ) throw Exception ( " Could not open lang.cpp for writing! " ) ;
if ( cpp . write ( cppText ) ! = cppText . size ( ) ) throw Exception ( " Could not open lang.cpp for writing! " ) ;
2014-05-30 08:53:19 +00:00
}
if ( h . open ( QIODevice : : ReadOnly ) ) {
QByteArray wasH = h . readAll ( ) ;
if ( wasH . size ( ) = = hText . size ( ) ) {
if ( ! memcmp ( wasH . constData ( ) , hText . constData ( ) , hText . size ( ) ) ) {
write_h = false ;
}
}
h . close ( ) ;
}
if ( write_h ) {
cout < < " lang.h updated, writing " < < keysOrder . size ( ) < < " rows. \n " ;
2014-06-14 19:32:11 +00:00
if ( ! h . open ( QIODevice : : WriteOnly ) ) throw Exception ( " Could not open lang.h for writing! " ) ;
if ( h . write ( hText ) ! = hText . size ( ) ) throw Exception ( " Could not open lang.h for writing! " ) ;
2014-05-30 08:53:19 +00:00
}
} catch ( exception & e ) {
cout < < e . what ( ) < < " \n " ;
QCoreApplication : : exit ( 1 ) ;
return false ;
}
return true ;
}