diff --git a/Telegram/Resources/art/sprite.png b/Telegram/Resources/art/sprite.png index 179237f54..e1f577849 100644 Binary files a/Telegram/Resources/art/sprite.png and b/Telegram/Resources/art/sprite.png differ diff --git a/Telegram/Resources/art/sprite_200x.png b/Telegram/Resources/art/sprite_200x.png index e5dd6795e..9eaedee27 100644 Binary files a/Telegram/Resources/art/sprite_200x.png and b/Telegram/Resources/art/sprite_200x.png differ diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index e44c89973..5b1aaae80 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -556,37 +556,6 @@ btnDefLink: linkButton { overFont: linkOverFont; } -cbDefFlat: flatCheckbox { - textColor: #000; - bgColor: transparent; - disColor: #999; - - height: 22px; - textTop: 1px; - textLeft: 34px; - font: font(fsize); - duration: 200; - bgFunc: transition(easeOutCirc); - cursor: cursor(pointer); - - disabledCursor: cursor(default); - - imageRect: sprite(142px, 43px, 22px, 22px); - chkImageRect: sprite(120px, 68px, 22px, 22px); - overImageRect: sprite(142px, 68px, 22px, 22px); - chkOverImageRect: sprite(120px, 68px, 22px, 22px); - disImageRect: sprite(142px, 43px, 22px, 22px); - chkDisImageRect: sprite(120px, 43px, 22px, 22px); - - imagePos: point(0px, 0px); -} - -rbDefFlat: flatCheckbox(cbDefFlat) { - chkImageRect: sprite(165px, 68px, 22px, 22px); - chkOverImageRect: sprite(165px, 68px, 22px, 22px); - chkDisImageRect: sprite(165px, 43px, 22px, 22px); -} - inpDefFont: font(17px); inpDefFlat: flatInput { textColor: #000; @@ -814,28 +783,7 @@ introErrLabel: flatLabel(labelDefFlat) { align: align(center); } -setWidth: 356px; -setTop: 26px; -setNameLeft: 3px; -setNameTop: 5px; -setNameFont: font(18px); -setStatusTop: 35px; -setStatusLeft: 3px; -setStatusFont: font(14px); -setPhotoSize: 120px; -setHeaderFont: font(17px); -setHeaderColor: black; -setHeaderSkip: 60px; -setHeaderLeft: -1px; -setHeaderTop: 26px; setLittleSkip: 9px; -setSectionSkip: 25px; -setContactInfoLeft: 150px; -setVersionHeight: 41px; -setVersionLeft: 36px; -setVersionTop: 3px; -setVersionColor: #999; -setBottom: 130px; setScroll: flatScroll(scrollDef) { bottomsh: 0px; topsh: 0px; @@ -852,92 +800,11 @@ setClose: iconedButton(btnDefIconed) { height: 43px; } setClosePos: point(32px, 32px); -setPhotoImg: sprite(0px, 218px, 120px, 120px); -setOverPhotoImg: sprite(122px, 218px, 120px, 120px); setPhotoDuration: 150; -setPadding: 26px; -setBG: #FFF; -setSh: #000; -setTitleFrom: point(20px, 20px); -setTitleFont: font(24px); -setTitleColor: #000; -setNameInput: flatInput(inpDefFlat) { - font: font(fsize); - height: 25px; - width: 170px; - textMrg: margins(3px, 3px, 3px, 3px); -} -setErrBG: #ffa5a5; setErrColor: #d84d4d; -setErrHeight: 30px; -setErrFont: font(fsize); setGoodColor: #4ab44a; -setBackgroundSize: 120px; - -btnSetUpload: flatButton(btnDefNext, btnDefBig) { - width: 206px; - height: 42px; - font: font(18px); - overFont: font(18px); - - textTop: 9px; - overTextTop: 9px; - downTextTop: 10px; -} - -btnEditSave: flatButton(btnSetUpload) { - width: 115px; -} -btnEditCancel: flatButton(btnDefFlat, btnDefBig) { - color: #666d78; - overColor: #666d78; - downColor: #50565e; - - bgColor: rgba(0, 0, 0, 63); - overBgColor: rgba(0, 0, 0, 47); - downBgColor: rgba(0, 0, 0, 95); - - width: 115px; - height: 40px; - - textTop: 9px; - overTextTop: 9px; - downTextTop: 10px; - - font: font(18px); - overFont: font(18px); -} - -btnLogout: flatButton(btnDefFlat, btnDefBig) { - color: white; - overColor: white; - downColor: white; - - bgColor: #db6352; - overBgColor: #d15948; - downBgColor: #c74d3b; - - width: 148px; - height: 42px; - - textTop: 8px; - overTextTop: 8px; - downTextTop: 9px; - - font: font(18px); - overFont: font(18px); -} - -searchFlatInput: flatInput(inpDefGray) { - font: font(fsize); - bgColor: #f2f2f2; - phColor: #949494; - phFocusColor: #a4a4a4; - imgRect: sprite(227px, 21px, 24px, 24px); -} - noContactsHeight: 100px; noContactsFont: font(fsize); noContactsColor: #777; @@ -954,7 +821,13 @@ dlgActiveChatImg: sprite(104px, 37px, 16px, 11px); dlgChannelImg: sprite(105px, 1px, 12px, 11px); dlgActiveChannelImg: sprite(105px, 14px, 12px, 11px); -dlgFilter: flatInput(searchFlatInput) { +dlgFilter: flatInput(inpDefGray) { + font: font(fsize); + bgColor: #f2f2f2; + phColor: #949494; + phFocusColor: #a4a4a4; + imgRect: sprite(227px, 21px, 24px, 24px); + width: 240px; height: 34px; textMrg: margins(34px, 2px, 34px, 4px); @@ -1816,13 +1689,6 @@ dragPadding: margins(20px, 10px, 20px, 10px); dragHeight: 72px; -dpiSlider: slider { - color: #ccc; - thickness: 2px; - - width: 260px; - bar: sprite(0px, 104px, 9px, 22px); -} dpiActive: black; dpiInactive: #999; dpiFont1: linkFont; diff --git a/Telegram/Resources/basic_types.style b/Telegram/Resources/basic_types.style index 2a8eedd4d..1d5d57f76 100644 --- a/Telegram/Resources/basic_types.style +++ b/Telegram/Resources/basic_types.style @@ -202,14 +202,6 @@ countryInput { align: align; } -slider { - color: color; - thickness: pixels; - - width: pixels; - bar: sprite; -} - flatLabel { font: font; margin: margins; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index a5985e0b2..049b2a6ff 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1197,22 +1197,20 @@ namespace { ImagePtr image(const MTPPhotoSize &size) { switch (size.type()) { case mtpc_photoSize: { - const auto &d(size.c_photoSize()); + auto &d = size.c_photoSize(); if (d.vlocation.type() == mtpc_fileLocation) { - const auto &l(d.vlocation.c_fileLocation()); + auto &l = d.vlocation.c_fileLocation(); return ImagePtr(StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v), d.vsize.v); } } break; case mtpc_photoCachedSize: { - const auto &d(size.c_photoCachedSize()); + auto &d = size.c_photoCachedSize(); if (d.vlocation.type() == mtpc_fileLocation) { - const auto &l(d.vlocation.c_fileLocation()); - const auto &s(d.vbytes.c_string().v); - QByteArray bytes(s.data(), s.size()); + auto &l = d.vlocation.c_fileLocation(); + auto bytes = qba(d.vbytes); return ImagePtr(StorageImageLocation(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v), bytes); } else if (d.vlocation.type() == mtpc_fileLocationUnavailable) { - const string &s(d.vbytes.c_string().v); - QByteArray bytes(s.data(), s.size()); + auto bytes = qba(d.vbytes); return ImagePtr(StorageImageLocation(d.vw.v, d.vh.v, 0, 0, 0, 0), bytes); } } break; @@ -1430,12 +1428,12 @@ namespace { char size = 0; switch (i->type()) { case mtpc_photoSize: { - const string &s(i->c_photoSize().vtype.c_string().v); + auto &s = i->c_photoSize().vtype.c_string().v; if (s.size()) size = s[0]; } break; case mtpc_photoCachedSize: { - const string &s(i->c_photoCachedSize().vtype.c_string().v); + auto &s = i->c_photoCachedSize().vtype.c_string().v; if (s.size()) size = s[0]; } break; } @@ -2070,22 +2068,28 @@ namespace { cSetSavedPeers(SavedPeers()); cSetSavedPeersByTime(SavedPeersByTime()); cSetRecentInlineBots(RecentInlineBots()); - for_const (PeerData *peer, peersData) { + + for_const (auto peer, ::peersData) { delete peer; } - peersData.clear(); - for_const (PhotoData *photo, ::photosData) { + ::peersData.clear(); + for_const (auto game, ::gamesData) { + delete game; + } + ::gamesData.clear(); + for_const (auto webpage, ::webPagesData) { + delete webpage; + } + ::webPagesData.clear(); + for_const (auto photo, ::photosData) { delete photo; } ::photosData.clear(); - for_const (DocumentData *document, ::documentsData) { + for_const (auto document, ::documentsData) { delete document; } ::documentsData.clear(); - for_const (WebPageData *webpage, webPagesData) { - delete webpage; - } - webPagesData.clear(); + if (api()) api()->clearWebPageRequests(); cSetRecentStickers(RecentStickerPack()); Global::SetStickerSets(Stickers::Sets()); diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index 61107ba4a..25265a48a 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -285,8 +285,8 @@ void MaxInviteBox::paintEvent(QPaintEvent *e) { p.drawText(_invitationLink, _link, option); if (!_goodTextLink.isEmpty() && a_goodOpacity.current() > 0) { p.setOpacity(a_goodOpacity.current()); - p.setPen(st::setGoodColor->p); - p.setFont(st::boxTextFont->f); + p.setPen(st::setGoodColor); + p.setFont(st::boxTextFont); p.drawTextLeft(st::boxPadding.left(), height() - st::boxButtonPadding.bottom() - _close.height() + st::defaultBoxButton.textTop + st::defaultBoxButton.font->ascent - st::boxTextFont->ascent, width(), _goodTextLink); p.setOpacity(1); } diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp index 6c20fbc79..1058ed031 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.cpp +++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp @@ -1508,8 +1508,8 @@ void StickersBox::paintEvent(QPaintEvent *e) { void StickersBox::closePressed() { if (!_disenableRequests.isEmpty()) { - for (QMap<mtpRequestId, NullType>::const_iterator i = _disenableRequests.cbegin(), e = _disenableRequests.cend(); i != e; ++i) { - MTP::cancel(i.key()); + for_const (auto requestId, _disenableRequests) { + MTP::cancel(requestId); } _disenableRequests.clear(); Global::SetLastStickersUpdate(0); @@ -1607,7 +1607,7 @@ void StickersBox::onSave() { if (!(it->flags & MTPDstickerSet::Flag::f_archived)) { MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName)); if (it->flags & MTPDstickerSet::Flag::f_official) { - _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolTrue()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); + _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolTrue()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5)); it->flags |= MTPDstickerSet::Flag::f_archived; auto index = Global::RefArchivedStickerSetsOrder().indexOf(it->id); if (index < 0) { @@ -1615,7 +1615,7 @@ void StickersBox::onSave() { writeArchived = true; } } else { - _disenableRequests.insert(MTP::send(MTPmessages_UninstallStickerSet(setId), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); + _disenableRequests.insert(MTP::send(MTPmessages_UninstallStickerSet(setId), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5)); int removeIndex = Global::StickerSetsOrder().indexOf(it->id); if (removeIndex >= 0) Global::RefStickerSetsOrder().removeAt(removeIndex); if (!(it->flags & MTPDstickerSet_ClientFlag::f_featured) && !(it->flags & MTPDstickerSet_ClientFlag::f_special)) { @@ -1645,7 +1645,7 @@ void StickersBox::onSave() { if (it != sets.cend()) { if ((it->flags & MTPDstickerSet::Flag::f_archived) && !disabled.contains(it->id)) { MTPInputStickerSet setId = (it->id && it->access) ? MTP_inputStickerSetID(MTP_long(it->id), MTP_long(it->access)) : MTP_inputStickerSetShortName(MTP_string(it->shortName)); - _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolFalse()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5), NullType()); + _disenableRequests.insert(MTP::send(MTPmessages_InstallStickerSet(setId, MTP_boolFalse()), rpcDone(&StickersBox::disenableDone), rpcFail(&StickersBox::disenableFail), 0, 5)); it->flags &= ~MTPDstickerSet::Flag::f_archived; writeArchived = true; } diff --git a/Telegram/SourceFiles/boxes/stickersetbox.h b/Telegram/SourceFiles/boxes/stickersetbox.h index 1626fd08a..113ac8aa3 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.h +++ b/Telegram/SourceFiles/boxes/stickersetbox.h @@ -186,7 +186,7 @@ private: ChildWidget<internal::StickersInner> _inner; ChildWidget<BoxButton> _save = { nullptr }; ChildWidget<BoxButton> _cancel = { nullptr }; - QMap<mtpRequestId, NullType> _disenableRequests; + OrderedSet<mtpRequestId> _disenableRequests; mtpRequestId _reorderRequest = 0; ChildWidget<PlainShadow> _topShadow = { nullptr }; ChildWidget<ScrollableBoxShadow> _bottomShadow = { nullptr }; diff --git a/Telegram/SourceFiles/core/basic_types.h b/Telegram/SourceFiles/core/basic_types.h index 2b22bc4cd..9487daec9 100644 --- a/Telegram/SourceFiles/core/basic_types.h +++ b/Telegram/SourceFiles/core/basic_types.h @@ -22,157 +22,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include <string> #include <exception> +#include <ctime> #include <QtCore/QReadWriteLock> -#include <ctime> +#include "core/stl_subset.h" +#include "core/ordered_set.h" -#ifndef OS_MAC_OLD -#include <memory> -#endif // OS_MAC_OLD - -template <typename T> -void deleteAndMark(T *&link) { - delete link; - link = reinterpret_cast<T*>(0x00000BAD); -} - -template <typename T> -T *getPointerAndReset(T *&ptr) { - T *result = nullptr; - qSwap(result, ptr); - return result; -} - -struct NullType { -}; - -// ordered set template based on QMap -template <typename T> -class OrderedSet { - typedef OrderedSet<T> Self; - typedef QMap<T, NullType> Impl; - typedef typename Impl::iterator IteratorImpl; - typedef typename Impl::const_iterator ConstIteratorImpl; - Impl impl_; - -public: - - inline bool operator==(const Self &other) const { return impl_ == other.impl_; } - inline bool operator!=(const Self &other) const { return impl_ != other.impl_; } - inline int size() const { return impl_.size(); } - inline bool isEmpty() const { return impl_.isEmpty(); } - inline void detach() { return impl_.detach(); } - inline bool isDetached() const { return impl_.isDetached(); } - inline void clear() { return impl_.clear(); } - inline QList<T> values() const { return impl_.keys(); } - inline const T &first() const { return impl_.firstKey(); } - inline const T &last() const { return impl_.lastKey(); } - - class const_iterator; - class iterator { - public: - typedef typename IteratorImpl::iterator_category iterator_category; - typedef typename IteratorImpl::difference_type difference_type; - typedef T value_type; - typedef T *pointer; - typedef T &reference; - - explicit iterator(const IteratorImpl &impl) : impl_(impl) { - } - inline const T &operator*() const { return impl_.key(); } - inline const T *operator->() const { return &impl_.key(); } - inline bool operator==(const iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; } - inline iterator &operator++() { ++impl_; return *this; } - inline iterator operator++(int) { return iterator(impl_++); } - inline iterator &operator--() { --impl_; return *this; } - inline iterator operator--(int) { return iterator(impl_--); } - inline iterator operator+(int j) const { return iterator(impl_ + j); } - inline iterator operator-(int j) const { return iterator(impl_ - j); } - inline iterator &operator+=(int j) { impl_ += j; return *this; } - inline iterator &operator-=(int j) { impl_ -= j; return *this; } - - friend class const_iterator; - inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; } - - private: - IteratorImpl impl_; - friend class OrderedSet<T>; - - }; - friend class iterator; - - class const_iterator { - public: - typedef typename IteratorImpl::iterator_category iterator_category; - typedef typename IteratorImpl::difference_type difference_type; - typedef T value_type; - typedef T *pointer; - typedef T &reference; - - explicit const_iterator(const ConstIteratorImpl &impl) : impl_(impl) { - } - inline const T &operator*() const { return impl_.key(); } - inline const T *operator->() const { return &impl_.key(); } - inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; } - inline const_iterator &operator++() { ++impl_; return *this; } - inline const_iterator operator++(int) { return const_iterator(impl_++); } - inline const_iterator &operator--() { --impl_; return *this; } - inline const_iterator operator--(int) { return const_iterator(impl_--); } - inline const_iterator operator+(int j) const { return const_iterator(impl_ + j); } - inline const_iterator operator-(int j) const { return const_iterator(impl_ - j); } - inline const_iterator &operator+=(int j) { impl_ += j; return *this; } - inline const_iterator &operator-=(int j) { impl_ -= j; return *this; } - - friend class iterator; - inline bool operator==(const iterator &other) const { return impl_ == other.impl_; } - inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; } - - private: - ConstIteratorImpl impl_; - friend class OrderedSet<T>; - - }; - friend class const_iterator; - - // STL style - inline iterator begin() { return iterator(impl_.begin()); } - inline const_iterator begin() const { return const_iterator(impl_.cbegin()); } - inline const_iterator constBegin() const { return const_iterator(impl_.cbegin()); } - inline const_iterator cbegin() const { return const_iterator(impl_.cbegin()); } - inline iterator end() { detach(); return iterator(impl_.end()); } - inline const_iterator end() const { return const_iterator(impl_.cend()); } - inline const_iterator constEnd() const { return const_iterator(impl_.cend()); } - inline const_iterator cend() const { return const_iterator(impl_.cend()); } - inline iterator erase(iterator it) { return iterator(impl_.erase(it.impl_)); } - - inline iterator insert(const T &value) { return iterator(impl_.insert(value, NullType())); } - inline iterator insert(const_iterator pos, const T &value) { return iterator(impl_.insert(pos.impl_, value, NullType())); } - inline int remove(const T &value) { return impl_.remove(value); } - inline bool contains(const T &value) const { return impl_.contains(value); } - - // more Qt - typedef iterator Iterator; - typedef const_iterator ConstIterator; - inline int count() const { return impl_.count(); } - inline iterator find(const T &value) { return iterator(impl_.find(value)); } - inline const_iterator find(const T &value) const { return const_iterator(impl_.constFind(value)); } - inline const_iterator constFind(const T &value) const { return const_iterator(impl_.constFind(value)); } - inline Self &unite(const Self &other) { impl_.unite(other.impl_); return *this; } - - // STL compatibility - typedef typename Impl::difference_type difference_type; - typedef typename Impl::size_type size_type; - inline bool empty() const { return impl_.empty(); } - -}; - -// thanks Chromium see https://blogs.msdn.microsoft.com/the1/2004/05/07/how-would-you-get-the-count-of-an-array-in-c-2/ -template <typename T, size_t N> char(&ArraySizeHelper(T(&array)[N]))[N]; -#define arraysize(array) (sizeof(ArraySizeHelper(array))) +//using uchar = unsigned char; // Qt has uchar +using int16 = qint16; +using uint16 = quint16; +using int32 = qint32; +using uint32 = quint32; +using int64 = qint64; +using uint64 = quint64; +using float32 = float; +using float64 = double; #define qsl(s) QStringLiteral(s) #define qstr(s) QLatin1String(s, sizeof(s) - 1) @@ -206,1064 +71,3 @@ Q_DECLARE_FRIEND_INCOMPATIBLE_FLAGS(Flags) // if you have "QVector<T*> v" then "for (T * const p : v)" will still call QVector::detach(), // while "for_const (T *p, v)" won't and "for_const (T *&p, v)" won't compile #define for_const(range_declaration, range_expression) for (range_declaration : std_::as_const(range_expression)) - -template <typename Enum> -inline QFlags<Enum> qFlags(Enum v) { - return QFlags<Enum>(v); -} - -//typedef unsigned char uchar; // Qt has uchar -typedef qint16 int16; -typedef quint16 uint16; -typedef qint32 int32; -typedef quint32 uint32; -typedef qint64 int64; -typedef quint64 uint64; - -static const int32 ScrollMax = INT_MAX; - -extern uint64 _SharedMemoryLocation[]; -template <typename T, unsigned int N> -T *SharedMemoryLocation() { - static_assert(N < 4, "Only 4 shared memory locations!"); - return reinterpret_cast<T*>(_SharedMemoryLocation + N); -} - -// see https://github.com/boostcon/cppnow_presentations_2012/blob/master/wed/schurr_cpp11_tools_for_class_authors.pdf -class str_const { // constexpr string -public: - template<std::size_t N> - constexpr str_const(const char(&a)[N]) : _str(a), _size(N - 1) { - } - constexpr char operator[](std::size_t n) const { - return (n < _size) ? _str[n] : -#ifndef OS_MAC_OLD - throw std::out_of_range(""); -#else // OS_MAC_OLD - throw std::exception(); -#endif // OS_MAC_OLD - } - constexpr std::size_t size() const { return _size; } - const char *c_str() const { return _str; } - -private: - const char* const _str; - const std::size_t _size; - -}; - -inline QString str_const_toString(const str_const &str) { - return QString::fromUtf8(str.c_str(), str.size()); -} - -template <typename T> -inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; } - -template <typename T> -inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; } - -#ifdef Q_OS_WIN -typedef float float32; -typedef double float64; -#else -typedef float float32; -typedef double float64; -#endif - -using std::string; -using std::exception; -#ifdef OS_MAC_OLD -namespace std { -using nullptr_t = decltype(nullptr); -} -#endif // OS_MAC_OLD - -// 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 { - using type = T; -}; -template <typename T> -struct remove_reference<T&> { - using type = T; -}; -template <typename T> -struct remove_reference<T&&> { - using type = T; -}; - -template <typename T> -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); -} - -template <typename T> -void swap(T &a, T &b) { - T tmp = move(a); - a = move(b); - b = move(tmp); -} - -template <typename T> -struct remove_const { - using type = T; -}; - -template <typename T> -struct remove_const<const T> { - using type = T; -}; - -template <typename T> -struct remove_volatile { - using type = T; -}; - -template <typename T> -struct remove_volatile<volatile T> { - using type = T; -}; - -template <typename T> -using decay_simple_t = typename remove_const<typename remove_volatile<typename remove_reference<T>::type>::type>::type; - -template <typename T1, typename T2> -struct is_same : false_type { -}; - -template <typename T> -struct is_same<T, T> : true_type { -}; - -template <bool, typename T = void> -struct enable_if { -}; - -template <typename T> -struct enable_if<true, T> { - using type = T; -}; - -template <bool Test, typename T = void> -using enable_if_t = typename enable_if<Test, T>::type; - -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; - -// This is not full unique_ptr, but at least with std interface. -template <typename T> -class unique_ptr { -public: - constexpr unique_ptr() noexcept = default; - unique_ptr(const unique_ptr<T> &) = delete; - unique_ptr<T> &operator=(const unique_ptr<T> &) = delete; - - constexpr unique_ptr(std::nullptr_t) { - } - unique_ptr<T> &operator=(std::nullptr_t) noexcept { - reset(); - return (*this); - } - - explicit unique_ptr(T *p) noexcept : _p(p) { - } - - template <typename U> - unique_ptr(unique_ptr<U> &&other) noexcept : _p(other.release()) { - } - template <typename U> - unique_ptr<T> &operator=(unique_ptr<U> &&other) noexcept { - reset(other.release()); - return (*this); - } - unique_ptr<T> &operator=(unique_ptr<T> &&other) noexcept { - if (this != &other) { - reset(other.release()); - } - return (*this); - } - - void swap(unique_ptr<T> &other) noexcept { - std::swap(_p, other._p); - } - ~unique_ptr() noexcept { - delete _p; - } - - T &operator*() const { - return (*get()); - } - T *operator->() const noexcept { - return get(); - } - T *get() const noexcept { - return _p; - } - explicit operator bool() const noexcept { - return get() != nullptr; - } - - T *release() noexcept { - return getPointerAndReset(_p); - } - - void reset(T *p = nullptr) noexcept { - T *old = _p; - _p = p; - if (old) { - delete old; - } - } - -private: - T *_p = nullptr; - -}; - -template <typename T, typename... Args> -inline unique_ptr<T> make_unique(Args&&... args) { - return unique_ptr<T>(new T(forward<Args>(args)...)); -} - -template <typename T> -inline bool operator==(const unique_ptr<T> &a, std::nullptr_t) noexcept { - return !a; -} -template <typename T> -inline bool operator==(std::nullptr_t, const unique_ptr<T> &b) noexcept { - return !b; -} -template <typename T> -inline bool operator!=(const unique_ptr<T> &a, std::nullptr_t b) noexcept { - return !(a == b); -} -template <typename T> -inline bool operator!=(std::nullptr_t a, const unique_ptr<T> &b) noexcept { - return !(a == b); -} - -using _yes = char(&)[1]; -using _no = char(&)[2]; - -template <typename Base, typename Derived> -struct _host { - operator Base*() const; - operator Derived*(); -}; - -template <typename Base, typename Derived> -struct is_base_of { - template <typename T> - static _yes check(Derived*, T); - static _no check(Base*, int); - - static constexpr bool value = sizeof(check(_host<Base, Derived>(), int())) == sizeof(_yes); -}; - -} // namespace std_ - -template <typename T> -T createAndSwap(T &value) { - T result = T(); - std_::swap(result, value); - return std_::move(result); -} - -#include "logs.h" - -static volatile int *t_assert_nullptr = nullptr; -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::setCrashAnnotation("Assertion", info); - *t_assert_nullptr = 0; -} -#define t_assert_full(condition, message, file, line) ((!(condition)) ? t_assert_fail(message, file, line) : t_noop()) -#define t_assert_c(condition, comment) t_assert_full(condition, "\"" #condition "\" (" comment ")", __FILE__, __LINE__) -#define t_assert(condition) t_assert_full(condition, "\"" #condition "\"", __FILE__, __LINE__) - -class Exception : public exception { -public: - - Exception(const QString &msg, bool isFatal = true) : _fatal(isFatal), _msg(msg.toUtf8()) { - LOG(("Exception: %1").arg(msg)); - } - bool fatal() const { - return _fatal; - } - - virtual const char *what() const throw() { - return _msg.constData(); - } - virtual ~Exception() throw() { - } - -private: - bool _fatal; - QByteArray _msg; -}; - -class MTPint; -typedef int32 TimeId; -TimeId myunixtime(); -void unixtimeInit(); -void unixtimeSet(TimeId servertime, bool force = false); -TimeId unixtime(); -TimeId fromServerTime(const MTPint &serverTime); -void toServerTime(const TimeId &clientTime, MTPint &outServerTime); -uint64 msgid(); -int32 reqid(); - -inline QDateTime date(int32 time = -1) { - QDateTime result; - if (time >= 0) result.setTime_t(time); - return result; -} - -inline QDateTime dateFromServerTime(const MTPint &time) { - return date(fromServerTime(time)); -} - -inline QDateTime date(const MTPint &time) { - return dateFromServerTime(time); -} - -QDateTime dateFromServerTime(TimeId time); - -inline void mylocaltime(struct tm * _Tm, const time_t * _Time) { -#ifdef Q_OS_WIN - localtime_s(_Tm, _Time); -#else - localtime_r(_Time, _Tm); -#endif -} - -namespace ThirdParty { - - void start(); - void finish(); - -} - -bool checkms(); // returns true if time has changed -uint64 getms(bool checked = false); - -class SingleTimer : public QTimer { // single shot timer with check - Q_OBJECT - -public: - - SingleTimer(); - - void setSingleShot(bool); // is not available - void start(); // is not available - -public slots: - - void start(int msec); - void startIfNotActive(int msec); - void adjust() { - uint64 n = getms(true); - if (isActive()) { - if (n >= _finishing) { - start(0); - } else { - start(_finishing - n); - } - } - } - -private: - uint64 _finishing; - bool _inited; - -}; - -const static uint32 _md5_block_size = 64; -class HashMd5 { -public: - - HashMd5(const void *input = 0, uint32 length = 0); - void feed(const void *input, uint32 length); - int32 *result(); - -private: - - void init(); - void finalize(); - void transform(const uchar *block); - - bool _finalized; - uchar _buffer[_md5_block_size]; - uint32 _count[2]; - uint32 _state[4]; - uchar _digest[16]; - -}; - -int32 hashCrc32(const void *data, uint32 len); -int32 *hashSha1(const void *data, uint32 len, void *dest); // dest - ptr to 20 bytes, returns (int32*)dest -int32 *hashSha256(const void *data, uint32 len, void *dest); // dest - ptr to 32 bytes, returns (int32*)dest -int32 *hashMd5(const void *data, uint32 len, void *dest); // dest = ptr to 16 bytes, returns (int32*)dest -char *hashMd5Hex(const int32 *hashmd5, void *dest); // dest = ptr to 32 bytes, returns (char*)dest -inline char *hashMd5Hex(const void *data, uint32 len, void *dest) { // dest = ptr to 32 bytes, returns (char*)dest - return hashMd5Hex(HashMd5(data, len).result(), dest); -} - -// good random (using openssl implementation) -void memset_rand(void *data, uint32 len); -template <typename T> -T rand_value() { - T result; - memset_rand(&result, sizeof(result)); - return result; -} - -inline void memset_rand_bad(void *data, uint32 len) { - for (uchar *i = reinterpret_cast<uchar*>(data), *e = i + len; i != e; ++i) { - *i = uchar(rand() & 0xFF); - } -} - -template <typename T> -inline void memsetrnd_bad(T &value) { - memset_rand_bad(&value, sizeof(value)); -} - -class ReadLockerAttempt { -public: - - ReadLockerAttempt(QReadWriteLock *_lock) : success(_lock->tryLockForRead()), lock(_lock) { - } - ~ReadLockerAttempt() { - if (success) { - lock->unlock(); - } - } - - operator bool() const { - return success; - } - -private: - - bool success; - QReadWriteLock *lock; - -}; - -inline QString fromUtf8Safe(const char *str, int32 size = -1) { - if (!str || !size) return QString(); - if (size < 0) size = int32(strlen(str)); - QString result(QString::fromUtf8(str, size)); - QByteArray back = result.toUtf8(); - if (back.size() != size || memcmp(back.constData(), str, size)) return QString::fromLocal8Bit(str, size); - return result; -} - -inline QString fromUtf8Safe(const QByteArray &str) { - return fromUtf8Safe(str.constData(), str.size()); -} - -static const QRegularExpression::PatternOptions reMultiline(QRegularExpression::DotMatchesEverythingOption | QRegularExpression::MultilineOption); - -template <typename T> -inline T snap(const T &v, const T &_min, const T &_max) { - return (v < _min) ? _min : ((v > _max) ? _max : v); -} - -template <typename T> -class ManagedPtr { -public: - ManagedPtr() : ptr(0) { - } - ManagedPtr(T *p) : ptr(p) { - } - T *operator->() const { - return ptr; - } - T *v() const { - return ptr; - } - -protected: - - T *ptr; - typedef ManagedPtr<T> Parent; -}; - -QString translitRusEng(const QString &rus); -QString rusKeyboardLayoutSwitch(const QString &from); - -enum DBISendKey { - dbiskEnter = 0, - dbiskCtrlEnter = 1, -}; - -enum DBINotifyView { - dbinvShowPreview = 0, - dbinvShowName = 1, - dbinvShowNothing = 2, -}; - -enum DBIWorkMode { - dbiwmWindowAndTray = 0, - dbiwmTrayOnly = 1, - dbiwmWindowOnly = 2, -}; - -enum DBIConnectionType { - dbictAuto = 0, - dbictHttpAuto = 1, // not used - dbictHttpProxy = 2, - dbictTcpProxy = 3, -}; - -enum DBIDefaultAttach { - dbidaDocument = 0, - dbidaPhoto = 1, -}; - -struct ProxyData { - QString host; - uint32 port = 0; - QString user, password; -}; - -enum DBIScale { - dbisAuto = 0, - dbisOne = 1, - dbisOneAndQuarter = 2, - dbisOneAndHalf = 3, - dbisTwo = 4, - - dbisScaleCount = 5, -}; - -static const int MatrixRowShift = 40000; - -enum DBIEmojiTab { - dbietRecent = -1, - dbietPeople = 0, - dbietNature = 1, - dbietFood = 2, - dbietActivity = 3, - dbietTravel = 4, - dbietObjects = 5, - dbietSymbols = 6, - dbietStickers = 666, -}; -static const int emojiTabCount = 8; -inline DBIEmojiTab emojiTabAtIndex(int index) { - return (index < 0 || index >= emojiTabCount) ? dbietRecent : DBIEmojiTab(index - 1); -} - -enum DBIPlatform { - dbipWindows = 0, - dbipMac = 1, - dbipLinux64 = 2, - dbipLinux32 = 3, - dbipMacOld = 4, -}; - -enum DBIPeerReportSpamStatus { - dbiprsNoButton = 0, // hidden, but not in the cloud settings yet - dbiprsUnknown = 1, // contacts not loaded yet - dbiprsShowButton = 2, // show report spam button, each show peer request setting from cloud - dbiprsReportSent = 3, // report sent, but the report spam panel is not hidden yet - dbiprsHidden = 4, // hidden in the cloud or not needed (bots, contacts, etc), no more requests - dbiprsRequesting = 5, // requesting the cloud setting right now -}; - -typedef enum { - HitTestNone = 0, - HitTestClient, - HitTestSysButton, - HitTestIcon, - HitTestCaption, - HitTestTop, - HitTestTopRight, - HitTestRight, - HitTestBottomRight, - HitTestBottom, - HitTestBottomLeft, - HitTestLeft, - HitTestTopLeft, -} HitTestType; - -inline QString strMakeFromLetters(const uint32 *letters, int32 len) { - QString result; - result.reserve(len); - for (int32 i = 0; i < len; ++i) { - result.push_back(QChar((((letters[i] >> 16) & 0xFF) << 8) | (letters[i] & 0xFF))); - } - return result; -} - -class MimeType { -public: - - enum TypeEnum { - Unknown, - WebP, - }; - - MimeType(const QMimeType &type) : _typeStruct(type), _type(Unknown) { - } - MimeType(TypeEnum type) : _type(type) { - } - QStringList globPatterns() const; - QString filterString() const; - QString name() const; - -private: - - QMimeType _typeStruct; - TypeEnum _type; - -}; - -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; -} -inline int floorclamp(int value, int step, int lowest, int highest) { - return qMin(qMax(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 int ceilclamp(int value, int step, int lowest, int highest) { - return qMax(qMin((value + step - 1) / 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 { - ForwardSelectedMessages, - ForwardContextMessage, - ForwardPressedMessage, - ForwardPressedLinkMessage -}; - -enum ShowLayerOption { - CloseOtherLayers = 0x00, - KeepOtherLayers = 0x01, - ShowAfterOtherLayers = 0x03, - - AnimatedShowLayer = 0x00, - ForceFastShowLayer = 0x04, -}; -Q_DECLARE_FLAGS(ShowLayerOptions, ShowLayerOption); -Q_DECLARE_OPERATORS_FOR_FLAGS(ShowLayerOptions); - -static int32 FullArcLength = 360 * 16; -static int32 QuarterArcLength = (FullArcLength / 4); -static int32 MinArcLength = (FullArcLength / 360); -static int32 AlmostFullArcLength = (FullArcLength - MinArcLength); - -template <typename T, typename... Args> -inline QSharedPointer<T> MakeShared(Args&&... args) { - return QSharedPointer<T>(new T(std_::forward<Args>(args)...)); -} - -// This pointer is used for global non-POD variables that are allocated -// on demand by createIfNull(lambda) and are never automatically freed. -template <typename T> -class NeverFreedPointer { -public: - NeverFreedPointer() = default; - NeverFreedPointer(const NeverFreedPointer<T> &other) = delete; - NeverFreedPointer &operator=(const NeverFreedPointer<T> &other) = delete; - - template <typename U> - void createIfNull(U creator) { - if (isNull()) { - reset(creator()); - } - } - - template <typename... Args> - void makeIfNull(Args&&... args) { - if (isNull()) { - reset(new T(std_::forward<Args>(args)...)); - } - }; - - T *data() const { - return _p; - } - T *release() { - return getPointerAndReset(_p); - } - void reset(T *p = nullptr) { - delete _p; - _p = 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(); - } - -private: - T *_p; - -}; - -// This pointer is used for static non-POD variables that are allocated -// on first use by constructor and are never automatically freed. -template <typename T> -class StaticNeverFreedPointer { -public: - explicit StaticNeverFreedPointer(T *p) : _p(p) { - } - StaticNeverFreedPointer(const StaticNeverFreedPointer<T> &other) = delete; - StaticNeverFreedPointer &operator=(const StaticNeverFreedPointer<T> &other) = delete; - - T *data() const { - return _p; - } - T *release() { - return getPointerAndReset(_p); - } - void reset(T *p = nullptr) { - delete _p; - _p = 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(); - } - -private: - T *_p = nullptr; - -}; - -class Composer; -typedef void(*ComponentConstruct)(void *location, Composer *composer); -typedef void(*ComponentDestruct)(void *location); -typedef void(*ComponentMove)(void *location, void *waslocation); - -struct ComponentWrapStruct { - // don't init any fields, because it is only created in - // global scope, so it will be filled by zeros from the start - ComponentWrapStruct() { - } - ComponentWrapStruct(std::size_t size, std::size_t align, ComponentConstruct construct, ComponentDestruct destruct, ComponentMove move) - : Size(size) - , Align(align) - , Construct(construct) - , Destruct(destruct) - , Move(move) { - } - std::size_t Size; - std::size_t Align; - ComponentConstruct Construct; - ComponentDestruct Destruct; - ComponentMove Move; -}; - -template <int Value, int Denominator> -struct CeilDivideMinimumOne { - static const int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0)); -}; - -extern ComponentWrapStruct ComponentWraps[64]; -extern QAtomicInt ComponentIndexLast; - -template <typename Type> -struct BaseComponent { - BaseComponent() { - static_assert(alignof(Type) <= alignof(SmallestSizeType), "Components should align to a pointer!"); - } - BaseComponent(const BaseComponent &other) = delete; - BaseComponent &operator=(const BaseComponent &other) = delete; - BaseComponent(BaseComponent &&other) = delete; - BaseComponent &operator=(BaseComponent &&other) = default; - - static int Index() { - static QAtomicInt _index(0); - if (int index = _index.loadAcquire()) { - return index - 1; - } - while (true) { - int last = ComponentIndexLast.loadAcquire(); - if (ComponentIndexLast.testAndSetOrdered(last, last + 1)) { - t_assert(last < 64); - if (_index.testAndSetOrdered(0, last + 1)) { - ComponentWraps[last] = ComponentWrapStruct( - CeilDivideMinimumOne<sizeof(Type), sizeof(SmallestSizeType)>::Result * sizeof(SmallestSizeType), - alignof(Type), - Type::ComponentConstruct, - Type::ComponentDestruct, - Type::ComponentMove); - } - break; - } - } - return _index.loadAcquire() - 1; - } - static uint64 Bit() { - return (1ULL << Index()); - } - -protected: - using SmallestSizeType = void*; - - static void ComponentConstruct(void *location, Composer *composer) { - new (location) Type(); - } - static void ComponentDestruct(void *location) { - ((Type*)location)->~Type(); - } - static void ComponentMove(void *location, void *waslocation) { - *(Type*)location = std_::move(*(Type*)waslocation); - } - -}; - -class ComposerMetadata { -public: - ComposerMetadata(uint64 mask) : size(0), last(64), _mask(mask) { - for (int i = 0; i < 64; ++i) { - uint64 m = (1ULL << i); - if (_mask & m) { - int s = ComponentWraps[i].Size; - if (s) { - offsets[i] = size; - size += s; - } else { - offsets[i] = -1; - } - } else if (_mask < m) { - last = i; - for (; i < 64; ++i) { - offsets[i] = -1; - } - } else { - offsets[i] = -1; - } - } - } - - int size, last; - int offsets[64]; - - bool equals(uint64 mask) const { - return _mask == mask; - } - uint64 maskadd(uint64 mask) const { - return _mask | mask; - } - uint64 maskremove(uint64 mask) const { - return _mask & (~mask); - } - -private: - uint64 _mask; - -}; - -const ComposerMetadata *GetComposerMetadata(uint64 mask); - -class Composer { -public: - Composer(uint64 mask = 0) : _data(zerodata()) { - if (mask) { - const ComposerMetadata *meta = GetComposerMetadata(mask); - int size = sizeof(meta) + meta->size; - - auto data = operator new(size); - t_assert(data != nullptr); - - _data = data; - _meta() = meta; - for (int i = 0; i < meta->last; ++i) { - int offset = meta->offsets[i]; - if (offset >= 0) { - try { - auto constructAt = _dataptrunsafe(offset); -#ifndef OS_MAC_OLD - auto space = ComponentWraps[i].Size; - auto alignedAt = std::align(ComponentWraps[i].Align, space, constructAt, space); - t_assert(alignedAt == constructAt); -#endif // OS_MAC_OLD - ComponentWraps[i].Construct(constructAt, this); - } catch (...) { - while (i > 0) { - --i; - offset = meta->offsets[--i]; - if (offset >= 0) { - ComponentWraps[i].Destruct(_dataptrunsafe(offset)); - } - } - throw; - } - } - } - } - } - Composer(const Composer &other) = delete; - Composer &operator=(const Composer &other) = delete; - ~Composer() { - if (_data != zerodata()) { - auto meta = _meta(); - for (int i = 0; i < meta->last; ++i) { - int offset = meta->offsets[i]; - if (offset >= 0) { - ComponentWraps[i].Destruct(_dataptrunsafe(offset)); - } - } - operator delete(_data); - } - } - - template <typename Type> - bool Has() const { - return (_meta()->offsets[Type::Index()] >= 0); - } - - template <typename Type> - Type *Get() { - return static_cast<Type*>(_dataptr(_meta()->offsets[Type::Index()])); - } - template <typename Type> - const Type *Get() const { - return static_cast<const Type*>(_dataptr(_meta()->offsets[Type::Index()])); - } - -protected: - void UpdateComponents(uint64 mask = 0) { - if (!_meta()->equals(mask)) { - Composer tmp(mask); - tmp.swap(*this); - if (_data != zerodata() && tmp._data != zerodata()) { - auto meta = _meta(), wasmeta = tmp._meta(); - for (int i = 0; i < meta->last; ++i) { - int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i]; - if (offset >= 0 && wasoffset >= 0) { - ComponentWraps[i].Move(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset)); - } - } - } - } - } - void AddComponents(uint64 mask = 0) { - UpdateComponents(_meta()->maskadd(mask)); - } - void RemoveComponents(uint64 mask = 0) { - UpdateComponents(_meta()->maskremove(mask)); - } - -private: - static const ComposerMetadata *ZeroComposerMetadata; - static void *zerodata() { - return &ZeroComposerMetadata; - } - - void *_dataptrunsafe(int skip) const { - return (char*)_data + sizeof(_meta()) + skip; - } - void *_dataptr(int skip) const { - return (skip >= 0) ? _dataptrunsafe(skip) : 0; - } - const ComposerMetadata *&_meta() const { - return *static_cast<const ComposerMetadata**>(_data); - } - void *_data; - - void swap(Composer &other) { - std::swap(_data, other._data); - } - -}; diff --git a/Telegram/SourceFiles/core/lambda_wrap.h b/Telegram/SourceFiles/core/lambda_wrap.h index 9305c6694..b8c6c8e53 100644 --- a/Telegram/SourceFiles/core/lambda_wrap.h +++ b/Telegram/SourceFiles/core/lambda_wrap.h @@ -146,11 +146,9 @@ struct lambda_wrap_helper_move_impl<Lambda, std_::false_type, Return, Args...> : } static void construct_move_lambda_method(void *lambda, void *source) { static_assert(alignof(JustLambda) <= alignof(void*), "Bad lambda alignment."); -#ifndef OS_MAC_OLD auto space = sizeof(JustLambda); - auto aligned = std::align(alignof(JustLambda), space, lambda, space); + auto aligned = std_::align(alignof(JustLambda), space, lambda, space); t_assert(aligned == lambda); -#endif // OS_MAC_OLD auto source_lambda = static_cast<JustLambda*>(source); new (lambda) JustLambda(static_cast<JustLambda&&>(*source_lambda)); } @@ -223,11 +221,9 @@ struct lambda_wrap_helper_copy_impl<Lambda, std_::false_type, Return, Args...> : } static void construct_copy_lambda_method(void *lambda, const void *source) { static_assert(alignof(JustLambda) <= alignof(void*), "Bad lambda alignment."); -#ifndef OS_MAC_OLD auto space = sizeof(JustLambda); - auto aligned = std::align(alignof(JustLambda), space, lambda, space); + auto aligned = std_::align(alignof(JustLambda), space, lambda, space); t_assert(aligned == lambda); -#endif // OS_MAC_OLD auto source_lambda = static_cast<const JustLambda*>(source); new (lambda) JustLambda(static_cast<const JustLambda &>(*source_lambda)); } diff --git a/Telegram/SourceFiles/core/ordered_set.h b/Telegram/SourceFiles/core/ordered_set.h new file mode 100644 index 000000000..05da1455e --- /dev/null +++ b/Telegram/SourceFiles/core/ordered_set.h @@ -0,0 +1,159 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include <QtCore/QMap> + +// ordered set template based on QMap +template <typename T> +class OrderedSet { + struct NullType { + }; + using Self = OrderedSet<T>; + using Impl = QMap<T, NullType>; + using IteratorImpl = typename Impl::iterator; + using ConstIteratorImpl = typename Impl::const_iterator; + Impl impl_; + +public: + inline bool operator==(const Self &other) const { return impl_ == other.impl_; } + inline bool operator!=(const Self &other) const { return impl_ != other.impl_; } + inline int size() const { return impl_.size(); } + inline bool isEmpty() const { return impl_.isEmpty(); } + inline void detach() { return impl_.detach(); } + inline bool isDetached() const { return impl_.isDetached(); } + inline void clear() { return impl_.clear(); } + inline QList<T> values() const { return impl_.keys(); } + inline const T &first() const { return impl_.firstKey(); } + inline const T &last() const { return impl_.lastKey(); } + + class const_iterator; + class iterator { + public: + typedef typename IteratorImpl::iterator_category iterator_category; + typedef typename IteratorImpl::difference_type difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + iterator() = default; + iterator(const iterator &other) = default; + iterator &operator=(const iterator &other) = default; + inline const T &operator*() const { return impl_.key(); } + inline const T *operator->() const { return &impl_.key(); } + inline bool operator==(const iterator &other) const { return impl_ == other.impl_; } + inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; } + inline iterator &operator++() { ++impl_; return *this; } + inline iterator operator++(int) { return iterator(impl_++); } + inline iterator &operator--() { --impl_; return *this; } + inline iterator operator--(int) { return iterator(impl_--); } + inline iterator operator+(int j) const { return iterator(impl_ + j); } + inline iterator operator-(int j) const { return iterator(impl_ - j); } + inline iterator &operator+=(int j) { impl_ += j; return *this; } + inline iterator &operator-=(int j) { impl_ -= j; return *this; } + + friend class const_iterator; + inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; } + inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; } + + private: + explicit iterator(const IteratorImpl &impl) : impl_(impl) { + } + IteratorImpl impl_; + friend class OrderedSet<T>; + + }; + friend class iterator; + + class const_iterator { + public: + typedef typename IteratorImpl::iterator_category iterator_category; + typedef typename IteratorImpl::difference_type difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + const_iterator() = default; + const_iterator(const const_iterator &other) = default; + const_iterator &operator=(const const_iterator &other) = default; + const_iterator(const iterator &other) : impl_(other.impl_) { + } + const_iterator &operator=(const iterator &other) { + impl_ = other.impl_; + return *this; + } + inline const T &operator*() const { return impl_.key(); } + inline const T *operator->() const { return &impl_.key(); } + inline bool operator==(const const_iterator &other) const { return impl_ == other.impl_; } + inline bool operator!=(const const_iterator &other) const { return impl_ != other.impl_; } + inline const_iterator &operator++() { ++impl_; return *this; } + inline const_iterator operator++(int) { return const_iterator(impl_++); } + inline const_iterator &operator--() { --impl_; return *this; } + inline const_iterator operator--(int) { return const_iterator(impl_--); } + inline const_iterator operator+(int j) const { return const_iterator(impl_ + j); } + inline const_iterator operator-(int j) const { return const_iterator(impl_ - j); } + inline const_iterator &operator+=(int j) { impl_ += j; return *this; } + inline const_iterator &operator-=(int j) { impl_ -= j; return *this; } + + friend class iterator; + inline bool operator==(const iterator &other) const { return impl_ == other.impl_; } + inline bool operator!=(const iterator &other) const { return impl_ != other.impl_; } + + private: + explicit const_iterator(const ConstIteratorImpl &impl) : impl_(impl) { + } + ConstIteratorImpl impl_; + friend class OrderedSet<T>; + + }; + friend class const_iterator; + + // STL style + inline iterator begin() { return iterator(impl_.begin()); } + inline const_iterator begin() const { return const_iterator(impl_.cbegin()); } + inline const_iterator constBegin() const { return const_iterator(impl_.cbegin()); } + inline const_iterator cbegin() const { return const_iterator(impl_.cbegin()); } + inline iterator end() { detach(); return iterator(impl_.end()); } + inline const_iterator end() const { return const_iterator(impl_.cend()); } + inline const_iterator constEnd() const { return const_iterator(impl_.cend()); } + inline const_iterator cend() const { return const_iterator(impl_.cend()); } + inline iterator erase(iterator it) { return iterator(impl_.erase(it.impl_)); } + + inline iterator insert(const T &value) { return iterator(impl_.insert(value, NullType())); } + inline iterator insert(const_iterator pos, const T &value) { return iterator(impl_.insert(pos.impl_, value, NullType())); } + inline int remove(const T &value) { return impl_.remove(value); } + inline bool contains(const T &value) const { return impl_.contains(value); } + + // more Qt + typedef iterator Iterator; + typedef const_iterator ConstIterator; + inline int count() const { return impl_.count(); } + inline iterator find(const T &value) { return iterator(impl_.find(value)); } + inline const_iterator find(const T &value) const { return const_iterator(impl_.constFind(value)); } + inline const_iterator constFind(const T &value) const { return const_iterator(impl_.constFind(value)); } + inline Self &unite(const Self &other) { impl_.unite(other.impl_); return *this; } + + // STL compatibility + typedef typename Impl::difference_type difference_type; + typedef typename Impl::size_type size_type; + inline bool empty() const { return impl_.empty(); } + +}; diff --git a/Telegram/SourceFiles/core/runtime_composer.cpp b/Telegram/SourceFiles/core/runtime_composer.cpp new file mode 100644 index 000000000..add2ecaa0 --- /dev/null +++ b/Telegram/SourceFiles/core/runtime_composer.cpp @@ -0,0 +1,52 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "core/runtime_composer.h" + +struct RuntimeComposerMetadatasMap { + QMap<uint64, RuntimeComposerMetadata*> data; + ~RuntimeComposerMetadatasMap() { + for_const (const RuntimeComposerMetadata *p, data) { + delete p; + } + } +}; + +const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask) { + static RuntimeComposerMetadatasMap RuntimeComposerMetadatas; + static QMutex RuntimeComposerMetadatasMutex; + + QMutexLocker lock(&RuntimeComposerMetadatasMutex); + auto i = RuntimeComposerMetadatas.data.constFind(mask); + if (i == RuntimeComposerMetadatas.data.cend()) { + RuntimeComposerMetadata *meta = new RuntimeComposerMetadata(mask); + t_assert(meta != nullptr); + + i = RuntimeComposerMetadatas.data.insert(mask, meta); + } + return i.value(); +} + +const RuntimeComposerMetadata *RuntimeComposer::ZeroRuntimeComposerMetadata = GetRuntimeComposerMetadata(0); + +RuntimeComponentWrapStruct RuntimeComponentWraps[64]; + +QAtomicInt RuntimeComponentIndexLast; diff --git a/Telegram/SourceFiles/core/runtime_composer.h b/Telegram/SourceFiles/core/runtime_composer.h new file mode 100644 index 000000000..bc5b0f15e --- /dev/null +++ b/Telegram/SourceFiles/core/runtime_composer.h @@ -0,0 +1,257 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +class RuntimeComposer; +typedef void(*RuntimeComponentConstruct)(void *location, RuntimeComposer *composer); +typedef void(*RuntimeComponentDestruct)(void *location); +typedef void(*RuntimeComponentMove)(void *location, void *waslocation); + +struct RuntimeComponentWrapStruct { + // don't init any fields, because it is only created in + // global scope, so it will be filled by zeros from the start + RuntimeComponentWrapStruct() = default; + RuntimeComponentWrapStruct(std::size_t size, std::size_t align, RuntimeComponentConstruct construct, RuntimeComponentDestruct destruct, RuntimeComponentMove move) + : Size(size) + , Align(align) + , Construct(construct) + , Destruct(destruct) + , Move(move) { + } + std::size_t Size; + std::size_t Align; + RuntimeComponentConstruct Construct; + RuntimeComponentDestruct Destruct; + RuntimeComponentMove Move; +}; + +template <int Value, int Denominator> +struct CeilDivideMinimumOne { + static constexpr int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0)); +}; + +extern RuntimeComponentWrapStruct RuntimeComponentWraps[64]; +extern QAtomicInt RuntimeComponentIndexLast; + +template <typename Type> +struct RuntimeComponent { + RuntimeComponent() { + static_assert(alignof(Type) <= alignof(SmallestSizeType), "Components should align to a pointer!"); + } + RuntimeComponent(const RuntimeComponent &other) = delete; + RuntimeComponent &operator=(const RuntimeComponent &other) = delete; + RuntimeComponent(RuntimeComponent &&other) = delete; + RuntimeComponent &operator=(RuntimeComponent &&other) = default; + + static int Index() { + static QAtomicInt _index(0); + if (int index = _index.loadAcquire()) { + return index - 1; + } + while (true) { + int last = RuntimeComponentIndexLast.loadAcquire(); + if (RuntimeComponentIndexLast.testAndSetOrdered(last, last + 1)) { + t_assert(last < 64); + if (_index.testAndSetOrdered(0, last + 1)) { + RuntimeComponentWraps[last] = RuntimeComponentWrapStruct( + CeilDivideMinimumOne<sizeof(Type), sizeof(SmallestSizeType)>::Result * sizeof(SmallestSizeType), + alignof(Type), + Type::RuntimeComponentConstruct, + Type::RuntimeComponentDestruct, + Type::RuntimeComponentMove); + } + break; + } + } + return _index.loadAcquire() - 1; + } + static uint64 Bit() { + return (1ULL << Index()); + } + +protected: + using SmallestSizeType = void*; + + static void RuntimeComponentConstruct(void *location, RuntimeComposer *composer) { + new (location) Type(); + } + static void RuntimeComponentDestruct(void *location) { + ((Type*)location)->~Type(); + } + static void RuntimeComponentMove(void *location, void *waslocation) { + *(Type*)location = std_::move(*(Type*)waslocation); + } + +}; + +class RuntimeComposerMetadata { +public: + RuntimeComposerMetadata(uint64 mask) : size(0), last(64), _mask(mask) { + for (int i = 0; i < 64; ++i) { + uint64 m = (1ULL << i); + if (_mask & m) { + int s = RuntimeComponentWraps[i].Size; + if (s) { + offsets[i] = size; + size += s; + } else { + offsets[i] = -1; + } + } else if (_mask < m) { + last = i; + for (; i < 64; ++i) { + offsets[i] = -1; + } + } else { + offsets[i] = -1; + } + } + } + + int size, last; + int offsets[64]; + + bool equals(uint64 mask) const { + return _mask == mask; + } + uint64 maskadd(uint64 mask) const { + return _mask | mask; + } + uint64 maskremove(uint64 mask) const { + return _mask & (~mask); + } + +private: + uint64 _mask; + +}; + +const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask); + +class RuntimeComposer { +public: + RuntimeComposer(uint64 mask = 0) : _data(zerodata()) { + if (mask) { + const RuntimeComposerMetadata *meta = GetRuntimeComposerMetadata(mask); + int size = sizeof(meta) + meta->size; + + auto data = operator new(size); + t_assert(data != nullptr); + + _data = data; + _meta() = meta; + for (int i = 0; i < meta->last; ++i) { + int offset = meta->offsets[i]; + if (offset >= 0) { + try { + auto constructAt = _dataptrunsafe(offset); + auto space = RuntimeComponentWraps[i].Size; + auto alignedAt = std_::align(RuntimeComponentWraps[i].Align, space, constructAt, space); + t_assert(alignedAt == constructAt); + RuntimeComponentWraps[i].Construct(constructAt, this); + } catch (...) { + while (i > 0) { + --i; + offset = meta->offsets[--i]; + if (offset >= 0) { + RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset)); + } + } + throw; + } + } + } + } + } + RuntimeComposer(const RuntimeComposer &other) = delete; + RuntimeComposer &operator=(const RuntimeComposer &other) = delete; + ~RuntimeComposer() { + if (_data != zerodata()) { + auto meta = _meta(); + for (int i = 0; i < meta->last; ++i) { + int offset = meta->offsets[i]; + if (offset >= 0) { + RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset)); + } + } + operator delete(_data); + } + } + + template <typename Type> + bool Has() const { + return (_meta()->offsets[Type::Index()] >= 0); + } + + template <typename Type> + Type *Get() { + return static_cast<Type*>(_dataptr(_meta()->offsets[Type::Index()])); + } + template <typename Type> + const Type *Get() const { + return static_cast<const Type*>(_dataptr(_meta()->offsets[Type::Index()])); + } + +protected: + void UpdateComponents(uint64 mask = 0) { + if (!_meta()->equals(mask)) { + RuntimeComposer tmp(mask); + tmp.swap(*this); + if (_data != zerodata() && tmp._data != zerodata()) { + auto meta = _meta(), wasmeta = tmp._meta(); + for (int i = 0; i < meta->last; ++i) { + int offset = meta->offsets[i], wasoffset = wasmeta->offsets[i]; + if (offset >= 0 && wasoffset >= 0) { + RuntimeComponentWraps[i].Move(_dataptrunsafe(offset), tmp._dataptrunsafe(wasoffset)); + } + } + } + } + } + void AddComponents(uint64 mask = 0) { + UpdateComponents(_meta()->maskadd(mask)); + } + void RemoveComponents(uint64 mask = 0) { + UpdateComponents(_meta()->maskremove(mask)); + } + +private: + static const RuntimeComposerMetadata *ZeroRuntimeComposerMetadata; + static void *zerodata() { + return &ZeroRuntimeComposerMetadata; + } + + void *_dataptrunsafe(int skip) const { + return (char*)_data + sizeof(_meta()) + skip; + } + void *_dataptr(int skip) const { + return (skip >= 0) ? _dataptrunsafe(skip) : 0; + } + const RuntimeComposerMetadata *&_meta() const { + return *static_cast<const RuntimeComposerMetadata**>(_data); + } + void *_data; + + void swap(RuntimeComposer &other) { + std::swap(_data, other._data); + } + +}; diff --git a/Telegram/SourceFiles/core/stl_subset.h b/Telegram/SourceFiles/core/stl_subset.h new file mode 100644 index 000000000..477614850 --- /dev/null +++ b/Telegram/SourceFiles/core/stl_subset.h @@ -0,0 +1,276 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +// 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_ { + +using nullptr_t = decltype(nullptr); + +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 { + using type = T; +}; +template <typename T> +struct remove_reference<T&> { + using type = T; +}; +template <typename T> +struct remove_reference<T&&> { + using type = T; +}; + +template <typename T> +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); +} + +template <typename T> +void swap(T &a, T &b) { + T tmp = move(a); + a = move(b); + b = move(tmp); +} + +template <typename T> +struct remove_const { + using type = T; +}; + +template <typename T> +struct remove_const<const T> { + using type = T; +}; + +template <typename T> +struct remove_volatile { + using type = T; +}; + +template <typename T> +struct remove_volatile<volatile T> { + using type = T; +}; + +template <typename T> +using decay_simple_t = typename remove_const<typename remove_volatile<typename remove_reference<T>::type>::type>::type; + +template <typename T1, typename T2> +struct is_same : false_type { +}; + +template <typename T> +struct is_same<T, T> : true_type { +}; + +template <bool, typename T = void> +struct enable_if { +}; + +template <typename T> +struct enable_if<true, T> { + using type = T; +}; + +template <bool Test, typename T = void> +using enable_if_t = typename enable_if<Test, T>::type; + +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; + +// This is not full unique_ptr, but at least with std interface. +template <typename T> +class unique_ptr { +public: + constexpr unique_ptr() noexcept = default; + unique_ptr(const unique_ptr<T> &) = delete; + unique_ptr<T> &operator=(const unique_ptr<T> &) = delete; + + constexpr unique_ptr(std_::nullptr_t) { + } + unique_ptr<T> &operator=(std_::nullptr_t) noexcept { + reset(); + return (*this); + } + + explicit unique_ptr(T *p) noexcept : _p(p) { + } + + template <typename U> + unique_ptr(unique_ptr<U> &&other) noexcept : _p(other.release()) { + } + template <typename U> + unique_ptr<T> &operator=(unique_ptr<U> &&other) noexcept { + reset(other.release()); + return (*this); + } + unique_ptr<T> &operator=(unique_ptr<T> &&other) noexcept { + if (this != &other) { + reset(other.release()); + } + return (*this); + } + + void swap(unique_ptr<T> &other) noexcept { + std::swap(_p, other._p); + } + ~unique_ptr() noexcept { + delete _p; + } + + T &operator*() const { + return (*get()); + } + T *operator->() const noexcept { + return get(); + } + T *get() const noexcept { + return _p; + } + explicit operator bool() const noexcept { + return get() != nullptr; + } + + T *release() noexcept { + return getPointerAndReset(_p); + } + + void reset(T *p = nullptr) noexcept { + T *old = _p; + _p = p; + if (old) { + delete old; + } + } + +private: + T *_p = nullptr; + +}; + +template <typename T, typename... Args> +inline unique_ptr<T> make_unique(Args&&... args) { + return unique_ptr<T>(new T(forward<Args>(args)...)); +} + +template <typename T> +inline bool operator==(const unique_ptr<T> &a, std_::nullptr_t) noexcept { + return !a; +} +template <typename T> +inline bool operator==(std_::nullptr_t, const unique_ptr<T> &b) noexcept { + return !b; +} +template <typename T> +inline bool operator!=(const unique_ptr<T> &a, std_::nullptr_t b) noexcept { + return !(a == b); +} +template <typename T> +inline bool operator!=(std_::nullptr_t a, const unique_ptr<T> &b) noexcept { + return !(a == b); +} + +using _yes = char(&)[1]; +using _no = char(&)[2]; + +template <typename Base, typename Derived> +struct _host { + operator Base*() const; + operator Derived*(); +}; + +template <typename Base, typename Derived> +struct is_base_of { + template <typename T> + static _yes check(Derived*, T); + static _no check(Base*, int); + + static constexpr bool value = sizeof(check(_host<Base, Derived>(), int())) == sizeof(_yes); +}; + +#ifndef OS_MAC_OLD +inline void *align(size_t alignment, size_t size, void*& ptr, size_t& space) noexcept { + auto p = reinterpret_cast<std::uintptr_t>(ptr); + auto a = (p - 1u + alignment) & -alignment; + auto d = a - p; + if ((size + d) > space) { + return nullptr; + } + space -= d; + return ptr = reinterpret_cast<void*>(a); +} +#endif // OS_MAC_OLD + +} // namespace std_ diff --git a/Telegram/SourceFiles/core/basic_types.cpp b/Telegram/SourceFiles/core/utils.cpp similarity index 97% rename from Telegram/SourceFiles/core/basic_types.cpp rename to Telegram/SourceFiles/core/utils.cpp index 868a5d23f..4ad8140ab 100644 --- a/Telegram/SourceFiles/core/basic_types.cpp +++ b/Telegram/SourceFiles/core/utils.cpp @@ -19,8 +19,7 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #include "stdafx.h" - -#include "basic_types.h" +#include "core/utils.h" #include <openssl/crypto.h> #include <openssl/sha.h> @@ -1020,33 +1019,3 @@ MimeType mimeTypeForData(const QByteArray &data) { } return MimeType(QMimeDatabase().mimeTypeForData(data)); } - -struct ComposerMetadatasMap { - QMap<uint64, ComposerMetadata*> data; - ~ComposerMetadatasMap() { - for_const (const ComposerMetadata *p, data) { - delete p; - } - } -}; - -const ComposerMetadata *GetComposerMetadata(uint64 mask) { - static ComposerMetadatasMap ComposerMetadatas; - static QMutex ComposerMetadatasMutex; - - QMutexLocker lock(&ComposerMetadatasMutex); - auto i = ComposerMetadatas.data.constFind(mask); - if (i == ComposerMetadatas.data.cend()) { - ComposerMetadata *meta = new ComposerMetadata(mask); - t_assert(meta != nullptr); - - i = ComposerMetadatas.data.insert(mask, meta); - } - return i.value(); -} - -const ComposerMetadata *Composer::ZeroComposerMetadata = GetComposerMetadata(0); - -ComponentWrapStruct ComponentWraps[64]; - -QAtomicInt ComponentIndexLast; diff --git a/Telegram/SourceFiles/core/utils.h b/Telegram/SourceFiles/core/utils.h new file mode 100644 index 000000000..df4c23af3 --- /dev/null +++ b/Telegram/SourceFiles/core/utils.h @@ -0,0 +1,581 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "core/basic_types.h" + +template <typename T, size_t N> +inline constexpr size_t arraysize(T(&ArrahSizeHelper)[N]) { + return N; +} + +template <typename T> +void deleteAndMark(T *&link) { + delete link; + link = reinterpret_cast<T*>(0x00000BAD); +} + +template <typename T> +T *getPointerAndReset(T *&ptr) { + T *result = nullptr; + qSwap(result, ptr); + return result; +} + +template <typename Enum> +inline QFlags<Enum> qFlags(Enum v) { + return QFlags<Enum>(v); +} + +static const int32 ScrollMax = INT_MAX; + +extern uint64 _SharedMemoryLocation[]; +template <typename T, unsigned int N> +T *SharedMemoryLocation() { + static_assert(N < 4, "Only 4 shared memory locations!"); + return reinterpret_cast<T*>(_SharedMemoryLocation + N); +} + +// see https://github.com/boostcon/cppnow_presentations_2012/blob/master/wed/schurr_cpp11_tools_for_class_authors.pdf +class str_const { // constexpr string +public: + template<std::size_t N> + constexpr str_const(const char(&a)[N]) : _str(a), _size(N - 1) { + } + constexpr char operator[](std::size_t n) const { + return (n < _size) ? _str[n] : +#ifndef OS_MAC_OLD + throw std::out_of_range(""); +#else // OS_MAC_OLD + throw std::exception(); +#endif // OS_MAC_OLD + } + constexpr std::size_t size() const { return _size; } + const char *c_str() const { return _str; } + +private: + const char* const _str; + const std::size_t _size; + +}; + +inline QString str_const_toString(const str_const &str) { + return QString::fromUtf8(str.c_str(), str.size()); +} + +template <typename T> +inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; } + +template <typename T> +inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; } + +template <typename T> +T createAndSwap(T &value) { + T result = T(); + std_::swap(result, value); + return std_::move(result); +} + +static volatile int *t_assert_nullptr = nullptr; +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::setCrashAnnotation("Assertion", info); + *t_assert_nullptr = 0; +} +#define t_assert_full(condition, message, file, line) ((!(condition)) ? t_assert_fail(message, file, line) : t_noop()) +#define t_assert_c(condition, comment) t_assert_full(condition, "\"" #condition "\" (" comment ")", __FILE__, __LINE__) +#define t_assert(condition) t_assert_full(condition, "\"" #condition "\"", __FILE__, __LINE__) + +class Exception : public std::exception { +public: + + Exception(const QString &msg, bool isFatal = true) : _fatal(isFatal), _msg(msg.toUtf8()) { + LOG(("Exception: %1").arg(msg)); + } + bool fatal() const { + return _fatal; + } + + virtual const char *what() const throw() { + return _msg.constData(); + } + virtual ~Exception() throw() { + } + +private: + bool _fatal; + QByteArray _msg; +}; + +class MTPint; +using TimeId = int32; +TimeId myunixtime(); +void unixtimeInit(); +void unixtimeSet(TimeId servertime, bool force = false); +TimeId unixtime(); +TimeId fromServerTime(const MTPint &serverTime); +void toServerTime(const TimeId &clientTime, MTPint &outServerTime); +uint64 msgid(); +int32 reqid(); + +inline QDateTime date(int32 time = -1) { + QDateTime result; + if (time >= 0) result.setTime_t(time); + return result; +} + +inline QDateTime dateFromServerTime(const MTPint &time) { + return date(fromServerTime(time)); +} + +inline QDateTime date(const MTPint &time) { + return dateFromServerTime(time); +} + +QDateTime dateFromServerTime(TimeId time); + +inline void mylocaltime(struct tm * _Tm, const time_t * _Time) { +#ifdef Q_OS_WIN + localtime_s(_Tm, _Time); +#else + localtime_r(_Time, _Tm); +#endif +} + +namespace ThirdParty { + +void start(); +void finish(); + +} + +bool checkms(); // returns true if time has changed +uint64 getms(bool checked = false); + +class SingleTimer : public QTimer { // single shot timer with check + Q_OBJECT + +public: + + SingleTimer(); + + void setSingleShot(bool); // is not available + void start(); // is not available + + public slots: + + void start(int msec); + void startIfNotActive(int msec); + void adjust() { + uint64 n = getms(true); + if (isActive()) { + if (n >= _finishing) { + start(0); + } else { + start(_finishing - n); + } + } + } + +private: + uint64 _finishing; + bool _inited; + +}; + +const static uint32 _md5_block_size = 64; +class HashMd5 { +public: + + HashMd5(const void *input = 0, uint32 length = 0); + void feed(const void *input, uint32 length); + int32 *result(); + +private: + + void init(); + void finalize(); + void transform(const uchar *block); + + bool _finalized; + uchar _buffer[_md5_block_size]; + uint32 _count[2]; + uint32 _state[4]; + uchar _digest[16]; + +}; + +int32 hashCrc32(const void *data, uint32 len); +int32 *hashSha1(const void *data, uint32 len, void *dest); // dest - ptr to 20 bytes, returns (int32*)dest +int32 *hashSha256(const void *data, uint32 len, void *dest); // dest - ptr to 32 bytes, returns (int32*)dest +int32 *hashMd5(const void *data, uint32 len, void *dest); // dest = ptr to 16 bytes, returns (int32*)dest +char *hashMd5Hex(const int32 *hashmd5, void *dest); // dest = ptr to 32 bytes, returns (char*)dest +inline char *hashMd5Hex(const void *data, uint32 len, void *dest) { // dest = ptr to 32 bytes, returns (char*)dest + return hashMd5Hex(HashMd5(data, len).result(), dest); +} + +// good random (using openssl implementation) +void memset_rand(void *data, uint32 len); +template <typename T> +T rand_value() { + T result; + memset_rand(&result, sizeof(result)); + return result; +} + +inline void memset_rand_bad(void *data, uint32 len) { + for (uchar *i = reinterpret_cast<uchar*>(data), *e = i + len; i != e; ++i) { + *i = uchar(rand() & 0xFF); + } +} + +template <typename T> +inline void memsetrnd_bad(T &value) { + memset_rand_bad(&value, sizeof(value)); +} + +class ReadLockerAttempt { +public: + + ReadLockerAttempt(QReadWriteLock *_lock) : success(_lock->tryLockForRead()), lock(_lock) { + } + ~ReadLockerAttempt() { + if (success) { + lock->unlock(); + } + } + + operator bool() const { + return success; + } + +private: + + bool success; + QReadWriteLock *lock; + +}; + +inline QString fromUtf8Safe(const char *str, int32 size = -1) { + if (!str || !size) return QString(); + if (size < 0) size = int32(strlen(str)); + QString result(QString::fromUtf8(str, size)); + QByteArray back = result.toUtf8(); + if (back.size() != size || memcmp(back.constData(), str, size)) return QString::fromLocal8Bit(str, size); + return result; +} + +inline QString fromUtf8Safe(const QByteArray &str) { + return fromUtf8Safe(str.constData(), str.size()); +} + +static const QRegularExpression::PatternOptions reMultiline(QRegularExpression::DotMatchesEverythingOption | QRegularExpression::MultilineOption); + +template <typename T> +inline T snap(const T &v, const T &_min, const T &_max) { + return (v < _min) ? _min : ((v > _max) ? _max : v); +} + +template <typename T> +class ManagedPtr { +public: + ManagedPtr() : ptr(0) { + } + ManagedPtr(T *p) : ptr(p) { + } + T *operator->() const { + return ptr; + } + T *v() const { + return ptr; + } + +protected: + + T *ptr; + typedef ManagedPtr<T> Parent; +}; + +QString translitRusEng(const QString &rus); +QString rusKeyboardLayoutSwitch(const QString &from); + +enum DBISendKey { + dbiskEnter = 0, + dbiskCtrlEnter = 1, +}; + +enum DBINotifyView { + dbinvShowPreview = 0, + dbinvShowName = 1, + dbinvShowNothing = 2, +}; + +enum DBIWorkMode { + dbiwmWindowAndTray = 0, + dbiwmTrayOnly = 1, + dbiwmWindowOnly = 2, +}; + +enum DBIConnectionType { + dbictAuto = 0, + dbictHttpAuto = 1, // not used + dbictHttpProxy = 2, + dbictTcpProxy = 3, +}; + +enum DBIDefaultAttach { + dbidaDocument = 0, + dbidaPhoto = 1, +}; + +struct ProxyData { + QString host; + uint32 port = 0; + QString user, password; +}; + +enum DBIScale { + dbisAuto = 0, + dbisOne = 1, + dbisOneAndQuarter = 2, + dbisOneAndHalf = 3, + dbisTwo = 4, + + dbisScaleCount = 5, +}; + +static const int MatrixRowShift = 40000; + +enum DBIEmojiTab { + dbietRecent = -1, + dbietPeople = 0, + dbietNature = 1, + dbietFood = 2, + dbietActivity = 3, + dbietTravel = 4, + dbietObjects = 5, + dbietSymbols = 6, + dbietStickers = 666, +}; +static const int emojiTabCount = 8; +inline DBIEmojiTab emojiTabAtIndex(int index) { + return (index < 0 || index >= emojiTabCount) ? dbietRecent : DBIEmojiTab(index - 1); +} + +enum DBIPlatform { + dbipWindows = 0, + dbipMac = 1, + dbipLinux64 = 2, + dbipLinux32 = 3, + dbipMacOld = 4, +}; + +enum DBIPeerReportSpamStatus { + dbiprsNoButton = 0, // hidden, but not in the cloud settings yet + dbiprsUnknown = 1, // contacts not loaded yet + dbiprsShowButton = 2, // show report spam button, each show peer request setting from cloud + dbiprsReportSent = 3, // report sent, but the report spam panel is not hidden yet + dbiprsHidden = 4, // hidden in the cloud or not needed (bots, contacts, etc), no more requests + dbiprsRequesting = 5, // requesting the cloud setting right now +}; + +inline QString strMakeFromLetters(const uint32 *letters, int32 len) { + QString result; + result.reserve(len); + for (int32 i = 0; i < len; ++i) { + result.push_back(QChar((((letters[i] >> 16) & 0xFF) << 8) | (letters[i] & 0xFF))); + } + return result; +} + +class MimeType { +public: + + enum TypeEnum { + Unknown, + WebP, + }; + + MimeType(const QMimeType &type) : _typeStruct(type), _type(Unknown) { + } + MimeType(TypeEnum type) : _type(type) { + } + QStringList globPatterns() const; + QString filterString() const; + QString name() const; + +private: + + QMimeType _typeStruct; + TypeEnum _type; + +}; + +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; +} +inline int floorclamp(int value, int step, int lowest, int highest) { + return qMin(qMax(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 int ceilclamp(int value, int step, int lowest, int highest) { + return qMax(qMin((value + step - 1) / 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 { + ForwardSelectedMessages, + ForwardContextMessage, + ForwardPressedMessage, + ForwardPressedLinkMessage +}; + +enum ShowLayerOption { + CloseOtherLayers = 0x00, + KeepOtherLayers = 0x01, + ShowAfterOtherLayers = 0x03, + + AnimatedShowLayer = 0x00, + ForceFastShowLayer = 0x04, +}; +Q_DECLARE_FLAGS(ShowLayerOptions, ShowLayerOption); +Q_DECLARE_OPERATORS_FOR_FLAGS(ShowLayerOptions); + +static int32 FullArcLength = 360 * 16; +static int32 QuarterArcLength = (FullArcLength / 4); +static int32 MinArcLength = (FullArcLength / 360); +static int32 AlmostFullArcLength = (FullArcLength - MinArcLength); + +template <typename T, typename... Args> +inline QSharedPointer<T> MakeShared(Args&&... args) { + return QSharedPointer<T>(new T(std_::forward<Args>(args)...)); +} + +// This pointer is used for global non-POD variables that are allocated +// on demand by createIfNull(lambda) and are never automatically freed. +template <typename T> +class NeverFreedPointer { +public: + NeverFreedPointer() = default; + NeverFreedPointer(const NeverFreedPointer<T> &other) = delete; + NeverFreedPointer &operator=(const NeverFreedPointer<T> &other) = delete; + + template <typename U> + void createIfNull(U creator) { + if (isNull()) { + reset(creator()); + } + } + + template <typename... Args> + void makeIfNull(Args&&... args) { + if (isNull()) { + reset(new T(std_::forward<Args>(args)...)); + } + }; + + T *data() const { + return _p; + } + T *release() { + return getPointerAndReset(_p); + } + void reset(T *p = nullptr) { + delete _p; + _p = 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(); + } + +private: + T *_p; + +}; + +// This pointer is used for static non-POD variables that are allocated +// on first use by constructor and are never automatically freed. +template <typename T> +class StaticNeverFreedPointer { +public: + explicit StaticNeverFreedPointer(T *p) : _p(p) { + } + StaticNeverFreedPointer(const StaticNeverFreedPointer<T> &other) = delete; + StaticNeverFreedPointer &operator=(const StaticNeverFreedPointer<T> &other) = delete; + + T *data() const { + return _p; + } + T *release() { + return getPointerAndReset(_p); + } + void reset(T *p = nullptr) { + delete _p; + _p = 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(); + } + +private: + T *_p = nullptr; + +}; diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index 428f16a51..ec66d04e0 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -#include "core/basic_types.h" +#include "core/utils.h" #define BETA_VERSION_MACRO (10008002ULL) diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 5a2f73667..7faf04fb4 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -945,7 +945,7 @@ bool History::addToOverview(MediaOverviewType type, MsgId msgId, AddToOverviewMe } if (!adding) return false; - overviewIds[type].insert(msgId, NullType()); + overviewIds[type].insert(msgId); switch (method) { case AddToOverviewNew: case AddToOverviewBack: overview[type].push_back(msgId); break; @@ -963,11 +963,11 @@ bool History::addToOverview(MediaOverviewType type, MsgId msgId, AddToOverviewMe void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) { if (overviewIds[type].isEmpty()) return; - History::MediaOverviewIds::iterator i = overviewIds[type].find(msgId); + auto i = overviewIds[type].find(msgId); if (i == overviewIds[type].cend()) return; overviewIds[type].erase(i); - for (History::MediaOverview::iterator i = overview[type].begin(), e = overview[type].end(); i != e; ++i) { + for (auto i = overview[type].begin(), e = overview[type].end(); i != e; ++i) { if ((*i) == msgId) { overview[type].erase(i); if (overviewCountData[type] > 0) { @@ -2011,8 +2011,8 @@ void History::overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages if (!onlyCounts && v->isEmpty()) { overviewCountData[overviewIndex] = 0; } else if (overviewCountData[overviewIndex] > 0) { - for (History::MediaOverviewIds::const_iterator i = overviewIds[overviewIndex].cbegin(), e = overviewIds[overviewIndex].cend(); i != e; ++i) { - if (i.key() < 0) { + for_const (auto msgId, overviewIds[overviewIndex]) { + if (msgId < 0) { ++overviewCountData[overviewIndex]; } else { break; @@ -2023,7 +2023,7 @@ void History::overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages for (QVector<MTPMessage>::const_iterator i = v->cbegin(), e = v->cend(); i != e; ++i) { HistoryItem *item = App::histories().addNewMessage(*i, NewMessageExisting); if (item && overviewIds[overviewIndex].constFind(item->id) == overviewIds[overviewIndex].cend()) { - overviewIds[overviewIndex].insert(item->id, NullType()); + overviewIds[overviewIndex].insert(item->id); overview[overviewIndex].push_front(item->id); } } @@ -2031,12 +2031,12 @@ void History::overviewSliceDone(int32 overviewIndex, const MTPmessages_Messages void History::changeMsgId(MsgId oldId, MsgId newId) { for (int32 i = 0; i < OverviewCount; ++i) { - History::MediaOverviewIds::iterator j = overviewIds[i].find(oldId); + auto j = overviewIds[i].find(oldId); if (j != overviewIds[i].cend()) { overviewIds[i].erase(j); int32 index = overview[i].indexOf(oldId); if (overviewIds[i].constFind(newId) == overviewIds[i].cend()) { - overviewIds[i].insert(newId, NullType()); + overviewIds[i].insert(newId); if (index >= 0) { overview[i][index] = newId; } else { diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index c9d44ebfb..db8cefa65 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -431,9 +431,9 @@ public: return result; } MsgId overviewMinId(int32 overviewIndex) const { - for (MediaOverviewIds::const_iterator i = overviewIds[overviewIndex].cbegin(), e = overviewIds[overviewIndex].cend(); i != e; ++i) { - if (i.key() > 0) { - return i.key(); + for_const (auto msgId, overviewIds[overviewIndex]) { + if (msgId > 0) { + return msgId; } } return 0; @@ -525,7 +525,7 @@ private: } uint64 _sortKeyInChatList = 0; // like ((unixtime) << 32) | (incremented counter) - typedef QMap<MsgId, NullType> MediaOverviewIds; + using MediaOverviewIds = OrderedSet<MsgId>; MediaOverviewIds overviewIds[OverviewCount]; int32 overviewCountData[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 008eb9b13..3be1f8665 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -20,6 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "core/runtime_composer.h" + class HistoryElement { public: HistoryElement() = default; @@ -95,7 +97,7 @@ enum HistoryItemType { HistoryItemJoined }; -struct HistoryMessageVia : public BaseComponent<HistoryMessageVia> { +struct HistoryMessageVia : public RuntimeComponent<HistoryMessageVia> { void create(int32 userId); void resize(int32 availw) const; @@ -106,20 +108,20 @@ struct HistoryMessageVia : public BaseComponent<HistoryMessageVia> { ClickHandlerPtr _lnk; }; -struct HistoryMessageViews : public BaseComponent<HistoryMessageViews> { +struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews> { QString _viewsText; int _views = 0; int _viewsWidth = 0; }; -struct HistoryMessageSigned : public BaseComponent<HistoryMessageSigned> { +struct HistoryMessageSigned : public RuntimeComponent<HistoryMessageSigned> { void create(UserData *from, const QDateTime &date); int maxWidth() const; Text _signature; }; -struct HistoryMessageEdited : public BaseComponent<HistoryMessageEdited> { +struct HistoryMessageEdited : public RuntimeComponent<HistoryMessageEdited> { void create(const QDateTime &editDate, const QDateTime &date); int maxWidth() const; @@ -127,7 +129,7 @@ struct HistoryMessageEdited : public BaseComponent<HistoryMessageEdited> { Text _edited; }; -struct HistoryMessageForwarded : public BaseComponent<HistoryMessageForwarded> { +struct HistoryMessageForwarded : public RuntimeComponent<HistoryMessageForwarded> { void create(const HistoryMessageVia *via) const; PeerData *_authorOriginal = nullptr; @@ -136,7 +138,7 @@ struct HistoryMessageForwarded : public BaseComponent<HistoryMessageForwarded> { mutable Text _text = { 1 }; }; -struct HistoryMessageReply : public BaseComponent<HistoryMessageReply> { +struct HistoryMessageReply : public RuntimeComponent<HistoryMessageReply> { HistoryMessageReply &operator=(HistoryMessageReply &&other) { replyToMsgId = other.replyToMsgId; std::swap(replyToMsg, other.replyToMsg); @@ -191,7 +193,7 @@ struct HistoryMessageReply : public BaseComponent<HistoryMessageReply> { Q_DECLARE_OPERATORS_FOR_FLAGS(HistoryMessageReply::PaintFlags); class ReplyKeyboard; -struct HistoryMessageReplyMarkup : public BaseComponent<HistoryMessageReplyMarkup> { +struct HistoryMessageReplyMarkup : public RuntimeComponent<HistoryMessageReplyMarkup> { HistoryMessageReplyMarkup() = default; HistoryMessageReplyMarkup(MTPDreplyKeyboardMarkup::Flags f) : flags(f) { } @@ -362,7 +364,7 @@ private: // any HistoryItem can have this Interface for // displaying the day mark above the message -struct HistoryMessageDate : public BaseComponent<HistoryMessageDate> { +struct HistoryMessageDate : public RuntimeComponent<HistoryMessageDate> { void init(const QDateTime &date); int height() const; @@ -374,7 +376,7 @@ struct HistoryMessageDate : public BaseComponent<HistoryMessageDate> { // any HistoryItem can have this Interface for // displaying the unread messages bar above the message -struct HistoryMessageUnreadBar : public BaseComponent<HistoryMessageUnreadBar> { +struct HistoryMessageUnreadBar : public RuntimeComponent<HistoryMessageUnreadBar> { void init(int count); static int height(); @@ -439,7 +441,7 @@ namespace internal { } // namespace internal -class HistoryItem : public HistoryElement, public Composer, public ClickHandlerHost { +class HistoryItem : public HistoryElement, public RuntimeComposer, public ClickHandlerHost { public: int resizeGetHeight(int width) { if (_flags & MTPDmessage_ClientFlag::f_pending_init_dimensions) { diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index 10c39c546..35f5114b3 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -527,13 +527,13 @@ void HistoryPhoto::updateSentMedia(const MTPMessageMedia &media) { const MTPFileLocation *loc = 0; switch (sizes.at(i).type()) { case mtpc_photoSize: { - const string &s(sizes.at(i).c_photoSize().vtype.c_string().v); + auto &s = sizes.at(i).c_photoSize().vtype.c_string().v; loc = &sizes.at(i).c_photoSize().vlocation; if (s.size()) size = s[0]; } break; case mtpc_photoCachedSize: { - const string &s(sizes.at(i).c_photoCachedSize().vtype.c_string().v); + auto &s = sizes.at(i).c_photoCachedSize().vtype.c_string().v; loc = &sizes.at(i).c_photoCachedSize().vlocation; if (s.size()) size = s[0]; } break; @@ -942,7 +942,7 @@ HistoryDocument::HistoryDocument(HistoryItem *parent, DocumentData *document, co } HistoryDocument::HistoryDocument(HistoryItem *parent, const HistoryDocument &other) : HistoryFileMedia(parent) -, Composer() +, RuntimeComposer() , _data(other._data) { auto captioned = other.Get<HistoryDocumentCaptioned>(); createComponents(captioned != 0); diff --git a/Telegram/SourceFiles/history/history_media_types.h b/Telegram/SourceFiles/history/history_media_types.h index 1dec2c746..341f278b6 100644 --- a/Telegram/SourceFiles/history/history_media_types.h +++ b/Telegram/SourceFiles/history/history_media_types.h @@ -278,17 +278,17 @@ private: }; -struct HistoryDocumentThumbed : public BaseComponent<HistoryDocumentThumbed> { +struct HistoryDocumentThumbed : public RuntimeComponent<HistoryDocumentThumbed> { ClickHandlerPtr _linksavel, _linkcancell; int _thumbw = 0; mutable int _linkw = 0; mutable QString _link; }; -struct HistoryDocumentCaptioned : public BaseComponent<HistoryDocumentCaptioned> { +struct HistoryDocumentCaptioned : public RuntimeComponent<HistoryDocumentCaptioned> { Text _caption = { int(st::msgFileMinWidth) - st::msgPadding.left() - st::msgPadding.right() }; }; -struct HistoryDocumentNamed : public BaseComponent<HistoryDocumentNamed> { +struct HistoryDocumentNamed : public RuntimeComponent<HistoryDocumentNamed> { QString _name; int _namew = 0; }; @@ -300,7 +300,7 @@ struct HistoryDocumentVoicePlayback { anim::fvalue a_progress; Animation _a_progress; }; -struct HistoryDocumentVoice : public BaseComponent<HistoryDocumentVoice> { +struct HistoryDocumentVoice : public RuntimeComponent<HistoryDocumentVoice> { HistoryDocumentVoice &operator=(HistoryDocumentVoice &&other) { std::swap(_playback, other._playback); return *this; @@ -313,7 +313,7 @@ struct HistoryDocumentVoice : public BaseComponent<HistoryDocumentVoice> { mutable HistoryDocumentVoicePlayback *_playback = nullptr; }; -class HistoryDocument : public HistoryFileMedia, public Composer { +class HistoryDocument : public HistoryFileMedia, public RuntimeComposer { public: HistoryDocument(HistoryItem *parent, DocumentData *document, const QString &caption); HistoryDocument(HistoryItem *parent, const HistoryDocument &other); diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index bfefaec4c..061420f38 100644 --- a/Telegram/SourceFiles/history/history_message.h +++ b/Telegram/SourceFiles/history/history_message.h @@ -252,10 +252,10 @@ struct HistoryServiceDependentData { ClickHandlerPtr lnk; }; -struct HistoryServicePinned : public BaseComponent<HistoryServicePinned>, public HistoryServiceDependentData { +struct HistoryServicePinned : public RuntimeComponent<HistoryServicePinned>, public HistoryServiceDependentData { }; -struct HistoryServiceGameScore : public BaseComponent<HistoryServiceGameScore>, public HistoryServiceDependentData { +struct HistoryServiceGameScore : public RuntimeComponent<HistoryServiceGameScore>, public HistoryServiceDependentData { int score = 0; }; diff --git a/Telegram/SourceFiles/intro/introsignup.cpp b/Telegram/SourceFiles/intro/introsignup.cpp index 923090a84..74034244f 100644 --- a/Telegram/SourceFiles/intro/introsignup.cpp +++ b/Telegram/SourceFiles/intro/introsignup.cpp @@ -96,7 +96,7 @@ void IntroSignup::mousePressEvent(QMouseEvent *e) { void IntroSignup::paintEvent(QPaintEvent *e) { bool trivial = (rect() == e->rect()); - QPainter p(this); + Painter p(this); if (!trivial) { p.setClipRect(e->rect()); } @@ -123,20 +123,22 @@ void IntroSignup::paintEvent(QPaintEvent *e) { } if (_photoSmall.isNull()) { - if (a_photoOver.current() < 1) { - QRect pix(st::setPhotoImg.rect()); - pix.moveTo(pix.x() + (pix.width() - (st::introPhotoSize * cIntRetinaFactor())) / 2, pix.y() + (pix.height() - (st::introPhotoSize * cIntRetinaFactor())) / 2); - pix.setSize(QSize(st::introPhotoSize * cIntRetinaFactor(), st::introPhotoSize * cIntRetinaFactor())); - p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), pix); - } - if (a_photoOver.current() > 0) { - QRect pix(st::setOverPhotoImg.rect()); - pix.moveTo(pix.x() + (pix.width() - (st::introPhotoSize * cIntRetinaFactor())) / 2, pix.y() + (pix.height() - (st::introPhotoSize * cIntRetinaFactor())) / 2); - pix.setSize(QSize(st::introPhotoSize * cIntRetinaFactor(), st::introPhotoSize * cIntRetinaFactor())); - p.setOpacity(a_photoOver.current()); - p.drawPixmap(QPoint(_phLeft, _phTop), App::sprite(), pix); - p.setOpacity(1); + float64 o = a_photoOver.current(); + QRect phRect(_phLeft, _phTop, st::introPhotoSize, st::introPhotoSize); + if (o > 0) { + if (o < 1) { + QColor c; + c.setRedF(st::newGroupPhotoBg->c.redF() * (1. - o) + st::newGroupPhotoBgOver->c.redF() * o); + c.setGreenF(st::newGroupPhotoBg->c.greenF() * (1. - o) + st::newGroupPhotoBgOver->c.greenF() * o); + c.setBlueF(st::newGroupPhotoBg->c.blueF() * (1. - o) + st::newGroupPhotoBgOver->c.blueF() * o); + p.fillRect(phRect, c); + } else { + p.fillRect(phRect, st::newGroupPhotoBgOver); + } + } else { + p.fillRect(phRect, st::newGroupPhotoBg); } + p.drawSpriteCenter(phRect, st::newGroupPhotoIcon); } else { p.drawPixmap(_phLeft, _phTop, _photoSmall); } diff --git a/Telegram/SourceFiles/langloaderplain.cpp b/Telegram/SourceFiles/langloaderplain.cpp index 2a8e2f33d..cc36e7d21 100644 --- a/Telegram/SourceFiles/langloaderplain.cpp +++ b/Telegram/SourceFiles/langloaderplain.cpp @@ -151,7 +151,7 @@ bool LangLoaderPlain::readKeyValue(const char *&from, const char *end) { tagReplacer[1] = TextCommandLangTag; tagReplacer[2] = QChar(0x0020 + index); varValue.append(tagReplacer.toUtf8()); - + if (*from == ':') { start = ++from; @@ -306,7 +306,7 @@ LangLoaderPlain::LangLoaderPlain(const QString &file, const LangLoaderRequest &r break; } } - } catch (exception &e) { + } catch (std::exception &e) { error(QString::fromUtf8(e.what())); return; } diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h index 1263f2de5..6b7d65531 100644 --- a/Telegram/SourceFiles/layout.h +++ b/Telegram/SourceFiles/layout.h @@ -20,6 +20,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +#include "core/runtime_composer.h" + static constexpr TextSelection FullSelection = { 0xFFFF, 0xFFFF }; extern TextParseOptions _textNameOptions, _textDlgOptions; @@ -96,7 +98,7 @@ public: }; -class LayoutItemBase : public Composer, public ClickHandlerHost { +class LayoutItemBase : public RuntimeComposer, public ClickHandlerHost { public: LayoutItemBase() { } diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index ea54fa5e0..fd83ba422 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -19,10 +19,11 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #include "stdafx.h" - #include "logs.h" #include <signal.h> +#include <new> + #include "pspecific.h" #ifndef TDESKTOP_DISABLE_CRASH_REPORTS @@ -736,6 +737,22 @@ namespace internal { namespace internal { + struct SomeAllocatedMemoryChunk { + char data[1024 * 1024]; + }; + std_::unique_ptr<SomeAllocatedMemoryChunk> SomeAllocatedMemory; + + void OperatorNewHandler() { + std::set_new_handler(nullptr); + SomeAllocatedMemory.reset(); + t_assert(!"Could not allocate!"); + } + + void InstallOperatorNewHandler() { + SomeAllocatedMemory = std_::make_unique<SomeAllocatedMemoryChunk>(); + std::set_new_handler(OperatorNewHandler); + } + Qt::HANDLE ReportingThreadId = nullptr; bool ReportingHeaderWritten = false; QMutex ReportingMutex; @@ -1078,6 +1095,9 @@ namespace internal { signal(SIGFPE, SignalHandlers::internal::Handler); #endif // else for !Q_OS_WIN } + + SignalHandlers::internal::InstallOperatorNewHandler(); + return Started; } diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index f69dfd2fc..eca53d7fd 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -966,31 +966,31 @@ HitTestType MainWindow::hitTest(const QPoint &p) const { if (!windowState().testFlag(Qt::WindowMaximized)) { if (y < raw) { if (x < raw) { - return HitTestTopLeft; + return HitTestType::TopLeft; } else if (x > w - raw - 1) { - return HitTestTopRight; + return HitTestType::TopRight; } - return HitTestTop; + return HitTestType::Top; } else if (y > h - raw - 1) { if (x < raw) { - return HitTestBottomLeft; + return HitTestType::BottomLeft; } else if (x > w - raw - 1) { - return HitTestBottomRight; + return HitTestType::BottomRight; } - return HitTestBottom; + return HitTestType::Bottom; } else if (x < raw) { - return HitTestLeft; + return HitTestType::Left; } else if (x > w - raw - 1) { - return HitTestRight; + return HitTestType::Right; } } - HitTestType titleTest = title->hitTest(p - title->geometry().topLeft()); - if (titleTest) { + auto titleTest = title->hitTest(p - title->geometry().topLeft()); + if (titleTest != HitTestType::None) { return titleTest; } else if (x >= 0 && y >= 0 && x < w && y < h) { - return HitTestClient; + return HitTestType::Client; } - return HitTestNone; + return HitTestType::None; } QRect MainWindow::iconRect() const { diff --git a/Telegram/SourceFiles/mtproto/connection.h b/Telegram/SourceFiles/mtproto/connection.h index dea2c3df3..89c62fb4b 100644 --- a/Telegram/SourceFiles/mtproto/connection.h +++ b/Telegram/SourceFiles/mtproto/connection.h @@ -162,7 +162,7 @@ private: int32 handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime); mtpBuffer ungzip(const mtpPrime *from, const mtpPrime *end) const; - void handleMsgsStates(const QVector<MTPlong> &ids, const string &states, QVector<MTPlong> &acked); + void handleMsgsStates(const QVector<MTPlong> &ids, const std::string &states, QVector<MTPlong> &acked); void clearMessages(); diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 846b8ef71..e48a952be 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -665,7 +665,7 @@ class MTPDstring : public mtpDataImpl<MTPDstring> { public: MTPDstring() { } - MTPDstring(const string &val) : v(val) { + MTPDstring(const std::string &val) : v(val) { } MTPDstring(const QString &val) : v(val.toUtf8().constData()) { } @@ -674,7 +674,7 @@ public: MTPDstring(const char *val) : v(val) { } - string v; + std::string v; }; class MTPstring : private mtpDataOwner { @@ -755,13 +755,13 @@ private: explicit MTPstring(MTPDstring *_data) : mtpDataOwner(_data) { } - friend MTPstring MTP_string(const string &v); + friend MTPstring MTP_string(const std::string &v); friend MTPstring MTP_string(const QString &v); friend MTPstring MTP_string(const char *v); friend MTPstring MTP_bytes(const QByteArray &v); }; -inline MTPstring MTP_string(const string &v) { +inline MTPstring MTP_string(const std::string &v) { return MTPstring(new MTPDstring(v)); } inline MTPstring MTP_string(const QString &v) { @@ -788,12 +788,12 @@ inline bool operator!=(const MTPstring &a, const MTPstring &b) { } inline QString qs(const MTPstring &v) { - const string &d(v.c_string().v); + auto &d = v.c_string().v; return QString::fromUtf8(d.data(), d.length()); } inline QByteArray qba(const MTPstring &v) { - const string &d(v.c_string().v); + auto &d = v.c_string().v; return QByteArray(d.data(), d.length()); } @@ -981,8 +981,6 @@ inline bool mtpIsFalse(const MTPBool &v) { return !mtpIsTrue(v); } -#define CHECK_MTP_SCHEME_AND_CLIENT_FLAGS_CONFLICT(Type) \ - // we must validate that MTProto scheme flags don't intersect with client side flags // and define common bit operators which allow use Type_ClientFlag together with Type::Flag #define DEFINE_MTP_CLIENT_FLAGS(Type) \ @@ -990,12 +988,10 @@ static_assert(static_cast<int32>(Type::Flag::MAX_FIELD) < static_cast<int32>(Typ "MTProto flags conflict with client side flags!"); \ inline Type::Flags qFlags(Type##_ClientFlag v) { return Type::Flags(static_cast<int32>(v)); } \ inline Type::Flags operator&(Type::Flags i, Type##_ClientFlag v) { return i & qFlags(v); } \ -inline Type::Flags operator&(Type::Flag i, Type##_ClientFlag v) { return qFlags(i) & v; } \ inline Type::Flags operator&(Type##_ClientFlag i, Type##_ClientFlag v) { return qFlags(i) & v; } \ -inline Type::Flags operator&(Type##_ClientFlag i, Type::Flag v) { return qFlags(i) & v; } \ inline Type::Flags &operator&=(Type::Flags &i, Type##_ClientFlag v) { return i &= qFlags(v); } \ inline Type::Flags operator|(Type::Flags i, Type##_ClientFlag v) { return i | qFlags(v); } \ -inline Type::Flags operator|(Type::Flag i, Type##_ClientFlag v) { return qFlags(i) | v; } \ +inline Type::Flags operator|(Type::Flag i, Type##_ClientFlag v) { return i | qFlags(v); } \ inline Type::Flags operator|(Type##_ClientFlag i, Type##_ClientFlag v) { return qFlags(i) | v; } \ inline Type::Flags operator|(Type##_ClientFlag i, Type::Flag v) { return qFlags(i) | v; } \ inline Type::Flags &operator|=(Type::Flags &i, Type##_ClientFlag v) { return i |= qFlags(v); } \ diff --git a/Telegram/SourceFiles/mtproto/facade.h b/Telegram/SourceFiles/mtproto/facade.h index 6634fb812..94f5e39c0 100644 --- a/Telegram/SourceFiles/mtproto/facade.h +++ b/Telegram/SourceFiles/mtproto/facade.h @@ -198,12 +198,12 @@ void setKey(int32 dc, AuthKeyPtr key); QReadWriteLock *dcOptionsMutex(); struct DcOption { - DcOption(int id, MTPDdcOption::Flags flags, const string &ip, int port) : id(id), flags(flags), ip(ip), port(port) { + DcOption(int id, MTPDdcOption::Flags flags, const std::string &ip, int port) : id(id), flags(flags), ip(ip), port(port) { } int id; MTPDdcOption::Flags flags; - string ip; + std::string ip; int port; }; typedef QMap<int, DcOption> DcOptions; diff --git a/Telegram/SourceFiles/mtproto/file_download.cpp b/Telegram/SourceFiles/mtproto/file_download.cpp index 513fbfd8e..349380c9c 100644 --- a/Telegram/SourceFiles/mtproto/file_download.cpp +++ b/Telegram/SourceFiles/mtproto/file_download.cpp @@ -459,8 +459,8 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe --_queue->queries; _requests.erase(i); - const auto &d(result.c_upload_file()); - const string &bytes(d.vbytes.c_string().v); + auto &d = result.c_upload_file(); + auto &bytes = d.vbytes.c_string().v; if (DebugLogging::FileLoader() && _id) DEBUG_LOG(("FileLoader(%1): got part with offset=%2, bytes=%3, _queue->queries=%4, _nextRequestOffset=%5, _requests=%6").arg(_id).arg(offset).arg(bytes.size()).arg(_queue->queries).arg(_nextRequestOffset).arg(serializereqs(_requests))); diff --git a/Telegram/SourceFiles/mtproto/rsa_public_key.h b/Telegram/SourceFiles/mtproto/rsa_public_key.h index b59deec79..5e1bcbf4f 100644 --- a/Telegram/SourceFiles/mtproto/rsa_public_key.h +++ b/Telegram/SourceFiles/mtproto/rsa_public_key.h @@ -34,7 +34,7 @@ public: uint64 getFingerPrint() const; // data has exactly 256 chars to be encrypted - bool encrypt(const void *data, string &result) const; + bool encrypt(const void *data, std::string &result) const; private: diff --git a/Telegram/SourceFiles/mtproto/session.cpp b/Telegram/SourceFiles/mtproto/session.cpp index 70f5561a5..6e80a3619 100644 --- a/Telegram/SourceFiles/mtproto/session.cpp +++ b/Telegram/SourceFiles/mtproto/session.cpp @@ -222,7 +222,7 @@ void Session::sendPong(quint64 msgId, quint64 pingId) { void Session::sendMsgsStateInfo(quint64 msgId, QByteArray data) { MTPMsgsStateInfo req(MTP_msgs_state_info(MTP_long(msgId), MTPstring())); - string &info(req._msgs_state_info().vinfo._string().v); + auto &info = req._msgs_state_info().vinfo._string().v; info.resize(data.size()); if (!data.isEmpty()) { memcpy(&info[0], data.constData(), data.size()); @@ -391,7 +391,7 @@ mtpRequestId Session::resend(quint64 msgId, quint64 msCanWait, bool forceContain char cantResend[2] = {1, 0}; DEBUG_LOG(("Message Info: cant resend %1, request not found").arg(msgId)); - return send(MTP_msgs_state_info(MTP_long(msgId), MTP_string(string(cantResend, cantResend + 1)))); + return send(MTP_msgs_state_info(MTP_long(msgId), MTP_string(std::string(cantResend, cantResend + 1)))); } return 0; } diff --git a/Telegram/SourceFiles/overview/overview_layout.h b/Telegram/SourceFiles/overview/overview_layout.h index 0705e5e21..af49c4bb8 100644 --- a/Telegram/SourceFiles/overview/overview_layout.h +++ b/Telegram/SourceFiles/overview/overview_layout.h @@ -156,7 +156,7 @@ protected: }; -struct Info : public BaseComponent<Info> { +struct Info : public RuntimeComponent<Info> { int top = 0; }; diff --git a/Telegram/SourceFiles/passcodewidget.cpp b/Telegram/SourceFiles/passcodewidget.cpp index ef4b8c9ed..1a2688f00 100644 --- a/Telegram/SourceFiles/passcodewidget.cpp +++ b/Telegram/SourceFiles/passcodewidget.cpp @@ -186,7 +186,7 @@ void PasscodeWidget::paintEvent(QPaintEvent *e) { p.setOpacity(a_shadow.current()); p.drawPixmap(QRect(a_coordOver.current() - st::slideShadow.pxWidth(), 0, st::slideShadow.pxWidth(), height()), App::sprite(), st::slideShadow.rect()); } else { - p.fillRect(rect(), st::setBG->b); + p.fillRect(rect(), st::windowBg); p.setFont(st::passcodeHeaderFont->f); p.drawText(QRect(0, _passcode.y() - st::passcodeHeaderHeight, width(), st::passcodeHeaderHeight), lang(lng_passcode_enter), style::al_center); diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp index 0d9331782..a9a96d9f0 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -181,21 +181,21 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa POINTS p = MAKEPOINTS(lParam); RECT r; GetWindowRect(hWnd, &r); - HitTestType res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); + auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); switch (res) { - case HitTestClient: - case HitTestSysButton: *result = HTCLIENT; break; - case HitTestIcon: *result = HTCAPTION; break; - case HitTestCaption: *result = HTCAPTION; break; - case HitTestTop: *result = HTTOP; break; - case HitTestTopRight: *result = HTTOPRIGHT; break; - case HitTestRight: *result = HTRIGHT; break; - case HitTestBottomRight: *result = HTBOTTOMRIGHT; break; - case HitTestBottom: *result = HTBOTTOM; break; - case HitTestBottomLeft: *result = HTBOTTOMLEFT; break; - case HitTestLeft: *result = HTLEFT; break; - case HitTestTopLeft: *result = HTTOPLEFT; break; - case HitTestNone: + case HitTestType::Client: + case HitTestType::SysButton: *result = HTCLIENT; break; + case HitTestType::Icon: *result = HTCAPTION; break; + case HitTestType::Caption: *result = HTCAPTION; break; + case HitTestType::Top: *result = HTTOP; break; + case HitTestType::TopRight: *result = HTTOPRIGHT; break; + case HitTestType::Right: *result = HTRIGHT; break; + case HitTestType::BottomRight: *result = HTBOTTOMRIGHT; break; + case HitTestType::Bottom: *result = HTBOTTOM; break; + case HitTestType::BottomLeft: *result = HTBOTTOMLEFT; break; + case HitTestType::Left: *result = HTLEFT; break; + case HitTestType::TopLeft: *result = HTTOPLEFT; break; + case HitTestType::None: default: *result = HTTRANSPARENT; break; }; } return true; @@ -208,9 +208,9 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa POINTS p = MAKEPOINTS(lParam); RECT r; GetWindowRect(hWnd, &r); - HitTestType res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); + auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); switch (res) { - case HitTestIcon: + case HitTestType::Icon: if (menuHidden && getms() < menuHidden + 10) { menuHidden = 0; if (getms() < menuShown + GetDoubleClickTime()) { @@ -234,9 +234,9 @@ bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa POINTS p = MAKEPOINTS(lParam); RECT r; GetWindowRect(hWnd, &r); - HitTestType res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); + auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); switch (res) { - case HitTestIcon: App::wnd()->close(); return true; + case HitTestType::Icon: App::wnd()->close(); return true; }; } return false; diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index a9ab6f89a..69e8380a7 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -185,39 +185,39 @@ void settingsParseArgs(int argc, char *argv[]) { gStartUrl = fromUtf8Safe(argv[1]); } for (int32 i = 0; i < argc; ++i) { - if (string("-testmode") == argv[i]) { + if (qstr("-testmode") == argv[i]) { gTestMode = true; - } else if (string("-debug") == argv[i]) { + } else if (qstr("-debug") == argv[i]) { gDebug = true; - } else if (string("-many") == argv[i]) { + } else if (qstr("-many") == argv[i]) { gManyInstance = true; - } else if (string("-key") == argv[i] && i + 1 < argc) { + } else if (qstr("-key") == argv[i] && i + 1 < argc) { gKeyFile = fromUtf8Safe(argv[++i]); - } else if (string("-autostart") == argv[i]) { + } else if (qstr("-autostart") == argv[i]) { gLaunchMode = LaunchModeAutoStart; - } else if (string("-fixprevious") == argv[i]) { + } else if (qstr("-fixprevious") == argv[i]) { gLaunchMode = LaunchModeFixPrevious; - } else if (string("-cleanup") == argv[i]) { + } else if (qstr("-cleanup") == argv[i]) { gLaunchMode = LaunchModeCleanup; - } else if (string("-crash") == argv[i] && i + 1 < argc) { + } else if (qstr("-crash") == argv[i] && i + 1 < argc) { gLaunchMode = LaunchModeShowCrash; gStartUrl = fromUtf8Safe(argv[++i]); - } else if (string("-noupdate") == argv[i]) { + } else if (qstr("-noupdate") == argv[i]) { gNoStartUpdate = true; - } else if (string("-tosettings") == argv[i]) { + } else if (qstr("-tosettings") == argv[i]) { gStartToSettings = true; - } else if (string("-startintray") == argv[i]) { + } else if (qstr("-startintray") == argv[i]) { gStartInTray = true; - } else if (string("-sendpath") == argv[i] && i + 1 < argc) { + } else if (qstr("-sendpath") == argv[i] && i + 1 < argc) { for (++i; i < argc; ++i) { gSendPaths.push_back(fromUtf8Safe(argv[i])); } - } else if (string("-workdir") == argv[i] && i + 1 < argc) { + } else if (qstr("-workdir") == argv[i] && i + 1 < argc) { QString dir = fromUtf8Safe(argv[++i]); if (QDir().exists(dir)) { gWorkingDir = dir; } - } else if (string("--") == argv[i] && i + 1 < argc) { + } else if (qstr("--") == argv[i] && i + 1 < argc) { gStartUrl = fromUtf8Safe(argv[++i]).mid(0, 8192); } } diff --git a/Telegram/SourceFiles/settings/settings_background_widget.cpp b/Telegram/SourceFiles/settings/settings_background_widget.cpp index ac25cbd53..518bf5039 100644 --- a/Telegram/SourceFiles/settings/settings_background_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_background_widget.cpp @@ -59,8 +59,8 @@ void BackgroundRow::paintEvent(QPaintEvent *e) { if (backThumb->isNull()) { p.drawPixmap(0, 0, _background); } else { - const QPixmap &pix = App::main()->newBackgroundThumb()->pixBlurred(st::setBackgroundSize); - p.drawPixmap(0, 0, st::setBackgroundSize, st::setBackgroundSize, pix, 0, (pix.height() - st::setBackgroundSize) / 2, st::setBackgroundSize, st::setBackgroundSize); + const QPixmap &pix = App::main()->newBackgroundThumb()->pixBlurred(st::settingsBackgroundSize); + p.drawPixmap(0, 0, st::settingsBackgroundSize, st::settingsBackgroundSize, pix, 0, (pix.height() - st::settingsBackgroundSize) / 2, st::settingsBackgroundSize, st::settingsBackgroundSize); } auto outer = radialRect(); @@ -115,7 +115,7 @@ bool BackgroundRow::radialLoading() const { } QRect BackgroundRow::radialRect() const { - return QRect(0, 0, st::setBackgroundSize, st::setBackgroundSize); + return QRect(0, 0, st::settingsBackgroundSize, st::settingsBackgroundSize); } void BackgroundRow::radialStart() { @@ -139,7 +139,7 @@ void BackgroundRow::step_radial(uint64 ms, bool timer) { } void BackgroundRow::updateImage() { - int32 size = st::setBackgroundSize * cIntRetinaFactor(); + int32 size = st::settingsBackgroundSize * cIntRetinaFactor(); QImage back(size, size, QImage::Format_ARGB32_Premultiplied); back.setDevicePixelRatio(cRetinaFactor()); { @@ -149,7 +149,7 @@ void BackgroundRow::updateImage() { int sy = (pix.height() > pix.width()) ? ((pix.height() - pix.width()) / 2) : 0; int s = (pix.width() > pix.height()) ? pix.height() : pix.width(); p.setRenderHint(QPainter::SmoothPixmapTransform); - p.drawPixmap(0, 0, st::setBackgroundSize, st::setBackgroundSize, pix, sx, sy, s, s); + p.drawPixmap(0, 0, st::settingsBackgroundSize, st::settingsBackgroundSize, pix, sx, sy, s, s); } imageRound(back, ImageRoundRadius::Small); _background = App::pixmapFromImageInPlace(std_::move(back)); diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index d4c7ed621..41c554fad 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -57,6 +57,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include <QtNetwork/QtNetwork> #include "core/basic_types.h" +#include "logs.h" +#include "core/utils.h" #include "config.h" #include "mtproto/facade.h" diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index babee7e99..f75c8ade2 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -172,7 +172,7 @@ struct NotifySettings { } MTPDpeerNotifySettings::Flags flags; TimeId mute; - string sound; + std::string sound; bool previews() const { return flags & MTPDpeerNotifySettings::Flag::f_show_previews; } @@ -288,9 +288,9 @@ public: QString name; Text nameText; - typedef QSet<QString> Names; + using Names = OrderedSet<QString>; Names names; // for filtering - typedef QSet<QChar> NameFirstChars; + using NameFirstChars = OrderedSet<QChar>; NameFirstChars chars; enum LoadedStatus { diff --git a/Telegram/SourceFiles/sysbuttons.cpp b/Telegram/SourceFiles/sysbuttons.cpp index 0614cf322..becff636f 100644 --- a/Telegram/SourceFiles/sysbuttons.cpp +++ b/Telegram/SourceFiles/sysbuttons.cpp @@ -93,9 +93,9 @@ void SysBtn::setSysBtnStyle(const style::sysButton &st) { HitTestType SysBtn::hitTest(const QPoint &p) const { int x(p.x()), y(p.y()), w(width()), h(height()); if (x >= 0 && y >= 0 && x < w && y < h && isVisible()) { - return HitTestSysButton; + return HitTestType::SysButton; } - return HitTestNone; + return HitTestType::None; } void SysBtn::step_color(float64 ms, bool timer) { diff --git a/Telegram/SourceFiles/sysbuttons.h b/Telegram/SourceFiles/sysbuttons.h index 88ff7b0a1..ea5609368 100644 --- a/Telegram/SourceFiles/sysbuttons.h +++ b/Telegram/SourceFiles/sysbuttons.h @@ -23,6 +23,22 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/animation.h" #include "ui/button.h" +enum class HitTestType { + None = 0, + Client, + SysButton, + Icon, + Caption, + Top, + TopRight, + Right, + BottomRight, + Bottom, + BottomLeft, + Left, + TopLeft, +}; + class MainWindow; class SysBtn : public Button { diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index f75eb8d58..638248ae3 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -360,22 +360,22 @@ void TitleWidget::maximizedChanged(bool maximized, bool force) { } HitTestType TitleWidget::hitTest(const QPoint &p) { - if (App::wnd() && Ui::isLayerShown()) return HitTestNone; + if (App::wnd() && Ui::isLayerShown()) return HitTestType::None; int x(p.x()), y(p.y()), w(width()), h(height()); - if (!Adaptive::OneColumn() && hider && x >= App::main()->dlgsWidth()) return HitTestNone; + if (!Adaptive::OneColumn() && hider && x >= App::main()->dlgsWidth()) return HitTestType::None; if (x >= st::titleIconPos.x() && y >= st::titleIconPos.y() && x < st::titleIconPos.x() + st::titleIconImg.pxWidth() && y < st::titleIconPos.y() + st::titleIconImg.pxHeight()) { - return HitTestIcon; + return HitTestType::Icon; } else if (false - || (_lock.hitTest(p - _lock.geometry().topLeft()) == HitTestSysButton && _lock.isVisible()) - || (_update.hitTest(p - _update.geometry().topLeft()) == HitTestSysButton && _update.isVisible()) - || (_minimize.hitTest(p - _minimize.geometry().topLeft()) == HitTestSysButton) - || (_maximize.hitTest(p - _maximize.geometry().topLeft()) == HitTestSysButton) - || (_restore.hitTest(p - _restore.geometry().topLeft()) == HitTestSysButton) - || (_close.hitTest(p - _close.geometry().topLeft()) == HitTestSysButton) + || (_lock.hitTest(p - _lock.geometry().topLeft()) == HitTestType::SysButton && _lock.isVisible()) + || (_update.hitTest(p - _update.geometry().topLeft()) == HitTestType::SysButton && _update.isVisible()) + || (_minimize.hitTest(p - _minimize.geometry().topLeft()) == HitTestType::SysButton) + || (_maximize.hitTest(p - _maximize.geometry().topLeft()) == HitTestType::SysButton) + || (_restore.hitTest(p - _restore.geometry().topLeft()) == HitTestType::SysButton) + || (_close.hitTest(p - _close.geometry().topLeft()) == HitTestType::SysButton) ) { - return HitTestSysButton; + return HitTestType::SysButton; } else if (x >= 0 && x < w && y >= 0 && y < h) { if (false || (!_cancel.isHidden() && _cancel.geometry().contains(x, y)) @@ -383,9 +383,9 @@ HitTestType TitleWidget::hitTest(const QPoint &p) { || (!_contacts.isHidden() && _contacts.geometry().contains(x, y)) || (!_about.isHidden() && _about.geometry().contains(x, y)) ) { - return HitTestClient; + return HitTestType::Client; } - return HitTestCaption; + return HitTestType::Caption; } - return HitTestNone; + return HitTestType::None; } diff --git a/Telegram/SourceFiles/ui/animation.h b/Telegram/SourceFiles/ui/animation.h index 4bbe4e49c..6842c55a7 100644 --- a/Telegram/SourceFiles/ui/animation.h +++ b/Telegram/SourceFiles/ui/animation.h @@ -31,7 +31,7 @@ namespace Clip { class Reader; class ReaderPointer { public: - ReaderPointer(std::nullptr_t = nullptr) { + ReaderPointer(std_::nullptr_t = nullptr) { } explicit ReaderPointer(Reader *pointer) : _pointer(pointer) { } diff --git a/Telegram/SourceFiles/ui/flatcheckbox.h b/Telegram/SourceFiles/ui/flatcheckbox.h index 64d59c24b..ea43ce09d 100644 --- a/Telegram/SourceFiles/ui/flatcheckbox.h +++ b/Telegram/SourceFiles/ui/flatcheckbox.h @@ -26,8 +26,7 @@ class FlatCheckbox : public Button { Q_OBJECT public: - - FlatCheckbox(QWidget *parent, const QString &text, bool checked = false, const style::flatCheckbox &st = st::cbDefFlat); + FlatCheckbox(QWidget *parent, const QString &text, bool checked, const style::flatCheckbox &st); bool checked() const; void setChecked(bool checked); @@ -38,16 +37,13 @@ public: void setOpacity(float64 o); public slots: - void onClicked(); void onStateChange(int oldState, ButtonStateChangeSource source); signals: - void changed(); private: - style::flatCheckbox _st; anim::fvalue a_over; Animation _a_appearance; @@ -66,7 +62,7 @@ class FlatRadiobutton : public FlatCheckbox { public: - FlatRadiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked = false, const style::flatCheckbox &st = st::rbDefFlat); + FlatRadiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::flatCheckbox &st); int32 val() const { return _value; } @@ -130,7 +126,6 @@ class Radiobutton : public Button { Q_OBJECT public: - Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked = false, const style::Radiobutton &st = st::defaultRadiobutton); bool checked() const; @@ -148,16 +143,13 @@ public: ~Radiobutton(); public slots: - void onClicked(); void onStateChange(int oldState, ButtonStateChangeSource source); signals: - void changed(); private: - void onChanged(); const style::Radiobutton &_st; diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index 0dc17700b..a883d746c 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -310,7 +310,7 @@ private: template <typename T> class ChildWidget { public: - ChildWidget(std::nullptr_t) : _widget(nullptr) { + ChildWidget(std_::nullptr_t) : _widget(nullptr) { } // No default constructor, but constructors with at least @@ -322,7 +322,7 @@ public: ChildWidget(const ChildWidget<T> &other) = delete; ChildWidget<T> &operator=(const ChildWidget<T> &other) = delete; - ChildWidget<T> &operator=(std::nullptr_t) { + ChildWidget<T> &operator=(std_::nullptr_t) { _widget = nullptr; return *this; } diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index e84b854f8..4e82727aa 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -191,7 +191,6 @@ '<(src_loc)/boxes/stickersetbox.h', '<(src_loc)/boxes/usernamebox.cpp', '<(src_loc)/boxes/usernamebox.h', - '<(src_loc)/core/basic_types.cpp', '<(src_loc)/core/basic_types.h', '<(src_loc)/core/click_handler.cpp', '<(src_loc)/core/click_handler.h', @@ -200,8 +199,14 @@ '<(src_loc)/core/lambda_wrap.h', '<(src_loc)/core/observer.cpp', '<(src_loc)/core/observer.h', + '<(src_loc)/core/ordered_set.h', '<(src_loc)/core/qthelp_url.cpp', '<(src_loc)/core/qthelp_url.h', + '<(src_loc)/core/runtime_composer.cpp', + '<(src_loc)/core/runtime_composer.h', + '<(src_loc)/core/stl_subset.h', + '<(src_loc)/core/utils.cpp', + '<(src_loc)/core/utils.h', '<(src_loc)/core/vector_of_moveable.h', '<(src_loc)/core/version.h', '<(src_loc)/data/data_abstract_structure.cpp',