From 532e7e7e81de6340b13a04a6c49cd60d7c0bf746 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Tue, 29 Mar 2016 20:48:54 +0300
Subject: [PATCH 01/17] Fixed crash when trying to update selected state in
 HistoryInner while _history/_migrated had pending resize items.

---
 Telegram/SourceFiles/historywidget.cpp | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index 902fe59c5..0f4017583 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -197,6 +197,16 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
 
 	if (!App::main()) return;
 
+	if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) {
+		Notify::handlePendingHistoryUpdate();
+		if (_history) {
+			t_assert(!_history->hasPendingResizedItems());
+		}
+		if (_migrated) {
+			t_assert(!_migrated->hasPendingResizedItems());
+		}
+	}
+
 	Painter p(this);
 	QRect r(e->rect());
 	bool trivial = (rect() == r);
@@ -1677,7 +1687,9 @@ void HistoryInner::onTouchSelect() {
 }
 
 void HistoryInner::onUpdateSelected() {
-	if (!_history) return;
+	if (!_history || _history->hasPendingResizedItems() || (_migrated && _migrated->hasPendingResizedItems())) {
+		return;
+	}
 
 	QPoint mousePos(mapFromGlobal(_dragPos));
 	QPoint point(_widget->clampMousePosition(mousePos));
@@ -6286,7 +6298,7 @@ void HistoryWidget::notify_automaticLoadSettingsChangedGif() {
 }
 
 void HistoryWidget::notify_handlePendingHistoryUpdate() {
-	if (_history && _history->hasPendingResizedItems()) {
+	if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) {
 		updateListSize();
 		_list->update();
 	}

From 80365c92075d425b97151af22155b8003dbb7fc8 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Tue, 29 Mar 2016 20:57:27 +0300
Subject: [PATCH 02/17] Receiving a min user now should not force showing him
 in the conversations list by a phone number instead of his name.

---
 Telegram/SourceFiles/app.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index 4887c2681..731a57ee1 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -437,6 +437,10 @@ namespace App {
 
 					bool showPhone = !isServiceUser(data->id) && !d.is_self() && !d.is_contact() && !d.is_mutual_contact();
 					bool showPhoneChanged = !isServiceUser(data->id) && !d.is_self() && ((showPhone && data->contact) || (!showPhone && !data->contact));
+					if (minimal) {
+						showPhoneChanged = false;
+						showPhone = !isServiceUser(data->id) && (data->id != peerFromUser(MTP::authedId())) && !data->contact;
+					}
 
 					// see also Local::readPeer
 

From cd495654573953fa356e1f9e142e20ef4971d18c Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Tue, 29 Mar 2016 21:03:53 +0300
Subject: [PATCH 03/17] Skipping message date height when scrolling to the
 unread bar.

---
 Telegram/SourceFiles/history.cpp       | 12 +++++++-----
 Telegram/SourceFiles/historywidget.cpp |  6 ++++++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 1478fe97c..7ea40b30d 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -377,11 +377,13 @@ bool History::updateTyping(uint64 ms, bool force) {
 	return changed;
 }
 
-ChannelHistory::ChannelHistory(const PeerId &peer) : History(peer),
-unreadCountAll(0),
-_onlyImportant(!isMegagroup()),
-_otherOldLoaded(false), _otherNewLoaded(true),
-_collapseMessage(0), _joinedMessage(0) {
+ChannelHistory::ChannelHistory(const PeerId &peer) : History(peer)
+, unreadCountAll(0)
+, _onlyImportant(!isMegagroup())
+, _otherOldLoaded(false)
+, _otherNewLoaded(true)
+, _collapseMessage(nullptr)
+, _joinedMessage(nullptr) {
 }
 
 bool ChannelHistory::isSwitchReadyFor(MsgId switchId, MsgId &fixInScrollMsgId, int32 &fixInScrollMsgTop) {
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index 0f4017583..c8f665649 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -6557,8 +6557,14 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 		}
 	} else if (initial && _migrated && _migrated->unreadBar) {
 		toY = _list->itemTop(_migrated->unreadBar);
+		if (_migrated->unreadBar->Has<HistoryMessageDate>()) {
+			toY += _migrated->unreadBar->Get<HistoryMessageDate>()->height();
+		}
 	} else if (initial && _history->unreadBar) {
 		toY = _list->itemTop(_history->unreadBar);
+		if (_history->unreadBar->Has<HistoryMessageDate>()) {
+			toY += _history->unreadBar->Get<HistoryMessageDate>()->height();
+		}
 	} else if (_migrated && _migrated->showFrom) {
 		toY = _list->itemTop(_migrated->showFrom);
 		if (toY < _scroll.scrollTopMax() + st::unreadBarHeight) {

From 18db57ba963e033a6774dcd833d547c86f4c3ed8 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Wed, 30 Mar 2016 01:35:36 +0400
Subject: [PATCH 04/17] Added a new project codegen_style to the solution. It
 should replace MetaStyle in the far future.

---
 .gitignore                                    |  1 +
 Telegram.sln                                  | 21 ++++-
 Telegram/SourceFiles/codegen/style/main.cpp   |  3 +
 .../vc/codegen_style/codegen_style.vcxproj    | 91 +++++++++++++++++++
 .../codegen_style.vcxproj.filters             | 28 ++++++
 5 files changed, 141 insertions(+), 3 deletions(-)
 create mode 100644 Telegram/SourceFiles/codegen/style/main.cpp
 create mode 100644 Telegram/build/vc/codegen_style/codegen_style.vcxproj
 create mode 100644 Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters

diff --git a/.gitignore b/.gitignore
index 94b1d353e..a155d81c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
 /Telegram/SourceFiles/art/sprite_125x.png
 /Telegram/SourceFiles/art/sprite_150x.png
 /Telegram/*.user
+*.vcxproj.user
 *.suo
 *.sdf
 *.opensdf
diff --git a/Telegram.sln b/Telegram.sln
index 836d4a043..6487c468a 100644
--- a/Telegram.sln
+++ b/Telegram.sln
@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.30501.0
+# Visual Studio 14
+VisualStudioVersion = 14.0.24720.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Telegram", "Telegram\Telegram.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}"
 	ProjectSection(ProjectDependencies) = postProject
@@ -18,10 +18,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updater", "Telegram\Updater
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MetaLang", "Telegram\MetaLang.vcxproj", "{E417CAA4-259B-4C99-88E3-805F1300E8EB}"
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2F863EAD-33C9-4014-A573-93F085BA9CB1}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "codegen", "codegen", "{2F863EAD-33C9-4014-A573-93F085BA9CB1}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Packer", "Telegram\Packer.vcxproj", "{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "codegen_style", "Telegram\build\vc\codegen_style\codegen_style.vcxproj", "{E4DF8176-4DEF-4859-962F-B497E3E7A323}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -82,8 +84,21 @@ Global
 		{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Deploy|x64.ActiveCfg = Release|Win32
 		{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|Win32.ActiveCfg = Release|Win32
 		{56A9A4B2-21E5-4360-AFA8-85B43AC43B08}.Release|x64.ActiveCfg = Release|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|Win32.ActiveCfg = Debug|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|Win32.Build.0 = Debug|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Debug|x64.ActiveCfg = Debug|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|Win32.ActiveCfg = Debug|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|Win32.Build.0 = Debug|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|x64.ActiveCfg = Release|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Deploy|x64.Build.0 = Release|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|Win32.ActiveCfg = Release|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|Win32.Build.0 = Release|Win32
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323}.Release|x64.ActiveCfg = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{E4DF8176-4DEF-4859-962F-B497E3E7A323} = {2F863EAD-33C9-4014-A573-93F085BA9CB1}
+	EndGlobalSection
 EndGlobal
diff --git a/Telegram/SourceFiles/codegen/style/main.cpp b/Telegram/SourceFiles/codegen/style/main.cpp
new file mode 100644
index 000000000..a553b5173
--- /dev/null
+++ b/Telegram/SourceFiles/codegen/style/main.cpp
@@ -0,0 +1,3 @@
+int main(int argc, char *argv[]) {
+	return 0;
+}
diff --git a/Telegram/build/vc/codegen_style/codegen_style.vcxproj b/Telegram/build/vc/codegen_style/codegen_style.vcxproj
new file mode 100644
index 000000000..cfff29554
--- /dev/null
+++ b/Telegram/build/vc/codegen_style/codegen_style.vcxproj
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\SourceFiles\codegen\style\main.cpp" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{E4DF8176-4DEF-4859-962F-B497E3E7A323}</ProjectGuid>
+    <Keyword>Qt4VSv1.0</Keyword>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>14.0.24730.2</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>$(SolutionDir)$(Platform)\codegen\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)$(Platform)\obj\$(ProjectName)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>UNICODE;WIN32;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Optimization>Disabled</Optimization>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <AdditionalIncludeDirectories>.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
+      <AdditionalLibraryDirectories>$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>ws2_32.lib;qtmaind.lib;qtharfbuzzngd.lib;qtpcred.lib;qtfreetyped.lib;imageformats\qwebpd.lib;Qt5Cored.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PreprocessorDefinitions>UNICODE;WIN32;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <DebugInformationFormat />
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <AdditionalIncludeDirectories>.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
+      <AdditionalLibraryDirectories>$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <AdditionalDependencies>qtmain.lib;Qt5Core.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+      <UserProperties MocDir=".\GeneratedFiles\$(ConfigurationName)" UicDir=".\GeneratedFiles" RccDir=".\GeneratedFiles" lupdateOptions="" lupdateOnBuild="0" lreleaseOptions="" Qt5Version_x0020_Win32="QtStatic" MocOptions="" />
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>
\ No newline at end of file
diff --git a/Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters b/Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters
new file mode 100644
index 000000000..3263d5640
--- /dev/null
+++ b/Telegram/build/vc/codegen_style/codegen_style.vcxproj.filters
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;cxx;c;def</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
+      <Extensions>qrc;*</Extensions>
+      <ParseFiles>false</ParseFiles>
+    </Filter>
+    <Filter Include="Generated Files">
+      <UniqueIdentifier>{71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}</UniqueIdentifier>
+      <Extensions>moc;h;cpp</Extensions>
+      <SourceControlFiles>False</SourceControlFiles>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\SourceFiles\codegen\style\main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file

From 00bada8d453269b1d2e60c6272eebb6787f8e4f4 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Wed, 30 Mar 2016 10:17:04 +0400
Subject: [PATCH 05/17] Added C++11 config option to MetaStyle and MetaLang
 .pro projects.

---
 Telegram/MetaLang.pro  | 2 +-
 Telegram/MetaStyle.pro | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Telegram/MetaLang.pro b/Telegram/MetaLang.pro
index dbef70ae9..0dfa29a6f 100644
--- a/Telegram/MetaLang.pro
+++ b/Telegram/MetaLang.pro
@@ -12,7 +12,7 @@ CONFIG(release, debug|release) {
     DESTDIR = ./../ReleaseLang
 }
 
-CONFIG += plugin static
+CONFIG += plugin static c++11
 
 macx {
     QMAKE_INFO_PLIST = ./SourceFiles/_other/Lang.plist
diff --git a/Telegram/MetaStyle.pro b/Telegram/MetaStyle.pro
index 2ef67ea2e..a68a44385 100644
--- a/Telegram/MetaStyle.pro
+++ b/Telegram/MetaStyle.pro
@@ -12,7 +12,7 @@ CONFIG(release, debug|release) {
     DESTDIR = ./../ReleaseStyle
 }
 
-CONFIG += plugin static
+CONFIG += plugin static c++11
 
 macx {
     QMAKE_INFO_PLIST = ./SourceFiles/_other/Style.plist

From 88282d83645dd8e2901e9474d6b8b3f8977a519e Mon Sep 17 00:00:00 2001
From: Christoph <auer.chrisi@gmx.net>
Date: Wed, 30 Mar 2016 21:42:16 +0200
Subject: [PATCH 06/17] Check commit message

Signed-off-by: Christoph <auer.chrisi@gmx.net>
---
 .travis.yml       |  4 ++++
 .travis/build.sh  | 41 +----------------------------------------
 .travis/check.sh  | 25 +++++++++++++++++++++++++
 .travis/common.sh | 40 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 70 insertions(+), 40 deletions(-)
 create mode 100755 .travis/check.sh
 create mode 100755 .travis/common.sh

diff --git a/.travis.yml b/.travis.yml
index 612e30f7a..11f305e48 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -39,5 +39,9 @@ arch:
    - libtool --finish /usr/lib
    - .travis/build.sh
 
+before_install:
+  - "export TRAVIS_COMMIT_MSG=\"$(git log --format=%B --no-merges -n 1)\""
+  - .travis/check.sh
+
 script:
   - .travis/arch.sh
\ No newline at end of file
diff --git a/.travis/build.sh b/.travis/build.sh
index ebbaeffc4..7deae1f95 100755
--- a/.travis/build.sh
+++ b/.travis/build.sh
@@ -10,23 +10,6 @@ run() {
 	check
 }
 
-# set colors
-RCol='\e[0m'    # Text Reset
-
-# Regular           Bold                Underline           High Intensity      BoldHigh Intens     Background          High Intensity Backgrounds
-Bla='\e[0;30m';     BBla='\e[1;30m';    UBla='\e[4;30m';    IBla='\e[0;90m';    BIBla='\e[1;90m';   On_Bla='\e[40m';    On_IBla='\e[0;100m';
-Red='\e[0;31m';     BRed='\e[1;31m';    URed='\e[4;31m';    IRed='\e[0;91m';    BIRed='\e[1;91m';   On_Red='\e[41m';    On_IRed='\e[0;101m';
-Gre='\e[0;32m';     BGre='\e[1;32m';    UGre='\e[4;32m';    IGre='\e[0;92m';    BIGre='\e[1;92m';   On_Gre='\e[42m';    On_IGre='\e[0;102m';
-Yel='\e[0;33m';     BYel='\e[1;33m';    UYel='\e[4;33m';    IYel='\e[0;93m';    BIYel='\e[1;93m';   On_Yel='\e[43m';    On_IYel='\e[0;103m';
-Blu='\e[0;34m';     BBlu='\e[1;34m';    UBlu='\e[4;34m';    IBlu='\e[0;94m';    BIBlu='\e[1;94m';   On_Blu='\e[44m';    On_IBlu='\e[0;104m';
-Pur='\e[0;35m';     BPur='\e[1;35m';    UPur='\e[4;35m';    IPur='\e[0;95m';    BIPur='\e[1;95m';   On_Pur='\e[45m';    On_IPur='\e[0;105m';
-Cya='\e[0;36m';     BCya='\e[1;36m';    UCya='\e[4;36m';    ICya='\e[0;96m';    BICya='\e[1;96m';   On_Cya='\e[46m';    On_ICya='\e[0;106m';
-Whi='\e[0;37m';     BWhi='\e[1;37m';    UWhi='\e[4;37m';    IWhi='\e[0;97m';    BIWhi='\e[1;97m';   On_Whi='\e[47m';    On_IWhi='\e[0;107m';
-
-# Set variables
-_qtver=5.5.1
-srcdir=${PWD}
-
 downloadLibs() {
 	travis_fold_start "download_libs"
 	# Move telegram project to subfolder
@@ -172,28 +155,6 @@ check() {
 	fi
 }
 
-start_msg() {
-	echo -e "\n${Gre}$*${RCol}"
-}
-
-info_msg() {
-	echo -e "\n${Cya}$*${RCol}"
-}
-
-error_msg() {
-	echo -e "\n${BRed}$*${RCol}"
-}
-
-success_msg() {
-	echo -e "\n${BGre}$*${RCol}"
-}
-
-travis_fold_start() {
-	echo "travis_fold:start:$*"
-}
-
-travis_fold_end() {
-	echo "travis_fold:end:$*"
-}
+source ./.travis/common.sh
 
 run
diff --git a/.travis/check.sh b/.travis/check.sh
new file mode 100755
index 000000000..3fe7c7fd3
--- /dev/null
+++ b/.travis/check.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Checks commit message, ...
+
+run() {
+	checkCommitMessage
+}
+
+checkCommitMessage() {
+	info_msg "Commit message: ${TRAVIS_COMMIT_MSG}";
+	info_msg "Is pull request: ${TRAVIS_PULL_REQUEST}";
+
+	if [[ $TRAVIS_PULL_REQUEST != "false" ]];then
+		if [[  $TRAVIS_COMMIT_MSG != *"Signed-off-by: "* ]];then
+			error_msg "The commit message does not contain the signature!"
+			error_msg "More information: https://github.com/telegramdesktop/tdesktop/blob/master/.github/CONTRIBUTING.md#sign-your-work"
+			exit 1
+		else
+			success_msg "Commit message contains signature"
+		fi
+	fi
+}
+
+source ./.travis/common.sh
+
+run
diff --git a/.travis/common.sh b/.travis/common.sh
new file mode 100755
index 000000000..dd3bb1967
--- /dev/null
+++ b/.travis/common.sh
@@ -0,0 +1,40 @@
+# set colors
+RCol='\e[0m'    # Text Reset
+
+# Regular           Bold                Underline           High Intensity      BoldHigh Intens     Background          High Intensity Backgrounds
+Bla='\e[0;30m';     BBla='\e[1;30m';    UBla='\e[4;30m';    IBla='\e[0;90m';    BIBla='\e[1;90m';   On_Bla='\e[40m';    On_IBla='\e[0;100m';
+Red='\e[0;31m';     BRed='\e[1;31m';    URed='\e[4;31m';    IRed='\e[0;91m';    BIRed='\e[1;91m';   On_Red='\e[41m';    On_IRed='\e[0;101m';
+Gre='\e[0;32m';     BGre='\e[1;32m';    UGre='\e[4;32m';    IGre='\e[0;92m';    BIGre='\e[1;92m';   On_Gre='\e[42m';    On_IGre='\e[0;102m';
+Yel='\e[0;33m';     BYel='\e[1;33m';    UYel='\e[4;33m';    IYel='\e[0;93m';    BIYel='\e[1;93m';   On_Yel='\e[43m';    On_IYel='\e[0;103m';
+Blu='\e[0;34m';     BBlu='\e[1;34m';    UBlu='\e[4;34m';    IBlu='\e[0;94m';    BIBlu='\e[1;94m';   On_Blu='\e[44m';    On_IBlu='\e[0;104m';
+Pur='\e[0;35m';     BPur='\e[1;35m';    UPur='\e[4;35m';    IPur='\e[0;95m';    BIPur='\e[1;95m';   On_Pur='\e[45m';    On_IPur='\e[0;105m';
+Cya='\e[0;36m';     BCya='\e[1;36m';    UCya='\e[4;36m';    ICya='\e[0;96m';    BICya='\e[1;96m';   On_Cya='\e[46m';    On_ICya='\e[0;106m';
+Whi='\e[0;37m';     BWhi='\e[1;37m';    UWhi='\e[4;37m';    IWhi='\e[0;97m';    BIWhi='\e[1;97m';   On_Whi='\e[47m';    On_IWhi='\e[0;107m';
+
+# Set variables
+_qtver=5.5.1
+srcdir=${PWD}
+
+start_msg() {
+	echo -e "\n${Gre}$*${RCol}"
+}
+
+info_msg() {
+	echo -e "\n${Cya}$*${RCol}"
+}
+
+error_msg() {
+	echo -e "\n${BRed}$*${RCol}"
+}
+
+success_msg() {
+	echo -e "\n${BGre}$*${RCol}"
+}
+
+travis_fold_start() {
+	echo "travis_fold:start:$*"
+}
+
+travis_fold_end() {
+	echo "travis_fold:end:$*"
+}

From fed715c1f414aac023cccef77cb3137df9536230 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Thu, 31 Mar 2016 14:37:58 +0400
Subject: [PATCH 07/17] Creating HistoryBlock only before adding an item to it.
 Now invariants always should be kept true, including indexInBlock,
 indexInHistory and !block->items.isEmpty()

Need to backport UniquePointer from other branch.
---
 Telegram/SourceFiles/history.cpp | 251 ++++++++++++++++++-------------
 Telegram/SourceFiles/history.h   |  85 ++++++++---
 2 files changed, 204 insertions(+), 132 deletions(-)

diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 7ea40b30d..f53c91689 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -577,14 +577,8 @@ void ChannelHistory::addNewGroup(const MTPMessageGroup &group) {
 
 	if (onlyImportant()) {
 		if (newLoaded) {
-			HistoryBlock *block = blocks.isEmpty() ? pushBackNewBlock() : blocks.back();
-			HistoryItem *prev = block->items.isEmpty() ? nullptr : block->items.back();
-
-			prev = addMessageGroupAfterPrevToBlock(d, prev, block);
-			if (block->items.isEmpty()) {
-				blocks.pop_back();
-				delete block;
-			}
+			t_assert(!isBuildingFrontBlock());
+			addMessageGroup(d);
 		}
 	} else {
 		setNotLoadedAtBottom();
@@ -641,14 +635,12 @@ HistoryJoined *ChannelHistory::insertJoinedMessage(bool unread) {
 		}
 	}
 
-	// adding new item to new block
-	HistoryBlock *block = pushFrontNewBlock();
+	startBuildingFrontBlock();
 
 	_joinedMessage = HistoryJoined::create(this, inviteDate, inviter, flags);
-	addItemToBlock(_joinedMessage, block);
+	addItemToBlock(_joinedMessage);
 
-	t_assert(blocks.size() > 1);
-	blocks.at(1)->items.front()->previousItemChanged();
+	finishBuildingFrontBlock();
 
 	return _joinedMessage;
 }
@@ -757,15 +749,15 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp
 	}
 
 	if (!isImportant && onlyImportant()) {
-		HistoryItem *item = addToHistory(msg), *prev = isEmpty() ? nullptr : blocks.back()->items.back();
+		HistoryItem *item = addToHistory(msg);
+
+		t_assert(!isBuildingFrontBlock());
+		addMessageGroup([item, this](HistoryItem *previous) -> HistoryItem* { // create(..)
+			return HistoryGroup::create(this, item, previous ? previous->date : item->date);
+		}, [item](HistoryGroup *existing) { // unite(..)
+			existing->uniteWith(item);
+		});
 
-		if (prev && prev->type() == HistoryItemGroup) {
-			static_cast<HistoryGroup*>(prev)->uniteWith(item);
-		} else {
-			QDateTime date = prev ? prev->date : item->date;
-			HistoryBlock *block = prev ? prev->block() : pushBackNewBlock();
-			addItemToBlock(HistoryGroup::create(this, item, date), block);
-		}
 		return item;
 	}
 
@@ -821,22 +813,15 @@ void ChannelHistory::switchMode() {
 
 	clear(true);
 
+	t_assert(!isBuildingFrontBlock());
+
 	newLoaded = _otherNewLoaded;
 	oldLoaded = _otherOldLoaded;
 	if (int count = _otherList.size()) {
-		blocks.reserve(qCeil(count / float64(MessagesPerPage)));
-
+		blocks.reserve((count / MessagesPerPage) + 1);
 		for (int i = 0; i < count;) {
-			HistoryBlock *block = pushBackNewBlock();
-
-			int willAddToBlock = qMin(int(MessagesPerPage), count - i);
-			block->items.reserve(willAddToBlock);
-			for (int till = i + willAddToBlock; i < till; ++i) {
-				t_assert(_otherList.at(i)->detached());
-				addItemToBlock(_otherList.at(i), block);
-			}
-
-			t_assert(!block->items.isEmpty());
+			t_assert(_otherList.at(i)->detached());
+			addItemToBlock(_otherList.at(i));
 		}
 	}
 
@@ -1550,16 +1535,10 @@ void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) {
 }
 
 HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) {
-	t_assert(adding != nullptr);
-	t_assert(adding->detached());
+	t_assert(!isBuildingFrontBlock());
+	addItemToBlock(adding);
 
-	HistoryBlock *block = blocks.isEmpty() ? pushBackNewBlock() : blocks.back();
-
-	adding->attachToBlock(block, block->items.size());
-	block->items.push_back(adding);
-	adding->previousItemChanged();
 	setLastMessage(adding);
-
 	if (newMsg) {
 		newItemAdded(adding);
 	}
@@ -1671,19 +1650,50 @@ void History::newItemAdded(HistoryItem *item) {
 	}
 }
 
-HistoryItem *History::addItemToBlock(HistoryItem *item, HistoryBlock *block) {
+HistoryBlock *History::prepareBlockForAddingItem() {
+	if (isBuildingFrontBlock()) {
+		if (_frontBlock->block) {
+			return _frontBlock->block;
+		}
+
+		HistoryBlock *result = _frontBlock->block = new HistoryBlock(this);
+		if (_frontBlock->expectedItemsCount > 0) {
+			result->items.reserve(_frontBlock->expectedItemsCount + 1);
+		}
+		result->setIndexInHistory(0);
+		blocks.push_front(result);
+		for (int i = 1, l = blocks.size(); i < l; ++i) {
+			blocks.at(i)->setIndexInHistory(i);
+		}
+		return result;
+	}
+
+	bool addNewBlock = blocks.isEmpty() || (blocks.back()->items.size() >= MessagesPerPage);
+	if (!addNewBlock) {
+		return blocks.back();
+	}
+
+	HistoryBlock *result = new HistoryBlock(this);
+	result->setIndexInHistory(blocks.size());
+	blocks.push_back(result);
+
+	result->items.reserve(MessagesPerPage);
+	return result;
+};
+
+void History::addItemToBlock(HistoryItem *item) {
+	t_assert(item != nullptr);
+	t_assert(item->detached());
+
+	HistoryBlock *block = prepareBlockForAddingItem();
+
 	item->attachToBlock(block, block->items.size());
 	block->items.push_back(item);
 	item->previousItemChanged();
-	return item;
-}
 
-HistoryItem *History::addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &group, HistoryItem *prev, HistoryBlock *block) {
-	if (prev && prev->type() == HistoryItemGroup) {
-		static_cast<HistoryGroup*>(prev)->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v);
-		return prev;
+	if (isBuildingFrontBlock() && _frontBlock->expectedItemsCount > 0) {
+		--_frontBlock->expectedItemsCount;
 	}
-	return addItemToBlock(HistoryGroup::create(this, group, prev ? prev->date : date(group.vdate)), block);
 }
 
 void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPMessageGroup> *collapsed) {
@@ -1700,10 +1710,8 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
 
 	const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
 
-	HistoryItem *prev = nullptr;
-	HistoryBlock *block = pushFrontNewBlock();
+	startBuildingFrontBlock(slice.size() + (collapsed ? collapsed->size() : 0));
 
-	block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0));
 	for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
 		--i;
 		HistoryItem *adding = createItem(*i, false, true);
@@ -1714,23 +1722,21 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
 			const MTPDmessageGroup &group(groupsIt->c_messageGroup());
 			if (group.vmin_id.v >= adding->id) break;
 
-			prev = addMessageGroupAfterPrevToBlock(group, prev, block);
+			addMessageGroup(group);
 		}
 
-		prev = addItemToBlock(adding, block);
+		addItemToBlock(adding);
 	}
 	for (; groupsIt != groupsEnd; ++groupsIt) {
 		if (groupsIt->type() != mtpc_messageGroup) continue;
 		const MTPDmessageGroup &group(groupsIt->c_messageGroup());
 
-		prev = addMessageGroupAfterPrevToBlock(group, prev, block);
+		addMessageGroup(group);
 	}
 
-	if (block->items.isEmpty()) {
-		blocks.pop_front();
-		delete block;
-		block = nullptr;
-
+	HistoryBlock *block = finishBuildingFrontBlock();
+	if (!block) {
+		// If no items were added it means we've loaded everything old.
 		oldLoaded = true;
 	} else if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors / lastParticipants
 		bool channel = isChannel();
@@ -1808,28 +1814,6 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
 		}
 	}
 
-	// some checks if there was some message history already
-	if (block && blocks.size() > 1) {
-		HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ...
-		HistoryItem *first = blocks.at(1)->items.front();
-
-		// we've added a new front block, so previous item for
-		// the old first item of a first block was changed
-		first->previousItemChanged();
-
-		// we've added a new front block, now we check if both
-		// last message of the first block and first message of
-		// the second block are groups, if they are - unite them
-		if (first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) {
-			static_cast<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(last));
-			last->destroy();
-
-			// last->destroy() could've destroyed this new block
-			// so we can't rely on this pointer any more
-			block = nullptr;
-		}
-	}
-
 	if (isChannel()) {
 		asChannelHistory()->checkJoinedMessage();
 		asChannelHistory()->checkMaxReadMessageDate();
@@ -1845,14 +1829,11 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
 		if (!lastMsg) setLastMessage(lastImportantMessage());
 	}
 
+	t_assert(!isBuildingFrontBlock());
 	if (!slice.isEmpty() || (isChannel() && collapsed && !collapsed->isEmpty())) {
 		const MTPMessageGroup *groupsBegin = (isChannel() && collapsed) ? collapsed->constData() : 0, *groupsIt = groupsBegin, *groupsEnd = (isChannel() && collapsed) ? (groupsBegin + collapsed->size()) : 0;
 
-		HistoryItem *prev = blocks.isEmpty() ? nullptr : blocks.back()->items.back();
-
-		HistoryBlock *block = pushBackNewBlock();
-
-		block->items.reserve(slice.size() + (collapsed ? collapsed->size() : 0));
+		bool atLeastOneAdded = false;
 		for (auto i = slice.cend(), e = slice.cbegin(); i != e;) {
 			--i;
 			HistoryItem *adding = createItem(*i, false, true);
@@ -1863,25 +1844,22 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
 				const MTPDmessageGroup &group(groupsIt->c_messageGroup());
 				if (group.vmin_id.v >= adding->id) break;
 
-				prev = addMessageGroupAfterPrevToBlock(group, prev, block);
+				addMessageGroup(group);
 			}
 
-			prev = addItemToBlock(adding, block);
+			addItemToBlock(adding);
+			atLeastOneAdded = true;
 		}
 		for (; groupsIt != groupsEnd; ++groupsIt) {
 			if (groupsIt->type() != mtpc_messageGroup) continue;
 			const MTPDmessageGroup &group(groupsIt->c_messageGroup());
 
-			prev = addMessageGroupAfterPrevToBlock(group, prev, block);
+			addMessageGroup(group);
 		}
 
-		if (block->items.isEmpty()) {
+		if (!atLeastOneAdded) {
 			newLoaded = true;
 			setLastMessage(lastImportantMessage());
-
-			blocks.pop_back();
-			delete block;
-			block = nullptr;
 		}
 	}
 
@@ -2181,21 +2159,76 @@ HistoryItem *History::addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex,
 	return newItem;
 }
 
-HistoryBlock *History::pushBackNewBlock() {
-	HistoryBlock *result = new HistoryBlock(this);
-	result->setIndexInHistory(blocks.size());
-	blocks.push_back(result);
-	return result;
+template <typename CreateGroup, typename UniteGroup>
+void History::addMessageGroup(CreateGroup create, UniteGroup unite) {
+	HistoryItem *previous = nullptr;
+	if (isBuildingFrontBlock()) {
+		if (_frontBlock->block) {
+			previous = _frontBlock->block->items.back();
+		}
+	} else {
+		if (!blocks.isEmpty()) {
+			previous = blocks.back()->items.back();
+		}
+	}
+
+	if (previous && previous->type() == HistoryItemGroup) {
+		unite(static_cast<HistoryGroup*>(previous));
+		return;
+	}
+
+	HistoryGroup *result = create(previous);
+	if (isBuildingFrontBlock()) {
+		addItemToBuildingFrontBlock(result);
+	} else {
+		addItemToBackBlock(result);
+	}
 }
 
-HistoryBlock *History::pushFrontNewBlock() {
-	HistoryBlock *result = new HistoryBlock(this);
-	result->setIndexInHistory(0);
-	blocks.push_front(result);
-	for (int i = 1, l = blocks.size(); i < l; ++i) {
-		blocks.at(i)->setIndexInHistory(i);
+void History::addMessageGroup(const MTPDmessageGroup &group) {
+	addMessageGroup([&group, this](HistoryItem *previous) -> HistoryItem* { // create(..)
+		return HistoryGroup::create(this, group, previous ? previous->date : date(group.vdate));
+	}, [&group](HistoryGroup *existing) { // unite(..)
+		existing->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v);
+	});
+}
+
+void History::startBuildingFrontBlock(int expectedItemsCount) {
+	t_assert(!isBuildingFrontBlock());
+	t_assert(expectedItemsCount > 0);
+
+	_frontBlock.reset(new BuildingBlock());
+	_frontBlock->expectedItemsCount = expectedItemsCount;
+}
+
+HistoryBlock *History::finishBuildingFrontBlock() {
+	t_assert(isBuildingFrontBlock());
+
+	// Some checks if there was some message history already
+	HistoryBlock *block = _frontBlock->block;
+	if (block && blocks.size() > 1) {
+		HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ...
+		HistoryItem *first = blocks.at(1)->items.front();
+
+		// we've added a new front block, so previous item for
+		// the old first item of a first block was changed
+		first->previousItemChanged();
+
+		// we've added a new front block, now we check if both
+		// last message of the first block and first message of
+		// the second block are groups, if they are - unite them
+		if (first->type() == HistoryItemGroup && last->type() == HistoryItemGroup) {
+			static_cast<HistoryGroup*>(first)->uniteWith(static_cast<HistoryGroup*>(last));
+			last->destroy();
+
+			// last->destroy() could've destroyed this new block
+			// so we can't rely on this pointer any more
+			block = _frontBlock->block;
+		}
 	}
-	return result;
+
+	_frontBlock.clear();
+	return block;
 }
 
 void History::clearNotifications() {
@@ -2572,6 +2605,10 @@ void History::changeMsgId(MsgId oldId, MsgId newId) {
 void History::removeBlock(HistoryBlock *block) {
 	t_assert(block->items.isEmpty());
 
+	if (_frontBlock && block == _frontBlock->block) {
+		_frontBlock->block = nullptr;
+	}
+
 	int index = block->indexInHistory();
 	blocks.removeAt(index);
 	for (int i = index, l = blocks.size(); i < l; ++i) {
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index 497dd1060..b42e7e8b0 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -470,19 +470,64 @@ protected:
 	void clearOnDestroy();
 	HistoryItem *addNewToLastBlock(const MTPMessage &msg, NewMessageType type);
 
+	friend class HistoryBlock;
+
+	// this method just removes a block from the blocks list
+	// when the last item from this block was detached and
+	// calls the required previousItemChanged()
+	void removeBlock(HistoryBlock *block);
+
+	void clearBlocks(bool leaveItems);
+
+	HistoryItem *createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem);
+	HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg);
+	HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption);
+	HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption);
+
+	HistoryItem *addNewItem(HistoryItem *adding, bool newMsg);
+	HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex);
+
+	// All this methods add a new item to the first or last block
+	// depending on if we are in isBuildingFronBlock() state.
+	// The last block is created on the go if it is needed.
+
+	// If the previous item is a message group the new group is
+	// not created but is just united with the previous one.
+	// create(HistoryItem *previous) should return a new HistoryGroup*
+	// unite(HistoryGroup *existing) should unite a new group with an existing
+	template <typename CreateGroup, typename UniteGroup>
+	void addMessageGroup(CreateGroup create, UniteGroup unite);
+	void addMessageGroup(const MTPDmessageGroup &group);
+
+	// Adds the item to the back or front block, depending on
+	// isBuildingFrontBlock(), creating the block if necessary.
+	void addItemToBlock(HistoryItem *item);
+
+	// Usually all new items are added to the last block.
+	// Only when we scroll up and add a new slice to the
+	// front we want to create a new front block.
+	void startBuildingFrontBlock(int expectedItemsCount = 1);
+	HistoryBlock *finishBuildingFrontBlock(); // Returns the built block or nullptr if nothing was added.
+	bool isBuildingFrontBlock() const {
+		return !_buildingFrontBlock.isNull();
+	}
+
 private:
 
-	enum Flag {
+	enum class Flag {
 		f_has_pending_resized_items = (1 << 0),
-		f_pending_resize = (1 << 1),
+		f_pending_resize            = (1 << 1),
 	};
 	Q_DECLARE_FLAGS(Flags, Flag);
-	Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) Q_DECL_NOTHROW {
+	Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept {
 		return QFlags<Flags::enum_type>(f1) | f2;
 	}
-	Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) Q_DECL_NOTHROW {
+	Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept {
 		return f2 | f1;
 	}
+	Q_DECL_CONSTEXPR friend inline QFlags<Flags::enum_type> operator~(Flags::enum_type f) noexcept {
+		return ~QFlags<Flags::enum_type>(f);
+	}
 	Flags _flags;
 
 	ChatListLinksMap _chatListLinks;
@@ -497,28 +542,18 @@ private:
 	MediaOverviewIds overviewIds[OverviewCount];
 	int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
 
-	friend class HistoryBlock;
-	friend class ChannelHistory;
+	// A pointer to the block that is currently being built.
+	// We hold this pointer so we can destroy it while building
+	// and then create a new one if it is necessary.
+	struct BuildingBlock {
+		int expectedItemsCount = 0; // optimization for block->items.reserve() call
+		HistoryBlock *block = nullptr;
+	};
+	UniquePointer<BuildingBlock> _buildingFrontBlock;
 
-	// this method just removes a block from the blocks list
-	// when the last item from this block was detached and
-	// calls the required previousItemChanged()
-	void removeBlock(HistoryBlock *block);
-
-	void clearBlocks(bool leaveItems);
-
-	HistoryItem *createItem(const MTPMessage &msg, bool applyServiceAction, bool detachExistingItem);
-	HistoryItem *createItemForwarded(MsgId id, MTPDmessage::Flags flags, QDateTime date, int32 from, HistoryMessage *msg);
-	HistoryItem *createItemDocument(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, DocumentData *doc, const QString &caption);
-	HistoryItem *createItemPhoto(MsgId id, MTPDmessage::Flags flags, int32 viaBotId, MsgId replyTo, QDateTime date, int32 from, PhotoData *photo, const QString &caption);
-
-	HistoryItem *addItemToBlock(HistoryItem *item, HistoryBlock *block);
-	HistoryItem *addNewItem(HistoryItem *adding, bool newMsg);
-	HistoryItem *addMessageGroupAfterPrevToBlock(const MTPDmessageGroup &group, HistoryItem *prev, HistoryBlock *block);
-	HistoryItem *addNewInTheMiddle(HistoryItem *newItem, int32 blockIndex, int32 itemIndex);
-
-	HistoryBlock *pushBackNewBlock();
-	HistoryBlock *pushFrontNewBlock();
+	// Creates if necessary a new block for adding item.
+	// Depending on isBuildingFrontBlock() gets front or back block.
+	HistoryBlock *prepareBlockForAddingItem();
 
  };
 

From 40fddc96976abfefa229a9ed64cd167ca218abf7 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Thu, 31 Mar 2016 15:18:21 +0400
Subject: [PATCH 08/17] UniquePointer backported. Fixed unifying of adding new
 history items.

---
 Telegram/SourceFiles/history.cpp            |  46 +++----
 Telegram/SourceFiles/history.h              |   6 +-
 Telegram/SourceFiles/mtproto/connection.cpp |   2 +-
 Telegram/SourceFiles/types.h                | 135 ++++++++++++++++++--
 4 files changed, 149 insertions(+), 40 deletions(-)

diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index f53c91689..3231bf89f 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -752,7 +752,7 @@ HistoryItem *ChannelHistory::addNewToBlocks(const MTPMessage &msg, NewMessageTyp
 		HistoryItem *item = addToHistory(msg);
 
 		t_assert(!isBuildingFrontBlock());
-		addMessageGroup([item, this](HistoryItem *previous) -> HistoryItem* { // create(..)
+		addMessageGroup([item, this](HistoryItem *previous) -> HistoryGroup* { // create(..)
 			return HistoryGroup::create(this, item, previous ? previous->date : item->date);
 		}, [item](HistoryGroup *existing) { // unite(..)
 			existing->uniteWith(item);
@@ -819,7 +819,7 @@ void ChannelHistory::switchMode() {
 	oldLoaded = _otherOldLoaded;
 	if (int count = _otherList.size()) {
 		blocks.reserve((count / MessagesPerPage) + 1);
-		for (int i = 0; i < count;) {
+		for (int i = 0; i < count; ++i) {
 			t_assert(_otherList.at(i)->detached());
 			addItemToBlock(_otherList.at(i));
 		}
@@ -1652,13 +1652,13 @@ void History::newItemAdded(HistoryItem *item) {
 
 HistoryBlock *History::prepareBlockForAddingItem() {
 	if (isBuildingFrontBlock()) {
-		if (_frontBlock->block) {
-			return _frontBlock->block;
+		if (_buildingFrontBlock->block) {
+			return _buildingFrontBlock->block;
 		}
 
-		HistoryBlock *result = _frontBlock->block = new HistoryBlock(this);
-		if (_frontBlock->expectedItemsCount > 0) {
-			result->items.reserve(_frontBlock->expectedItemsCount + 1);
+		HistoryBlock *result = _buildingFrontBlock->block = new HistoryBlock(this);
+		if (_buildingFrontBlock->expectedItemsCount > 0) {
+			result->items.reserve(_buildingFrontBlock->expectedItemsCount + 1);
 		}
 		result->setIndexInHistory(0);
 		blocks.push_front(result);
@@ -1691,8 +1691,8 @@ void History::addItemToBlock(HistoryItem *item) {
 	block->items.push_back(item);
 	item->previousItemChanged();
 
-	if (isBuildingFrontBlock() && _frontBlock->expectedItemsCount > 0) {
-		--_frontBlock->expectedItemsCount;
+	if (isBuildingFrontBlock() && _buildingFrontBlock->expectedItemsCount > 0) {
+		--_buildingFrontBlock->expectedItemsCount;
 	}
 }
 
@@ -2163,8 +2163,8 @@ template <typename CreateGroup, typename UniteGroup>
 void History::addMessageGroup(CreateGroup create, UniteGroup unite) {
 	HistoryItem *previous = nullptr;
 	if (isBuildingFrontBlock()) {
-		if (_frontBlock->block) {
-			previous = _frontBlock->block->items.back();
+		if (_buildingFrontBlock->block) {
+			previous = _buildingFrontBlock->block->items.back();
 		}
 	} else {
 		if (!blocks.isEmpty()) {
@@ -2174,19 +2174,13 @@ void History::addMessageGroup(CreateGroup create, UniteGroup unite) {
 
 	if (previous && previous->type() == HistoryItemGroup) {
 		unite(static_cast<HistoryGroup*>(previous));
-		return;
-	}
-
-	HistoryGroup *result = create(previous);
-	if (isBuildingFrontBlock()) {
-		addItemToBuildingFrontBlock(result);
 	} else {
-		addItemToBackBlock(result);
+		addItemToBlock(create(previous));
 	}
 }
 
 void History::addMessageGroup(const MTPDmessageGroup &group) {
-	addMessageGroup([&group, this](HistoryItem *previous) -> HistoryItem* { // create(..)
+	addMessageGroup([&group, this](HistoryItem *previous) -> HistoryGroup* { // create(..)
 		return HistoryGroup::create(this, group, previous ? previous->date : date(group.vdate));
 	}, [&group](HistoryGroup *existing) { // unite(..)
 		existing->uniteWith(group.vmin_id.v, group.vmax_id.v, group.vcount.v);
@@ -2197,15 +2191,15 @@ void History::startBuildingFrontBlock(int expectedItemsCount) {
 	t_assert(!isBuildingFrontBlock());
 	t_assert(expectedItemsCount > 0);
 
-	_frontBlock.reset(new BuildingBlock());
-	_frontBlock->expectedItemsCount = expectedItemsCount;
+	_buildingFrontBlock.reset(new BuildingBlock());
+	_buildingFrontBlock->expectedItemsCount = expectedItemsCount;
 }
 
 HistoryBlock *History::finishBuildingFrontBlock() {
 	t_assert(isBuildingFrontBlock());
 
 	// Some checks if there was some message history already
-	HistoryBlock *block = _frontBlock->block;
+	HistoryBlock *block = _buildingFrontBlock->block;
 	if (block && blocks.size() > 1) {
 		HistoryItem *last = block->items.back(); // ... item, item, item, last ], [ first, item, item ...
 		HistoryItem *first = blocks.at(1)->items.front();
@@ -2223,11 +2217,11 @@ HistoryBlock *History::finishBuildingFrontBlock() {
 
 			// last->destroy() could've destroyed this new block
 			// so we can't rely on this pointer any more
-			block = _frontBlock->block;
+			block = _buildingFrontBlock->block;
 		}
 	}
 
-	_frontBlock.clear();
+	_buildingFrontBlock.clear();
 	return block;
 }
 
@@ -2605,8 +2599,8 @@ void History::changeMsgId(MsgId oldId, MsgId newId) {
 void History::removeBlock(HistoryBlock *block) {
 	t_assert(block->items.isEmpty());
 
-	if (_frontBlock && block == _frontBlock->block) {
-		_frontBlock->block = nullptr;
+	if (_buildingFrontBlock && block == _buildingFrontBlock->block) {
+		_buildingFrontBlock->block = nullptr;
 	}
 
 	int index = block->indexInHistory();
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index b42e7e8b0..1dd9dd95e 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -1049,9 +1049,9 @@ struct HistoryMessageReply : public BaseComponent<HistoryMessageReply> {
 	HistoryMessageReply &operator=(HistoryMessageReply &&other) {
 		replyToMsgId = other.replyToMsgId;
 		std::swap(replyToMsg, other.replyToMsg);
-		replyToLnk = std11::move(other.replyToLnk);
-		replyToName = std11::move(other.replyToName);
-		replyToText = std11::move(other.replyToText);
+		replyToLnk = std_::move(other.replyToLnk);
+		replyToName = std_::move(other.replyToName);
+		replyToText = std_::move(other.replyToText);
 		replyToVersion = other.replyToVersion;
 		_maxReplyWidth = other._maxReplyWidth;
 		std::swap(_replyToVia, other._replyToVia);
diff --git a/Telegram/SourceFiles/mtproto/connection.cpp b/Telegram/SourceFiles/mtproto/connection.cpp
index d05737382..49cbd9f48 100644
--- a/Telegram/SourceFiles/mtproto/connection.cpp
+++ b/Telegram/SourceFiles/mtproto/connection.cpp
@@ -62,7 +62,7 @@ bool parsePQ(const string &pqStr, string &pStr, string &qStr) {
 			break;
 		}
 	}
-	if (p > q) swap(p, q);
+	if (p > q) std::swap(p, q);
 
 	pStr.resize(4);
 	uchar *pChars = (uchar*)&pStr[0];
diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h
index 836b7af37..27515b177 100644
--- a/Telegram/SourceFiles/types.h
+++ b/Telegram/SourceFiles/types.h
@@ -215,31 +215,86 @@ typedef double float64;
 
 using std::string;
 using std::exception;
-using std::swap;
 
-// we copy some parts of C++11 std:: library, because on OS X 10.6+
-// version we can use C++11, but we can't use its library :(
-namespace std11 {
+// we copy some parts of C++11/14/17 std:: library, because on OS X 10.6+
+// version we can use C++11/14/17, but we can not use its library :(
+namespace std_ {
+
+template <typename T, T V>
+struct integral_constant {
+	static constexpr T value = V;
+
+	using value_type = T;
+	using type = integral_constant<T, V>;
+
+	constexpr operator value_type() const noexcept {
+		return (value);
+	}
+
+	constexpr value_type operator()() const noexcept {
+		return (value);
+	}
+};
+
+using true_type = integral_constant<bool, true>;
+using false_type = integral_constant<bool, false>;
 
 template <typename T>
 struct remove_reference {
-	typedef T type;
+	using type = T;
 };
 template <typename T>
 struct remove_reference<T&> {
-	typedef T type;
+	using type = T;
 };
 template <typename T>
 struct remove_reference<T&&> {
-	typedef T type;
+	using type = T;
 };
 
 template <typename T>
-inline typename remove_reference<T>::type &&move(T &&value) {
+struct is_lvalue_reference : false_type {
+};
+template <typename T>
+struct is_lvalue_reference<T&> : true_type {
+};
+
+template <typename T>
+struct is_rvalue_reference : false_type {
+};
+template <typename T>
+struct is_rvalue_reference<T&&> : true_type {
+};
+
+template <typename T>
+inline constexpr T &&forward(typename remove_reference<T>::type &value) noexcept {
+	return static_cast<T&&>(value);
+}
+template <typename T>
+inline constexpr T &&forward(typename remove_reference<T>::type &&value) noexcept {
+	static_assert(!is_lvalue_reference<T>::value, "bad forward call");
+	return static_cast<T&&>(value);
+}
+
+template <typename T>
+inline constexpr typename remove_reference<T>::type &&move(T &&value) noexcept {
 	return static_cast<typename remove_reference<T>::type&&>(value);
 }
 
-} // namespace std11
+template <typename T>
+struct add_const {
+	using type = const T;
+};
+template <typename T>
+using add_const_t = typename add_const<T>::type;
+template <typename T>
+constexpr add_const_t<T> &as_const(T& t) noexcept {
+	return t;
+}
+template <typename T>
+void as_const(const T&&) = delete;
+
+} // namespace std_
 
 #include "logs.h"
 
@@ -669,6 +724,66 @@ inline RefPairImplementation<T1, T2> RefPairCreator(T1 &first, T2 &second) {
 
 #define RefPair(Type1, Name1, Type2, Name2) Type1 Name1; Type2 Name2; RefPairCreator(Name1, Name2)
 
+template <typename T>
+class UniquePointer {
+public:
+	explicit UniquePointer(T *p = nullptr) : _p(p) {
+	}
+	UniquePointer(const UniquePointer<T> &other) = delete;
+	UniquePointer &operator=(const UniquePointer<T> &other) = delete;
+	UniquePointer(UniquePointer<T> &&other) : _p(other.release()) {
+	}
+	UniquePointer &operator=(UniquePointer<T> &&other) {
+		std::swap(_p, other._p);
+		return *this;
+	}
+	template <typename U>
+	UniquePointer(UniquePointer<U> &&other) : _p(other.release()) {
+	}
+	T *data() const {
+		return _p;
+	}
+	T *release() {
+		return getPointerAndReset(_p);
+	}
+	void reset(T *p = nullptr) {
+		*this = UniquePointer<T>(p);
+	}
+	bool isNull() const {
+		return data() == nullptr;
+	}
+
+	void clear() {
+		reset();
+	}
+	T *operator->() const {
+		return data();
+	}
+	T &operator*() const {
+		t_assert(!isNull());
+		return *data();
+	}
+	explicit operator bool() const {
+		return !isNull();
+	}
+	~UniquePointer() {
+		delete data();
+	}
+
+private:
+	T *_p;
+
+};
+template <typename T, class... Args>
+inline UniquePointer<T> MakeUnique(Args&&... args) {
+	return UniquePointer<T>(new T(std_::forward<Args>(args)...));
+}
+
+template <typename T, class... Args>
+inline QSharedPointer<T> MakeShared(Args&&... args) {
+	return QSharedPointer<T>(new T(std_::forward<Args>(args)...));
+}
+
 template <typename I>
 inline void destroyImplementation(I *&ptr) {
 	if (ptr) {
@@ -715,7 +830,7 @@ struct ComponentWrapTemplate {
 		((Type*)location)->~Type();
 	}
 	static void Move(void *location, void *waslocation) {
-		*(Type*)location = std11::move(*(Type*)waslocation);
+		*(Type*)location = std_::move(*(Type*)waslocation);
 	}
 };
 

From a23470f4b8cb63e63462e8e8b0f2c1208faf4db1 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Thu, 31 Mar 2016 15:55:25 +0400
Subject: [PATCH 09/17] Fixed possible crash in NotifyWindow click handler.
 Adding information about crashed string in TextBlock parser.

---
 Telegram/SourceFiles/app.cpp      |   2 +-
 Telegram/SourceFiles/gui/text.cpp |   7 +
 Telegram/SourceFiles/logs.cpp     | 219 ++++++++++++++++--------------
 Telegram/SourceFiles/logs.h       |  10 +-
 Telegram/SourceFiles/types.h      |   2 +-
 Telegram/SourceFiles/window.cpp   |   6 +-
 6 files changed, 141 insertions(+), 105 deletions(-)

diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index 731a57ee1..18dfe7ae6 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -447,7 +447,7 @@ namespace App {
 					QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone;
 
 					if (!minimal && d.is_self() && uname != data->username) {
-						SignalHandlers::setSelfUsername(uname);
+						SignalHandlers::setCrashAnnotation("Username", uname);
 					}
 					data->setName(fname, lname, pname, uname);
 					if (d.has_photo()) {
diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp
index f350a1f3e..b12fdfe3f 100644
--- a/Telegram/SourceFiles/gui/text.cpp
+++ b/Telegram/SourceFiles/gui/text.cpp
@@ -3533,7 +3533,14 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi
 		layout.beginLayout();
 		layout.createLine();
 
+		bool logCrashString = (rand_value<uchar>() % 4 == 1);
+		if (logCrashString) {
+			SignalHandlers::setCrashAnnotationRef("CrashString", &part);
+		}
 		BlockParser parser(&engine, this, minResizeWidth, _from, part);
+		if (logCrashString) {
+			SignalHandlers::clearCrashAnnotationRef("CrashString");
+		}
 
 		layout.endLayout();
 	}
diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp
index 68fa217d0..916193635 100644
--- a/Telegram/SourceFiles/logs.cpp
+++ b/Telegram/SourceFiles/logs.cpp
@@ -614,119 +614,127 @@ void _moveOldDataFiles(const QString &wasDir) {
 
 namespace SignalHandlers {
 
-	typedef std::map<std::string, std::string> AnnotationsMap;
-	AnnotationsMap ProcessAnnotations;
+namespace internal {
+	using Annotations = std::map<std::string, std::string>;
+	using AnnotationRefs = std::map<std::string, const QString*>;
+
+	Annotations ProcessAnnotations;
+	AnnotationRefs ProcessAnnotationRefs;
 
 #ifndef TDESKTOP_DISABLE_CRASH_REPORTS
 
-	QString CrashDumpPath;
-	FILE *CrashDumpFile = nullptr;
-	int CrashDumpFileNo = 0;
+	QString ReportPath;
+	FILE *ReportFile = nullptr;
+	int ReportFileNo = 0;
 	char LaunchedDateTimeStr[32] = { 0 };
 	char LaunchedBinaryName[256] = { 0 };
 
-	void _writeChar(char ch) {
-		fwrite(&ch, 1, 1, CrashDumpFile);
+	void writeChar(char ch) {
+		fwrite(&ch, 1, 1, ReportFile);
 	}
 
-	dump::~dump() {
-		if (CrashDumpFile) {
-			fflush(CrashDumpFile);
-		}
-	}
-
-	const dump &operator<<(const dump &stream, const char *str) {
-		if (!CrashDumpFile) return stream;
-
-		fwrite(str, 1, strlen(str), CrashDumpFile);
-		return stream;
-	}
-
-    const dump &operator<<(const dump &stream, const wchar_t *str) {
-        if (!CrashDumpFile) return stream;
-
-        for (int i = 0, l = wcslen(str); i < l; ++i) {
-            if (str[i] >= 0 && str[i] < 128) {
-                _writeChar(char(str[i]));
-            } else {
-                _writeChar('?');
-            }
-        }
-        return stream;
-    }
-
 	template <bool Unsigned, typename Type>
-	struct _writeNumberSignAndRemoveIt {
+	struct writeNumberSignAndRemoveIt {
 		static void call(Type &number) {
 			if (number < 0) {
-				_writeChar('-');
+				writeChar('-');
 				number = -number;
 			}
 		}
 	};
 	template <typename Type>
-	struct _writeNumberSignAndRemoveIt<true, Type> {
+	struct writeNumberSignAndRemoveIt<true, Type> {
 		static void call(Type &number) {
 		}
 	};
 
 	template <typename Type>
-	const dump &_writeNumber(const dump &stream, Type number) {
-		if (!CrashDumpFile) return stream;
+	const dump &writeNumber(const dump &stream, Type number) {
+		if (!ReportFile) return stream;
 
-		_writeNumberSignAndRemoveIt<(Type(-1) > Type(0)), Type>::call(number);
+		writeNumberSignAndRemoveIt<(Type(-1) > Type(0)), Type>::call(number);
 		Type upper = 1, prev = number / 10;
 		while (prev >= upper) {
 			upper *= 10;
 		}
 		while (upper > 0) {
 			int digit = (number / upper);
-			_writeChar('0' + digit);
+			internal::writeChar('0' + digit);
 			number -= digit * upper;
 			upper /= 10;
 		}
 		return stream;
 	}
 
+} // namespace internal
+
+	dump::~dump() {
+		if (internal::ReportFile) {
+			fflush(internal::ReportFile);
+		}
+	}
+
+	const dump &operator<<(const dump &stream, const char *str) {
+		if (!internal::ReportFile) return stream;
+
+		fwrite(str, 1, strlen(str), internal::ReportFile);
+		return stream;
+	}
+
+    const dump &operator<<(const dump &stream, const wchar_t *str) {
+        if (!internal::ReportFile) return stream;
+
+        for (int i = 0, l = wcslen(str); i < l; ++i) {
+            if (str[i] >= 0 && str[i] < 128) {
+				internal::writeChar(char(str[i]));
+            } else {
+				internal::writeChar('?');
+            }
+        }
+        return stream;
+    }
+
 	const dump &operator<<(const dump &stream, int num) {
-		return _writeNumber(stream, num);
+		return internal::writeNumber(stream, num);
 	}
 
 	const dump &operator<<(const dump &stream, unsigned int num) {
-		return _writeNumber(stream, num);
+		return internal::writeNumber(stream, num);
 	}
 
 	const dump &operator<<(const dump &stream, unsigned long num) {
-		return _writeNumber(stream, num);
+		return internal::writeNumber(stream, num);
 	}
 
 	const dump &operator<<(const dump &stream, unsigned long long num) {
-		return _writeNumber(stream, num);
+		return internal::writeNumber(stream, num);
 	}
 
 	const dump &operator<<(const dump &stream, double num) {
 		if (num < 0) {
-			_writeChar('-');
+			internal::writeChar('-');
 			num = -num;
 		}
-		_writeNumber(stream, uint64(floor(num)));
-		_writeChar('.');
+		internal::writeNumber(stream, uint64(floor(num)));
+		internal::writeChar('.');
 		num -= floor(num);
 		for (int i = 0; i < 4; ++i) {
 			num *= 10;
 			int digit = int(floor(num));
-			_writeChar('0' + digit);
+			internal::writeChar('0' + digit);
 			num -= digit;
 		}
 		return stream;
 	}
 
-	Qt::HANDLE LoggingCrashThreadId = 0;
-	bool LoggingCrashHeaderWritten = false;
-	QMutex LoggingCrashMutex;
+namespace internal {
 
-	const char *BreakpadDumpPath = 0;
-    const wchar_t *BreakpadDumpPathW = 0;
+	Qt::HANDLE ReportingThreadId = nullptr;
+	bool ReportingHeaderWritten = false;
+	QMutex ReportingMutex;
+
+	const char *BreakpadDumpPath = nullptr;
+	const wchar_t *BreakpadDumpPathW = nullptr;
 
 #if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64
 	struct sigaction SIG_def[32];
@@ -753,14 +761,19 @@ namespace SignalHandlers {
 		}
 
 		Qt::HANDLE thread = QThread::currentThreadId();
-		if (thread == LoggingCrashThreadId) return;
+		if (thread == ReportingThreadId) return;
 
-		QMutexLocker lock(&LoggingCrashMutex);
-		LoggingCrashThreadId = thread;
+		QMutexLocker lock(&ReportingMutex);
+		ReportingThreadId = thread;
 
-		if (!LoggingCrashHeaderWritten) {
-			LoggingCrashHeaderWritten = true;
-			const AnnotationsMap c_ProcessAnnotations(ProcessAnnotations);
+		if (!ReportingHeaderWritten) {
+			ReportingHeaderWritten = true;
+
+			for (const auto &i : ProcessAnnotationRefs) {
+				ProcessAnnotations[i.first] = i.second->toUtf8().constData();
+			}
+
+			const Annotations c_ProcessAnnotations(ProcessAnnotations);
 			for (const auto &i : c_ProcessAnnotations) {
 				dump() << i.first.c_str() << ": " << i.second.c_str() << "\n";
 			}
@@ -843,7 +856,7 @@ namespace SignalHandlers {
 
 		dump() << "\nBacktrace:\n";
 
-		backtrace_symbols_fd(addresses, size, CrashDumpFileNo);
+		backtrace_symbols_fd(addresses, size, ReportFileNo);
 
 #else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
 		dump() << "\nBacktrace:\n";
@@ -853,7 +866,7 @@ namespace SignalHandlers {
 
 		dump() << "\n";
 
-		LoggingCrashThreadId = 0;
+		ReportingThreadId = nullptr;
 	}
 
 	bool SetSignalHandlers = true;
@@ -890,8 +903,12 @@ namespace SignalHandlers {
 
 #endif // !TDESKTOP_DISABLE_CRASH_REPORTS
 
+} // namespace internal
+
 	void StartCrashHandler() {
 #ifndef TDESKTOP_DISABLE_CRASH_REPORTS
+		using internal::ProcessAnnotations;
+
 		ProcessAnnotations["Binary"] = cExeName().toUtf8().constData();
 		ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData();
 		ProcessAnnotations["Version"] = (cBetaVersion() ? qsl("%1 beta").arg(cBetaVersion()) : (cDevVersion() ? qsl("%1 dev") : qsl("%1")).arg(AppVersion)).toUtf8().constData();
@@ -903,10 +920,10 @@ namespace SignalHandlers {
 		QDir().mkpath(dumpspath);
 
 #ifdef Q_OS_WIN
-		BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
+		internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
 			dumpspath.toStdWString(),
 			/*FilterCallback*/ 0,
-			DumpCallback,
+			internal::DumpCallback,
 			/*context*/	0,
 			true
 		);
@@ -914,16 +931,16 @@ namespace SignalHandlers {
 
 #ifdef MAC_USE_BREAKPAD
 #ifndef _DEBUG
-		BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
+		internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
 			QFile::encodeName(dumpspath).toStdString(),
 			/*FilterCallback*/ 0,
-			DumpCallback,
+			internal::DumpCallback,
 			/*context*/ 0,
 			true,
 			0
 		);
 #endif // !_DEBUG
-		SetSignalHandlers = false;
+		internal::SetSignalHandlers = false;
 #else // MAC_USE_BREAKPAD
 		crashpad::CrashpadClient crashpad_client;
 		std::string handler = (cExeDir() + cExeName() + qsl("/Contents/Helpers/crashpad_handler")).toUtf8().constData();
@@ -938,10 +955,10 @@ namespace SignalHandlers {
 		}
 #endif // else for MAC_USE_BREAKPAD
 #elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32
-		BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
+		internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
 			google_breakpad::MinidumpDescriptor(QFile::encodeName(dumpspath).toStdString()),
 			/*FilterCallback*/ 0,
-			DumpCallback,
+			internal::DumpCallback,
 			/*context*/ 0,
 			true,
 			-1
@@ -954,9 +971,8 @@ namespace SignalHandlers {
 #ifndef TDESKTOP_DISABLE_CRASH_REPORTS
 
 #if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
-		if (BreakpadExceptionHandler) {
-			google_breakpad::ExceptionHandler *h = BreakpadExceptionHandler;
-			BreakpadExceptionHandler = 0;
+		if (internal::BreakpadExceptionHandler) {
+			google_breakpad::ExceptionHandler *h = getPointerAndReset(internal::BreakpadExceptionHandler);
 			delete h;
 		}
 #endif // !Q_OS_MAC || MAC_USE_BREAKPAD
@@ -966,15 +982,16 @@ namespace SignalHandlers {
 
 	Status start() {
 #ifndef TDESKTOP_DISABLE_CRASH_REPORTS
-		CrashDumpPath = cWorkingDir() + qsl("tdata/working");
+		using internal::ReportPath;
+		ReportPath = cWorkingDir() + qsl("tdata/working");
 
 #ifdef Q_OS_WIN
 		FILE *f = nullptr;
-		if (_wfopen_s(&f, CrashDumpPath.toStdWString().c_str(), L"rb") != 0) {
+		if (_wfopen_s(&f, ReportPath.toStdWString().c_str(), L"rb") != 0) {
 			f = nullptr;
 		} else {
 #else // !Q_OS_WIN
-		if (FILE *f = fopen(QFile::encodeName(CrashDumpPath).constData(), "rb")) {
+		if (FILE *f = fopen(QFile::encodeName(ReportPath).constData(), "rb")) {
 #endif // else for !Q_OS_WIN
 			QByteArray lastdump;
 			char buffer[256 * 1024] = { 0 };
@@ -986,7 +1003,7 @@ namespace SignalHandlers {
 
 			Sandbox::SetLastCrashDump(lastdump);
 
-			LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(CrashDumpPath).arg(lastdump.size()));
+			LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(ReportPath).arg(lastdump.size()));
 
 			return LastCrashed;
 		}
@@ -997,28 +1014,28 @@ namespace SignalHandlers {
 
 	Status restart() {
 #ifndef TDESKTOP_DISABLE_CRASH_REPORTS
-		if (CrashDumpFile) {
+		if (internal::ReportFile) {
 			return Started;
 		}
 
 #ifdef Q_OS_WIN
-		if (_wfopen_s(&CrashDumpFile, CrashDumpPath.toStdWString().c_str(), L"wb") != 0) {
-			CrashDumpFile = nullptr;
+		if (_wfopen_s(&internal::ReportFile, internal::ReportPath.toStdWString().c_str(), L"wb") != 0) {
+			internal::ReportFile = nullptr;
 		}
 #else // Q_OS_WIN
 		CrashDumpFile = fopen(QFile::encodeName(CrashDumpPath).constData(), "wb");
 #endif // else for Q_OS_WIN
-		if (CrashDumpFile) {
+		if (internal::ReportFile) {
 #ifdef Q_OS_WIN
-			CrashDumpFileNo = _fileno(CrashDumpFile);
+			internal::ReportFileNo = _fileno(internal::ReportFile);
 #else // Q_OS_WIN
-			CrashDumpFileNo = fileno(CrashDumpFile);
+			CrashDumpFileNo = fileno(internal::ReportFile);
 #endif // else for Q_OS_WIN
-			if (SetSignalHandlers) {
+			if (internal::SetSignalHandlers) {
 #ifndef Q_OS_WIN
 				struct sigaction sigact;
 
-				sigact.sa_sigaction = SignalHandlers::Handler;
+				sigact.sa_sigaction = SignalHandlers::internal::Handler;
 				sigemptyset(&sigact.sa_mask);
 				sigact.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
 
@@ -1029,16 +1046,16 @@ namespace SignalHandlers {
 				sigaction(SIGBUS, &sigact, &SIG_def[SIGBUS]);
 				sigaction(SIGSYS, &sigact, &SIG_def[SIGSYS]);
 #else // !Q_OS_WIN
-				signal(SIGABRT, SignalHandlers::Handler);
-				signal(SIGSEGV, SignalHandlers::Handler);
-				signal(SIGILL, SignalHandlers::Handler);
-				signal(SIGFPE, SignalHandlers::Handler);
+				signal(SIGABRT, SignalHandlers::internal::Handler);
+				signal(SIGSEGV, SignalHandlers::internal::Handler);
+				signal(SIGILL, SignalHandlers::internal::Handler);
+				signal(SIGFPE, SignalHandlers::internal::Handler);
 #endif // else for !Q_OS_WIN
 			}
 			return Started;
 		}
 
-		LOG(("FATAL: Could not open '%1' for writing!").arg(CrashDumpPath));
+		LOG(("FATAL: Could not open '%1' for writing!").arg(internal::ReportPath));
 
 		return CantOpen;
 #else // !TDESKTOP_DISABLE_CRASH_REPORTS
@@ -1049,29 +1066,33 @@ namespace SignalHandlers {
 	void finish() {
 #ifndef TDESKTOP_DISABLE_CRASH_REPORTS
 		FinishCrashHandler();
-		if (CrashDumpFile) {
-			fclose(CrashDumpFile);
-			CrashDumpFile = nullptr;
+		if (internal::ReportFile) {
+			fclose(internal::ReportFile);
+			internal::ReportFile = nullptr;
 
 #ifdef Q_OS_WIN
-			_wunlink(CrashDumpPath.toStdWString().c_str());
+			_wunlink(internal::ReportPath.toStdWString().c_str());
 #else // Q_OS_WIN
-			unlink(CrashDumpPath.toUtf8().constData());
+			unlink(internal::ReportPath.toUtf8().constData());
 #endif // else for Q_OS_WIN
 		}
 #endif // !TDESKTOP_DISABLE_CRASH_REPORTS
 	}
 
-	void setSelfUsername(const QString &username) {
-		if (username.trimmed().isEmpty()) {
-			ProcessAnnotations.erase("Username");
+	void setCrashAnnotation(const std::string &key, const QString &value) {
+		if (value.trimmed().isEmpty()) {
+			internal::ProcessAnnotations.erase(key);
 		} else {
-			ProcessAnnotations["Username"] = username.toUtf8().constData();
+			internal::ProcessAnnotations[key] = value.toUtf8().constData();
 		}
 	}
 
-	void setAssertionInfo(const QString &info) {
-		ProcessAnnotations["Assertion"] = info.toUtf8().constData();
+	void setCrashAnnotationRef(const std::string &key, const QString *valuePtr) {
+		if (valuePtr) {
+			internal::ProcessAnnotationRefs.erase(key);
+		} else {
+			internal::ProcessAnnotationRefs[key] = valuePtr;
+		}
 	}
 
 }
diff --git a/Telegram/SourceFiles/logs.h b/Telegram/SourceFiles/logs.h
index 6e997e4cf..737d6ecff 100644
--- a/Telegram/SourceFiles/logs.h
+++ b/Telegram/SourceFiles/logs.h
@@ -107,7 +107,13 @@ namespace SignalHandlers {
 	Status restart(); // can be only CantOpen or Started
 	void finish();
 
-	void setSelfUsername(const QString &username);
-	void setAssertionInfo(const QString &info);
+	void setCrashAnnotation(const std::string &key, const QString &value);
+
+	// Remembers value pointer and tries to add the value to the crash report.
+	// Attention! You should call clearCrashAnnotationRef(key) before destroying value.
+	void setCrashAnnotationRef(const std::string &key, const QString *valuePtr);
+	inline void clearCrashAnnotationRef(const std::string &key) {
+		setCrashAnnotationRef(key, nullptr);
+	}
 
 }
diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h
index 27515b177..3a775b9cb 100644
--- a/Telegram/SourceFiles/types.h
+++ b/Telegram/SourceFiles/types.h
@@ -303,7 +303,7 @@ inline void t_noop() {}
 inline void t_assert_fail(const char *message, const char *file, int32 line) {
 	QString info(qsl("%1 %2:%3").arg(message).arg(file).arg(line));
 	LOG(("Assertion Failed! %1 %2:%3").arg(info));
-	SignalHandlers::setAssertionInfo(info);
+	SignalHandlers::setCrashAnnotation("Assertion", info);
 	*t_assert_nullptr = 0;
 }
 #define t_assert_full(condition, message, file, line) ((!(condition)) ? t_assert_fail(message, file, line) : t_noop())
diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp
index d2ce17a4f..6decac3f6 100644
--- a/Telegram/SourceFiles/window.cpp
+++ b/Telegram/SourceFiles/window.cpp
@@ -287,18 +287,20 @@ void NotifyWindow::startHiding() {
 
 void NotifyWindow::mousePressEvent(QMouseEvent *e) {
 	if (!history) return;
+
 	PeerId peer = history->peer->id;
+	MsgId msgId = (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId;
 
 	if (e->button() == Qt::RightButton) {
 		unlinkHistoryAndNotify();
-	} else if (history) {
+	} else {
 		App::wnd()->showFromTray();
 		if (App::passcoded()) {
 			App::wnd()->setInnerFocus();
 			App::wnd()->notifyClear();
 		} else {
 			App::wnd()->hideSettings();
-			Ui::showPeerHistory(peer, (!history->peer->isUser() && item && item->mentionsMe() && item->id > 0) ? item->id : ShowAtUnreadMsgId);
+			Ui::showPeerHistory(peer, msgId);
 		}
 		e->ignore();
 	}

From f1dfcef86863f4390eec1f02f3579d8df11bf7e8 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Thu, 31 Mar 2016 18:06:40 +0400
Subject: [PATCH 10/17] Styles improved for unread bar margins and sticker
 timestamp. Possible crash fixes: emoji color picker show, pending repaint
 items cleared when history items are cleared.

Deleting MainWidget syncroniously when clearWidgets() is called.
---
 Telegram/Resources/style.txt           |  7 +--
 Telegram/SourceFiles/app.cpp           | 33 +++++++-------
 Telegram/SourceFiles/app.h             |  1 -
 Telegram/SourceFiles/dropdown.cpp      |  2 +
 Telegram/SourceFiles/facades.cpp       |  6 +++
 Telegram/SourceFiles/facades.h         |  2 +
 Telegram/SourceFiles/history.cpp       | 53 ++++++++++++++--------
 Telegram/SourceFiles/history.h         | 10 ++++-
 Telegram/SourceFiles/historywidget.cpp | 62 +++++++++++++++++---------
 Telegram/SourceFiles/historywidget.h   | 10 ++++-
 Telegram/SourceFiles/mainwidget.cpp    |  6 +--
 Telegram/SourceFiles/types.h           | 18 ++++----
 Telegram/SourceFiles/window.cpp        | 20 +++++----
 Telegram/SourceFiles/window.h          |  4 +-
 14 files changed, 148 insertions(+), 86 deletions(-)

diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index 5ada019a8..357a487bb 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -1052,8 +1052,8 @@ msgMinWidth: 190px;
 msgPhotoSize: 33px;
 msgPhotoSkip: 40px;
 msgPadding: margins(13px, 7px, 13px, 8px);
-msgMargin: margins(13px, 6px, 53px, 2px);
-msgMarginTopAttached: 2px;
+msgMargin: margins(13px, 10px, 53px, 2px);
+msgMarginTopAttached: 3px;
 msgLnkPadding: 2px; // for media open / save links
 msgBorder: #f0f0f0;
 msgInBg: #fff;
@@ -1089,7 +1089,7 @@ msgServiceBg: #89a0b47f;
 msgServiceSelectBg: #bbc8d4a2;
 msgServiceColor: #FFF;
 msgServicePadding: margins(12px, 3px, 12px, 4px);
-msgServiceMargin: margins(10px, 9px, 80px, 5px);
+msgServiceMargin: margins(10px, 10px, 80px, 2px);
 
 msgColor: #000;
 msgDateColor: #000;
@@ -1527,6 +1527,7 @@ reportSpamBg: #fffffff0;
 newMsgSound: ':/gui/art/newmsg.wav';
 
 unreadBarHeight: 32px;
+unreadBarMargin: 8px;
 unreadBarFont: semiboldFont;
 unreadBarBG: #fcfbfa;
 unreadBarBorder: shadowColor;
diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index 18dfe7ae6..8d33b9797 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -180,21 +180,19 @@ namespace App {
 		return main() ? main()->api() : 0;
 	}
 
+namespace {
 	bool loggedOut() {
-		Window *w(wnd());
 		if (cHasPasscode()) {
 			cSetHasPasscode(false);
 		}
 		if (audioPlayer()) {
 			audioPlayer()->stopAndClear();
 		}
-		if (w) {
+		if (Window *w = wnd()) {
 			w->tempDirDelete(Local::ClearManagerAll);
 			w->notifyClearFast();
 			w->setupIntro(true);
 		}
-		MainWidget *m(main());
-		if (m) m->destroyData();
 		MTP::authed(0);
 		Local::reset();
 
@@ -205,13 +203,14 @@ namespace App {
 		globalNotifyChatsPtr = UnknownNotifySettings;
 		if (App::uploader()) App::uploader()->clear();
 		clearStorageImages();
-		if (w) {
+		if (Window *w = wnd()) {
 			w->getTitle()->updateBackButton();
 			w->updateTitleStatus();
 			w->getTitle()->resizeEvent(0);
 		}
 		return true;
 	}
+} // namespace
 
 	void logOut() {
 		if (MTP::started()) {
@@ -1454,12 +1453,12 @@ namespace App {
 
 	PeerData *peerByName(const QString &username) {
 		QString uname(username.trimmed());
-		for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
-			if (!i.value()->userName().compare(uname, Qt::CaseInsensitive)) {
-				return i.value();
+		for_const (PeerData *peer, peersData) {
+			if (!peer->userName().compare(uname, Qt::CaseInsensitive)) {
+				return peer;
 			}
 		}
-		return 0;
+		return nullptr;
 	}
 
 	void updateImage(ImagePtr &old, ImagePtr now) {
@@ -1867,20 +1866,20 @@ namespace App {
 		cSetSavedPeers(SavedPeers());
 		cSetSavedPeersByTime(SavedPeersByTime());
 		cSetRecentInlineBots(RecentInlineBots());
-		for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (PeerData *peer, peersData) {
+			delete peer;
 		}
 		peersData.clear();
-		for (PhotosData::const_iterator i = ::photosData.cbegin(), e = ::photosData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (PhotoData *photo, ::photosData) {
+			delete photo;
 		}
 		::photosData.clear();
-		for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (DocumentData *document, ::documentsData) {
+			delete document;
 		}
 		::documentsData.clear();
-		for (WebPagesData::const_iterator i = webPagesData.cbegin(), e = webPagesData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (WebPageData *webpage, webPagesData) {
+			delete webpage;
 		}
 		webPagesData.clear();
 		if (api()) api()->clearWebPageRequests();
diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h
index ebe1711e5..ac475da29 100644
--- a/Telegram/SourceFiles/app.h
+++ b/Telegram/SourceFiles/app.h
@@ -64,7 +64,6 @@ namespace App {
 	ApiWrap *api();
 
 	void logOut();
-	bool loggedOut();
 
 	QString formatPhone(QString phone);
 
diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp
index ee475348b..97d672a1d 100644
--- a/Telegram/SourceFiles/dropdown.cpp
+++ b/Telegram/SourceFiles/dropdown.cpp
@@ -941,6 +941,8 @@ void EmojiPanInner::selectEmoji(EmojiPtr emoji) {
 }
 
 void EmojiPanInner::onShowPicker() {
+	if (_pickerSel < 0) return;
+
 	int tab = (_pickerSel / MatrixRowShift), sel = _pickerSel % MatrixRowShift;
 	if (tab < emojiTabCount && sel < _emojis[tab].size() && _emojis[tab][sel]->color) {
 		int32 y = 0;
diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp
index 0b9557e3d..d89aec33f 100644
--- a/Telegram/SourceFiles/facades.cpp
+++ b/Telegram/SourceFiles/facades.cpp
@@ -86,6 +86,12 @@ namespace App {
 		}
 	}
 
+	void logOutDelayed() {
+		if (Window *w = App::wnd()) {
+			QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection);
+		}
+	}
+
 }
 
 namespace Ui {
diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h
index ba77a20a2..14b16742e 100644
--- a/Telegram/SourceFiles/facades.h
+++ b/Telegram/SourceFiles/facades.h
@@ -37,6 +37,8 @@ namespace App {
 
 	void activateTextLink(TextLinkPtr link, Qt::MouseButton button);
 
+	void logOutDelayed();
+
 };
 
 namespace Ui {
diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 3231bf89f..9aa63c654 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -1125,6 +1125,8 @@ void Histories::clear() {
 	for (Map::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) {
 		delete i.value();
 	}
+	Global::RefPendingRepaintItems().clear();
+
 	_unreadFull = _unreadMuted = 0;
 	if (App::wnd()) {
 		App::wnd()->updateCounter();
@@ -2753,13 +2755,17 @@ void HistoryMessageUnreadBar::init(int count) {
 	_width = st::semiboldFont->width(_text);
 }
 
-int HistoryMessageUnreadBar::height() const {
-	return st::unreadBarHeight;
+int HistoryMessageUnreadBar::height() {
+	return st::unreadBarHeight + st::unreadBarMargin;
+}
+
+int HistoryMessageUnreadBar::marginTop() {
+	return st::lineWidth + st::unreadBarMargin;
 }
 
 void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const {
-	p.fillRect(0, y + st::lineWidth, w, st::unreadBarHeight - 2 * st::lineWidth, st::unreadBarBG);
-	p.fillRect(0, y + st::unreadBarHeight - st::lineWidth, w, st::lineWidth, st::unreadBarBorder);
+	p.fillRect(0, y + marginTop(), w, height() - marginTop() - st::lineWidth, st::unreadBarBG);
+	p.fillRect(0, y + height() - st::lineWidth, w, st::lineWidth, st::unreadBarBorder);
 	p.setFont(st::unreadBarFont);
 	p.setPen(st::unreadBarColor);
 
@@ -2770,7 +2776,7 @@ void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const {
 	}
 	w = maxwidth;
 
-	p.drawText((w - _width) / 2, y + (st::unreadBarHeight - st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text);
+	p.drawText((w - _width) / 2, y + marginTop() + (st::unreadBarHeight - 2 * st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text);
 }
 
 void HistoryMessageDate::init(const QDateTime &date) {
@@ -2833,6 +2839,7 @@ void HistoryItem::destroy() {
 	if ((!out() || isPost()) && unread() && history()->unreadCount > 0) {
 		history()->setUnreadCount(history()->unreadCount - 1);
 	}
+	Global::RefPendingRepaintItems().remove(this);
 	delete this;
 }
 
@@ -3039,7 +3046,8 @@ void RadialAnimation::update(float64 prg, bool finished, uint64 ms) {
 		_opacity *= 1 - r;
 	}
 	float64 fromstart = fulldt / st::radialPeriod;
-	a_arcStart.update(fromstart - qFloor(fromstart), anim::linear);
+	float64 fromstartpart = fromstart - std::floor(fromstart);
+	a_arcStart.update(static_cast<int>(fromstartpart), anim::linear);
 }
 
 void RadialAnimation::stop() {
@@ -4862,7 +4870,7 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r,
 	}
 
 	if (parent->getMedia() == this) {
-		parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverImage);
+		parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverBackground);
 
 		if (reply) {
 			int32 rw = _width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
@@ -6630,18 +6638,24 @@ bool HistoryMessage::textHasLinks() {
 void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const {
 	p.setFont(st::msgDateFont);
 
-	bool outbg = out() && !isPost(), overimg = (type == InfoDisplayOverImage);
+	bool outbg = out() && !isPost();
+	bool invertedsprites = (type == InfoDisplayOverImage || type == InfoDisplayOverBackground);
 	int32 infoRight = right, infoBottom = bottom;
 	switch (type) {
 	case InfoDisplayDefault:
 		infoRight -= st::msgPadding.right() - st::msgDateDelta.x();
 		infoBottom -= st::msgPadding.bottom() - st::msgDateDelta.y();
-		p.setPen((selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg))->p);
+		p.setPen(selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg));
 	break;
 	case InfoDisplayOverImage:
 		infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
 		infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
-		p.setPen(st::msgDateImgColor->p);
+		p.setPen(st::msgDateImgColor);
+	break;
+	case InfoDisplayOverBackground:
+		infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
+		infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
+		p.setPen(st::msgServiceColor);
 	break;
 	}
 
@@ -6653,6 +6667,9 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width
 	if (type == InfoDisplayOverImage) {
 		int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
 		App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
+	} else if (type == InfoDisplayOverBackground) {
+		int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
+		App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, App::msgServiceBg(), ServiceCorners);
 	}
 	dateX += HistoryMessage::timeLeft();
 
@@ -6668,35 +6685,35 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width
 		iconPos = QPoint(infoRight - infoW + st::msgViewsPos.x(), infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
 		if (id > 0) {
 			if (outbg) {
-				iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg));
+				iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg));
 			} else {
-				iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg));
+				iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg));
 			}
 			p.drawText(iconPos.x() + st::msgViewsImg.pxWidth() + st::msgDateCheckSpace, infoBottom - st::msgDateFont->descent, views->_viewsText);
 		} else {
 			iconPos.setX(iconPos.x() + st::msgDateViewsSpace + views->_viewsWidth);
 			if (outbg) {
-				iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg);
+				iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg);
 			} else {
-				iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
+				iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
 			}
 		}
 		p.drawPixmap(iconPos, App::sprite(), *iconRect);
 	} else if (id < 0 && history()->peer->isSelf()) {
 		iconPos = QPoint(infoRight - infoW, infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
-		iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
+		iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
 		p.drawPixmap(iconPos, App::sprite(), *iconRect);
 	}
 	if (outbg) {
 		iconPos = QPoint(infoRight - st::msgCheckImg.pxWidth() + st::msgCheckPos.x(), infoBottom - st::msgCheckImg.pxHeight() + st::msgCheckPos.y());
 		if (id > 0) {
 			if (unread()) {
-				iconRect = &(overimg ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg));
+				iconRect = &(invertedsprites ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg));
 			} else {
-				iconRect = &(overimg ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg));
+				iconRect = &(invertedsprites ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg));
 			}
 		} else {
-			iconRect = &(overimg ? st::msgInvSendingImg : st::msgSendingImg);
+			iconRect = &(invertedsprites ? st::msgInvSendingImg : st::msgSendingImg);
 		}
 		p.drawPixmap(iconPos, App::sprite(), *iconRect);
 	}
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index 1dd9dd95e..4d8350488 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -987,6 +987,7 @@ enum HistoryCursorState {
 enum InfoDisplayType {
 	InfoDisplayDefault,
 	InfoDisplayOverImage,
+	InfoDisplayOverBackground,
 };
 
 inline bool isImportantChannelMessage(MsgId id, MTPDmessage::Flags flags) { // client-side important msgs always has_views or has_from_id
@@ -1130,7 +1131,9 @@ struct HistoryMessageUnreadBar : public BaseComponent<HistoryMessageUnreadBar> {
 	}
 	void init(int count);
 
-	int height() const;
+	static int height();
+	static int marginTop();
+
 	void paint(Painter &p, int y, int w) const;
 
 	QString _text;
@@ -1536,8 +1539,11 @@ protected:
 
 	HistoryItem *previous() const {
 		if (_block && _indexInBlock >= 0) {
-			if (_indexInBlock > 0) return _block->items.at(_indexInBlock - 1);
+			if (_indexInBlock > 0) {
+				return _block->items.at(_indexInBlock - 1);
+			}
 			if (HistoryBlock *previousBlock = _block->previous()) {
+				t_assert(!previousBlock->items.isEmpty());
 				return previousBlock->items.back();
 			}
 		}
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index c8f665649..43cd4b360 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -6444,7 +6444,9 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 	if (_pinnedBar) {
 		newScrollHeight -= st::replyHeight;
 	}
-	bool wasAtBottom = _scroll.scrollTop() + 1 > _scroll.scrollTopMax(), needResize = _scroll.width() != width() || _scroll.height() != newScrollHeight;
+	int wasScrollTop = _scroll.scrollTop();
+	bool wasAtBottom = wasScrollTop + 1 > _scroll.scrollTopMax();
+	bool needResize = (_scroll.width() != width()) || (_scroll.height() != newScrollHeight);
 	if (needResize) {
 		_scroll.resize(width(), newScrollHeight);
 		// on initial updateListSize we didn't put the _scroll.scrollTop correctly yet
@@ -6470,14 +6472,15 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 	}
 
 	if ((!initial && !wasAtBottom) || (loadedDown && (!_history->showFrom || _history->unreadBar || _history->loadedAtBottom()) && (!_migrated || !_migrated->showFrom || _migrated->unreadBar || _history->loadedAtBottom()))) {
-		int addToY = 0;
+		int toY = _list->historyScrollTop();
 		if (change.type == ScrollChangeAdd) {
-			addToY = change.value;
-		} else if (change.type == ScrollChangeOldHistoryHeight) {
-			addToY = _list->historyHeight() - change.value;
+			toY += change.value;
+		} else if (change.type == ScrollChangeNoJumpToBottom) {
+			toY = wasScrollTop;
+		}
+		if (toY > _scroll.scrollTopMax()) {
+			toY = _scroll.scrollTopMax();
 		}
-		int toY = _list->historyScrollTop() + addToY;
-		if (toY > _scroll.scrollTopMax()) toY = _scroll.scrollTopMax();
 		if (_scroll.scrollTop() == toY) {
 			visibleAreaUpdated();
 		} else {
@@ -6555,19 +6558,11 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 		} else {
 			toY = qMax(iy + item->height() - _fixedInScrollMsgTop, 0);
 		}
-	} else if (initial && _migrated && _migrated->unreadBar) {
-		toY = _list->itemTop(_migrated->unreadBar);
-		if (_migrated->unreadBar->Has<HistoryMessageDate>()) {
-			toY += _migrated->unreadBar->Get<HistoryMessageDate>()->height();
-		}
-	} else if (initial && _history->unreadBar) {
-		toY = _list->itemTop(_history->unreadBar);
-		if (_history->unreadBar->Has<HistoryMessageDate>()) {
-			toY += _history->unreadBar->Get<HistoryMessageDate>()->height();
-		}
+	} else if (initial && (_history->unreadBar || (_migrated && _migrated->unreadBar))) {
+		toY = unreadBarTop();
 	} else if (_migrated && _migrated->showFrom) {
 		toY = _list->itemTop(_migrated->showFrom);
-		if (toY < _scroll.scrollTopMax() + st::unreadBarHeight) {
+		if (toY < _scroll.scrollTopMax() + HistoryMessageUnreadBar::height() - HistoryMessageUnreadBar::marginTop()) {
 			_migrated->addUnreadBar();
 			if (_migrated->unreadBar) {
 				setMsgId(ShowAtUnreadMsgId);
@@ -6599,6 +6594,26 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 	}
 }
 
+int HistoryWidget::unreadBarTop() const {
+	auto getUnreadBar = [this]() -> HistoryItem* {
+		if (_migrated && _migrated->unreadBar) {
+			return _migrated->unreadBar;
+		}
+		if (_history->unreadBar) {
+			return _history->unreadBar;
+		}
+		return nullptr;
+	};
+	if (HistoryItem *bar = getUnreadBar()) {
+		int result = _list->itemTop(bar) + HistoryMessageUnreadBar::marginTop();
+		if (bar->Has<HistoryMessageDate>()) {
+			result += bar->Get<HistoryMessageDate>()->height();
+		}
+		return result;
+	}
+	return -1;
+}
+
 void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
 	int oldH = _list->historyHeight();
 	_list->messagesReceived(peer, messages, collapsed);
@@ -6617,7 +6632,7 @@ void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage>
 void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
 	_list->messagesReceivedDown(peer, messages, collapsed);
 	if (!_firstLoadRequest) {
-		updateListSize(false, true);
+		updateListSize(false, true, { ScrollChangeNoJumpToBottom, 0 });
 	}
 }
 
@@ -7001,7 +7016,10 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
 			_topShadow.raise();
 			updatePinnedBar();
 			result = true;
-			_scroll.scrollToY(_scroll.scrollTop() + st::replyHeight);
+
+			if (_scroll.scrollTop() != unreadBarTop()) {
+				_scroll.scrollToY(_scroll.scrollTop() + st::replyHeight);
+			}
 		} else if (_pinnedBar->msgId != pinnedMsgId) {
 			_pinnedBar->msgId = pinnedMsgId;
 			_pinnedBar->msg = 0;
@@ -7015,7 +7033,9 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
 	} else if (_pinnedBar) {
 		destroyPinnedBar();
 		result = true;
-		_scroll.scrollToY(_scroll.scrollTop() - st::replyHeight);
+		if (_scroll.scrollTop() != unreadBarTop()) {
+			_scroll.scrollToY(_scroll.scrollTop() - st::replyHeight);
+		}
 		resizeEvent(0);
 	}
 	return result;
diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h
index 5eabc4ffb..d8d8b542e 100644
--- a/Telegram/SourceFiles/historywidget.h
+++ b/Telegram/SourceFiles/historywidget.h
@@ -834,8 +834,12 @@ private:
 
 	enum ScrollChangeType {
 		ScrollChangeNone,
+
+		// When we toggle a pinned message.
 		ScrollChangeAdd,
-		ScrollChangeOldHistoryHeight,
+
+		// When loading a history part while scrolling down.
+		ScrollChangeNoJumpToBottom,
 	};
 	struct ScrollChange {
 		ScrollChangeType type;
@@ -843,6 +847,10 @@ private:
 	};
 	void updateListSize(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
 
+	// Counts scrollTop for placing the scroll right at the unread
+	// messages bar, choosing from _history and _migrated unreadBar.
+	int unreadBarTop() const;
+
 	void saveGifDone(DocumentData *doc, const MTPBool &result);
 
 	void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 2f2805d1e..b62ea7d61 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -2958,9 +2958,7 @@ void MainWidget::feedMessageIds(const MTPVector<MTPUpdate> &updates) {
 }
 
 bool MainWidget::updateFail(const RPCError &e) {
-	if (MTP::authedId()) {
-		App::logOut();
-	}
+	App::logOutDelayed();
 	return true;
 }
 
@@ -3707,7 +3705,7 @@ bool MainWidget::inviteImportFail(const RPCError &error) {
 void MainWidget::startFull(const MTPVector<MTPUser> &users) {
 	const QVector<MTPUser> &v(users.c_vector().v);
 	if (v.isEmpty() || v[0].type() != mtpc_user || !v[0].c_user().is_self()) { // wtf?..
-		return App::logOut();
+		return App::logOutDelayed();
 	}
 	start(v[0]);
 }
diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h
index 3a775b9cb..bbf44693d 100644
--- a/Telegram/SourceFiles/types.h
+++ b/Telegram/SourceFiles/types.h
@@ -650,20 +650,20 @@ MimeType mimeTypeForName(const QString &mime);
 MimeType mimeTypeForFile(const QFileInfo &file);
 MimeType mimeTypeForData(const QByteArray &data);
 
-inline int32 rowscount(int32 count, int32 perrow) {
-	return (count + perrow - 1) / perrow;
+inline int rowscount(int fullCount, int countPerRow) {
+	return (fullCount + countPerRow - 1) / countPerRow;
 }
-inline int32 floorclamp(int32 value, int32 step, int32 lowest, int32 highest) {
+inline int floorclamp(int value, int step, int lowest, int highest) {
 	return qMin(qMax(value / step, lowest), highest);
 }
-inline int32 floorclamp(float64 value, int32 step, int32 lowest, int32 highest) {
-	return qMin(qMax(qFloor(value / step), lowest), highest);
+inline int floorclamp(float64 value, int step, int lowest, int highest) {
+	return qMin(qMax(static_cast<int>(std::floor(value / step)), lowest), highest);
 }
-inline int32 ceilclamp(int32 value, int32 step, int32 lowest, int32 highest) {
-	return qMax(qMin((value / step) + ((value % step) ? 1 : 0), highest), lowest);
+inline int ceilclamp(int value, int step, int lowest, int highest) {
+	return qMax(qMin((value + step - 1) / step, highest), lowest);
 }
-inline int32 ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
-	return qMax(qMin(qCeil(value / step), highest), lowest);
+inline int ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
+	return qMax(qMin(static_cast<int>(std::ceil(value / step)), highest), lowest);
 }
 
 enum ForwardWhatMessages {
diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp
index 6decac3f6..74d58158e 100644
--- a/Telegram/SourceFiles/window.cpp
+++ b/Telegram/SourceFiles/window.cpp
@@ -507,11 +507,8 @@ void Window::clearWidgets() {
 		settings = 0;
 	}
 	if (main) {
-		main->animStop_show();
-		main->hide();
-		main->deleteLater();
-		main->rpcClear();
-		main = 0;
+		delete main;
+		main = nullptr;
 	}
 	if (intro) {
 		intro->stop_show();
@@ -693,7 +690,7 @@ void Window::setupMain(bool anim, const MTPUser *self) {
 }
 
 void Window::updateCounter() {
-	if (App::quitting()) return;
+	if (!Global::started() || App::quitting()) return;
 
 	psUpdateCounter();
 	title->updateCounter();
@@ -1178,7 +1175,11 @@ void Window::onLogout() {
 }
 
 void Window::onLogoutSure() {
-	App::logOut();
+	if (MTP::authedId()) {
+		App::logOut();
+	} else {
+		setupIntro(true);
+	}
 }
 
 void Window::updateGlobalMenu() {
@@ -1944,7 +1945,10 @@ PreLaunchWindow::PreLaunchWindow(QString title) : TWidget(0) {
 	tmp.setText(qsl("Tmp"));
 	_size = tmp.sizeHint().height();
 
-	setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(qFloor(_size / 2)).arg(qFloor(_size)).arg(qFloor(_size / 5)));
+	int paddingVertical = (_size / 2);
+	int paddingHorizontal = _size;
+	int borderRadius = (_size / 5);
+	setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(paddingVertical).arg(paddingHorizontal).arg(borderRadius));
 	if (!PreLaunchWindowInstance) {
 		PreLaunchWindowInstance = this;
 	}
diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h
index cecad8cf7..0fd5df1b4 100644
--- a/Telegram/SourceFiles/window.h
+++ b/Telegram/SourceFiles/window.h
@@ -362,7 +362,7 @@ public:
 
 	PreLaunchWindow(QString title = QString());
 	void activate();
-	float64 basicSize() const {
+	int basicSize() const {
 		return _size;
 	}
 	~PreLaunchWindow();
@@ -371,7 +371,7 @@ public:
 
 protected:
 
-	float64 _size;
+	int _size;
 
 };
 

From 829513c9ce654af4e2dc74a59164d888f45fd2e8 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Thu, 31 Mar 2016 18:12:30 +0400
Subject: [PATCH 11/17] fixed building for OS X / Linux

---
 Telegram/SourceFiles/logs.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp
index 916193635..c57528911 100644
--- a/Telegram/SourceFiles/logs.cpp
+++ b/Telegram/SourceFiles/logs.cpp
@@ -1023,13 +1023,13 @@ namespace internal {
 			internal::ReportFile = nullptr;
 		}
 #else // Q_OS_WIN
-		CrashDumpFile = fopen(QFile::encodeName(CrashDumpPath).constData(), "wb");
+		internal::ReportFile = fopen(QFile::encodeName(internal::ReportPath).constData(), "wb");
 #endif // else for Q_OS_WIN
 		if (internal::ReportFile) {
 #ifdef Q_OS_WIN
 			internal::ReportFileNo = _fileno(internal::ReportFile);
 #else // Q_OS_WIN
-			CrashDumpFileNo = fileno(internal::ReportFile);
+			internal::ReportFileNo = fileno(internal::ReportFile);
 #endif // else for Q_OS_WIN
 			if (internal::SetSignalHandlers) {
 #ifndef Q_OS_WIN
@@ -1039,12 +1039,12 @@ namespace internal {
 				sigemptyset(&sigact.sa_mask);
 				sigact.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
 
-				sigaction(SIGABRT, &sigact, &SIG_def[SIGABRT]);
-				sigaction(SIGSEGV, &sigact, &SIG_def[SIGSEGV]);
-				sigaction(SIGILL, &sigact, &SIG_def[SIGILL]);
-				sigaction(SIGFPE, &sigact, &SIG_def[SIGFPE]);
-				sigaction(SIGBUS, &sigact, &SIG_def[SIGBUS]);
-				sigaction(SIGSYS, &sigact, &SIG_def[SIGSYS]);
+				sigaction(SIGABRT, &sigact, &internal::SIG_def[SIGABRT]);
+				sigaction(SIGSEGV, &sigact, &internal::SIG_def[SIGSEGV]);
+				sigaction(SIGILL, &sigact, &internal::SIG_def[SIGILL]);
+				sigaction(SIGFPE, &sigact, &internal::SIG_def[SIGFPE]);
+				sigaction(SIGBUS, &sigact, &internal::SIG_def[SIGBUS]);
+				sigaction(SIGSYS, &sigact, &internal::SIG_def[SIGSYS]);
 #else // !Q_OS_WIN
 				signal(SIGABRT, SignalHandlers::internal::Handler);
 				signal(SIGSEGV, SignalHandlers::internal::Handler);

From f1c69a495ba02e8bcdd4096e3b4e4c74daf9e049 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Thu, 31 Mar 2016 18:26:38 +0400
Subject: [PATCH 12/17] 0.9.37 dev version

---
 Telegram/SourceFiles/config.h               |  4 ++--
 Telegram/Telegram.plist                     |  2 +-
 Telegram/Telegram.rc                        |  8 ++++----
 Telegram/Telegram.xcodeproj/project.pbxproj | 12 ++++++------
 Telegram/Version                            |  6 +++---
 5 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h
index 39e5008f3..432abb6df 100644
--- a/Telegram/SourceFiles/config.h
+++ b/Telegram/SourceFiles/config.h
@@ -20,8 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-static const int32 AppVersion = 9036;
-static const wchar_t *AppVersionStr = L"0.9.36";
+static const int32 AppVersion = 9037;
+static const wchar_t *AppVersionStr = L"0.9.37";
 static const bool DevVersion = true;
 //#define BETA_VERSION (9034004ULL) // just comment this line to build public version
 
diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist
index 8e055f9b7..e697ce59e 100644
--- a/Telegram/Telegram.plist
+++ b/Telegram/Telegram.plist
@@ -11,7 +11,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.9.36</string>
+	<string>0.9.37</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleURLTypes</key>
diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc
index a6392a42a..c3b1412a0 100644
--- a/Telegram/Telegram.rc
+++ b/Telegram/Telegram.rc
@@ -34,8 +34,8 @@ IDI_ICON1               ICON                    "SourceFiles\\art\\icon256.ico"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,9,36,0
- PRODUCTVERSION 0,9,36,0
+ FILEVERSION 0,9,37,0
+ PRODUCTVERSION 0,9,37,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -51,10 +51,10 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "CompanyName", "Telegram Messenger LLP"
-            VALUE "FileVersion", "0.9.36.0"
+            VALUE "FileVersion", "0.9.37.0"
             VALUE "LegalCopyright", "Copyright (C) 2014-2016"
             VALUE "ProductName", "Telegram Desktop"
-            VALUE "ProductVersion", "0.9.36.0"
+            VALUE "ProductVersion", "0.9.37.0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj
index 7c99556fb..5b81e5f17 100644
--- a/Telegram/Telegram.xcodeproj/project.pbxproj
+++ b/Telegram/Telegram.xcodeproj/project.pbxproj
@@ -1772,7 +1772,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.36;
+				CURRENT_PROJECT_VERSION = 0.9.37;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
@@ -1791,7 +1791,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = YES;
-				CURRENT_PROJECT_VERSION = 0.9.36;
+				CURRENT_PROJECT_VERSION = 0.9.37;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_OPTIMIZATION_LEVEL = fast;
 				GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@@ -1820,10 +1820,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.36;
+				CURRENT_PROJECT_VERSION = 0.9.37;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DYLIB_COMPATIBILITY_VERSION = 0.9;
-				DYLIB_CURRENT_VERSION = 0.9.36;
+				DYLIB_CURRENT_VERSION = 0.9.37;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1961,10 +1961,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.36;
+				CURRENT_PROJECT_VERSION = 0.9.37;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DYLIB_COMPATIBILITY_VERSION = 0.9;
-				DYLIB_CURRENT_VERSION = 0.9.36;
+				DYLIB_CURRENT_VERSION = 0.9.37;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
diff --git a/Telegram/Version b/Telegram/Version
index 2227962ec..6c83176cd 100644
--- a/Telegram/Version
+++ b/Telegram/Version
@@ -1,6 +1,6 @@
-AppVersion         9036
+AppVersion         9037
 AppVersionStrMajor 0.9
-AppVersionStrSmall 0.9.36
-AppVersionStr      0.9.36
+AppVersionStrSmall 0.9.37
+AppVersionStr      0.9.37
 DevChannel         1
 BetaVersion        0 9034004

From f96b7da7ce92440b1c72fb9eb3d29a0f33160a12 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 1 Apr 2016 00:36:46 +0400
Subject: [PATCH 13/17] Crash reporting fixed, radial progress fixed. 0.9.38
 dev version.

---
 Telegram/SourceFiles/config.h               |  4 ++--
 Telegram/SourceFiles/history.cpp            |  3 +--
 Telegram/SourceFiles/logs.cpp               | 10 +++++-----
 Telegram/Telegram.plist                     |  2 +-
 Telegram/Telegram.rc                        |  8 ++++----
 Telegram/Telegram.xcodeproj/project.pbxproj | 12 ++++++------
 Telegram/Version                            |  6 +++---
 7 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h
index 432abb6df..c8a83ff05 100644
--- a/Telegram/SourceFiles/config.h
+++ b/Telegram/SourceFiles/config.h
@@ -20,8 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-static const int32 AppVersion = 9037;
-static const wchar_t *AppVersionStr = L"0.9.37";
+static const int32 AppVersion = 9038;
+static const wchar_t *AppVersionStr = L"0.9.38";
 static const bool DevVersion = true;
 //#define BETA_VERSION (9034004ULL) // just comment this line to build public version
 
diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 9aa63c654..bbfb98731 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -3046,8 +3046,7 @@ void RadialAnimation::update(float64 prg, bool finished, uint64 ms) {
 		_opacity *= 1 - r;
 	}
 	float64 fromstart = fulldt / st::radialPeriod;
-	float64 fromstartpart = fromstart - std::floor(fromstart);
-	a_arcStart.update(static_cast<int>(fromstartpart), anim::linear);
+	a_arcStart.update(fromstart - std::floor(fromstart), anim::linear);
 }
 
 void RadialAnimation::stop() {
diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp
index c57528911..668990da2 100644
--- a/Telegram/SourceFiles/logs.cpp
+++ b/Telegram/SourceFiles/logs.cpp
@@ -1080,18 +1080,18 @@ namespace internal {
 	}
 
 	void setCrashAnnotation(const std::string &key, const QString &value) {
-		if (value.trimmed().isEmpty()) {
-			internal::ProcessAnnotations.erase(key);
-		} else {
+		if (!value.trimmed().isEmpty()) {
 			internal::ProcessAnnotations[key] = value.toUtf8().constData();
+		} else {
+			internal::ProcessAnnotations.erase(key);
 		}
 	}
 
 	void setCrashAnnotationRef(const std::string &key, const QString *valuePtr) {
 		if (valuePtr) {
-			internal::ProcessAnnotationRefs.erase(key);
-		} else {
 			internal::ProcessAnnotationRefs[key] = valuePtr;
+		} else {
+			internal::ProcessAnnotationRefs.erase(key);
 		}
 	}
 
diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist
index e697ce59e..3cb7a80d9 100644
--- a/Telegram/Telegram.plist
+++ b/Telegram/Telegram.plist
@@ -11,7 +11,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.9.37</string>
+	<string>0.9.38</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleURLTypes</key>
diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc
index c3b1412a0..dc73d5daa 100644
--- a/Telegram/Telegram.rc
+++ b/Telegram/Telegram.rc
@@ -34,8 +34,8 @@ IDI_ICON1               ICON                    "SourceFiles\\art\\icon256.ico"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,9,37,0
- PRODUCTVERSION 0,9,37,0
+ FILEVERSION 0,9,38,0
+ PRODUCTVERSION 0,9,38,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -51,10 +51,10 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "CompanyName", "Telegram Messenger LLP"
-            VALUE "FileVersion", "0.9.37.0"
+            VALUE "FileVersion", "0.9.38.0"
             VALUE "LegalCopyright", "Copyright (C) 2014-2016"
             VALUE "ProductName", "Telegram Desktop"
-            VALUE "ProductVersion", "0.9.37.0"
+            VALUE "ProductVersion", "0.9.38.0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj
index 5b81e5f17..8f77b8522 100644
--- a/Telegram/Telegram.xcodeproj/project.pbxproj
+++ b/Telegram/Telegram.xcodeproj/project.pbxproj
@@ -1772,7 +1772,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.37;
+				CURRENT_PROJECT_VERSION = 0.9.38;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
@@ -1791,7 +1791,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = YES;
-				CURRENT_PROJECT_VERSION = 0.9.37;
+				CURRENT_PROJECT_VERSION = 0.9.38;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_OPTIMIZATION_LEVEL = fast;
 				GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@@ -1820,10 +1820,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.37;
+				CURRENT_PROJECT_VERSION = 0.9.38;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DYLIB_COMPATIBILITY_VERSION = 0.9;
-				DYLIB_CURRENT_VERSION = 0.9.37;
+				DYLIB_CURRENT_VERSION = 0.9.38;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1961,10 +1961,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.37;
+				CURRENT_PROJECT_VERSION = 0.9.38;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DYLIB_COMPATIBILITY_VERSION = 0.9;
-				DYLIB_CURRENT_VERSION = 0.9.37;
+				DYLIB_CURRENT_VERSION = 0.9.38;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
diff --git a/Telegram/Version b/Telegram/Version
index 6c83176cd..59825138f 100644
--- a/Telegram/Version
+++ b/Telegram/Version
@@ -1,6 +1,6 @@
-AppVersion         9037
+AppVersion         9038
 AppVersionStrMajor 0.9
-AppVersionStrSmall 0.9.37
-AppVersionStr      0.9.37
+AppVersionStrSmall 0.9.38
+AppVersionStr      0.9.38
 DevChannel         1
 BetaVersion        0 9034004

From 1f6da4c7346cfad264411552dcfb1f2a9740f0f9 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 1 Apr 2016 11:43:14 +0400
Subject: [PATCH 14/17] Logging crashed string in hexdump ofutf8.

---
 Telegram/SourceFiles/logs.cpp | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp
index 668990da2..0040b4f1b 100644
--- a/Telegram/SourceFiles/logs.cpp
+++ b/Telegram/SourceFiles/logs.cpp
@@ -768,9 +768,24 @@ namespace internal {
 
 		if (!ReportingHeaderWritten) {
 			ReportingHeaderWritten = true;
+			auto dec2hex = [](int value) -> char {
+				if (value >= 0 && value < 10) {
+					return '0' + value;
+				} else if (value >= 10 && value < 16) {
+					return 'a' + (value - 10);
+				}
+				return '#';
+			};
 
 			for (const auto &i : ProcessAnnotationRefs) {
-				ProcessAnnotations[i.first] = i.second->toUtf8().constData();
+				QByteArray utf8 = i.second->toUtf8();
+				std::string wrapped;
+				wrapped.reserve(4 * utf8.size());
+				for (auto ch : utf8) {
+					auto uch = static_cast<uchar>(ch);
+					wrapped.append("\\x", 2).append(1, dec2hex(uch >> 4)).append(1, dec2hex(uch & 0x0F));
+				}
+				ProcessAnnotations[i.first] = wrapped;
 			}
 
 			const Annotations c_ProcessAnnotations(ProcessAnnotations);

From 73a27c2def85c60d1151919fc7688db8ff3ec79a Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 1 Apr 2016 11:52:25 +0400
Subject: [PATCH 15/17] Not painting anything in HistoryInner if _history or
 _migrated have pending resized items.

---
 Telegram/SourceFiles/historywidget.cpp | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index 43cd4b360..a56f48750 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -193,18 +193,16 @@ void HistoryInner::enumerateUserpicsInHistory(History *h, int htop, Method metho
 }
 
 void HistoryInner::paintEvent(QPaintEvent *e) {
-	if (App::wnd() && App::wnd()->contentOverlapped(this, e)) return;
+	if (App::wnd() && App::wnd()->contentOverlapped(this, e)) {
+		return;
+	}
 
-	if (!App::main()) return;
+	if (!App::main()) {
+		return;
+	}
 
 	if ((_history && _history->hasPendingResizedItems()) || (_migrated && _migrated->hasPendingResizedItems())) {
-		Notify::handlePendingHistoryUpdate();
-		if (_history) {
-			t_assert(!_history->hasPendingResizedItems());
-		}
-		if (_migrated) {
-			t_assert(!_migrated->hasPendingResizedItems());
-		}
+		return;
 	}
 
 	Painter p(this);

From 2826bb9134d35d1b791ba52fdfba8864eed8f434 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 1 Apr 2016 11:57:30 +0400
Subject: [PATCH 16/17] 0.9.39 dev version (possible crash fix)

---
 Telegram/SourceFiles/config.h               |  4 ++--
 Telegram/Telegram.plist                     |  2 +-
 Telegram/Telegram.rc                        |  8 ++++----
 Telegram/Telegram.xcodeproj/project.pbxproj | 12 ++++++------
 Telegram/Version                            |  6 +++---
 5 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h
index c8a83ff05..270dc855f 100644
--- a/Telegram/SourceFiles/config.h
+++ b/Telegram/SourceFiles/config.h
@@ -20,8 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
-static const int32 AppVersion = 9038;
-static const wchar_t *AppVersionStr = L"0.9.38";
+static const int32 AppVersion = 9039;
+static const wchar_t *AppVersionStr = L"0.9.39";
 static const bool DevVersion = true;
 //#define BETA_VERSION (9034004ULL) // just comment this line to build public version
 
diff --git a/Telegram/Telegram.plist b/Telegram/Telegram.plist
index 3cb7a80d9..d2af99bfb 100644
--- a/Telegram/Telegram.plist
+++ b/Telegram/Telegram.plist
@@ -11,7 +11,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.9.38</string>
+	<string>0.9.39</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleURLTypes</key>
diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc
index dc73d5daa..f9be16de3 100644
--- a/Telegram/Telegram.rc
+++ b/Telegram/Telegram.rc
@@ -34,8 +34,8 @@ IDI_ICON1               ICON                    "SourceFiles\\art\\icon256.ico"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,9,38,0
- PRODUCTVERSION 0,9,38,0
+ FILEVERSION 0,9,39,0
+ PRODUCTVERSION 0,9,39,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -51,10 +51,10 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "CompanyName", "Telegram Messenger LLP"
-            VALUE "FileVersion", "0.9.38.0"
+            VALUE "FileVersion", "0.9.39.0"
             VALUE "LegalCopyright", "Copyright (C) 2014-2016"
             VALUE "ProductName", "Telegram Desktop"
-            VALUE "ProductVersion", "0.9.38.0"
+            VALUE "ProductVersion", "0.9.39.0"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/Telegram/Telegram.xcodeproj/project.pbxproj b/Telegram/Telegram.xcodeproj/project.pbxproj
index 8f77b8522..bed09ed1b 100644
--- a/Telegram/Telegram.xcodeproj/project.pbxproj
+++ b/Telegram/Telegram.xcodeproj/project.pbxproj
@@ -1772,7 +1772,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.38;
+				CURRENT_PROJECT_VERSION = 0.9.39;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
@@ -1791,7 +1791,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				COPY_PHASE_STRIP = YES;
-				CURRENT_PROJECT_VERSION = 0.9.38;
+				CURRENT_PROJECT_VERSION = 0.9.39;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_OPTIMIZATION_LEVEL = fast;
 				GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@@ -1820,10 +1820,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.38;
+				CURRENT_PROJECT_VERSION = 0.9.39;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DYLIB_COMPATIBILITY_VERSION = 0.9;
-				DYLIB_CURRENT_VERSION = 0.9.38;
+				DYLIB_CURRENT_VERSION = 0.9.39;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
 				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1961,10 +1961,10 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				CODE_SIGN_IDENTITY = "";
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 0.9.38;
+				CURRENT_PROJECT_VERSION = 0.9.39;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DYLIB_COMPATIBILITY_VERSION = 0.9;
-				DYLIB_CURRENT_VERSION = 0.9.38;
+				DYLIB_CURRENT_VERSION = 0.9.39;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				FRAMEWORK_SEARCH_PATHS = "";
diff --git a/Telegram/Version b/Telegram/Version
index 59825138f..355c48b4b 100644
--- a/Telegram/Version
+++ b/Telegram/Version
@@ -1,6 +1,6 @@
-AppVersion         9038
+AppVersion         9039
 AppVersionStrMajor 0.9
-AppVersionStrSmall 0.9.38
-AppVersionStr      0.9.38
+AppVersionStrSmall 0.9.39
+AppVersionStr      0.9.39
 DevChannel         1
 BetaVersion        0 9034004

From 174302a90771bb6571454ee96b6f6bc9af42cf23 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 1 Apr 2016 12:50:02 +0400
Subject: [PATCH 17/17] Ignoring 4099 warning in VS project linking. Added
 <cmath> header to precompiled header and std:: math usage.

---
 Telegram/SourceFiles/stdafx.h | 2 ++
 Telegram/SourceFiles/types.h  | 2 ++
 Telegram/Telegram.vcxproj     | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h
index 12885f468..e87a6c5b0 100644
--- a/Telegram/SourceFiles/stdafx.h
+++ b/Telegram/SourceFiles/stdafx.h
@@ -25,6 +25,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 
 #ifdef __cplusplus
 
+#include <cmath>
+
 #include <QtCore/QtCore>
 #include <QtWidgets/QtWidgets>
 #include <QtNetwork/QtNetwork>
diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h
index bbf44693d..babef3cb0 100644
--- a/Telegram/SourceFiles/types.h
+++ b/Telegram/SourceFiles/types.h
@@ -650,6 +650,8 @@ MimeType mimeTypeForName(const QString &mime);
 MimeType mimeTypeForFile(const QFileInfo &file);
 MimeType mimeTypeForData(const QByteArray &data);
 
+#include <cmath>
+
 inline int rowscount(int fullCount, int countPerRow) {
 	return (fullCount + countPerRow - 1) / countPerRow;
 }
diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj
index 8b18f8ada..cdde8b981 100644
--- a/Telegram/Telegram.vcxproj
+++ b/Telegram/Telegram.vcxproj
@@ -123,6 +123,7 @@
       <OptimizeReferences>true</OptimizeReferences>
       <IgnoreSpecificDefaultLibraries>
       </IgnoreSpecificDefaultLibraries>
+      <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">
@@ -154,6 +155,7 @@
       <OptimizeReferences>true</OptimizeReferences>
       <IgnoreSpecificDefaultLibraries>
       </IgnoreSpecificDefaultLibraries>
+      <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>