diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..2a6af7156
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+Telegram/GeneratedFiles/
+Telegram/*.user
+Telegram.*.suo
+Telegram.sdf
+Telegram.opensdf
+Win32/
+ipch/
+
+Telegram/log.txt
+Telegram/data
+Telegram/data_config
+Telegram/DebugLogs/
+Telegram/tdata/
+Telegram/tdumps/
diff --git a/README.md b/README.md
index 602727044..62d3eda88 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,198 @@
-tdesktop
-========
+## [Telegram D](https://tdesktop.com) – Unofficial Telegram Desktop App
-Telegram Desktop messaging app
+This is complete source code and build instructions for alpha version of unofficial desktop client for [Telegram](https://telegram.org) messenger, based on [Telegram API](https://core.telegram.org/) and [MTProto](https://core.telegram.org/mtproto) secure protocol.
+
+###Supported systems
+
+Only Windows systems are supported at this moment, OS X and Linux builds are on their way.
+
+* Windows XP
+* Windows Vista
+* Windows 7
+* Windows 8 (**not** RT)
+* Windows 8.1 (**not** RT)
+
+###Third-party libraries
+
+* Qt 5.3.0, slightly patched
+* OpenSSL 1.0.1g
+* zlib 1.2.8
+* libexif 0.6.20
+* LZMA SDK 9.20
+
+##Build instructions for Visual Studio 2013
+
+###Prepare folder
+
+Choose a folder for the future build, for example **D:\TBuild\**. There you will have two folders, **Libraries** for third-party libs and **tdesktop** (or **tdesktop-master**) for the app.
+
+###Clone source code
+
+By git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild** and run
+
+ git clone https://github.com/telegramdesktop/tdesktop.git
+
+or download in ZIP and extract to **D:\TBuild\**, rename **tdesktop-master** to **tdesktop** to have **D:\TBuild\tdesktop\Telegram.sln** solution
+
+###Prepare libraries
+
+####OpenSSL 1.0.1g
+
+https://www.openssl.org/related/binaries.html > **OpenSSL for Windows** > Download [**Win32 OpenSSL v1.0.1g** (16 Mb)](http://slproweb.com/download/Win32OpenSSL-1_0_1g.exe)
+
+Install to **D:\TBuild\Libraries\OpenSSL-Win32**, while installing **Copy OpenSSL DLLs to** choose **The OpenSSL binaries (/bin) directory**
+
+####LZMA SDK 9.20
+
+http://www.7-zip.org/sdk.html > Download [**LZMA SDK (C, C++, C#, Java)** 9.20](http://downloads.sourceforge.net/sevenzip/lzma920.tar.bz2)
+
+Extract to **D:\TBuild\Libraries**
+
+#####Building library
+
+* Open in VS2013 **D:\TBuild\Libraries\lzma\C\Util\LzmaLib\LzmaLib.dsw** > One-way upgrade – **OK**
+* For **Debug** and **Release** configurations
+ * LzmaLib Properties > General > Configuration Type = **Static library (.lib)** – **OK**
+ * LzmaLib Properties > Librarian > General > Target Machine = **MachineX86 (/MACHINE:X86)** – **OK**
+* Build Debug configuration
+* Build Release configuration
+
+####zlib 1.2.8
+
+http://www.zlib.net/ > Download [**zlib source code, version 1.2.8, zipfile format**](http://zlib.net/zlib128.zip)
+
+Extract to **D:\TBuild\Libraries\**
+
+#####Building library
+
+* Open in VS2013 **D:\TBuild\Libraries\zlib-1.2.8\contrib\vstudio\vc11\zlibvc.sln** > One-way upgrade – **OK**
+* We are interested only in **zlibstat** project, but it depends on some custom pre-build step, so build all
+* For **Debug** configuration
+ * zlibstat Properties > C/C++ > Code Generation > Runtime Library = **Multi-threaded Debug (/MTd)** – **OK**
+* For **Release** configuration
+ * zlibstat Properties > C/C++ > Code Generation > Runtime Library = **Multi-threaded (/MT)** – **OK**
+* Build Solution for Debug configuration – only **zlibstat** project builds successfully
+* Build Solution for Release configuration – only **zlibstat** project builds successfully
+
+####libexif 0.6.20
+
+Get sources from https://github.com/telegramdesktop/libexif-0.6.20, by git – in [Git Bash](http://git-scm.com/downloads) go to **/d/tbuild/libraries** and run
+
+ git clone https://github.com/telegramdesktop/libexif-0.6.20.git
+
+or download in ZIP and extract to **D:\TBuild\Libraries\**, rename **libexif-0.6.20-master** to **libexif-0.6.20** to have **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln** solution
+
+#####Building library
+
+* Open in VS2013 **D:\TBuild\Libraries\libexif-0.6.20\win32\lib_exif.sln**
+* Build Debug configuration
+* Build Release configuration
+
+####Qt 5.3.0, slightly patched
+
+http://download.qt-project.org/official_releases/qt/5.3/5.3.0/single/qt-everywhere-opensource-src-5.3.0.zip
+
+Extract to **D:\TBuild\Libraries\**, rename **qt-everywhere-opensource-src-5.3.0** to **QtStatic** to have **D:\TBuild\Libraries\QtStatic\qtbase\** folder
+
+Apply patch – copy (with overwrite!) everything from **D:\TBuild\tdesktop\\\_qt\_5\_3\_0\_patch\** to **D:\TBuild\Libraries\QtStatic\**
+
+#####Building library
+
+* Install Python 3.3.2 from https://www.python.org/download/releases/3.3.2 > [**Windows x86 MSI Installer (3.3.2)**](https://www.python.org/ftp/python/3.3.2/python-3.3.2.msi)
+* Open **VS2013 x86 Native Tools Command Prompt.bat** (should be in **\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts\** folder)
+
+There go to Qt directory
+
+ D:
+ cd TBuild\Libraries\QtStatic
+
+and after that run configure
+
+ configure -debug-and-release -opensource -static -opengl desktop -mp -nomake examples -platform win32-msvc2013
+ y
+
+to configure Qt build. After configuration is complete run
+
+ nmake
+ nmake install
+
+building (**nmake** command) will take really long time.
+
+####Qt Visual Studio Addin 1.2.3
+
+http://download.qt-project.org/official_releases/vsaddin/qt-vs-addin-1.2.3-opensource.exe
+
+Close all VS2013 instances and install to default location
+
+###Building Telegram Desktop
+
+* Launch VS2013 for configuring Qt Addin
+* QT5 > Qt Options > Add
+ * Version name: **QtStatic.5.3.0**
+ * Path: **D:\TBuild\Libraries\QtStatic\qtbase**
+* Default Qt/Win version: **QtStatic.5.3.0** – **OK**
+* File > Open > Project/Solution > **D:\TBuild\tdesktop\Telegram.sln**
+* Build \ Build Solution (Debug and Release configurations)
+
+##Projects in Telegram solution
+
+####Telegram
+
+tdesktop messenger
+
+####Updater
+
+little app, that is launched by Telegram when update is ready, replaces all files and launches it back
+
+####Packer
+
+compiles given files to single update file, compresses it with lzma and signs with a private key, it was not included to Telegram solution, because private key is inaccessible
+
+####Prepare
+
+prepares a release for deployment, puts all files to deploy/{version} folder
+* current tsetup{version}exe installer
+* current Telegram.exe
+* current Telegram.pdb (debug info for crash minidumps view)
+* current tupdate{updversion} binary lzma update archive
+
+####MetaEmoji
+
+from two folders
+* SourceFiles/art/Emoji
+* SourceFiles/art/Emoji_200x
+
+and some inner config creates four sprites and text2emoji replace code
+* SourceFiles/art/emoji.png
+* SourceFiles/art/emoji_125x.png
+* SourceFiles/art/emoji_150x.png
+* SourceFiles/art/emoji_200x.png
+* SourceFiles/gui/emoji_config.cpp
+
+####MetaStyle
+
+from two files and two sprites
+* Resources/style_classes.txt
+* Resources/style.txt
+* SourceFiles/art/sprite.png
+* SourceFiles/art/sprite_200x.png
+
+creates two other sprites, four sprite grids and style constants code
+* SourceFiles/art/sprite_125x.png
+* SourceFiles/art/sprite_150x.png
+* SourceFiles/art/grid.png
+* SourceFiles/art/grid_125x.png
+* SourceFiles/art/grid_150x.png
+* SourceFiles/art/grid_200x.png
+* GeneratedFiles/style_classes.h
+* GeneratedFiles/style_auto.h
+* GeneratedFiles/style_auto.cpp
+
+####MetaLang
+
+from langpack file
+* Resources/lang.txt
+
+creates lang constants code and lang file parse code
+* GeneratedFiles/lang.h
+* GeneratedFiles/lang.cpp
\ No newline at end of file
diff --git a/Telegram.sln b/Telegram.sln
new file mode 100644
index 000000000..19aece280
--- /dev/null
+++ b/Telegram.sln
@@ -0,0 +1,72 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.30110.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Telegram", "Telegram\Telegram.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0} = {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB} = {E417CAA4-259B-4C99-88E3-805F1300E8EB}
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794} = {EB7D16AC-EACF-4577-B05A-F28E5F356794}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaStyle", "Telegram\MetaStyle.vcxproj", "{6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaEmoji", "Telegram\MetaEmoji.vcxproj", "{EB7D16AC-EACF-4577-B05A-F28E5F356794}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updater", "Telegram\Updater.vcxproj", "{6B4BA3BE-7B15-4B4C-B200-81ABFDEF2C76}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Prepare", "Telegram\Prepare.vcxproj", "{88AB1138-143A-4CFB-A0E6-79B646B5E1B0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaLang", "Telegram\MetaLang.vcxproj", "{E417CAA4-259B-4C99-88E3-805F1300E8EB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Win32.Build.0 = Debug|Win32
+ {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|Win32.Deploy.0 = Debug|Win32
+ {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|Win32
+ {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.ActiveCfg = Release|Win32
+ {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.Build.0 = Release|Win32
+ {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|Win32
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}.Debug|Win32.Build.0 = Debug|Win32
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}.Debug|x64.ActiveCfg = Debug|Win32
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}.Release|Win32.ActiveCfg = Release|Win32
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}.Release|Win32.Build.0 = Release|Win32
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}.Release|x64.ActiveCfg = Release|Win32
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794}.Debug|Win32.Build.0 = Debug|Win32
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794}.Debug|x64.ActiveCfg = Debug|Win32
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794}.Release|Win32.ActiveCfg = Release|Win32
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794}.Release|Win32.Build.0 = Release|Win32
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794}.Release|x64.ActiveCfg = Release|Win32
+ {6B4BA3BE-7B15-4B4C-B200-81ABFDEF2C76}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6B4BA3BE-7B15-4B4C-B200-81ABFDEF2C76}.Debug|Win32.Build.0 = Debug|Win32
+ {6B4BA3BE-7B15-4B4C-B200-81ABFDEF2C76}.Debug|x64.ActiveCfg = Debug|Win32
+ {6B4BA3BE-7B15-4B4C-B200-81ABFDEF2C76}.Release|Win32.ActiveCfg = Release|Win32
+ {6B4BA3BE-7B15-4B4C-B200-81ABFDEF2C76}.Release|Win32.Build.0 = Release|Win32
+ {6B4BA3BE-7B15-4B4C-B200-81ABFDEF2C76}.Release|x64.ActiveCfg = Release|Win32
+ {88AB1138-143A-4CFB-A0E6-79B646B5E1B0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {88AB1138-143A-4CFB-A0E6-79B646B5E1B0}.Debug|Win32.Build.0 = Debug|Win32
+ {88AB1138-143A-4CFB-A0E6-79B646B5E1B0}.Debug|x64.ActiveCfg = Debug|Win32
+ {88AB1138-143A-4CFB-A0E6-79B646B5E1B0}.Release|Win32.ActiveCfg = Release|Win32
+ {88AB1138-143A-4CFB-A0E6-79B646B5E1B0}.Release|Win32.Build.0 = Release|Win32
+ {88AB1138-143A-4CFB-A0E6-79B646B5E1B0}.Release|x64.ActiveCfg = Release|Win32
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB}.Debug|Win32.Build.0 = Debug|Win32
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB}.Debug|x64.ActiveCfg = Debug|Win32
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB}.Release|Win32.ActiveCfg = Release|Win32
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB}.Release|Win32.Build.0 = Release|Win32
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB}.Release|x64.ActiveCfg = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Telegram/MetaEmoji.vcxproj b/Telegram/MetaEmoji.vcxproj
new file mode 100644
index 000000000..3c61c633d
--- /dev/null
+++ b/Telegram/MetaEmoji.vcxproj
@@ -0,0 +1,115 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+ Moc%27ing genemoji.h...
+ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\."
+ Moc%27ing genemoji.h...
+ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\."
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+
+
+
+
+ {EB7D16AC-EACF-4577-B05A-F28E5F356794}
+ Qt4VSv1.0
+
+
+
+ Application
+ v120_xp
+
+
+ Application
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>11.0.60610.1
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)Emoji\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediateEmoji\
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)Emoji\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediateEmoji\
+
+
+
+ UNICODE;WIN32;WIN64;%(PreprocessorDefinitions)
+ Disabled
+ ProgramDatabase
+ MultiThreadedDebug
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;%(AdditionalDependencies)
+ true
+ $(IntDir)$(TargetName).pdb
+ $(IntDir)$(TargetName).pgd
+
+
+
+
+ UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;%(PreprocessorDefinitions)
+
+ MultiThreaded
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;qtmain.lib;glu32.lib;opengl32.lib;imm32.lib;winmm.lib;Qt5Core.lib;Qt5Gui.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;%(AdditionalDependencies)
+ false
+ $(IntDir)$(TargetName).pdb
+ $(IntDir)$(TargetName).pgd
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Telegram/MetaEmoji.vcxproj.filters b/Telegram/MetaEmoji.vcxproj.filters
new file mode 100644
index 000000000..34a46ccae
--- /dev/null
+++ b/Telegram/MetaEmoji.vcxproj.filters
@@ -0,0 +1,57 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;cxx;c;def
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h
+
+
+ {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}
+ qrc;*
+ false
+
+
+ {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}
+ moc;h;cpp
+ False
+
+
+ {d43dc9f2-202b-4a47-b396-e7e2882cd611}
+ cpp;moc
+ False
+
+
+ {6a90eef7-d2c6-46bd-8158-a8c5185190a7}
+ cpp;moc
+ False
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Generated Files\Debug
+
+
+ Generated Files\Release
+
+
+
+
+ Header Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/Telegram/MetaLang.vcxproj b/Telegram/MetaLang.vcxproj
new file mode 100644
index 000000000..10523275d
--- /dev/null
+++ b/Telegram/MetaLang.vcxproj
@@ -0,0 +1,113 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing genlang.h...
+ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\."
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ Moc%27ing genlang.h...
+ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\."
+
+
+
+
+ {E417CAA4-259B-4C99-88E3-805F1300E8EB}
+ Qt4VSv1.0
+
+
+
+ Application
+ v120_xp
+
+
+ Application
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>12.0.21005.1
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)Lang\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediateLang\
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)Lang\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediateLang\
+
+
+
+ UNICODE;WIN32;WIN64;%(PreprocessorDefinitions)
+ Disabled
+ ProgramDatabase
+ MultiThreadedDebug
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;%(AdditionalDependencies)
+ true
+ $(IntDir)$(TargetName).pdb
+ $(IntDir)$(TargetName).pgd
+
+
+
+
+ UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;%(PreprocessorDefinitions)
+
+ MultiThreaded
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;qtmain.lib;opengl32.lib;imm32.lib;winmm.lib;Qt5Core.lib;Qt5Gui.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;%(AdditionalDependencies)
+ false
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Telegram/MetaLang.vcxproj.filters b/Telegram/MetaLang.vcxproj.filters
new file mode 100644
index 000000000..4de4918b2
--- /dev/null
+++ b/Telegram/MetaLang.vcxproj.filters
@@ -0,0 +1,57 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;cxx;c;def
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h
+
+
+ {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}
+ qrc;*
+ false
+
+
+ {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}
+ moc;h;cpp
+ False
+
+
+ {3c9f729e-b8c7-4b14-b2df-4a3eda27c074}
+ cpp;moc
+ False
+
+
+ {3e5a3edb-4328-4310-aec6-a3c6449e1aab}
+ cpp;moc
+ False
+
+
+
+
+ Source Files
+
+
+ Generated Files\Debug
+
+
+ Source Files
+
+
+ Generated Files\Release
+
+
+
+
+ Header Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/Telegram/MetaStyle.vcxproj b/Telegram/MetaStyle.vcxproj
new file mode 100644
index 000000000..cefb3f878
--- /dev/null
+++ b/Telegram/MetaStyle.vcxproj
@@ -0,0 +1,129 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Moc%27ing genstyles.h...
+ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\."
+ Moc%27ing genstyles.h...
+ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\."
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+
+
+
+ {6F483617-7C84-4E7E-91D8-1FF28A4CE3A0}
+ Qt4VSv1.0
+
+
+
+ Application
+ v120_xp
+
+
+ Application
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>11.0.60610.1
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediateMeta\
+ $(SolutionDir)$(Platform)\$(Configuration)Meta\
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)Meta\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediateMeta\
+
+
+
+ UNICODE;WIN32;WIN64;%(PreprocessorDefinitions)
+ Disabled
+ ProgramDatabase
+ MultiThreadedDebug
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;imm32.lib;winmm.lib;qtmaind.lib;glu32.lib;opengl32.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5Networkd.lib;Qt5PlatformSupportd.lib;platforms\qwindowsd.lib;%(AdditionalDependencies)
+ true
+ $(IntDir)$(TargetName).pdb
+ $(IntDir)$(TargetName).pgd
+
+
+
+
+
+ UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;%(PreprocessorDefinitions)
+
+ MultiThreaded
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;qtmain.lib;opengl32.lib;imm32.lib;winmm.lib;Qt5Core.lib;Qt5Gui.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;%(AdditionalDependencies)
+ false
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Telegram/MetaStyle.vcxproj.filters b/Telegram/MetaStyle.vcxproj.filters
new file mode 100644
index 000000000..9210ed15a
--- /dev/null
+++ b/Telegram/MetaStyle.vcxproj.filters
@@ -0,0 +1,55 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;cxx;c;def
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h
+
+
+ {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}
+ qrc;*
+ false
+
+
+ {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}
+ moc;h;cpp
+ False
+
+
+ {1ace0630-c46a-4299-a4c3-d155a4cb04bb}
+ cpp;moc
+ False
+
+
+ {2473bf06-b2ba-4f68-9bfe-72a58da61f94}
+ cpp;moc
+ False
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Generated Files\Debug
+
+
+ Generated Files\Release
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/Telegram/Packer.vcxproj b/Telegram/Packer.vcxproj
new file mode 100644
index 000000000..7bd010bc1
--- /dev/null
+++ b/Telegram/Packer.vcxproj
@@ -0,0 +1,96 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+
+
+
+
+
+ {56A9A4B2-21E5-4360-AFA8-85B43AC43B08}
+ Qt4VSv1.0
+
+
+
+ Application
+ v120_xp
+
+
+ Application
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>11.0.61030.0
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediatePacker\
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediatePacker\
+
+
+
+ UNICODE;WIN32;WIN64;QT_CORE_LIB;ZLIB_WINAPI;%(PreprocessorDefinitions)
+ Disabled
+ ProgramDatabase
+ MultiThreadedDebug
+ .\..\..\Libraries\lzma\C;.;$(QTDIR)\include;.\..\..\Libraries\zlib-1.2.8;.\..\..\Libraries\OpenSSL-32-Debug\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ .\..\..\Libraries\lzma\C\Util\LzmaLib\Debug;$(QTDIR)\lib;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatQtDebug;.\..\..\Libraries\OpenSSL-32-Debug\lib;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;qtmaind.lib;zlibstat_qt.lib;libeay32.lib;Qt5Cored.lib;LzmaLib.lib;%(AdditionalDependencies)
+ true
+
+
+
+
+
+ UNICODE;WIN32;WIN64;QT_NO_DEBUG;ZLIB_WINAPI;NDEBUG;QT_CORE_LIB;%(PreprocessorDefinitions)
+
+ MultiThreaded
+ .\..\..\Libraries\lzma\C;.;$(QTDIR)\include;.\..\..\Libraries\zlib-1.2.8;.\..\..\Libraries\OpenSSL-32\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ .\..\..\Libraries\lzma\C\Util\LzmaLib\Release;$(QTDIR)\lib;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatQtRelease;.\..\..\Libraries\OpenSSL-32\lib;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;qtmain.lib;zlibstat_qt.lib;libeay32.lib;Qt5Core.lib;LzmaLib.lib;%(AdditionalDependencies)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Telegram/Packer.vcxproj.filters b/Telegram/Packer.vcxproj.filters
new file mode 100644
index 000000000..9ba4d3460
--- /dev/null
+++ b/Telegram/Packer.vcxproj.filters
@@ -0,0 +1,16 @@
+
+
+
+
+ {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}
+ moc;h;cpp
+ False
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Telegram/Prepare.bat b/Telegram/Prepare.bat
new file mode 100644
index 000000000..d7364a119
--- /dev/null
+++ b/Telegram/Prepare.bat
@@ -0,0 +1 @@
+Prepare.exe -path Telegram.exe -path Updater.exe
\ No newline at end of file
diff --git a/Telegram/Prepare.vcxproj b/Telegram/Prepare.vcxproj
new file mode 100644
index 000000000..2a76b8bcc
--- /dev/null
+++ b/Telegram/Prepare.vcxproj
@@ -0,0 +1,94 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+
+
+
+
+
+ {88AB1138-143A-4CFB-A0E6-79B646B5E1B0}
+ Qt4VSv1.0
+
+
+
+ Application
+ v120_xp
+
+
+ Application
+ v120_xp
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>11.0.61030.0
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediatePrepare\
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)IntermediatePrepare\
+
+
+
+ UNICODE;WIN32;WIN64;QT_CORE_LIB;%(PreprocessorDefinitions)
+ Disabled
+ ProgramDatabase
+ MultiThreadedDebug
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;qtmaind.lib;Qt5Cored.lib;%(AdditionalDependencies)
+ true
+
+
+
+
+ UNICODE;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;%(PreprocessorDefinitions)
+
+ MultiThreaded
+ .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)
+ false
+
+
+ Console
+ $(OutDir)\$(ProjectName).exe
+ $(QTDIR)\lib;%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;qtmain.lib;Qt5Core.lib;%(AdditionalDependencies)
+ false
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Telegram/Prepare.vcxproj.filters b/Telegram/Prepare.vcxproj.filters
new file mode 100644
index 000000000..c4a106555
--- /dev/null
+++ b/Telegram/Prepare.vcxproj.filters
@@ -0,0 +1,33 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;cxx;c;def
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h
+
+
+ {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}
+ qrc;*
+ false
+
+
+ {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}
+ moc;h;cpp
+ False
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/Telegram/Resources/lang.txt b/Telegram/Resources/lang.txt
new file mode 100644
index 000000000..b14eb0580
--- /dev/null
+++ b/Telegram/Resources/lang.txt
@@ -0,0 +1,379 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+direction: "LTR";
+
+lng_maintitle: "Telegram D";
+
+lng_menu_contacts: "Contacts";
+lng_menu_settings: "Settings";
+lng_menu_about: "About";
+
+lng_open_from_tray: "Open Telegram";
+lng_quit_from_tray: "Quit Telegram";
+lng_tray_icon_text: "Telegram is still running here,
+you can change this from settings page.
+
+If this icon disappears from tray menu,
+you can drag it back here from hidden icons.";
+
+lng_month1: "January";
+lng_month2: "February";
+lng_month3: "March";
+lng_month4: "April";
+lng_month5: "May";
+lng_month6: "June";
+lng_month7: "July";
+lng_month8: "August";
+lng_month9: "September";
+lng_month10: "October";
+lng_month11: "November";
+lng_month12: "December";
+
+lng_weekday1: "Mon";
+lng_weekday2: "Tue";
+lng_weekday3: "Wed";
+lng_weekday4: "Thu";
+lng_weekday5: "Fri";
+lng_weekday6: "Sat";
+lng_weekday7: "Sun";
+
+lng_month_day: "{month} {day}";
+
+lng_cancel: "Cancel";
+lng_continue: "Continue";
+lng_connecting: "Connecting...";
+lng_reconnecting: "Reconnect in %1 s...";
+lng_reconnecting_try_now: "Try now";
+
+lng_status_offline: "offline";
+lng_status_invisible: "invisible";
+lng_status_lastseen: "last seen {when}";
+lng_status_lastseen_now: "just now";
+lng_status_lastseen_minute: "%1 minute ago";
+lng_status_lastseen_minutes: "%1 minutes ago";
+lng_status_lastseen_hour: "%1 hour ago";
+lng_status_lastseen_hours: "%1 hours ago";
+lng_status_lastseen_today: "today at {time}";
+lng_status_lastseen_yesterday: "yesterday at {time}";
+lng_status_lastseen_date: "{date}";
+lng_status_online: "online";
+
+lng_chat_no_members: "Group is unaccessible";
+lng_chat_members: "%1 members";
+lng_chat_members_online: "%1 members, %2 online";
+
+lng_server_error: "Internal server error.";
+lng_flood_error: "Too much tries. Please try again later.";
+lng_deleted: "Unknown";
+
+lng_intro1: "Welcome to an unofficial [b]desktop[/b] client
+of [b]Telegram[/b] mobile messenger.";
+lng_intro2: "Visit [a href=\"https://telegram.org/\"]telegram.org[/a] to learn more.";
+lng_start_msgs: "Start Messaging";
+
+lng_intro_back: "Back";
+lng_intro_next: "Next";
+lng_intro_finish: "Finish";
+
+lng_phone_ph: "Your phone number";
+lng_phone_title: "Your Phone";
+lng_phone_desc: "Please confirm your country code and
+enter your phone number.";
+lng_phone_notreg: "Note: if you don't have a Telegram account yet,
+please [b]sign up[/b] with your [a href=\"https://telegram.org/\"]iOS / Android[/a] or {signup}here »{/signup}";
+lng_country_code: "Country Code";
+lng_bad_country_code: "Invalid Country Code";
+lng_country_ph: "Search";
+lng_country_done: "Done";
+lng_country_none: "Country not found";
+lng_country_select: "Select Country";
+
+lng_code_ph: "Your code";
+lng_code_desc: "We have sent you an SMS with activation
+code to your phone. Please enter it below.";
+lng_code_call: "Telegram will dial your number in %1:%2";
+lng_code_calling: "Requesting a call from Telegram...";
+lng_code_called: "Telegram dialed your number";
+
+lng_bad_phone: "Invalid phone number. Please try again.";
+lng_bad_phone_noreg: "Phone number not registered.";
+lng_bad_code: "You have entered an invalid code. Please try again.";
+lng_bad_name: "Please enter your first and last name.";
+lng_bad_chat_title: "Please enter new chat title.";
+lng_bad_photo: "Bad image selected.";
+
+lng_signup_title: "Information and photo";
+lng_signup_firstname: "First Name";
+lng_signup_lastname: "Last Name";
+
+lng_dlg_filter: "Search";
+lng_dlg_new_group_name: "Group name";
+lng_dlg_create_group: "Create";
+
+lng_settings_profile: "Profile";
+lng_settings_edit: "Edit";
+lng_settings_save: "Save";
+lng_settings_cancel: "Cancel";
+lng_settings_upload: "Set Profile Photo";
+lng_settings_badsize: "This image has bad size, please try other.";
+lng_settings_crop_profile: "Select square area for your profile photo";
+lng_settings_uploading_photo: "Uploading photo...";
+
+lng_settings_section_notify: "Notifications";
+lng_settings_desktop_notify: "Desktop notifications";
+lng_settings_sound_notify: "Sound";
+
+lng_settings_section_general: "General";
+lng_settings_auto_update: "Update automatically";
+lng_settings_current_version: "Version {version}";
+lng_settings_check_now: "Check for updates";
+lng_settings_update_checking: "Checking for updates...";
+lng_settings_latest_installed: "Latest version is installed";
+lng_settings_downloading: "Downloading update {ready} / {total} Mb...";
+lng_settings_update_ready: "New version is ready";
+lng_settings_update_now: "Restart Now";
+lng_settings_update_fail: "Update check failed :(";
+lng_settings_workmode_tray: "Show tray icon";
+lng_settings_workmode_window: "Show taskbar icon";
+lng_settings_auto_start: "Launch Telegram when system starts";
+lng_settings_start_min: "Launch minimized";
+lng_settings_scale_label: "Interface scale";
+lng_settings_scale_auto: "Auto ({cur})";
+
+lng_settings_section_chat: "Chat options";
+lng_settings_replace_emojis: "Replace emojis";
+lng_settings_view_emojis: "View list";
+lng_settings_emoji_list: "List of supported emojis";
+lng_settings_send_enter: "Send by Enter";
+lng_settings_send_ctrlenter: "Send by Ctrl+Enter";
+lng_settings_cats_and_dogs: "Allow cats and dogs";
+
+lng_download_path_dont_ask: "Don't ask download path for each file";
+lng_download_path_label: "Download path: ";
+lng_download_path_temp: "temp folder";
+lng_download_path_clear: "Clear All";
+lng_download_path_header: "Choose download path";
+lng_download_path_temp_radio: "Temp folder, cleared on logout or uninstall";
+lng_download_path_dir_radio: "Custom folder, cleared only manually";
+lng_download_path_choose: "Choose download path";
+lng_sure_clear_downloads: "Do you want to remove all downloaded files from temp folder? It is done automatically on logout or program uninstall.";
+lng_download_path_failed: "File download could not be started. It could happen because of a bad download location.
+
+You can change download path in Settings.";
+lng_download_path_settings: "Go to Settings";
+lng_download_finish_failed: "File download could not be finished.
+
+Would you like to try again?";
+lng_download_path_clearing: "Clearing...";
+lng_download_path_cleared: "Cleared!";
+lng_download_path_clear_failed: "Clear failed :(";
+
+lng_settings_section_advanced: "Advanced";
+lng_connection_type: "Connection type:";
+lng_connection_auto_connecting: "Default (connecting..)";
+lng_connection_auto: "Default ({type} used)";
+lng_connection_http_proxy: "HTTP with proxy";
+lng_connection_tcp_proxy: "TCP with proxy";
+lng_connection_header: "Connection type";
+lng_connection_auto_rb: "Auto (TCP if available or HTTP)";
+lng_connection_http_proxy_rb: "HTTP with custom http-proxy";
+lng_connection_tcp_proxy_rb: "TCP with custom socks5-proxy";
+lng_connection_host_ph: "Hostname";
+lng_connection_port_ph: "Port";
+lng_connection_user_ph: "Username";
+lng_connection_password_ph: "Password";
+lng_connection_save: "Save";
+lng_settings_reset: "Reset other sessions";
+lng_settings_reset_done: "Sessions reset done";
+lng_settings_logout: "Log Out";
+
+lng_settings_need_restart: "You need to restart for applying
+some of the new settings. Restart now?";
+lng_settings_restart_now: "Restart";
+lng_settings_restart_later: "Later";
+
+lng_profile_settings_section: "Settings";
+lng_profile_participants_section: "Participants";
+lng_profile_info: "Contact info";
+lng_profile_group_info: "Group info";
+lng_profile_add_contact: "Add Contact";
+lng_profile_edit_contact: "Edit";
+lng_profile_edit_group: "Edit";
+lng_profile_phone: "Phone number: {phone}";
+lng_profile_enable_notifications: "Notifications";
+lng_profile_clear_history: "Clear history";
+lng_profile_send_message: "Send Message";
+lng_profile_share_contact: "Share Contact";
+lng_profile_delete_contact: "Delete";
+lng_profile_set_group_photo: "Set Photo";
+lng_profile_add_participant: "Add Member";
+lng_profile_delete_and_exit: "Leave";
+lng_profile_kick: "Kick";
+lng_profile_sure_kick: "Kick {user} from the group?";
+lng_profile_loading: "Loading...";
+
+lng_participant_filter: "Search";
+lng_participant_invite: "Invite";
+lng_create_new_group: "New Group";
+lng_create_group_next: "Next";
+lng_create_group_title: "New Group";
+
+lng_sure_delete_contact: "Are you sure, you want to delete {contact} from your contact list?";
+lng_sure_delete_history: "Are you sure, you want to delete all message history with {contact}?
+
+This action cannot be undone.";
+
+lng_sure_delete_and_exit: "Are you sure, you want to delete all message history and leave «{group}»?
+
+This action cannot be undone.";
+
+lng_sure_enable_debug: "Do you want to enable DEBUG mode?
+
+All network events will be logged.";
+
+lng_message_empty: "(empty)";
+
+lng_action_add_user: "{from} added {user}";
+lng_action_kick_user: "{from} kicked {user}";
+lng_action_user_left: "{from} left the group";
+lng_action_user_joined: "{from} joined the group";
+lng_action_user_photo: "{from} added a new profile photo";
+lng_action_user_registered: "{from} just joined Telegram";
+lng_action_removed_photo: "{from} removed group photo";
+lng_action_changed_photo: "{from} changed group photo";
+lng_action_changed_title: "{from} changed group name to «{title}»";
+lng_action_created_chat: "{from} created group «{title}»";
+lng_action_checked_in: "{from} checked in";
+
+lng_forwarded_from: "Forwarded from ";
+
+lng_attach_failed: "Failed";
+lng_attach_file: "File";
+lng_attach_photo: "Photo";
+
+lng_media_open_with: "Open With";
+lng_media_download: "Download";
+lng_media_cancel: "Cancel";
+lng_media_video: "Video";
+lng_media_audio: "Audio";
+
+lng_in_dlg_photo: "Photo";
+lng_in_dlg_video: "Video";
+lng_in_dlg_geo: "Map";
+lng_in_dlg_contact: "Contact";
+lng_in_dlg_audio: "Audio";
+lng_in_dlg_document: "File";
+
+lng_send_button: "Send";
+lng_message_ph: "Write a message...";
+lng_empty_history: "";
+lng_willbe_history: "Please select chat to start messaging";
+lng_message_with_from: "[c]{from}:[/c] {message}";
+lng_from_you: "You";
+
+lng_typing: "typing";
+lng_user_typing: "{user} is typing";
+lng_users_typing: "{user1} and {user2} are typing";
+lng_many_typing: "{n} are typing";
+lng_unread_bar: "%1 unread messages";
+
+lng_maps_point: "Location";
+lng_save_photo: "Save image";
+lng_save_video: "Save video";
+lng_save_audio: "Save audio";
+lng_save_document: "Save document";
+lng_save_downloaded: "{ready} / {total} {mb}";
+lng_duration_and_size: "{duration}, {size}";
+lng_choose_images: "Choose images";
+
+lng_context_open_link: "Open Link";
+lng_context_copy_link: "Copy Link";
+lng_context_open_email: "Write to this address";
+lng_context_copy_email: "Copy email address";
+lng_context_open_image: "Open Image";
+lng_context_save_image: "Save Image As...";
+lng_context_forward_image: "Forward Image";
+lng_context_delete_image: "Delete Image";
+lng_context_copy_image: "Copy Image";
+lng_context_close_image: "Close Image";
+lng_context_cancel_download: "Cancel Download";
+lng_context_show_in_folder: "Show in Folder";
+lng_context_open_video: "Open Video";
+lng_context_save_video: "Save Video As...";
+lng_context_open_audio: "Open Audio";
+lng_context_save_audio: "Save Audio As...";
+lng_context_open_document: "Open File";
+lng_context_save_document: "Save File As...";
+lng_context_copy_text: "Copy Message Text";
+lng_context_forward_msg: "Forward Message";
+lng_context_delete_msg: "Delete Message";
+lng_context_cancel_upload: "Cancel Upload";
+lng_context_copy_selected: "Copy Selected Text";
+lng_context_forward_selected: "Forward Selected";
+lng_context_delete_selected: "Delete Selected";
+lng_context_clear_selection: "Clear Selection";
+lng_really_send_image: "Do you want to send this image?";
+
+lng_forward_choose: "Choose recipient...";
+lng_forward_confirm: "Forward to {recipient}?";
+lng_forward_share_contact: "Share contact to {recipient}?";
+lng_forward: "Forward";
+
+lng_contact_phone: "Phone number";
+lng_enter_contact_data: "New Contact";
+lng_edit_group_title: "Edit group name";
+lng_edit_contact_title: "Edit contact name";
+lng_edit_self_title: "Edit your name";
+lng_confirm_contact_data: "New Contact";
+lng_add_contact: "Create";
+lng_add_contact_button: "Add Contact";
+lng_contacts_header: "Contacts";
+lng_contact_not_joined: "Unfortunately {name} did not join Telegram yet, but you can send your friend an invitation.
+
+We will notify you about any of your contacts who is joining Telegram.";
+lng_try_other_contact: "Try other";
+lng_contacts_done: "Cancel";
+
+lng_drag_images_here: "Drop images here";
+lng_drag_photos_here: "Drop photos here";
+lng_drag_files_here: "Drop files here";
+
+lng_drag_to_send_quick: "to send them in a quick way";
+lng_drag_to_send_no_compression: "to send them without compression";
+lng_drag_to_send_documents: "to send them as documents";
+
+lng_selected_clear: "Cancel";
+lng_selected_delete: "Delete";
+lng_selected_forward: "Forward";
+lng_selected_count_1: "%1 message";
+lng_selected_count_5: "%1 messages";
+lng_selected_cancel_sure_this: "Do you want to cancel this upload?";
+lng_selected_delete_sure_this: "Do you want to delete this message?";
+lng_selected_delete_sure_1: "Do you want to delete %1 message?";
+lng_selected_delete_sure_5: "Do you want to delete %1 messages?";
+lng_selected_delete_confirm: "Delete";
+
+lng_emoji_no_recent: "Recent emojis will be here";
+
+lng_about_version: "Version {version}";
+lng_about_text: "Unofficial free messaging app based on [a href=\"https://core.telegram.org/mtproto\"]MTProto[/a] and
+[a href=\"https://core.telegram.org/api\"]Telegram API[/a] for speed and security
+
+This software is licensed under [a href=\"https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE\"]GNU GPL[/a] version 3,
+source code is available on [a href=\"https://github.com/telegramdesktop/tdesktop\"]GitHub[/a].";
+lng_about_done: "Done";
diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
new file mode 100644
index 000000000..7df2b7ac3
--- /dev/null
+++ b/Telegram/Resources/style.txt
@@ -0,0 +1,1388 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+defaultFontFamily: 'Segoe UI';
+//defaultFontFamily: 'ThoolikaTraditionalUnicode';
+semibold: 'Segoe WP Semibold';
+
+spriteFile: ':/gui/art/sprite.png' / 2:':/gui/art/sprite_125x.png' / 3:':/gui/art/sprite_150x.png' / 4:':/gui/art/sprite_200x.png';
+emojisFile: ':/gui/art/emoji.png' / 2:':/gui/art/emoji_125x.png' / 3:':/gui/art/emoji_150x.png' / 4:':/gui/art/emoji_200x.png';
+emojiSize: 16px;
+emojiPadding: 1px;
+
+counterBG: #b42f35;
+counterMuteBG: #777;
+counterColor: #fff;
+
+transparent: rgba(255, 255, 255, 0);
+white: rgba(255, 255, 255, 255);
+black: rgba(0, 0, 0, 255);
+
+color1: #c03d33; // red
+color2: #4fad2d; // green
+color3: #d09306; // yellow
+color4: #348cd4; // blue
+color5: #8544d6; // purple
+color6: #cd4073; // pink
+color7: #2996ad; // sea
+color8: #ce671b; // orange
+
+wndMinWidth: 640px;
+wndMinHeight: 480px;
+wndDefWidth: 800px;
+wndDefHeight: 600px;
+wndBG: #FFF;
+wndShadow: sprite(184px, 21px, 19px, 19px);
+wndShadowShift: 1px;
+
+layerAlpha: 0.3;
+layerBG: #000;
+
+titleBG: #6389a8;
+titleColor: #0f8dcc;//rgb(20, 136, 210);
+titleHeight: 39px;
+titleShadowColor: rgba(0, 0, 0, 24);//#ebebeb
+titleShadow: 1px;
+titleIconPos: point(7px, 7px);
+titleIconRect: sprite(160px, 100px, 26px, 26px);
+titleFont: font(17px);
+titlePos: point(44px, 29px);
+titleMenuOffset: 36px;
+
+titleRed: #ee4928;
+titleGray: #777;
+titleGreen: #41a903;
+
+titleStatusColor: #999;
+titleTypingColor: #0080c0;
+
+statusFont: font(14px);
+versionColor: #777;
+
+sysBtnDelta: 6px;
+sysUpd: sysButton {
+ size: size(31px, 39px);
+ img: sprite(184px, 1px, 19px, 19px);
+ color: #c4d8e9;
+ overColor: white;
+ duration: 150;
+}
+sysMin: sysButton(sysUpd) {
+ img: sprite(207px, 1px, 19px, 19px);
+}
+sysMax: sysButton(sysUpd) {
+ img: sprite(230px, 1px, 19px, 19px);
+}
+sysRes: sysButton(sysUpd) {
+ img: sprite(253px, 1px, 19px, 19px);
+}
+sysCls: sysButton(sysUpd) {
+ img: sprite(276px, 1px, 19px, 19px);
+}
+
+btnWhiteHover: #f5f5f5;
+btnBoxWhiteHover: #fafafa;
+btnYesColor: #0080c0;
+btnYesHover: #0073ad;
+btnNoColor: #8b8b8b;
+btnNoHover: #777;
+
+btnDefIconed: iconedButton {
+ color: white;
+ bgColor: white;
+ overBgColor: white;
+ font: font(14px);
+
+ opacity: 0.78;
+ overOpacity: 1;
+
+ textPos: point(0px, 0px);
+ downTextPos: point(0px, 0px);
+
+ duration: 150;
+ cursor: cursor(pointer);
+}
+
+titleTextButton: flatButton {
+ color: #d4e3ef;
+ overColor: #fff;
+ downColor: #fff;
+ bgColor: transparent;
+ overBgColor: transparent;
+ downBgColor: transparent;
+
+ width: -14px;
+ height: 39px;
+
+ textTop: 10px;
+ overTextTop: 10px;
+ downTextTop: 11px;
+
+ font: font(13px);
+ overFont: font(13px);
+ duration: 150;
+ cursor: cursor(default);
+}
+
+btnDefFlat: flatButton {
+ duration: 200;
+ cursor: cursor(pointer);
+}
+btnDefBig: flatButton(btnDefFlat) {
+ textTop: 11px;
+ overTextTop: 11px;
+ downTextTop: 12px;
+
+ font: font(23px);
+ overFont: font(23px);
+ height: 56px;
+}
+btnDefNext: flatButton(btnDefFlat) {
+ color: white;
+ overColor: white;
+ downColor: white;
+ bgColor: #2fa9e2;
+ overBgColor: #279ad0;
+ downBgColor: #279ad0;
+}
+btnDefBack: flatButton(btnDefFlat) {
+ color: white;
+ overColor: white;
+ downColor: white;
+ bgColor: #c7c7c7;
+ overBgColor: #b9b9b9;
+ downBgColor: #b9b9b9;
+}
+
+linkFont: font(14px);
+linkOverFont: font(14px underline);
+btnDefLink: linkButton {
+ color: btnYesColor;
+ overColor: btnYesColor;
+ downColor: btnYesHover;
+ font: linkFont;
+ overFont: linkOverFont;
+}
+
+cbDefFlat: flatCheckbox {
+ textColor: #000;
+ bgColor: transparent;
+ disColor: #999;
+
+ height: 22px;
+ textTop: 0px;
+ textLeft: 34px;
+ font: font(14px);
+ duration: 200;
+ bgFunc: transition(easeOutCirc);
+ cursor: cursor(pointer);
+
+ disabledCursor: cursor(default);
+
+ imageRect: sprite(144px, 68px, 22px, 22px);
+ chkImageRect: sprite(119px, 68px, 22px, 22px);
+ overImageRect: sprite(144px, 68px, 22px, 22px);
+ chkOverImageRect: sprite(119px, 68px, 22px, 22px);
+ disImageRect: sprite(193px, 68px, 22px, 22px);
+ chkDisImageRect: sprite(193px, 68px, 22px, 22px);
+
+ imagePos: point(0px, 0px);
+}
+
+rbDefFlat: flatCheckbox(cbDefFlat) {
+ chkImageRect: sprite(169px, 68px, 22px, 22px);
+ chkOverImageRect: sprite(169px, 68px, 22px, 22px);
+}
+
+inpDefFont: font(17px);
+inpDefFlat: flatInput {
+ textColor: #000;
+ bgColor: #FFF;
+ bgActive: #FFF;
+ width: 210px;
+ height: 40px;
+ align: align(left);
+ textMrg: margins(5px, 5px, 5px, 5px);
+ font: inpDefFont;
+ cursor: cursor(text);
+
+ borderWidth: 0px;
+ borderColor: black;
+ borderActive: black;
+ borderError: black;
+
+ phColor: #949494;
+ phFocusColor: #AAA;
+ phAlign: align(left);
+ phPos: point(2px, 0px);
+ phShift: 50px;
+ phDuration: 100;
+ phLeftFunc: transition(linear);
+ phAlphaFunc: transition(linear);
+ phColorFunc: transition(linear);
+}
+
+inpDefGray: flatInput(inpDefFlat) {
+ bgColor: #ebebeb;
+ borderWidth: 2px;
+ borderColor: #ebebeb;
+ borderActive: #80cff9;
+ borderError: #ed8080;
+ phColor: #808080;
+}
+
+taDefFlat: flatTextarea {
+ textColor: #000;
+ bgColor: #FFF;
+ align: align(left);
+ textMrg: margins(5px, 5px, 5px, 5px);
+ font: inpDefFont;
+ cursor: cursor(text);
+
+ phColor: #AAA;
+ phFocusColor: #CCC;
+ phAlign: align(topleft);
+ phPos: point(2px, 0px);
+ phShift: 50px;
+ phDuration: 100;
+ phLeftFunc: transition(linear);
+ phAlphaFunc: transition(linear);
+ phColorFunc: transition(linear);
+}
+
+scrollDef: flatScroll {
+ barColor: rgba(0, 0, 0, 83);
+ bgColor: rgba(0, 0, 0, 26);
+ barOverColor: rgba(0, 0, 0, 122);
+ bgOverColor: rgba(0, 0, 0, 44);
+
+ round: 0px;
+
+ width: 10px;
+ minHeight: 20px;
+ deltax: 3px;
+ deltay: 3px;
+
+ topsh: 2px;
+ bottomsh: 2px;
+ shColor: rgba(0, 0, 0, 18);
+
+ duration: 150;
+ hiding: 1000;
+}
+scrollCountries: flatScroll(scrollDef) {
+ topsh: 0px;
+ bottomsh: -2px;
+}
+
+lnkText: #0f7dc7;
+
+labelDefFlat: flatLabel {
+ font: font(14px);
+ minWidth: 100px;
+ width: 0px;
+ align: align(left);
+}
+
+introSkip: 20px;
+introFinishSkip: 15px;
+introHeaderFont: font(28px);
+introHeaderSkip: 14px;
+introFont: font(17px);
+introVersionFont: introFont;
+introVersionColor: #9b9b9b;
+introVersionSkip: 10px;
+intro2Skip: 60px;
+intro1Skip: 14px;
+introColor: black;
+
+introLabel: flatLabel(labelDefFlat) {
+ font: introFont;
+}
+
+introPointsTop: -30px; // intro steps bottom points
+introPointWidth: 4px;
+introPointHeight: 4px;
+introPointHoverWidth: 10px;
+introPointHoverHeight: 10px;
+introPointLeft: 3px;
+introPointTop: 3px;
+introPointDelta: 10px;
+introPointColor: rgb(0, 0, 0);
+introPointAlpha: 0.5;
+introPointHoverColor: rgb(47, 158, 218);
+introPointHoverAlpha: 0.5;
+introPointStepT: transition(sineInOut);
+introPointAlphaT: transition(linear);
+introPointShowStepT: transition(easeOutCirc);
+introPointHideStepT: transition(easeInCirc);
+introPointShowAlphaT: transition(easeInCirc);
+introPointHideAlphaT: transition(easeOutCirc);
+
+introStepSize: size(400px, 200px);
+introSize: size(400px, 400px);
+introSlideShift: 500px; // intro hiding animation
+introSlideDuration: 200;
+introSlideDelta: 0; // between hide start and show start
+introHideFunc: transition(easeInCirc);
+introShowFunc: transition(easeOutCirc);
+introAlphaHideFunc: transition(easeOutCirc);
+introAlphaShowFunc: transition(easeInCirc);
+introTextSize: size(400px, 97px);
+
+introTitleFont: font(24px);
+introDescFont: font(18px);
+
+btnIntroSep: 12px;
+btnIntroNext: flatButton(btnDefNext, btnDefBig) {
+ width: 144px;
+}
+btnIntroBack: flatButton(btnIntroNext, btnDefBack) {
+}
+
+btnIntroStart: flatButton(btnIntroNext) {
+ width: 300px;
+}
+btnIntroFinish: flatButton(btnIntroNext) {
+ width: 240px;
+}
+
+boxShadow: sprite(240px, 21px, 9px, 9px);
+
+introCountry: countryInput {
+ width: 300px;
+ height: 41px;
+ top: 24px;
+ bgColor: #ebebeb;
+ ptrSize: size(15px, 8px);
+ textMrg: margins(16px, 5px, 16px, 15px);
+ font: inpDefFont;
+ align: align(left);
+}
+
+introPhoneTop: 8px;
+inpIntroCountryCode: flatInput(inpDefGray) {
+ width: 70px;
+ height: 41px;
+ align: align(center);
+}
+inpIntroPhone: flatInput(inpDefGray) {
+ textMrg: margins(12px, 5px, 12px, 6px);
+ width: 225px;
+ height: 41px;
+}
+inpIntroCode: flatInput(inpDefGray) {
+ textMrg: margins(12px, 5px, 12px, 6px);
+ width: 106px;
+ height: 41px;
+
+ phPos: point(0px, 0px);
+ phAlign: align(center);
+ phShift: 0px;
+}
+inpIntroName: flatInput(inpIntroPhone) {
+ width: 240px;
+}
+
+introSelectDelta: 30px;
+introSelectMaxHeight: 550px;
+btnSelectDone: flatButton(btnDefFlat) {
+ color: btnYesColor;
+ overColor: btnYesHover;
+ downColor: btnYesHover;
+
+ bgColor: white;
+ overBgColor: btnBoxWhiteHover;
+ downBgColor: btnBoxWhiteHover;
+
+ width: 182px;
+ height: 52px;
+
+ textTop: 14px;
+ overTextTop: 14px;
+ downTextTop: 15px;
+
+ font: font(17px);
+ overFont: font(17px);
+}
+btnSelectCancel: flatButton(btnSelectDone) {
+ width: 181px;
+ color: btnNoColor;
+ overColor: btnNoHover;
+ downColor: btnNoHover;
+}
+btnSelectSep: #e0e0e0;
+
+countryList: countryList {
+ notFoundColor: #aaa;//rgb(20, 136, 210);
+ notFoundFont: font(18px);
+
+ verticalMargin: 0px;
+
+ font: font(18px);
+ codeFont: font(16px);
+ rowHeight: 42px;
+ color: #000;
+ codeColor: #aaaaaa;//rgb(20, 136, 210);
+ bgColor: #FFF;
+ bgHovered: #f1f1f1;
+ margin: 13px;
+ codeWidth: 60px;
+
+ borderMargin: 0px;
+ borderColor: rgba(228, 233, 240, 127);
+ borderWidth: 0px;
+}
+
+countriesSlideShift: 500px;
+countriesSlideDuration: 200;
+countriesHideFunc: transition(easeInCirc);
+countriesShowFunc: transition(easeOutCirc);
+countriesBackHideFunc: transition(linear);
+countriesBackShowFunc: transition(linear);
+countriesAlphaHideFunc: transition(easeOutCirc);
+countriesAlphaShowFunc: transition(easeInCirc);
+
+introBtnTop: 244px;
+
+introErrWidth: 450px;
+introErrDuration: 200;
+introErrFunc: transition(linear);
+introErrBG: #ffa5a5;
+introErrColor: black;//#800000;
+introErrTop: 15px;
+introErrHeight: 40px;
+introErrFont: font(16px);
+
+introErrLabel: flatLabel(labelDefFlat) {
+ font: introErrFont;
+}
+
+setWidth: 356px;
+setTop: 26px;
+setNameLeft: 3px;
+setNameTop: 0px;
+setNameFont: font(23px);
+setPhoneFont: font(16px);
+setPhoneColor: #999;
+setPhoneTop: 38px;
+setPhoneLeft: 1px;
+setPhotoSize: 120px;
+setHeaderFont: font(20px);
+setHeaderColor: black;
+setHeaderSkip: 59px;
+setHeaderLeft: -1px;
+setHeaderTop: 21px;
+setLittleSkip: 9px;
+setSectionSkip: 25px;
+setVersionHeight: 41px;
+setVersionLeft: 36px;
+setVersionTop: 2px;
+setVersionColor: #999;
+setBottom: 130px;
+setScroll: flatScroll(scrollDef) {
+ bottomsh: 0px;
+ topsh: 0px;
+}
+setClose: iconedButton(btnDefIconed) {
+ icon: sprite(245px, 221px, 43px, 43px);
+ iconPos: point(0px, 0px);
+ downIcon: sprite(245px, 221px, 43px, 43px);
+ downIconPos: point(0px, 0px);
+
+ width: 43px;
+ height: 43px;
+}
+setClosePos: point(18px, 18px);
+setPhotoImg: sprite(0px, 220px, 120px, 120px);
+setOverPhotoImg: sprite(122px, 220px, 120px, 120px);
+setPhotoDuration: 150;
+
+setPadding: 26px;
+setBG: #FFF;
+setSh: #000;
+setTitleFrom: point(20px, 20px);
+setTitleFont: font(24px);
+setTitleColor: #000;
+setNameInput: flatInput(inpDefFlat) {
+ font: font(14px);
+ height: 25px;
+ width: 170px;
+ textMrg: margins(3px, 3px, 3px, 3px);
+}
+setErrBG: #ffa5a5;
+setErrColor: #800000;
+setErrHeight: 30px;
+setErrFont: font(14px);
+
+btnSetUpload: flatButton(btnDefNext, btnDefBig) {
+ width: 206px;
+ height: 42px;
+ font: font(18px);
+ overFont: font(18px);
+
+ textTop: 9px;
+ overTextTop: 9px;
+ downTextTop: 10px;
+}
+
+btnEditSave: flatButton(btnSetUpload) {
+ width: 115px;
+}
+btnEditCancel: flatButton(btnDefFlat, btnDefBig) {
+ color: #666d78;
+ overColor: #666d78;
+ downColor: #50565e;
+
+ bgColor: rgba(0, 0, 0, 63);
+ overBgColor: rgba(0, 0, 0, 47);
+ downBgColor: rgba(0, 0, 0, 95);
+
+ width: 115px;
+ height: 40px;
+
+ textTop: 9px;
+ overTextTop: 9px;
+ downTextTop: 10px;
+
+ font: font(18px);
+ overFont: font(18px);
+}
+
+btnLogout: flatButton(btnDefFlat, btnDefBig) {
+ color: white;
+ overColor: white;
+ downColor: white;
+
+ bgColor: #db6352;
+ overBgColor: #d15948;
+ downBgColor: #c74d3b;
+
+ width: 148px;
+ height: 42px;
+
+ textTop: 8px;
+ overTextTop: 8px;
+ downTextTop: 9px;
+
+ font: font(18px);
+ overFont: font(18px);
+}
+
+//// dialogs
+dlgFilterPadding: 10px;
+dlgPhotoSize: 46px;
+dlgPaddingHor: 10px;
+dlgPaddingVer: 8px;
+dlgHeight: 62px;
+dlgPhotoPadding: 12px;
+
+dlgSep: 6px;
+
+dlgShadowColor: rgba(0, 0, 0, 24);//#ebebeb
+dlgShadow: 1px;
+
+dlgMinWidth: 260px;
+dlgRichMinWidth: 150px;
+dlgMaxWidth: 540px;
+dlgFilter: flatInput(inpDefGray) {
+ font: font(14px);
+ height: 34px;
+ bgColor: #f2f2f2;
+ phColor: #949494;
+ phFocusColor: #a4a4a4;
+ textMrg: margins(34px, 2px, 5px, 4px);
+ imgRect: sprite(208px, 28px, 24px, 24px);
+ imgPos: point(6px, 5px);
+ width: 240px;
+
+ borderWidth: 2px;
+ borderColor: #f2f2f2;
+ borderActive: #80cff9;
+ borderError: #ed8080;
+}
+dlgScroll: flatScroll(scrollDef) {
+ topsh: 0px;
+ bottomsh: 0px;
+}
+dlgFont: font(14px);
+
+dlgDblCheckImg: sprite(302px, 23px, 17px, 11px);
+dlgCheckImg: sprite(320px, 23px, 17px, 11px);
+dlgActiveDblCheckImg: sprite(302px, 36px, 17px, 11px);
+dlgActiveCheckImg: sprite(320px, 36px, 17px, 11px);
+dlgSendImg: sprite(122px, 25px, 17px, 11px);
+dlgActiveSendImg: sprite(142px, 25px, 17px, 11px);
+dlgChatImg: sprite(302px, 51px, 16px, 11px);
+dlgActiveChatImg: sprite(322px, 51px, 16px, 11px);
+
+dlgChatImgLeft: 1px;
+dlgChatImgTop: 5px;
+dlgChatImgSkip: 22px;
+
+dlgCheckLeft: 5px;
+dlgCheckTop: 5px;
+dlgCheckSkip: 3px;
+
+dlgFromFont: font(12px bold);
+dlgFromColor: #4981af;
+
+dlgHistFont: font(14px);
+dlgNameColor: #000;
+dlgNameTop: 1px;
+dlgSystemColor: #4981af;
+dlgTextColor: #888888;
+
+dlgDateFont: font(13px);
+dlgDateColor: #a8a8a8;
+dlgDateSkip: 5px;
+
+dlgUnreadColor: #FFF;
+dlgUnreadBG: #6fc766;
+dlgUnreadFont: font(12px bold);
+dlgUnreadPaddingHor: 5px;
+dlgUnreadPaddingVer: 1px;
+dlgUnreadRadius: 2px;
+dlgBG: #FFF;
+dlgHoverBG: #f5f5f5;
+
+dlgActiveBG: #6a91b1;
+dlgActiveUnreadColor: #5b94bf;
+dlgActiveUnreadBG: white;
+dlgActiveColor: white;
+dlgActiveDateColor: #d3e2ee;
+
+topBarHeight: 54px;
+topBarBG: white;
+topBarDuration: 200;
+topBarForwardPadding: margins(17px, 7px, 40px, 8px);
+topBarForwardAlpha: 0.6;
+topBarForwardImg: sprite(45px, 112px, 9px, 16px);
+topBarBackPadding: margins(15px, 7px, 9px, 7px);
+topBarBackAlpha: 0.8;
+topBarBackImg: sprite(65px, 112px, 9px, 16px);
+topBarBackColor: #005faf;
+topBarBackFont: font(16px);
+topBarButton: flatButton(btnDefFlat) {
+ color: btnYesColor;
+ overColor: btnYesHover;
+ downColor: btnYesHover;
+
+ bgColor: white;
+ overBgColor: white;
+ downBgColor: white;
+
+ width: -40px;
+ height: 54px;
+
+ textTop: 18px;
+ overTextTop: 18px;
+ downTextTop: 19px;
+
+ font: font(14px);
+ overFont: font(14px underline);
+}
+topBarActionButton: flatButton(btnDefNext, btnDefBig) {
+ textTop: 8px;
+ overTextTop: 8px;
+ downTextTop: 9px;
+
+ font: font(14px);
+ overFont: font(14px);
+ width: 101px;
+ height: 34px;
+}
+topBarActionSkip: 13px;
+topBarSelectedPos: point(18px, 18px);
+
+historyBG: #dfe4e8;
+msgMaxWidth: 550px;
+msgFont: font(14px);
+msgNameFont: font(14px semibold);
+msgServiceFont: font(14px semibold);
+msgServiceNameFont: font(14px semibold);
+msgDateFont: font(13px);
+msgMinWidth: 190px;
+msgPhotoSize: 30px;
+msgPhotoSkip: 40px;
+msgPadding: margins(13px, 7px, 13px, 8px);
+msgMargin: margins(13px, 4px, 53px, 4px);
+msgLnkPadding: 2px; // for media open / save links
+msgBorder: #f0f0f0;
+msgOutBG: #effdde;
+msgInBG: #fff;
+msgOutSelectBG: #b7dbdb;
+msgInSelectBG: #c2dcf2; // #358cd4 with 30% opacity
+msgOutSelectOverlay: #358cd44c;
+msgInSelectOverlay: #358cd44c;
+msgOutServiceColor: #3a8e26;
+msgInServiceColor: #0e7acd;
+msgShadow: 2px;
+msgInShadow: #748ea229;
+msgOutShadow: #3ac34740;
+msgInSelectShadow: #548dbb29;
+msgOutSelectShadow: #37a78e40;
+msgInDateColor: #a0acb6;
+msgOutDateColor: #6cc264;
+msgInSelectDateColor: #6a9cc5;
+msgOutSelectDateColor: #50a79c;
+
+msgServiceSelectBG: #fff4;
+msgServiceRadius: 2px;
+
+msgServiceBG: #89a0b47f;
+msgServiceColor: #FFF;
+msgServicePadding: margins(12px, 3px, 12px, 4px);
+msgServiceMargin: margins(10px, 7px, 80px, 7px);
+
+msgColor: #000;
+msgDateColor: #000;
+msgLinkColor: #2a6dc2;
+msgPressedLinkColor: #004bad;
+msgSkip: 40px;
+msgPtr: 8px;
+msgBG: ':/gui/art/bg.png' / 2:':/gui/art/bg_125x.png' / 3:':/gui/art/bg_150x.png' / 4:':/gui/art/bg_200x.png';
+
+msgSendingRect: sprite(260px, 20px, 20px, 20px);
+msgCheckRect: sprite(320px, 0px, 20px, 20px);
+msgDblCheckRect: sprite(300px, 0px, 20px, 20px);
+msgSelectCheckRect: sprite(160px, 0px, 20px, 20px);
+msgSelectDblCheckRect: sprite(140px, 0px, 20px, 20px);
+msgDateSpace: 19px;
+msgDateCheckSpace: 4px;
+msgDateDelta: point(2px, 5px);
+
+msgImgSendingRect: sprite(280px, 40px, 20px, 20px);
+msgImgCheckRect: sprite(280px, 20px, 20px, 20px);
+msgImgDblCheckRect: sprite(260px, 40px, 20px, 20px);
+msgDateImgDelta: 4px;
+msgDateImgColor: #fff;
+msgDateImgBg: #00000054;
+msgDateImgPadding: point(8px, 2px);
+msgDateImgCheckSpace: 4px;
+
+msgDogImg: sprite(213px, 93px, 126px, 126px);
+historyPadding: 10px;
+
+defaultTextStyle: textStyle {
+ lnkFlags: font(14px);
+ lnkOverFlags: font(14px underline);
+ lnkColor: btnYesColor;
+ lnkDownColor: btnYesHover;
+ selectBG: msgInSelectBG;
+ selectOverlay: msgInSelectOverlay;
+ lineHeight: 0px;
+}
+serviceTextStyle: textStyle(defaultTextStyle) {
+ lnkColor: msgServiceColor;
+ lnkDownColor: msgServiceColor;
+ selectBG: msgServiceSelectBG;
+ selectOverlay: msgServiceSelectBG;
+}
+inTextStyle: textStyle(defaultTextStyle) {
+ selectBG: msgInSelectBG;
+ selectOverlay: msgInSelectOverlay;
+}
+outTextStyle: textStyle(defaultTextStyle) {
+ selectBG: msgOutSelectBG;
+ selectOverlay: msgOutSelectOverlay;
+}
+
+dlgTextStyle: textStyle(defaultTextStyle) {
+ lnkColor: dlgSystemColor;
+ lnkDownColor: dlgSystemColor;
+ lnkOverFlags: font(14px);
+}
+dlgActiveTextStyle: textStyle(defaultTextStyle) {
+ lnkColor: dlgActiveColor;
+ lnkDownColor: dlgActiveColor;
+ lnkOverFlags: font(14px);
+}
+
+mediaMaxWidth: 250px;
+mediaFont: font(14px);
+mediaPadding: margins(7px, 6px, 11px, 6px);
+mediaThumbSize: 48px;
+mediaDocOutImg: sprite(6px, 146px, 48px, 48px);
+mediaDocInImg: sprite(56px, 146px, 48px, 48px);
+mediaAudioOutImg: sprite(106px, 146px, 48px, 48px);
+mediaAudioInImg: sprite(156px, 146px, 48px, 48px);
+mediaInColor: msgInDateColor;
+mediaOutColor: msgOutDateColor;
+mediaInSelectColor: msgInSelectDateColor;
+mediaOutSelectColor: msgOutSelectDateColor;
+mediaSaveDelta: 14px; // between bubble and download
+mediaSaveButton: flatButton(btnDefFlat) {
+ color: btnYesColor;
+ overColor: btnYesHover;
+ downColor: btnYesHover;
+
+ bgColor: white;
+ overBgColor: btnWhiteHover;
+ downBgColor: btnWhiteHover;
+
+ width: -28px;
+ height: 34px;
+
+ textTop: 7px;
+ overTextTop: 7px;
+ downTextTop: 8px;
+
+ font: font(14px);
+ overFont: font(14px);
+}
+
+sendPadding: 8px;
+btnSend: flatButton(btnDefFlat) {
+ color: btnYesColor;
+ overColor: btnYesHover;
+ downColor: btnYesHover;
+
+ bgColor: white;
+ overBgColor: btnWhiteHover;
+ downBgColor: btnWhiteHover;
+
+ width: -32px;
+ height: 46px;
+
+ textTop: 13px;
+ overTextTop: 13px;
+ downTextTop: 14px;
+
+ font: font(16px);
+ overFont: font(16px);
+}
+
+btnAttachDocument: iconedButton(btnDefIconed) {
+ icon: sprite(218px, 68px, 24px, 24px);
+ iconPos: point(11px, 11px);
+ downIcon: sprite(218px, 68px, 24px, 24px);
+ downIconPos: point(11px, 12px);
+
+ overBgColor: btnWhiteHover;
+ width: 46px;
+ height: 46px;
+}
+btnAttachPhoto: iconedButton(btnAttachDocument) {
+ icon: sprite(278px, 68px, 24px, 24px);
+ downIcon: sprite(278px, 68px, 24px, 24px);
+}
+btnAttachEmoji: iconedButton(btnAttachDocument) {
+ overBgColor: white;
+ icon: sprite(311px, 221px, 20px, 20px);
+ iconPos: point(6px, 13px);
+ downIcon: sprite(311px, 221px, 20px, 20px);
+ downIconPos: point(6px, 13px);
+
+ width: 32px;
+}
+
+historyScroll: flatScroll(scrollDef) {
+ barColor: #89a0b47a;
+ bgColor: #89a0b44c;
+ barOverColor: #89a0b4bc;
+ bgOverColor: #89a0b46b;
+
+ round: 2px;
+
+ width: 12px;
+ deltax: 3px;
+ deltay: 3px;
+
+ topsh: 0px;
+ bottomsh: -1px;
+}
+textRectMargins: margins(-2px, -1px, -2px, -1px);
+taMsgField: flatTextarea(taDefFlat) {
+ font: msgFont;
+}
+maxFieldHeight: 250px;
+minFieldHeight: 30px;
+
+newMsgSound: ':/gui/art/newmsg.wav';
+
+unreadBarHeight: 32px;
+unreadBarFont: font(14px semibold);
+unreadBarBG: #fcfbfa;
+unreadBarBorder: titleShadowColor;
+unreadBarColor: #538bb4;
+
+layerSlideDuration: 200;
+layerHideDuration: 200;
+layerPadding: margins(10px, 10px, 10px, 10px);
+
+boxFont: font(16px);
+boxPadding: margins(18px, 18px, 18px, 18px);
+boxBG: white;//rgb(228, 233, 240);
+boxGrayTitle: #777;
+
+confirmWidth: 364px;
+addContactWidth: 364px;
+addContactPadding: margins(18px, 24px, 18px, 24px);
+addContactDelta: 14px;
+addContactTitleHeight: 52px;
+addContactTitlePos: point(20px, 15px);
+addContactTitleFont: font(17px);
+inpAddContact: flatInput(inpDefGray) {
+ height: 42px;
+ textMrg: margins(10px, 5px, 10px, 5px);
+ font: font(15px);
+}
+
+btnNewGroup: iconedButton(btnDefIconed) {
+ icon: sprite(189px, 118px, 18px, 17px);
+ iconPos: point(8px, 8px);
+ downIcon: sprite(189px, 118px, 18px, 17px);
+ downIconPos: point(8px, 9px);
+
+ bgColor: transparent;
+ overBgColor: transparent;
+ width: 36px;
+ height: 36px;
+}
+btnAddContact: iconedButton(btnNewGroup) {
+ icon: sprite(188px, 93px, 18px, 18px);
+ downIcon: sprite(188px, 93px, 18px, 18px);
+}
+
+notifyBG: white;
+notifyBorder: #f1f1f1;
+notifySlowHide: 4000;
+notifyPhotoSize: 62px;
+notifyPhotoPos: point(9px, 9px);
+notifyClosePos: point(1px, 2px);
+notifyClose: iconedButton(btnDefIconed) {
+ icon: sprite(167px, 130px, 10px, 10px);
+ iconPos: point(10px, 10px);
+ downIcon: sprite(167px, 130px, 10px, 10px);
+ downIconPos: point(10px, 11px);
+
+ width: 30px;
+ height: 30px;
+}
+notifyItemTop: 12px;
+notifyTextLeft: 12px;
+notifyTextTop: 7px;
+notifySlowHideFunc: transition(easeInCirc);
+notifyWaitShortHide: 0;
+notifyWaitLongHide: 20000;
+notifyFastAnim: 100;
+notifyFastAnimFunc: transition(linear);
+notifyWidth: 316px;
+notifyHeight: 80px;
+notifyDeltaX: 6px;
+notifyDeltaY: 7px;
+
+cropBoxWidth: 364px;
+cropPointSize: 10px;
+cropMinSize: 20px;
+
+profileMaxWidth: 410px;
+profilePadding: margins(28px, 30px, 28px, 0px);
+profilePhotoSize: 120px;
+profileNameLeft: 21px;
+profileNameTop: -2px;
+profileNameFont: font(20px);
+profileStatusLeft: 22px;
+profileStatusTop: 30px;
+profileStatusFont: font(14px);
+profilePhoneLeft: 20px;
+profilePhoneTop: 62px;
+profilePhoneFont: font(16px);
+profileButtonTop: 18px;
+profileButtonSkip: 10px;
+profileHeaderFont: font(20px);
+profileHeaderColor: black;
+profileHeaderSkip: 59px;
+profileHeaderLeft: -1px;
+profileHeaderTop: 21px;
+
+profileListPhotoSize: 46px;
+profileListPadding: size(12px, 6px);
+profileListNameTop: 7px;
+profileListStatusBottom: 6px;
+profileHoverBG: #f1f1f1;
+profileActiveBG: #6294b9;
+profileSubFont: font(14px);
+profileCheckRect: sprite(88px, 108px, 24px, 24px);
+profileCheckActiveRect: sprite(128px, 108px, 24px, 24px);
+profileCheckDeltaX: 18px;
+profileCheckDeltaY: 1px;
+profileListNameFont: font(14px semibold);
+profileListNameColor: #000;
+profileOnlineColor: titleTypingColor;
+profileOfflineColor: titleStatusColor;
+btnShareContact: flatButton(btnDefNext, btnDefBig) {
+ width: 145px;
+ height: 42px;
+
+ textTop: 9px;
+ overTextTop: 9px;
+ downTextTop: 10px;
+
+ font: font(17px);
+ overFont: font(17px);
+}
+
+forwardWidth: 364px;
+forwardRadius: 2px;
+forwardMargins: margins(30px, 10px, 30px, 10px);
+forwardFont: font(16px);
+forwardBG: rgba(0, 0, 0, 76);
+btnProfileCancel: flatButton(btnDefFlat, btnDefBig) {
+ color: #666d78;
+ overColor: #666d78;
+ downColor: #50565e;
+
+ bgColor: rgba(0, 0, 0, 63);
+ overBgColor: rgba(0, 0, 0, 47);
+ downBgColor: rgba(0, 0, 0, 95);
+
+ width: 145px;
+ height: 40px;
+
+ textTop: 9px;
+ overTextTop: 9px;
+ downTextTop: 10px;
+
+ font: font(18px);
+ overFont: font(18px);
+}
+
+btnDeleteContact: flatButton(btnDefFlat, btnDefBig) {
+ color: #fff;
+ overColor: #fff;
+ downColor: #ffcbc1;
+
+ bgColor: #ee4928bf;
+ overBgColor: #ee4928;
+ downBgColor: #d14024;
+
+ width: 300px;
+ height: 40px;
+
+ textTop: 9px;
+ overTextTop: 9px;
+ downTextTop: 10px;
+
+ font: font(18px);
+ overFont: font(18px);
+}
+
+profileNameInput: flatInput(setNameInput) {
+ width: 230px;
+}
+
+newGroupScroll: flatScroll(scrollDef) {
+ topsh: 0px;
+ bottomsh: -2px;
+}
+
+participantInnerAdd: flatButton(btnDefNext) {
+ width: 145px;
+ height: 40px;
+ font: font(18px);
+ overFont: font(18px);
+ textTop: 9px;
+ overTextTop: 9px;
+ downTextTop: 10px;
+}
+participantInnerCancel: flatButton(participantInnerAdd, btnDefBack) {
+}
+participantCancel: flatButton(participantInnerAdd, btnDefBack) {
+ width: 300px;
+}
+participantWidth: 364px;
+participantMaxHeight: 600px;
+participantFilter: flatInput(inpDefFlat) {
+ width: 364px;
+ height: 52px;
+ font: font(16px);
+ textMrg: margins(39px, 11px, 10px, 10px);
+ imgRect: sprite(208px, 28px, 24px, 24px);
+ imgPos: point(10px, 15px);
+}
+participantDelta: 12px;
+
+contactsFilter: flatInput(dlgFilter) {
+ width: 340px;
+ height: 38px;
+ textMrg: margins(34px, 3px, 5px, 4px);
+ imgPos: point(6px, 7px);
+}
+newGroupName: flatInput(inpDefGray) {
+ width: 340px;
+ height: 44px;
+ font: font(15px);
+ textMrg: margins(12px, 5px, 12px, 5px);
+}
+inpCountry: flatInput(contactsFilter) {
+}
+newGroupNamePadding: margins(12px, 15px, 12px, 13px);
+
+connectionSkip: 20px;
+inpConnectionHost: flatInput(inpDefGray) {
+ font: font(14px);
+ height: 34px;
+ bgColor: #f2f2f2;
+ phColor: #949494;
+ phFocusColor: #a4a4a4;
+ textMrg: margins(4px, 2px, 5px, 4px);
+ width: 205px;
+
+ borderWidth: 2px;
+ borderColor: #f2f2f2;
+ borderActive: #80cff9;
+ borderError: #ed8080;
+}
+inpConnectionPort: flatInput(inpConnectionHost) {
+ width: 80px;
+}
+inpConnectionUser: flatInput(inpConnectionHost) {
+ width: 130px;
+}
+inpConnectionPassword: flatInput(inpConnectionHost) {
+ width: 155px;
+}
+
+contactsClose: flatButton {
+ color: btnYesColor;
+ overColor: btnYesHover;
+ downColor: btnYesHover;
+
+ bgColor: #fffe;
+ overBgColor: white;
+ downBgColor: white;
+
+ width: 364px;
+ height: 46px;
+
+ textTop: 12px;
+ overTextTop: 12px;
+ downTextTop: 13px;
+
+ font: font(16px);
+ overFont: font(16px);
+}
+contactsImg: sprite(45px, 112px, 9px, 16px);
+contactsAdd: flatButton(topBarButton) {
+ width: -40px;
+ height: 52px;
+
+ textTop: 18px;
+ overTextTop: 18px;
+ downTextTop: 19px;
+}
+
+aboutIcon: sprite(2px, 2px, 104px, 104px);
+aboutIconTop: 28px;
+aboutWidth: 448px;
+aboutHeight: 441px;
+aboutHeaderFont: font(24px semibold);
+aboutSubheaderFont: font(24px);
+aboutHeaderTop: 139px;
+aboutVersionFont: font(16px);
+aboutVersionColor: #999;
+aboutVersionTop: 178px;
+aboutTextFont: font(15px);
+aboutTextTop: 221px;
+aboutLabel: flatLabel(labelDefFlat) {
+ font: aboutTextFont;
+ width: aboutWidth;
+ align: align(center);
+}
+aboutTextStyle: textStyle(defaultTextStyle) {
+ lineHeight: 24px;
+}
+aboutCloseButton: flatButton(contactsClose) {
+ width: aboutWidth;
+ height: 52px;
+ textTop: 15px;
+ overTextTop: 15px;
+ downTextTop: 16px;
+}
+
+emojiTextFont: font(16px);
+emojiReplaceWidth: 56px;
+emojiReplaceHeight: 56px;
+emojiReplaceInnerHeight: 38px;
+
+connectingBG: #fffe;
+connectingColor: #777;
+connectingPadding: margins(5px, 5px, 5px, 5px);
+
+dropdownPadding: margins(10px, 10px, 10px, 10px);
+dropdownShadow: sprite(240px, 35px, 6px, 6px);
+dropdownBorder: 1px;
+dropdownBorderColor: #ebebeb;
+dropdownBackground: white;
+
+dropdownAttachDocument: iconedButton(btnAttachDocument) {
+ iconPos: point(14px, 13px);
+ downIconPos: point(14px, 14px);
+
+ width: 172px;
+ height: 49px;
+
+ color: black;
+
+ font: font(16px);
+
+ textPos: point(50px, 13px);
+ downTextPos: point(50px, 14px);
+}
+dropdownAttachPhoto: iconedButton(dropdownAttachDocument) {
+ icon: sprite(278px, 68px, 24px, 24px);
+ downIcon: sprite(278px, 68px, 24px, 24px);
+}
+
+dragFont: font(28px semibold);
+dragSubfont: font(20px semibold);
+dragColor: #777;
+dragDropColor: btnYesColor;
+
+dragMargin: margins(0px, 10px, 0px, 10px);
+dragPadding: margins(20px, 10px, 20px, 10px);
+
+dragHeight: 72px;
+
+selectedFont: font(14px);
+selectedColor: #777;
+selectedTop: 14px;
+
+downloadSkip: 20px;
+inpDownloadDir: flatInput(inpDefGray) {
+ font: font(14px);
+ height: 34px;
+ bgColor: #fff;
+ textMrg: margins(5px, 2px, 5px, 4px);
+ width: 295px;
+
+ borderWidth: 2px;
+ borderColor: #f2f2f2;
+}
+
+dpiSlider: slider {
+ color: #ccc;
+ thikness: 2px;
+
+ width: 260px;
+ bar: sprite(6px, 110px, 9px, 22px);
+}
+dpiActive: black;
+dpiInactive: #999;
+dpiFont1: linkFont;
+dpiFont2: linkFont;
+dpiFont3: linkFont;
+dpiFont4: linkFont;
+
+emojiScroll: flatScroll(scrollDef) {
+ topsh: 0px;
+ bottomsh: 0px;
+}
+emojiRecentActive: sprite(290px, 287px, 20px, 20px);
+emojiRecentOver: sprite(311px, 287px, 20px, 20px);
+emojiRecent: sprite(6px, 197px, 20px, 20px);
+emojiPeopleActive: sprite(290px, 221px, 20px, 20px);
+emojiPeopleOver: sprite(311px, 221px, 20px, 20px);
+emojiPeople: sprite(27px, 197px, 20px, 20px);
+emojiNatureActive: sprite(245px, 266px, 20px, 20px);
+emojiNatureOver: sprite(266px, 266px, 20px, 20px);
+emojiNature: sprite(48px, 197px, 20px, 20px);
+emojiObjectsActive: sprite(290px, 242px, 20px, 20px);
+emojiObjectsOver: sprite(311px, 242px, 20px, 20px);
+emojiObjects: sprite(69px, 197px, 20px, 20px);
+emojiPlacesActive: sprite(245px, 287px, 20px, 20px);
+emojiPlacesOver: sprite(266px, 287px, 20px, 20px);
+emojiPlaces: sprite(90px, 197px, 20px, 20px);
+emojiSymbolsActive: sprite(290px, 266px, 20px, 20px);
+emojiSymbolsOver: sprite(311px, 266px, 20px, 20px);
+emojiSymbols: sprite(111px, 197px, 20px, 20px);
+rbEmoji: flatCheckbox {
+ textColor: transparent;
+ bgColor: transparent;
+ disColor: transparent;
+
+ width: 36px;
+ height: 36px;
+
+ textTop: 0px;
+ textLeft: 0px;
+ font: font(14px);
+ duration: 200;
+ bgFunc: transition(easeOutCirc);
+ cursor: cursor(pointer);
+
+ disabledCursor: cursor(default);
+ imagePos: point(8px, 8px);
+}
+rbEmojiRecent: flatCheckbox(rbEmoji) {
+ imageRect: emojiRecent;
+ chkImageRect: emojiRecentActive;
+ overImageRect: emojiRecentOver;
+ chkOverImageRect: emojiRecentActive;
+ disImageRect: emojiRecent;
+ chkDisImageRect: emojiRecentActive;
+}
+rbEmojiPeople: flatCheckbox(rbEmoji) {
+ imageRect: emojiPeople;
+ chkImageRect: emojiPeopleActive;
+ overImageRect: emojiPeopleOver;
+ chkOverImageRect: emojiPeopleActive;
+ disImageRect: emojiPeople;
+ chkDisImageRect: emojiPeopleActive;
+}
+rbEmojiNature: flatCheckbox(rbEmoji) {
+ imageRect: emojiNature;
+ chkImageRect: emojiNatureActive;
+ overImageRect: emojiNatureOver;
+ chkOverImageRect: emojiNatureActive;
+ disImageRect: emojiNature;
+ chkDisImageRect: emojiNatureActive;
+}
+rbEmojiObjects: flatCheckbox(rbEmoji) {
+ imageRect: emojiObjects;
+ chkImageRect: emojiObjectsActive;
+ overImageRect: emojiObjectsOver;
+ chkOverImageRect: emojiObjectsActive;
+ disImageRect: emojiObjects;
+ chkDisImageRect: emojiObjectsActive;
+}
+rbEmojiPlaces: flatCheckbox(rbEmoji) {
+ imageRect: emojiPlaces;
+ chkImageRect: emojiPlacesActive;
+ overImageRect: emojiPlacesOver;
+ chkOverImageRect: emojiPlacesActive;
+ disImageRect: emojiPlaces;
+ chkDisImageRect: emojiPlacesActive;
+}
+rbEmojiSymbols: flatCheckbox(rbEmoji) {
+ imageRect: emojiSymbols;
+ chkImageRect: emojiSymbolsActive;
+ overImageRect: emojiSymbolsOver;
+ chkOverImageRect: emojiSymbolsActive;
+ disImageRect: emojiSymbols;
+ chkDisImageRect: emojiSymbolsActive;
+}
+emojiPanPadding: margins(10px, 5px, 0px, 5px);
+emojiPanSize: size(28px, 28px);
+emojiPanFont: font(14px);
+emojiPanText: #999;
+emojiPanSub: 0px;
+emojiPanDuration: 200;
+emojiPanHover: #f0f0f0;
+emojiPanRound: 2px;
diff --git a/Telegram/Resources/style_classes.txt b/Telegram/Resources/style_classes.txt
new file mode 100644
index 000000000..568e08ace
--- /dev/null
+++ b/Telegram/Resources/style_classes.txt
@@ -0,0 +1,231 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+textStyle {
+ lnkFlags: font;
+ lnkOverFlags: font;
+ lnkColor: color;
+ lnkDownColor: color;
+ selectBG: color;
+ selectOverlay: color;
+ lineHeight: number;
+}
+
+linkButton {
+ color: color;
+ overColor: color;
+ downColor: color;
+ font: font;
+ overFont: font;
+}
+
+sysButton {
+ size: size;
+ img: sprite;
+ color: color;
+ overColor: color;
+ duration: number;
+}
+
+flatButton {
+ color: color;
+ overColor: color;
+ downColor: color;
+
+ bgColor: color;
+ overBgColor: color;
+ downBgColor: color;
+
+ width: number;
+ height: number;
+
+ textTop: number;
+ overTextTop: number;
+ downTextTop: number;
+
+ font: font;
+ overFont: font;
+ duration: number;
+ cursor: cursor;
+}
+
+iconedButton {
+ icon: sprite;
+ iconPos: point;
+ downIcon: sprite;
+ downIconPos: point;
+
+ color: color;
+ bgColor: color;
+ overBgColor: color;
+ width: number;
+ height: number;
+ font: font;
+
+ opacity: number;
+ overOpacity: number;
+
+ textPos: point;
+ downTextPos: point;
+
+ duration: number;
+ cursor: cursor;
+}
+
+flatCheckbox {
+ textColor: color;
+ bgColor: color;
+ disColor: color;
+
+ width: number;
+ height: number;
+ textTop: number;
+ textLeft: number;
+ font: font;
+ duration: number;
+ bgFunc: transition;
+ cursor: cursor;
+
+ disabledCursor: cursor;
+
+ imageRect: sprite;
+ chkImageRect: sprite;
+ overImageRect: sprite;
+ chkOverImageRect: sprite;
+ disImageRect: sprite;
+ chkDisImageRect: sprite;
+
+ imagePos: point;
+}
+
+flatInput {
+ textColor: color;
+ bgColor: color;
+ bgActive: color;
+ width: number;
+ height: number;
+ textMrg: margins;
+ align: align;
+ font: font;
+ cursor: cursor;
+
+ imgRect: sprite;
+ imgPos: point;
+
+ borderWidth: number;
+ borderColor: color;
+ borderActive: color;
+ borderError: color;
+
+ phColor: color;
+ phFocusColor: color;
+ phPos: point;
+ phAlign: align;
+ phShift: number;
+ phDuration: number;
+ phLeftFunc: transition;
+ phAlphaFunc: transition;
+ phColorFunc: transition;
+}
+
+flatTextarea {
+ textColor: color;
+ bgColor: color;
+ width: number;
+ textMrg: margins;
+ align: align;
+ font: font;
+ cursor: cursor;
+
+ phColor: color;
+ phFocusColor: color;
+ phPos: point;
+ phAlign: align;
+ phShift: number;
+ phDuration: number;
+ phLeftFunc: transition;
+ phAlphaFunc: transition;
+ phColorFunc: transition;
+}
+
+flatScroll {
+ barColor: color;
+ bgColor: color;
+ barOverColor: color;
+ bgOverColor: color;
+
+ round: number;
+
+ width: number;
+ minHeight: number;
+ deltax: number;
+ deltay: number;
+
+ topsh: number;
+ bottomsh: number;
+ shColor: color;
+
+ duration: number;
+ hiding: number;
+}
+
+countryInput {
+ width: number;
+ height: number;
+ top: number;
+ bgColor: color;
+ ptrSize: size;
+ textMrg: margins;
+ font: font;
+ align: align;
+}
+
+countryList {
+ notFoundColor: color;
+ notFoundFont: font;
+
+ verticalMargin: number;
+
+ font: font;
+ codeFont: font;
+ rowHeight: number;
+ color: color;
+ codeColor: color;
+ bgColor: color;
+ bgHovered: color;
+ margin: number;
+ codeWidth: number;
+
+ borderMargin: number;
+ borderColor: color;
+ borderWidth: number;
+}
+
+slider {
+ color: color;
+ thikness: number;
+
+ width: number;
+ bar: sprite;
+}
+
+flatLabel {
+ font: font;
+ minWidth: number;
+ width: number;
+ align: align;
+}
diff --git a/Telegram/Setup.iss b/Telegram/Setup.iss
new file mode 100644
index 000000000..d8963573c
--- /dev/null
+++ b/Telegram/Setup.iss
@@ -0,0 +1,116 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define MyAppShortName "Telegram"
+#define MyAppName "Telegram Win (Unofficial)"
+#define MyAppVersion "0.4.18"
+#define MyAppVersionZero "0.4.18"
+#define MyAppFullVersion "0.4.18.0"
+#define MyAppPublisher "Telegram (Unofficial)"
+#define MyAppURL "https://tdesktop.com"
+#define MyAppExeName "Telegram.exe"
+#define MyAppId "53F49750-6209-4FBF-9CA8-7A333C87D1ED"
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{{#MyAppId}}
+AppName={#MyAppName}
+AppVersion={#MyAppVersion}
+;AppVerName={#MyAppName} {#MyAppVersion}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppURL}
+AppSupportURL={#MyAppURL}
+AppUpdatesURL={#MyAppURL}
+DefaultDirName={userappdata}\{#MyAppName}
+DefaultGroupName={#MyAppName}
+AllowNoIcons=yes
+OutputDir=.\..\Win32\Release
+OutputBaseFilename=tsetup.{#MyAppVersionZero}
+SetupIconFile=.\SourceFiles\art\iconround256.ico
+UninstallDisplayIcon={app}\Telegram.exe
+Compression=lzma
+SolidCompression=yes
+DisableStartupPrompt=yes
+PrivilegesRequired=lowest
+VersionInfoVersion={#MyAppFullVersion}
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
+Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; OnlyBelowVersion: 0,6.1
+
+[Files]
+Source: ".\..\Win32\Release\Telegram.exe"; DestDir: "{app}"; Flags: ignoreversion
+Source: ".\..\Win32\Release\Updater.exe"; DestDir: "{app}"; Flags: ignoreversion
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+[Icons]
+Name: "{group}\{#MyAppShortName}"; Filename: "{app}\{#MyAppExeName}"
+Name: "{group}\{cm:UninstallProgram,{#MyAppShortName}}"; Filename: "{uninstallexe}"
+Name: "{userdesktop}\{#MyAppShortName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
+Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppShortName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon
+
+[Run]
+Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppShortName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
+
+[UninstallDelete]
+Type: files; Name: "{app}\data"
+Type: files; Name: "{app}\data_config"
+Type: files; Name: "{app}\log.txt"
+Type: filesandordirs; Name: "{app}\DebugLogs"
+Type: filesandordirs; Name: "{app}\tupdates"
+Type: filesandordirs; Name: "{app}\tdata"
+Type: filesandordirs; Name: "{app}\tdumps"
+Type: dirifempty; Name: "{app}"
+Type: files; Name: "{userappdata}\{#MyAppName}\data"
+Type: files; Name: "{userappdata}\{#MyAppName}\data_config"
+Type: files; Name: "{userappdata}\{#MyAppName}\log.txt"
+Type: filesandordirs; Name: "{userappdata}\{#MyAppName}\DebugLogs"
+Type: filesandordirs; Name: "{userappdata}\{#MyAppName}\tupdates"
+Type: filesandordirs; Name: "{userappdata}\{#MyAppName}\tdata"
+Type: filesandordirs; Name: "{userappdata}\{#MyAppName}\tdumps"
+Type: dirifempty; Name: "{userappdata}\{#MyAppName}"
+
+[Code]
+procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
+var ResultCode: Integer;
+begin
+ if CurUninstallStep = usUninstall then
+ begin
+ ShellExec('', ExpandConstant('{app}\{#MyAppExeName}'), '-cleanup', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
+ end;
+end;
+
+const CSIDL_DESKTOPDIRECTORY = $0010;
+ CSIDL_COMMON_DESKTOPDIRECTORY = $0019;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var ResultCode: Integer;
+ HasOldKey: Boolean;
+ HasNewKey: Boolean;
+ HasOldLnk: Boolean;
+ HasNewLnk: Boolean;
+ UserDesktopLnk: String;
+ CommonDesktopLnk: String;
+begin
+ if CurStep = ssPostInstall then
+ begin
+ HasNewKey := RegKeyExists(HKEY_CURRENT_USER, 'Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{{#MyAppId}}_is1') or RegKeyExists(HKEY_CURRENT_USER, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{{#MyAppId}}_is1');
+ HasOldKey := RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{{#MyAppId}}_is1') or RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{{#MyAppId}}_is1');
+ UserDesktopLnk := ExpandFileName(GetShellFolderByCSIDL(CSIDL_DESKTOPDIRECTORY, False) + '\{#MyAppShortName}.lnk');
+ CommonDesktopLnk := ExpandFileName(GetShellFolderByCSIDL(CSIDL_COMMON_DESKTOPDIRECTORY, False) + '\{#MyAppShortName}.lnk');
+ HasNewLnk := FileExists(UserDesktopLnk);
+ HasOldLnk := FileExists(CommonDesktopLnk) and (UserDesktopLnk <> CommonDesktopLnk);
+ if (HasOldKey and HasNewKey) or (HasOldLnk and HasNewLnk) then
+ begin
+ if (GetWindowsVersion >= $06000000) then // Vista or later
+ ShellExec('runas', ExpandConstant('{app}\{#MyAppExeName}'), '-fixprevious', '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
+ else
+ ShellExec('', ExpandConstant('{app}\{#MyAppExeName}'), '-fixprevious', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
+ end;
+ end;
+end;
diff --git a/Telegram/SetupFiles/data b/Telegram/SetupFiles/data
new file mode 100644
index 000000000..e69de29bb
diff --git a/Telegram/SetupFiles/log.txt b/Telegram/SetupFiles/log.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/Telegram/SourceFiles/_other/genemoji.cpp b/Telegram/SourceFiles/_other/genemoji.cpp
new file mode 100644
index 000000000..817e23a24
--- /dev/null
+++ b/Telegram/SourceFiles/_other/genemoji.cpp
@@ -0,0 +1,1280 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+#include "genemoji.h"
+
+#include
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+
+typedef unsigned int uint32;
+
+struct EmojiData {
+ uint32 code, code2;
+ int x, y;
+ QString name, name_200x;
+};
+
+// copied from emojibox.cpp
+struct EmojiReplace {
+ uint32 code;
+ const char *replace;
+};
+
+EmojiReplace replaces[] = {
+ {0xD83DDE0A, ":-)"},
+ {0xD83DDE03, ":-D"},
+ {0xD83DDE09, ";-)"},
+ {0xD83DDE06, "xD"},
+ {0xD83DDE1C, ";-P"},
+ {0xD83DDE0B, ":-p"},
+ {0xD83DDE0D, "8-)"},
+ {0xD83DDE0E, "B-)"},
+ {0xD83DDE12, ":-("},
+ {0xD83DDE0F, ":]"},
+ {0xD83DDE14, "3("},
+ {0xD83DDE22, ":'("},
+ {0xD83DDE2D, ":_("},
+ {0xD83DDE29, ":(("},
+ {0xD83DDE28, ":o"},
+ {0xD83DDE10, ":|"},
+ {0xD83DDE0C, "3-)"},
+ {0xD83DDE20, ">("},
+ {0xD83DDE21, ">(("},
+ {0xD83DDE07, "O:)"},
+ {0xD83DDE30, ";o"},
+ {0xD83DDE33, "8|"},
+ {0xD83DDE32, "8o"},
+ {0xD83DDE37, ":X"},
+ {0xD83DDE1A, ":-*"},
+ {0xD83DDE08, "}:)"},
+ {0x2764, "<3"},
+ {0xD83DDC4D, ":like:"},
+ {0xD83DDC4E, ":dislike:"},
+ {0x261D, ":up:"},
+ {0x270C, ":v:"},
+ {0xD83DDC4C, ":ok:"}
+};
+const uint32 replacesCount = sizeof(replaces) / sizeof(EmojiReplace);
+typedef QMap ReplaceMap;
+ReplaceMap replaceMap;
+
+static const int variantsCount = 4, variants[] = { 0, 2, 3, 4 }, inRow = 40, imSizes[] = { 16, 20, 24, 32 };
+static const char *variantPostfix[] = { "", "_125x", "_150x", "_200x" };
+static const char *variantNames[] = { "dbisOne", "dbisOneAndQuarter", "dbisOneAndHalf", "dbisTwo" };
+
+typedef QMap EmojisData;
+EmojisData emojisData;
+
+uint32 emojiCategory0[] = {
+ 0xD83DDE04,
+ 0xD83DDE03,
+ 0xD83DDE00,
+ 0xD83DDE0A,
+ 0x263A,
+ 0xD83DDE09,
+ 0xD83DDE0D,
+ 0xD83DDE18,
+ 0xD83DDE1A,
+ 0xD83DDE17,
+ 0xD83DDE19,
+ 0xD83DDE1C,
+ 0xD83DDE1D,
+ 0xD83DDE1B,
+ 0xD83DDE33,
+ 0xD83DDE01,
+ 0xD83DDE14,
+ 0xD83DDE0C,
+ 0xD83DDE12,
+ 0xD83DDE1E,
+ 0xD83DDE23,
+ 0xD83DDE22,
+ 0xD83DDE02,
+ 0xD83DDE2D,
+ 0xD83DDE2A,
+ 0xD83DDE25,
+ 0xD83DDE30,
+ 0xD83DDE05,
+ 0xD83DDE13,
+ 0xD83DDE29,
+ 0xD83DDE2B,
+ 0xD83DDE28,
+ 0xD83DDE31,
+ 0xD83DDE20,
+ 0xD83DDE21,
+ 0xD83DDE24,
+ 0xD83DDE16,
+ 0xD83DDE06,
+ 0xD83DDE0B,
+ 0xD83DDE37,
+ 0xD83DDE0E,
+ 0xD83DDE34,
+ 0xD83DDE35,
+ 0xD83DDE32,
+ 0xD83DDE1F,
+ 0xD83DDE26,
+ 0xD83DDE27,
+ 0xD83DDE08,
+ 0xD83DDC7F,
+ 0xD83DDE2E,
+ 0xD83DDE2C,
+ 0xD83DDE10,
+ 0xD83DDE15,
+ 0xD83DDE2F,
+ 0xD83DDE36,
+ 0xD83DDE07,
+ 0xD83DDE0F,
+ 0xD83DDE11,
+ 0xD83DDC72,
+ 0xD83DDC73,
+ 0xD83DDC6E,
+ 0xD83DDC77,
+ 0xD83DDC82,
+ 0xD83DDC76,
+ 0xD83DDC66,
+ 0xD83DDC67,
+ 0xD83DDC68,
+ 0xD83DDC69,
+ 0xD83DDC74,
+ 0xD83DDC75,
+ 0xD83DDC71,
+ 0xD83DDC7C,
+ 0xD83DDC78,
+ 0xD83DDE3A,
+ 0xD83DDE38,
+ 0xD83DDE3B,
+ 0xD83DDE3D,
+ 0xD83DDE3C,
+ 0xD83DDE40,
+ 0xD83DDE3F,
+ 0xD83DDE39,
+ 0xD83DDE3E,
+ 0xD83DDC79,
+ 0xD83DDC7A,
+ 0xD83DDE48,
+ 0xD83DDE49,
+ 0xD83DDE4A,
+ 0xD83DDC80,
+ 0xD83DDC7D,
+ 0xD83DDCA9,
+ 0xD83DDD25,
+ 0x2728,
+ 0xD83CDF1F,
+ 0xD83DDCAB,
+ 0xD83DDCA5,
+ 0xD83DDCA2,
+ 0xD83DDCA6,
+ 0xD83DDCA7,
+ 0xD83DDCA4,
+ 0xD83DDCA8,
+ 0xD83DDC42,
+ 0xD83DDC40,
+ 0xD83DDC43,
+ 0xD83DDC45,
+ 0xD83DDC44,
+ 0xD83DDC4D,
+ 0xD83DDC4E,
+ 0xD83DDC4C,
+ 0xD83DDC4A,
+ 0x270A,
+ 0x270C,
+ 0xD83DDC4B,
+ 0x270B,
+ 0xD83DDC50,
+ 0xD83DDC46,
+ 0xD83DDC47,
+ 0xD83DDC49,
+ 0xD83DDC48,
+ 0xD83DDE4C,
+ 0xD83DDE4F,
+ 0x261D,
+ 0xD83DDC4F,
+ 0xD83DDCAA,
+ 0xD83DDEB6,
+ 0xD83CDFC3,
+ 0xD83DDC83,
+ 0xD83DDC6B,
+ 0xD83DDC6A,
+ 0xD83DDC6C,
+ 0xD83DDC6D,
+ 0xD83DDC8F,
+ 0xD83DDC91,
+ 0xD83DDC6F,
+ 0xD83DDE46,
+ 0xD83DDE45,
+ 0xD83DDC81,
+ 0xD83DDE4B,
+ 0xD83DDC86,
+ 0xD83DDC87,
+ 0xD83DDC85,
+ 0xD83DDC70,
+ 0xD83DDE4E,
+ 0xD83DDE4D,
+ 0xD83DDE47,
+ 0xD83CDFA9,
+ 0xD83DDC51,
+ 0xD83DDC52,
+ 0xD83DDC5F,
+ 0xD83DDC5E,
+ 0xD83DDC61,
+ 0xD83DDC60,
+ 0xD83DDC62,
+ 0xD83DDC55,
+ 0xD83DDC54,
+ 0xD83DDC5A,
+ 0xD83DDC57,
+ 0xD83CDFBD,
+ 0xD83DDC56,
+ 0xD83DDC58,
+ 0xD83DDC59,
+ 0xD83DDCBC,
+ 0xD83DDC5C,
+ 0xD83DDC5D,
+ 0xD83DDC5B,
+ 0xD83DDC53,
+ 0xD83CDF80,
+ 0xD83CDF02,
+ 0xD83DDC84,
+ 0xD83DDC9B,
+ 0xD83DDC99,
+ 0xD83DDC9C,
+ 0xD83DDC9A,
+ 0x2764,
+ 0xD83DDC94,
+ 0xD83DDC97,
+ 0xD83DDC93,
+ 0xD83DDC95,
+ 0xD83DDC96,
+ 0xD83DDC9E,
+ 0xD83DDC98,
+ 0xD83DDC8C,
+ 0xD83DDC8B,
+ 0xD83DDC8D,
+ 0xD83DDC8E,
+ 0xD83DDC64,
+ 0xD83DDC65,
+ 0xD83DDCAC,
+ 0xD83DDC63,
+ 0xD83DDCAD,
+};
+
+uint32 emojiCategory1[] = {
+ 0xD83DDC36,
+ 0xD83DDC3A,
+ 0xD83DDC31,
+ 0xD83DDC2D,
+ 0xD83DDC39,
+ 0xD83DDC30,
+ 0xD83DDC38,
+ 0xD83DDC2F,
+ 0xD83DDC28,
+ 0xD83DDC3B,
+ 0xD83DDC37,
+ 0xD83DDC3D,
+ 0xD83DDC2E,
+ 0xD83DDC17,
+ 0xD83DDC35,
+ 0xD83DDC12,
+ 0xD83DDC34,
+ 0xD83DDC11,
+ 0xD83DDC18,
+ 0xD83DDC3C,
+ 0xD83DDC27,
+ 0xD83DDC26,
+ 0xD83DDC24,
+ 0xD83DDC25,
+ 0xD83DDC23,
+ 0xD83DDC14,
+ 0xD83DDC0D,
+ 0xD83DDC22,
+ 0xD83DDC1B,
+ 0xD83DDC1D,
+ 0xD83DDC1C,
+ 0xD83DDC1E,
+ 0xD83DDC0C,
+ 0xD83DDC19,
+ 0xD83DDC1A,
+ 0xD83DDC20,
+ 0xD83DDC1F,
+ 0xD83DDC2C,
+ 0xD83DDC33,
+ 0xD83DDC0B,
+ 0xD83DDC04,
+ 0xD83DDC0F,
+ 0xD83DDC00,
+ 0xD83DDC03,
+ 0xD83DDC05,
+ 0xD83DDC07,
+ 0xD83DDC09,
+ 0xD83DDC0E,
+ 0xD83DDC10,
+ 0xD83DDC13,
+ 0xD83DDC15,
+ 0xD83DDC16,
+ 0xD83DDC01,
+ 0xD83DDC02,
+ 0xD83DDC32,
+ 0xD83DDC21,
+ 0xD83DDC0A,
+ 0xD83DDC2B,
+ 0xD83DDC2A,
+ 0xD83DDC06,
+ 0xD83DDC08,
+ 0xD83DDC29,
+ 0xD83DDC3E,
+ 0xD83DDC90,
+ 0xD83CDF38,
+ 0xD83CDF37,
+ 0xD83CDF40,
+ 0xD83CDF39,
+ 0xD83CDF3B,
+ 0xD83CDF3A,
+ 0xD83CDF41,
+ 0xD83CDF43,
+ 0xD83CDF42,
+ 0xD83CDF3F,
+ 0xD83CDF3E,
+ 0xD83CDF44,
+ 0xD83CDF35,
+ 0xD83CDF34,
+ 0xD83CDF32,
+ 0xD83CDF33,
+ 0xD83CDF30,
+ 0xD83CDF31,
+ 0xD83CDF3C,
+ 0xD83CDF10,
+ 0xD83CDF1E,
+ 0xD83CDF1D,
+ 0xD83CDF1A,
+ 0xD83CDF11,
+ 0xD83CDF12,
+ 0xD83CDF13,
+ 0xD83CDF14,
+ 0xD83CDF15,
+ 0xD83CDF16,
+ 0xD83CDF17,
+ 0xD83CDF18,
+ 0xD83CDF1C,
+ 0xD83CDF1B,
+ 0xD83CDF19,
+ 0xD83CDF0D,
+ 0xD83CDF0E,
+ 0xD83CDF0F,
+ 0xD83CDF0B,
+ 0xD83CDF0C,
+ 0xD83CDF0D,
+ 0x2B50,
+ 0x2600,
+ 0x26C5,
+ 0x2601,
+ 0x26A1,
+ 0x2614,
+ 0x2744,
+ 0x26C4,
+ 0xD83CDF00,
+ 0xD83CDF01,
+ 0xD83CDF08,
+ 0xD83CDF0A,
+};
+
+uint32 emojiCategory2[] = {
+ 0xD83CDF8D,
+ 0xD83DDC9D,
+ 0xD83CDF8E,
+ 0xD83CDF92,
+ 0xD83CDF93,
+ 0xD83CDF8F,
+ 0xD83CDF86,
+ 0xD83CDF87,
+ 0xD83CDF90,
+ 0xD83CDF91,
+ 0xD83CDF83,
+ 0xD83DDC7B,
+ 0xD83CDF85,
+ 0xD83CDF84,
+ 0xD83CDF81,
+ 0xD83CDF8B,
+ 0xD83CDF89,
+ 0xD83CDF8A,
+ 0xD83CDF88,
+ 0xD83CDF8C,
+ 0xD83DDD2E,
+ 0xD83CDFA5,
+ 0xD83DDCF7,
+ 0xD83DDCF9,
+ 0xD83DDCFC,
+ 0xD83DDCBF,
+ 0xD83DDCC0,
+ 0xD83DDCBD,
+ 0xD83DDCBE,
+ 0xD83DDCBB,
+ 0xD83DDCF1,
+ 0x260E,
+ 0xD83DDCDE,
+ 0xD83DDCDF,
+ 0xD83DDCE0,
+ 0xD83DDCE1,
+ 0xD83DDCFA,
+ 0xD83DDCFB,
+ 0xD83DDD0A,
+ 0xD83DDD09,
+ 0xD83DDD09,
+ 0xD83DDD07,
+ 0xD83DDD14,
+ 0xD83DDD14,
+ 0xD83DDCE2,
+ 0xD83DDCE3,
+ 0x23F3,
+ 0x231B,
+ 0x23F0,
+ 0x231A,
+ 0xD83DDD13,
+ 0xD83DDD12,
+ 0xD83DDD0F,
+ 0xD83DDD10,
+ 0xD83DDD11,
+ 0xD83DDD0E,
+ 0xD83DDCA1,
+ 0xD83DDD26,
+ 0xD83DDD06,
+ 0xD83DDD05,
+ 0xD83DDD0C,
+ 0xD83DDD0B,
+ 0xD83DDD0D,
+ 0xD83DDEC0,
+ 0xD83DDEBF,
+ 0xD83DDEBD,
+ 0xD83DDD27,
+ 0xD83DDD29,
+ 0xD83DDD28,
+ 0xD83DDEAA,
+ 0xD83DDEAC,
+ 0xD83DDCA3,
+ 0xD83DDD2B,
+ 0xD83DDD2A,
+ 0xD83DDC8A,
+ 0xD83DDC89,
+ 0xD83DDCB0,
+ 0xD83DDCB4,
+ 0xD83DDCB5,
+ 0xD83DDCB7,
+ 0xD83DDCB6,
+ 0xD83DDCB3,
+ 0xD83DDCB8,
+ 0xD83DDCF2,
+ 0xD83DDCE7,
+ 0xD83DDCE5,
+ 0xD83DDCE4,
+ 0x2709,
+ 0xD83DDCE9,
+ 0xD83DDCE8,
+ 0xD83DDCEF,
+ 0xD83DDCEB,
+ 0xD83DDCEA,
+ 0xD83DDCEC,
+ 0xD83DDCED,
+ 0xD83DDCEE,
+ 0xD83DDCE6,
+ 0xD83DDCDD,
+ 0xD83DDCC4,
+ 0xD83DDCC3,
+ 0xD83DDCD1,
+ 0xD83DDCCA,
+ 0xD83DDCC8,
+ 0xD83DDCC9,
+ 0xD83DDCDC,
+ 0xD83DDCCB,
+ 0xD83DDCC5,
+ 0xD83DDCC6,
+ 0xD83DDCC7,
+ 0xD83DDCC1,
+ 0xD83DDCC2,
+ 0x2702,
+ 0xD83DDCCC,
+ 0xD83DDCCE,
+ 0x2712,
+ 0x270F,
+ 0xD83DDCCF,
+ 0xD83DDCD0,
+ 0xD83DDCD5,
+ 0xD83DDCD7,
+ 0xD83DDCD8,
+ 0xD83DDCD9,
+ 0xD83DDCD3,
+ 0xD83DDCD4,
+ 0xD83DDCD2,
+ 0xD83DDCDA,
+ 0xD83DDCD6,
+ 0xD83DDD16,
+ 0xD83DDCDB,
+ 0xD83DDD2C,
+ 0xD83DDD2D,
+ 0xD83DDCF0,
+ 0xD83CDFA8,
+ 0xD83CDFAC,
+ 0xD83CDFA4,
+ 0xD83CDFA7,
+ 0xD83CDFBC,
+ 0xD83CDFB5,
+ 0xD83CDFB6,
+ 0xD83CDFB9,
+ 0xD83CDFBB,
+ 0xD83CDFBA,
+ 0xD83CDFB7,
+ 0xD83CDFB8,
+ 0xD83DDC7E,
+ 0xD83CDFAE,
+ 0xD83CDCCF,
+ 0xD83CDFB4,
+ 0xD83CDC04,
+ 0xD83CDFB2,
+ 0xD83CDFAF,
+ 0xD83CDFC8,
+ 0xD83CDFC0,
+ 0x26BD,
+ 0x26BE,
+ 0xD83CDFBE,
+ 0xD83CDFB1,
+ 0xD83CDFC9,
+ 0xD83CDFB3,
+ 0x26F3,
+ 0xD83DDEB5,
+ 0xD83DDEB4,
+ 0xD83CDFC1,
+ 0xD83CDFC7,
+ 0xD83CDFC6,
+ 0xD83CDFBF,
+ 0xD83CDFC2,
+ 0xD83CDFCA,
+ 0xD83CDFC4,
+ 0xD83CDFA3,
+ 0x2615,
+ 0xD83CDF75,
+ 0xD83CDF76,
+ 0xD83CDF7C,
+ 0xD83CDF7A,
+ 0xD83CDF7B,
+ 0xD83CDF78,
+ 0xD83CDF79,
+ 0xD83CDF77,
+ 0xD83CDF74,
+ 0xD83CDF55,
+ 0xD83CDF54,
+ 0xD83CDF5F,
+ 0xD83CDF57,
+ 0xD83CDF56,
+ 0xD83CDF5D,
+ 0xD83CDF5B,
+ 0xD83CDF64,
+ 0xD83CDF71,
+ 0xD83CDF63,
+ 0xD83CDF65,
+ 0xD83CDF59,
+ 0xD83CDF58,
+ 0xD83CDF5A,
+ 0xD83CDF5C,
+ 0xD83CDF72,
+ 0xD83CDF62,
+ 0xD83CDF61,
+ 0xD83CDF73,
+ 0xD83CDF5E,
+ 0xD83CDF69,
+ 0xD83CDF6E,
+ 0xD83CDF66,
+ 0xD83CDF68,
+ 0xD83CDF67,
+ 0xD83CDF82,
+ 0xD83CDF70,
+ 0xD83CDF6A,
+ 0xD83CDF6B,
+ 0xD83CDF6C,
+ 0xD83CDF6D,
+ 0xD83CDF6F,
+ 0xD83CDF4E,
+ 0xD83CDF4F,
+ 0xD83CDF4A,
+ 0xD83CDF4B,
+ 0xD83CDF52,
+ 0xD83CDF47,
+ 0xD83CDF49,
+ 0xD83CDF53,
+ 0xD83CDF51,
+ 0xD83CDF48,
+ 0xD83CDF4C,
+ 0xD83CDF50,
+ 0xD83CDF4D,
+ 0xD83CDF60,
+ 0xD83CDF46,
+ 0xD83CDF45,
+ 0xD83CDF3D,
+};
+
+uint32 emojiCategory3[] = {
+ 0xD83CDFE0,
+ 0xD83CDFE1,
+ 0xD83CDFEB,
+ 0xD83CDFE2,
+ 0xD83CDFE3,
+ 0xD83CDFE5,
+ 0xD83CDFE6,
+ 0xD83CDFEA,
+ 0xD83CDFE9,
+ 0xD83CDFE8,
+ 0xD83DDC92,
+ 0x26EA,
+ 0xD83CDFEC,
+ 0xD83CDFE4,
+ 0xD83CDF07,
+ 0xD83CDF06,
+ 0xD83CDFEF,
+ 0xD83CDFF0,
+ 0x26FA,
+ 0xD83CDFED,
+ 0xD83DDDFC,
+ 0xD83DDDFE,
+ 0xD83DDDFB,
+ 0xD83CDF04,
+ 0xD83CDF05,
+ 0xD83CDF03,
+ 0xD83DDDFD,
+ 0xD83CDF09,
+ 0xD83CDFA0,
+ 0xD83CDFA1,
+ 0x26F2,
+ 0xD83CDFA2,
+ 0xD83DDEA2,
+ 0x26F5,
+ 0xD83DDEA4,
+ 0xD83DDEA3,
+ 0x2693,
+ 0xD83DDE80,
+ 0x2708,
+ 0xD83DDCBA,
+ 0xD83DDE81,
+ 0xD83DDE82,
+ 0xD83DDE8A,
+ 0xD83DDE89,
+ 0xD83DDE9E,
+ 0xD83DDE86,
+ 0xD83DDE84,
+ 0xD83DDE85,
+ 0xD83DDE88,
+ 0xD83DDE87,
+ 0xD83DDE9D,
+ 0xD83DDE9D,
+ 0xD83DDE83,
+ 0xD83DDE8E,
+ 0xD83DDE8C,
+ 0xD83DDE8D,
+ 0xD83DDE99,
+ 0xD83DDE98,
+ 0xD83DDE97,
+ 0xD83DDE95,
+ 0xD83DDE96,
+ 0xD83DDE9B,
+ 0xD83DDE9A,
+ 0xD83DDEA8,
+ 0xD83DDE93,
+ 0xD83DDE94,
+ 0xD83DDE92,
+ 0xD83DDE91,
+ 0xD83DDE90,
+ 0xD83DDEB2,
+ 0xD83DDEA1,
+ 0xD83DDE9F,
+ 0xD83DDEA0,
+ 0xD83DDE9C,
+ 0xD83DDC88,
+ 0xD83DDE8F,
+ 0xD83CDFAB,
+ 0xD83DDEA6,
+ 0xD83DDEA5,
+ 0x26A0,
+ 0xD83DDEA7,
+ 0xD83DDD30,
+ 0x26FD,
+ 0xD83CDFEE,
+ 0xD83CDFB0,
+ 0x2668,
+ 0xD83DDDFF,
+ 0xD83CDFAA,
+ 0xD83CDFAD,
+ 0xD83DDCCD,
+ 0xD83DDEA9,
+ 0xD83CDDEF,
+ 0xD83CDDF0,
+ 0xD83CDDE9,
+ 0xD83CDDE8,
+ 0xD83CDDFA,
+ 0xD83CDDEB,
+ 0xD83CDDEA,
+ 0xD83CDDEE,
+ 0xD83CDDF7,
+ 0xD83CDDEC,
+};
+
+uint32 emojiCategory4[] = {
+ 0x3120E3,
+ 0x3220E3,
+ 0x3320E3,
+ 0x3420E3,
+ 0x3520E3,
+ 0x3620E3,
+ 0x3720E3,
+ 0x3820E3,
+ 0x3920E3,
+ 0x3020E3,
+ 0xD83DDD1F,
+ 0xD83DDD22,
+ 0x2320E3,
+ 0xD83DDD23,
+ 0x2B06,
+ 0x2B07,
+ 0x2B05,
+ 0x27A1,
+ 0xD83DDD20,
+ 0xD83DDD21,
+ 0xD83DDD24,
+ 0x2197,
+ 0x2196,
+ 0x2198,
+ 0x2199,
+ 0x2194,
+ 0x2195,
+ 0xD83DDD04,
+ 0x25C0,
+ 0x25B6,
+ 0xD83DDD3C,
+ 0xD83DDD3D,
+ 0x21A9,
+ 0x21AA,
+ 0x2139,
+ 0x23EA,
+ 0x23E9,
+ 0x23EB,
+ 0x23EC,
+ 0x2935,
+ 0x2934,
+ 0xD83CDD97,
+ 0xD83DDD00,
+ 0xD83DDD01,
+ 0xD83DDD02,
+ 0xD83CDD95,
+ 0xD83CDD99,
+ 0xD83CDD92,
+ 0xD83CDD93,
+ 0xD83CDD96,
+ 0xD83DDCF6,
+ 0xD83CDFA6,
+ 0xD83CDE01,
+ 0xD83CDE2F,
+ 0xD83CDE33,
+ 0xD83CDE35,
+ 0xD83CDE32,
+ 0xD83CDE34,
+ 0xD83CDE32,
+ 0xD83CDE50,
+ 0xD83CDE39,
+ 0xD83CDE3A,
+ 0xD83CDE36,
+ 0xD83CDE1A,
+ 0xD83DDEBB,
+ 0xD83DDEB9,
+ 0xD83DDEBA,
+ 0xD83DDEBC,
+ 0xD83DDEBE,
+ 0xD83DDEB0,
+ 0xD83DDEAE,
+ 0xD83CDD7F,
+ 0x267F,
+ 0xD83DDEAD,
+ 0xD83CDE37,
+ 0xD83CDE38,
+ 0xD83CDE02,
+ 0x24C2,
+ 0xD83CDE51,
+ 0x3299,
+ 0x3297,
+ 0xD83CDD91,
+ 0xD83CDD98,
+ 0xD83CDD94,
+ 0xD83DDEAB,
+ 0xD83DDD1E,
+ 0xD83DDCF5,
+ 0xD83DDEAF,
+ 0xD83DDEB1,
+ 0xD83DDEB3,
+ 0xD83DDEB7,
+ 0xD83DDEB8,
+ 0x26D4,
+ 0x2733,
+ 0x2747,
+ 0x274E,
+ 0x2705,
+ 0x2734,
+ 0xD83DDC9F,
+ 0xD83CDD9A,
+ 0xD83DDCF3,
+ 0xD83DDCF4,
+ 0xD83CDD70,
+ 0xD83CDD71,
+ 0xD83CDD8E,
+ 0xD83CDD7E,
+ 0xD83DDCA0,
+ 0x27BF,
+ 0x267B,
+ 0x2648,
+ 0x2649,
+ 0x264A,
+ 0x264B,
+ 0x264C,
+ 0x264D,
+ 0x264E,
+ 0x264F,
+ 0x2650,
+ 0x2651,
+ 0x2652,
+ 0x2653,
+ 0x26CE,
+ 0xD83DDD2F,
+ 0xD83CDFE7,
+ 0xD83DDCB9,
+ 0xD83DDCB2,
+ 0xD83DDCB1,
+ 0xA9,
+ 0xAE,
+ 0x2122,
+ 0x303D,
+ 0x3030,
+ 0xD83DDD1D,
+ 0xD83DDD1A,
+ 0xD83DDD19,
+ 0xD83DDD1B,
+ 0xD83DDD1C,
+ 0x274C,
+ 0x2B55,
+ 0x2757,
+ 0x2753,
+ 0x2755,
+ 0x2754,
+ 0xD83DDD03,
+ 0xD83DDD5B,
+ 0xD83DDD67,
+ 0xD83DDD50,
+ 0xD83DDD5C,
+ 0xD83DDD51,
+ 0xD83DDD5D,
+ 0xD83DDD52,
+ 0xD83DDD5E,
+ 0xD83DDD53,
+ 0xD83DDD5F,
+ 0xD83DDD54,
+ 0xD83DDD60,
+ 0xD83DDD55,
+ 0xD83DDD56,
+ 0xD83DDD57,
+ 0xD83DDD58,
+ 0xD83DDD59,
+ 0xD83DDD5A,
+ 0xD83DDD61,
+ 0xD83DDD62,
+ 0xD83DDD63,
+ 0xD83DDD64,
+ 0xD83DDD65,
+ 0xD83DDD66,
+ 0x2716,
+ 0x2795,
+ 0x2796,
+ 0x2797,
+ 0x2660,
+ 0x2665,
+ 0x2663,
+ 0x2666,
+ 0xD83DDCAE,
+ 0xD83DDCAF,
+ 0x2714,
+ 0x2611,
+ 0xD83DDD18,
+ 0xD83DDD17,
+ 0x27B0,
+ 0xD83DDD31,
+ 0xD83DDD32,
+ 0xD83DDD33,
+ 0x25FC,
+ 0x25FB,
+ 0x25FE,
+ 0x25FD,
+ 0x25AA,
+ 0x25AB,
+ 0xD83DDD3A,
+ 0x2B1C,
+ 0x2B1B,
+ 0x26AB,
+ 0x26AA,
+ 0xD83DDD34,
+ 0xD83DDD35,
+ 0xD83DDD3B,
+ 0xD83DDD36,
+ 0xD83DDD37,
+ 0xD83DDD38,
+ 0xD83DDD39,
+};
+
+void writeEmojiCategory(QTextStream &tcpp, uint32 *emojiCategory, uint32 size, const char *name) {
+ tcpp << "\tcase dbiet" << name << ": {\n";
+ tcpp << "\t\tstatic QVector v" << name << ";\n";
+ tcpp << "\t\tif (v" << name << ".isEmpty()) {\n";
+ tcpp << "\t\t\tv" << name << ".resize(" << size << ");\n";
+ for (int i = 0; i < size; ++i) {
+ int index = 0;
+ for (EmojisData::const_iterator j = emojisData.cbegin(), e = emojisData.cend(); j != e; ++j) {
+ if (j->code == emojiCategory[i]) {
+ break;
+ }
+ ++index;
+ }
+ if (index == emojisData.size()) {
+ throw exception(QString("Could not find emoji from category '%1' with index %2, code %3").arg(name).arg(i).arg(emojiCategory[i]).toUtf8().constData());
+ }
+ tcpp << "\t\t\tv" << name << "[" << i << "] = &emojis[" << index << "];\n";
+ }
+ tcpp << "\t\t}\n";
+ tcpp << "\t\treturn v" << name << ";\n";
+ tcpp << "\t} break;\n\n";
+}
+
+bool genEmoji(QString emoji_in, const QString &emoji_out) {
+ QDir d(emoji_in);
+ if (!d.exists()) {
+ cout << "Could not open emoji input dir '" << emoji_in.toUtf8().constData() << "'!\n";
+ QCoreApplication::exit(1);
+ return false;
+ }
+ emoji_in = d.absolutePath() + '/';
+ QString emoji_in_200x = d.absolutePath() + "_200x/";
+ QDir d_200x(emoji_in_200x);
+ if (!d.exists()) {
+ cout << "Could not open emoji _200x input dir '" << emoji_in_200x.toUtf8().constData() << "'!\n";
+ QCoreApplication::exit(1);
+ return false;
+ }
+
+ int currentRow = 0, currentColumn = 0;
+ uint32 min1 = 0xFFFFFFFF, max1 = 0, min2 = 0xFFFFFFFF, max2 = 0;
+
+ QStringList filters;
+ filters << "*.png" << "*.gif";
+ QFileInfoList emojis = d.entryInfoList(filters, QDir::Files | QDir::NoDotAndDotDot | QDir::Readable);
+ for (QFileInfoList::const_iterator i = emojis.cbegin(), e = emojis.cend(); i != e; ++i) {
+ QString s = i->fileName();
+ QRegularExpressionMatch m = QRegularExpression("^([A-F0-9]+)\\.(png|gif)$").match(s);
+ if (m.hasMatch()) {
+ EmojiData data;
+ QString num = m.captured(1);
+ if (num.size() != 4 && num.size() != 8 && num.size() != 16) {
+ cout << "Bad name found '" << s.toUtf8().constData() << "'!\n";
+ continue;
+ }
+
+ data.code = ("0x" + num.mid(0, 8)).toUInt(0, 16);
+ if (num.size() > 8) {
+ data.code2 = ("0x" + num.mid(8)).toUInt(0, 16);
+ } else {
+ data.code2 = 0;
+ }
+ data.name = emoji_in + s;
+ data.name_200x = emoji_in_200x + s;
+ data.x = currentColumn;
+ data.y = currentRow;
+ ++currentColumn;
+
+ if (currentColumn == inRow) {
+ ++currentRow;
+ currentColumn = 0;
+ }
+ uint32 high = data.code >> 16;
+ if (!high) { // small codes
+ if (data.code == 169 || data.code == 174) { // two small
+ } else {
+ if (data.code < min1) min1 = data.code;
+ if (data.code > max1) max1 = data.code;
+ }
+ } else if (high == 35 || high >= 48 && high < 58) { // digits
+ } else {
+ if (data.code < min2) min2 = data.code;
+ if (data.code > max2) max2 = data.code;
+ }
+ EmojisData::const_iterator i = emojisData.constFind(data.code);
+ if (i != emojisData.cend()) {
+ cout << QString("Bad emoji code (duplicate) %1 %2 and %3 %4").arg(data.code).arg(data.code2).arg(i->code).arg(i->code2).toUtf8().constData() << "\n";
+ continue;
+ }
+ emojisData.insert(data.code, data);
+ } else {
+ cout << QString("Bad emoji file found: %1").arg(s).toUtf8().constData() << "\n";
+ }
+ }
+
+ if (currentColumn) ++currentRow;
+ if (!currentRow) {
+ cout << "No emojis written..\n";
+ return true;
+ }
+
+ for (int variantIndex = 0; variantIndex < variantsCount; variantIndex++) {
+ int variant = variants[variantIndex], imSize = imSizes[variantIndex];
+
+ QImage emojisImg(inRow * imSize, currentRow * imSize, QImage::Format_ARGB32);
+ QPainter p(&emojisImg);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(0, 0, emojisImg.width(), emojisImg.height(), Qt::transparent);
+ for (EmojisData::const_iterator i = emojisData.cbegin(), e = emojisData.cend(); i != e; ++i) {
+ QString name = variant ? i->name_200x : i->name;
+ int emojiSize = variant ? imSizes[3] : imSizes[0];
+
+ QPixmap emoji(name);
+ if (emoji.width() == emojiSize && emoji.height() == emojiSize) {
+ if (emojiSize != imSize) {
+ emoji = QPixmap::fromImage(emoji.toImage().scaled(imSize, imSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ }
+ p.drawPixmap(i->x * imSize, i->y * imSize, emoji);
+ } else {
+ cout << "Could not read image '" << name.toUtf8().constData() << "'!\n";
+ }
+ }
+ QString postfix = variantPostfix[variantIndex], emojif = "./SourceFiles/art/emoji" + postfix + ".png";
+ QByteArray emojib;
+ {
+ QBuffer ebuf(&emojib);
+ if (!emojisImg.save(&ebuf, "PNG")) {
+ cout << "Could not save 'emoji" << postfix.toUtf8().constData() << ".png'!\n";
+ return false;
+ }
+ }
+ bool needResave = !QFileInfo(emojif).exists();
+ if (!needResave) {
+ QFile ef(emojif);
+ if (!ef.open(QIODevice::ReadOnly)) {
+ needResave = true;
+ } else {
+ QByteArray already(ef.readAll());
+ if (already.size() != emojib.size() || memcmp(already.constData(), emojib.constData(), already.size())) {
+ needResave = true;
+ }
+ }
+ }
+ if (needResave) {
+ QFile ef(emojif);
+ if (!ef.open(QIODevice::WriteOnly)) {
+ cout << "Could not save 'emoji" << postfix.toUtf8().constData() << ".png'!\n";
+ return false;
+ } else {
+ if (ef.write(emojib) != emojib.size()) {
+ cout << "Could not save 'emoji" << postfix.toUtf8().constData() << ".png'!\n";
+ return false;
+ }
+ }
+ }
+ }
+
+ try {
+
+ QByteArray cppText;
+ {
+ QTextStream tcpp(&cppText);
+ tcpp << "\
+/*\n\
+Created from emoji config by \'/MetaEmoji\' project\n\
+\n\
+WARNING! All changes made in this file will be lost!\n\
+\n\
+This file is part of Telegram Desktop, \n\
+an unofficial desktop messaging app, see https://telegram.org\n\
+\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\
+Copyright (c) 2014 John Preston, https://tdesktop.com\n\
+*/\n";
+ tcpp << "#include \"stdafx.h\"\n#include \"gui/emoji_config.h\"\n\n";
+
+ tcpp << "namespace {\n"; // namespace with data
+ tcpp << "\tEmojiData *emojis = 0;\n";
+ tcpp << "\tchar emojisData[sizeof(EmojiData) * " << emojisData.size() << "];\n";
+ tcpp << "}\n\n";
+
+ tcpp << "void initEmoji() {\n";
+ tcpp << "\tEmojiData *toFill = emojis = (EmojiData*)emojisData;\n\n";
+ tcpp << "\tswitch (cScale()) {\n\n";
+ for (int variantIndex = 0; variantIndex < variantsCount; ++variantIndex) {
+ int imSize = imSizes[variantIndex];
+ tcpp << "\tcase " << variantNames[variantIndex] << ":\n";
+ for (EmojisData::const_iterator i = emojisData.cbegin(), e = emojisData.cend(); i != e; ++i) {
+ int len = i->code2 ? 4 : ((i->code >> 16) ? 2 : 1);
+ tcpp << "\t\tnew (toFill++) EmojiData(" << (i->x * imSize) << ", " << (i->y * imSize) << ", " << i->code << ", " << i->code2 << ", " << len << ");\n";
+ }
+ tcpp << "\tbreak;\n\n";
+ }
+ tcpp << "\t};\n";
+ tcpp << "};\n\n";
+
+ tcpp << "const EmojiData *getEmoji(uint32 code) {\n"; // getter
+ tcpp << "\tif (!emojis) return 0;\n\n";
+ tcpp << "\tuint32 highCode = code >> 16;\n";
+
+ uint32 index = 0;
+ EmojisData::const_iterator i = emojisData.cbegin(), e = emojisData.cend();
+
+ tcpp << "\tif (!highCode) {\n"; // small codes
+ tcpp << "\t\tswitch (code) {\n";
+ for (; i != e; ++i) { // two small
+ if (i->code2) break;
+ if (i->code != 169 && i->code != 174) break;
+
+ tcpp << "\t\t\tcase " << i->code << ": return &emojis[" << (index++) << "];\n";
+ }
+ tcpp << "\t\t}\n\n";
+ tcpp << "\t\tif (code < " << min1 << " || code > " << max1 << ") return 0;\n\n";
+ tcpp << "\t\tswitch (code) {\n";
+ for (; i != e; ++i) {
+ if (i->code2 || (i->code >> 16)) break;
+ tcpp << "\t\t\tcase " << i->code << ": return &emojis[" << (index++) << "];\n";
+ }
+ tcpp << "\t\t}\n\n";
+ tcpp << "\t\treturn 0;\n";
+ tcpp << "\t}\n\n";
+
+ tcpp << "\tif (highCode == 35 || highCode >= 48 && highCode < 58) {\n"; // digits
+ tcpp << "\t\tif ((code & 0xFFFF) != 0x20E3) return 0;\n\n";
+ tcpp << "\t\tswitch (code) {\n";
+ for (; i != e; ++i) {
+ if (i->code2) break;
+ uint32 high = i->code >> 16;
+ if (high != 35 && (high < 48 || high >= 58)) break;
+
+ tcpp << "\t\t\tcase " << i->code << ": return &emojis[" << (index++) << "];\n";
+ }
+ tcpp << "\t\t}\n\n";
+ tcpp << "\t\treturn 0;\n";
+ tcpp << "\t}\n\n";
+
+ tcpp << "\tif (code < " << min2 << " || code > " << max2 << ") return 0;\n\n";
+ tcpp << "\tswitch (code) {\n";
+ for (; i != e; ++i) {
+ tcpp << "\tcase " << i->code << ": return &emojis[" << (index++) << "];\n";
+ }
+ tcpp << "\t}\n\n";
+
+ tcpp << "\treturn 0;\n";
+ tcpp << "}\n\n";
+
+ // emoji autoreplace
+ tcpp << "void findEmoji(const QChar *ch, const QChar *e, const QChar *&newEmojiEnd, uint32 &emojiCode) {\n";
+ tcpp << "\tswitch (ch->unicode()) {\n";
+
+ QString tab("\t");
+ for (int i = 0; i < replacesCount; ++i) {
+ QString key = QString::fromUtf8(replaces[i].replace);
+ replaceMap[key] = replaces[i].code;
+ }
+ QString chars;
+ for (ReplaceMap::const_iterator i = replaceMap.cend(), e = replaceMap.cbegin(); i != e;) {
+ --i;
+ QString key = i.key();
+ if (key == chars) {
+ tcpp << tab.repeated(1 + chars.size()) << "}\n";
+ }
+ bool needSwitch = chars.size();
+ while (chars.size() && key.midRef(0, chars.size()) != chars) {
+ needSwitch = false;
+ chars.resize(chars.size() - 1);
+ tcpp << tab.repeated(1 + chars.size()) << "break;\n";
+ if (chars.size() && (key.midRef(0, chars.size()) != chars || key == chars)) {
+ tcpp << tab.repeated(1 + chars.size()) << "}\n";
+ }
+ }
+ for (int j = chars.size(); j < key.size(); ++j) {
+ if (needSwitch) {
+ tcpp << tab.repeated(1 + chars.size()) << "if (ch + " << chars.size() << " != e) switch ((ch + " << chars.size() << ")->unicode()) {\n";
+ }
+ tcpp << tab.repeated(1 + chars.size()) << "case '" << ((key.at(j) == '\\' || key.at(j) == '\'') ? "\\" : "") << key.at(j) << "':\n";
+ chars.push_back(key.at(j));
+ needSwitch = true;
+ }
+ tcpp << tab.repeated(1 + chars.size()) << "newEmojiEnd = ch + " << chars.size() << ";\n";
+ tcpp << tab.repeated(1 + chars.size()) << "if (newEmojiEnd == e || emojiEdge(newEmojiEnd) || newEmojiEnd->unicode() == ' ') {\n";
+ tcpp << tab.repeated(1 + chars.size()) << "\temojiCode = " << i.value() << ";\n";
+ tcpp << tab.repeated(1 + chars.size()) << "\treturn;\n";
+ tcpp << tab.repeated(1 + chars.size()) << "}\n";
+ }
+ while (chars.size()) {
+ chars.resize(chars.size() - 1);
+ tcpp << tab.repeated(1 + chars.size()) << "break;\n";
+ if (chars.size()) {
+ tcpp << tab.repeated(1 + chars.size()) << "}\n";
+ }
+ }
+
+ tcpp << "\t}\n";
+ tcpp << "}\n\n";
+
+ tcpp << "EmojiPack emojiPack(DBIEmojiTab tab) {\n";
+ tcpp << "\tswitch (tab) {\n\n";
+ writeEmojiCategory(tcpp, emojiCategory0, sizeof(emojiCategory0) / sizeof(emojiCategory0[0]), "People");
+ writeEmojiCategory(tcpp, emojiCategory1, sizeof(emojiCategory1) / sizeof(emojiCategory1[0]), "Nature");
+ writeEmojiCategory(tcpp, emojiCategory2, sizeof(emojiCategory2) / sizeof(emojiCategory2[0]), "Objects");
+ writeEmojiCategory(tcpp, emojiCategory3, sizeof(emojiCategory3) / sizeof(emojiCategory3[0]), "Places");
+ writeEmojiCategory(tcpp, emojiCategory4, sizeof(emojiCategory4) / sizeof(emojiCategory4[0]), "Symbols");
+ tcpp << "\t};\n\n";
+ tcpp << "\tEmojiPack result;\n";
+ tcpp << "\tresult.reserve(cGetRecentEmojis().size());\n";
+ tcpp << "\tfor (RecentEmojiPack::const_iterator i = cGetRecentEmojis().cbegin(), e = cGetRecentEmojis().cend(); i != e; ++i) {\n";
+ tcpp << "\t\tresult.push_back(i->first);\n";
+ tcpp << "\t}\n";
+ tcpp << "\treturn result;";
+ tcpp << "}\n\n";
+ }
+ QFile cpp(emoji_out);
+ bool write_cpp = 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 << "Emoji updated, writing " << currentRow << " rows, full count " << emojisData.size() << " emojis.\n";
+ if (!cpp.open(QIODevice::WriteOnly)) throw exception("Could not open style_auto.cpp for writing!");
+ if (cpp.write(cppText) != cppText.size()) throw exception("Could not open style_auto.cpp for writing!");
+ }/**/
+ } catch (exception &e) {
+ cout << e.what() << "\n";
+ QCoreApplication::exit(1);
+ return false;
+ }
+ return true;
+}
diff --git a/Telegram/SourceFiles/_other/genemoji.h b/Telegram/SourceFiles/_other/genemoji.h
new file mode 100644
index 000000000..029c62e41
--- /dev/null
+++ b/Telegram/SourceFiles/_other/genemoji.h
@@ -0,0 +1,63 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::exception;
+
+bool genEmoji(QString emoji_in, const QString &emoji_out);
+
+class GenEmoji : public QObject {
+ Q_OBJECT
+
+public:
+ GenEmoji(const QString &emoji_in, const QString &emoji_out) : QObject(0),
+ _emoji_in(emoji_in), _emoji_out(emoji_out) {
+ }
+
+ public slots :
+ void run() {
+ if (genEmoji(_emoji_in, _emoji_out)) {
+ emit finished();
+ }
+ }
+
+signals:
+ void finished();
+
+private:
+
+ QString _emoji_in, _emoji_out;
+};
diff --git a/Telegram/SourceFiles/_other/genlang.cpp b/Telegram/SourceFiles/_other/genlang.cpp
new file mode 100644
index 000000000..c92b48309
--- /dev/null
+++ b/Telegram/SourceFiles/_other/genlang.cpp
@@ -0,0 +1,454 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+#include "genlang.h"
+
+#include
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+
+typedef unsigned int uint32;
+
+QString layoutDirection;
+typedef QMap LangKeys;
+LangKeys keys;
+typedef QVector KeysOrder;
+KeysOrder keysOrder;
+
+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;
+ }
+ ++from;
+ return (from < end);
+ } 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;
+ if (!skipComment(from, end)) throw exception("Unexpected end of comment!");
+ } while (start != from);
+ return true;
+}
+
+void readKeyValue(const char *&from, const char *end) {
+ if (!skipJunk(from, end)) return;
+
+ const char *nameStart = from;
+ while (from < end && (*from >= 'a' && *from <= 'z' || *from >= 'A' && *from <= 'Z' || *from == '_' || *from >= '0' && *from <= '9')) {
+ ++from;
+ }
+
+ QString varName = QString::fromUtf8(nameStart, from - nameStart);
+
+ if (!skipJunk(from, end)) throw exception("Unexpected end of file!");
+ if (*from != ':') throw exception(QString("':' expected after '%1'").arg(varName).toUtf8().constData());
+
+ if (!skipJunk(++from, end)) throw exception("Unexpected end of file!");
+ if (*from != '"') throw exception(QString("Expected string after '%1:'").arg(varName).toUtf8().constData());
+
+ QByteArray varValue;
+ const char *start = ++from;
+ while (from < end && *from != '"') {
+ if (*from == '\\') {
+ if (from + 1 >= end) throw exception("Unexpected end of file!");
+ if (*(from + 1) == '"' || *(from + 1) == '\\') {
+ if (from > start) varValue.append(start, from - start);
+ start = ++from;
+ }
+ }
+ ++from;
+ }
+ if (from >= end) throw exception("Unexpected end of file!");
+ if (from > start) varValue.append(start, from - start);
+
+ if (!skipJunk(++from, end)) throw exception("Unexpected end of file!");
+ if (*from != ';') throw exception(QString("';' expected after '%1: \"value\"'").arg(varName).toUtf8().constData());
+
+ skipJunk(++from, end);
+
+ if (varName == "direction") {
+ if (varValue == "LTR" || varValue == "RTL") {
+ layoutDirection = QString::fromUtf8(varValue);
+ } else {
+ throw exception(QString("Unexpected value for 'direction' key: '%1'").arg(QString::fromUtf8(varValue)).toUtf8().constData());
+ }
+ } else if (varName.midRef(0, 4) != "lng_") {
+ throw exception(QString("Bad key '%1'").arg(varName).toUtf8().constData());
+ } else if (keys.constFind(varName) != keys.cend()) {
+ throw exception(QString("Key doubled '%1'").arg(varName).toUtf8().constData());
+ } else {
+ keys.insert(varName, QString::fromUtf8(varValue));
+ keysOrder.push_back(varName);
+ }
+}
+
+QString escapeCpp(const QString &key, QString value, bool wideChar) {
+ if (value.isEmpty()) return "QString()";
+ value = value.replace('\\', "\\\\").replace('\n', "\\n").replace('\r', "").replace('"', "\\\"");
+ QString res;
+ res.reserve(value.size() * 10);
+ bool instr = false;
+ for (const QChar *ch = value.constData(), *e = value.constData() + value.size(); ch != e; ++ch) {
+ if (ch->unicode() < 32) {
+ throw exception(QString("Bad value for key '%1'").arg(key).toUtf8().constData());
+ } else if (ch->unicode() > 127) {
+ 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;
+ }
+ res.append(*ch);
+ }
+ }
+ if (instr) res.append('"');
+ return (wideChar ? "qsl(" : "QString::fromUtf8(") + res.mid(wideChar ? 2 : 1) + ")";
+}
+
+void writeCppKey(QTextStream &tcpp, const QString &key, const QString &val) {
+ QString wide = escapeCpp(key, val, true), utf = escapeCpp(key, val, false);
+ if (wide.indexOf(" L\"") < 0) {
+ tcpp << "\t\t\tset(" << key << ", " << wide << ");\n";
+ } else {
+ tcpp << "#ifdef Q_OS_WIN\n";
+ tcpp << "\t\t\tset(" << key << ", " << wide << ");\n";
+ tcpp << "#else\n";
+ tcpp << "\t\t\tset(" << 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)) {
+ cout << "Could not open styles input file '" << lang_in.toUtf8().constData() << "'!\n";
+ QCoreApplication::exit(1);
+ return false;
+ }
+
+ QByteArray blob = f.readAll();
+ const char *text = blob.constData(), *end = blob.constData() + blob.size();
+ f.close();
+
+ try {
+ while (text != end) {
+ 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\
+an unofficial desktop messaging app, see https://telegram.org\n\
+\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\
+Copyright (c) 2014 John Preston, https://tdesktop.com\n\
+*/\n";
+ th << "#pragma once\n\n";
+ th << "enum LangKey {\n";
+ for (int i = 0, l = keysOrder.size(); i < l; ++i) {
+ th << "\t" << keysOrder[i] << (i ? "" : " = 0") << ",\n";
+ }
+ th << "\n\tlng_keys_cnt\n";
+ th << "};\n\n";
+ th << "QString lang(LangKey key);\n";
+ th << "inline QString langDayOfMonth(const QDate &date) {\n";
+ th << "\tint32 month = date.month(), day = date.day();\n";
+ th << "\treturn (month > 0 && month <= 12) ? lang(lng_month_day).replace(qsl(\"{month}\"), lang(LangKey(lng_month1 + month - 1))).replace(qsl(\"{day}\"), QString::number(day)) : qsl(\"{err}\");\n";
+ th << "}\n\n";
+ th << "inline QString langDayOfWeek(const QDate &date) {\n";
+ th << "\tint32 day = date.dayOfWeek();\n";
+ th << "\treturn (day > 0 && day <= 7) ? lang(LangKey(lng_weekday1 + day - 1)) : qsl(\"{err}\");\n";
+ th << "}\n\n";
+ th << "Qt::LayoutDirection langDir();\n\n";
+ th << "class LangLoader {\n";
+ th << "public:\n";
+ th << "\tconst QString &errors() const;\n";
+ th << "\tconst QString &warnings() const;\n\n";
+ th << "protected:\n";
+ th << "\tLangLoader() : _checked(false) {\n";
+ th << "\t\tmemset(_found, 0, sizeof(_found));\n";
+ th << "\t}\n\n";
+ th << "\tbool feedKeyValue(const QString &key, const QString &value);\n\n";
+ th << "\tvoid error(const QString &text) {\n";
+ th << "\t\t_err.push_back(text);\n";
+ th << "\t}\n";
+ th << "\tvoid warning(const QString &text) {\n";
+ th << "\t\t_warn.push_back(text);\n";
+ th << "\t}\n\n";
+ th << "private:\n";
+ th << "\tmutable QStringList _err, _warn;\n";
+ th << "\tmutable QString _errors, _warnings;\n";
+ th << "\tmutable bool _checked;\n";
+ th << "\tbool _found[lng_keys_cnt];\n\n";
+ th << "\tLangLoader(const LangLoader &);\n";
+ th << "\tLangLoader &operator=(const LangLoader &);\n";
+ th << "};\n";
+
+ 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\
+an unofficial desktop messaging app, see https://telegram.org\n\
+\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\
+Copyright (c) 2014 John Preston, https://tdesktop.com\n\
+*/\n";
+ tcpp << "#include \"stdafx.h\"\n#include \"lang.h\"\n\n";
+ tcpp << "namespace {\n";
+ tcpp << "\tQt::LayoutDirection _langDir = Qt::" << (layoutDirection == "LTR" ? "LeftToRight" : "RightToLeft") << ";\n";
+ tcpp << "\tconst char *_langKeyNames[lng_keys_cnt + 1] = {\n";
+ for (int i = 0, l = keysOrder.size(); i < l; ++i) {
+ tcpp << "\t\t\"" << keysOrder[i] << "\",\n";
+ }
+ tcpp << "\t\t\"lng_keys_cnt\"\n";
+ tcpp << "\t};\n\n";
+ tcpp << "\tQString _langValues[lng_keys_cnt + 1];\n\n";
+ tcpp << "\tvoid set(LangKey key, const QString &val) {\n";
+ tcpp << "\t\t_langValues[key] = val;\n";
+ tcpp << "\t}\n\n";
+ tcpp << "\tclass LangInit {\n";
+ tcpp << "\tpublic:\n";
+ tcpp << "\t\tLangInit() {\n";
+ for (int i = 0, l = keysOrder.size(); i < l; ++i) {
+ writeCppKey(tcpp, keysOrder[i], keys[keysOrder[i]]);
+ }
+ tcpp << "\t\t\tset(lng_keys_cnt, QString());\n";
+ tcpp << "\t\t}\n";
+ tcpp << "\t};\n\n";
+ tcpp << "\tLangInit _langInit;\n";
+ tcpp << "}\n\n";
+
+ tcpp << "QString lang(LangKey key) {\n";
+ tcpp << "\treturn _langValues[(key < 0 || key > lng_keys_cnt) ? lng_keys_cnt : key];\n";
+ tcpp << "}\n\n";
+
+ tcpp << "Qt::LayoutDirection langDir() {\n";
+ tcpp << "\treturn _langDir;\n";
+ tcpp << "}\n\n";
+
+ tcpp << "bool LangLoader::feedKeyValue(const QString &key, const QString &value) {\n";
+ tcpp << "\tif (key == qsl(\"direction\")) {\n";
+ tcpp << "\t\tif (value == qsl(\"LTR\")) {\n";
+ tcpp << "\t\t\t_langDir = Qt::LeftToRight;\n";
+ tcpp << "\t\t\treturn true;\n";
+ tcpp << "\t\t} else if (value == qsl(\"RTL\")) {\n";
+ tcpp << "\t\t\t_langDir = Qt::RightToLeft;\n";
+ tcpp << "\t\t\treturn true;\n";
+ tcpp << "\t\t} else {\n";
+ tcpp << "\t\t\t_err.push_back(qsl(\"Bad value for 'direction' key.\"));\n";
+ tcpp << "\t\t\treturn false;\n";
+ tcpp << "\t\t}\n";
+ tcpp << "\t}\n";
+ tcpp << "\tif (key.size() < 5 || key.midRef(0, 4) != qsl(\"lng_\")) {\n";
+ tcpp << "\t\t_err.push_back(qsl(\"Bad key name '%1'\").arg(key));\n";
+ tcpp << "\t\treturn false;\n";
+ tcpp << "\t}\n\n";
+ if (!keys.isEmpty()) {
+ QString tab("\t");
+ tcpp << "\tLangKey keyIndex = lng_keys_cnt;\n";
+ tcpp << "\tconst QChar *ch = key.constData(), *e = key.constData() + key.size();\n";
+ QString current("lng_");
+ int depth = current.size();
+ tcpp << "\tswitch ((ch + " << depth << ")->unicode()) {\n";
+ for (LangKeys::const_iterator i = keys.cbegin(), j = i + 1, e = keys.cend(); i != e; ++i) {
+ QString key = i.key();
+ while (key.midRef(0, depth) != current) {
+ tcpp << tab.repeated(depth - 3) << "}\n";
+ current.chop(1);
+ --depth;
+ tcpp << tab.repeated(depth - 3) << "break;\n";
+ }
+ do {
+ if (key == current) break;
+
+ QChar ich = i.key().at(current.size());
+ 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) {
+ tcpp << tab.repeated(depth - 3) << "\tif (ch + " << (depth + 1) << " == e) keyIndex = " << key << ";\n";
+ } else {
+ tcpp << tab.repeated(depth - 3) << "\tif (key.midRef(" << (depth + 1) << ") == qsl(\"" << i.key().mid(depth + 1) << "\")) keyIndex = " << key << ";\n";
+ }
+ tcpp << tab.repeated(depth - 3) << "break;\n";
+ break;
+ }
+
+ ++depth;
+ current += ich;
+
+ if (key == current) {
+ tcpp << tab.repeated(depth - 3) << "if (ch + " << depth << " == e) {\n";
+ tcpp << tab.repeated(depth - 3) << "\tkeyIndex = " << key << ";\n";
+ tcpp << tab.repeated(depth - 3) << "}\n";
+ }
+
+ tcpp << tab.repeated(depth - 3) << "if (ch + " << depth << " < e) switch ((ch + " << depth << ")->unicode()) {\n";
+ } while (true);
+ ++j;
+ }
+ while (QString("lng_") != current) {
+ tcpp << tab.repeated(depth - 3) << "}\n";
+ current.chop(1);
+ --depth;
+ tcpp << tab.repeated(depth - 3) << "break;\n";
+ }
+ tcpp << "\t}\n\n";
+ tcpp << "\tif (keyIndex < lng_keys_cnt) {\n";
+ tcpp << "\t\t_found[keyIndex] = 1;\n";
+ tcpp << "\t\t_langValues[keyIndex] = value;\n";
+ tcpp << "\t\treturn true;\n";
+ tcpp << "\t}\n\n";
+ }
+ tcpp << "\t_err.push_back(qsl(\"Unknown key name '%1'\").arg(key));\n";
+ tcpp << "\treturn false;\n";
+ tcpp << "}\n\n";
+
+ tcpp << "const QString &LangLoader::errors() const {\n";
+ tcpp << "\tif (_errors.isEmpty() && !_err.isEmpty()) {\n";
+ tcpp << "\t\t_errors = _err.join('\\n');\n";
+ tcpp << "\t}\n";
+ tcpp << "\treturn _errors;\n";
+ tcpp << "}\n\n";
+
+ tcpp << "const QString &LangLoader::warnings() const {\n";
+ tcpp << "\tif (!_checked) {\n";
+ tcpp << "\t\tfor (int32 i = 0; i < lng_keys_cnt; ++i) {\n";
+ tcpp << "\t\t\tif (!_found[i]) {\n";
+ tcpp << "\t\t\t\t_warn.push_back(qsl(\"No value found for key '%1'\").arg(_langKeyNames[i]));\n";
+ tcpp << "\t\t\t}\n";
+ tcpp << "\t\t}\n";
+ tcpp << "\t\t_checked = true;\n";
+ tcpp << "\t}\n";
+ tcpp << "\tif (_warnings.isEmpty() && !_warn.isEmpty()) {\n";
+ tcpp << "\t\t_warnings = _warn.join('\\n');\n";
+ tcpp << "\t}\n";
+ tcpp << "\treturn _warnings;\n";
+ tcpp << "}\n";
+ }
+
+ 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";
+ 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!");
+ }
+ 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";
+ 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!");
+ }
+ } catch (exception &e) {
+ cout << e.what() << "\n";
+ QCoreApplication::exit(1);
+ return false;
+ }
+ return true;
+}
diff --git a/Telegram/SourceFiles/_other/genlang.h b/Telegram/SourceFiles/_other/genlang.h
new file mode 100644
index 000000000..31f8b4609
--- /dev/null
+++ b/Telegram/SourceFiles/_other/genlang.h
@@ -0,0 +1,61 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using std::string;
+using std::cout;
+using std::cerr;
+using std::exception;
+
+bool genLang(const QString &lang_in, const QString &lang_out);
+
+class GenLang : public QObject {
+ Q_OBJECT
+
+public:
+ GenLang(const QString &lang_in, const QString &lang_out) : QObject(0),
+ _lang_in(lang_in), _lang_out(lang_out) {
+ }
+
+ public slots :
+ void run() {
+ if (genLang(_lang_in, _lang_out)) {
+ emit finished();
+ }
+ }
+
+signals:
+ void finished();
+
+private:
+
+ QString _lang_in, _lang_out;
+};
diff --git a/Telegram/SourceFiles/_other/genstyles.cpp b/Telegram/SourceFiles/_other/genstyles.cpp
new file mode 100644
index 000000000..23b2cf3f6
--- /dev/null
+++ b/Telegram/SourceFiles/_other/genstyles.cpp
@@ -0,0 +1,1817 @@
+/*
+This file is part of Telegram Desktop,
+an unofficial desktop messaging app, see https://telegram.org
+
+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
+Copyright (c) 2014 John Preston, https://tdesktop.com
+*/
+#include "genstyles.h"
+
+#include
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
+
+enum ScalarType {
+ scNumber,
+ scString,
+ scColor,
+ scPoint,
+ scRect,
+ scSprite,
+ scSize,
+ scTransition,
+ scCursor,
+ scAlign,
+ scMargins,
+ scFont,
+
+ scTypesCount,
+};
+
+string scalarTypeNames[] = {
+ "number",
+ "string",
+ "color",
+ "point",
+ "rect",
+ "sprite",
+ "size",
+ "transition",
+ "cursor",
+ "align",
+ "margins",
+ "font",
+};
+
+string outputTypeNames[] = {
+ "number",
+ "string",
+ "color",
+ "point",
+ "rect",
+ "rect",
+ "size",
+ "transition",
+ "cursor",
+ "align",
+ "margins",
+ "font",
+};
+
+enum ClassGenTokenType {
+ csName, // [a-zA-Z_][a-zA-Z0-9_]*
+ csDelimeter, // ':'
+ csFieldFinish, // ';'
+ csClassStart, // '{'
+ csClassFinish, // '}'
+};
+
+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;
+ }
+ ++from;
+ return (from < end);
+ } else {
+ return true;
+ }
+ }
+ return true;
+}
+
+void readName(const char *&from, const char *end, string &token) {
+ if (from >= end) throw exception("Unexpected end of file!");
+
+ const char *start = from;
+ char ch = *from;
+ if (!((ch >= 'a' && ch <= 'z') || ((ch >= 'A') && (ch <= 'Z')))) {
+ throw exception("Unknown error :(");
+ }
+ while (++from < end) {
+ ch = *from;
+ if (!((ch >= 'a' && ch <= 'z') || ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || ch == '_')) break;
+ }
+ token = string(start, from);
+}
+
+void readString(const char *&from, const char *end, string &token) {
+ if (from + 1 >= end) throw exception("Unexpected end of file!");
+
+ token = "";
+ char border = *from;
+ if (border != '"' && border != '\'') {
+ throw exception("Unknown error :(");
+ }
+
+ bool spec = false;
+ for (++from; spec || (*from != border); ) {
+ if (*from == '\\') {
+ spec = true;
+ } else if (spec) {
+ if (*from == 'n') {
+ token += '\n';
+ } else if (*from == 't') {
+ token += '\t';
+ } else if (*from == '\\' || *from == '"' || *from == '\'') {
+ token += *from;
+ } else {
+ throw exception(QString("Unexpected escaped character in string: %1").arg(*from).toUtf8().constData());
+ }
+ spec = false;
+ } else {
+ token += *from;
+ }
+ if (++from >= end) throw exception("Unexpected end of file!");
+ }
+ ++from;
+}
+
+char hexChar(char ch) {
+ if (ch >= 'a' && ch <= 'f') {
+ return ch + ('A' - 'a');
+ }
+ return ch;
+}
+
+void readColor(const char *&from, const char *end, string &token) {
+ if (from + 3 >= end) throw exception("Unexpected end of file!");
+
+ token.resize(8);
+
+ int len = 0;
+ for (const char *ch = from + 1; ch < end; ++ch) {
+ if (*ch >= '0' && *ch <= '9' || *ch >= 'A' && *ch <= 'F' || *ch >= 'a' && *ch <= 'f') {
+ ++len;
+ } else {
+ break;
+ }
+ }
+ if (len != 3 && len != 4 && len != 6 && len != 8) {
+ throw exception("Bad color token");
+ }
+ if (len == 3 || len == 4) {
+ token[0] = token[1] = hexChar(*(++from));
+ token[2] = token[3] = hexChar(*(++from));
+ token[4] = token[5] = hexChar(*(++from));
+ if (len == 3) {
+ token[6] = token[7] = 'F';
+ } else {
+ token[6] = token[7] = hexChar(*(++from));
+ }
+ } else {
+ token[0] = hexChar(*(++from));
+ token[1] = hexChar(*(++from));
+ token[2] = hexChar(*(++from));
+ token[3] = hexChar(*(++from));
+ token[4] = hexChar(*(++from));
+ token[5] = hexChar(*(++from));
+ if (len == 6) {
+ token[6] = token[7] = 'F';
+ } else {
+ token[6] = hexChar(*(++from));
+ token[7] = hexChar(*(++from));
+ }
+ }
+ ++from;
+}
+
+void readNumber(const char *&from, const char *end, string &token) {
+ if (from >= end) throw exception("Unexpected end of file!");
+
+ bool neg = false;
+ if (*from == '-') {
+ neg = true;
+ if (++from >= end) throw exception("Unexpected end of file!");
+ }
+
+ if (*from == '0' && from < end && *(from + 1) >= '0' && *(from + 1) <= '9') throw exception("Bad number token!");
+
+ bool wasDot = false;
+ token = neg ? "-" : "";
+ for (bool wasDot = false; from < end; ++from) {
+ if (*from == '.') {
+ if (wasDot) throw exception("Unexpected dot in number!");
+ wasDot = true;
+ } else if (*from < '0' || *from > '9') {
+ break;
+ }
+ token += *from;
+ }
+}
+
+void readClassGenToken(const char *&from, const char *end, ClassGenTokenType &tokenType, string &token) {
+ const char *start;
+ do {
+ start = from;
+ if (!skipWhitespaces(from, end)) throw exception("Unexpected end of file!");
+ if (!skipComment(from, end)) throw exception("Unexpected end of comment!");
+ } while (start != from);
+
+ if ((*from >= 'a' && *from <= 'z') || ((*from >= 'A') && (*from <= 'Z'))) {
+ tokenType = csName;
+ return readName(from, end, token);
+ } else if (*from == ':') {
+ tokenType = csDelimeter;
+ } else if (*from == ';') {
+ tokenType = csFieldFinish;
+ } else if (*from == '{') {
+ tokenType = csClassStart;
+ } else if (*from == '}') {
+ tokenType = csClassFinish;
+ } else {
+ throw exception("Could not parse token!");
+ }
+ ++from;
+ return;
+}
+
+typedef QMap FieldTypesMap;
+struct ClassData {
+ string name;
+ FieldTypesMap fields;
+};
+
+typedef QMap Classes;
+Classes classes;
+
+typedef QMap ByName;
+
+bool genClasses(const QString &classes_in, const QString &classes_out) {
+ QFile f(classes_in);
+ if (!f.open(QIODevice::ReadOnly)) {
+ cout << "Could not open style classes input file '" << classes_in.toUtf8().constData() << "'!\n";
+ QCoreApplication::exit(1);
+ return false;
+ }
+
+ QByteArray blob = f.readAll();
+ const char *text = blob.constData(), *end = blob.constData() + blob.size();
+ ByName byName;
+ QVector byIndex;
+ string token;
+ ClassGenTokenType type;
+ try {
+ while (true) {
+ try {
+ readClassGenToken(text, end, type, token);
+ } catch (exception &e) {
+ if (e.what() != string("Unexpected end of file!")) {
+ throw;
+ }
+ break;
+ }
+ if (type != csName) {
+ throw exception(QString("Unexpected token, type %1: %2").arg(type).arg(token.c_str()).toUtf8().constData());
+ }
+
+ byIndex.push_back(ClassData());
+ ClassData &cls(byIndex.back());
+ cls.name = token;
+ readClassGenToken(text, end, type, token);
+ if (type == csDelimeter) {
+ readClassGenToken(text, end, type, token);
+ if (type != csName) throw exception(QString("Unexpected token after '%1:', type %2").arg(cls.name.c_str()).arg(type).toUtf8().constData());
+
+ QMap::const_iterator i = byName.constFind(token);
+ if (i == byName.cend()) throw exception(QString("Parent class '%1' not found for class '%2'").arg(token.c_str()).arg(cls.name.c_str()).toUtf8().constData());
+ cls.fields = byIndex[i.value()].fields;
+ readClassGenToken(text, end, type, token);
+ }
+ if (type != csClassStart) throw exception(QString("Unexpected token after '%1:%2', type %3").arg(cls.name.c_str()).arg(token.c_str()).arg(type).toUtf8().constData());
+
+ do {
+ string fname, ftype;
+ readClassGenToken(text, end, type, fname);
+ if (type == csClassFinish) {
+ byName.insert(cls.name, byIndex.size() - 1);
+ break;
+ }
+ if (type != csName) throw exception(QString("Unexpected token %1 while reading class '%2'").arg(type).arg(cls.name.c_str()).toUtf8().constData());
+ readClassGenToken(text, end, type, token);
+ if (type != csDelimeter) throw exception(QString("Unexpected token %1 while reading field '%2' in class '%3'").arg(type).arg(fname.c_str()).arg(cls.name.c_str()).toUtf8().constData());
+ readClassGenToken(text, end, type, ftype);
+ if (type != csName) throw exception(QString("Unexpected token %1 while reading field '%2' in class '%3'").arg(type).arg(fname.c_str()).arg(cls.name.c_str()).toUtf8().constData());
+ readClassGenToken(text, end, type, token);
+ if (type != csFieldFinish) throw exception(QString("Unexpected token %1 while reading field '%2:%3' in class '%4'").arg(type).arg(fname.c_str()).arg(ftype.c_str()).arg(cls.name.c_str()).toUtf8().constData());
+
+ ScalarType typeIndex = scTypesCount;
+ for (int t = 0; t < scTypesCount; ++t) {
+ if (ftype == scalarTypeNames[t]) {
+ typeIndex = ScalarType(t);
+ break;
+ }
+ }
+ if (typeIndex == scTypesCount) throw exception(QString("Unknown field type %1 while reading field '%2' in class '%3'").arg(ftype.c_str()).arg(fname.c_str()).arg(cls.name.c_str()).toUtf8().constData());
+ FieldTypesMap::const_iterator alr = cls.fields.find(fname);
+ if (alr != cls.fields.cend()) throw exception(QString("Redeclaration of field '%1' in class '%2'").arg(fname.c_str()).arg(cls.name.c_str()).toUtf8().constData());
+ cls.fields.insert(fname, typeIndex);
+ } while(true);
+ }
+
+ QByteArray outText;
+ {
+ QTextStream tout(&outText);
+ tout << "\
+/*\n\
+Created from \'/Resources/style_classes.txt\' by \'/MetaStyle\' project\n\
+\n\
+WARNING! All changes made in this file will be lost!\n\
+\n\
+This file is part of Telegram Desktop,\n\
+an unofficial desktop messaging app, see https://telegram.org\n\
+\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\
+Copyright (c) 2014 John Preston, https://tdesktop.com\n\
+*/\n";
+ tout << "#pragma once\n\n#include \"style.h\"\n\nnamespace style {\n";
+ for (int i = 0, l = byIndex.size(); i < l; ++i) {
+ ClassData &cls(byIndex[i]);
+ classes.insert(cls.name, cls);
+ tout << "\n\tclass " << cls.name.c_str() << " {\n\tpublic:\n\t\t" << cls.name.c_str() << "(";
+ for (FieldTypesMap::const_iterator j = cls.fields.cbegin(), e = cls.fields.cend(); j != e;) {
+ tout << "const style::" << outputTypeNames[j.value()].c_str() << " &_" << j.key().c_str();
+ if (++j != e) {
+ tout << ", ";
+ }
+ }
+ tout << ", Qt::Initialization = Qt::Uninitialized)";
+ if (!cls.fields.isEmpty()) {
+ tout << " : ";
+ }
+ for (FieldTypesMap::const_iterator j = cls.fields.cbegin(), e = cls.fields.cend(); j != e;) {
+ tout << j.key().c_str() << "(_" << j.key().c_str() << ")";
+ if (++j != e) {
+ tout << ", ";
+ }
+ }
+ tout << " {\n\t\t}\n\n";
+ for (FieldTypesMap::const_iterator j = cls.fields.cbegin(), e = cls.fields.cend(); j != e;) {
+ tout << "\t\tstyle::" << outputTypeNames[j.value()].c_str() << " " << j.key().c_str() << ";\n";
+ ++j;
+ }
+ tout << "\t};\n";
+ }
+ tout << "\n};\n";
+ }
+ QFile out(classes_out);
+ if (out.open(QIODevice::ReadOnly)) {
+ QByteArray wasOut = out.readAll();
+ if (wasOut.size() == outText.size()) {
+ if (!memcmp(wasOut.constData(), outText.constData(), outText.size())) {
+ return true;
+ }
+ }
+ out.close();
+ }
+ cout << "Style classes compiled, writing " << byIndex.size() << " classes.\n";
+ if (!out.open(QIODevice::WriteOnly)) throw exception("Could not open style_classes.h for writing!");
+ if (out.write(outText) != outText.size()) throw exception("Could not open style_classes.h for writing!");
+ } catch (exception &e) {
+ cout << e.what() << "\n";
+ QCoreApplication::exit(1);
+ return false;
+ }
+ return true;
+}
+
+enum StyleGenTokenType {
+ stName, // [a-zA-Z_][a-zA-Z0-9_]*
+ stDelimeter, // ':'
+ stFieldFinish, // ';'
+ stObjectStart, // '{'
+ stObjectFinish, // '}'
+ stConsStart, // '('
+ stConsFinish, // ')'
+ stComma, // ','
+ stVariant, // '/'
+ stString, // "text" or 'text'
+ stColor, // #rgb or #rrggbb
+ stNumber, // -?([1-9][0-9]+(\.[0-9]+)?|\.[0-9]+)
+};
+
+static const int variants[] = { 0, 2, 3, 4 }, variantsCount = sizeof(variants) / sizeof(variants[0]);
+static const char *variantNames[] = { "dbisOne", "dbisOneAndQuarter", "dbisOneAndHalf", "dbisTwo" };
+
+static const char *variantPostfixes[] = { "", "_125x", "_150x", "_200x" };
+QPixmap *spriteMax = 0;
+QImage *variantSprites = 0;
+QImage *variantGrids = 0;
+
+void readStyleGenToken(const char *&from, const char *end, StyleGenTokenType &tokenType, string &token) {
+ const char *start;
+ do {
+ start = from;
+ if (!skipWhitespaces(from, end)) throw exception("Unexpected end of file!");
+ if (!skipComment(from, end)) throw exception("Unexpected end of comment!");
+ } while (start != from);
+
+ if ((*from >= 'a' && *from <= 'z') || ((*from >= 'A') && (*from <= 'Z'))) {
+ tokenType = stName;
+ return readName(from, end, token);
+ } else if (*from == '"' || *from == '\'') {
+ tokenType = stString;
+ return readString(from, end, token);
+ } else if (*from == '#') {
+ tokenType = stColor;
+ return readColor(from, end, token);
+ } else if (*from == '.' || *from >= '0' && *from <= '9' || *from == '-') {
+ tokenType = stNumber;
+ return readNumber(from, end, token);
+ } else if (*from == ':') {
+ tokenType = stDelimeter;
+ } else if (*from == ';') {
+ tokenType = stFieldFinish;
+ } else if (*from == '{') {
+ tokenType = stObjectStart;
+ } else if (*from == '}') {
+ tokenType = stObjectFinish;
+ } else if (*from == '(') {
+ tokenType = stConsStart;
+ } else if (*from == ')') {
+ tokenType = stConsFinish;
+ } else if (*from == ',') {
+ tokenType = stComma;
+ } else if (*from == '/') {
+ tokenType = stVariant;
+ } else {
+ throw exception("Could not parse token!");
+ }
+ ++from;
+ return;
+}
+
+bool readPxAfterNumber(const char *&from, const char *end) {
+ if (from + 2 <= end && *from == 'p' && *(from + 1) == 'x') {
+ from += 2;
+ return true;
+ }
+ return false;
+}
+
+typedef QMap ScalarValue;
+typedef QPair ScalarData;
+typedef QPair Scalar;
+typedef QMap Fields;
+typedef QPair ObjectData;
+typedef QPair Object;
+typedef QVector