diff --git a/Telegram/Resources/art/sprite.png b/Telegram/Resources/art/sprite.png index 179237f54a..e1f5778499 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 e5dd6795e5..9eaedee277 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 2f78e7377a..ab01b4e097 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -558,37 +558,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; @@ -816,28 +785,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; @@ -854,92 +802,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; @@ -956,7 +823,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); @@ -1136,7 +1009,7 @@ msgInvDblCheckImg: sprite(300px, 65px, 20px, 20px); msgInvViewsImg: sprite(104px, 59px, 16px, 11px); msgInvSendingViewsImg: sprite(104px, 114px, 16px, 11px); -msgDateSpace: 19px; +msgDateSpace: 12px; msgDateCheckSpace: 4px; msgDateViewsSpace: 11px; msgDateDelta: point(2px, 5px); @@ -1818,13 +1691,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 2a8eedd4d6..1d5d57f76e 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/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index d36c93ffc2..6e40e9452d 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -581,8 +581,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_pinned_media_location" = "a location mark"; "lng_action_pinned_media_sticker" = "a sticker"; "lng_action_pinned_media_emoji_sticker" = "a {emoji} sticker"; -"lng_action_pinned_media_game" = "a game «{game}»"; +"lng_action_pinned_media_game" = "the game «{game}»"; "lng_action_game_score" = "{from} scored {count:#|#|#} in {game}"; +"lng_action_game_you_scored" = "You scored {count:#|#|#} in {game}"; "lng_profile_migrate_reached" = "{count:_not_used_|# member|# members} limit reached"; "lng_profile_migrate_body" = "To get over this limit, you can upgrade your group to a supergroup."; diff --git a/Telegram/Resources/langs/lang_de.strings b/Telegram/Resources/langs/lang_de.strings index 353b954dbd..73f9219f95 100644 --- a/Telegram/Resources/langs/lang_de.strings +++ b/Telegram/Resources/langs/lang_de.strings @@ -580,7 +580,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_pinned_media_contact" = "einen Kontakt"; "lng_action_pinned_media_location" = "einen Standort"; "lng_action_pinned_media_sticker" = "einen Sticker"; -"lng_action_game_score" = "{from} erzielte {count:Punkte|Punkt|Punkte} bei {game}"; +"lng_action_pinned_media_emoji_sticker" = "einen {emoji} Sticker"; +"lng_action_pinned_media_game" = "das Spiel «{game}»"; +"lng_action_game_score" = "{from} erzielte {count:# Punkte|# Punkt|# Punkte} bei {game}"; +"lng_action_game_you_scored" = "Du hast {count:# Punkte|# Punkt|# Punkte} bei {game} erzielt"; "lng_profile_migrate_reached" = "Limit von {count:_not_used_|# Mitglied|# Mitgliedern} erreicht"; "lng_profile_migrate_body" = "Um das Limit aufzuheben, ändere die Gruppe in eine Supergruppe."; @@ -774,6 +777,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_bot_groups_not_found" = "Keine Gruppen gefunden"; "lng_bot_sure_invite" = "Den Bot zu «{group}» hinzufügen?"; "lng_bot_already_in_group" = "Der Bot ist schon in dieser Gruppe."; +"lng_bot_choose_chat" = "Chat auswählen"; +"lng_bot_no_chats" = "Du hast keine Chats"; +"lng_bot_chats_not_found" = "Keine Chats gefunden"; +"lng_bot_sure_share_game" = "Das Spiel mit {user} teilen?"; +"lng_bot_sure_share_game_group" = "Das Spiel mit «{group}» teilen?"; "lng_typing" = "tippt"; "lng_user_typing" = "{user} tippt"; @@ -808,6 +816,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_duration_played" = "{played} / {duration}"; "lng_date_and_duration" = "{date}, {duration}"; "lng_choose_images" = "Bilder auswählen"; +"lng_game_tag" = "Spiel"; "lng_context_view_profile" = "Profil öffnen"; "lng_context_view_group" = "Gruppeninfo zeigen"; diff --git a/Telegram/Resources/langs/lang_es.strings b/Telegram/Resources/langs/lang_es.strings index b844de3b22..6787e38943 100644 --- a/Telegram/Resources/langs/lang_es.strings +++ b/Telegram/Resources/langs/lang_es.strings @@ -580,7 +580,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_pinned_media_contact" = "un contacto"; "lng_action_pinned_media_location" = "una ubicación"; "lng_action_pinned_media_sticker" = "un sticker"; -"lng_action_game_score" = "{from} ha conseguido {count:# puntos|# punto|# puntos} en {game}"; +"lng_action_pinned_media_emoji_sticker" = "un {emoji} sticker"; +"lng_action_pinned_media_game" = "el juego «{game}»"; +"lng_action_game_score" = "{from} consiguió {count:# puntos|# punto|# puntos} en {game}"; +"lng_action_game_you_scored" = "Conseguiste {count:# puntos|# punto|#puntos} en {game}"; "lng_profile_migrate_reached" = "Límite de {count:_not_used_|# miembro|# miembros} alcanzado"; "lng_profile_migrate_body" = "Para superar este límite, puedes convertir tu grupo en un supergrupo."; @@ -774,6 +777,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_bot_groups_not_found" = "No se encontraron grupos"; "lng_bot_sure_invite" = "¿Añadir el bot a «{group}»?"; "lng_bot_already_in_group" = "El bot ya es un miembro del grupo."; +"lng_bot_choose_chat" = "Elige un chat"; +"lng_bot_no_chats" = "No tienes chats"; +"lng_bot_chats_not_found" = "No se encontraron chats"; +"lng_bot_sure_share_game" = "¿Compartir el juego con {user}?"; +"lng_bot_sure_share_game_group" = "¿Compartir el juego en «{group}»?"; "lng_typing" = "escribiendo"; "lng_user_typing" = "{user} está escribiendo"; @@ -808,6 +816,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_duration_played" = "{played} / {duration}"; "lng_date_and_duration" = "{date}, {duration}"; "lng_choose_images" = "Elegir imágenes"; +"lng_game_tag" = "Juego"; "lng_context_view_profile" = "Ver información"; "lng_context_view_group" = "Ver información"; diff --git a/Telegram/Resources/langs/lang_it.strings b/Telegram/Resources/langs/lang_it.strings index 2d2d99dd4a..0811a42995 100644 --- a/Telegram/Resources/langs/lang_it.strings +++ b/Telegram/Resources/langs/lang_it.strings @@ -580,7 +580,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_pinned_media_contact" = "un contatto"; "lng_action_pinned_media_location" = "una posizione"; "lng_action_pinned_media_sticker" = "uno sticker"; -"lng_action_game_score" = "{from} ha segnato {count:# punti|# punto|# punti} in {game}"; +"lng_action_pinned_media_emoji_sticker" = "uno {emoji} sticker"; +"lng_action_pinned_media_game" = "il gioco «{game}»"; +"lng_action_game_score" = "{from} ha totalizzato {count:# punti|# punto|# punti} a {game}"; +"lng_action_game_you_scored" = "Hai totalizzato {count:# punti|# punto|# punti} a {game}"; "lng_profile_migrate_reached" = "Limite di {count:_not_used_|# membro|# membri} raggiunto"; "lng_profile_migrate_body" = "Per superare questo limite, puoi aggiornare il gruppo a supergruppo."; @@ -774,6 +777,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_bot_groups_not_found" = "Nessun gruppo trovato"; "lng_bot_sure_invite" = "Aggiungere il bot a «{group}»?"; "lng_bot_already_in_group" = "Questo bot è già membro del gruppo."; +"lng_bot_choose_chat" = "Scegli chat"; +"lng_bot_no_chats" = "Non hai chat"; +"lng_bot_chats_not_found" = "Nessuna chat trovata"; +"lng_bot_sure_share_game" = "Condividere questo gioco con {user}?"; +"lng_bot_sure_share_game_group" = "Condividere questo gioco con «{group}»?"; "lng_typing" = "sta scrivendo"; "lng_user_typing" = "{user} sta scrivendo"; @@ -808,6 +816,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_duration_played" = "{played} / {duration}"; "lng_date_and_duration" = "{date}, {duration}"; "lng_choose_images" = "Scegli immagini"; +"lng_game_tag" = "Gioco"; "lng_context_view_profile" = "Visualizza profilo"; "lng_context_view_group" = "Visualizza info gruppo"; diff --git a/Telegram/Resources/langs/lang_ko.strings b/Telegram/Resources/langs/lang_ko.strings index e0a6c86f54..0fdee3958e 100644 --- a/Telegram/Resources/langs/lang_ko.strings +++ b/Telegram/Resources/langs/lang_ko.strings @@ -580,7 +580,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_pinned_media_contact" = "연락처 정보"; "lng_action_pinned_media_location" = "위치 마크"; "lng_action_pinned_media_sticker" = "스티커"; +"lng_action_pinned_media_emoji_sticker" = " {emoji} 스티커"; +"lng_action_pinned_media_game" = " «{game}» 게임"; "lng_action_game_score" = "{game} 에서 {from} 님이 {count:#|#|#} 점 획득"; +"lng_action_game_you_scored" = "{game} 에서 {count:#|#|#} 점 획득"; "lng_profile_migrate_reached" = "{count:_not_used_|# 명|# 명} 한계치에 도달 되었습니다."; "lng_profile_migrate_body" = "제한을 초과하고 싶으실 경우, 슈퍼그룹으로 그룹 업그레이드가 가능합니다."; @@ -774,6 +777,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_bot_groups_not_found" = "그룹을 찾을 수 없습니다."; "lng_bot_sure_invite" = "<<{group}>>에 봇을 추가 하시겠습니까?"; "lng_bot_already_in_group" = "봇이 이미 그룹의 멤버입니다."; +"lng_bot_choose_chat" = "채팅방 선택"; +"lng_bot_no_chats" = "채팅방이 없습니다."; +"lng_bot_chats_not_found" = "채팅방을 찾 을 수 없음"; +"lng_bot_sure_share_game" = "{user}에게 게임을 공유하겠습니까?"; +"lng_bot_sure_share_game_group" = " «{group}»에게 게임을 공유하겠습니까?"; "lng_typing" = "입력중"; "lng_user_typing" = "{user}님이 입력중입니다."; @@ -808,6 +816,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_duration_played" = "{played} / {duration}"; "lng_date_and_duration" = "{date}, {duration}"; "lng_choose_images" = "이미지 선택"; +"lng_game_tag" = "게임"; "lng_context_view_profile" = "프로필 보기"; "lng_context_view_group" = "그룹 정보 보기"; diff --git a/Telegram/Resources/langs/lang_nl.strings b/Telegram/Resources/langs/lang_nl.strings index c2b2b2ff68..317066c38e 100644 --- a/Telegram/Resources/langs/lang_nl.strings +++ b/Telegram/Resources/langs/lang_nl.strings @@ -580,7 +580,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_pinned_media_contact" = "een contact"; "lng_action_pinned_media_location" = "een locatie"; "lng_action_pinned_media_sticker" = "een sticker"; -"lng_action_game_score" = "{from} heeft met {game} {count:#punten|#punt|#punten} behaald"; +"lng_action_pinned_media_emoji_sticker" = "een {emoji} sticker"; +"lng_action_pinned_media_game" = "het spel «{game}»"; +"lng_action_game_score" = "{from} heeft met {game} {count:# punten|# punt|# punten} behaald"; +"lng_action_game_you_scored" = "Je hebt met {game} {count:# punten|# punt|# punten} behaald"; "lng_profile_migrate_reached" = "{count:_not_used_|# lid |# leden} limiet bereikt"; "lng_profile_migrate_body" = "Wil je een hogere limiet? Waardeer op naar een supergroep."; @@ -774,6 +777,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_bot_groups_not_found" = "Geen groepen gevonden"; "lng_bot_sure_invite" = "De bot toevoegen aan \"{group}\"?"; "lng_bot_already_in_group" = "Deze bot is al een groepslid."; +"lng_bot_choose_chat" = "Kies chat"; +"lng_bot_no_chats" = "Je hebt nog geen chats"; +"lng_bot_chats_not_found" = "Geen chats gevonden"; +"lng_bot_sure_share_game" = "Spel met {user} delen?"; +"lng_bot_sure_share_game_group" = "Spel met «{group}» delen?"; "lng_typing" = "aan het typen"; "lng_user_typing" = "{user} is aan het typen"; @@ -808,6 +816,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_duration_played" = "{played} / {duration}"; "lng_date_and_duration" = "{date}, {duration}"; "lng_choose_images" = "Afbeeldingen kiezen"; +"lng_game_tag" = "Spel"; "lng_context_view_profile" = "Profiel weergeven"; "lng_context_view_group" = "Groepsinformatie weergeven"; diff --git a/Telegram/Resources/langs/lang_pt_BR.strings b/Telegram/Resources/langs/lang_pt_BR.strings index 16b4438495..e75b35cbd8 100644 --- a/Telegram/Resources/langs/lang_pt_BR.strings +++ b/Telegram/Resources/langs/lang_pt_BR.strings @@ -580,7 +580,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_action_pinned_media_contact" = "um contato"; "lng_action_pinned_media_location" = "uma localização"; "lng_action_pinned_media_sticker" = "um sticker"; -"lng_action_game_score" = "{from} marcou {count:pontos|ponto|pontos} em {game}"; +"lng_action_pinned_media_emoji_sticker" = "um {emoji} sticker"; +"lng_action_pinned_media_game" = "o jogo «{game}»"; +"lng_action_game_score" = "{from} marcou {count:# pontos|# ponto|# pontos} em {game}"; +"lng_action_game_you_scored" = "Você marcou {count:# pontos|# ponto|# pontos} em {game}"; "lng_profile_migrate_reached" = "{count:_not_used_|# membro|# membros} limite alcançado"; "lng_profile_migrate_body" = "Para ir além desse limite, você pode converter seu grupo em um supergrupo."; @@ -774,6 +777,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_bot_groups_not_found" = "Nenhum grupo encontrado"; "lng_bot_sure_invite" = "Adicionar bot ao «{group}»?"; "lng_bot_already_in_group" = "O bot já é um membro do grupo."; +"lng_bot_choose_chat" = "Escolher Conversa"; +"lng_bot_no_chats" = "Você não possui conversas"; +"lng_bot_chats_not_found" = "Nenhuma conversa encontrada"; +"lng_bot_sure_share_game" = "Compartilhar o jogo com {user}?"; +"lng_bot_sure_share_game_group" = "Compartilhar o jogo com «{group}»?"; "lng_typing" = "escrevendo"; "lng_user_typing" = "{user} está escrevendo"; @@ -808,6 +816,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_duration_played" = "{played} / {duration}"; "lng_date_and_duration" = "{date}, {duration}"; "lng_choose_images" = "Escolher imagens"; +"lng_game_tag" = "Jogo"; "lng_context_view_profile" = "Ver perfil"; "lng_context_view_group" = "Ver info do grupo"; diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index c52e8eb1c8..1d240708ca 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,10,8,1 - PRODUCTVERSION 0,10,8,1 + FILEVERSION 0,10,8,3 + PRODUCTVERSION 0,10,8,3 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -51,10 +51,10 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Telegram Messenger LLP" - VALUE "FileVersion", "0.10.8.1" + VALUE "FileVersion", "0.10.8.3" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.10.8.1" + VALUE "ProductVersion", "0.10.8.3" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index 4ecec96054..c82764a5c9 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,10,8,1 - PRODUCTVERSION 0,10,8,1 + FILEVERSION 0,10,8,3 + PRODUCTVERSION 0,10,8,3 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,10 +43,10 @@ BEGIN BEGIN VALUE "CompanyName", "Telegram Messenger LLP" VALUE "FileDescription", "Telegram Updater" - VALUE "FileVersion", "0.10.8.1" + VALUE "FileVersion", "0.10.8.3" VALUE "LegalCopyright", "Copyright (C) 2014-2016" VALUE "ProductName", "Telegram Desktop" - VALUE "ProductVersion", "0.10.8.1" + VALUE "ProductVersion", "0.10.8.3" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index d5ab15beee..28527ab3b9 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1196,22 +1196,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; @@ -1429,12 +1427,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; } @@ -2069,22 +2067,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 61107ba4a1..25265a48af 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 6c20fbc79e..1058ed0319 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::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 1626fd08a4..113ac8aa32 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.h +++ b/Telegram/SourceFiles/boxes/stickersetbox.h @@ -186,7 +186,7 @@ private: ChildWidget _inner; ChildWidget _save = { nullptr }; ChildWidget _cancel = { nullptr }; - QMap _disenableRequests; + OrderedSet _disenableRequests; mtpRequestId _reorderRequest = 0; ChildWidget _topShadow = { nullptr }; ChildWidget _bottomShadow = { nullptr }; diff --git a/Telegram/SourceFiles/core/basic_types.h b/Telegram/SourceFiles/core/basic_types.h index a5401961c0..9487daec93 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 #include +#include #include -#include +#include "core/stl_subset.h" +#include "core/ordered_set.h" -#ifndef OS_MAC_OLD -#include -#endif // OS_MAC_OLD - -template -void deleteAndMark(T *&link) { - delete link; - link = reinterpret_cast(0x00000BAD); -} - -template -T *getPointerAndReset(T *&ptr) { - T *result = nullptr; - qSwap(result, ptr); - return result; -} - -struct NullType { -}; - -// ordered set template based on QMap -template -class OrderedSet { - typedef OrderedSet Self; - typedef QMap 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 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; - - }; - 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; - - }; - 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 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 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 -inline QFlags qFlags(Enum v) { - return QFlags(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 -T *SharedMemoryLocation() { - static_assert(N < 4, "Only 4 shared memory locations!"); - return reinterpret_cast(_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 - 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 -inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; } - -template -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 -struct integral_constant { - static constexpr T value = V; - - using value_type = T; - using type = integral_constant; - - constexpr operator value_type() const noexcept { - return (value); - } - - constexpr value_type operator()() const noexcept { - return (value); - } -}; - -using true_type = integral_constant; -using false_type = integral_constant; - -template -struct remove_reference { - using type = T; -}; -template -struct remove_reference { - using type = T; -}; -template -struct remove_reference { - using type = T; -}; - -template -struct is_lvalue_reference : false_type { -}; -template -struct is_lvalue_reference : true_type { -}; - -template -struct is_rvalue_reference : false_type { -}; -template -struct is_rvalue_reference : true_type { -}; - -template -inline constexpr T &&forward(typename remove_reference::type &value) noexcept { - return static_cast(value); -} -template -inline constexpr T &&forward(typename remove_reference::type &&value) noexcept { - static_assert(!is_lvalue_reference::value, "bad forward call"); - return static_cast(value); -} - -template -inline constexpr typename remove_reference::type &&move(T &&value) noexcept { - return static_cast::type&&>(value); -} - -template -void swap_moveable(T &a, T &b) { - T tmp = move(a); - a = move(b); - b = move(tmp); -} - -template -struct remove_const { - using type = T; -}; - -template -struct remove_const { - using type = T; -}; - -template -struct remove_volatile { - using type = T; -}; - -template -struct remove_volatile { - using type = T; -}; - -template -using decay_simple_t = typename remove_const::type>::type>::type; - -template -struct is_same : false_type { -}; - -template -struct is_same : true_type { -}; - -template -struct enable_if { -}; - -template -struct enable_if { - using type = T; -}; - -template -using enable_if_t = typename enable_if::type; - -template -struct add_const { - using type = const T; -}; -template -using add_const_t = typename add_const::type; -template -constexpr add_const_t &as_const(T& t) noexcept { - return t; -} -template -void as_const(const T&&) = delete; - -// This is not full unique_ptr, but at least with std interface. -template -class unique_ptr { -public: - constexpr unique_ptr() noexcept = default; - unique_ptr(const unique_ptr &) = delete; - unique_ptr &operator=(const unique_ptr &) = delete; - - constexpr unique_ptr(std::nullptr_t) { - } - unique_ptr &operator=(std::nullptr_t) noexcept { - reset(); - return (*this); - } - - explicit unique_ptr(T *p) noexcept : _p(p) { - } - - template - unique_ptr(unique_ptr &&other) noexcept : _p(other.release()) { - } - template - unique_ptr &operator=(unique_ptr &&other) noexcept { - reset(other.release()); - return (*this); - } - unique_ptr &operator=(unique_ptr &&other) noexcept { - if (this != &other) { - reset(other.release()); - } - return (*this); - } - - void swap(unique_ptr &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 -inline unique_ptr make_unique(Args&&... args) { - return unique_ptr(new T(forward(args)...)); -} - -template -inline bool operator==(const unique_ptr &a, std::nullptr_t) noexcept { - return !a; -} -template -inline bool operator==(std::nullptr_t, const unique_ptr &b) noexcept { - return !b; -} -template -inline bool operator!=(const unique_ptr &a, std::nullptr_t b) noexcept { - return !(a == b); -} -template -inline bool operator!=(std::nullptr_t a, const unique_ptr &b) noexcept { - return !(a == b); -} - -using _yes = char(&)[1]; -using _no = char(&)[2]; - -template -struct _host { - operator Base*() const; - operator Derived*(); -}; - -template -struct is_base_of { - template - static _yes check(Derived*, T); - static _no check(Base*, int); - - static constexpr bool value = sizeof(check(_host(), int())) == sizeof(_yes); -}; - -} // namespace std_ - -template -T createAndSwap(T &value) { - T result = T(); - std_::swap_moveable(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 -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(data), *e = i + len; i != e; ++i) { - *i = uchar(rand() & 0xFF); - } -} - -template -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 -inline T snap(const T &v, const T &_min, const T &_max) { - return (v < _min) ? _min : ((v > _max) ? _max : v); -} - -template -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 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 - -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(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(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 -inline QSharedPointer MakeShared(Args&&... args) { - return QSharedPointer(new T(std_::forward(args)...)); -} - -// This pointer is used for global non-POD variables that are allocated -// on demand by createIfNull(lambda) and are never automatically freed. -template -class NeverFreedPointer { -public: - NeverFreedPointer() = default; - NeverFreedPointer(const NeverFreedPointer &other) = delete; - NeverFreedPointer &operator=(const NeverFreedPointer &other) = delete; - - template - void createIfNull(U creator) { - if (isNull()) { - reset(creator()); - } - } - - template - void makeIfNull(Args&&... args) { - if (isNull()) { - reset(new T(std_::forward(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 -class StaticNeverFreedPointer { -public: - explicit StaticNeverFreedPointer(T *p) : _p(p) { - } - StaticNeverFreedPointer(const StaticNeverFreedPointer &other) = delete; - StaticNeverFreedPointer &operator=(const StaticNeverFreedPointer &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 -struct CeilDivideMinimumOne { - static const int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0)); -}; - -extern ComponentWrapStruct ComponentWraps[64]; -extern QAtomicInt ComponentIndexLast; - -template -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::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 - bool Has() const { - return (_meta()->offsets[Type::Index()] >= 0); - } - - template - Type *Get() { - return static_cast(_dataptr(_meta()->offsets[Type::Index()])); - } - template - const Type *Get() const { - return static_cast(_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(_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 9305c66945..b8c6c8e531 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 : } 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(source); new (lambda) JustLambda(static_cast(*source_lambda)); } @@ -223,11 +221,9 @@ struct lambda_wrap_helper_copy_impl : } 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(source); new (lambda) JustLambda(static_cast(*source_lambda)); } diff --git a/Telegram/SourceFiles/core/ordered_set.h b/Telegram/SourceFiles/core/ordered_set.h new file mode 100644 index 0000000000..05da1455e5 --- /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 + +// ordered set template based on QMap +template +class OrderedSet { + struct NullType { + }; + using Self = OrderedSet; + using Impl = QMap; + 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 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; + + }; + 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; + + }; + 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 0000000000..add2ecaa02 --- /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 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 0000000000..bc5b0f15ef --- /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 +struct CeilDivideMinimumOne { + static constexpr int Result = ((Value / Denominator) + ((!Value || (Value % Denominator)) ? 1 : 0)); +}; + +extern RuntimeComponentWrapStruct RuntimeComponentWraps[64]; +extern QAtomicInt RuntimeComponentIndexLast; + +template +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::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 + bool Has() const { + return (_meta()->offsets[Type::Index()] >= 0); + } + + template + Type *Get() { + return static_cast(_dataptr(_meta()->offsets[Type::Index()])); + } + template + const Type *Get() const { + return static_cast(_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(_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 0000000000..10eeadbdf1 --- /dev/null +++ b/Telegram/SourceFiles/core/stl_subset.h @@ -0,0 +1,282 @@ +/* +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 + +// 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 +struct integral_constant { + static constexpr T value = V; + + using value_type = T; + using type = integral_constant; + + constexpr operator value_type() const noexcept { + return (value); + } + + constexpr value_type operator()() const noexcept { + return (value); + } +}; + +using true_type = integral_constant; +using false_type = integral_constant; + +template +struct remove_reference { + using type = T; +}; +template +struct remove_reference { + using type = T; +}; +template +struct remove_reference { + using type = T; +}; + +template +struct is_lvalue_reference : false_type { +}; +template +struct is_lvalue_reference : true_type { +}; + +template +struct is_rvalue_reference : false_type { +}; +template +struct is_rvalue_reference : true_type { +}; + +template +inline constexpr T &&forward(typename remove_reference::type &value) noexcept { + return static_cast(value); +} +template +inline constexpr T &&forward(typename remove_reference::type &&value) noexcept { + static_assert(!is_lvalue_reference::value, "bad forward call"); + return static_cast(value); +} + +template +inline constexpr typename remove_reference::type &&move(T &&value) noexcept { + return static_cast::type&&>(value); +} + +template +void swap(T &a, T &b) { + T tmp = move(a); + a = move(b); + b = move(tmp); +} + +template +struct remove_const { + using type = T; +}; + +template +struct remove_const { + using type = T; +}; + +template +struct remove_volatile { + using type = T; +}; + +template +struct remove_volatile { + using type = T; +}; + +template +using decay_simple_t = typename remove_const::type>::type>::type; + +template +struct is_same : false_type { +}; + +template +struct is_same : true_type { +}; + +template +struct enable_if { +}; + +template +struct enable_if { + using type = T; +}; + +template +using enable_if_t = typename enable_if::type; + +template +struct add_const { + using type = const T; +}; +template +using add_const_t = typename add_const::type; +template +constexpr add_const_t &as_const(T& t) noexcept { + return t; +} +template +void as_const(const T&&) = delete; + +// This is not full unique_ptr, but at least with std interface. +template +class unique_ptr { +public: + constexpr unique_ptr() noexcept = default; + unique_ptr(const unique_ptr &) = delete; + unique_ptr &operator=(const unique_ptr &) = delete; + + constexpr unique_ptr(std_::nullptr_t) { + } + unique_ptr &operator=(std_::nullptr_t) noexcept { + reset(); + return (*this); + } + + explicit unique_ptr(T *p) noexcept : _p(p) { + } + + template + unique_ptr(unique_ptr &&other) noexcept : _p(other.release()) { + } + template + unique_ptr &operator=(unique_ptr &&other) noexcept { + reset(other.release()); + return (*this); + } + unique_ptr &operator=(unique_ptr &&other) noexcept { + if (this != &other) { + reset(other.release()); + } + return (*this); + } + + void swap(unique_ptr &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 { + auto old = _p; + _p = nullptr; + return old; + } + + void reset(T *p = nullptr) noexcept { + auto old = _p; + _p = p; + if (old) { + delete old; + } + } + +private: + T *_p = nullptr; + +}; + +template +inline unique_ptr make_unique(Args&&... args) { + return unique_ptr(new T(forward(args)...)); +} + +template +inline bool operator==(const unique_ptr &a, std_::nullptr_t) noexcept { + return !a; +} +template +inline bool operator==(std_::nullptr_t, const unique_ptr &b) noexcept { + return !b; +} +template +inline bool operator!=(const unique_ptr &a, std_::nullptr_t b) noexcept { + return !(a == b); +} +template +inline bool operator!=(std_::nullptr_t a, const unique_ptr &b) noexcept { + return !(a == b); +} + +using _yes = char(&)[1]; +using _no = char(&)[2]; + +template +struct _host { + operator Base*() const; + operator Derived*(); +}; + +template +struct is_base_of { + template + static _yes check(Derived*, T); + static _no check(Base*, int); + + static constexpr bool value = sizeof(check(_host(), int())) == sizeof(_yes); +}; + +inline void *align(size_t alignment, size_t size, void*& ptr, size_t& space) noexcept { +#ifndef OS_MAC_OLD + using std::uintptr_t; +#endif // OS_MAC_OLD + + auto p = reinterpret_cast(ptr); + auto a = (p - 1u + alignment) & -alignment; + auto d = a - p; + if ((size + d) > space) { + return nullptr; + } + space -= d; + return ptr = reinterpret_cast(a); +} + +} // 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 868a5d23f4..4ad8140abd 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 #include @@ -1020,33 +1019,3 @@ MimeType mimeTypeForData(const QByteArray &data) { } return MimeType(QMimeDatabase().mimeTypeForData(data)); } - -struct ComposerMetadatasMap { - QMap 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 0000000000..df4c23af37 --- /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 +inline constexpr size_t arraysize(T(&ArrahSizeHelper)[N]) { + return N; +} + +template +void deleteAndMark(T *&link) { + delete link; + link = reinterpret_cast(0x00000BAD); +} + +template +T *getPointerAndReset(T *&ptr) { + T *result = nullptr; + qSwap(result, ptr); + return result; +} + +template +inline QFlags qFlags(Enum v) { + return QFlags(v); +} + +static const int32 ScrollMax = INT_MAX; + +extern uint64 _SharedMemoryLocation[]; +template +T *SharedMemoryLocation() { + static_assert(N < 4, "Only 4 shared memory locations!"); + return reinterpret_cast(_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 + 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 +inline void accumulate_max(T &a, const T &b) { if (a < b) a = b; } + +template +inline void accumulate_min(T &a, const T &b) { if (a > b) a = b; } + +template +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 +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(data), *e = i + len; i != e; ++i) { + *i = uchar(rand() & 0xFF); + } +} + +template +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 +inline T snap(const T &v, const T &_min, const T &_max) { + return (v < _min) ? _min : ((v > _max) ? _max : v); +} + +template +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 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 + +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(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(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 +inline QSharedPointer MakeShared(Args&&... args) { + return QSharedPointer(new T(std_::forward(args)...)); +} + +// This pointer is used for global non-POD variables that are allocated +// on demand by createIfNull(lambda) and are never automatically freed. +template +class NeverFreedPointer { +public: + NeverFreedPointer() = default; + NeverFreedPointer(const NeverFreedPointer &other) = delete; + NeverFreedPointer &operator=(const NeverFreedPointer &other) = delete; + + template + void createIfNull(U creator) { + if (isNull()) { + reset(creator()); + } + } + + template + void makeIfNull(Args&&... args) { + if (isNull()) { + reset(new T(std_::forward(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 +class StaticNeverFreedPointer { +public: + explicit StaticNeverFreedPointer(T *p) : _p(p) { + } + StaticNeverFreedPointer(const StaticNeverFreedPointer &other) = delete; + StaticNeverFreedPointer &operator=(const StaticNeverFreedPointer &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 87b63fb6a2..170016e560 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -20,9 +20,9 @@ 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 (10008001ULL) +#define BETA_VERSION_MACRO (10008003ULL) constexpr int AppVersion = 10008; constexpr str_const AppVersionStr = "0.10.8"; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 8c9b7007ee..f62bbc31eb 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::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 c9d44ebfb6..db8cefa651 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 MediaOverviewIds; + using MediaOverviewIds = OrderedSet; 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 008eb9b13f..3be1f86650 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 { +struct HistoryMessageVia : public RuntimeComponent { void create(int32 userId); void resize(int32 availw) const; @@ -106,20 +108,20 @@ struct HistoryMessageVia : public BaseComponent { ClickHandlerPtr _lnk; }; -struct HistoryMessageViews : public BaseComponent { +struct HistoryMessageViews : public RuntimeComponent { QString _viewsText; int _views = 0; int _viewsWidth = 0; }; -struct HistoryMessageSigned : public BaseComponent { +struct HistoryMessageSigned : public RuntimeComponent { void create(UserData *from, const QDateTime &date); int maxWidth() const; Text _signature; }; -struct HistoryMessageEdited : public BaseComponent { +struct HistoryMessageEdited : public RuntimeComponent { void create(const QDateTime &editDate, const QDateTime &date); int maxWidth() const; @@ -127,7 +129,7 @@ struct HistoryMessageEdited : public BaseComponent { Text _edited; }; -struct HistoryMessageForwarded : public BaseComponent { +struct HistoryMessageForwarded : public RuntimeComponent { void create(const HistoryMessageVia *via) const; PeerData *_authorOriginal = nullptr; @@ -136,7 +138,7 @@ struct HistoryMessageForwarded : public BaseComponent { mutable Text _text = { 1 }; }; -struct HistoryMessageReply : public BaseComponent { +struct HistoryMessageReply : public RuntimeComponent { HistoryMessageReply &operator=(HistoryMessageReply &&other) { replyToMsgId = other.replyToMsgId; std::swap(replyToMsg, other.replyToMsg); @@ -191,7 +193,7 @@ struct HistoryMessageReply : public BaseComponent { Q_DECLARE_OPERATORS_FOR_FLAGS(HistoryMessageReply::PaintFlags); class ReplyKeyboard; -struct HistoryMessageReplyMarkup : public BaseComponent { +struct HistoryMessageReplyMarkup : public RuntimeComponent { 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 { +struct HistoryMessageDate : public RuntimeComponent { void init(const QDateTime &date); int height() const; @@ -374,7 +376,7 @@ struct HistoryMessageDate : public BaseComponent { // any HistoryItem can have this Interface for // displaying the unread messages bar above the message -struct HistoryMessageUnreadBar : public BaseComponent { +struct HistoryMessageUnreadBar : public RuntimeComponent { 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 a6816c6c3c..813ff67f13 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(); createComponents(captioned != 0); @@ -2560,7 +2560,7 @@ int HistoryWebPage::resizeGetHeight(int width) { return _height; } - _width = qMin(width, _maxw); + _width = width = qMin(width, _maxw); width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); int32 linesMax = 5; @@ -2659,10 +2659,10 @@ void HistoryWebPage::draw(Painter &p, const QRect &r, TextSelection selection, u auto padding = inBubblePadding(); auto tshift = padding.top(); auto bshift = padding.bottom(); + width -= padding.left() + padding.right(); if (_asArticle || (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right())) { bshift += bottomInfoPadding(); } - width -= padding.left() + padding.right(); QRect bar(rtlrect(st::msgPadding.left(), tshift, st::webPageBar, _height - tshift - bshift, _width)); p.fillRect(bar, barfg); @@ -2959,7 +2959,8 @@ void HistoryGame::initDimensions() { _minh = 0; int32 titleMinHeight = _title.isEmpty() ? 0 : _lineHeight; - int32 descMaxLines = (4 + (titleMinHeight ? 0 : 1)); + // enable any count of lines in game description / message + int descMaxLines = 4096; int32 descriptionMinHeight = _description.isEmpty() ? 0 : qMin(_description.minHeight(), descMaxLines * _lineHeight); if (!_title.isEmpty()) { @@ -2993,7 +2994,7 @@ void HistoryGame::initDimensions() { } int HistoryGame::resizeGetHeight(int width) { - _width = qMin(width, _maxw); + _width = width = qMin(width, _maxw); width -= st::msgPadding.left() + st::webPageLeft + st::msgPadding.right(); // enable any count of lines in game description / message @@ -3055,10 +3056,10 @@ void HistoryGame::draw(Painter &p, const QRect &r, TextSelection selection, uint auto padding = inBubblePadding(); auto tshift = padding.top(); auto bshift = padding.bottom(); + width -= padding.left() + padding.right(); if (isBubbleBottom() && _attach && _attach->customInfoLayout() && _attach->currentWidth() + _parent->skipBlockWidth() > width + bubble.left() + bubble.right()) { bshift += bottomInfoPadding(); } - width -= padding.left() + padding.right(); QRect bar(rtlrect(st::msgPadding.left(), tshift, st::webPageBar, _height - tshift - bshift, _width)); p.fillRect(bar, barfg); diff --git a/Telegram/SourceFiles/history/history_media_types.h b/Telegram/SourceFiles/history/history_media_types.h index 1dec2c7462..341f278b6c 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 { +struct HistoryDocumentThumbed : public RuntimeComponent { ClickHandlerPtr _linksavel, _linkcancell; int _thumbw = 0; mutable int _linkw = 0; mutable QString _link; }; -struct HistoryDocumentCaptioned : public BaseComponent { +struct HistoryDocumentCaptioned : public RuntimeComponent { Text _caption = { int(st::msgFileMinWidth) - st::msgPadding.left() - st::msgPadding.right() }; }; -struct HistoryDocumentNamed : public BaseComponent { +struct HistoryDocumentNamed : public RuntimeComponent { QString _name; int _namew = 0; }; @@ -300,7 +300,7 @@ struct HistoryDocumentVoicePlayback { anim::fvalue a_progress; Animation _a_progress; }; -struct HistoryDocumentVoice : public BaseComponent { +struct HistoryDocumentVoice : public RuntimeComponent { HistoryDocumentVoice &operator=(HistoryDocumentVoice &&other) { std::swap(_playback, other._playback); return *this; @@ -313,7 +313,7 @@ struct HistoryDocumentVoice : public BaseComponent { 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.cpp b/Telegram/SourceFiles/history/history_message.cpp index cf0894118e..f47b7e1ff1 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -1968,7 +1968,7 @@ bool HistoryService::preparePinnedText(const QString &from, QString *outText, Li bool HistoryService::prepareGameScoreText(const QString &from, QString *outText, Links *outLinks) { bool result = false; - QString text; + QString gameTitle; ClickHandlerPtr second; auto gamescore = Get(); @@ -1976,20 +1976,25 @@ bool HistoryService::prepareGameScoreText(const QString &from, QString *outText, auto getGameTitle = [item = gamescore->msg, &second]()->QString { if (auto media = item->getMedia()) { if (media->type() == MediaTypeGame) { - return static_cast(media)->game()->title; + second = MakeShared(item, 0, 0); + return textcmdLink(2, static_cast(media)->game()->title); } } return lang(lng_deleted_message); }; - text = lng_action_game_score(lt_from, from, lt_count, gamescore->score, lt_game, getGameTitle()); + gameTitle = getGameTitle(); result = true; } else if (gamescore && gamescore->msgId) { - text = lng_action_game_score(lt_from, from, lt_count, gamescore->score, lt_game, lang(lng_contacts_loading)); + gameTitle = lang(lng_contacts_loading); result = true; } else { - text = lng_action_game_score(lt_from, from, lt_count, gamescore->score, lt_game, lang(lng_deleted_message)); + gameTitle = lang(lng_deleted_message); + } + if (_from->isSelf()) { + *outText = lng_action_game_you_scored(lt_count, gamescore->score, lt_game, gameTitle); + } else { + *outText = lng_action_game_score(lt_from, from, lt_count, gamescore->score, lt_game, gameTitle); } - *outText = text; if (second) { outLinks->push_back(second); } diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index bfefaec4c8..061420f38f 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, public HistoryServiceDependentData { +struct HistoryServicePinned : public RuntimeComponent, public HistoryServiceDependentData { }; -struct HistoryServiceGameScore : public BaseComponent, public HistoryServiceDependentData { +struct HistoryServiceGameScore : public RuntimeComponent, public HistoryServiceDependentData { int score = 0; }; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index ab9824bb39..482b20a37d 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -303,6 +303,10 @@ QString Result::getLayoutDescription() const { return sendData->getLayoutDescription(this); } +// just to make unique_ptr see the destructors. +Result::~Result() { +} + void Result::createPhoto() { if (_photo) return; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h index 09c58aad9e..944b0a8079 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h @@ -74,6 +74,8 @@ public: QString getLayoutTitle() const; QString getLayoutDescription() const; + ~Result(); + private: void createPhoto(); void createDocument(); diff --git a/Telegram/SourceFiles/intro/introsignup.cpp b/Telegram/SourceFiles/intro/introsignup.cpp index 923090a84c..74034244f7 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 2a8e2f33d3..cc36e7d21a 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 1263f2de5e..6b7d655317 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 ea54fa5e0d..fd83ba4220 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 +#include + #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 SomeAllocatedMemory; + + void OperatorNewHandler() { + std::set_new_handler(nullptr); + SomeAllocatedMemory.reset(); + t_assert(!"Could not allocate!"); + } + + void InstallOperatorNewHandler() { + SomeAllocatedMemory = std_::make_unique(); + 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 a8e56c1482..0a3a62d58a 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -959,31 +959,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/media/media_clip_reader.h b/Telegram/SourceFiles/media/media_clip_reader.h index 220632c551..0b3a8a3952 100644 --- a/Telegram/SourceFiles/media/media_clip_reader.h +++ b/Telegram/SourceFiles/media/media_clip_reader.h @@ -171,6 +171,11 @@ private: }; +template +inline ReaderPointer MakeReader(Args&&... args) { + return ReaderPointer(new Reader(std_::forward(args)...)); +} + enum class ProcessResult { Error, Started, diff --git a/Telegram/SourceFiles/mtproto/connection.h b/Telegram/SourceFiles/mtproto/connection.h index dea2c3df3a..89c62fb4bf 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 &ids, const string &states, QVector &acked); + void handleMsgsStates(const QVector &ids, const std::string &states, QVector &acked); void clearMessages(); diff --git a/Telegram/SourceFiles/mtproto/core_types.h b/Telegram/SourceFiles/mtproto/core_types.h index 846b8ef712..e48a952be9 100644 --- a/Telegram/SourceFiles/mtproto/core_types.h +++ b/Telegram/SourceFiles/mtproto/core_types.h @@ -665,7 +665,7 @@ class MTPDstring : public mtpDataImpl { 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(Type::Flag::MAX_FIELD) < static_cast(Typ "MTProto flags conflict with client side flags!"); \ inline Type::Flags qFlags(Type##_ClientFlag v) { return Type::Flags(static_cast(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 15741c44cb..85aa9c6866 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 DcOptions; diff --git a/Telegram/SourceFiles/mtproto/file_download.cpp b/Telegram/SourceFiles/mtproto/file_download.cpp index 513fbfd8e0..349380c9c3 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 b59deec79e..5e1bcbf4f4 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 70f5561a50..6e80a36198 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 0705e5e216..af49c4bb8c 100644 --- a/Telegram/SourceFiles/overview/overview_layout.h +++ b/Telegram/SourceFiles/overview/overview_layout.h @@ -156,7 +156,7 @@ protected: }; -struct Info : public BaseComponent { +struct Info : public RuntimeComponent { int top = 0; }; diff --git a/Telegram/SourceFiles/passcodewidget.cpp b/Telegram/SourceFiles/passcodewidget.cpp index ef4b8c9edb..1a2688f00e 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 0d9331782b..a9a96d9f0c 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/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index bfc1baba09..2ed9fd9b75 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "localstorage.h" #include "passcodewidget.h" +#include "history/history_location_manager.h" #include diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index a9ab6f89ad..69e8380a70 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 ac25cbd539..518bf50398 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 d4c7ed621c..41c554fad0 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 #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 76d1c6c2f9..31f6acb083 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 Names; + using Names = OrderedSet; Names names; // for filtering - typedef QSet NameFirstChars; + using NameFirstChars = OrderedSet; NameFirstChars chars; enum LoadedStatus { diff --git a/Telegram/SourceFiles/sysbuttons.cpp b/Telegram/SourceFiles/sysbuttons.cpp index 7b429cb867..859e5b9caa 100644 --- a/Telegram/SourceFiles/sysbuttons.cpp +++ b/Telegram/SourceFiles/sysbuttons.cpp @@ -92,9 +92,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 537c17b181..784d6900d4 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 SysBtn : public Button { public: SysBtn(QWidget *parent, const style::sysButton &st, const QString &text = QString()); diff --git a/Telegram/SourceFiles/title.cpp b/Telegram/SourceFiles/title.cpp index 07b50cd6b6..4279df77d8 100644 --- a/Telegram/SourceFiles/title.cpp +++ b/Telegram/SourceFiles/title.cpp @@ -385,23 +385,23 @@ 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 || (_player && _player->geometry().contains(p)) - || (_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)) @@ -409,9 +409,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.cpp b/Telegram/SourceFiles/ui/animation.cpp index 0fd8b79959..88d79b43f1 100644 --- a/Telegram/SourceFiles/ui/animation.cpp +++ b/Telegram/SourceFiles/ui/animation.cpp @@ -35,11 +35,6 @@ ReaderPointer::~ReaderPointer() { _pointer = nullptr; } -class Tmp; -void f(Tmp *t) { - delete t; -} - } // namespace Clip } // namespace Media diff --git a/Telegram/SourceFiles/ui/animation.h b/Telegram/SourceFiles/ui/animation.h index dc9e7b83a5..6842c55a7f 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) { } @@ -77,11 +77,6 @@ private: }; -template -inline ReaderPointer MakeReader(Args&&... args) { - return ReaderPointer(new Reader(std_::forward(args)...)); -} - class Manager; enum Notification { diff --git a/Telegram/SourceFiles/ui/flatcheckbox.h b/Telegram/SourceFiles/ui/flatcheckbox.h index 64d59c24b9..ea43ce09d1 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 f54112647c..9cf8be01f2 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -310,7 +310,7 @@ private: template 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 &other) = delete; ChildWidget &operator=(const ChildWidget &other) = delete; - ChildWidget &operator=(std::nullptr_t) { + ChildWidget &operator=(std_::nullptr_t) { _widget = nullptr; return *this; } diff --git a/Telegram/build/version b/Telegram/build/version index a56338061e..37cdddf1e0 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -3,4 +3,4 @@ AppVersionStrMajor 0.10 AppVersionStrSmall 0.10.8 AppVersionStr 0.10.8 AlphaChannel 0 -BetaVersion 10008001 +BetaVersion 10008003 diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index 04652dc1e4..b808171e06 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -192,7 +192,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', @@ -201,8 +200,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',