diff --git a/.gitignore b/.gitignore index 0cc39366d..baa529015 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,8 @@ /out/ -/Debug/ -/Release/ -/Deploy/ +Debug/ +Release/ /ThirdParty/ /Telegram/build/target -/Telegram/GeneratedFiles/ -/Telegram/SourceFiles/art/grid.png -/Telegram/SourceFiles/art/grid_125x.png -/Telegram/SourceFiles/art/grid_150x.png -/Telegram/SourceFiles/art/grid_200x.png -/Telegram/SourceFiles/art/sprite_125x.png -/Telegram/SourceFiles/art/sprite_150x.png -/Telegram/Resources/art/grid.png -/Telegram/Resources/art/grid_125x.png -/Telegram/Resources/art/grid_150x.png -/Telegram/Resources/art/grid_200x.png -/Telegram/Resources/art/sprite_125x.png -/Telegram/Resources/art/sprite_150x.png -/Telegram/Debug/ -/Telegram/Release/ /Telegram/tests/ /Telegram/gyp/tests/*.test /Telegram/out/ @@ -32,7 +16,6 @@ *.VC.db *.aps *.xcodeproj -/Win32/ ipch/ .vs/ diff --git a/.gitmodules b/.gitmodules index e292cfd38..f51e8e319 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,15 +10,42 @@ [submodule "Telegram/ThirdParty/Catch"] path = Telegram/ThirdParty/Catch url = https://github.com/philsquared/Catch -[submodule "Telegram/ThirdParty/crl"] - path = Telegram/ThirdParty/crl - url = https://github.com/telegramdesktop/crl.git [submodule "Telegram/ThirdParty/xxHash"] path = Telegram/ThirdParty/xxHash url = https://github.com/Cyan4973/xxHash.git [submodule "Telegram/ThirdParty/rlottie"] path = Telegram/ThirdParty/rlottie - url = https://github.com/john-preston/rlottie + url = https://github.com/desktop-app/rlottie.git [submodule "Telegram/ThirdParty/lz4"] path = Telegram/ThirdParty/lz4 url = https://github.com/lz4/lz4.git +[submodule "Telegram/lib_crl"] + path = Telegram/lib_crl + url = https://github.com/desktop-app/lib_crl.git +[submodule "Telegram/lib_rpl"] + path = Telegram/lib_rpl + url = https://github.com/desktop-app/lib_rpl.git +[submodule "Telegram/lib_base"] + path = Telegram/lib_base + url = https://github.com/desktop-app/lib_base.git +[submodule "Telegram/gyp/helpers"] + path = Telegram/gyp/helpers + url = https://github.com/desktop-app/gyp_helpers.git +[submodule "Telegram/codegen"] + path = Telegram/codegen + url = https://github.com/desktop-app/codegen.git +[submodule "Telegram/lib_ui"] + path = Telegram/lib_ui + url = https://github.com/desktop-app/lib_ui.git +[submodule "Telegram/lib_rlottie"] + path = Telegram/lib_rlottie + url = https://github.com/desktop-app/lib_rlottie.git +[submodule "Telegram/lib_lottie"] + path = Telegram/lib_lottie + url = https://github.com/desktop-app/lib_lottie.git +[submodule "Telegram/lib_tl"] + path = Telegram/lib_tl + url = https://github.com/desktop-app/lib_tl.git +[submodule "Telegram/lib_spellcheck"] + path = Telegram/lib_spellcheck + url = https://github.com/desktop-app/lib_spellcheck diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style deleted file mode 100644 index a6cd8f0b2..000000000 --- a/Telegram/Resources/basic.style +++ /dev/null @@ -1,303 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -using "colors.palette"; - -TextPalette { - linkFg: color; - monoFg: color; - selectBg: color; - selectFg: color; - selectLinkFg: color; - selectMonoFg: color; - selectOverlay: color; -} - -TextStyle { - font: font; - linkFont: font; - linkFontOver: font; - lineHeight: pixels; -} - -semibold: "Open Sans Semibold"; - -fsize: 13px; -normalFont: font(fsize); -semiboldFont: font(fsize semibold); -boxFontSize: 14px; -boxTextFont: font(boxFontSize); - -emojiImgSize: 18px; // exceptional value for retina -emojiSize: 18px; -emojiPadding: 1px; - -lineWidth: 1px; - -defaultTextPalette: TextPalette { - linkFg: windowActiveTextFg; - monoFg: msgInMonoFg; - selectBg: msgInBgSelected; - selectFg: transparent; // use painter current pen instead - selectLinkFg: historyLinkInFgSelected; - selectMonoFg: msgInMonoFgSelected; - selectOverlay: msgSelectOverlay; -} -defaultTextStyle: TextStyle { - font: normalFont; - linkFont: normalFont; - linkFontOver: font(fsize underline); - lineHeight: 0px; -} -semiboldTextStyle: TextStyle(defaultTextStyle) { - font: semiboldFont; - linkFont: semiboldFont; - linkFontOver: font(fsize semibold underline); -} - -shadowToggleDuration: 200; - -slideDuration: 240; -slideShift: 100px; -slideShadow: icon {{ "slide_shadow", slideFadeOutShadowFg }}; - -slideWrapDuration: 150; -fadeWrapDuration: 200; - -linkCropLimit: 360px; -linkFont: normalFont; -linkOverFont: font(fsize underline); - -roundRadiusLarge: 6px; -roundRadiusSmall: 3px; - -dateRadius: roundRadiusLarge; -buttonRadius: roundRadiusSmall; - -setLittleSkip: 9px; - -noContactsHeight: 100px; -noContactsFont: font(fsize); -noContactsColor: windowSubTextFg; - -activeFadeInDuration: 500; -activeFadeOutDuration: 3000; - -msgMaxWidth: 430px; -msgFont: font(fsize); -msgNameFont: semiboldFont; -msgNameStyle: semiboldTextStyle; -msgServiceFont: semiboldFont; -msgServiceNameFont: semiboldFont; -msgServicePhotoWidth: 100px; -msgDateFont: font(13px); -msgMinWidth: 160px; -msgPhotoSize: 33px; -msgPhotoSkip: 40px; -msgPadding: margins(13px, 7px, 13px, 8px); -msgMargin: margins(16px, 6px, 56px, 2px); -msgMarginTopAttached: 1px; -msgLnkPadding: 2px; // for media open / save links -msgShadow: 2px; - -msgReplyPadding: margins(6px, 6px, 11px, 6px); -msgReplyBarPos: point(1px, 0px); -msgReplyBarSize: size(2px, 36px); -msgReplyBarSkip: 10px; -msgServicePadding: margins(12px, 3px, 12px, 4px); -msgServiceMargin: margins(10px, 10px, 10px, 2px); - -msgDateSpace: 12px; -msgDateDelta: point(2px, 5px); - -msgDateImgDelta: 4px; -msgDateImgPadding: point(8px, 2px); -msgDateImgCheckSpace: 4px; - -messageTextStyle: defaultTextStyle; -msgDateTextStyle: defaultTextStyle; -serviceTextPalette: TextPalette(defaultTextPalette) { - linkFg: msgServiceFg; - monoFg: msgServiceFg; - selectBg: msgServiceBgSelected; - selectFg: msgServiceFg; - selectLinkFg: msgServiceFg; - selectMonoFg: msgServiceFg; - selectOverlay: msgServiceBgSelected; -} -serviceTextStyle: TextStyle(defaultTextStyle) { - font: msgServiceFont; - linkFont: msgServiceFont; - linkFontOver: font(fsize semibold underline); -} -inTextPalette: TextPalette(defaultTextPalette) { - linkFg: historyLinkInFg; - monoFg: msgInMonoFg; - selectBg: msgInBgSelected; - selectFg: historyTextInFgSelected; - selectLinkFg: historyLinkInFgSelected; - selectMonoFg: msgInMonoFgSelected; - selectOverlay: msgSelectOverlay; -} -inTextPaletteSelected: TextPalette(inTextPalette) { - linkFg: historyLinkInFgSelected; - monoFg: msgInMonoFgSelected; -} -outTextPalette: TextPalette(defaultTextPalette) { - linkFg: historyLinkOutFg; - monoFg: msgOutMonoFg; - selectBg: msgOutBgSelected; - selectFg: historyTextOutFgSelected; - selectLinkFg: historyLinkOutFgSelected; - selectMonoFg: msgOutMonoFgSelected; - selectOverlay: msgSelectOverlay; -} -outTextPaletteSelected: TextPalette(outTextPalette) { - linkFg: historyLinkOutFgSelected; - monoFg: msgOutMonoFgSelected; -} -fwdTextStyle: TextStyle(semiboldTextStyle) { - linkFontOver: semiboldFont; -} -inFwdTextPalette: TextPalette(defaultTextPalette) { - linkFg: msgInServiceFg; -} -outFwdTextPalette: TextPalette(defaultTextPalette) { - linkFg: msgOutServiceFg; -} -inFwdTextPaletteSelected: TextPalette(defaultTextPalette) { - linkFg: msgInServiceFgSelected; -} -outFwdTextPaletteSelected: TextPalette(defaultTextPalette) { - linkFg: msgOutServiceFgSelected; -} -inReplyTextPalette: TextPalette(inTextPalette) { - linkFg: msgInDateFg; -} -inReplyTextPaletteSelected: TextPalette(inTextPaletteSelected) { - linkFg: msgInDateFgSelected; -} -outReplyTextPalette: TextPalette(outTextPalette) { - linkFg: msgOutDateFg; -} -outReplyTextPaletteSelected: TextPalette(outTextPaletteSelected) { - linkFg: msgOutDateFgSelected; -} -imgReplyTextPalette: TextPalette(defaultTextPalette) { - linkFg: msgImgReplyBarColor; -} -inSemiboldPalette: TextPalette(inTextPalette) { - linkFg: msgInServiceFg; - selectFg: msgInServiceFgSelected; - selectLinkFg: msgInServiceFgSelected; -} -outSemiboldPalette: TextPalette(outTextPalette) { - linkFg: msgOutServiceFg; - selectFg: msgOutServiceFgSelected; - selectLinkFg: msgOutServiceFgSelected; -} -historyComposeAreaPalette: TextPalette(defaultTextPalette) { - linkFg: historyComposeAreaFgService; -} - -mediaCaptionSkip: 5px; -mediaInBubbleSkip: 5px; -mediaThumbSize: 48px; -mediaNameTop: 3px; -mediaDetailsShift: 3px; -mediaUnreadSize: 7px; -mediaUnreadSkip: 5px; -mediaUnreadTop: 6px; - -mediaInPalette: TextPalette(defaultTextPalette) { - linkFg: mediaInFg; -} -mediaInPaletteSelected: TextPalette(defaultTextPalette) { - linkFg: mediaInFgSelected; -} - -textRectMargins: margins(-2px, -1px, -2px, -1px); - -searchedBarHeight: 32px; -searchedBarFont: normalFont; -searchedBarPosition: point(17px, 7px); - -smallCloseIcon: icon {{ "simple_close", smallCloseIconFg }}; -smallCloseIconOver: icon {{ "simple_close", smallCloseIconFgOver }}; -dialogsForwardCancelIcon: icon {{ "simple_close", dialogsForwardFg }}; - -emojiTextFont: font(15px); -emojiReplaceWidth: 52px; -emojiReplaceHeight: 56px; -emojiReplaceInnerHeight: 42px; -emojiReplacePadding: 14px; - -dragFont: font(28px semibold); -dragSubfont: font(20px semibold); -dragColor: windowSubTextFg; -dragDropColor: windowActiveTextFg; - -dragMargin: margins(0px, 10px, 0px, 10px); -dragPadding: margins(20px, 10px, 20px, 10px); - -dragHeight: 72px; - -radialSize: size(50px, 50px); -radialLine: 3px; -radialDuration: 350; -radialPeriod: 3000; - -youtubeIcon: icon { - { "media_youtube_play_bg", youtubePlayIconBg }, - { "media_youtube_play", youtubePlayIconFg, point(24px, 12px) }, -}; -videoIcon: icon { - { "media_video_play_bg", videoPlayIconBg }, - { "media_video_play", videoPlayIconFg, point(12px, 12px) }, -}; -locationSize: size(320px, 240px); - -mediaPlayerSuppressDuration: 150; - -botDescSkip: 8px; - -inlineResultsLeft: 11px; -inlineResultsSkip: 3px; -inlineMediaHeight: 96px; -inlineThumbSize: 64px; -inlineThumbSkip: 10px; -inlineTitleFg: windowFg; -inlineDescriptionFg: windowSubTextFg; -inlineRowMargin: 6px; -inlineRowBorder: 1px; -inlineRowBorderFg: shadowFg; -inlineRowFileNameTop: 2px; -inlineRowFileDescriptionTop: 23px; -inlineResultsMinWidth: 48px; -inlineDurationMargin: 3px; - -toastTextStyle: defaultTextStyle; -toastMaxWidth: 480px; -toastMinMargin: 13px; -toastPadding: margins(19px, 13px, 19px, 12px); -toastFadeInDuration: 200; -toastFadeOutDuration: 1000; - -historyReplyCancelIcon: icon {{ "box_button_close", historyReplyCancelFg }}; -historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }}; -boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }}; -boxTitleCloseIconOver: icon {{ "box_button_close", boxTitleCloseFgOver }}; - -notifyFadeRight: icon {{ "fade_horizontal", notificationBg }}; - -stickerIconLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }}; -stickerIconRight: icon {{ "fade_horizontal", emojiPanCategories }}; - -emojiSuggestionsFadeLeft: icon {{ "fade_horizontal-flip_horizontal", boxBg }}; -emojiSuggestionsFadeRight: icon {{ "fade_horizontal", boxBg }}; - -transparentPlaceholderSize: 4px; diff --git a/Telegram/Resources/colors.palette b/Telegram/Resources/colors.palette deleted file mode 100644 index 82473313e..000000000 --- a/Telegram/Resources/colors.palette +++ /dev/null @@ -1,559 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ - -// basic -windowBg: #ffffff; // white: fallback for background -windowFg: #000000; // black: fallback for text -windowBgOver: #f1f1f1; // light gray: fallback for background with mouse over -windowBgRipple: #e5e5e5; // darker gray: fallback for ripple effect -windowFgOver: windowFg; // black: fallback for text with mouse over -windowSubTextFg: #999999; // gray: fallback for additional text -windowSubTextFgOver: #919191; // darker gray: fallback for additional text with mouse over -windowBoldFg: #222222; // dark gray: fallback for bold text -windowBoldFgOver: #222222; // dark gray: fallback for bold text with mouse over -windowBgActive: #40a7e3; // bright blue: fallback for blue filled active areas -windowFgActive: #ffffff; // white: fallback for text on active areas -windowActiveTextFg: #168acd; // online blue: fallback for active text like online status -windowShadowFg: #000000; // black: fallback for shadow -windowShadowFgFallback: #f1f1f1; // gray: fallback for shadow without opacity - -shadowFg: #00000018; // most shadows (including opacity) -slideFadeOutBg: #0000003c; // slide animation (chat to profile) fade out filling -slideFadeOutShadowFg: windowShadowFg; // slide animation (chat to profile) fade out right section shadow - -imageBg: #000000; // image background fallback (when photo size is less than minimum allowed) -imageBgTransparent: #ffffff; // image background when displaying an image with opacity where no opacity is needed - -// widgets -activeButtonBg: windowBgActive; // default active button background -activeButtonBgOver: #39a5db; // default active button background with mouse over -activeButtonBgRipple: #2095d0; // default active button ripple effect -activeButtonFg: windowFgActive; // default active button text -activeButtonFgOver: activeButtonFg; // default active button text with mouse over -activeButtonSecondaryFg: #cceeff; // default active button additional text (selected messages counter in forward / delete buttons) -activeButtonSecondaryFgOver: activeButtonSecondaryFg; // default active button additional text with mouse over -activeLineFg: #37a1de; // default active line (like code input field bottom border when you log in and field is focused) -activeLineFgError: #e48383; // default active line for error state (like code input field bottom border when you log in and you've entered incorrect code) - -lightButtonBg: windowBg; // default light button background (like buttons in boxes) -lightButtonBgOver: #e3f1fa; // default light button background with mouse over -lightButtonBgRipple: #c9e4f6; // default light button ripple effect -lightButtonFg: windowActiveTextFg; // default light button text -lightButtonFgOver: lightButtonFg; // default light button text with mouse over - -attentionButtonFg: #d14e4e; // default attention button text (like confirm button on log out) -attentionButtonFgOver: #d14e4e; // default attention button text with mouse over -attentionButtonBgOver: #fcdfde; // default attention button background with mouse over -attentionButtonBgRipple: #f4c3c2; // default attention button ripple effect - -menuBg: windowBg; // default popup menu background -menuBgOver: windowBgOver; // default popup menu item background with mouse over -menuBgRipple: windowBgRipple; // default popup menu item ripple effect -menuIconFg: #a8a8a8; // default popup menu item icon (like main menu) -menuIconFgOver: #999999; // default popup menu item icon with mouse over -menuSubmenuArrowFg: #373737; // default popup menu submenu arrow icon (like in message field context menu in case of RTL system language) -menuFgDisabled: #cccccc; // default popup menu item disabled text (like unavailable items in message field context menu) -menuSeparatorFg: #f1f1f1; // default popup menu separator (like in message field context menu) - -scrollBarBg: #00000053; // default scroll bar current rectangle, the bar itself (like in chats list) -scrollBarBgOver: #0000007a; // default scroll bar current rectangle with mouse over it -scrollBg: #0000001a; // default scroll bar background -scrollBgOver: #0000002c; // default scroll bar background with mouse over the scroll bar - -smallCloseIconFg: #c7c7c7; // small X icon (like in Show all sessions box to the right for sessions termination) -smallCloseIconFgOver: #a3a3a3; // small X icon with mouse over - -radialFg: windowFgActive; // default radial loader line (like in Media Viewer when loading a photo) -radialBg: #00000056; // default radial loader background (like in Media Viewer when loading a photo) - -placeholderFg: windowSubTextFg; // default input field placeholder when field is not focused (like in phone input field when you log in) -placeholderFgActive: #aaaaaa; // default input field placeholder when field is focused -inputBorderFg: #e0e0e0; // default input field bottom border (like in code input field when you log in and field is not focused) -filterInputBorderFg: #54c3f3; // default rounded input field border (like in chats list search field when field is focused) -filterInputActiveBg: windowBg; // default rounded input field active background (like in chats list search field when field is focused) -filterInputInactiveBg: windowBgOver; // default rounded input field inactive background (like in chats list search field when field is inactive) -checkboxFg: #b3b3b3; // default unchecked checkbox rounded rectangle - -botKbBg: menuBgOver; // bot keyboard button background -botKbDownBg: menuBgRipple; // bot keyboard button ripple effect -botKbColor: windowBoldFgOver; // bot keyboard button text - -sliderBgInactive: #e1eaef; // default slider not active bar (like in Settings when you choose interface scale or custom notifications count) -sliderBgActive: windowBgActive; // default slider active bar (like in Settings when you choose interface scale or custom notifications count) - -tooltipBg: #eef2f5; // tooltip background (like when you put mouse over the message timestamp and wait) -tooltipFg: #5d6c80; // tooltip text -tooltipBorderFg: #c9d1db; // tooltip border - -// custom title bar for Windows and macOS -titleShadow: #00000003; // one pixel line shadow at the bottom of custom window title -titleBg: windowBgOver; // custom window title background when window is inactive -titleBgActive: titleBg; // custom window title background when window is active -titleButtonBg: titleBg; // custom window title minimize/maximize/restore button background when window is inactive (Windows only) -titleButtonFg: #ababab; // custom window title minimize/maximize/restore button icon when window is inactive (Windows only) -titleButtonBgOver: #e5e5e5; // custom window title minimize/maximize/restore button background with mouse over when window is inactive (Windows only) -titleButtonFgOver: #9a9a9a; // custom window title minimize/maximize/restore button icon with mouse over when window is inactive (Windows only) -titleButtonBgActive: titleButtonBg; // custom window title minimize/maximize/restore button background when window is active (Windows only) -titleButtonFgActive: titleButtonFg; // custom window title minimize/maximize/restore button icon when window is active (Windows only) -titleButtonBgActiveOver: titleButtonBgOver; // custom window title minimize/maximize/restore button background with mouse over when window is active (Windows only) -titleButtonFgActiveOver: titleButtonFgOver; // custom window title minimize/maximize/restore button icon with mouse over when window is active (Windows only) -titleButtonCloseBg: titleButtonBg; // custom window title close button background when window is inactive (Windows only) -titleButtonCloseFg: titleButtonFg; // custom window title close button icon when window is inactive (Windows only) -titleButtonCloseBgOver: #e81123; // custom window title close button background with mouse over when window is inactive (Windows only) -titleButtonCloseFgOver: windowFgActive; // custom window title close button icon with mouse over when window is inactive (Windows only) -titleButtonCloseBgActive: titleButtonCloseBg; // custom window title close button background when window is active (Windows only) -titleButtonCloseFgActive: titleButtonCloseFg; // custom window title close button icon when window is active (Windows only) -titleButtonCloseBgActiveOver: titleButtonCloseBgOver; // custom window title close button background with mouse over when window is active (Windows only) -titleButtonCloseFgActiveOver: titleButtonCloseFgOver; // custom window title close button icon with mouse over when window is active (Windows only) -titleFg: #acacac; // custom window title text when window is inactive (macOS only) -titleFgActive: #3e3c3e; // custom window title text when window is active (macOS only) - -// tray icon -trayCounterBg: #f23c34; // tray icon counter background -trayCounterBgMute: #888888; // tray icon counter background if all unread messages are muted -trayCounterFg: #ffffff; // tray icon counter text -trayCounterBgMacInvert: #ffffff; // tray icon counter background when tray icon is pressed or when dark theme of macOS is used (macOS only) -trayCounterFgMacInvert: #ffffff01; // tray icon counter text when tray icon is pressed or when dark theme of macOS is used (macOS only) - -// layers -layerBg: #0000007f; // box and main menu background layer fade - -cancelIconFg: menuIconFg; // default for settings close icon and box search cancel icon -cancelIconFgOver: menuIconFgOver; // default for settings close icon and box search cancel icon with mouse over - -// boxes -boxBg: windowBg; // box background -boxTextFg: windowFg; // box text -boxTextFgGood: #4ab44a; // accepted box text (like when choosing username that is not occupied) -boxTextFgError: #d84d4d; // rejecting box text (like when choosing username that is occupied) -boxTitleFg: #404040; // box title text -boxSearchBg: boxBg; // box search field background (like in contacts box) - -boxTitleAdditionalFg: #808080; // box title additional text (like in create group box when you see chosen members count) -boxTitleCloseFg: cancelIconFg; // settings close icon and box search cancel icon (like in contacts box) -boxTitleCloseFgOver: cancelIconFgOver; // settings close icon and box search cancel icon (like in contacts box) with mouse over - -//boxSearchCancelIconFg: cancelIconFg; // search cancel X button icon (like in contacts box) (not implemented yet) -//boxSearchCancelIconFgOver: cancelIconFgOver; // search cancel X button icon with mouse over (not implemented yet) - -membersAboutLimitFg: windowSubTextFgOver; // text in channel members box about the limit (max 200 last members are shown) - -contactsBg: windowBg; // contacts (and some other) box row background -contactsBgOver: windowBgOver; // contacts (and some other) box row background with mouse over -contactsNameFg: boxTextFg; // contacts (and some other) box row name text -contactsStatusFg: windowSubTextFg; // contacts (and some other) box row additional text (like last seen stamp) -contactsStatusFgOver: windowSubTextFgOver; // contacts (and some other) box row additional text (like last seen stamp) with mouse over -contactsStatusFgOnline: windowActiveTextFg; // contacts (and some other) box row active additional text (like online status) - -photoCropFadeBg: layerBg; // avatar crop box fade background (when choosing a new photo in Settings or for a group) -photoCropPointFg: #ffffff7f; // avatar crop box corner rectangles (when choosing a new photo in Settings or for a group) - -callArrowFg: #2ab32a | boxTextFgGood; // received phone call arrow (in calls list box) -callArrowMissedFg: #dd5b4a | boxTextFgError; // missed phone call arrow (in calls list box) - -// intro -introBg: windowBg; // login background -introTitleFg: windowBoldFg; // login title text -introDescriptionFg: windowSubTextFg; // login description text -introErrorFg: windowSubTextFg; // login error text (like when providing a wrong log in code) - -introCoverTopBg: #0f89d0; // intro gradient top (from) -introCoverBottomBg: #39b0f0; // intro gradient bottom (to) -introCoverIconsFg: #5ec6ff; // intro cloud graphics -introCoverPlaneTrace: #5ec6ff69; // intro plane traces -introCoverPlaneInner: #c6d8e8; // intro plane part -introCoverPlaneOuter: #a1bed4; // intro plane part -introCoverPlaneTop: #ffffff; // intro plane part - -// dialogs -dialogsMenuIconFg: menuIconFg; // main menu and lock telegram icon -dialogsMenuIconFgOver: menuIconFgOver; // main menu and lock telegram icon with mouse over - -dialogsBg: windowBg; // chat list background -dialogsNameFg: windowBoldFg; // chat list name text -dialogsChatIconFg: dialogsNameFg; // chat list group or channel icon -dialogsDateFg: windowSubTextFg; // chat list date text -dialogsTextFg: windowSubTextFg; // chat list message text -dialogsTextFgService: windowActiveTextFg; // chat list group sender name text (or media message type text) -dialogsDraftFg: #dd4b39; // chat list draft label -dialogsVerifiedIconBg: windowBgActive; // chat list verified icon background -dialogsVerifiedIconFg: windowFgActive; // chat list verified icon check -dialogsSendingIconFg: #c1c1c1; // chat list sending message icon (clock) -dialogsSentIconFg: #5dc452; // chat list sent message tick / double tick icon -dialogsUnreadBg: windowBgActive; // chat list unread badge background for not muted chat -dialogsUnreadBgMuted: #bbbbbb; // chat list unread badge background for muted chat -dialogsUnreadFg: windowFgActive; // chat list unread badge text -dialogsArchiveFg: #525252 | dialogsNameFg; // chat list archive name text -dialogsOnlineBadgeFg: #4dc920 | dialogsUnreadBg; // chat list online status -dialogsScamFg: dialogsDraftFg; // chat list scam label - -dialogsBgOver: windowBgOver; // chat list background with mouse over -dialogsNameFgOver: windowBoldFgOver; // chat list name text with mouse over -dialogsChatIconFgOver: dialogsNameFgOver; // chat list group or channel icon with mouse over -dialogsDateFgOver: windowSubTextFgOver; // chat list date text with mouse over -dialogsTextFgOver: windowSubTextFgOver; // chat list message text with mouse over -dialogsTextFgServiceOver: dialogsTextFgService; // chat list group sender name text with mouse over -dialogsDraftFgOver: dialogsDraftFg; // chat list draft label with mouse over -dialogsVerifiedIconBgOver: dialogsVerifiedIconBg; // chat list verified icon background with mouse over -dialogsVerifiedIconFgOver: dialogsVerifiedIconFg; // chat list verified icon check with mouse over -dialogsSendingIconFgOver: dialogsSendingIconFg; // chat list sending message icon (clock) with mouse over -dialogsSentIconFgOver: dialogsSentIconFg; // chat list sent message tick / double tick icon with mouse over -dialogsUnreadBgOver: dialogsUnreadBg; // chat list unread badge background for not muted chat with mouse over -dialogsUnreadBgMutedOver: dialogsUnreadBgMuted; // chat list unread badge background for muted chat with mouse over -dialogsUnreadFgOver: dialogsUnreadFg; // chat list unread badge text with mouse over -dialogsArchiveFgOver: #525252 | dialogsNameFgOver; // chat list archive name text with mouse over -dialogsScamFgOver: dialogsDraftFgOver; // chat list scam label with mouse over - -dialogsBgActive: #419fd9; // chat list background for current (active) chat -dialogsNameFgActive: windowFgActive; // chat list name text for current (active) chat -dialogsChatIconFgActive: dialogsNameFgActive; // chat list group or channel icon for current (active) chat -dialogsDateFgActive: windowFgActive; // chat list date text for current (active) chat -dialogsTextFgActive: windowFgActive; // chat list message text for current (active) chat -dialogsTextFgServiceActive: dialogsTextFgActive; // chat list group sender name text for current (active) chat -dialogsDraftFgActive: #c6e1f7; // chat list draft label for current (active) chat -dialogsVerifiedIconBgActive: dialogsTextFgActive; // chat list verified icon background for current (active) chat -dialogsVerifiedIconFgActive: dialogsBgActive; // chat list verified icon check for current (active) chat -dialogsSendingIconFgActive: #ffffff99; // chat list sending message icon (clock) for current (active) chat -dialogsSentIconFgActive: dialogsTextFgActive; // chat list sent message tick / double tick icon for current (active) chat -dialogsUnreadBgActive: dialogsTextFgActive; // chat list unread badge background for not muted chat for current (active) chat -dialogsUnreadBgMutedActive: dialogsDraftFgActive; // chat list unread badge background for muted chat for current (active) chat -dialogsUnreadFgActive: dialogsBgActive; // chat list unread badge text for current (active) chat -dialogsOnlineBadgeFgActive: #ffffff; // chat list online status for current (active) chat -dialogsScamFgActive: dialogsDraftFgActive; // chat list scam label for current (active) chat - -dialogsRippleBg: windowBgRipple; // chat list background ripple effect -dialogsRippleBgActive: activeButtonBgRipple; // chat list background ripple effect for current (active) chat - -dialogsForwardBg: dialogsBgActive; // forwarding panel background (when forwarding messages in the smallest window size) -dialogsForwardFg: dialogsNameFgActive; // forwarding panel text (when forwarding messages in the smallest window size) - -searchedBarBg: windowBgOver; // search results bar background (in chats list, contacts box..) -searchedBarFg: windowSubTextFgOver; // search results bar text (in chats list, contacts box..) - -// history -topBarBg: windowBg; // top bar background (in chat view, media overview..) - -emojiPanBg: windowBg; // emoji panel background -emojiPanCategories: #f7f7f7 | windowBg; // emoji panel categories background -emojiPanHeaderFg: windowSubTextFg; // emoji panel section header text -emojiPanHeaderBg: #fffffff2 | emojiPanBg; // emoji panel section header background -emojiIconFg: checkboxFg; // emoji category icon -emojiIconFgActive: windowBgActive; // active emoji category icon -stickerPanDeleteBg: #000000ff; // delete X button background for custom sent stickers in stickers panel (legacy) -stickerPanDeleteFg: windowFgActive; // delete X button icon for custom sent stickers in stickers panel (legacy) -stickerPreviewBg: #ffffffb0; // sticker and GIF preview background (when you press and hold on a sticker) - -historyTextInFg: windowFg; // inbox message text -historyTextInFgSelected: historyTextInFg; // inbox message selected text or text in a selected message -historyTextOutFg: windowFg; // outbox message text -historyTextOutFgSelected: historyTextOutFg; // outbox message selected text or text in a selected message -historyLinkInFg: windowActiveTextFg; // inbox message link -historyLinkInFgSelected: historyLinkInFg; // inbox message link in a selected text or message -historyLinkOutFg: windowActiveTextFg; // outbox message link -historyLinkOutFgSelected: historyLinkOutFg; // outbox message link in a selected text or message -historyFileNameInFg: historyTextInFg; // inbox media filename text -historyFileNameInFgSelected: historyFileNameInFg; // inbox media filename text in a selected message -historyFileNameOutFg: historyTextOutFg; // outbox media filename text -historyFileNameOutFgSelected: historyFileNameOutFg; // outbox media filename text in a selected message -historyOutIconFg: dialogsSentIconFg; // outbox message tick / double tick icon -historyOutIconFgSelected: #4da79f; // outbox message tick / double tick icon in a selected message -historyIconFgInverted: windowFgActive; // media message tick / double tick icon (like in sent photo) -historySendingOutIconFg: #98d292; // outbox sending message icon (clock) -historySendingInIconFg: #a0adb5; // inbox sending message icon (clock) (like in sent messages to yourself or in sent messages to a channel) -historySendingInvertedIconFg: #ffffffc8; // media sending message icon (clock) (like in sent photo) -historyCallArrowInFg: callArrowFg; // received phone call arrow -historyCallArrowInFgSelected: callArrowFg; // received phone call arrow in a selected message -historyCallArrowMissedInFg: callArrowMissedFg; // missed phone call arrow -historyCallArrowMissedInFgSelected: callArrowMissedFg; // missed phone call arrow in a selected message -historyCallArrowOutFg: historyCallArrowInFg; // outgoing phone call arrow -historyCallArrowOutFgSelected: historyCallArrowInFgSelected; // outgoing phone call arrow - -historyUnreadBarBg: #fcfbfa; // new unread messages bar background -historyUnreadBarBorder: shadowFg; // new unread messages bar shadow -historyUnreadBarFg: #538bb4; // new unread messages bar text - -historyForwardChooseBg: #0000004c; // forwarding messages in a large window size "choose recipient" background -historyForwardChooseFg: windowFgActive; // forwarding messages in a large window size "choose recipient" text - -historyPeer1NameFg: #c03d33; // red group member name -historyPeer1NameFgSelected: historyPeer1NameFg; // red group member name in a selected message -historyPeer1UserpicBg: #e17076; // red userpic background -historyPeer2NameFg: #4fad2d; // green group member name -historyPeer2NameFgSelected: historyPeer2NameFg; // green group member name in a selected message -historyPeer2UserpicBg: #7bc862; // green userpic background -historyPeer3NameFg: #d09306; // yellow group member name -historyPeer3NameFgSelected: historyPeer3NameFg; // yellow group member name in a selected message -historyPeer3UserpicBg: #e5ca77; // yellow userpic background -historyPeer4NameFg: windowActiveTextFg; // blue group member name -historyPeer4NameFgSelected: historyPeer4NameFg; // blue group member name in a selected message -historyPeer4UserpicBg: #65aadd; // blue userpic background -historyPeer5NameFg: #8544d6; // purple group member name -historyPeer5NameFgSelected: historyPeer5NameFg; // purple group member name in a selected message -historyPeer5UserpicBg: #a695e7; // purple userpic background -historyPeer6NameFg: #cd4073; // pink group member name -historyPeer6NameFgSelected: historyPeer6NameFg; // pink group member name in a selected message -historyPeer6UserpicBg: #ee7aae; // pink userpic background -historyPeer7NameFg: #2996ad; // sea group member name -historyPeer7NameFgSelected: historyPeer7NameFg; // sea group member name in a selected message -historyPeer7UserpicBg: #6ec9cb; // sea userpic background -historyPeer8NameFg: #ce671b; // orange group member name -historyPeer8NameFgSelected: historyPeer8NameFg; // orange group member name in a selected message -historyPeer8UserpicBg: #faa774; // orange userpic background -historyPeerUserpicFg: windowFgActive; // default userpic initials -historyPeerSavedMessagesBg: historyPeer4UserpicBg; // saved messages userpic background -historyPeerArchiveUserpicBg: dialogsUnreadBgMuted; // archive folder userpic background - -// Some values are marked as (adjusted), it means they're adjusted by -// hue and saturation of the average background color if user chooses -// some other (not bundled to this color theme) background. If the -// bundled background is used those colors are not adjusted in any way. -historyScrollBarBg: #517c417a; // scroll bar current rectangle, the bar itself in the chat view (adjusted) -historyScrollBarBgOver: #517c41bc; // scroll bar current rectangle with mouse over it in the chat view (adjusted) -historyScrollBg: #517c414c; // scroll bar background (adjusted) -historyScrollBgOver: #517c416b; // scroll bar background with mouse over the scroll bar (adjusted) - -msgInBg: windowBg; // inbox message background -msgInBgSelected: #c2dcf2; // inbox selected message background (and background of selected text in those messages) -msgOutBg: #effdde; // outbox message background -msgOutBgSelected: #b7dbdb; // outbox selected message background (and background of selected text in those messages) -msgSelectOverlay: #358cd44c; // overlay which is filling the media parts of selected messages (like in selected photo message) -msgStickerOverlay: #358cd47f; // overlay which is filling the selected sticker message -msgInServiceFg: windowActiveTextFg; // inbox message information text (like information about a forwarded message original sender) -msgInServiceFgSelected: windowActiveTextFg; // inbox selected message information text (like information about a forwarded message original sender) -msgOutServiceFg: #3a8e26; // outbox message information text (like information about a forwarded message original sender) -msgOutServiceFgSelected: #367570; // outbox message information text (like information about a forwarded message original sender) -msgInShadow: #748ea229; // inbox message shadow (below the bubble) -msgInShadowSelected: #548dbb29; // inbox selected message shadow (below the bubble) -msgOutShadow: #3ac34740; // outbox message shadow (below the bubble) -msgOutShadowSelected: #37a78e40; // outbox selected message shadow (below the bubble) -msgInDateFg: #a0acb6; // inbox message time text -msgInDateFgSelected: #6a9cc5; // inbox selected message time text -msgOutDateFg: #6cc264; // outbox message time text -msgOutDateFgSelected: #50a79c; // outbox selected message time text -msgServiceFg: windowFgActive; // service message text (like date dividers or service message about the group title being changed) -msgServiceBg: #517c417f; // service message background (like in a service message about group title being changed) (adjusted) -msgServiceBgSelected: #96b38ba2; // service message selected text background (like in a service message about group title being changed) (adjusted) -msgInReplyBarColor: activeLineFg; // inbox message reply outline -msgInReplyBarSelColor: activeLineFg; // inbox selected message reply outline -msgOutReplyBarColor: historyOutIconFg; // outbox message reply outline -msgOutReplyBarSelColor: historyOutIconFgSelected; // outbox selected message reply outline -msgImgReplyBarColor: msgServiceFg; // sticker message reply outline -msgInMonoFg: #4e7391; // inbox message monospace text (like a message sent with `test` text) -msgOutMonoFg: #469165; // outbox message monospace text -msgInMonoFgSelected: msgInMonoFg; // inbox message monospace text in a selected text or message -msgOutMonoFgSelected: msgOutMonoFg; // outbox message monospace text in a selected text or message -msgDateImgFg: msgServiceFg; // media message time text (like time text in a sent photo) -msgDateImgBg: #00000054; // media message time bubble background (like time bubble in a sent photo) or file with thumbnail download icon circle background -msgDateImgBgOver: #00000074; // media message download icon circle background with mouse over (like file with thumbnail download icon) -msgDateImgBgSelected: #1c4a7187; // selected media message time bubble background - -msgFileThumbLinkInFg: lightButtonFg; // inbox media file message with thumbnail download / open with button text -msgFileThumbLinkInFgSelected: lightButtonFgOver; // inbox selected media file message with thumbnail download / open with button text -msgFileThumbLinkOutFg: #5eba5b; // outbox media file message with thumbnail download / open with button text -msgFileThumbLinkOutFgSelected: #31a298; // outbox selected media file message with thumbnail download / open with button text -msgFileInBg: windowBgActive; // inbox audio file download circle background -msgFileInBgOver: #4eade3; // inbox audio file download circle background with mouse over -msgFileInBgSelected: #51a3d3; // inbox selected audio file download circle background -msgFileOutBg: #78c67f; // outbox audio file download circle background -msgFileOutBgOver: #6bc272; // outbox audio file download circle background with mouse over -msgFileOutBgSelected: #5fb389; // outbox selected audio file download circle background - -msgFile1Bg: #72b1df; // blue shared links / files without image square thumbnail -msgFile1BgDark: #5c9ece; // blue shared files without image download circle background -msgFile1BgOver: #5294c4; // blue shared files without image download circle background with mouse over -msgFile1BgSelected: #5099d0; // blue shared files without image download circle background if file is selected -msgFile2Bg: #61b96e; // green shared links / shared files without image square thumbnail -msgFile2BgDark: #4da859; // green shared files without image download circle background -msgFile2BgOver: #44a050; // green shared files without image download circle background with mouse over -msgFile2BgSelected: #46a07e; // green shared files without image download circle background if file is selected -msgFile3Bg: #e47272; // red shared links / shared files without image square thumbnail -msgFile3BgDark: #cd5b5e; // red shared files without image download circle background -msgFile3BgOver: #c35154; // red shared files without image download circle background with mouse over -msgFile3BgSelected: #9f6a82; // red shared files without image download circle background if file is selected -msgFile4Bg: #efc274; // yellow shared links / shared files without image square thumbnail -msgFile4BgDark: #e6a561; // yellow shared files without image download circle background -msgFile4BgOver: #dc9c5a; // yellow shared files without image download circle background with mouse over -msgFile4BgSelected: #b19d84; // yellow shared files without image download circle background if file is selected - -historyFileInIconFg: msgInBg; // inbox file without thumbnail (like audio file) download arrow icon -historyFileInIconFgSelected: msgInBgSelected; // inbox selected file without thumbnail (like audio file) download arrow icon -historyFileInRadialFg: historyFileInIconFg; // inbox file without thumbnail (like audio file) radial download animation line -historyFileInRadialFgSelected: historyFileInIconFgSelected; // inbox selected file without thumbnail (like audio file) radial download animation line -historyFileOutIconFg: msgOutBg; // outbox file without thumbnail (like audio file) download arrow icon -historyFileOutIconFgSelected: msgOutBgSelected; // outbox selected file without thumbnail (like audio file) download arrow icon -historyFileOutRadialFg: historyFileOutIconFg; // outbox file without thumbnail (like audio file) radial download animation line -historyFileOutRadialFgSelected: historyFileOutIconFgSelected; // outbox selected file without thumbnail (like audio file) radial download animation line -historyFileThumbIconFg: msgInBg; // file with thumbnail (or photo / video) download arrow icon -historyFileThumbIconFgSelected: msgInBgSelected; // selected file with thumbnail (or photo / video) download arrow icon -historyFileThumbRadialFg: historyFileThumbIconFg; // file with thumbnail (or photo / video) radial download animation line -historyFileThumbRadialFgSelected: historyFileThumbIconFgSelected; // selected file with thumbnail (or photo / video) radial download animation line - -historyVideoMessageProgressFg: historyFileThumbIconFg; // radial playback progress in round video messages - -msgWaveformInActive: windowBgActive; // inbox voice message active waveform lines (like played part of currently playing voice message) -msgWaveformInActiveSelected: #51a3d3; // inbox selected voice message active waveform lines (like played part of currently playing voice message) -msgWaveformInInactive: #d4dee6; // inbox voice message inactive waveform lines (like upcoming part of currently playing voice message) -msgWaveformInInactiveSelected: #9cc1e1; // inbox selected voice message inactive waveform lines (like upcoming part of currently playing voice message) -msgWaveformOutActive: #78c67f; // outbox voice message active waveform lines (like played part of currently playing voice message) -msgWaveformOutActiveSelected: #6badad; // outbox selected voice message active waveform lines (like played part of currently playing voice message) -msgWaveformOutInactive: #b3e2b4; // outbox voice message inactive waveform lines (like upcoming part of currently playing voice message) -msgWaveformOutInactiveSelected: #91c3c3; // outbox selected voice message inactive waveform lines (like upcoming part of currently playing voice message) - -msgBotKbOverBgAdd: #ffffff20; // this is painted over a bot inline keyboard button (which has msgServiceBg background) when mouse is over that button -msgBotKbIconFg: msgServiceFg; // bot inline keyboard button icon in the top-right corner (like in @vote bot when a poll is ready to be shared) -msgBotKbRippleBg: #00000020; // bot inline keyboard button ripple effect - -mediaInFg: msgInDateFg; // inbox media message status text (like in file that is being downloaded) -mediaInFgSelected: msgInDateFgSelected; // inbox selected media message status text (like in file that is being downloaded) -mediaOutFg: msgOutDateFg; // outbox media message status text (like in file that is being downloaded) -mediaOutFgSelected: msgOutDateFgSelected; // outbox selected media message status text (like in file that is being downloaded) - -youtubePlayIconBg: #e83131c8; // youtube play icon background (when a link to a youtube video with a webpage preview is sent) -youtubePlayIconFg: windowFgActive; // youtube play icon arrow (when a link to a youtube video with a webpage preview is sent) -videoPlayIconBg: #0000007f; // other video play icon background (like when a link to a vimeo video with a webpage preview is sent) -videoPlayIconFg: #ffffff; // other video play icon arrow (like when a link to a vimeo video with a webpage preview is sent) -toastBg: #000000b2; // toast notification background (like when you click on your t.me link when editing your username) -toastFg: windowFgActive; // toast notification text (like when you click on your t.me link when editing your username) - -reportSpamBg: emojiPanHeaderBg; // report spam panel background (like a non contact user writes your for the first time) -reportSpamFg: windowFg; // report spam panel text (when you send a report from that panel) - -historyToDownBg: windowBg; // arrow button background (to scroll to the end of the viewed chat) -historyToDownBgOver: windowBgOver; // arrow button background with mouse over -historyToDownBgRipple: windowBgRipple; // arrow button ripple effect -historyToDownFg: menuIconFg; // arrow button icon -historyToDownFgOver: menuIconFgOver; // arrow button icon with mouse over -historyToDownShadow: #00000040; // arrow button shadow - -historyComposeAreaBg: msgInBg; // history compose area background (message write area / reply information / forwarding information) -historyComposeAreaFg: historyTextInFg; // history compose area text -historyComposeAreaFgService: msgInDateFg; // history compose area text when replying to a media message -historyComposeIconFg: menuIconFg; // history compose area icon (like emoji, attach, bot command..) -historyComposeIconFgOver: menuIconFgOver; // history compose area icon with mouse over -historySendIconFg: windowBgActive; // send message icon -historySendIconFgOver: windowBgActive; // send message icon with mouse over -historyPinnedBg: historyComposeAreaBg; // pinned message area background -historyReplyBg: historyComposeAreaBg; // reply / forward / edit message area background -historyReplyIconFg: windowBgActive; // reply / forward / edit message left icon -historyReplyCancelFg: cancelIconFg; // reply / forward / edit message cancel button -historyReplyCancelFgOver: cancelIconFgOver; // reply / forward / edit message cancel button with mouse over - -historyComposeButtonBg: historyComposeAreaBg; // unblock / join channel / mute channel button background -historyComposeButtonBgOver: windowBgOver; // unblock / join channel / mute channel button background with mouse over -historyComposeButtonBgRipple: windowBgRipple; // unblock / join channel / mute channel button ripple effect - -mapPointDrop: #fd4444; // geo location marker background -mapPointDot: #ffffff; // geo location marker point - -// overview -overviewCheckBg: #00000040; // shared media / files / links checkbox background for not selected rows when some rows are selected -overviewCheckBgActive: windowBgActive; // shared media / files / links checkbox background for selected rows -overviewCheckBorder: windowBg; // shared media round checkbox border -overviewCheckFg: windowBg; // shared files / links checkbox icon for not selected rows when some rows are selected -overviewCheckFgActive: windowBg; // shared files / links checkbox icon for selected rows -overviewPhotoSelectOverlay: #40ace333; // shared photos / videos / links fill for selected rows - -// profile -profileStatusFgOver: #7c99b2; // group members list in group profile user last seen text with mouse over -profileVerifiedCheckBg: windowBgActive; // profile verified check icon background -profileVerifiedCheckFg: windowFgActive; // profile verified check icon tick -profileAdminStartFg: windowBgActive; // group members list creator star icon -profileAdminStarFgOver: profileAdminStartFg; // group members list creator star icon with mouse over -profileOtherAdminStarFg: windowSubTextFg; // group members list admin star icon -profileOtherAdminStarFgOver: profileStatusFgOver; // group members list admin star icon with mouse over - -// settings -notificationsBoxMonitorFg: windowFg; // custom notifications settings box monitor color -notificationsBoxScreenBg: dialogsBgActive; // #6389a8; // custom notifications settings box monitor screen background - -notificationSampleUserpicFg: windowBgActive; // custom notifications settings box small sample userpic placeholder -notificationSampleCloseFg: #d7d7d7 | windowSubTextFg; // custom notifications settings box small sample close button placeholder -notificationSampleTextFg: #d7d7d7 | windowSubTextFg; // custom notifications settings box small sample text placeholder -notificationSampleNameFg: #939393 | windowSubTextFg; // custom notifications settings box small sample name placeholder - -changePhoneSimcardFrom: notificationSampleTextFg; // change phone number box left simcard icon -changePhoneSimcardTo: notificationSampleNameFg; // change phone number box right simcard and plane icons - -mainMenuBg: windowBg; // main menu background -mainMenuCoverBg: dialogsBgActive; // main menu top cover background -mainMenuCoverFg: windowFgActive; // main menu top cover text -mainMenuCloudFg: activeButtonFg; -mainMenuCloudBg: #2785bf | activeButtonBgRipple; - -mediaPlayerBg: windowBg; // audio file player background -mediaPlayerActiveFg: windowBgActive; // audio file player playback progress already played part -mediaPlayerInactiveFg: sliderBgInactive; // audio file player playback progress upcoming (not played yet) part with mouse over -mediaPlayerDisabledFg: #9dd1ef; // audio file player loading progress (when you're playing an audio file and switch to the previous one which is not loaded yet) - -// mediaview -mediaviewFileBg: windowBg; // file rectangle background (when you view a png file in Media Viewer and go to a previous, not loaded yet, file) -mediaviewFileNameFg: windowFg; // file name in file rectangle -mediaviewFileSizeFg: windowSubTextFg; // file size text in file rectangle -mediaviewFileRedCornerFg: #d55959; // red file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .pdf) -mediaviewFileYellowCornerFg: #e8a659; // yellow file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .zip) -mediaviewFileGreenCornerFg: #49a957; // green file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .exe) -mediaviewFileBlueCornerFg: #599dcf; // blue file thumbnail placeholder corner in file rectangle (for a file without thumbnail, like .dmg) -mediaviewFileExtFg: activeButtonFg; // file extension text in file thumbnail placeholder in file rectangle - -mediaviewMenuBg: #383838; // context menu in Media Viewer background -mediaviewMenuBgOver: #505050; // context menu item background with mouse over -mediaviewMenuBgRipple: #676767; // context menu item ripple effect -mediaviewMenuFg: windowFgActive; // context menu item text - -mediaviewBg: #222222eb; // Media Viewer background -mediaviewVideoBg: imageBg; // Media Viewer background when viewing a video in full screen -mediaviewControlBg: #0000003c; // controls background (like next photo / previous photo) -mediaviewControlFg: windowFgActive; // controls icon (like next photo / previous photo) -mediaviewCaptionBg: #11111180; // caption text background (when viewing photo with caption) -mediaviewCaptionFg: mediaviewControlFg; // caption text -mediaviewTextLinkFg: #91d9ff; // caption text link -mediaviewSaveMsgBg: toastBg; // save to file toast message background in Media Viewer -mediaviewSaveMsgFg: toastFg; // save to file toast message text - -mediaviewPlaybackActive: #c7c7c7; // video playback progress already played part -mediaviewPlaybackInactive: #252525; // video playback progress upcoming (not played yet) part -mediaviewPlaybackActiveOver: #ffffff; // video playback progress already played part with mouse over -mediaviewPlaybackInactiveOver: #474747; // video playback progress upcoming (not played yet) part with mouse over -mediaviewPlaybackProgressFg: #ffffffc7; // video playback progress text -mediaviewPlaybackIconFg: mediaviewPlaybackActive; // video playback controls icon -mediaviewPlaybackIconFgOver: mediaviewPlaybackActiveOver; // video playback controls icon with mouse over -mediaviewTransparentBg: #ffffff; // transparent filling part (when viewing a transparent .png file in Media Viewer) -mediaviewTransparentFg: #cccccc; // another transparent filling part - -// notification -notificationBg: windowBg; // custom notification window background - -// calls -callBg: #26282cf2; // phone call popup background -callNameFg: #ffffff; // phone call popup name text -callFingerprintBg: #00000066; // phone call popup emoji fingerprint background -callStatusFg: #aaabac; // phone call popup status text -callIconFg: #ffffff; // phone call popup answer, hangup and mute mic icon -callAnswerBg: #64c15b; // phone call popup answer button background -callAnswerRipple: #52b149; // phone call popup answer button ripple effect -callAnswerBgOuter: #50eb4126; // phone call popup answer button outer ripple effect -callHangupBg: #d75a5a; // phone call popup hangup button background -callHangupRipple: #c04646; // phone call popup hangup button ripple effect -callCancelBg: #ffffff; // phone call popup line busy cancel button background -callCancelFg: #777777; // phone call popup line busy cancel button icon -callCancelRipple: #f1f1f1; // phone call popup line busy cancel button ripple effect -callMuteRipple: #ffffff12; // phone call popup mute mic ripple effect - -callBarBg: dialogsBgActive; // active phone call bar background -callBarMuteRipple: dialogsRippleBgActive; // active phone call bar mute and hangup button ripple effect -callBarBgMuted: #8f8f8f | dialogsUnreadBgMuted; // phone call bar with muted mic background -callBarUnmuteRipple: #7f7f7f | shadowFg; // phone call bar with muted mic mute and hangup button ripple effect -callBarFg: dialogsNameFgActive; // phone call bar text and icons - -importantTooltipBg: toastBg; -importantTooltipFg: toastFg; -importantTooltipFgLink: mediaviewTextLinkFg; - -outdatedFg: #ffffff; -outdateSoonBg: #e08543; -outdatedBg: #e05745; diff --git a/Telegram/Resources/emoji_autocomplete.json b/Telegram/Resources/emoji_autocomplete.json deleted file mode 100644 index 40efc5f71..000000000 --- a/Telegram/Resources/emoji_autocomplete.json +++ /dev/null @@ -1,15998 +0,0 @@ -{ - "0023-20e3": { - "output": "0023-fe0f-20e3", - "name": "keycap: #", - "alpha_code": ":hash:", - "aliases": "" - }, - "0030-20e3": { - "output": "0030-fe0f-20e3", - "name": "keycap: 0", - "alpha_code": ":zero:", - "aliases": "" - }, - "0031-20e3": { - "output": "0031-fe0f-20e3", - "name": "keycap: 1", - "alpha_code": ":one:", - "aliases": "" - }, - "0032-20e3": { - "output": "0032-fe0f-20e3", - "name": "keycap: 2", - "alpha_code": ":two:", - "aliases": "" - }, - "0033-20e3": { - "output": "0033-fe0f-20e3", - "name": "keycap: 3", - "alpha_code": ":three:", - "aliases": "" - }, - "0034-20e3": { - "output": "0034-fe0f-20e3", - "name": "keycap: 4", - "alpha_code": ":four:", - "aliases": "" - }, - "0035-20e3": { - "output": "0035-fe0f-20e3", - "name": "keycap: 5", - "alpha_code": ":five:", - "aliases": "" - }, - "0036-20e3": { - "output": "0036-fe0f-20e3", - "name": "keycap: 6", - "alpha_code": ":six:", - "aliases": "" - }, - "0037-20e3": { - "output": "0037-fe0f-20e3", - "name": "keycap: 7", - "alpha_code": ":seven:", - "aliases": "" - }, - "0038-20e3": { - "output": "0038-fe0f-20e3", - "name": "keycap: 8", - "alpha_code": ":eight:", - "aliases": "" - }, - "0039-20e3": { - "output": "0039-fe0f-20e3", - "name": "keycap: 9", - "alpha_code": ":nine:", - "aliases": "" - }, - "00a9": { - "output": "00a9-fe0f", - "name": "copyright", - "alpha_code": ":copyright:", - "aliases": "" - }, - "00ae": { - "output": "00ae-fe0f", - "name": "registered", - "alpha_code": ":registered:", - "aliases": "" - }, - "203c": { - "output": "203c-fe0f", - "name": "double exclamation mark", - "alpha_code": ":bangbang:", - "aliases": "" - }, - "2049": { - "output": "2049-fe0f", - "name": "exclamation question mark", - "alpha_code": ":interrobang:", - "aliases": "" - }, - "2122": { - "output": "2122-fe0f", - "name": "trade mark", - "alpha_code": ":tm:", - "aliases": "" - }, - "2139": { - "output": "2139-fe0f", - "name": "information", - "alpha_code": ":information_source:", - "aliases": "" - }, - "2194": { - "output": "2194-fe0f", - "name": "left-right arrow", - "alpha_code": ":left_right_arrow:", - "aliases": "" - }, - "2195": { - "output": "2195-fe0f", - "name": "up-down arrow", - "alpha_code": ":arrow_up_down:", - "aliases": "" - }, - "2196": { - "output": "2196-fe0f", - "name": "up-left arrow", - "alpha_code": ":arrow_upper_left:", - "aliases": "" - }, - "1f949": { - "output": "1f949", - "name": "3rd place medal", - "alpha_code": ":third_place:", - "aliases": ":third_place_medal:" - }, - "2197": { - "output": "2197-fe0f", - "name": "up-right arrow", - "alpha_code": ":arrow_upper_right:", - "aliases": "" - }, - "2198": { - "output": "2198-fe0f", - "name": "down-right arrow", - "alpha_code": ":arrow_lower_right:", - "aliases": "" - }, - "2199": { - "output": "2199-fe0f", - "name": "down-left arrow", - "alpha_code": ":arrow_lower_left:", - "aliases": "" - }, - "1f948": { - "output": "1f948", - "name": "2nd place medal", - "alpha_code": ":second_place:", - "aliases": ":second_place_medal:" - }, - "21a9": { - "output": "21a9-fe0f", - "name": "right arrow curving left", - "alpha_code": ":leftwards_arrow_with_hook:", - "aliases": "" - }, - "21aa": { - "output": "21aa-fe0f", - "name": "left arrow curving right", - "alpha_code": ":arrow_right_hook:", - "aliases": "" - }, - "231a": { - "output": "231a", - "name": "watch", - "alpha_code": ":watch:", - "aliases": "" - }, - "231b": { - "output": "231b", - "name": "hourglass", - "alpha_code": ":hourglass:", - "aliases": "" - }, - "23e9": { - "output": "23e9", - "name": "fast-forward button", - "alpha_code": ":fast_forward:", - "aliases": "" - }, - "23ea": { - "output": "23ea", - "name": "fast reverse button", - "alpha_code": ":rewind:", - "aliases": "" - }, - "23eb": { - "output": "23eb", - "name": "fast up button", - "alpha_code": ":arrow_double_up:", - "aliases": "" - }, - "23ec": { - "output": "23ec", - "name": "fast down button", - "alpha_code": ":arrow_double_down:", - "aliases": "" - }, - "23f0": { - "output": "23f0", - "name": "alarm clock", - "alpha_code": ":alarm_clock:", - "aliases": "" - }, - "23f3": { - "output": "23f3", - "name": "hourglass with flowing sand", - "alpha_code": ":hourglass_flowing_sand:", - "aliases": "" - }, - "24c2": { - "output": "24c2-fe0f", - "name": "circled M", - "alpha_code": ":m:", - "aliases": "" - }, - "25aa": { - "output": "25aa-fe0f", - "name": "black small square", - "alpha_code": ":black_small_square:", - "aliases": "" - }, - "25ab": { - "output": "25ab-fe0f", - "name": "white small square", - "alpha_code": ":white_small_square:", - "aliases": "" - }, - "25b6": { - "output": "25b6-fe0f", - "name": "play button", - "alpha_code": ":arrow_forward:", - "aliases": "" - }, - "25c0": { - "output": "25c0-fe0f", - "name": "reverse button", - "alpha_code": ":arrow_backward:", - "aliases": "" - }, - "25fb": { - "output": "25fb-fe0f", - "name": "white medium square", - "alpha_code": ":white_medium_square:", - "aliases": "" - }, - "25fc": { - "output": "25fc-fe0f", - "name": "black medium square", - "alpha_code": ":black_medium_square:", - "aliases": "" - }, - "25fd": { - "output": "25fd", - "name": "white medium-small square", - "alpha_code": ":white_medium_small_square:", - "aliases": "" - }, - "25fe": { - "output": "25fe", - "name": "black medium-small square", - "alpha_code": ":black_medium_small_square:", - "aliases": "" - }, - "2600": { - "output": "2600-fe0f", - "name": "sun", - "alpha_code": ":sunny:", - "aliases": "" - }, - "2601": { - "output": "2601-fe0f", - "name": "cloud", - "alpha_code": ":cloud:", - "aliases": "" - }, - "260e": { - "output": "260e-fe0f", - "name": "telephone", - "alpha_code": ":telephone:", - "aliases": "" - }, - "2611": { - "output": "2611-fe0f", - "name": "ballot box with check", - "alpha_code": ":ballot_box_with_check:", - "aliases": "" - }, - "2614": { - "output": "2614", - "name": "umbrella with rain drops", - "alpha_code": ":umbrella:", - "aliases": "" - }, - "2615": { - "output": "2615", - "name": "hot beverage", - "alpha_code": ":coffee:", - "aliases": "" - }, - "261d": { - "output": "261d-fe0f", - "name": "index pointing up", - "alpha_code": ":point_up:", - "aliases": "" - }, - "263a": { - "output": "263a-fe0f", - "name": "smiling face", - "alpha_code": ":relaxed:", - "aliases": "" - }, - "2648": { - "output": "2648", - "name": "Aries", - "alpha_code": ":aries:", - "aliases": "" - }, - "1f947": { - "output": "1f947", - "name": "1st place medal", - "alpha_code": ":first_place:", - "aliases": ":first_place_medal:" - }, - "2649": { - "output": "2649", - "name": "Taurus", - "alpha_code": ":taurus:", - "aliases": "" - }, - "1f93a": { - "output": "1f93a", - "name": "person fencing", - "alpha_code": ":person_fencing:", - "aliases": ":fencer:|:fencing:" - }, - "264a": { - "output": "264a", - "name": "Gemini", - "alpha_code": ":gemini:", - "aliases": "" - }, - "264b": { - "output": "264b", - "name": "Cancer", - "alpha_code": ":cancer:", - "aliases": "" - }, - "1f945": { - "output": "1f945", - "name": "goal net", - "alpha_code": ":goal:", - "aliases": ":goal_net:" - }, - "264c": { - "output": "264c", - "name": "Leo", - "alpha_code": ":leo:", - "aliases": "" - }, - "002a": { - "output": "002a-fe0f", - "name": "asterisk", - "alpha_code": ":asterisk_symbol:", - "aliases": "" - }, - "264d": { - "output": "264d", - "name": "Virgo", - "alpha_code": ":virgo:", - "aliases": "" - }, - "1f93e": { - "output": "1f93e", - "name": "person playing handball", - "alpha_code": ":person_playing_handball:", - "aliases": ":handball:" - }, - "264e": { - "output": "264e", - "name": "Libra", - "alpha_code": ":libra:", - "aliases": "" - }, - "1f1ff": { - "output": "1f1ff", - "name": "regional indicator symbol letter z", - "alpha_code": ":regional_indicator_z:", - "aliases": "" - }, - "1f93d": { - "output": "1f93d", - "name": "person playing water polo", - "alpha_code": ":person_playing_water_polo:", - "aliases": ":water_polo:" - }, - "264f": { - "output": "264f", - "name": "Scorpius", - "alpha_code": ":scorpius:", - "aliases": "" - }, - "2650": { - "output": "2650", - "name": "Sagittarius", - "alpha_code": ":sagittarius:", - "aliases": "" - }, - "1f94b": { - "output": "1f94b", - "name": "martial arts uniform", - "alpha_code": ":martial_arts_uniform:", - "aliases": ":karate_uniform:" - }, - "2651": { - "output": "2651", - "name": "Capricorn", - "alpha_code": ":capricorn:", - "aliases": "" - }, - "1f94a": { - "output": "1f94a", - "name": "boxing glove", - "alpha_code": ":boxing_glove:", - "aliases": ":boxing_gloves:" - }, - "2652": { - "output": "2652", - "name": "Aquarius", - "alpha_code": ":aquarius:", - "aliases": "" - }, - "1f93c": { - "output": "1f93c", - "name": "people wrestling", - "alpha_code": ":people_wrestling:", - "aliases": ":wrestlers:|:wrestling:" - }, - "2653": { - "output": "2653", - "name": "Pisces", - "alpha_code": ":pisces:", - "aliases": "" - }, - "2660": { - "output": "2660-fe0f", - "name": "spade suit", - "alpha_code": ":spades:", - "aliases": "" - }, - "2663": { - "output": "2663-fe0f", - "name": "club suit", - "alpha_code": ":clubs:", - "aliases": "" - }, - "2665": { - "output": "2665-fe0f", - "name": "heart suit", - "alpha_code": ":hearts:", - "aliases": "" - }, - "2666": { - "output": "2666-fe0f", - "name": "diamond suit", - "alpha_code": ":diamonds:", - "aliases": "" - }, - "2668": { - "output": "2668-fe0f", - "name": "hot springs", - "alpha_code": ":hotsprings:", - "aliases": "" - }, - "267b": { - "output": "267b-fe0f", - "name": "recycling symbol", - "alpha_code": ":recycle:", - "aliases": "" - }, - "1f939": { - "output": "1f939", - "name": "person juggling", - "alpha_code": ":person_juggling:", - "aliases": ":juggling:|:juggler:" - }, - "267f": { - "output": "267f", - "name": "wheelchair symbol", - "alpha_code": ":wheelchair:", - "aliases": "" - }, - "2693": { - "output": "2693", - "name": "anchor", - "alpha_code": ":anchor:", - "aliases": "" - }, - "26a0": { - "output": "26a0-fe0f", - "name": "warning", - "alpha_code": ":warning:", - "aliases": "" - }, - "26a1": { - "output": "26a1", - "name": "high voltage", - "alpha_code": ":zap:", - "aliases": "" - }, - "26aa": { - "output": "26aa", - "name": "white circle", - "alpha_code": ":white_circle:", - "aliases": "" - }, - "26ab": { - "output": "26ab", - "name": "black circle", - "alpha_code": ":black_circle:", - "aliases": "" - }, - "26bd": { - "output": "26bd", - "name": "soccer ball", - "alpha_code": ":soccer:", - "aliases": "" - }, - "26be": { - "output": "26be", - "name": "baseball", - "alpha_code": ":baseball:", - "aliases": "" - }, - "26c4": { - "output": "26c4", - "name": "snowman without snow", - "alpha_code": ":snowman:", - "aliases": "" - }, - "26c5": { - "output": "26c5", - "name": "sun behind cloud", - "alpha_code": ":partly_sunny:", - "aliases": "" - }, - "26ce": { - "output": "26ce", - "name": "Ophiuchus", - "alpha_code": ":ophiuchus:", - "aliases": "" - }, - "1f938": { - "output": "1f938", - "name": "person cartwheeling", - "alpha_code": ":person_doing_cartwheel:", - "aliases": ":cartwheel:" - }, - "26d4": { - "output": "26d4", - "name": "no entry", - "alpha_code": ":no_entry:", - "aliases": "" - }, - "26ea": { - "output": "26ea", - "name": "church", - "alpha_code": ":church:", - "aliases": "" - }, - "26f2": { - "output": "26f2", - "name": "fountain", - "alpha_code": ":fountain:", - "aliases": "" - }, - "1f6f6": { - "output": "1f6f6", - "name": "canoe", - "alpha_code": ":canoe:", - "aliases": ":kayak:" - }, - "26f3": { - "output": "26f3", - "name": "flag in hole", - "alpha_code": ":golf:", - "aliases": "" - }, - "26f5": { - "output": "26f5", - "name": "sailboat", - "alpha_code": ":sailboat:", - "aliases": "" - }, - "26fa": { - "output": "26fa", - "name": "tent", - "alpha_code": ":tent:", - "aliases": "" - }, - "26fd": { - "output": "26fd", - "name": "fuel pump", - "alpha_code": ":fuelpump:", - "aliases": "" - }, - "2702": { - "output": "2702-fe0f", - "name": "scissors", - "alpha_code": ":scissors:", - "aliases": "" - }, - "2705": { - "output": "2705", - "name": "white heavy check mark", - "alpha_code": ":white_check_mark:", - "aliases": "" - }, - "2708": { - "output": "2708-fe0f", - "name": "airplane", - "alpha_code": ":airplane:", - "aliases": "" - }, - "2709": { - "output": "2709-fe0f", - "name": "envelope", - "alpha_code": ":envelope:", - "aliases": "" - }, - "270a": { - "output": "270a", - "name": "raised fist", - "alpha_code": ":fist:", - "aliases": "" - }, - "270b": { - "output": "270b", - "name": "raised hand", - "alpha_code": ":raised_hand:", - "aliases": "" - }, - "270c": { - "output": "270c-fe0f", - "name": "victory hand", - "alpha_code": ":v:", - "aliases": "" - }, - "270f": { - "output": "270f-fe0f", - "name": "pencil", - "alpha_code": ":pencil2:", - "aliases": "" - }, - "2712": { - "output": "2712-fe0f", - "name": "black nib", - "alpha_code": ":black_nib:", - "aliases": "" - }, - "2714": { - "output": "2714-fe0f", - "name": "heavy check mark", - "alpha_code": ":heavy_check_mark:", - "aliases": "" - }, - "2716": { - "output": "2716-fe0f", - "name": "heavy multiplication x", - "alpha_code": ":heavy_multiplication_x:", - "aliases": "" - }, - "2728": { - "output": "2728", - "name": "sparkles", - "alpha_code": ":sparkles:", - "aliases": "" - }, - "2733": { - "output": "2733-fe0f", - "name": "eight-spoked asterisk", - "alpha_code": ":eight_spoked_asterisk:", - "aliases": "" - }, - "2734": { - "output": "2734-fe0f", - "name": "eight-pointed star", - "alpha_code": ":eight_pointed_black_star:", - "aliases": "" - }, - "2744": { - "output": "2744-fe0f", - "name": "snowflake", - "alpha_code": ":snowflake:", - "aliases": "" - }, - "2747": { - "output": "2747-fe0f", - "name": "sparkle", - "alpha_code": ":sparkle:", - "aliases": "" - }, - "274c": { - "output": "274c", - "name": "cross mark", - "alpha_code": ":x:", - "aliases": "" - }, - "274e": { - "output": "274e", - "name": "cross mark button", - "alpha_code": ":negative_squared_cross_mark:", - "aliases": "" - }, - "2753": { - "output": "2753", - "name": "question mark", - "alpha_code": ":question:", - "aliases": "" - }, - "2754": { - "output": "2754", - "name": "white question mark", - "alpha_code": ":grey_question:", - "aliases": "" - }, - "1f6f5": { - "output": "1f6f5", - "name": "motor scooter", - "alpha_code": ":motor_scooter:", - "aliases": ":motorbike:" - }, - "2755": { - "output": "2755", - "name": "white exclamation mark", - "alpha_code": ":grey_exclamation:", - "aliases": "" - }, - "2757": { - "output": "2757", - "name": "exclamation mark", - "alpha_code": ":exclamation:", - "aliases": "" - }, - "2764": { - "output": "2764-fe0f", - "name": "red heart", - "alpha_code": ":heart:", - "aliases": "" - }, - "2795": { - "output": "2795", - "name": "heavy plus sign", - "alpha_code": ":heavy_plus_sign:", - "aliases": "" - }, - "2796": { - "output": "2796", - "name": "heavy minus sign", - "alpha_code": ":heavy_minus_sign:", - "aliases": "" - }, - "2797": { - "output": "2797", - "name": "heavy division sign", - "alpha_code": ":heavy_division_sign:", - "aliases": "" - }, - "27a1": { - "output": "27a1-fe0f", - "name": "right arrow", - "alpha_code": ":arrow_right:", - "aliases": "" - }, - "27b0": { - "output": "27b0", - "name": "curly loop", - "alpha_code": ":curly_loop:", - "aliases": "" - }, - "2934": { - "output": "2934-fe0f", - "name": "right arrow curving up", - "alpha_code": ":arrow_heading_up:", - "aliases": "" - }, - "2935": { - "output": "2935-fe0f", - "name": "right arrow curving down", - "alpha_code": ":arrow_heading_down:", - "aliases": "" - }, - "2b05": { - "output": "2b05-fe0f", - "name": "left arrow", - "alpha_code": ":arrow_left:", - "aliases": "" - }, - "2b06": { - "output": "2b06-fe0f", - "name": "up arrow", - "alpha_code": ":arrow_up:", - "aliases": "" - }, - "1f6f4": { - "output": "1f6f4", - "name": "kick scooter", - "alpha_code": ":scooter:", - "aliases": "" - }, - "2b07": { - "output": "2b07-fe0f", - "name": "down arrow", - "alpha_code": ":arrow_down:", - "aliases": "" - }, - "2b1b": { - "output": "2b1b", - "name": "black large square", - "alpha_code": ":black_large_square:", - "aliases": "" - }, - "2b1c": { - "output": "2b1c", - "name": "white large square", - "alpha_code": ":white_large_square:", - "aliases": "" - }, - "2b50": { - "output": "2b50", - "name": "white medium star", - "alpha_code": ":star:", - "aliases": "" - }, - "2b55": { - "output": "2b55", - "name": "heavy large circle", - "alpha_code": ":o:", - "aliases": "" - }, - "3030": { - "output": "3030-fe0f", - "name": "wavy dash", - "alpha_code": ":wavy_dash:", - "aliases": "" - }, - "303d": { - "output": "303d-fe0f", - "name": "part alternation mark", - "alpha_code": ":part_alternation_mark:", - "aliases": "" - }, - "3297": { - "output": "3297-fe0f", - "name": "Japanese \u201ccongratulations\u201d button", - "alpha_code": ":congratulations:", - "aliases": "" - }, - "1f6d2": { - "output": "1f6d2", - "name": "shopping cart", - "alpha_code": ":shopping_cart:", - "aliases": ":shopping_trolley:" - }, - "3299": { - "output": "3299-fe0f", - "name": "Japanese \u201csecret\u201d button", - "alpha_code": ":secret:", - "aliases": "" - }, - "1f004": { - "output": "1f004", - "name": "mahjong red dragon", - "alpha_code": ":mahjong:", - "aliases": "" - }, - "1f0cf": { - "output": "1f0cf", - "name": "joker", - "alpha_code": ":black_joker:", - "aliases": "" - }, - "1f170": { - "output": "1f170-fe0f", - "name": "A button (blood type)", - "alpha_code": ":a:", - "aliases": "" - }, - "1f171": { - "output": "1f171-fe0f", - "name": "B button (blood type)", - "alpha_code": ":b:", - "aliases": "" - }, - "1f17e": { - "output": "1f17e-fe0f", - "name": "O button (blood type)", - "alpha_code": ":o2:", - "aliases": "" - }, - "1f17f": { - "output": "1f17f-fe0f", - "name": "P button", - "alpha_code": ":parking:", - "aliases": "" - }, - "1f6d1": { - "output": "1f6d1", - "name": "stop sign", - "alpha_code": ":octagonal_sign:", - "aliases": ":stop_sign:" - }, - "1f18e": { - "output": "1f18e", - "name": "AB button (blood type)", - "alpha_code": ":ab:", - "aliases": "" - }, - "1f191": { - "output": "1f191", - "name": "CL button", - "alpha_code": ":cl:", - "aliases": "" - }, - "1f1fe": { - "output": "1f1fe", - "name": "regional indicator symbol letter y", - "alpha_code": ":regional_indicator_y:", - "aliases": "" - }, - "1f192": { - "output": "1f192", - "name": "COOL button", - "alpha_code": ":cool:", - "aliases": "" - }, - "1f193": { - "output": "1f193", - "name": "FREE button", - "alpha_code": ":free:", - "aliases": "" - }, - "1f194": { - "output": "1f194", - "name": "ID button", - "alpha_code": ":id:", - "aliases": "" - }, - "1f195": { - "output": "1f195", - "name": "NEW button", - "alpha_code": ":new:", - "aliases": "" - }, - "1f196": { - "output": "1f196", - "name": "NG button", - "alpha_code": ":ng:", - "aliases": "" - }, - "1f197": { - "output": "1f197", - "name": "OK button", - "alpha_code": ":ok:", - "aliases": "" - }, - "1f198": { - "output": "1f198", - "name": "SOS button", - "alpha_code": ":sos:", - "aliases": "" - }, - "1f944": { - "output": "1f944", - "name": "spoon", - "alpha_code": ":spoon:", - "aliases": "" - }, - "1f199": { - "output": "1f199", - "name": "UP! button", - "alpha_code": ":up:", - "aliases": "" - }, - "1f19a": { - "output": "1f19a", - "name": "VS button", - "alpha_code": ":vs:", - "aliases": "" - }, - "1f1e8-1f1f3": { - "output": "1f1e8-1f1f3", - "name": "China", - "alpha_code": ":flag_cn:", - "aliases": ":cn:" - }, - "1f1e9-1f1ea": { - "output": "1f1e9-1f1ea", - "name": "Germany", - "alpha_code": ":flag_de:", - "aliases": ":de:" - }, - "1f1ea-1f1f8": { - "output": "1f1ea-1f1f8", - "name": "Spain", - "alpha_code": ":flag_es:", - "aliases": ":es:" - }, - "1f1eb-1f1f7": { - "output": "1f1eb-1f1f7", - "name": "France", - "alpha_code": ":flag_fr:", - "aliases": ":fr:" - }, - "1f1ec-1f1e7": { - "output": "1f1ec-1f1e7", - "name": "United Kingdom", - "alpha_code": ":flag_gb:", - "aliases": ":gb:" - }, - "1f942": { - "output": "1f942", - "name": "clinking glasses", - "alpha_code": ":champagne_glass:", - "aliases": ":clinking_glass:" - }, - "1f943": { - "output": "1f943", - "name": "tumbler glass", - "alpha_code": ":tumbler_glass:", - "aliases": ":whisky:" - }, - "1f1ee-1f1f9": { - "output": "1f1ee-1f1f9", - "name": "Italy", - "alpha_code": ":flag_it:", - "aliases": ":it:" - }, - "1f1ef-1f1f5": { - "output": "1f1ef-1f1f5", - "name": "Japan", - "alpha_code": ":flag_jp:", - "aliases": ":jp:" - }, - "1f1f0-1f1f7": { - "output": "1f1f0-1f1f7", - "name": "South Korea", - "alpha_code": ":flag_kr:", - "aliases": ":kr:" - }, - "1f1fa-1f1f8": { - "output": "1f1fa-1f1f8", - "name": "United States", - "alpha_code": ":flag_us:", - "aliases": ":us:" - }, - "1f1f7-1f1fa": { - "output": "1f1f7-1f1fa", - "name": "Russia", - "alpha_code": ":flag_ru:", - "aliases": ":ru:" - }, - "1f201": { - "output": "1f201", - "name": "Japanese \u201chere\u201d button", - "alpha_code": ":koko:", - "aliases": "" - }, - "1f202": { - "output": "1f202-fe0f", - "name": "Japanese \u201cservice charge\u201d button", - "alpha_code": ":sa:", - "aliases": "" - }, - "1f21a": { - "output": "1f21a", - "name": "Japanese \u201cfree of charge\u201d button", - "alpha_code": ":u7121:", - "aliases": "" - }, - "1f22f": { - "output": "1f22f", - "name": "Japanese \u201creserved\u201d button", - "alpha_code": ":u6307:", - "aliases": "" - }, - "1f959": { - "output": "1f959", - "name": "stuffed flatbread", - "alpha_code": ":stuffed_flatbread:", - "aliases": ":stuffed_pita:" - }, - "1f232": { - "output": "1f232", - "name": "Japanese \u201cprohibited\u201d button", - "alpha_code": ":u7981:", - "aliases": "" - }, - "1f233": { - "output": "1f233", - "name": "Japanese \u201cvacancy\u201d button", - "alpha_code": ":u7a7a:", - "aliases": "" - }, - "1f234": { - "output": "1f234", - "name": "Japanese \u201cpassing grade\u201d button", - "alpha_code": ":u5408:", - "aliases": "" - }, - "1f235": { - "output": "1f235", - "name": "Japanese \u201cno vacancy\u201d button", - "alpha_code": ":u6e80:", - "aliases": "" - }, - "1f236": { - "output": "1f236", - "name": "Japanese \u201cnot free of charge\u201d button", - "alpha_code": ":u6709:", - "aliases": "" - }, - "1f958": { - "output": "1f958", - "name": "shallow pan of food", - "alpha_code": ":shallow_pan_of_food:", - "aliases": ":paella:" - }, - "1f237": { - "output": "1f237-fe0f", - "name": "Japanese \u201cmonthly amount\u201d button", - "alpha_code": ":u6708:", - "aliases": "" - }, - "1f238": { - "output": "1f238", - "name": "Japanese \u201capplication\u201d button", - "alpha_code": ":u7533:", - "aliases": "" - }, - "1f239": { - "output": "1f239", - "name": "Japanese \u201cdiscount\u201d button", - "alpha_code": ":u5272:", - "aliases": "" - }, - "1f957": { - "output": "1f957", - "name": "green salad", - "alpha_code": ":salad:", - "aliases": ":green_salad:" - }, - "1f23a": { - "output": "1f23a", - "name": "Japanese \u201copen for business\u201d button", - "alpha_code": ":u55b6:", - "aliases": "" - }, - "1f250": { - "output": "1f250", - "name": "Japanese \u201cbargain\u201d button", - "alpha_code": ":ideograph_advantage:", - "aliases": "" - }, - "1f251": { - "output": "1f251", - "name": "Japanese \u201cacceptable\u201d button", - "alpha_code": ":accept:", - "aliases": "" - }, - "1f300": { - "output": "1f300", - "name": "cyclone", - "alpha_code": ":cyclone:", - "aliases": "" - }, - "1f956": { - "output": "1f956", - "name": "baguette bread", - "alpha_code": ":french_bread:", - "aliases": ":baguette_bread:" - }, - "1f301": { - "output": "1f301", - "name": "foggy", - "alpha_code": ":foggy:", - "aliases": "" - }, - "1f302": { - "output": "1f302", - "name": "closed umbrella", - "alpha_code": ":closed_umbrella:", - "aliases": "" - }, - "1f303": { - "output": "1f303", - "name": "night with stars", - "alpha_code": ":night_with_stars:", - "aliases": "" - }, - "1f304": { - "output": "1f304", - "name": "sunrise over mountains", - "alpha_code": ":sunrise_over_mountains:", - "aliases": "" - }, - "1f305": { - "output": "1f305", - "name": "sunrise", - "alpha_code": ":sunrise:", - "aliases": "" - }, - "1f306": { - "output": "1f306", - "name": "cityscape at dusk", - "alpha_code": ":city_dusk:", - "aliases": "" - }, - "1f955": { - "output": "1f955", - "name": "carrot", - "alpha_code": ":carrot:", - "aliases": "" - }, - "1f307": { - "output": "1f307", - "name": "sunset", - "alpha_code": ":city_sunset:", - "aliases": ":city_sunrise:" - }, - "1f308": { - "output": "1f308", - "name": "rainbow", - "alpha_code": ":rainbow:", - "aliases": "" - }, - "1f954": { - "output": "1f954", - "name": "potato", - "alpha_code": ":potato:", - "aliases": "" - }, - "1f309": { - "output": "1f309", - "name": "bridge at night", - "alpha_code": ":bridge_at_night:", - "aliases": "" - }, - "1f30a": { - "output": "1f30a", - "name": "water wave", - "alpha_code": ":ocean:", - "aliases": "" - }, - "1f30b": { - "output": "1f30b", - "name": "volcano", - "alpha_code": ":volcano:", - "aliases": "" - }, - "1f30c": { - "output": "1f30c", - "name": "milky way", - "alpha_code": ":milky_way:", - "aliases": "" - }, - "1f30f": { - "output": "1f30f", - "name": "globe showing Asia-Australia", - "alpha_code": ":earth_asia:", - "aliases": "" - }, - "1f311": { - "output": "1f311", - "name": "new moon", - "alpha_code": ":new_moon:", - "aliases": "" - }, - "1f953": { - "output": "1f953", - "name": "bacon", - "alpha_code": ":bacon:", - "aliases": "" - }, - "1f313": { - "output": "1f313", - "name": "first quarter moon", - "alpha_code": ":first_quarter_moon:", - "aliases": "" - }, - "1f314": { - "output": "1f314", - "name": "waxing gibbous moon", - "alpha_code": ":waxing_gibbous_moon:", - "aliases": "" - }, - "1f315": { - "output": "1f315", - "name": "full moon", - "alpha_code": ":full_moon:", - "aliases": "" - }, - "1f319": { - "output": "1f319", - "name": "crescent moon", - "alpha_code": ":crescent_moon:", - "aliases": "" - }, - "1f31b": { - "output": "1f31b", - "name": "first quarter moon with face", - "alpha_code": ":first_quarter_moon_with_face:", - "aliases": "" - }, - "1f31f": { - "output": "1f31f", - "name": "glowing star", - "alpha_code": ":star2:", - "aliases": "" - }, - "1f952": { - "output": "1f952", - "name": "cucumber", - "alpha_code": ":cucumber:", - "aliases": "" - }, - "1f320": { - "output": "1f320", - "name": "shooting star", - "alpha_code": ":stars:", - "aliases": "" - }, - "1f330": { - "output": "1f330", - "name": "chestnut", - "alpha_code": ":chestnut:", - "aliases": "" - }, - "1f951": { - "output": "1f951", - "name": "avocado", - "alpha_code": ":avocado:", - "aliases": "" - }, - "1f331": { - "output": "1f331", - "name": "seedling", - "alpha_code": ":seedling:", - "aliases": "" - }, - "1f334": { - "output": "1f334", - "name": "palm tree", - "alpha_code": ":palm_tree:", - "aliases": "" - }, - "1f335": { - "output": "1f335", - "name": "cactus", - "alpha_code": ":cactus:", - "aliases": "" - }, - "1f337": { - "output": "1f337", - "name": "tulip", - "alpha_code": ":tulip:", - "aliases": "" - }, - "1f338": { - "output": "1f338", - "name": "cherry blossom", - "alpha_code": ":cherry_blossom:", - "aliases": "" - }, - "1f339": { - "output": "1f339", - "name": "rose", - "alpha_code": ":rose:", - "aliases": "" - }, - "1f33a": { - "output": "1f33a", - "name": "hibiscus", - "alpha_code": ":hibiscus:", - "aliases": "" - }, - "1f33b": { - "output": "1f33b", - "name": "sunflower", - "alpha_code": ":sunflower:", - "aliases": "" - }, - "1f33c": { - "output": "1f33c", - "name": "blossom", - "alpha_code": ":blossom:", - "aliases": "" - }, - "1f33d": { - "output": "1f33d", - "name": "ear of corn", - "alpha_code": ":corn:", - "aliases": "" - }, - "1f950": { - "output": "1f950", - "name": "croissant", - "alpha_code": ":croissant:", - "aliases": "" - }, - "1f33e": { - "output": "1f33e", - "name": "sheaf of rice", - "alpha_code": ":ear_of_rice:", - "aliases": "" - }, - "1f33f": { - "output": "1f33f", - "name": "herb", - "alpha_code": ":herb:", - "aliases": "" - }, - "1f340": { - "output": "1f340", - "name": "four leaf clover", - "alpha_code": ":four_leaf_clover:", - "aliases": "" - }, - "1f341": { - "output": "1f341", - "name": "maple leaf", - "alpha_code": ":maple_leaf:", - "aliases": "" - }, - "1f342": { - "output": "1f342", - "name": "fallen leaf", - "alpha_code": ":fallen_leaf:", - "aliases": "" - }, - "1f343": { - "output": "1f343", - "name": "leaf fluttering in wind", - "alpha_code": ":leaves:", - "aliases": "" - }, - "1f344": { - "output": "1f344", - "name": "mushroom", - "alpha_code": ":mushroom:", - "aliases": "" - }, - "1f345": { - "output": "1f345", - "name": "tomato", - "alpha_code": ":tomato:", - "aliases": "" - }, - "1f346": { - "output": "1f346", - "name": "eggplant", - "alpha_code": ":eggplant:", - "aliases": "" - }, - "1f347": { - "output": "1f347", - "name": "grapes", - "alpha_code": ":grapes:", - "aliases": "" - }, - "1f348": { - "output": "1f348", - "name": "melon", - "alpha_code": ":melon:", - "aliases": "" - }, - "1f349": { - "output": "1f349", - "name": "watermelon", - "alpha_code": ":watermelon:", - "aliases": "" - }, - "1f34a": { - "output": "1f34a", - "name": "tangerine", - "alpha_code": ":tangerine:", - "aliases": "" - }, - "1f940": { - "output": "1f940", - "name": "wilted flower", - "alpha_code": ":wilted_rose:", - "aliases": ":wilted_flower:" - }, - "1f34c": { - "output": "1f34c", - "name": "banana", - "alpha_code": ":banana:", - "aliases": "" - }, - "1f34d": { - "output": "1f34d", - "name": "pineapple", - "alpha_code": ":pineapple:", - "aliases": "" - }, - "1f34e": { - "output": "1f34e", - "name": "red apple", - "alpha_code": ":apple:", - "aliases": "" - }, - "1f34f": { - "output": "1f34f", - "name": "green apple", - "alpha_code": ":green_apple:", - "aliases": "" - }, - "1f351": { - "output": "1f351", - "name": "peach", - "alpha_code": ":peach:", - "aliases": "" - }, - "1f352": { - "output": "1f352", - "name": "cherries", - "alpha_code": ":cherries:", - "aliases": "" - }, - "1f353": { - "output": "1f353", - "name": "strawberry", - "alpha_code": ":strawberry:", - "aliases": "" - }, - "1f98f": { - "output": "1f98f", - "name": "rhinoceros", - "alpha_code": ":rhino:", - "aliases": ":rhinoceros:" - }, - "1f354": { - "output": "1f354", - "name": "hamburger", - "alpha_code": ":hamburger:", - "aliases": "" - }, - "1f355": { - "output": "1f355", - "name": "pizza", - "alpha_code": ":pizza:", - "aliases": "" - }, - "1f356": { - "output": "1f356", - "name": "meat on bone", - "alpha_code": ":meat_on_bone:", - "aliases": "" - }, - "1f98e": { - "output": "1f98e", - "name": "lizard", - "alpha_code": ":lizard:", - "aliases": "" - }, - "1f357": { - "output": "1f357", - "name": "poultry leg", - "alpha_code": ":poultry_leg:", - "aliases": "" - }, - "1f358": { - "output": "1f358", - "name": "rice cracker", - "alpha_code": ":rice_cracker:", - "aliases": "" - }, - "1f359": { - "output": "1f359", - "name": "rice ball", - "alpha_code": ":rice_ball:", - "aliases": "" - }, - "1f98d": { - "output": "1f98d", - "name": "gorilla", - "alpha_code": ":gorilla:", - "aliases": "" - }, - "1f35a": { - "output": "1f35a", - "name": "cooked rice", - "alpha_code": ":rice:", - "aliases": "" - }, - "1f35b": { - "output": "1f35b", - "name": "curry rice", - "alpha_code": ":curry:", - "aliases": "" - }, - "1f98c": { - "output": "1f98c", - "name": "deer", - "alpha_code": ":deer:", - "aliases": "" - }, - "1f35c": { - "output": "1f35c", - "name": "steaming bowl", - "alpha_code": ":ramen:", - "aliases": "" - }, - "1f35d": { - "output": "1f35d", - "name": "spaghetti", - "alpha_code": ":spaghetti:", - "aliases": "" - }, - "1f35e": { - "output": "1f35e", - "name": "bread", - "alpha_code": ":bread:", - "aliases": "" - }, - "1f35f": { - "output": "1f35f", - "name": "french fries", - "alpha_code": ":fries:", - "aliases": "" - }, - "1f98b": { - "output": "1f98b", - "name": "butterfly", - "alpha_code": ":butterfly:", - "aliases": "" - }, - "1f360": { - "output": "1f360", - "name": "roasted sweet potato", - "alpha_code": ":sweet_potato:", - "aliases": "" - }, - "1f361": { - "output": "1f361", - "name": "dango", - "alpha_code": ":dango:", - "aliases": "" - }, - "1f98a": { - "output": "1f98a", - "name": "fox face", - "alpha_code": ":fox:", - "aliases": ":fox_face:" - }, - "1f362": { - "output": "1f362", - "name": "oden", - "alpha_code": ":oden:", - "aliases": "" - }, - "1f363": { - "output": "1f363", - "name": "sushi", - "alpha_code": ":sushi:", - "aliases": "" - }, - "1f989": { - "output": "1f989", - "name": "owl", - "alpha_code": ":owl:", - "aliases": "" - }, - "1f364": { - "output": "1f364", - "name": "fried shrimp", - "alpha_code": ":fried_shrimp:", - "aliases": "" - }, - "1f365": { - "output": "1f365", - "name": "fish cake with swirl", - "alpha_code": ":fish_cake:", - "aliases": "" - }, - "1f988": { - "output": "1f988", - "name": "shark", - "alpha_code": ":shark:", - "aliases": "" - }, - "1f366": { - "output": "1f366", - "name": "soft ice cream", - "alpha_code": ":icecream:", - "aliases": "" - }, - "1f987": { - "output": "1f987", - "name": "bat", - "alpha_code": ":bat:", - "aliases": "" - }, - "1f367": { - "output": "1f367", - "name": "shaved ice", - "alpha_code": ":shaved_ice:", - "aliases": "" - }, - "1f1fd": { - "output": "1f1fd", - "name": "regional indicator symbol letter x", - "alpha_code": ":regional_indicator_x:", - "aliases": "" - }, - "1f368": { - "output": "1f368", - "name": "ice cream", - "alpha_code": ":ice_cream:", - "aliases": "" - }, - "1f986": { - "output": "1f986", - "name": "duck", - "alpha_code": ":duck:", - "aliases": "" - }, - "1f369": { - "output": "1f369", - "name": "doughnut", - "alpha_code": ":doughnut:", - "aliases": "" - }, - "1f985": { - "output": "1f985", - "name": "eagle", - "alpha_code": ":eagle:", - "aliases": "" - }, - "1f36a": { - "output": "1f36a", - "name": "cookie", - "alpha_code": ":cookie:", - "aliases": "" - }, - "1f5a4": { - "output": "1f5a4", - "name": "black heart", - "alpha_code": ":black_heart:", - "aliases": "" - }, - "1f36b": { - "output": "1f36b", - "name": "chocolate bar", - "alpha_code": ":chocolate_bar:", - "aliases": "" - }, - "1f36c": { - "output": "1f36c", - "name": "candy", - "alpha_code": ":candy:", - "aliases": "" - }, - "1f36d": { - "output": "1f36d", - "name": "lollipop", - "alpha_code": ":lollipop:", - "aliases": "" - }, - "1f36e": { - "output": "1f36e", - "name": "custard", - "alpha_code": ":custard:", - "aliases": ":pudding:|:flan:" - }, - "1f36f": { - "output": "1f36f", - "name": "honey pot", - "alpha_code": ":honey_pot:", - "aliases": "" - }, - "1f91e": { - "output": "1f91e", - "name": "crossed fingers", - "alpha_code": ":fingers_crossed:", - "aliases": ":hand_with_index_and_middle_finger_crossed:" - }, - "1f370": { - "output": "1f370", - "name": "shortcake", - "alpha_code": ":cake:", - "aliases": "" - }, - "1f371": { - "output": "1f371", - "name": "bento box", - "alpha_code": ":bento:", - "aliases": "" - }, - "1f372": { - "output": "1f372", - "name": "pot of food", - "alpha_code": ":stew:", - "aliases": "" - }, - "1f91d": { - "output": "1f91d", - "name": "handshake", - "alpha_code": ":handshake:", - "aliases": ":shaking_hands:" - }, - "1f373": { - "output": "1f373", - "name": "cooking", - "alpha_code": ":cooking:", - "aliases": "" - }, - "1f374": { - "output": "1f374", - "name": "fork and knife", - "alpha_code": ":fork_and_knife:", - "aliases": "" - }, - "1f375": { - "output": "1f375", - "name": "teacup without handle", - "alpha_code": ":tea:", - "aliases": "" - }, - "1f376": { - "output": "1f376", - "name": "sake", - "alpha_code": ":sake:", - "aliases": "" - }, - "1f377": { - "output": "1f377", - "name": "wine glass", - "alpha_code": ":wine_glass:", - "aliases": "" - }, - "1f378": { - "output": "1f378", - "name": "cocktail glass", - "alpha_code": ":cocktail:", - "aliases": "" - }, - "1f379": { - "output": "1f379", - "name": "tropical drink", - "alpha_code": ":tropical_drink:", - "aliases": "" - }, - "1f37a": { - "output": "1f37a", - "name": "beer mug", - "alpha_code": ":beer:", - "aliases": "" - }, - "1f37b": { - "output": "1f37b", - "name": "clinking beer mugs", - "alpha_code": ":beers:", - "aliases": "" - }, - "1f380": { - "output": "1f380", - "name": "ribbon", - "alpha_code": ":ribbon:", - "aliases": "" - }, - "1f381": { - "output": "1f381", - "name": "wrapped gift", - "alpha_code": ":gift:", - "aliases": "" - }, - "1f382": { - "output": "1f382", - "name": "birthday cake", - "alpha_code": ":birthday:", - "aliases": "" - }, - "1f383": { - "output": "1f383", - "name": "jack-o-lantern", - "alpha_code": ":jack_o_lantern:", - "aliases": "" - }, - "1f91b": { - "output": "1f91b", - "name": "left-facing fist", - "alpha_code": ":left_facing_fist:", - "aliases": ":left_fist:" - }, - "1f91c": { - "output": "1f91c", - "name": "right-facing fist", - "alpha_code": ":right_facing_fist:", - "aliases": ":right_fist:" - }, - "1f384": { - "output": "1f384", - "name": "Christmas tree", - "alpha_code": ":christmas_tree:", - "aliases": "" - }, - "1f385": { - "output": "1f385", - "name": "Santa Claus", - "alpha_code": ":santa:", - "aliases": "" - }, - "1f386": { - "output": "1f386", - "name": "fireworks", - "alpha_code": ":fireworks:", - "aliases": "" - }, - "1f91a": { - "output": "1f91a", - "name": "raised back of hand", - "alpha_code": ":raised_back_of_hand:", - "aliases": ":back_of_hand:" - }, - "1f387": { - "output": "1f387", - "name": "sparkler", - "alpha_code": ":sparkler:", - "aliases": "" - }, - "1f388": { - "output": "1f388", - "name": "balloon", - "alpha_code": ":balloon:", - "aliases": "" - }, - "1f389": { - "output": "1f389", - "name": "party popper", - "alpha_code": ":tada:", - "aliases": "" - }, - "1f38a": { - "output": "1f38a", - "name": "confetti ball", - "alpha_code": ":confetti_ball:", - "aliases": "" - }, - "1f38b": { - "output": "1f38b", - "name": "tanabata tree", - "alpha_code": ":tanabata_tree:", - "aliases": "" - }, - "1f38c": { - "output": "1f38c", - "name": "crossed flags", - "alpha_code": ":crossed_flags:", - "aliases": "" - }, - "1f919": { - "output": "1f919", - "name": "call me hand", - "alpha_code": ":call_me:", - "aliases": ":call_me_hand:" - }, - "1f38d": { - "output": "1f38d", - "name": "pine decoration", - "alpha_code": ":bamboo:", - "aliases": "" - }, - "1f57a": { - "output": "1f57a", - "name": "man dancing", - "alpha_code": ":man_dancing:", - "aliases": ":male_dancer:" - }, - "1f38e": { - "output": "1f38e", - "name": "Japanese dolls", - "alpha_code": ":dolls:", - "aliases": "" - }, - "1f933": { - "output": "1f933", - "name": "selfie", - "alpha_code": ":selfie:", - "aliases": "" - }, - "1f38f": { - "output": "1f38f", - "name": "carp streamer", - "alpha_code": ":flags:", - "aliases": "" - }, - "1f930": { - "output": "1f930", - "name": "pregnant woman", - "alpha_code": ":pregnant_woman:", - "aliases": ":expecting_woman:" - }, - "1f390": { - "output": "1f390", - "name": "wind chime", - "alpha_code": ":wind_chime:", - "aliases": "" - }, - "1f926": { - "output": "1f926", - "name": "person facepalming", - "alpha_code": ":person_facepalming:", - "aliases": ":face_palm:|:facepalm:" - }, - "1f937": { - "output": "1f937", - "name": "person shrugging", - "alpha_code": ":person_shrugging:", - "aliases": ":shrug:" - }, - "1f391": { - "output": "1f391", - "name": "moon viewing ceremony", - "alpha_code": ":rice_scene:", - "aliases": "" - }, - "1f392": { - "output": "1f392", - "name": "school backpack", - "alpha_code": ":school_satchel:", - "aliases": "" - }, - "1f393": { - "output": "1f393", - "name": "graduation cap", - "alpha_code": ":mortar_board:", - "aliases": "" - }, - "1f3a0": { - "output": "1f3a0", - "name": "carousel horse", - "alpha_code": ":carousel_horse:", - "aliases": "" - }, - "1f3a1": { - "output": "1f3a1", - "name": "ferris wheel", - "alpha_code": ":ferris_wheel:", - "aliases": "" - }, - "1f3a2": { - "output": "1f3a2", - "name": "roller coaster", - "alpha_code": ":roller_coaster:", - "aliases": "" - }, - "1f3a3": { - "output": "1f3a3", - "name": "fishing pole", - "alpha_code": ":fishing_pole_and_fish:", - "aliases": "" - }, - "1f3a4": { - "output": "1f3a4", - "name": "microphone", - "alpha_code": ":microphone:", - "aliases": "" - }, - "0023": { - "output": "0023-fe0f", - "name": "pound symbol", - "alpha_code": ":pound_symbol:", - "aliases": "" - }, - "1f3a5": { - "output": "1f3a5", - "name": "movie camera", - "alpha_code": ":movie_camera:", - "aliases": "" - }, - "1f3a6": { - "output": "1f3a6", - "name": "cinema", - "alpha_code": ":cinema:", - "aliases": "" - }, - "1f3a7": { - "output": "1f3a7", - "name": "headphone", - "alpha_code": ":headphones:", - "aliases": "" - }, - "1f936": { - "output": "1f936", - "name": "Mrs. Claus", - "alpha_code": ":mrs_claus:", - "aliases": ":mother_christmas:" - }, - "1f3a8": { - "output": "1f3a8", - "name": "artist palette", - "alpha_code": ":art:", - "aliases": "" - }, - "1f935": { - "output": "1f935", - "name": "man in tuxedo", - "alpha_code": ":man_in_tuxedo:", - "aliases": "" - }, - "1f3a9": { - "output": "1f3a9", - "name": "top hat", - "alpha_code": ":tophat:", - "aliases": "" - }, - "1f3aa": { - "output": "1f3aa", - "name": "circus tent", - "alpha_code": ":circus_tent:", - "aliases": "" - }, - "1f934": { - "output": "1f934", - "name": "prince", - "alpha_code": ":prince:", - "aliases": "" - }, - "1f3ab": { - "output": "1f3ab", - "name": "ticket", - "alpha_code": ":ticket:", - "aliases": "" - }, - "1f3ac": { - "output": "1f3ac", - "name": "clapper board", - "alpha_code": ":clapper:", - "aliases": "" - }, - "1f3ad": { - "output": "1f3ad", - "name": "performing arts", - "alpha_code": ":performing_arts:", - "aliases": "" - }, - "1f927": { - "output": "1f927", - "name": "sneezing face", - "alpha_code": ":sneezing_face:", - "aliases": ":sneeze:" - }, - "1f3ae": { - "output": "1f3ae", - "name": "video game", - "alpha_code": ":video_game:", - "aliases": "" - }, - "1f3af": { - "output": "1f3af", - "name": "direct hit", - "alpha_code": ":dart:", - "aliases": "" - }, - "1f3b0": { - "output": "1f3b0", - "name": "slot machine", - "alpha_code": ":slot_machine:", - "aliases": "" - }, - "1f3b1": { - "output": "1f3b1", - "name": "pool 8 ball", - "alpha_code": ":8ball:", - "aliases": "" - }, - "1f3b2": { - "output": "1f3b2", - "name": "game die", - "alpha_code": ":game_die:", - "aliases": "" - }, - "1f3b3": { - "output": "1f3b3", - "name": "bowling", - "alpha_code": ":bowling:", - "aliases": "" - }, - "1f3b4": { - "output": "1f3b4", - "name": "flower playing cards", - "alpha_code": ":flower_playing_cards:", - "aliases": "" - }, - "1f925": { - "output": "1f925", - "name": "lying face", - "alpha_code": ":lying_face:", - "aliases": ":liar:" - }, - "1f3b5": { - "output": "1f3b5", - "name": "musical note", - "alpha_code": ":musical_note:", - "aliases": "" - }, - "1f3b6": { - "output": "1f3b6", - "name": "musical notes", - "alpha_code": ":notes:", - "aliases": "" - }, - "1f3b7": { - "output": "1f3b7", - "name": "saxophone", - "alpha_code": ":saxophone:", - "aliases": "" - }, - "1f924": { - "output": "1f924", - "name": "drooling face", - "alpha_code": ":drooling_face:", - "aliases": ":drool:" - }, - "1f3b8": { - "output": "1f3b8", - "name": "guitar", - "alpha_code": ":guitar:", - "aliases": "" - }, - "1f3b9": { - "output": "1f3b9", - "name": "musical keyboard", - "alpha_code": ":musical_keyboard:", - "aliases": "" - }, - "1f3ba": { - "output": "1f3ba", - "name": "trumpet", - "alpha_code": ":trumpet:", - "aliases": "" - }, - "1f923": { - "output": "1f923", - "name": "rolling on the floor laughing", - "alpha_code": ":rofl:", - "aliases": ":rolling_on_the_floor_laughing:" - }, - "1f3bb": { - "output": "1f3bb", - "name": "violin", - "alpha_code": ":violin:", - "aliases": "" - }, - "1f3bc": { - "output": "1f3bc", - "name": "musical score", - "alpha_code": ":musical_score:", - "aliases": "" - }, - "1f3bd": { - "output": "1f3bd", - "name": "running shirt", - "alpha_code": ":running_shirt_with_sash:", - "aliases": "" - }, - "1f922": { - "output": "1f922", - "name": "nauseated face", - "alpha_code": ":nauseated_face:", - "aliases": ":sick:" - }, - "1f3be": { - "output": "1f3be", - "name": "tennis", - "alpha_code": ":tennis:", - "aliases": "" - }, - "1f3bf": { - "output": "1f3bf", - "name": "skis", - "alpha_code": ":ski:", - "aliases": "" - }, - "1f3c0": { - "output": "1f3c0", - "name": "basketball", - "alpha_code": ":basketball:", - "aliases": "" - }, - "1f3c1": { - "output": "1f3c1", - "name": "chequered flag", - "alpha_code": ":checkered_flag:", - "aliases": "" - }, - "1f921": { - "output": "1f921", - "name": "clown face", - "alpha_code": ":clown:", - "aliases": ":clown_face:" - }, - "1f3c2": { - "output": "1f3c2", - "name": "snowboarder", - "alpha_code": ":snowboarder:", - "aliases": "" - }, - "1f3c3": { - "output": "1f3c3", - "name": "person running", - "alpha_code": ":person_running:", - "aliases": ":runner:" - }, - "1f3c4": { - "output": "1f3c4", - "name": "person surfing", - "alpha_code": ":person_surfing:", - "aliases": ":surfer:" - }, - "1f3c6": { - "output": "1f3c6", - "name": "trophy", - "alpha_code": ":trophy:", - "aliases": "" - }, - "1f3c8": { - "output": "1f3c8", - "name": "american football", - "alpha_code": ":football:", - "aliases": "" - }, - "1f3ca": { - "output": "1f3ca", - "name": "person swimming", - "alpha_code": ":person_swimming:", - "aliases": ":swimmer:" - }, - "1f3e0": { - "output": "1f3e0", - "name": "house", - "alpha_code": ":house:", - "aliases": "" - }, - "1f3e1": { - "output": "1f3e1", - "name": "house with garden", - "alpha_code": ":house_with_garden:", - "aliases": "" - }, - "1f3e2": { - "output": "1f3e2", - "name": "office building", - "alpha_code": ":office:", - "aliases": "" - }, - "1f3e3": { - "output": "1f3e3", - "name": "Japanese post office", - "alpha_code": ":post_office:", - "aliases": "" - }, - "1f3e5": { - "output": "1f3e5", - "name": "hospital", - "alpha_code": ":hospital:", - "aliases": "" - }, - "1f3e6": { - "output": "1f3e6", - "name": "bank", - "alpha_code": ":bank:", - "aliases": "" - }, - "1f3e7": { - "output": "1f3e7", - "name": "ATM sign", - "alpha_code": ":atm:", - "aliases": "" - }, - "1f3e8": { - "output": "1f3e8", - "name": "hotel", - "alpha_code": ":hotel:", - "aliases": "" - }, - "1f3e9": { - "output": "1f3e9", - "name": "love hotel", - "alpha_code": ":love_hotel:", - "aliases": "" - }, - "1f3ea": { - "output": "1f3ea", - "name": "convenience store", - "alpha_code": ":convenience_store:", - "aliases": "" - }, - "1f3eb": { - "output": "1f3eb", - "name": "school", - "alpha_code": ":school:", - "aliases": "" - }, - "1f3ec": { - "output": "1f3ec", - "name": "department store", - "alpha_code": ":department_store:", - "aliases": "" - }, - "1f920": { - "output": "1f920", - "name": "cowboy hat face", - "alpha_code": ":cowboy:", - "aliases": ":face_with_cowboy_hat:" - }, - "1f3ed": { - "output": "1f3ed", - "name": "factory", - "alpha_code": ":factory:", - "aliases": "" - }, - "1f3ee": { - "output": "1f3ee", - "name": "red paper lantern", - "alpha_code": ":izakaya_lantern:", - "aliases": "" - }, - "1f3ef": { - "output": "1f3ef", - "name": "Japanese castle", - "alpha_code": ":japanese_castle:", - "aliases": "" - }, - "1f3f0": { - "output": "1f3f0", - "name": "castle", - "alpha_code": ":european_castle:", - "aliases": "" - }, - "1f40c": { - "output": "1f40c", - "name": "snail", - "alpha_code": ":snail:", - "aliases": "" - }, - "1f40d": { - "output": "1f40d", - "name": "snake", - "alpha_code": ":snake:", - "aliases": "" - }, - "1f40e": { - "output": "1f40e", - "name": "horse", - "alpha_code": ":racehorse:", - "aliases": "" - }, - "1f411": { - "output": "1f411", - "name": "ewe", - "alpha_code": ":sheep:", - "aliases": "" - }, - "1f412": { - "output": "1f412", - "name": "monkey", - "alpha_code": ":monkey:", - "aliases": "" - }, - "1f414": { - "output": "1f414", - "name": "chicken", - "alpha_code": ":chicken:", - "aliases": "" - }, - "1f417": { - "output": "1f417", - "name": "boar", - "alpha_code": ":boar:", - "aliases": "" - }, - "1f418": { - "output": "1f418", - "name": "elephant", - "alpha_code": ":elephant:", - "aliases": "" - }, - "1f419": { - "output": "1f419", - "name": "octopus", - "alpha_code": ":octopus:", - "aliases": "" - }, - "1f41a": { - "output": "1f41a", - "name": "spiral shell", - "alpha_code": ":shell:", - "aliases": "" - }, - "1f934-1f3fb": { - "output": "1f934-1f3fb", - "name": "prince: light skin tone", - "alpha_code": ":prince_tone1:", - "aliases": "" - }, - "1f41b": { - "output": "1f41b", - "name": "bug", - "alpha_code": ":bug:", - "aliases": "" - }, - "1f41c": { - "output": "1f41c", - "name": "ant", - "alpha_code": ":ant:", - "aliases": "" - }, - "1f41d": { - "output": "1f41d", - "name": "honeybee", - "alpha_code": ":bee:", - "aliases": "" - }, - "1f41e": { - "output": "1f41e", - "name": "lady beetle", - "alpha_code": ":beetle:", - "aliases": "" - }, - "1f41f": { - "output": "1f41f", - "name": "fish", - "alpha_code": ":fish:", - "aliases": "" - }, - "1f420": { - "output": "1f420", - "name": "tropical fish", - "alpha_code": ":tropical_fish:", - "aliases": "" - }, - "1f421": { - "output": "1f421", - "name": "blowfish", - "alpha_code": ":blowfish:", - "aliases": "" - }, - "1f422": { - "output": "1f422", - "name": "turtle", - "alpha_code": ":turtle:", - "aliases": "" - }, - "1f423": { - "output": "1f423", - "name": "hatching chick", - "alpha_code": ":hatching_chick:", - "aliases": "" - }, - "1f424": { - "output": "1f424", - "name": "baby chick", - "alpha_code": ":baby_chick:", - "aliases": "" - }, - "1f425": { - "output": "1f425", - "name": "front-facing baby chick", - "alpha_code": ":hatched_chick:", - "aliases": "" - }, - "1f426": { - "output": "1f426", - "name": "bird", - "alpha_code": ":bird:", - "aliases": "" - }, - "1f427": { - "output": "1f427", - "name": "penguin", - "alpha_code": ":penguin:", - "aliases": "" - }, - "1f428": { - "output": "1f428", - "name": "koala", - "alpha_code": ":koala:", - "aliases": "" - }, - "1f429": { - "output": "1f429", - "name": "poodle", - "alpha_code": ":poodle:", - "aliases": "" - }, - "1f42b": { - "output": "1f42b", - "name": "two-hump camel", - "alpha_code": ":camel:", - "aliases": "" - }, - "1f42c": { - "output": "1f42c", - "name": "dolphin", - "alpha_code": ":dolphin:", - "aliases": "" - }, - "1f42d": { - "output": "1f42d", - "name": "mouse face", - "alpha_code": ":mouse:", - "aliases": "" - }, - "1f42e": { - "output": "1f42e", - "name": "cow face", - "alpha_code": ":cow:", - "aliases": "" - }, - "1f42f": { - "output": "1f42f", - "name": "tiger face", - "alpha_code": ":tiger:", - "aliases": "" - }, - "1f430": { - "output": "1f430", - "name": "rabbit face", - "alpha_code": ":rabbit:", - "aliases": "" - }, - "1f431": { - "output": "1f431", - "name": "cat face", - "alpha_code": ":cat:", - "aliases": "" - }, - "1f432": { - "output": "1f432", - "name": "dragon face", - "alpha_code": ":dragon_face:", - "aliases": "" - }, - "1f433": { - "output": "1f433", - "name": "spouting whale", - "alpha_code": ":whale:", - "aliases": "" - }, - "1f434": { - "output": "1f434", - "name": "horse face", - "alpha_code": ":horse:", - "aliases": "" - }, - "1f435": { - "output": "1f435", - "name": "monkey face", - "alpha_code": ":monkey_face:", - "aliases": "" - }, - "1f436": { - "output": "1f436", - "name": "dog face", - "alpha_code": ":dog:", - "aliases": "" - }, - "1f437": { - "output": "1f437", - "name": "pig face", - "alpha_code": ":pig:", - "aliases": "" - }, - "1f438": { - "output": "1f438", - "name": "frog face", - "alpha_code": ":frog:", - "aliases": "" - }, - "1f439": { - "output": "1f439", - "name": "hamster face", - "alpha_code": ":hamster:", - "aliases": "" - }, - "1f43a": { - "output": "1f43a", - "name": "wolf face", - "alpha_code": ":wolf:", - "aliases": "" - }, - "1f43b": { - "output": "1f43b", - "name": "bear face", - "alpha_code": ":bear:", - "aliases": "" - }, - "1f43c": { - "output": "1f43c", - "name": "panda face", - "alpha_code": ":panda_face:", - "aliases": "" - }, - "1f43d": { - "output": "1f43d", - "name": "pig nose", - "alpha_code": ":pig_nose:", - "aliases": "" - }, - "1f43e": { - "output": "1f43e", - "name": "paw prints", - "alpha_code": ":feet:", - "aliases": ":paw_prints:" - }, - "1f934-1f3fc": { - "output": "1f934-1f3fc", - "name": "prince: medium-light skin tone", - "alpha_code": ":prince_tone2:", - "aliases": "" - }, - "1f440": { - "output": "1f440", - "name": "eyes", - "alpha_code": ":eyes:", - "aliases": "" - }, - "1f442": { - "output": "1f442", - "name": "ear", - "alpha_code": ":ear:", - "aliases": "" - }, - "1f443": { - "output": "1f443", - "name": "nose", - "alpha_code": ":nose:", - "aliases": "" - }, - "1f444": { - "output": "1f444", - "name": "mouth", - "alpha_code": ":lips:", - "aliases": "" - }, - "1f445": { - "output": "1f445", - "name": "tongue", - "alpha_code": ":tongue:", - "aliases": "" - }, - "1f934-1f3fd": { - "output": "1f934-1f3fd", - "name": "prince: medium skin tone", - "alpha_code": ":prince_tone3:", - "aliases": "" - }, - "1f446": { - "output": "1f446", - "name": "backhand index pointing up", - "alpha_code": ":point_up_2:", - "aliases": "" - }, - "1f447": { - "output": "1f447", - "name": "backhand index pointing down", - "alpha_code": ":point_down:", - "aliases": "" - }, - "1f448": { - "output": "1f448", - "name": "backhand index pointing left", - "alpha_code": ":point_left:", - "aliases": "" - }, - "1f449": { - "output": "1f449", - "name": "backhand index pointing right", - "alpha_code": ":point_right:", - "aliases": "" - }, - "1f44a": { - "output": "1f44a", - "name": "oncoming fist", - "alpha_code": ":punch:", - "aliases": "" - }, - "1f44b": { - "output": "1f44b", - "name": "waving hand", - "alpha_code": ":wave:", - "aliases": "" - }, - "1f44c": { - "output": "1f44c", - "name": "OK hand", - "alpha_code": ":ok_hand:", - "aliases": "" - }, - "1f44d": { - "output": "1f44d", - "name": "thumbs up", - "alpha_code": ":thumbsup:", - "aliases": ":+1:|:thumbup:" - }, - "1f44e": { - "output": "1f44e", - "name": "thumbs down", - "alpha_code": ":thumbsdown:", - "aliases": ":-1:|:thumbdown:" - }, - "1f44f": { - "output": "1f44f", - "name": "clapping hands", - "alpha_code": ":clap:", - "aliases": "" - }, - "1f450": { - "output": "1f450", - "name": "open hands", - "alpha_code": ":open_hands:", - "aliases": "" - }, - "1f451": { - "output": "1f451", - "name": "crown", - "alpha_code": ":crown:", - "aliases": "" - }, - "1f452": { - "output": "1f452", - "name": "woman\u2019s hat", - "alpha_code": ":womans_hat:", - "aliases": "" - }, - "1f453": { - "output": "1f453", - "name": "glasses", - "alpha_code": ":eyeglasses:", - "aliases": "" - }, - "1f454": { - "output": "1f454", - "name": "necktie", - "alpha_code": ":necktie:", - "aliases": "" - }, - "1f455": { - "output": "1f455", - "name": "t-shirt", - "alpha_code": ":shirt:", - "aliases": "" - }, - "1f934-1f3fe": { - "output": "1f934-1f3fe", - "name": "prince: medium-dark skin tone", - "alpha_code": ":prince_tone4:", - "aliases": "" - }, - "1f456": { - "output": "1f456", - "name": "jeans", - "alpha_code": ":jeans:", - "aliases": "" - }, - "1f457": { - "output": "1f457", - "name": "dress", - "alpha_code": ":dress:", - "aliases": "" - }, - "1f458": { - "output": "1f458", - "name": "kimono", - "alpha_code": ":kimono:", - "aliases": "" - }, - "1f934-1f3ff": { - "output": "1f934-1f3ff", - "name": "prince: dark skin tone", - "alpha_code": ":prince_tone5:", - "aliases": "" - }, - "1f459": { - "output": "1f459", - "name": "bikini", - "alpha_code": ":bikini:", - "aliases": "" - }, - "1f45a": { - "output": "1f45a", - "name": "woman\u2019s clothes", - "alpha_code": ":womans_clothes:", - "aliases": "" - }, - "1f45b": { - "output": "1f45b", - "name": "purse", - "alpha_code": ":purse:", - "aliases": "" - }, - "1f45c": { - "output": "1f45c", - "name": "handbag", - "alpha_code": ":handbag:", - "aliases": "" - }, - "1f45d": { - "output": "1f45d", - "name": "clutch bag", - "alpha_code": ":pouch:", - "aliases": "" - }, - "1f45e": { - "output": "1f45e", - "name": "man\u2019s shoe", - "alpha_code": ":mans_shoe:", - "aliases": "" - }, - "1f45f": { - "output": "1f45f", - "name": "running shoe", - "alpha_code": ":athletic_shoe:", - "aliases": "" - }, - "1f460": { - "output": "1f460", - "name": "high-heeled shoe", - "alpha_code": ":high_heel:", - "aliases": "" - }, - "1f461": { - "output": "1f461", - "name": "woman\u2019s sandal", - "alpha_code": ":sandal:", - "aliases": "" - }, - "1f462": { - "output": "1f462", - "name": "woman\u2019s boot", - "alpha_code": ":boot:", - "aliases": "" - }, - "1f463": { - "output": "1f463", - "name": "footprints", - "alpha_code": ":footprints:", - "aliases": "" - }, - "1f464": { - "output": "1f464", - "name": "bust in silhouette", - "alpha_code": ":bust_in_silhouette:", - "aliases": "" - }, - "1f936-1f3fb": { - "output": "1f936-1f3fb", - "name": "Mrs. Claus: light skin tone", - "alpha_code": ":mrs_claus_tone1:", - "aliases": ":mother_christmas_tone1:" - }, - "1f466": { - "output": "1f466", - "name": "boy", - "alpha_code": ":boy:", - "aliases": "" - }, - "1f467": { - "output": "1f467", - "name": "girl", - "alpha_code": ":girl:", - "aliases": "" - }, - "1f468": { - "output": "1f468", - "name": "man", - "alpha_code": ":man:", - "aliases": "" - }, - "1f469": { - "output": "1f469", - "name": "woman", - "alpha_code": ":woman:", - "aliases": "" - }, - "1f46a": { - "output": "1f46a", - "name": "family", - "alpha_code": ":family:", - "aliases": "" - }, - "1f46b": { - "output": "1f46b", - "name": "man and woman holding hands", - "alpha_code": ":couple:", - "aliases": "" - }, - "1f46e": { - "output": "1f46e", - "name": "police officer", - "alpha_code": ":police_officer:", - "aliases": ":cop:" - }, - "1f46f": { - "output": "1f46f", - "name": "people with bunny ears partying", - "alpha_code": ":people_with_bunny_ears_partying:", - "aliases": ":dancers:" - }, - "1f470": { - "output": "1f470", - "name": "bride with veil", - "alpha_code": ":bride_with_veil:", - "aliases": "" - }, - "1f471": { - "output": "1f471", - "name": "blond-haired person", - "alpha_code": ":blond_haired_person:", - "aliases": ":person_with_blond_hair:" - }, - "1f472": { - "output": "1f472", - "name": "man with Chinese cap", - "alpha_code": ":man_with_chinese_cap:", - "aliases": ":man_with_gua_pi_mao:" - }, - "1f473": { - "output": "1f473", - "name": "person wearing turban", - "alpha_code": ":person_wearing_turban:", - "aliases": ":man_with_turban:" - }, - "1f474": { - "output": "1f474", - "name": "old man", - "alpha_code": ":older_man:", - "aliases": "" - }, - "1f475": { - "output": "1f475", - "name": "old woman", - "alpha_code": ":older_woman:", - "aliases": ":grandma:" - }, - "1f476": { - "output": "1f476", - "name": "baby", - "alpha_code": ":baby:", - "aliases": "" - }, - "1f477": { - "output": "1f477", - "name": "construction worker", - "alpha_code": ":construction_worker:", - "aliases": "" - }, - "1f478": { - "output": "1f478", - "name": "princess", - "alpha_code": ":princess:", - "aliases": "" - }, - "1f479": { - "output": "1f479", - "name": "ogre", - "alpha_code": ":japanese_ogre:", - "aliases": "" - }, - "1f936-1f3fc": { - "output": "1f936-1f3fc", - "name": "Mrs. Claus: medium-light skin tone", - "alpha_code": ":mrs_claus_tone2:", - "aliases": ":mother_christmas_tone2:" - }, - "1f47a": { - "output": "1f47a", - "name": "goblin", - "alpha_code": ":japanese_goblin:", - "aliases": "" - }, - "1f47b": { - "output": "1f47b", - "name": "ghost", - "alpha_code": ":ghost:", - "aliases": "" - }, - "1f47c": { - "output": "1f47c", - "name": "baby angel", - "alpha_code": ":angel:", - "aliases": "" - }, - "1f47d": { - "output": "1f47d", - "name": "alien", - "alpha_code": ":alien:", - "aliases": "" - }, - "1f47e": { - "output": "1f47e", - "name": "alien monster", - "alpha_code": ":space_invader:", - "aliases": "" - }, - "1f936-1f3fd": { - "output": "1f936-1f3fd", - "name": "Mrs. Claus: medium skin tone", - "alpha_code": ":mrs_claus_tone3:", - "aliases": ":mother_christmas_tone3:" - }, - "1f47f": { - "output": "1f47f", - "name": "angry face with horns", - "alpha_code": ":imp:", - "aliases": "" - }, - "1f480": { - "output": "1f480", - "name": "skull", - "alpha_code": ":skull:", - "aliases": ":skeleton:" - }, - "1f4c7": { - "output": "1f4c7", - "name": "card index", - "alpha_code": ":card_index:", - "aliases": "" - }, - "1f481": { - "output": "1f481", - "name": "person tipping hand", - "alpha_code": ":person_tipping_hand:", - "aliases": ":information_desk_person:" - }, - "1f482": { - "output": "1f482", - "name": "guard", - "alpha_code": ":guard:", - "aliases": ":guardsman:" - }, - "1f483": { - "output": "1f483", - "name": "woman dancing", - "alpha_code": ":dancer:", - "aliases": "" - }, - "1f484": { - "output": "1f484", - "name": "lipstick", - "alpha_code": ":lipstick:", - "aliases": "" - }, - "1f485": { - "output": "1f485", - "name": "nail polish", - "alpha_code": ":nail_care:", - "aliases": "" - }, - "1f4d2": { - "output": "1f4d2", - "name": "ledger", - "alpha_code": ":ledger:", - "aliases": "" - }, - "1f486": { - "output": "1f486", - "name": "person getting massage", - "alpha_code": ":person_getting_massage:", - "aliases": ":massage:" - }, - "1f4d3": { - "output": "1f4d3", - "name": "notebook", - "alpha_code": ":notebook:", - "aliases": "" - }, - "1f487": { - "output": "1f487", - "name": "person getting haircut", - "alpha_code": ":person_getting_haircut:", - "aliases": ":haircut:" - }, - "1f4d4": { - "output": "1f4d4", - "name": "notebook with decorative cover", - "alpha_code": ":notebook_with_decorative_cover:", - "aliases": "" - }, - "1f488": { - "output": "1f488", - "name": "barber pole", - "alpha_code": ":barber:", - "aliases": "" - }, - "1f4d5": { - "output": "1f4d5", - "name": "closed book", - "alpha_code": ":closed_book:", - "aliases": "" - }, - "1f489": { - "output": "1f489", - "name": "syringe", - "alpha_code": ":syringe:", - "aliases": "" - }, - "1f4d6": { - "output": "1f4d6", - "name": "open book", - "alpha_code": ":book:", - "aliases": "" - }, - "1f48a": { - "output": "1f48a", - "name": "pill", - "alpha_code": ":pill:", - "aliases": "" - }, - "1f4d7": { - "output": "1f4d7", - "name": "green book", - "alpha_code": ":green_book:", - "aliases": "" - }, - "1f48b": { - "output": "1f48b", - "name": "kiss mark", - "alpha_code": ":kiss:", - "aliases": "" - }, - "1f4d8": { - "output": "1f4d8", - "name": "blue book", - "alpha_code": ":blue_book:", - "aliases": "" - }, - "1f48c": { - "output": "1f48c", - "name": "love letter", - "alpha_code": ":love_letter:", - "aliases": "" - }, - "1f4d9": { - "output": "1f4d9", - "name": "orange book", - "alpha_code": ":orange_book:", - "aliases": "" - }, - "1f48d": { - "output": "1f48d", - "name": "ring", - "alpha_code": ":ring:", - "aliases": "" - }, - "1f4da": { - "output": "1f4da", - "name": "books", - "alpha_code": ":books:", - "aliases": "" - }, - "1f48e": { - "output": "1f48e", - "name": "gem stone", - "alpha_code": ":gem:", - "aliases": "" - }, - "1f936-1f3fe": { - "output": "1f936-1f3fe", - "name": "Mrs. Claus: medium-dark skin tone", - "alpha_code": ":mrs_claus_tone4:", - "aliases": ":mother_christmas_tone4:" - }, - "1f4db": { - "output": "1f4db", - "name": "name badge", - "alpha_code": ":name_badge:", - "aliases": "" - }, - "1f48f": { - "output": "1f48f", - "name": "kiss", - "alpha_code": ":couplekiss:", - "aliases": "" - }, - "1f4dc": { - "output": "1f4dc", - "name": "scroll", - "alpha_code": ":scroll:", - "aliases": "" - }, - "1f490": { - "output": "1f490", - "name": "bouquet", - "alpha_code": ":bouquet:", - "aliases": "" - }, - "1f4dd": { - "output": "1f4dd", - "name": "memo", - "alpha_code": ":pencil:", - "aliases": ":memo:" - }, - "1f936-1f3ff": { - "output": "1f936-1f3ff", - "name": "Mrs. Claus: dark skin tone", - "alpha_code": ":mrs_claus_tone5:", - "aliases": ":mother_christmas_tone5:" - }, - "1f491": { - "output": "1f491", - "name": "couple with heart", - "alpha_code": ":couple_with_heart:", - "aliases": "" - }, - "1f4de": { - "output": "1f4de", - "name": "telephone receiver", - "alpha_code": ":telephone_receiver:", - "aliases": "" - }, - "1f492": { - "output": "1f492", - "name": "wedding", - "alpha_code": ":wedding:", - "aliases": "" - }, - "1f4df": { - "output": "1f4df", - "name": "pager", - "alpha_code": ":pager:", - "aliases": "" - }, - "1f4e0": { - "output": "1f4e0", - "name": "fax machine", - "alpha_code": ":fax:", - "aliases": "" - }, - "1f493": { - "output": "1f493", - "name": "beating heart", - "alpha_code": ":heartbeat:", - "aliases": "" - }, - "1f4e1": { - "output": "1f4e1", - "name": "satellite antenna", - "alpha_code": ":satellite:", - "aliases": "" - }, - "1f4e2": { - "output": "1f4e2", - "name": "loudspeaker", - "alpha_code": ":loudspeaker:", - "aliases": "" - }, - "1f935-1f3fb": { - "output": "1f935-1f3fb", - "name": "man in tuxedo: light skin tone", - "alpha_code": ":man_in_tuxedo_tone1:", - "aliases": ":tuxedo_tone1:" - }, - "1f494": { - "output": "1f494", - "name": "broken heart", - "alpha_code": ":broken_heart:", - "aliases": "" - }, - "1f4e3": { - "output": "1f4e3", - "name": "megaphone", - "alpha_code": ":mega:", - "aliases": "" - }, - "1f4e4": { - "output": "1f4e4", - "name": "outbox tray", - "alpha_code": ":outbox_tray:", - "aliases": "" - }, - "1f495": { - "output": "1f495", - "name": "two hearts", - "alpha_code": ":two_hearts:", - "aliases": "" - }, - "1f4e5": { - "output": "1f4e5", - "name": "inbox tray", - "alpha_code": ":inbox_tray:", - "aliases": "" - }, - "1f4e6": { - "output": "1f4e6", - "name": "package", - "alpha_code": ":package:", - "aliases": "" - }, - "1f935-1f3fc": { - "output": "1f935-1f3fc", - "name": "man in tuxedo: medium-light skin tone", - "alpha_code": ":man_in_tuxedo_tone2:", - "aliases": ":tuxedo_tone2:" - }, - "1f496": { - "output": "1f496", - "name": "sparkling heart", - "alpha_code": ":sparkling_heart:", - "aliases": "" - }, - "1f4e7": { - "output": "1f4e7", - "name": "e-mail", - "alpha_code": ":e-mail:", - "aliases": ":email:" - }, - "1f4e8": { - "output": "1f4e8", - "name": "incoming envelope", - "alpha_code": ":incoming_envelope:", - "aliases": "" - }, - "1f497": { - "output": "1f497", - "name": "growing heart", - "alpha_code": ":heartpulse:", - "aliases": "" - }, - "1f935-1f3fd": { - "output": "1f935-1f3fd", - "name": "man in tuxedo: medium skin tone", - "alpha_code": ":man_in_tuxedo_tone3:", - "aliases": ":tuxedo_tone3:" - }, - "1f4e9": { - "output": "1f4e9", - "name": "envelope with arrow", - "alpha_code": ":envelope_with_arrow:", - "aliases": "" - }, - "1f4ea": { - "output": "1f4ea", - "name": "closed mailbox with lowered flag", - "alpha_code": ":mailbox_closed:", - "aliases": "" - }, - "1f498": { - "output": "1f498", - "name": "heart with arrow", - "alpha_code": ":cupid:", - "aliases": "" - }, - "1f4eb": { - "output": "1f4eb", - "name": "closed mailbox with raised flag", - "alpha_code": ":mailbox:", - "aliases": "" - }, - "1f935-1f3fe": { - "output": "1f935-1f3fe", - "name": "man in tuxedo: medium-dark skin tone", - "alpha_code": ":man_in_tuxedo_tone4:", - "aliases": ":tuxedo_tone4:" - }, - "1f4ee": { - "output": "1f4ee", - "name": "postbox", - "alpha_code": ":postbox:", - "aliases": "" - }, - "1f499": { - "output": "1f499", - "name": "blue heart", - "alpha_code": ":blue_heart:", - "aliases": "" - }, - "1f4f0": { - "output": "1f4f0", - "name": "newspaper", - "alpha_code": ":newspaper:", - "aliases": "" - }, - "1f935-1f3ff": { - "output": "1f935-1f3ff", - "name": "man in tuxedo: dark skin tone", - "alpha_code": ":man_in_tuxedo_tone5:", - "aliases": ":tuxedo_tone5:" - }, - "1f4f1": { - "output": "1f4f1", - "name": "mobile phone", - "alpha_code": ":iphone:", - "aliases": "" - }, - "1f49a": { - "output": "1f49a", - "name": "green heart", - "alpha_code": ":green_heart:", - "aliases": "" - }, - "1f937-1f3fb": { - "output": "1f937-1f3fb", - "name": "person shrugging: light skin tone", - "alpha_code": ":person_shrugging_tone1:", - "aliases": ":shrug_tone1:" - }, - "1f4f2": { - "output": "1f4f2", - "name": "mobile phone with arrow", - "alpha_code": ":calling:", - "aliases": "" - }, - "1f4f3": { - "output": "1f4f3", - "name": "vibration mode", - "alpha_code": ":vibration_mode:", - "aliases": "" - }, - "1f49b": { - "output": "1f49b", - "name": "yellow heart", - "alpha_code": ":yellow_heart:", - "aliases": "" - }, - "1f937-1f3fc": { - "output": "1f937-1f3fc", - "name": "person shrugging: medium-light skin tone", - "alpha_code": ":person_shrugging_tone2:", - "aliases": ":shrug_tone2:" - }, - "1f4f4": { - "output": "1f4f4", - "name": "mobile phone off", - "alpha_code": ":mobile_phone_off:", - "aliases": "" - }, - "1f4f6": { - "output": "1f4f6", - "name": "antenna bars", - "alpha_code": ":signal_strength:", - "aliases": "" - }, - "1f937-1f3fd": { - "output": "1f937-1f3fd", - "name": "person shrugging: medium skin tone", - "alpha_code": ":person_shrugging_tone3:", - "aliases": ":shrug_tone3:" - }, - "1f49c": { - "output": "1f49c", - "name": "purple heart", - "alpha_code": ":purple_heart:", - "aliases": "" - }, - "1f937-1f3fe": { - "output": "1f937-1f3fe", - "name": "person shrugging: medium-dark skin tone", - "alpha_code": ":person_shrugging_tone4:", - "aliases": ":shrug_tone4:" - }, - "1f4f7": { - "output": "1f4f7", - "name": "camera", - "alpha_code": ":camera:", - "aliases": "" - }, - "1f4f9": { - "output": "1f4f9", - "name": "video camera", - "alpha_code": ":video_camera:", - "aliases": "" - }, - "1f49d": { - "output": "1f49d", - "name": "heart with ribbon", - "alpha_code": ":gift_heart:", - "aliases": "" - }, - "1f4fa": { - "output": "1f4fa", - "name": "television", - "alpha_code": ":tv:", - "aliases": "" - }, - "1f937-1f3ff": { - "output": "1f937-1f3ff", - "name": "person shrugging: dark skin tone", - "alpha_code": ":person_shrugging_tone5:", - "aliases": ":shrug_tone5:" - }, - "1f4fb": { - "output": "1f4fb", - "name": "radio", - "alpha_code": ":radio:", - "aliases": "" - }, - "1f49e": { - "output": "1f49e", - "name": "revolving hearts", - "alpha_code": ":revolving_hearts:", - "aliases": "" - }, - "1f4fc": { - "output": "1f4fc", - "name": "videocassette", - "alpha_code": ":vhs:", - "aliases": "" - }, - "1f926-1f3fb": { - "output": "1f926-1f3fb", - "name": "person facepalming: light skin tone", - "alpha_code": ":person_facepalming_tone1:", - "aliases": ":face_palm_tone1:|:facepalm_tone1:" - }, - "1f503": { - "output": "1f503", - "name": "clockwise vertical arrows", - "alpha_code": ":arrows_clockwise:", - "aliases": "" - }, - "1f49f": { - "output": "1f49f", - "name": "heart decoration", - "alpha_code": ":heart_decoration:", - "aliases": "" - }, - "1f50a": { - "output": "1f50a", - "name": "speaker high volume", - "alpha_code": ":loud_sound:", - "aliases": "" - }, - "1f50b": { - "output": "1f50b", - "name": "battery", - "alpha_code": ":battery:", - "aliases": "" - }, - "1f4a0": { - "output": "1f4a0", - "name": "diamond with a dot", - "alpha_code": ":diamond_shape_with_a_dot_inside:", - "aliases": "" - }, - "1f50c": { - "output": "1f50c", - "name": "electric plug", - "alpha_code": ":electric_plug:", - "aliases": "" - }, - "1f50d": { - "output": "1f50d", - "name": "left-pointing magnifying glass", - "alpha_code": ":mag:", - "aliases": "" - }, - "1f926-1f3fc": { - "output": "1f926-1f3fc", - "name": "person facepalming: medium-light skin tone", - "alpha_code": ":person_facepalming_tone2:", - "aliases": ":face_palm_tone2:|:facepalm_tone2:" - }, - "1f4a1": { - "output": "1f4a1", - "name": "light bulb", - "alpha_code": ":bulb:", - "aliases": "" - }, - "1f50e": { - "output": "1f50e", - "name": "right-pointing magnifying glass", - "alpha_code": ":mag_right:", - "aliases": "" - }, - "1f50f": { - "output": "1f50f", - "name": "locked with pen", - "alpha_code": ":lock_with_ink_pen:", - "aliases": "" - }, - "1f4a2": { - "output": "1f4a2", - "name": "anger symbol", - "alpha_code": ":anger:", - "aliases": "" - }, - "1f510": { - "output": "1f510", - "name": "locked with key", - "alpha_code": ":closed_lock_with_key:", - "aliases": "" - }, - "1f511": { - "output": "1f511", - "name": "key", - "alpha_code": ":key:", - "aliases": "" - }, - "1f4a3": { - "output": "1f4a3", - "name": "bomb", - "alpha_code": ":bomb:", - "aliases": "" - }, - "1f512": { - "output": "1f512", - "name": "locked", - "alpha_code": ":lock:", - "aliases": "" - }, - "1f513": { - "output": "1f513", - "name": "unlocked", - "alpha_code": ":unlock:", - "aliases": "" - }, - "1f4a4": { - "output": "1f4a4", - "name": "zzz", - "alpha_code": ":zzz:", - "aliases": "" - }, - "1f514": { - "output": "1f514", - "name": "bell", - "alpha_code": ":bell:", - "aliases": "" - }, - "1f516": { - "output": "1f516", - "name": "bookmark", - "alpha_code": ":bookmark:", - "aliases": "" - }, - "1f4a5": { - "output": "1f4a5", - "name": "collision", - "alpha_code": ":boom:", - "aliases": "" - }, - "1f926-1f3fd": { - "output": "1f926-1f3fd", - "name": "person facepalming: medium skin tone", - "alpha_code": ":person_facepalming_tone3:", - "aliases": ":face_palm_tone3:|:facepalm_tone3:" - }, - "1f517": { - "output": "1f517", - "name": "link", - "alpha_code": ":link:", - "aliases": "" - }, - "1f518": { - "output": "1f518", - "name": "radio button", - "alpha_code": ":radio_button:", - "aliases": "" - }, - "1f4a6": { - "output": "1f4a6", - "name": "sweat droplets", - "alpha_code": ":sweat_drops:", - "aliases": "" - }, - "1f519": { - "output": "1f519", - "name": "BACK arrow", - "alpha_code": ":back:", - "aliases": "" - }, - "1f51a": { - "output": "1f51a", - "name": "END arrow", - "alpha_code": ":end:", - "aliases": "" - }, - "1f4a7": { - "output": "1f4a7", - "name": "droplet", - "alpha_code": ":droplet:", - "aliases": "" - }, - "1f926-1f3fe": { - "output": "1f926-1f3fe", - "name": "person facepalming: medium-dark skin tone", - "alpha_code": ":person_facepalming_tone4:", - "aliases": ":face_palm_tone4:|:facepalm_tone4:" - }, - "1f51b": { - "output": "1f51b", - "name": "ON! arrow", - "alpha_code": ":on:", - "aliases": "" - }, - "1f51c": { - "output": "1f51c", - "name": "SOON arrow", - "alpha_code": ":soon:", - "aliases": "" - }, - "1f4a8": { - "output": "1f4a8", - "name": "dashing away", - "alpha_code": ":dash:", - "aliases": "" - }, - "1f51d": { - "output": "1f51d", - "name": "TOP arrow", - "alpha_code": ":top:", - "aliases": "" - }, - "1f51e": { - "output": "1f51e", - "name": "no one under eighteen", - "alpha_code": ":underage:", - "aliases": "" - }, - "1f4a9": { - "output": "1f4a9", - "name": "pile of poo", - "alpha_code": ":poop:", - "aliases": ":shit:|:hankey:|:poo:" - }, - "1f51f": { - "output": "1f51f", - "name": "keycap 10", - "alpha_code": ":keycap_ten:", - "aliases": "" - }, - "1f4aa": { - "output": "1f4aa", - "name": "flexed biceps", - "alpha_code": ":muscle:", - "aliases": "" - }, - "1f520": { - "output": "1f520", - "name": "input latin uppercase", - "alpha_code": ":capital_abcd:", - "aliases": "" - }, - "1f521": { - "output": "1f521", - "name": "input latin lowercase", - "alpha_code": ":abcd:", - "aliases": "" - }, - "1f4ab": { - "output": "1f4ab", - "name": "dizzy", - "alpha_code": ":dizzy:", - "aliases": "" - }, - "1f926-1f3ff": { - "output": "1f926-1f3ff", - "name": "person facepalming: dark skin tone", - "alpha_code": ":person_facepalming_tone5:", - "aliases": ":face_palm_tone5:|:facepalm_tone5:" - }, - "1f522": { - "output": "1f522", - "name": "input numbers", - "alpha_code": ":1234:", - "aliases": "" - }, - "1f523": { - "output": "1f523", - "name": "input symbols", - "alpha_code": ":symbols:", - "aliases": "" - }, - "1f4ac": { - "output": "1f4ac", - "name": "speech balloon", - "alpha_code": ":speech_balloon:", - "aliases": "" - }, - "1f524": { - "output": "1f524", - "name": "input latin letters", - "alpha_code": ":abc:", - "aliases": "" - }, - "1f525": { - "output": "1f525", - "name": "fire", - "alpha_code": ":fire:", - "aliases": ":flame:" - }, - "1f4ae": { - "output": "1f4ae", - "name": "white flower", - "alpha_code": ":white_flower:", - "aliases": "" - }, - "1f526": { - "output": "1f526", - "name": "flashlight", - "alpha_code": ":flashlight:", - "aliases": "" - }, - "1f527": { - "output": "1f527", - "name": "wrench", - "alpha_code": ":wrench:", - "aliases": "" - }, - "1f4af": { - "output": "1f4af", - "name": "hundred points", - "alpha_code": ":100:", - "aliases": "" - }, - "1f528": { - "output": "1f528", - "name": "hammer", - "alpha_code": ":hammer:", - "aliases": "" - }, - "1f529": { - "output": "1f529", - "name": "nut and bolt", - "alpha_code": ":nut_and_bolt:", - "aliases": "" - }, - "1f4b0": { - "output": "1f4b0", - "name": "money bag", - "alpha_code": ":moneybag:", - "aliases": "" - }, - "1f52a": { - "output": "1f52a", - "name": "kitchen knife", - "alpha_code": ":knife:", - "aliases": "" - }, - "1f52b": { - "output": "1f52b", - "name": "pistol", - "alpha_code": ":gun:", - "aliases": "" - }, - "1f4b1": { - "output": "1f4b1", - "name": "currency exchange", - "alpha_code": ":currency_exchange:", - "aliases": "" - }, - "1f930-1f3fb": { - "output": "1f930-1f3fb", - "name": "pregnant woman: light skin tone", - "alpha_code": ":pregnant_woman_tone1:", - "aliases": ":expecting_woman_tone1:" - }, - "1f52e": { - "output": "1f52e", - "name": "crystal ball", - "alpha_code": ":crystal_ball:", - "aliases": "" - }, - "1f4b2": { - "output": "1f4b2", - "name": "heavy dollar sign", - "alpha_code": ":heavy_dollar_sign:", - "aliases": "" - }, - "1f52f": { - "output": "1f52f", - "name": "dotted six-pointed star", - "alpha_code": ":six_pointed_star:", - "aliases": "" - }, - "1f4b3": { - "output": "1f4b3", - "name": "credit card", - "alpha_code": ":credit_card:", - "aliases": "" - }, - "1f530": { - "output": "1f530", - "name": "Japanese symbol for beginner", - "alpha_code": ":beginner:", - "aliases": "" - }, - "1f531": { - "output": "1f531", - "name": "trident emblem", - "alpha_code": ":trident:", - "aliases": "" - }, - "1f4b4": { - "output": "1f4b4", - "name": "yen banknote", - "alpha_code": ":yen:", - "aliases": "" - }, - "1f930-1f3fc": { - "output": "1f930-1f3fc", - "name": "pregnant woman: medium-light skin tone", - "alpha_code": ":pregnant_woman_tone2:", - "aliases": ":expecting_woman_tone2:" - }, - "1f532": { - "output": "1f532", - "name": "black square button", - "alpha_code": ":black_square_button:", - "aliases": "" - }, - "1f533": { - "output": "1f533", - "name": "white square button", - "alpha_code": ":white_square_button:", - "aliases": "" - }, - "1f4b5": { - "output": "1f4b5", - "name": "dollar banknote", - "alpha_code": ":dollar:", - "aliases": "" - }, - "1f534": { - "output": "1f534", - "name": "red circle", - "alpha_code": ":red_circle:", - "aliases": "" - }, - "1f535": { - "output": "1f535", - "name": "blue circle", - "alpha_code": ":blue_circle:", - "aliases": "" - }, - "1f4b8": { - "output": "1f4b8", - "name": "money with wings", - "alpha_code": ":money_with_wings:", - "aliases": "" - }, - "1f536": { - "output": "1f536", - "name": "large orange diamond", - "alpha_code": ":large_orange_diamond:", - "aliases": "" - }, - "1f537": { - "output": "1f537", - "name": "large blue diamond", - "alpha_code": ":large_blue_diamond:", - "aliases": "" - }, - "1f4b9": { - "output": "1f4b9", - "name": "chart increasing with yen", - "alpha_code": ":chart:", - "aliases": "" - }, - "1f930-1f3fd": { - "output": "1f930-1f3fd", - "name": "pregnant woman: medium skin tone", - "alpha_code": ":pregnant_woman_tone3:", - "aliases": ":expecting_woman_tone3:" - }, - "1f538": { - "output": "1f538", - "name": "small orange diamond", - "alpha_code": ":small_orange_diamond:", - "aliases": "" - }, - "1f539": { - "output": "1f539", - "name": "small blue diamond", - "alpha_code": ":small_blue_diamond:", - "aliases": "" - }, - "1f4ba": { - "output": "1f4ba", - "name": "seat", - "alpha_code": ":seat:", - "aliases": "" - }, - "1f53a": { - "output": "1f53a", - "name": "red triangle pointed up", - "alpha_code": ":small_red_triangle:", - "aliases": "" - }, - "1f53b": { - "output": "1f53b", - "name": "red triangle pointed down", - "alpha_code": ":small_red_triangle_down:", - "aliases": "" - }, - "1f4bb": { - "output": "1f4bb", - "name": "laptop computer", - "alpha_code": ":computer:", - "aliases": "" - }, - "1f53c": { - "output": "1f53c", - "name": "up button", - "alpha_code": ":arrow_up_small:", - "aliases": "" - }, - "1f4bc": { - "output": "1f4bc", - "name": "briefcase", - "alpha_code": ":briefcase:", - "aliases": "" - }, - "1f53d": { - "output": "1f53d", - "name": "down button", - "alpha_code": ":arrow_down_small:", - "aliases": "" - }, - "1f550": { - "output": "1f550", - "name": "one o\u2019clock", - "alpha_code": ":clock1:", - "aliases": "" - }, - "1f4bd": { - "output": "1f4bd", - "name": "computer disk", - "alpha_code": ":minidisc:", - "aliases": "" - }, - "1f551": { - "output": "1f551", - "name": "two o\u2019clock", - "alpha_code": ":clock2:", - "aliases": "" - }, - "1f4be": { - "output": "1f4be", - "name": "floppy disk", - "alpha_code": ":floppy_disk:", - "aliases": "" - }, - "1f930-1f3fe": { - "output": "1f930-1f3fe", - "name": "pregnant woman: medium-dark skin tone", - "alpha_code": ":pregnant_woman_tone4:", - "aliases": ":expecting_woman_tone4:" - }, - "1f552": { - "output": "1f552", - "name": "three o\u2019clock", - "alpha_code": ":clock3:", - "aliases": "" - }, - "1f4bf": { - "output": "1f4bf", - "name": "optical disk", - "alpha_code": ":cd:", - "aliases": "" - }, - "1f553": { - "output": "1f553", - "name": "four o\u2019clock", - "alpha_code": ":clock4:", - "aliases": "" - }, - "1f4c0": { - "output": "1f4c0", - "name": "dvd", - "alpha_code": ":dvd:", - "aliases": "" - }, - "1f554": { - "output": "1f554", - "name": "five o\u2019clock", - "alpha_code": ":clock5:", - "aliases": "" - }, - "1f555": { - "output": "1f555", - "name": "six o\u2019clock", - "alpha_code": ":clock6:", - "aliases": "" - }, - "1f4c1": { - "output": "1f4c1", - "name": "file folder", - "alpha_code": ":file_folder:", - "aliases": "" - }, - "1f556": { - "output": "1f556", - "name": "seven o\u2019clock", - "alpha_code": ":clock7:", - "aliases": "" - }, - "1f557": { - "output": "1f557", - "name": "eight o\u2019clock", - "alpha_code": ":clock8:", - "aliases": "" - }, - "1f4c2": { - "output": "1f4c2", - "name": "open file folder", - "alpha_code": ":open_file_folder:", - "aliases": "" - }, - "1f558": { - "output": "1f558", - "name": "nine o\u2019clock", - "alpha_code": ":clock9:", - "aliases": "" - }, - "1f559": { - "output": "1f559", - "name": "ten o\u2019clock", - "alpha_code": ":clock10:", - "aliases": "" - }, - "1f4c3": { - "output": "1f4c3", - "name": "page with curl", - "alpha_code": ":page_with_curl:", - "aliases": "" - }, - "1f55a": { - "output": "1f55a", - "name": "eleven o\u2019clock", - "alpha_code": ":clock11:", - "aliases": "" - }, - "1f55b": { - "output": "1f55b", - "name": "twelve o\u2019clock", - "alpha_code": ":clock12:", - "aliases": "" - }, - "1f4c4": { - "output": "1f4c4", - "name": "page facing up", - "alpha_code": ":page_facing_up:", - "aliases": "" - }, - "1f5fb": { - "output": "1f5fb", - "name": "mount fuji", - "alpha_code": ":mount_fuji:", - "aliases": "" - }, - "1f5fc": { - "output": "1f5fc", - "name": "Tokyo tower", - "alpha_code": ":tokyo_tower:", - "aliases": "" - }, - "1f4c5": { - "output": "1f4c5", - "name": "calendar", - "alpha_code": ":date:", - "aliases": "" - }, - "1f5fd": { - "output": "1f5fd", - "name": "Statue of Liberty", - "alpha_code": ":statue_of_liberty:", - "aliases": "" - }, - "1f5fe": { - "output": "1f5fe", - "name": "map of Japan", - "alpha_code": ":japan:", - "aliases": "" - }, - "1f4c6": { - "output": "1f4c6", - "name": "tear-off calendar", - "alpha_code": ":calendar:", - "aliases": "" - }, - "1f5ff": { - "output": "1f5ff", - "name": "moai", - "alpha_code": ":moyai:", - "aliases": "" - }, - "1f601": { - "output": "1f601", - "name": "grinning face with smiling eyes", - "alpha_code": ":grin:", - "aliases": "" - }, - "1f602": { - "output": "1f602", - "name": "face with tears of joy", - "alpha_code": ":joy:", - "aliases": "" - }, - "1f603": { - "output": "1f603", - "name": "smiling face with open mouth", - "alpha_code": ":smiley:", - "aliases": "" - }, - "1f4c8": { - "output": "1f4c8", - "name": "chart increasing", - "alpha_code": ":chart_with_upwards_trend:", - "aliases": "" - }, - "1f604": { - "output": "1f604", - "name": "smiling face with open mouth & smiling eyes", - "alpha_code": ":smile:", - "aliases": "" - }, - "1f605": { - "output": "1f605", - "name": "smiling face with open mouth & cold sweat", - "alpha_code": ":sweat_smile:", - "aliases": "" - }, - "1f4c9": { - "output": "1f4c9", - "name": "chart decreasing", - "alpha_code": ":chart_with_downwards_trend:", - "aliases": "" - }, - "1f606": { - "output": "1f606", - "name": "smiling face with open mouth & closed eyes", - "alpha_code": ":laughing:", - "aliases": ":satisfied:" - }, - "1f609": { - "output": "1f609", - "name": "winking face", - "alpha_code": ":wink:", - "aliases": "" - }, - "1f4ca": { - "output": "1f4ca", - "name": "bar chart", - "alpha_code": ":bar_chart:", - "aliases": "" - }, - "1f60a": { - "output": "1f60a", - "name": "smiling face with smiling eyes", - "alpha_code": ":blush:", - "aliases": "" - }, - "1f60b": { - "output": "1f60b", - "name": "face savouring delicious food", - "alpha_code": ":yum:", - "aliases": "" - }, - "1f4cb": { - "output": "1f4cb", - "name": "clipboard", - "alpha_code": ":clipboard:", - "aliases": "" - }, - "1f60c": { - "output": "1f60c", - "name": "relieved face", - "alpha_code": ":relieved:", - "aliases": "" - }, - "1f60d": { - "output": "1f60d", - "name": "smiling face with heart-eyes", - "alpha_code": ":heart_eyes:", - "aliases": "" - }, - "1f4cc": { - "output": "1f4cc", - "name": "pushpin", - "alpha_code": ":pushpin:", - "aliases": "" - }, - "1f60f": { - "output": "1f60f", - "name": "smirking face", - "alpha_code": ":smirk:", - "aliases": "" - }, - "1f612": { - "output": "1f612", - "name": "unamused face", - "alpha_code": ":unamused:", - "aliases": "" - }, - "1f4cd": { - "output": "1f4cd", - "name": "round pushpin", - "alpha_code": ":round_pushpin:", - "aliases": "" - }, - "1f613": { - "output": "1f613", - "name": "face with cold sweat", - "alpha_code": ":sweat:", - "aliases": "" - }, - "1f614": { - "output": "1f614", - "name": "pensive face", - "alpha_code": ":pensive:", - "aliases": "" - }, - "1f4ce": { - "output": "1f4ce", - "name": "paperclip", - "alpha_code": ":paperclip:", - "aliases": "" - }, - "1f616": { - "output": "1f616", - "name": "confounded face", - "alpha_code": ":confounded:", - "aliases": "" - }, - "1f618": { - "output": "1f618", - "name": "face blowing a kiss", - "alpha_code": ":kissing_heart:", - "aliases": "" - }, - "1f930-1f3ff": { - "output": "1f930-1f3ff", - "name": "pregnant woman: dark skin tone", - "alpha_code": ":pregnant_woman_tone5:", - "aliases": ":expecting_woman_tone5:" - }, - "1f4cf": { - "output": "1f4cf", - "name": "straight ruler", - "alpha_code": ":straight_ruler:", - "aliases": "" - }, - "1f61a": { - "output": "1f61a", - "name": "kissing face with closed eyes", - "alpha_code": ":kissing_closed_eyes:", - "aliases": "" - }, - "1f61c": { - "output": "1f61c", - "name": "face with stuck-out tongue & winking eye", - "alpha_code": ":stuck_out_tongue_winking_eye:", - "aliases": "" - }, - "1f4d0": { - "output": "1f4d0", - "name": "triangular ruler", - "alpha_code": ":triangular_ruler:", - "aliases": "" - }, - "1f61d": { - "output": "1f61d", - "name": "face with stuck-out tongue & closed eyes", - "alpha_code": ":stuck_out_tongue_closed_eyes:", - "aliases": "" - }, - "1f61e": { - "output": "1f61e", - "name": "disappointed face", - "alpha_code": ":disappointed:", - "aliases": "" - }, - "1f4d1": { - "output": "1f4d1", - "name": "bookmark tabs", - "alpha_code": ":bookmark_tabs:", - "aliases": "" - }, - "1f620": { - "output": "1f620", - "name": "angry face", - "alpha_code": ":angry:", - "aliases": "" - }, - "1f621": { - "output": "1f621", - "name": "pouting face", - "alpha_code": ":rage:", - "aliases": "" - }, - "1f622": { - "output": "1f622", - "name": "crying face", - "alpha_code": ":cry:", - "aliases": "" - }, - "1f623": { - "output": "1f623", - "name": "persevering face", - "alpha_code": ":persevere:", - "aliases": "" - }, - "1f624": { - "output": "1f624", - "name": "face with steam from nose", - "alpha_code": ":triumph:", - "aliases": "" - }, - "1f625": { - "output": "1f625", - "name": "disappointed but relieved face", - "alpha_code": ":disappointed_relieved:", - "aliases": "" - }, - "1f628": { - "output": "1f628", - "name": "fearful face", - "alpha_code": ":fearful:", - "aliases": "" - }, - "1f629": { - "output": "1f629", - "name": "weary face", - "alpha_code": ":weary:", - "aliases": "" - }, - "1f62a": { - "output": "1f62a", - "name": "sleepy face", - "alpha_code": ":sleepy:", - "aliases": "" - }, - "1f62b": { - "output": "1f62b", - "name": "tired face", - "alpha_code": ":tired_face:", - "aliases": "" - }, - "1f62d": { - "output": "1f62d", - "name": "loudly crying face", - "alpha_code": ":sob:", - "aliases": "" - }, - "1f630": { - "output": "1f630", - "name": "face with open mouth & cold sweat", - "alpha_code": ":cold_sweat:", - "aliases": "" - }, - "1f631": { - "output": "1f631", - "name": "face screaming in fear", - "alpha_code": ":scream:", - "aliases": "" - }, - "1f632": { - "output": "1f632", - "name": "astonished face", - "alpha_code": ":astonished:", - "aliases": "" - }, - "1f633": { - "output": "1f633", - "name": "flushed face", - "alpha_code": ":flushed:", - "aliases": "" - }, - "1f635": { - "output": "1f635", - "name": "dizzy face", - "alpha_code": ":dizzy_face:", - "aliases": "" - }, - "1f637": { - "output": "1f637", - "name": "face with medical mask", - "alpha_code": ":mask:", - "aliases": "" - }, - "1f638": { - "output": "1f638", - "name": "grinning cat face with smiling eyes", - "alpha_code": ":smile_cat:", - "aliases": "" - }, - "1f639": { - "output": "1f639", - "name": "cat face with tears of joy", - "alpha_code": ":joy_cat:", - "aliases": "" - }, - "1f63a": { - "output": "1f63a", - "name": "smiling cat face with open mouth", - "alpha_code": ":smiley_cat:", - "aliases": "" - }, - "1f63b": { - "output": "1f63b", - "name": "smiling cat face with heart-eyes", - "alpha_code": ":heart_eyes_cat:", - "aliases": "" - }, - "1f63c": { - "output": "1f63c", - "name": "cat face with wry smile", - "alpha_code": ":smirk_cat:", - "aliases": "" - }, - "1f63d": { - "output": "1f63d", - "name": "kissing cat face with closed eyes", - "alpha_code": ":kissing_cat:", - "aliases": "" - }, - "1f63e": { - "output": "1f63e", - "name": "pouting cat face", - "alpha_code": ":pouting_cat:", - "aliases": "" - }, - "1f63f": { - "output": "1f63f", - "name": "crying cat face", - "alpha_code": ":crying_cat_face:", - "aliases": "" - }, - "1f640": { - "output": "1f640", - "name": "weary cat face", - "alpha_code": ":scream_cat:", - "aliases": "" - }, - "1f645": { - "output": "1f645", - "name": "person gesturing NO", - "alpha_code": ":person_gesturing_no:", - "aliases": ":no_good:" - }, - "1f646": { - "output": "1f646", - "name": "person gesturing OK", - "alpha_code": ":person_gesturing_ok:", - "aliases": ":ok_woman:" - }, - "1f647": { - "output": "1f647", - "name": "person bowing", - "alpha_code": ":person_bowing:", - "aliases": ":bow:" - }, - "1f648": { - "output": "1f648", - "name": "see-no-evil monkey", - "alpha_code": ":see_no_evil:", - "aliases": "" - }, - "1f57a-1f3fb": { - "output": "1f57a-1f3fb", - "name": "man dancing: light skin tone", - "alpha_code": ":man_dancing_tone1:", - "aliases": ":male_dancer_tone1:" - }, - "1f649": { - "output": "1f649", - "name": "hear-no-evil monkey", - "alpha_code": ":hear_no_evil:", - "aliases": "" - }, - "1f64a": { - "output": "1f64a", - "name": "speak-no-evil monkey", - "alpha_code": ":speak_no_evil:", - "aliases": "" - }, - "1f57a-1f3fc": { - "output": "1f57a-1f3fc", - "name": "man dancing: medium-light skin tone", - "alpha_code": ":man_dancing_tone2:", - "aliases": ":male_dancer_tone2:" - }, - "1f64b": { - "output": "1f64b", - "name": "person raising hand", - "alpha_code": ":person_raising_hand:", - "aliases": ":raising_hand:" - }, - "1f64c": { - "output": "1f64c", - "name": "raising hands", - "alpha_code": ":raised_hands:", - "aliases": "" - }, - "1f64d": { - "output": "1f64d", - "name": "person frowning", - "alpha_code": ":person_frowning:", - "aliases": "" - }, - "1f64e": { - "output": "1f64e", - "name": "person pouting", - "alpha_code": ":person_pouting:", - "aliases": ":person_with_pouting_face:" - }, - "1f64f": { - "output": "1f64f", - "name": "folded hands", - "alpha_code": ":pray:", - "aliases": "" - }, - "1f680": { - "output": "1f680", - "name": "rocket", - "alpha_code": ":rocket:", - "aliases": "" - }, - "1f683": { - "output": "1f683", - "name": "railway car", - "alpha_code": ":railway_car:", - "aliases": "" - }, - "1f684": { - "output": "1f684", - "name": "high-speed train", - "alpha_code": ":bullettrain_side:", - "aliases": "" - }, - "1f685": { - "output": "1f685", - "name": "high-speed train with bullet nose", - "alpha_code": ":bullettrain_front:", - "aliases": "" - }, - "1f687": { - "output": "1f687", - "name": "metro", - "alpha_code": ":metro:", - "aliases": "" - }, - "1f689": { - "output": "1f689", - "name": "station", - "alpha_code": ":station:", - "aliases": "" - }, - "1f68c": { - "output": "1f68c", - "name": "bus", - "alpha_code": ":bus:", - "aliases": "" - }, - "1f68f": { - "output": "1f68f", - "name": "bus stop", - "alpha_code": ":busstop:", - "aliases": "" - }, - "1f691": { - "output": "1f691", - "name": "ambulance", - "alpha_code": ":ambulance:", - "aliases": "" - }, - "1f692": { - "output": "1f692", - "name": "fire engine", - "alpha_code": ":fire_engine:", - "aliases": "" - }, - "1f693": { - "output": "1f693", - "name": "police car", - "alpha_code": ":police_car:", - "aliases": "" - }, - "1f695": { - "output": "1f695", - "name": "taxi", - "alpha_code": ":taxi:", - "aliases": "" - }, - "1f697": { - "output": "1f697", - "name": "automobile", - "alpha_code": ":red_car:", - "aliases": "" - }, - "1f699": { - "output": "1f699", - "name": "sport utility vehicle", - "alpha_code": ":blue_car:", - "aliases": "" - }, - "1f69a": { - "output": "1f69a", - "name": "delivery truck", - "alpha_code": ":truck:", - "aliases": "" - }, - "1f6a2": { - "output": "1f6a2", - "name": "ship", - "alpha_code": ":ship:", - "aliases": "" - }, - "1f6a4": { - "output": "1f6a4", - "name": "speedboat", - "alpha_code": ":speedboat:", - "aliases": "" - }, - "1f6a5": { - "output": "1f6a5", - "name": "horizontal traffic light", - "alpha_code": ":traffic_light:", - "aliases": "" - }, - "1f6a7": { - "output": "1f6a7", - "name": "construction", - "alpha_code": ":construction:", - "aliases": "" - }, - "1f6a8": { - "output": "1f6a8", - "name": "police car light", - "alpha_code": ":rotating_light:", - "aliases": "" - }, - "1f6a9": { - "output": "1f6a9", - "name": "triangular flag", - "alpha_code": ":triangular_flag_on_post:", - "aliases": "" - }, - "1f6aa": { - "output": "1f6aa", - "name": "door", - "alpha_code": ":door:", - "aliases": "" - }, - "1f57a-1f3fd": { - "output": "1f57a-1f3fd", - "name": "man dancing: medium skin tone", - "alpha_code": ":man_dancing_tone3:", - "aliases": ":male_dancer_tone3:" - }, - "1f6ab": { - "output": "1f6ab", - "name": "prohibited", - "alpha_code": ":no_entry_sign:", - "aliases": "" - }, - "1f6ac": { - "output": "1f6ac", - "name": "cigarette", - "alpha_code": ":smoking:", - "aliases": "" - }, - "1f6ad": { - "output": "1f6ad", - "name": "no smoking", - "alpha_code": ":no_smoking:", - "aliases": "" - }, - "1f6b2": { - "output": "1f6b2", - "name": "bicycle", - "alpha_code": ":bike:", - "aliases": "" - }, - "1f6b6": { - "output": "1f6b6", - "name": "person walking", - "alpha_code": ":person_walking:", - "aliases": ":walking:" - }, - "1f6b9": { - "output": "1f6b9", - "name": "men\u2019s room", - "alpha_code": ":mens:", - "aliases": "" - }, - "1f6ba": { - "output": "1f6ba", - "name": "women\u2019s room", - "alpha_code": ":womens:", - "aliases": "" - }, - "1f57a-1f3fe": { - "output": "1f57a-1f3fe", - "name": "man dancing: medium-dark skin tone", - "alpha_code": ":man_dancing_tone4:", - "aliases": ":male_dancer_tone4:" - }, - "1f6bb": { - "output": "1f6bb", - "name": "restroom", - "alpha_code": ":restroom:", - "aliases": "" - }, - "1f6bc": { - "output": "1f6bc", - "name": "baby symbol", - "alpha_code": ":baby_symbol:", - "aliases": "" - }, - "1f57a-1f3ff": { - "output": "1f57a-1f3ff", - "name": "man dancing: dark skin tone", - "alpha_code": ":man_dancing_tone5:", - "aliases": ":male_dancer_tone5:" - }, - "1f6bd": { - "output": "1f6bd", - "name": "toilet", - "alpha_code": ":toilet:", - "aliases": "" - }, - "1f6be": { - "output": "1f6be", - "name": "water closet", - "alpha_code": ":wc:", - "aliases": "" - }, - "1f933-1f3fb": { - "output": "1f933-1f3fb", - "name": "selfie: light skin tone", - "alpha_code": ":selfie_tone1:", - "aliases": "" - }, - "1f6c0": { - "output": "1f6c0", - "name": "person taking bath", - "alpha_code": ":bath:", - "aliases": "" - }, - "1f918": { - "output": "1f918", - "name": "sign of the horns", - "alpha_code": ":metal:", - "aliases": ":sign_of_the_horns:" - }, - "1f600": { - "output": "1f600", - "name": "grinning face", - "alpha_code": ":grinning:", - "aliases": "" - }, - "1f607": { - "output": "1f607", - "name": "smiling face with halo", - "alpha_code": ":innocent:", - "aliases": "" - }, - "1f608": { - "output": "1f608", - "name": "smiling face with horns", - "alpha_code": ":smiling_imp:", - "aliases": "" - }, - "1f60e": { - "output": "1f60e", - "name": "smiling face with sunglasses", - "alpha_code": ":sunglasses:", - "aliases": "" - }, - "1f610": { - "output": "1f610", - "name": "neutral face", - "alpha_code": ":neutral_face:", - "aliases": "" - }, - "1f611": { - "output": "1f611", - "name": "expressionless face", - "alpha_code": ":expressionless:", - "aliases": "" - }, - "1f615": { - "output": "1f615", - "name": "confused face", - "alpha_code": ":confused:", - "aliases": "" - }, - "1f617": { - "output": "1f617", - "name": "kissing face", - "alpha_code": ":kissing:", - "aliases": "" - }, - "1f933-1f3fc": { - "output": "1f933-1f3fc", - "name": "selfie: medium-light skin tone", - "alpha_code": ":selfie_tone2:", - "aliases": "" - }, - "1f619": { - "output": "1f619", - "name": "kissing face with smiling eyes", - "alpha_code": ":kissing_smiling_eyes:", - "aliases": "" - }, - "1f61b": { - "output": "1f61b", - "name": "face with stuck-out tongue", - "alpha_code": ":stuck_out_tongue:", - "aliases": "" - }, - "1f61f": { - "output": "1f61f", - "name": "worried face", - "alpha_code": ":worried:", - "aliases": "" - }, - "1f626": { - "output": "1f626", - "name": "frowning face with open mouth", - "alpha_code": ":frowning:", - "aliases": "" - }, - "1f627": { - "output": "1f627", - "name": "anguished face", - "alpha_code": ":anguished:", - "aliases": "" - }, - "1f62c": { - "output": "1f62c", - "name": "grimacing face", - "alpha_code": ":grimacing:", - "aliases": "" - }, - "1f62e": { - "output": "1f62e", - "name": "face with open mouth", - "alpha_code": ":open_mouth:", - "aliases": "" - }, - "1f62f": { - "output": "1f62f", - "name": "hushed face", - "alpha_code": ":hushed:", - "aliases": "" - }, - "1f634": { - "output": "1f634", - "name": "sleeping face", - "alpha_code": ":sleeping:", - "aliases": "" - }, - "1f636": { - "output": "1f636", - "name": "face without mouth", - "alpha_code": ":no_mouth:", - "aliases": "" - }, - "1f681": { - "output": "1f681", - "name": "helicopter", - "alpha_code": ":helicopter:", - "aliases": "" - }, - "1f682": { - "output": "1f682", - "name": "locomotive", - "alpha_code": ":steam_locomotive:", - "aliases": "" - }, - "1f686": { - "output": "1f686", - "name": "train", - "alpha_code": ":train2:", - "aliases": "" - }, - "1f688": { - "output": "1f688", - "name": "light rail", - "alpha_code": ":light_rail:", - "aliases": "" - }, - "1f68a": { - "output": "1f68a", - "name": "tram", - "alpha_code": ":tram:", - "aliases": "" - }, - "1f68d": { - "output": "1f68d", - "name": "oncoming bus", - "alpha_code": ":oncoming_bus:", - "aliases": "" - }, - "1f68e": { - "output": "1f68e", - "name": "trolleybus", - "alpha_code": ":trolleybus:", - "aliases": "" - }, - "1f690": { - "output": "1f690", - "name": "minibus", - "alpha_code": ":minibus:", - "aliases": "" - }, - "1f694": { - "output": "1f694", - "name": "oncoming police car", - "alpha_code": ":oncoming_police_car:", - "aliases": "" - }, - "1f696": { - "output": "1f696", - "name": "oncoming taxi", - "alpha_code": ":oncoming_taxi:", - "aliases": "" - }, - "1f698": { - "output": "1f698", - "name": "oncoming automobile", - "alpha_code": ":oncoming_automobile:", - "aliases": "" - }, - "1f69b": { - "output": "1f69b", - "name": "articulated lorry", - "alpha_code": ":articulated_lorry:", - "aliases": "" - }, - "1f933-1f3fd": { - "output": "1f933-1f3fd", - "name": "selfie: medium skin tone", - "alpha_code": ":selfie_tone3:", - "aliases": "" - }, - "1f69c": { - "output": "1f69c", - "name": "tractor", - "alpha_code": ":tractor:", - "aliases": "" - }, - "1f69d": { - "output": "1f69d", - "name": "monorail", - "alpha_code": ":monorail:", - "aliases": "" - }, - "1f69e": { - "output": "1f69e", - "name": "mountain railway", - "alpha_code": ":mountain_railway:", - "aliases": "" - }, - "1f69f": { - "output": "1f69f", - "name": "suspension railway", - "alpha_code": ":suspension_railway:", - "aliases": "" - }, - "1f6a0": { - "output": "1f6a0", - "name": "mountain cableway", - "alpha_code": ":mountain_cableway:", - "aliases": "" - }, - "1f6a1": { - "output": "1f6a1", - "name": "aerial tramway", - "alpha_code": ":aerial_tramway:", - "aliases": "" - }, - "1f6a3": { - "output": "1f6a3", - "name": "person rowing boat", - "alpha_code": ":person_rowing_boat:", - "aliases": ":rowboat:" - }, - "1f6a6": { - "output": "1f6a6", - "name": "vertical traffic light", - "alpha_code": ":vertical_traffic_light:", - "aliases": "" - }, - "1f933-1f3fe": { - "output": "1f933-1f3fe", - "name": "selfie: medium-dark skin tone", - "alpha_code": ":selfie_tone4:", - "aliases": "" - }, - "1f6ae": { - "output": "1f6ae", - "name": "litter in bin sign", - "alpha_code": ":put_litter_in_its_place:", - "aliases": "" - }, - "1f6af": { - "output": "1f6af", - "name": "no littering", - "alpha_code": ":do_not_litter:", - "aliases": "" - }, - "1f933-1f3ff": { - "output": "1f933-1f3ff", - "name": "selfie: dark skin tone", - "alpha_code": ":selfie_tone5:", - "aliases": "" - }, - "1f6b0": { - "output": "1f6b0", - "name": "potable water", - "alpha_code": ":potable_water:", - "aliases": "" - }, - "1f6b1": { - "output": "1f6b1", - "name": "non-potable water", - "alpha_code": ":non-potable_water:", - "aliases": "" - }, - "1f6b3": { - "output": "1f6b3", - "name": "no bicycles", - "alpha_code": ":no_bicycles:", - "aliases": "" - }, - "1f91e-1f3fb": { - "output": "1f91e-1f3fb", - "name": "crossed fingers: light skin tone", - "alpha_code": ":fingers_crossed_tone1:", - "aliases": ":hand_with_index_and_middle_fingers_crossed_tone1:" - }, - "1f6b4": { - "output": "1f6b4", - "name": "person biking", - "alpha_code": ":person_biking:", - "aliases": ":bicyclist:" - }, - "1f6b5": { - "output": "1f6b5", - "name": "person mountain biking", - "alpha_code": ":person_mountain_biking:", - "aliases": ":mountain_bicyclist:" - }, - "1f6b7": { - "output": "1f6b7", - "name": "no pedestrians", - "alpha_code": ":no_pedestrians:", - "aliases": "" - }, - "1f6b8": { - "output": "1f6b8", - "name": "children crossing", - "alpha_code": ":children_crossing:", - "aliases": "" - }, - "1f6bf": { - "output": "1f6bf", - "name": "shower", - "alpha_code": ":shower:", - "aliases": "" - }, - "1f6c1": { - "output": "1f6c1", - "name": "bathtub", - "alpha_code": ":bathtub:", - "aliases": "" - }, - "1f6c2": { - "output": "1f6c2", - "name": "passport control", - "alpha_code": ":passport_control:", - "aliases": "" - }, - "1f91e-1f3fc": { - "output": "1f91e-1f3fc", - "name": "crossed fingers: medium-light skin tone", - "alpha_code": ":fingers_crossed_tone2:", - "aliases": ":hand_with_index_and_middle_fingers_crossed_tone2:" - }, - "1f6c3": { - "output": "1f6c3", - "name": "customs", - "alpha_code": ":customs:", - "aliases": "" - }, - "1f6c4": { - "output": "1f6c4", - "name": "baggage claim", - "alpha_code": ":baggage_claim:", - "aliases": "" - }, - "1f91e-1f3fd": { - "output": "1f91e-1f3fd", - "name": "crossed fingers: medium skin tone", - "alpha_code": ":fingers_crossed_tone3:", - "aliases": ":hand_with_index_and_middle_fingers_crossed_tone3:" - }, - "1f6c5": { - "output": "1f6c5", - "name": "left luggage", - "alpha_code": ":left_luggage:", - "aliases": "" - }, - "1f30d": { - "output": "1f30d", - "name": "globe showing Europe-Africa", - "alpha_code": ":earth_africa:", - "aliases": "" - }, - "1f30e": { - "output": "1f30e", - "name": "globe showing Americas", - "alpha_code": ":earth_americas:", - "aliases": "" - }, - "1f310": { - "output": "1f310", - "name": "globe with meridians", - "alpha_code": ":globe_with_meridians:", - "aliases": "" - }, - "1f312": { - "output": "1f312", - "name": "waxing crescent moon", - "alpha_code": ":waxing_crescent_moon:", - "aliases": "" - }, - "1f316": { - "output": "1f316", - "name": "waning gibbous moon", - "alpha_code": ":waning_gibbous_moon:", - "aliases": "" - }, - "1f317": { - "output": "1f317", - "name": "last quarter moon", - "alpha_code": ":last_quarter_moon:", - "aliases": "" - }, - "1f318": { - "output": "1f318", - "name": "waning crescent moon", - "alpha_code": ":waning_crescent_moon:", - "aliases": "" - }, - "1f31a": { - "output": "1f31a", - "name": "new moon face", - "alpha_code": ":new_moon_with_face:", - "aliases": "" - }, - "1f31c": { - "output": "1f31c", - "name": "last quarter moon with face", - "alpha_code": ":last_quarter_moon_with_face:", - "aliases": "" - }, - "1f31d": { - "output": "1f31d", - "name": "full moon with face", - "alpha_code": ":full_moon_with_face:", - "aliases": "" - }, - "1f31e": { - "output": "1f31e", - "name": "sun with face", - "alpha_code": ":sun_with_face:", - "aliases": "" - }, - "1f332": { - "output": "1f332", - "name": "evergreen tree", - "alpha_code": ":evergreen_tree:", - "aliases": "" - }, - "1f333": { - "output": "1f333", - "name": "deciduous tree", - "alpha_code": ":deciduous_tree:", - "aliases": "" - }, - "1f34b": { - "output": "1f34b", - "name": "lemon", - "alpha_code": ":lemon:", - "aliases": "" - }, - "1f91e-1f3fe": { - "output": "1f91e-1f3fe", - "name": "crossed fingers: medium-dark skin tone", - "alpha_code": ":fingers_crossed_tone4:", - "aliases": ":hand_with_index_and_middle_fingers_crossed_tone4:" - }, - "1f350": { - "output": "1f350", - "name": "pear", - "alpha_code": ":pear:", - "aliases": "" - }, - "1f37c": { - "output": "1f37c", - "name": "baby bottle", - "alpha_code": ":baby_bottle:", - "aliases": "" - }, - "1f3c7": { - "output": "1f3c7", - "name": "horse racing", - "alpha_code": ":horse_racing:", - "aliases": "" - }, - "1f3c9": { - "output": "1f3c9", - "name": "rugby football", - "alpha_code": ":rugby_football:", - "aliases": "" - }, - "1f3e4": { - "output": "1f3e4", - "name": "post office", - "alpha_code": ":european_post_office:", - "aliases": "" - }, - "1f400": { - "output": "1f400", - "name": "rat", - "alpha_code": ":rat:", - "aliases": "" - }, - "1f401": { - "output": "1f401", - "name": "mouse", - "alpha_code": ":mouse2:", - "aliases": "" - }, - "1f402": { - "output": "1f402", - "name": "ox", - "alpha_code": ":ox:", - "aliases": "" - }, - "1f403": { - "output": "1f403", - "name": "water buffalo", - "alpha_code": ":water_buffalo:", - "aliases": "" - }, - "1f404": { - "output": "1f404", - "name": "cow", - "alpha_code": ":cow2:", - "aliases": "" - }, - "1f405": { - "output": "1f405", - "name": "tiger", - "alpha_code": ":tiger2:", - "aliases": "" - }, - "1f406": { - "output": "1f406", - "name": "leopard", - "alpha_code": ":leopard:", - "aliases": "" - }, - "1f407": { - "output": "1f407", - "name": "rabbit", - "alpha_code": ":rabbit2:", - "aliases": "" - }, - "1f408": { - "output": "1f408", - "name": "cat", - "alpha_code": ":cat2:", - "aliases": "" - }, - "1f409": { - "output": "1f409", - "name": "dragon", - "alpha_code": ":dragon:", - "aliases": "" - }, - "1f40a": { - "output": "1f40a", - "name": "crocodile", - "alpha_code": ":crocodile:", - "aliases": "" - }, - "1f40b": { - "output": "1f40b", - "name": "whale", - "alpha_code": ":whale2:", - "aliases": "" - }, - "1f40f": { - "output": "1f40f", - "name": "ram", - "alpha_code": ":ram:", - "aliases": "" - }, - "1f410": { - "output": "1f410", - "name": "goat", - "alpha_code": ":goat:", - "aliases": "" - }, - "1f413": { - "output": "1f413", - "name": "rooster", - "alpha_code": ":rooster:", - "aliases": "" - }, - "1f415": { - "output": "1f415", - "name": "dog", - "alpha_code": ":dog2:", - "aliases": "" - }, - "1f416": { - "output": "1f416", - "name": "pig", - "alpha_code": ":pig2:", - "aliases": "" - }, - "1f91e-1f3ff": { - "output": "1f91e-1f3ff", - "name": "crossed fingers: dark skin tone", - "alpha_code": ":fingers_crossed_tone5:", - "aliases": ":hand_with_index_and_middle_fingers_crossed_tone5:" - }, - "1f42a": { - "output": "1f42a", - "name": "camel", - "alpha_code": ":dromedary_camel:", - "aliases": "" - }, - "1f465": { - "output": "1f465", - "name": "busts in silhouette", - "alpha_code": ":busts_in_silhouette:", - "aliases": "" - }, - "1f46c": { - "output": "1f46c", - "name": "two men holding hands", - "alpha_code": ":two_men_holding_hands:", - "aliases": "" - }, - "1f46d": { - "output": "1f46d", - "name": "two women holding hands", - "alpha_code": ":two_women_holding_hands:", - "aliases": "" - }, - "1f4ad": { - "output": "1f4ad", - "name": "thought balloon", - "alpha_code": ":thought_balloon:", - "aliases": "" - }, - "1f4b6": { - "output": "1f4b6", - "name": "euro banknote", - "alpha_code": ":euro:", - "aliases": "" - }, - "1f919-1f3fb": { - "output": "1f919-1f3fb", - "name": "call me hand: light skin tone", - "alpha_code": ":call_me_tone1:", - "aliases": ":call_me_hand_tone1:" - }, - "1f4b7": { - "output": "1f4b7", - "name": "pound banknote", - "alpha_code": ":pound:", - "aliases": "" - }, - "1f4ec": { - "output": "1f4ec", - "name": "open mailbox with raised flag", - "alpha_code": ":mailbox_with_mail:", - "aliases": "" - }, - "1f4ed": { - "output": "1f4ed", - "name": "open mailbox with lowered flag", - "alpha_code": ":mailbox_with_no_mail:", - "aliases": "" - }, - "1f919-1f3fc": { - "output": "1f919-1f3fc", - "name": "call me hand: medium-light skin tone", - "alpha_code": ":call_me_tone2:", - "aliases": ":call_me_hand_tone2:" - }, - "1f4ef": { - "output": "1f4ef", - "name": "postal horn", - "alpha_code": ":postal_horn:", - "aliases": "" - }, - "1f4f5": { - "output": "1f4f5", - "name": "no mobile phones", - "alpha_code": ":no_mobile_phones:", - "aliases": "" - }, - "1f500": { - "output": "1f500", - "name": "shuffle tracks button", - "alpha_code": ":twisted_rightwards_arrows:", - "aliases": "" - }, - "1f501": { - "output": "1f501", - "name": "repeat button", - "alpha_code": ":repeat:", - "aliases": "" - }, - "1f502": { - "output": "1f502", - "name": "repeat single button", - "alpha_code": ":repeat_one:", - "aliases": "" - }, - "1f504": { - "output": "1f504", - "name": "anticlockwise arrows button", - "alpha_code": ":arrows_counterclockwise:", - "aliases": "" - }, - "1f919-1f3fd": { - "output": "1f919-1f3fd", - "name": "call me hand: medium skin tone", - "alpha_code": ":call_me_tone3:", - "aliases": ":call_me_hand_tone3:" - }, - "1f505": { - "output": "1f505", - "name": "dim button", - "alpha_code": ":low_brightness:", - "aliases": "" - }, - "1f506": { - "output": "1f506", - "name": "bright button", - "alpha_code": ":high_brightness:", - "aliases": "" - }, - "1f507": { - "output": "1f507", - "name": "muted speaker", - "alpha_code": ":mute:", - "aliases": "" - }, - "1f509": { - "output": "1f509", - "name": "speaker medium volume", - "alpha_code": ":sound:", - "aliases": "" - }, - "1f515": { - "output": "1f515", - "name": "bell with slash", - "alpha_code": ":no_bell:", - "aliases": "" - }, - "1f52c": { - "output": "1f52c", - "name": "microscope", - "alpha_code": ":microscope:", - "aliases": "" - }, - "1f52d": { - "output": "1f52d", - "name": "telescope", - "alpha_code": ":telescope:", - "aliases": "" - }, - "1f55c": { - "output": "1f55c", - "name": "one-thirty", - "alpha_code": ":clock130:", - "aliases": "" - }, - "1f55d": { - "output": "1f55d", - "name": "two-thirty", - "alpha_code": ":clock230:", - "aliases": "" - }, - "1f55e": { - "output": "1f55e", - "name": "three-thirty", - "alpha_code": ":clock330:", - "aliases": "" - }, - "1f55f": { - "output": "1f55f", - "name": "four-thirty", - "alpha_code": ":clock430:", - "aliases": "" - }, - "1f560": { - "output": "1f560", - "name": "five-thirty", - "alpha_code": ":clock530:", - "aliases": "" - }, - "1f561": { - "output": "1f561", - "name": "six-thirty", - "alpha_code": ":clock630:", - "aliases": "" - }, - "1f562": { - "output": "1f562", - "name": "seven-thirty", - "alpha_code": ":clock730:", - "aliases": "" - }, - "1f563": { - "output": "1f563", - "name": "eight-thirty", - "alpha_code": ":clock830:", - "aliases": "" - }, - "1f564": { - "output": "1f564", - "name": "nine-thirty", - "alpha_code": ":clock930:", - "aliases": "" - }, - "1f565": { - "output": "1f565", - "name": "ten-thirty", - "alpha_code": ":clock1030:", - "aliases": "" - }, - "1f566": { - "output": "1f566", - "name": "eleven-thirty", - "alpha_code": ":clock1130:", - "aliases": "" - }, - "1f567": { - "output": "1f567", - "name": "twelve-thirty", - "alpha_code": ":clock1230:", - "aliases": "" - }, - "1f508": { - "output": "1f508", - "name": "speaker low volume", - "alpha_code": ":speaker:", - "aliases": "" - }, - "1f68b": { - "output": "1f68b", - "name": "tram car", - "alpha_code": ":train:", - "aliases": "" - }, - "27bf": { - "output": "27bf", - "name": "double curly loop", - "alpha_code": ":loop:", - "aliases": "" - }, - "1f1e6-1f1eb": { - "output": "1f1e6-1f1eb", - "name": "Afghanistan", - "alpha_code": ":flag_af:", - "aliases": ":af:" - }, - "1f1e6-1f1f1": { - "output": "1f1e6-1f1f1", - "name": "Albania", - "alpha_code": ":flag_al:", - "aliases": ":al:" - }, - "1f1e9-1f1ff": { - "output": "1f1e9-1f1ff", - "name": "Algeria", - "alpha_code": ":flag_dz:", - "aliases": ":dz:" - }, - "1f1e6-1f1e9": { - "output": "1f1e6-1f1e9", - "name": "Andorra", - "alpha_code": ":flag_ad:", - "aliases": ":ad:" - }, - "1f1e6-1f1f4": { - "output": "1f1e6-1f1f4", - "name": "Angola", - "alpha_code": ":flag_ao:", - "aliases": ":ao:" - }, - "1f1e6-1f1ec": { - "output": "1f1e6-1f1ec", - "name": "Antigua & Barbuda", - "alpha_code": ":flag_ag:", - "aliases": ":ag:" - }, - "1f1e6-1f1f7": { - "output": "1f1e6-1f1f7", - "name": "Argentina", - "alpha_code": ":flag_ar:", - "aliases": ":ar:" - }, - "1f1e6-1f1f2": { - "output": "1f1e6-1f1f2", - "name": "Armenia", - "alpha_code": ":flag_am:", - "aliases": ":am:" - }, - "1f1e6-1f1fa": { - "output": "1f1e6-1f1fa", - "name": "Australia", - "alpha_code": ":flag_au:", - "aliases": ":au:" - }, - "1f1e6-1f1f9": { - "output": "1f1e6-1f1f9", - "name": "Austria", - "alpha_code": ":flag_at:", - "aliases": ":at:" - }, - "1f1e6-1f1ff": { - "output": "1f1e6-1f1ff", - "name": "Azerbaijan", - "alpha_code": ":flag_az:", - "aliases": ":az:" - }, - "1f1e7-1f1f8": { - "output": "1f1e7-1f1f8", - "name": "Bahamas", - "alpha_code": ":flag_bs:", - "aliases": ":bs:" - }, - "1f1e7-1f1ed": { - "output": "1f1e7-1f1ed", - "name": "Bahrain", - "alpha_code": ":flag_bh:", - "aliases": ":bh:" - }, - "1f1e7-1f1e9": { - "output": "1f1e7-1f1e9", - "name": "Bangladesh", - "alpha_code": ":flag_bd:", - "aliases": ":bd:" - }, - "1f1e7-1f1e7": { - "output": "1f1e7-1f1e7", - "name": "Barbados", - "alpha_code": ":flag_bb:", - "aliases": ":bb:" - }, - "1f1e7-1f1fe": { - "output": "1f1e7-1f1fe", - "name": "Belarus", - "alpha_code": ":flag_by:", - "aliases": ":by:" - }, - "1f1e7-1f1ea": { - "output": "1f1e7-1f1ea", - "name": "Belgium", - "alpha_code": ":flag_be:", - "aliases": ":be:" - }, - "1f1e7-1f1ff": { - "output": "1f1e7-1f1ff", - "name": "Belize", - "alpha_code": ":flag_bz:", - "aliases": ":bz:" - }, - "1f1e7-1f1ef": { - "output": "1f1e7-1f1ef", - "name": "Benin", - "alpha_code": ":flag_bj:", - "aliases": ":bj:" - }, - "1f1e7-1f1f9": { - "output": "1f1e7-1f1f9", - "name": "Bhutan", - "alpha_code": ":flag_bt:", - "aliases": ":bt:" - }, - "1f1e7-1f1f4": { - "output": "1f1e7-1f1f4", - "name": "Bolivia", - "alpha_code": ":flag_bo:", - "aliases": ":bo:" - }, - "1f1e7-1f1e6": { - "output": "1f1e7-1f1e6", - "name": "Bosnia & Herzegovina", - "alpha_code": ":flag_ba:", - "aliases": ":ba:" - }, - "1f1e7-1f1fc": { - "output": "1f1e7-1f1fc", - "name": "Botswana", - "alpha_code": ":flag_bw:", - "aliases": ":bw:" - }, - "1f1e7-1f1f7": { - "output": "1f1e7-1f1f7", - "name": "Brazil", - "alpha_code": ":flag_br:", - "aliases": ":br:" - }, - "1f1e7-1f1f3": { - "output": "1f1e7-1f1f3", - "name": "Brunei", - "alpha_code": ":flag_bn:", - "aliases": ":bn:" - }, - "1f1e7-1f1ec": { - "output": "1f1e7-1f1ec", - "name": "Bulgaria", - "alpha_code": ":flag_bg:", - "aliases": ":bg:" - }, - "1f1e7-1f1eb": { - "output": "1f1e7-1f1eb", - "name": "Burkina Faso", - "alpha_code": ":flag_bf:", - "aliases": ":bf:" - }, - "1f1e7-1f1ee": { - "output": "1f1e7-1f1ee", - "name": "Burundi", - "alpha_code": ":flag_bi:", - "aliases": ":bi:" - }, - "1f1f0-1f1ed": { - "output": "1f1f0-1f1ed", - "name": "Cambodia", - "alpha_code": ":flag_kh:", - "aliases": ":kh:" - }, - "1f1e8-1f1f2": { - "output": "1f1e8-1f1f2", - "name": "Cameroon", - "alpha_code": ":flag_cm:", - "aliases": ":cm:" - }, - "1f1e8-1f1e6": { - "output": "1f1e8-1f1e6", - "name": "Canada", - "alpha_code": ":flag_ca:", - "aliases": ":ca:" - }, - "1f1e8-1f1fb": { - "output": "1f1e8-1f1fb", - "name": "Cape Verde", - "alpha_code": ":flag_cv:", - "aliases": ":cv:" - }, - "1f919-1f3fe": { - "output": "1f919-1f3fe", - "name": "call me hand: medium-dark skin tone", - "alpha_code": ":call_me_tone4:", - "aliases": ":call_me_hand_tone4:" - }, - "1f1e8-1f1eb": { - "output": "1f1e8-1f1eb", - "name": "Central African Republic", - "alpha_code": ":flag_cf:", - "aliases": ":cf:" - }, - "1f1f9-1f1e9": { - "output": "1f1f9-1f1e9", - "name": "Chad", - "alpha_code": ":flag_td:", - "aliases": ":td:" - }, - "1f1e8-1f1f1": { - "output": "1f1e8-1f1f1", - "name": "Chile", - "alpha_code": ":flag_cl:", - "aliases": ":chile:" - }, - "1f1e8-1f1f4": { - "output": "1f1e8-1f1f4", - "name": "Colombia", - "alpha_code": ":flag_co:", - "aliases": ":co:" - }, - "1f1f0-1f1f2": { - "output": "1f1f0-1f1f2", - "name": "Comoros", - "alpha_code": ":flag_km:", - "aliases": ":km:" - }, - "1f1e8-1f1f7": { - "output": "1f1e8-1f1f7", - "name": "Costa Rica", - "alpha_code": ":flag_cr:", - "aliases": ":cr:" - }, - "1f1e8-1f1ee": { - "output": "1f1e8-1f1ee", - "name": "C\u00f4te d\u2019Ivoire", - "alpha_code": ":flag_ci:", - "aliases": ":ci:" - }, - "1f1ed-1f1f7": { - "output": "1f1ed-1f1f7", - "name": "Croatia", - "alpha_code": ":flag_hr:", - "aliases": ":hr:" - }, - "1f1e8-1f1fa": { - "output": "1f1e8-1f1fa", - "name": "Cuba", - "alpha_code": ":flag_cu:", - "aliases": ":cu:" - }, - "1f1e8-1f1fe": { - "output": "1f1e8-1f1fe", - "name": "Cyprus", - "alpha_code": ":flag_cy:", - "aliases": ":cy:" - }, - "1f1e8-1f1ff": { - "output": "1f1e8-1f1ff", - "name": "Czechia", - "alpha_code": ":flag_cz:", - "aliases": ":cz:" - }, - "1f919-1f3ff": { - "output": "1f919-1f3ff", - "name": "call me hand: dark skin tone", - "alpha_code": ":call_me_tone5:", - "aliases": ":call_me_hand_tone5:" - }, - "1f1e8-1f1e9": { - "output": "1f1e8-1f1e9", - "name": "Congo - Kinshasa", - "alpha_code": ":flag_cd:", - "aliases": ":congo:" - }, - "1f91b-1f3fb": { - "output": "1f91b-1f3fb", - "name": "left-facing fist: light skin tone", - "alpha_code": ":left_facing_fist_tone1:", - "aliases": ":left_fist_tone1:" - }, - "1f1e9-1f1f0": { - "output": "1f1e9-1f1f0", - "name": "Denmark", - "alpha_code": ":flag_dk:", - "aliases": ":dk:" - }, - "1f1e9-1f1ef": { - "output": "1f1e9-1f1ef", - "name": "Djibouti", - "alpha_code": ":flag_dj:", - "aliases": ":dj:" - }, - "1f1e9-1f1f2": { - "output": "1f1e9-1f1f2", - "name": "Dominica", - "alpha_code": ":flag_dm:", - "aliases": ":dm:" - }, - "1f1e9-1f1f4": { - "output": "1f1e9-1f1f4", - "name": "Dominican Republic", - "alpha_code": ":flag_do:", - "aliases": ":do:" - }, - "1f1f9-1f1f1": { - "output": "1f1f9-1f1f1", - "name": "Timor-Leste", - "alpha_code": ":flag_tl:", - "aliases": ":tl:" - }, - "1f1ea-1f1e8": { - "output": "1f1ea-1f1e8", - "name": "Ecuador", - "alpha_code": ":flag_ec:", - "aliases": ":ec:" - }, - "1f1ea-1f1ec": { - "output": "1f1ea-1f1ec", - "name": "Egypt", - "alpha_code": ":flag_eg:", - "aliases": ":eg:" - }, - "1f1f8-1f1fb": { - "output": "1f1f8-1f1fb", - "name": "El Salvador", - "alpha_code": ":flag_sv:", - "aliases": ":sv:" - }, - "1f1ec-1f1f6": { - "output": "1f1ec-1f1f6", - "name": "Equatorial Guinea", - "alpha_code": ":flag_gq:", - "aliases": ":gq:" - }, - "1f1ea-1f1f7": { - "output": "1f1ea-1f1f7", - "name": "Eritrea", - "alpha_code": ":flag_er:", - "aliases": ":er:" - }, - "1f1ea-1f1ea": { - "output": "1f1ea-1f1ea", - "name": "Estonia", - "alpha_code": ":flag_ee:", - "aliases": ":ee:" - }, - "1f1ea-1f1f9": { - "output": "1f1ea-1f1f9", - "name": "Ethiopia", - "alpha_code": ":flag_et:", - "aliases": ":et:" - }, - "1f91b-1f3fc": { - "output": "1f91b-1f3fc", - "name": "left-facing fist: medium-light skin tone", - "alpha_code": ":left_facing_fist_tone2:", - "aliases": ":left_fist_tone2:" - }, - "1f1eb-1f1ef": { - "output": "1f1eb-1f1ef", - "name": "Fiji", - "alpha_code": ":flag_fj:", - "aliases": ":fj:" - }, - "1f1eb-1f1ee": { - "output": "1f1eb-1f1ee", - "name": "Finland", - "alpha_code": ":flag_fi:", - "aliases": ":fi:" - }, - "1f1ec-1f1e6": { - "output": "1f1ec-1f1e6", - "name": "Gabon", - "alpha_code": ":flag_ga:", - "aliases": ":ga:" - }, - "1f1ec-1f1f2": { - "output": "1f1ec-1f1f2", - "name": "Gambia", - "alpha_code": ":flag_gm:", - "aliases": ":gm:" - }, - "1f1ec-1f1ea": { - "output": "1f1ec-1f1ea", - "name": "Georgia", - "alpha_code": ":flag_ge:", - "aliases": ":ge:" - }, - "1f1ec-1f1ed": { - "output": "1f1ec-1f1ed", - "name": "Ghana", - "alpha_code": ":flag_gh:", - "aliases": ":gh:" - }, - "1f1ec-1f1f7": { - "output": "1f1ec-1f1f7", - "name": "Greece", - "alpha_code": ":flag_gr:", - "aliases": ":gr:" - }, - "1f1ec-1f1e9": { - "output": "1f1ec-1f1e9", - "name": "Grenada", - "alpha_code": ":flag_gd:", - "aliases": ":gd:" - }, - "1f1ec-1f1f9": { - "output": "1f1ec-1f1f9", - "name": "Guatemala", - "alpha_code": ":flag_gt:", - "aliases": ":gt:" - }, - "1f1ec-1f1f3": { - "output": "1f1ec-1f1f3", - "name": "Guinea", - "alpha_code": ":flag_gn:", - "aliases": ":gn:" - }, - "1f1ec-1f1fc": { - "output": "1f1ec-1f1fc", - "name": "Guinea-Bissau", - "alpha_code": ":flag_gw:", - "aliases": ":gw:" - }, - "1f1ec-1f1fe": { - "output": "1f1ec-1f1fe", - "name": "Guyana", - "alpha_code": ":flag_gy:", - "aliases": ":gy:" - }, - "1f1ed-1f1f9": { - "output": "1f1ed-1f1f9", - "name": "Haiti", - "alpha_code": ":flag_ht:", - "aliases": ":ht:" - }, - "1f1ed-1f1f3": { - "output": "1f1ed-1f1f3", - "name": "Honduras", - "alpha_code": ":flag_hn:", - "aliases": ":hn:" - }, - "1f1ed-1f1fa": { - "output": "1f1ed-1f1fa", - "name": "Hungary", - "alpha_code": ":flag_hu:", - "aliases": ":hu:" - }, - "1f1ee-1f1f8": { - "output": "1f1ee-1f1f8", - "name": "Iceland", - "alpha_code": ":flag_is:", - "aliases": ":is:" - }, - "1f1ee-1f1f3": { - "output": "1f1ee-1f1f3", - "name": "India", - "alpha_code": ":flag_in:", - "aliases": ":in:" - }, - "1f1ee-1f1e9": { - "output": "1f1ee-1f1e9", - "name": "Indonesia", - "alpha_code": ":flag_id:", - "aliases": ":indonesia:" - }, - "1f1ee-1f1f7": { - "output": "1f1ee-1f1f7", - "name": "Iran", - "alpha_code": ":flag_ir:", - "aliases": ":ir:" - }, - "1f1ee-1f1f6": { - "output": "1f1ee-1f1f6", - "name": "Iraq", - "alpha_code": ":flag_iq:", - "aliases": ":iq:" - }, - "1f1ee-1f1ea": { - "output": "1f1ee-1f1ea", - "name": "Ireland", - "alpha_code": ":flag_ie:", - "aliases": ":ie:" - }, - "1f1ee-1f1f1": { - "output": "1f1ee-1f1f1", - "name": "Israel", - "alpha_code": ":flag_il:", - "aliases": ":il:" - }, - "1f1ef-1f1f2": { - "output": "1f1ef-1f1f2", - "name": "Jamaica", - "alpha_code": ":flag_jm:", - "aliases": ":jm:" - }, - "1f1ef-1f1f4": { - "output": "1f1ef-1f1f4", - "name": "Jordan", - "alpha_code": ":flag_jo:", - "aliases": ":jo:" - }, - "1f1f0-1f1ff": { - "output": "1f1f0-1f1ff", - "name": "Kazakhstan", - "alpha_code": ":flag_kz:", - "aliases": ":kz:" - }, - "1f1f0-1f1ea": { - "output": "1f1f0-1f1ea", - "name": "Kenya", - "alpha_code": ":flag_ke:", - "aliases": ":ke:" - }, - "1f1f0-1f1ee": { - "output": "1f1f0-1f1ee", - "name": "Kiribati", - "alpha_code": ":flag_ki:", - "aliases": ":ki:" - }, - "1f1fd-1f1f0": { - "output": "1f1fd-1f1f0", - "name": "Kosovo", - "alpha_code": ":flag_xk:", - "aliases": ":xk:" - }, - "1f1f0-1f1fc": { - "output": "1f1f0-1f1fc", - "name": "Kuwait", - "alpha_code": ":flag_kw:", - "aliases": ":kw:" - }, - "1f1f0-1f1ec": { - "output": "1f1f0-1f1ec", - "name": "Kyrgyzstan", - "alpha_code": ":flag_kg:", - "aliases": ":kg:" - }, - "1f91b-1f3fd": { - "output": "1f91b-1f3fd", - "name": "left-facing fist: medium skin tone", - "alpha_code": ":left_facing_fist_tone3:", - "aliases": ":left_fist_tone3:" - }, - "1f1f1-1f1e6": { - "output": "1f1f1-1f1e6", - "name": "Laos", - "alpha_code": ":flag_la:", - "aliases": ":la:" - }, - "1f1f1-1f1fb": { - "output": "1f1f1-1f1fb", - "name": "Latvia", - "alpha_code": ":flag_lv:", - "aliases": ":lv:" - }, - "1f1f1-1f1e7": { - "output": "1f1f1-1f1e7", - "name": "Lebanon", - "alpha_code": ":flag_lb:", - "aliases": ":lb:" - }, - "1f1f1-1f1f8": { - "output": "1f1f1-1f1f8", - "name": "Lesotho", - "alpha_code": ":flag_ls:", - "aliases": ":ls:" - }, - "1f1f1-1f1f7": { - "output": "1f1f1-1f1f7", - "name": "Liberia", - "alpha_code": ":flag_lr:", - "aliases": ":lr:" - }, - "1f1f1-1f1fe": { - "output": "1f1f1-1f1fe", - "name": "Libya", - "alpha_code": ":flag_ly:", - "aliases": ":ly:" - }, - "1f1f1-1f1ee": { - "output": "1f1f1-1f1ee", - "name": "Liechtenstein", - "alpha_code": ":flag_li:", - "aliases": ":li:" - }, - "1f1f1-1f1f9": { - "output": "1f1f1-1f1f9", - "name": "Lithuania", - "alpha_code": ":flag_lt:", - "aliases": ":lt:" - }, - "1f1f1-1f1fa": { - "output": "1f1f1-1f1fa", - "name": "Luxembourg", - "alpha_code": ":flag_lu:", - "aliases": ":lu:" - }, - "1f1f2-1f1f0": { - "output": "1f1f2-1f1f0", - "name": "Macedonia", - "alpha_code": ":flag_mk:", - "aliases": ":mk:" - }, - "1f1f2-1f1ec": { - "output": "1f1f2-1f1ec", - "name": "Madagascar", - "alpha_code": ":flag_mg:", - "aliases": ":mg:" - }, - "1f1f2-1f1fc": { - "output": "1f1f2-1f1fc", - "name": "Malawi", - "alpha_code": ":flag_mw:", - "aliases": ":mw:" - }, - "1f1f2-1f1fe": { - "output": "1f1f2-1f1fe", - "name": "Malaysia", - "alpha_code": ":flag_my:", - "aliases": ":my:" - }, - "1f1f2-1f1fb": { - "output": "1f1f2-1f1fb", - "name": "Maldives", - "alpha_code": ":flag_mv:", - "aliases": ":mv:" - }, - "1f1f2-1f1f1": { - "output": "1f1f2-1f1f1", - "name": "Mali", - "alpha_code": ":flag_ml:", - "aliases": ":ml:" - }, - "1f1f2-1f1f9": { - "output": "1f1f2-1f1f9", - "name": "Malta", - "alpha_code": ":flag_mt:", - "aliases": ":mt:" - }, - "1f1f2-1f1ed": { - "output": "1f1f2-1f1ed", - "name": "Marshall Islands", - "alpha_code": ":flag_mh:", - "aliases": ":mh:" - }, - "1f1f2-1f1f7": { - "output": "1f1f2-1f1f7", - "name": "Mauritania", - "alpha_code": ":flag_mr:", - "aliases": ":mr:" - }, - "1f1f2-1f1fa": { - "output": "1f1f2-1f1fa", - "name": "Mauritius", - "alpha_code": ":flag_mu:", - "aliases": ":mu:" - }, - "1f1f2-1f1fd": { - "output": "1f1f2-1f1fd", - "name": "Mexico", - "alpha_code": ":flag_mx:", - "aliases": ":mx:" - }, - "1f1eb-1f1f2": { - "output": "1f1eb-1f1f2", - "name": "Micronesia", - "alpha_code": ":flag_fm:", - "aliases": ":fm:" - }, - "1f1f2-1f1e9": { - "output": "1f1f2-1f1e9", - "name": "Moldova", - "alpha_code": ":flag_md:", - "aliases": ":md:" - }, - "1f1f2-1f1e8": { - "output": "1f1f2-1f1e8", - "name": "Monaco", - "alpha_code": ":flag_mc:", - "aliases": ":mc:" - }, - "1f1f2-1f1f3": { - "output": "1f1f2-1f1f3", - "name": "Mongolia", - "alpha_code": ":flag_mn:", - "aliases": ":mn:" - }, - "1f1f2-1f1ea": { - "output": "1f1f2-1f1ea", - "name": "Montenegro", - "alpha_code": ":flag_me:", - "aliases": ":me:" - }, - "1f1f2-1f1e6": { - "output": "1f1f2-1f1e6", - "name": "Morocco", - "alpha_code": ":flag_ma:", - "aliases": ":ma:" - }, - "1f1f2-1f1ff": { - "output": "1f1f2-1f1ff", - "name": "Mozambique", - "alpha_code": ":flag_mz:", - "aliases": ":mz:" - }, - "1f1f2-1f1f2": { - "output": "1f1f2-1f1f2", - "name": "Myanmar (Burma)", - "alpha_code": ":flag_mm:", - "aliases": ":mm:" - }, - "1f1f3-1f1e6": { - "output": "1f1f3-1f1e6", - "name": "Namibia", - "alpha_code": ":flag_na:", - "aliases": ":na:" - }, - "1f1f3-1f1f7": { - "output": "1f1f3-1f1f7", - "name": "Nauru", - "alpha_code": ":flag_nr:", - "aliases": ":nr:" - }, - "1f1f3-1f1f5": { - "output": "1f1f3-1f1f5", - "name": "Nepal", - "alpha_code": ":flag_np:", - "aliases": ":np:" - }, - "1f1f3-1f1f1": { - "output": "1f1f3-1f1f1", - "name": "Netherlands", - "alpha_code": ":flag_nl:", - "aliases": ":nl:" - }, - "1f1f3-1f1ff": { - "output": "1f1f3-1f1ff", - "name": "New Zealand", - "alpha_code": ":flag_nz:", - "aliases": ":nz:" - }, - "1f1f3-1f1ee": { - "output": "1f1f3-1f1ee", - "name": "Nicaragua", - "alpha_code": ":flag_ni:", - "aliases": ":ni:" - }, - "1f1f3-1f1ea": { - "output": "1f1f3-1f1ea", - "name": "Niger", - "alpha_code": ":flag_ne:", - "aliases": ":ne:" - }, - "1f1f3-1f1ec": { - "output": "1f1f3-1f1ec", - "name": "Nigeria", - "alpha_code": ":flag_ng:", - "aliases": ":nigeria:" - }, - "1f1f0-1f1f5": { - "output": "1f1f0-1f1f5", - "name": "North Korea", - "alpha_code": ":flag_kp:", - "aliases": ":kp:" - }, - "1f1f3-1f1f4": { - "output": "1f1f3-1f1f4", - "name": "Norway", - "alpha_code": ":flag_no:", - "aliases": ":no:" - }, - "1f1f4-1f1f2": { - "output": "1f1f4-1f1f2", - "name": "Oman", - "alpha_code": ":flag_om:", - "aliases": ":om:" - }, - "1f1f5-1f1f0": { - "output": "1f1f5-1f1f0", - "name": "Pakistan", - "alpha_code": ":flag_pk:", - "aliases": ":pk:" - }, - "1f1f5-1f1fc": { - "output": "1f1f5-1f1fc", - "name": "Palau", - "alpha_code": ":flag_pw:", - "aliases": ":pw:" - }, - "1f1f5-1f1e6": { - "output": "1f1f5-1f1e6", - "name": "Panama", - "alpha_code": ":flag_pa:", - "aliases": ":pa:" - }, - "1f1f5-1f1ec": { - "output": "1f1f5-1f1ec", - "name": "Papua New Guinea", - "alpha_code": ":flag_pg:", - "aliases": ":pg:" - }, - "1f91b-1f3fe": { - "output": "1f91b-1f3fe", - "name": "left-facing fist: medium-dark skin tone", - "alpha_code": ":left_facing_fist_tone4:", - "aliases": ":left_fist_tone4:" - }, - "1f1f5-1f1fe": { - "output": "1f1f5-1f1fe", - "name": "Paraguay", - "alpha_code": ":flag_py:", - "aliases": ":py:" - }, - "1f1f5-1f1ea": { - "output": "1f1f5-1f1ea", - "name": "Peru", - "alpha_code": ":flag_pe:", - "aliases": ":pe:" - }, - "1f1f5-1f1ed": { - "output": "1f1f5-1f1ed", - "name": "Philippines", - "alpha_code": ":flag_ph:", - "aliases": ":ph:" - }, - "1f1f5-1f1f1": { - "output": "1f1f5-1f1f1", - "name": "Poland", - "alpha_code": ":flag_pl:", - "aliases": ":pl:" - }, - "1f1f5-1f1f9": { - "output": "1f1f5-1f1f9", - "name": "Portugal", - "alpha_code": ":flag_pt:", - "aliases": ":pt:" - }, - "1f1f6-1f1e6": { - "output": "1f1f6-1f1e6", - "name": "Qatar", - "alpha_code": ":flag_qa:", - "aliases": ":qa:" - }, - "1f1f9-1f1fc": { - "output": "1f1f9-1f1fc", - "name": "Taiwan", - "alpha_code": ":flag_tw:", - "aliases": ":tw:" - }, - "1f1e8-1f1ec": { - "output": "1f1e8-1f1ec", - "name": "Congo - Brazzaville", - "alpha_code": ":flag_cg:", - "aliases": ":cg:" - }, - "1f1f7-1f1f4": { - "output": "1f1f7-1f1f4", - "name": "Romania", - "alpha_code": ":flag_ro:", - "aliases": ":ro:" - }, - "1f1f7-1f1fc": { - "output": "1f1f7-1f1fc", - "name": "Rwanda", - "alpha_code": ":flag_rw:", - "aliases": ":rw:" - }, - "1f1f0-1f1f3": { - "output": "1f1f0-1f1f3", - "name": "St. Kitts & Nevis", - "alpha_code": ":flag_kn:", - "aliases": ":kn:" - }, - "1f1f1-1f1e8": { - "output": "1f1f1-1f1e8", - "name": "St. Lucia", - "alpha_code": ":flag_lc:", - "aliases": ":lc:" - }, - "1f1fb-1f1e8": { - "output": "1f1fb-1f1e8", - "name": "St. Vincent & Grenadines", - "alpha_code": ":flag_vc:", - "aliases": ":vc:" - }, - "1f1fc-1f1f8": { - "output": "1f1fc-1f1f8", - "name": "Samoa", - "alpha_code": ":flag_ws:", - "aliases": ":ws:" - }, - "1f1f8-1f1f2": { - "output": "1f1f8-1f1f2", - "name": "San Marino", - "alpha_code": ":flag_sm:", - "aliases": ":sm:" - }, - "1f1f8-1f1f9": { - "output": "1f1f8-1f1f9", - "name": "S\u00e3o Tom\u00e9 & Pr\u00edncipe", - "alpha_code": ":flag_st:", - "aliases": ":st:" - }, - "1f1f8-1f1e6": { - "output": "1f1f8-1f1e6", - "name": "Saudi Arabia", - "alpha_code": ":flag_sa:", - "aliases": ":saudiarabia:|:saudi:" - }, - "1f91b-1f3ff": { - "output": "1f91b-1f3ff", - "name": "left-facing fist: dark skin tone", - "alpha_code": ":left_facing_fist_tone5:", - "aliases": ":left_fist_tone5:" - }, - "1f1f8-1f1f3": { - "output": "1f1f8-1f1f3", - "name": "Senegal", - "alpha_code": ":flag_sn:", - "aliases": ":sn:" - }, - "1f1f7-1f1f8": { - "output": "1f1f7-1f1f8", - "name": "Serbia", - "alpha_code": ":flag_rs:", - "aliases": ":rs:" - }, - "1f1f8-1f1e8": { - "output": "1f1f8-1f1e8", - "name": "Seychelles", - "alpha_code": ":flag_sc:", - "aliases": ":sc:" - }, - "1f1f8-1f1f1": { - "output": "1f1f8-1f1f1", - "name": "Sierra Leone", - "alpha_code": ":flag_sl:", - "aliases": ":sl:" - }, - "1f1f8-1f1ec": { - "output": "1f1f8-1f1ec", - "name": "Singapore", - "alpha_code": ":flag_sg:", - "aliases": ":sg:" - }, - "1f1f8-1f1f0": { - "output": "1f1f8-1f1f0", - "name": "Slovakia", - "alpha_code": ":flag_sk:", - "aliases": ":sk:" - }, - "1f1f8-1f1ee": { - "output": "1f1f8-1f1ee", - "name": "Slovenia", - "alpha_code": ":flag_si:", - "aliases": ":si:" - }, - "1f1f8-1f1e7": { - "output": "1f1f8-1f1e7", - "name": "Solomon Islands", - "alpha_code": ":flag_sb:", - "aliases": ":sb:" - }, - "1f1f8-1f1f4": { - "output": "1f1f8-1f1f4", - "name": "Somalia", - "alpha_code": ":flag_so:", - "aliases": ":so:" - }, - "1f1ff-1f1e6": { - "output": "1f1ff-1f1e6", - "name": "South Africa", - "alpha_code": ":flag_za:", - "aliases": ":za:" - }, - "1f1f1-1f1f0": { - "output": "1f1f1-1f1f0", - "name": "Sri Lanka", - "alpha_code": ":flag_lk:", - "aliases": ":lk:" - }, - "1f1f8-1f1e9": { - "output": "1f1f8-1f1e9", - "name": "Sudan", - "alpha_code": ":flag_sd:", - "aliases": ":sd:" - }, - "1f1f8-1f1f7": { - "output": "1f1f8-1f1f7", - "name": "Suriname", - "alpha_code": ":flag_sr:", - "aliases": ":sr:" - }, - "1f1f8-1f1ff": { - "output": "1f1f8-1f1ff", - "name": "Swaziland", - "alpha_code": ":flag_sz:", - "aliases": ":sz:" - }, - "1f1f8-1f1ea": { - "output": "1f1f8-1f1ea", - "name": "Sweden", - "alpha_code": ":flag_se:", - "aliases": ":se:" - }, - "1f1e8-1f1ed": { - "output": "1f1e8-1f1ed", - "name": "Switzerland", - "alpha_code": ":flag_ch:", - "aliases": ":ch:" - }, - "1f1f8-1f1fe": { - "output": "1f1f8-1f1fe", - "name": "Syria", - "alpha_code": ":flag_sy:", - "aliases": ":sy:" - }, - "1f1f9-1f1ef": { - "output": "1f1f9-1f1ef", - "name": "Tajikistan", - "alpha_code": ":flag_tj:", - "aliases": ":tj:" - }, - "1f1f9-1f1ff": { - "output": "1f1f9-1f1ff", - "name": "Tanzania", - "alpha_code": ":flag_tz:", - "aliases": ":tz:" - }, - "1f1f9-1f1ed": { - "output": "1f1f9-1f1ed", - "name": "Thailand", - "alpha_code": ":flag_th:", - "aliases": ":th:" - }, - "1f1f9-1f1ec": { - "output": "1f1f9-1f1ec", - "name": "Togo", - "alpha_code": ":flag_tg:", - "aliases": ":tg:" - }, - "1f1f9-1f1f4": { - "output": "1f1f9-1f1f4", - "name": "Tonga", - "alpha_code": ":flag_to:", - "aliases": ":to:" - }, - "1f1f9-1f1f9": { - "output": "1f1f9-1f1f9", - "name": "Trinidad & Tobago", - "alpha_code": ":flag_tt:", - "aliases": ":tt:" - }, - "1f1f9-1f1f3": { - "output": "1f1f9-1f1f3", - "name": "Tunisia", - "alpha_code": ":flag_tn:", - "aliases": ":tn:" - }, - "1f1f9-1f1f7": { - "output": "1f1f9-1f1f7", - "name": "Turkey", - "alpha_code": ":flag_tr:", - "aliases": ":tr:" - }, - "1f1f9-1f1f2": { - "output": "1f1f9-1f1f2", - "name": "Turkmenistan", - "alpha_code": ":flag_tm:", - "aliases": ":turkmenistan:" - }, - "1f1f9-1f1fb": { - "output": "1f1f9-1f1fb", - "name": "Tuvalu", - "alpha_code": ":flag_tv:", - "aliases": ":tuvalu:" - }, - "1f1fa-1f1ec": { - "output": "1f1fa-1f1ec", - "name": "Uganda", - "alpha_code": ":flag_ug:", - "aliases": ":ug:" - }, - "1f1fa-1f1e6": { - "output": "1f1fa-1f1e6", - "name": "Ukraine", - "alpha_code": ":flag_ua:", - "aliases": ":ua:" - }, - "1f1e6-1f1ea": { - "output": "1f1e6-1f1ea", - "name": "United Arab Emirates", - "alpha_code": ":flag_ae:", - "aliases": ":ae:" - }, - "1f1fa-1f1fe": { - "output": "1f1fa-1f1fe", - "name": "Uruguay", - "alpha_code": ":flag_uy:", - "aliases": ":uy:" - }, - "1f1fa-1f1ff": { - "output": "1f1fa-1f1ff", - "name": "Uzbekistan", - "alpha_code": ":flag_uz:", - "aliases": ":uz:" - }, - "1f1fb-1f1fa": { - "output": "1f1fb-1f1fa", - "name": "Vanuatu", - "alpha_code": ":flag_vu:", - "aliases": ":vu:" - }, - "1f1fb-1f1e6": { - "output": "1f1fb-1f1e6", - "name": "Vatican City", - "alpha_code": ":flag_va:", - "aliases": ":va:" - }, - "1f1fb-1f1ea": { - "output": "1f1fb-1f1ea", - "name": "Venezuela", - "alpha_code": ":flag_ve:", - "aliases": ":ve:" - }, - "1f1fb-1f1f3": { - "output": "1f1fb-1f1f3", - "name": "Vietnam", - "alpha_code": ":flag_vn:", - "aliases": ":vn:" - }, - "1f1ea-1f1ed": { - "output": "1f1ea-1f1ed", - "name": "Western Sahara", - "alpha_code": ":flag_eh:", - "aliases": ":eh:" - }, - "1f91c-1f3fb": { - "output": "1f91c-1f3fb", - "name": "right-facing fist: light skin tone", - "alpha_code": ":right_facing_fist_tone1:", - "aliases": ":right_fist_tone1:" - }, - "1f1fe-1f1ea": { - "output": "1f1fe-1f1ea", - "name": "Yemen", - "alpha_code": ":flag_ye:", - "aliases": ":ye:" - }, - "1f1ff-1f1f2": { - "output": "1f1ff-1f1f2", - "name": "Zambia", - "alpha_code": ":flag_zm:", - "aliases": ":zm:" - }, - "1f1ff-1f1fc": { - "output": "1f1ff-1f1fc", - "name": "Zimbabwe", - "alpha_code": ":flag_zw:", - "aliases": ":zw:" - }, - "1f1f5-1f1f7": { - "output": "1f1f5-1f1f7", - "name": "Puerto Rico", - "alpha_code": ":flag_pr:", - "aliases": ":pr:" - }, - "1f1f0-1f1fe": { - "output": "1f1f0-1f1fe", - "name": "Cayman Islands", - "alpha_code": ":flag_ky:", - "aliases": ":ky:" - }, - "1f1e7-1f1f2": { - "output": "1f1e7-1f1f2", - "name": "Bermuda", - "alpha_code": ":flag_bm:", - "aliases": ":bm:" - }, - "1f1f5-1f1eb": { - "output": "1f1f5-1f1eb", - "name": "French Polynesia", - "alpha_code": ":flag_pf:", - "aliases": ":pf:" - }, - "1f1f5-1f1f8": { - "output": "1f1f5-1f1f8", - "name": "Palestinian Territories", - "alpha_code": ":flag_ps:", - "aliases": ":ps:" - }, - "1f1f3-1f1e8": { - "output": "1f1f3-1f1e8", - "name": "New Caledonia", - "alpha_code": ":flag_nc:", - "aliases": ":nc:" - }, - "1f91c-1f3fc": { - "output": "1f91c-1f3fc", - "name": "right-facing fist: medium-light skin tone", - "alpha_code": ":right_facing_fist_tone2:", - "aliases": ":right_fist_tone2:" - }, - "1f1f8-1f1ed": { - "output": "1f1f8-1f1ed", - "name": "St. Helena", - "alpha_code": ":flag_sh:", - "aliases": ":sh:" - }, - "1f1e6-1f1fc": { - "output": "1f1e6-1f1fc", - "name": "Aruba", - "alpha_code": ":flag_aw:", - "aliases": ":aw:" - }, - "1f1fb-1f1ee": { - "output": "1f1fb-1f1ee", - "name": "U.S. Virgin Islands", - "alpha_code": ":flag_vi:", - "aliases": ":vi:" - }, - "1f1ed-1f1f0": { - "output": "1f1ed-1f1f0", - "name": "Hong Kong SAR China", - "alpha_code": ":flag_hk:", - "aliases": ":hk:" - }, - "1f1e6-1f1e8": { - "output": "1f1e6-1f1e8", - "name": "Ascension Island", - "alpha_code": ":flag_ac:", - "aliases": ":ac:" - }, - "1f1f2-1f1f8": { - "output": "1f1f2-1f1f8", - "name": "Montserrat", - "alpha_code": ":flag_ms:", - "aliases": ":ms:" - }, - "1f1ec-1f1fa": { - "output": "1f1ec-1f1fa", - "name": "Guam", - "alpha_code": ":flag_gu:", - "aliases": ":gu:" - }, - "1f1ec-1f1f1": { - "output": "1f1ec-1f1f1", - "name": "Greenland", - "alpha_code": ":flag_gl:", - "aliases": ":gl:" - }, - "1f1f3-1f1fa": { - "output": "1f1f3-1f1fa", - "name": "Niue", - "alpha_code": ":flag_nu:", - "aliases": ":nu:" - }, - "1f1fc-1f1eb": { - "output": "1f1fc-1f1eb", - "name": "Wallis & Futuna", - "alpha_code": ":flag_wf:", - "aliases": ":wf:" - }, - "1f1f2-1f1f4": { - "output": "1f1f2-1f1f4", - "name": "Macau SAR China", - "alpha_code": ":flag_mo:", - "aliases": ":mo:" - }, - "1f91c-1f3fd": { - "output": "1f91c-1f3fd", - "name": "right-facing fist: medium skin tone", - "alpha_code": ":right_facing_fist_tone3:", - "aliases": ":right_fist_tone3:" - }, - "1f1eb-1f1f4": { - "output": "1f1eb-1f1f4", - "name": "Faroe Islands", - "alpha_code": ":flag_fo:", - "aliases": ":fo:" - }, - "1f1eb-1f1f0": { - "output": "1f1eb-1f1f0", - "name": "Falkland Islands", - "alpha_code": ":flag_fk:", - "aliases": ":fk:" - }, - "1f1ef-1f1ea": { - "output": "1f1ef-1f1ea", - "name": "Jersey", - "alpha_code": ":flag_je:", - "aliases": ":je:" - }, - "1f1e6-1f1ee": { - "output": "1f1e6-1f1ee", - "name": "Anguilla", - "alpha_code": ":flag_ai:", - "aliases": ":ai:" - }, - "1f1ec-1f1ee": { - "output": "1f1ec-1f1ee", - "name": "Gibraltar", - "alpha_code": ":flag_gi:", - "aliases": ":gi:" - }, - "1f39e": { - "output": "1f39e-fe0f", - "name": "film frames", - "alpha_code": ":film_frames:", - "aliases": "" - }, - "1f39f": { - "output": "1f39f-fe0f", - "name": "admission tickets", - "alpha_code": ":tickets:", - "aliases": ":admission_tickets:" - }, - "1f3c5": { - "output": "1f3c5", - "name": "sports medal", - "alpha_code": ":medal:", - "aliases": ":sports_medal:" - }, - "1f3cb": { - "output": "1f3cb-fe0f", - "name": "person lifting weights", - "alpha_code": ":person_lifting_weights:", - "aliases": ":lifter:|:weight_lifter:" - }, - "1f3cc": { - "output": "1f3cc-fe0f", - "name": "person golfing", - "alpha_code": ":person_golfing:", - "aliases": ":golfer:" - }, - "1f3cd": { - "output": "1f3cd-fe0f", - "name": "motorcycle", - "alpha_code": ":motorcycle:", - "aliases": ":racing_motorcycle:" - }, - "1f3ce": { - "output": "1f3ce-fe0f", - "name": "racing car", - "alpha_code": ":race_car:", - "aliases": ":racing_car:" - }, - "1f396": { - "output": "1f396-fe0f", - "name": "military medal", - "alpha_code": ":military_medal:", - "aliases": "" - }, - "1f397": { - "output": "1f397-fe0f", - "name": "reminder ribbon", - "alpha_code": ":reminder_ribbon:", - "aliases": "" - }, - "1f336": { - "output": "1f336-fe0f", - "name": "hot pepper", - "alpha_code": ":hot_pepper:", - "aliases": "" - }, - "1f91c-1f3fe": { - "output": "1f91c-1f3fe", - "name": "right-facing fist: medium-dark skin tone", - "alpha_code": ":right_facing_fist_tone4:", - "aliases": ":right_fist_tone4:" - }, - "1f327": { - "output": "1f327-fe0f", - "name": "cloud with rain", - "alpha_code": ":cloud_rain:", - "aliases": ":cloud_with_rain:" - }, - "1f328": { - "output": "1f328-fe0f", - "name": "cloud with snow", - "alpha_code": ":cloud_snow:", - "aliases": ":cloud_with_snow:" - }, - "1f329": { - "output": "1f329-fe0f", - "name": "cloud with lightning", - "alpha_code": ":cloud_lightning:", - "aliases": ":cloud_with_lightning:" - }, - "1f32a": { - "output": "1f32a-fe0f", - "name": "tornado", - "alpha_code": ":cloud_tornado:", - "aliases": ":cloud_with_tornado:" - }, - "1f32b": { - "output": "1f32b-fe0f", - "name": "fog", - "alpha_code": ":fog:", - "aliases": "" - }, - "1f32c": { - "output": "1f32c-fe0f", - "name": "wind face", - "alpha_code": ":wind_blowing_face:", - "aliases": "" - }, - "1f43f": { - "output": "1f43f-fe0f", - "name": "chipmunk", - "alpha_code": ":chipmunk:", - "aliases": "" - }, - "1f577": { - "output": "1f577-fe0f", - "name": "spider", - "alpha_code": ":spider:", - "aliases": "" - }, - "1f578": { - "output": "1f578-fe0f", - "name": "spider web", - "alpha_code": ":spider_web:", - "aliases": "" - }, - "1f321": { - "output": "1f321-fe0f", - "name": "thermometer", - "alpha_code": ":thermometer:", - "aliases": "" - }, - "1f399": { - "output": "1f399-fe0f", - "name": "studio microphone", - "alpha_code": ":microphone2:", - "aliases": ":studio_microphone:" - }, - "1f39a": { - "output": "1f39a-fe0f", - "name": "level slider", - "alpha_code": ":level_slider:", - "aliases": "" - }, - "1f39b": { - "output": "1f39b-fe0f", - "name": "control knobs", - "alpha_code": ":control_knobs:", - "aliases": "" - }, - "1f3f3": { - "output": "1f3f3-fe0f", - "name": "white flag", - "alpha_code": ":flag_white:", - "aliases": ":waving_white_flag:" - }, - "1f3f4": { - "output": "1f3f4", - "name": "black flag", - "alpha_code": ":flag_black:", - "aliases": ":waving_black_flag:" - }, - "1f3f5": { - "output": "1f3f5-fe0f", - "name": "rosette", - "alpha_code": ":rosette:", - "aliases": "" - }, - "1f3f7": { - "output": "1f3f7-fe0f", - "name": "label", - "alpha_code": ":label:", - "aliases": "" - }, - "1f4f8": { - "output": "1f4f8", - "name": "camera with flash", - "alpha_code": ":camera_with_flash:", - "aliases": "" - }, - "1f4fd": { - "output": "1f4fd-fe0f", - "name": "film projector", - "alpha_code": ":projector:", - "aliases": ":film_projector:" - }, - "271d": { - "output": "271d-fe0f", - "name": "latin cross", - "alpha_code": ":cross:", - "aliases": ":latin_cross:" - }, - "1f549": { - "output": "1f549-fe0f", - "name": "om", - "alpha_code": ":om_symbol:", - "aliases": "" - }, - "1f54a": { - "output": "1f54a-fe0f", - "name": "dove", - "alpha_code": ":dove:", - "aliases": ":dove_of_peace:" - }, - "1f56f": { - "output": "1f56f-fe0f", - "name": "candle", - "alpha_code": ":candle:", - "aliases": "" - }, - "1f570": { - "output": "1f570-fe0f", - "name": "mantelpiece clock", - "alpha_code": ":clock:", - "aliases": ":mantlepiece_clock:" - }, - "1f573": { - "output": "1f573-fe0f", - "name": "hole", - "alpha_code": ":hole:", - "aliases": "" - }, - "1f576": { - "output": "1f576-fe0f", - "name": "sunglasses", - "alpha_code": ":dark_sunglasses:", - "aliases": "" - }, - "1f579": { - "output": "1f579-fe0f", - "name": "joystick", - "alpha_code": ":joystick:", - "aliases": "" - }, - "1f587": { - "output": "1f587-fe0f", - "name": "linked paperclips", - "alpha_code": ":paperclips:", - "aliases": ":linked_paperclips:" - }, - "1f58a": { - "output": "1f58a-fe0f", - "name": "pen", - "alpha_code": ":pen_ballpoint:", - "aliases": ":lower_left_ballpoint_pen:" - }, - "1f58b": { - "output": "1f58b-fe0f", - "name": "fountain pen", - "alpha_code": ":pen_fountain:", - "aliases": ":lower_left_fountain_pen:" - }, - "1f58c": { - "output": "1f58c-fe0f", - "name": "paintbrush", - "alpha_code": ":paintbrush:", - "aliases": ":lower_left_paintbrush:" - }, - "1f58d": { - "output": "1f58d-fe0f", - "name": "crayon", - "alpha_code": ":crayon:", - "aliases": ":lower_left_crayon:" - }, - "1f5a5": { - "output": "1f5a5-fe0f", - "name": "desktop computer", - "alpha_code": ":desktop:", - "aliases": ":desktop_computer:" - }, - "1f5a8": { - "output": "1f5a8-fe0f", - "name": "printer", - "alpha_code": ":printer:", - "aliases": "" - }, - "1f91c-1f3ff": { - "output": "1f91c-1f3ff", - "name": "right-facing fist: dark skin tone", - "alpha_code": ":right_facing_fist_tone5:", - "aliases": ":right_fist_tone5:" - }, - "2328": { - "output": "2328-fe0f", - "name": "keyboard", - "alpha_code": ":keyboard:", - "aliases": "" - }, - "1f5b2": { - "output": "1f5b2-fe0f", - "name": "trackball", - "alpha_code": ":trackball:", - "aliases": "" - }, - "1f91a-1f3fb": { - "output": "1f91a-1f3fb", - "name": "raised back of hand: light skin tone", - "alpha_code": ":raised_back_of_hand_tone1:", - "aliases": ":back_of_hand_tone1:" - }, - "1f5bc": { - "output": "1f5bc-fe0f", - "name": "framed picture", - "alpha_code": ":frame_photo:", - "aliases": ":frame_with_picture:" - }, - "1f5c2": { - "output": "1f5c2-fe0f", - "name": "card index dividers", - "alpha_code": ":dividers:", - "aliases": ":card_index_dividers:" - }, - "1f5c3": { - "output": "1f5c3-fe0f", - "name": "card file box", - "alpha_code": ":card_box:", - "aliases": ":card_file_box:" - }, - "1f5c4": { - "output": "1f5c4-fe0f", - "name": "file cabinet", - "alpha_code": ":file_cabinet:", - "aliases": "" - }, - "1f5d1": { - "output": "1f5d1-fe0f", - "name": "wastebasket", - "alpha_code": ":wastebasket:", - "aliases": "" - }, - "1f5d2": { - "output": "1f5d2-fe0f", - "name": "spiral notepad", - "alpha_code": ":notepad_spiral:", - "aliases": ":spiral_note_pad:" - }, - "1f5d3": { - "output": "1f5d3-fe0f", - "name": "spiral calendar", - "alpha_code": ":calendar_spiral:", - "aliases": ":spiral_calendar_pad:" - }, - "1f5dc": { - "output": "1f5dc-fe0f", - "name": "clamp", - "alpha_code": ":compression:", - "aliases": "" - }, - "1f5dd": { - "output": "1f5dd-fe0f", - "name": "old key", - "alpha_code": ":key2:", - "aliases": ":old_key:" - }, - "1f5de": { - "output": "1f5de-fe0f", - "name": "rolled-up newspaper", - "alpha_code": ":newspaper2:", - "aliases": ":rolled_up_newspaper:" - }, - "1f5e1": { - "output": "1f5e1-fe0f", - "name": "dagger", - "alpha_code": ":dagger:", - "aliases": ":dagger_knife:" - }, - "1f5e3": { - "output": "1f5e3-fe0f", - "name": "speaking head", - "alpha_code": ":speaking_head:", - "aliases": ":speaking_head_in_silhouette:" - }, - "1f5e8": { - "output": "1f5e8-fe0f", - "name": "left speech bubble", - "alpha_code": ":speech_left:", - "aliases": ":left_speech_bubble:" - }, - "1f91a-1f3fc": { - "output": "1f91a-1f3fc", - "name": "raised back of hand: medium-light skin tone", - "alpha_code": ":raised_back_of_hand_tone2:", - "aliases": ":back_of_hand_tone2:" - }, - "1f5ef": { - "output": "1f5ef-fe0f", - "name": "right anger bubble", - "alpha_code": ":anger_right:", - "aliases": ":right_anger_bubble:" - }, - "1f91a-1f3fd": { - "output": "1f91a-1f3fd", - "name": "raised back of hand: medium skin tone", - "alpha_code": ":raised_back_of_hand_tone3:", - "aliases": ":back_of_hand_tone3:" - }, - "1f5f3": { - "output": "1f5f3-fe0f", - "name": "ballot box with ballot", - "alpha_code": ":ballot_box:", - "aliases": ":ballot_box_with_ballot:" - }, - "1f5fa": { - "output": "1f5fa-fe0f", - "name": "world map", - "alpha_code": ":map:", - "aliases": ":world_map:" - }, - "1f6cc": { - "output": "1f6cc", - "name": "person in bed", - "alpha_code": ":sleeping_accommodation:", - "aliases": "" - }, - "1f6e0": { - "output": "1f6e0-fe0f", - "name": "hammer and wrench", - "alpha_code": ":tools:", - "aliases": ":hammer_and_wrench:" - }, - "1f6e1": { - "output": "1f6e1-fe0f", - "name": "shield", - "alpha_code": ":shield:", - "aliases": "" - }, - "1f6e2": { - "output": "1f6e2-fe0f", - "name": "oil drum", - "alpha_code": ":oil:", - "aliases": ":oil_drum:" - }, - "1f6f0": { - "output": "1f6f0-fe0f", - "name": "satellite", - "alpha_code": ":satellite_orbital:", - "aliases": "" - }, - "1f37d": { - "output": "1f37d-fe0f", - "name": "fork and knife with plate", - "alpha_code": ":fork_knife_plate:", - "aliases": ":fork_and_knife_with_plate:" - }, - "1f441": { - "output": "1f441-fe0f", - "name": "eye", - "alpha_code": ":eye:", - "aliases": "" - }, - "1f574": { - "output": "1f574-fe0f", - "name": "man in business suit levitating", - "alpha_code": ":man_in_business_suit_levitating:", - "aliases": "" - }, - "1f575": { - "output": "1f575-fe0f", - "name": "detective", - "alpha_code": ":detective:", - "aliases": ":spy:|:sleuth_or_spy:" - }, - "270d": { - "output": "270d-fe0f", - "name": "writing hand", - "alpha_code": ":writing_hand:", - "aliases": "" - }, - "1f590": { - "output": "1f590-fe0f", - "name": "raised hand with fingers splayed", - "alpha_code": ":hand_splayed:", - "aliases": ":raised_hand_with_fingers_splayed:" - }, - "1f595": { - "output": "1f595", - "name": "middle finger", - "alpha_code": ":middle_finger:", - "aliases": ":reversed_hand_with_middle_finger_extended:" - }, - "1f596": { - "output": "1f596", - "name": "vulcan salute", - "alpha_code": ":vulcan:", - "aliases": ":raised_hand_with_part_between_middle_and_ring_fingers:" - }, - "1f641": { - "output": "1f641", - "name": "slightly frowning face", - "alpha_code": ":slight_frown:", - "aliases": ":slightly_frowning_face:" - }, - "1f642": { - "output": "1f642", - "name": "slightly smiling face", - "alpha_code": ":slight_smile:", - "aliases": ":slightly_smiling_face:" - }, - "1f3d4": { - "output": "1f3d4-fe0f", - "name": "snow-capped mountain", - "alpha_code": ":mountain_snow:", - "aliases": ":snow_capped_mountain:" - }, - "1f3d5": { - "output": "1f3d5-fe0f", - "name": "camping", - "alpha_code": ":camping:", - "aliases": "" - }, - "1f3d6": { - "output": "1f3d6-fe0f", - "name": "beach with umbrella", - "alpha_code": ":beach:", - "aliases": ":beach_with_umbrella:" - }, - "1f3d7": { - "output": "1f3d7-fe0f", - "name": "building construction", - "alpha_code": ":construction_site:", - "aliases": ":building_construction:" - }, - "1f3d8": { - "output": "1f3d8-fe0f", - "name": "houses", - "alpha_code": ":homes:", - "aliases": ":house_buildings:" - }, - "1f3d9": { - "output": "1f3d9-fe0f", - "name": "cityscape", - "alpha_code": ":cityscape:", - "aliases": "" - }, - "1f3da": { - "output": "1f3da-fe0f", - "name": "derelict house", - "alpha_code": ":house_abandoned:", - "aliases": ":derelict_house_building:" - }, - "1f3db": { - "output": "1f3db-fe0f", - "name": "classical building", - "alpha_code": ":classical_building:", - "aliases": "" - }, - "1f3dc": { - "output": "1f3dc-fe0f", - "name": "desert", - "alpha_code": ":desert:", - "aliases": "" - }, - "1f3dd": { - "output": "1f3dd-fe0f", - "name": "desert island", - "alpha_code": ":island:", - "aliases": ":desert_island:" - }, - "1f3de": { - "output": "1f3de-fe0f", - "name": "national park", - "alpha_code": ":park:", - "aliases": ":national_park:" - }, - "1f3df": { - "output": "1f3df-fe0f", - "name": "stadium", - "alpha_code": ":stadium:", - "aliases": "" - }, - "1f6cb": { - "output": "1f6cb-fe0f", - "name": "couch and lamp", - "alpha_code": ":couch:", - "aliases": ":couch_and_lamp:" - }, - "1f91a-1f3fe": { - "output": "1f91a-1f3fe", - "name": "raised back of hand: medium-dark skin tone", - "alpha_code": ":raised_back_of_hand_tone4:", - "aliases": ":back_of_hand_tone4:" - }, - "1f6cd": { - "output": "1f6cd-fe0f", - "name": "shopping bags", - "alpha_code": ":shopping_bags:", - "aliases": "" - }, - "1f6ce": { - "output": "1f6ce-fe0f", - "name": "bellhop bell", - "alpha_code": ":bellhop:", - "aliases": ":bellhop_bell:" - }, - "1f6cf": { - "output": "1f6cf-fe0f", - "name": "bed", - "alpha_code": ":bed:", - "aliases": "" - }, - "1f6e3": { - "output": "1f6e3-fe0f", - "name": "motorway", - "alpha_code": ":motorway:", - "aliases": "" - }, - "1f6e4": { - "output": "1f6e4-fe0f", - "name": "railway track", - "alpha_code": ":railway_track:", - "aliases": ":railroad_track:" - }, - "1f6e5": { - "output": "1f6e5-fe0f", - "name": "motor boat", - "alpha_code": ":motorboat:", - "aliases": "" - }, - "1f6e9": { - "output": "1f6e9-fe0f", - "name": "small airplane", - "alpha_code": ":airplane_small:", - "aliases": ":small_airplane:" - }, - "1f6eb": { - "output": "1f6eb", - "name": "airplane departure", - "alpha_code": ":airplane_departure:", - "aliases": "" - }, - "1f6ec": { - "output": "1f6ec", - "name": "airplane arrival", - "alpha_code": ":airplane_arriving:", - "aliases": "" - }, - "1f6f3": { - "output": "1f6f3-fe0f", - "name": "passenger ship", - "alpha_code": ":cruise_ship:", - "aliases": ":passenger_ship:" - }, - "1f476-1f3fb": { - "output": "1f476-1f3fb", - "name": "baby: light skin tone", - "alpha_code": ":baby_tone1:", - "aliases": "" - }, - "1f476-1f3fc": { - "output": "1f476-1f3fc", - "name": "baby: medium-light skin tone", - "alpha_code": ":baby_tone2:", - "aliases": "" - }, - "1f476-1f3fd": { - "output": "1f476-1f3fd", - "name": "baby: medium skin tone", - "alpha_code": ":baby_tone3:", - "aliases": "" - }, - "1f476-1f3fe": { - "output": "1f476-1f3fe", - "name": "baby: medium-dark skin tone", - "alpha_code": ":baby_tone4:", - "aliases": "" - }, - "1f476-1f3ff": { - "output": "1f476-1f3ff", - "name": "baby: dark skin tone", - "alpha_code": ":baby_tone5:", - "aliases": "" - }, - "1f466-1f3fb": { - "output": "1f466-1f3fb", - "name": "boy: light skin tone", - "alpha_code": ":boy_tone1:", - "aliases": "" - }, - "1f466-1f3fc": { - "output": "1f466-1f3fc", - "name": "boy: medium-light skin tone", - "alpha_code": ":boy_tone2:", - "aliases": "" - }, - "1f466-1f3fd": { - "output": "1f466-1f3fd", - "name": "boy: medium skin tone", - "alpha_code": ":boy_tone3:", - "aliases": "" - }, - "1f466-1f3fe": { - "output": "1f466-1f3fe", - "name": "boy: medium-dark skin tone", - "alpha_code": ":boy_tone4:", - "aliases": "" - }, - "1f466-1f3ff": { - "output": "1f466-1f3ff", - "name": "boy: dark skin tone", - "alpha_code": ":boy_tone5:", - "aliases": "" - }, - "1f467-1f3fb": { - "output": "1f467-1f3fb", - "name": "girl: light skin tone", - "alpha_code": ":girl_tone1:", - "aliases": "" - }, - "1f467-1f3fc": { - "output": "1f467-1f3fc", - "name": "girl: medium-light skin tone", - "alpha_code": ":girl_tone2:", - "aliases": "" - }, - "1f467-1f3fd": { - "output": "1f467-1f3fd", - "name": "girl: medium skin tone", - "alpha_code": ":girl_tone3:", - "aliases": "" - }, - "1f467-1f3fe": { - "output": "1f467-1f3fe", - "name": "girl: medium-dark skin tone", - "alpha_code": ":girl_tone4:", - "aliases": "" - }, - "1f467-1f3ff": { - "output": "1f467-1f3ff", - "name": "girl: dark skin tone", - "alpha_code": ":girl_tone5:", - "aliases": "" - }, - "1f468-1f3fb": { - "output": "1f468-1f3fb", - "name": "man: light skin tone", - "alpha_code": ":man_tone1:", - "aliases": "" - }, - "1f468-1f3fc": { - "output": "1f468-1f3fc", - "name": "man: medium-light skin tone", - "alpha_code": ":man_tone2:", - "aliases": "" - }, - "1f468-1f3fd": { - "output": "1f468-1f3fd", - "name": "man: medium skin tone", - "alpha_code": ":man_tone3:", - "aliases": "" - }, - "1f468-1f3fe": { - "output": "1f468-1f3fe", - "name": "man: medium-dark skin tone", - "alpha_code": ":man_tone4:", - "aliases": "" - }, - "1f468-1f3ff": { - "output": "1f468-1f3ff", - "name": "man: dark skin tone", - "alpha_code": ":man_tone5:", - "aliases": "" - }, - "1f469-1f3fb": { - "output": "1f469-1f3fb", - "name": "woman: light skin tone", - "alpha_code": ":woman_tone1:", - "aliases": "" - }, - "1f469-1f3fc": { - "output": "1f469-1f3fc", - "name": "woman: medium-light skin tone", - "alpha_code": ":woman_tone2:", - "aliases": "" - }, - "1f469-1f3fd": { - "output": "1f469-1f3fd", - "name": "woman: medium skin tone", - "alpha_code": ":woman_tone3:", - "aliases": "" - }, - "1f469-1f3fe": { - "output": "1f469-1f3fe", - "name": "woman: medium-dark skin tone", - "alpha_code": ":woman_tone4:", - "aliases": "" - }, - "1f469-1f3ff": { - "output": "1f469-1f3ff", - "name": "woman: dark skin tone", - "alpha_code": ":woman_tone5:", - "aliases": "" - }, - "1f470-1f3fb": { - "output": "1f470-1f3fb", - "name": "bride with veil: light skin tone", - "alpha_code": ":bride_with_veil_tone1:", - "aliases": "" - }, - "1f470-1f3fc": { - "output": "1f470-1f3fc", - "name": "bride with veil: medium-light skin tone", - "alpha_code": ":bride_with_veil_tone2:", - "aliases": "" - }, - "1f91a-1f3ff": { - "output": "1f91a-1f3ff", - "name": "raised back of hand: dark skin tone", - "alpha_code": ":raised_back_of_hand_tone5:", - "aliases": ":back_of_hand_tone5:" - }, - "1f470-1f3fd": { - "output": "1f470-1f3fd", - "name": "bride with veil: medium skin tone", - "alpha_code": ":bride_with_veil_tone3:", - "aliases": "" - }, - "1f470-1f3fe": { - "output": "1f470-1f3fe", - "name": "bride with veil: medium-dark skin tone", - "alpha_code": ":bride_with_veil_tone4:", - "aliases": "" - }, - "1f470-1f3ff": { - "output": "1f470-1f3ff", - "name": "bride with veil: dark skin tone", - "alpha_code": ":bride_with_veil_tone5:", - "aliases": "" - }, - "1f471-1f3fb": { - "output": "1f471-1f3fb", - "name": "blond-haired person: light skin tone", - "alpha_code": ":blond_haired_person_tone1:", - "aliases": ":person_with_blond_hair_tone1:" - }, - "1f471-1f3fc": { - "output": "1f471-1f3fc", - "name": "blond-haired person: medium-light skin tone", - "alpha_code": ":blond_haired_person_tone2:", - "aliases": ":person_with_blond_hair_tone2:" - }, - "1f471-1f3fd": { - "output": "1f471-1f3fd", - "name": "blond-haired person: medium skin tone", - "alpha_code": ":blond_haired_person_tone3:", - "aliases": ":person_with_blond_hair_tone3:" - }, - "1f471-1f3fe": { - "output": "1f471-1f3fe", - "name": "blond-haired person: medium-dark skin tone", - "alpha_code": ":blond_haired_person_tone4:", - "aliases": ":person_with_blond_hair_tone4:" - }, - "1f471-1f3ff": { - "output": "1f471-1f3ff", - "name": "blond-haired person: dark skin tone", - "alpha_code": ":blond_haired_person_tone5:", - "aliases": ":person_with_blond_hair_tone5:" - }, - "1f472-1f3fb": { - "output": "1f472-1f3fb", - "name": "man with Chinese cap: light skin tone", - "alpha_code": ":man_with_chinese_cap_tone1:", - "aliases": ":man_with_gua_pi_mao_tone1:" - }, - "1f472-1f3fc": { - "output": "1f472-1f3fc", - "name": "man with Chinese cap: medium-light skin tone", - "alpha_code": ":man_with_chinese_cap_tone2:", - "aliases": ":man_with_gua_pi_mao_tone2:" - }, - "1f472-1f3fd": { - "output": "1f472-1f3fd", - "name": "man with Chinese cap: medium skin tone", - "alpha_code": ":man_with_chinese_cap_tone3:", - "aliases": ":man_with_gua_pi_mao_tone3:" - }, - "1f472-1f3fe": { - "output": "1f472-1f3fe", - "name": "man with Chinese cap: medium-dark skin tone", - "alpha_code": ":man_with_chinese_cap_tone4:", - "aliases": ":man_with_gua_pi_mao_tone4:" - }, - "1f472-1f3ff": { - "output": "1f472-1f3ff", - "name": "man with Chinese cap: dark skin tone", - "alpha_code": ":man_with_chinese_cap_tone5:", - "aliases": ":man_with_gua_pi_mao_tone5:" - }, - "1f473-1f3fb": { - "output": "1f473-1f3fb", - "name": "person wearing turban: light skin tone", - "alpha_code": ":person_wearing_turban_tone1:", - "aliases": ":man_with_turban_tone1:" - }, - "1f473-1f3fc": { - "output": "1f473-1f3fc", - "name": "person wearing turban: medium-light skin tone", - "alpha_code": ":person_wearing_turban_tone2:", - "aliases": ":man_with_turban_tone2:" - }, - "1f473-1f3fd": { - "output": "1f473-1f3fd", - "name": "person wearing turban: medium skin tone", - "alpha_code": ":person_wearing_turban_tone3:", - "aliases": ":man_with_turban_tone3:" - }, - "1f473-1f3fe": { - "output": "1f473-1f3fe", - "name": "person wearing turban: medium-dark skin tone", - "alpha_code": ":person_wearing_turban_tone4:", - "aliases": ":man_with_turban_tone4:" - }, - "1f473-1f3ff": { - "output": "1f473-1f3ff", - "name": "person wearing turban: dark skin tone", - "alpha_code": ":person_wearing_turban_tone5:", - "aliases": ":man_with_turban_tone5:" - }, - "1f474-1f3fb": { - "output": "1f474-1f3fb", - "name": "old man: light skin tone", - "alpha_code": ":older_man_tone1:", - "aliases": "" - }, - "1f474-1f3fc": { - "output": "1f474-1f3fc", - "name": "old man: medium-light skin tone", - "alpha_code": ":older_man_tone2:", - "aliases": "" - }, - "1f474-1f3fd": { - "output": "1f474-1f3fd", - "name": "old man: medium skin tone", - "alpha_code": ":older_man_tone3:", - "aliases": "" - }, - "1f474-1f3fe": { - "output": "1f474-1f3fe", - "name": "old man: medium-dark skin tone", - "alpha_code": ":older_man_tone4:", - "aliases": "" - }, - "1f474-1f3ff": { - "output": "1f474-1f3ff", - "name": "old man: dark skin tone", - "alpha_code": ":older_man_tone5:", - "aliases": "" - }, - "1f475-1f3fb": { - "output": "1f475-1f3fb", - "name": "old woman: light skin tone", - "alpha_code": ":older_woman_tone1:", - "aliases": ":grandma_tone1:" - }, - "1f475-1f3fc": { - "output": "1f475-1f3fc", - "name": "old woman: medium-light skin tone", - "alpha_code": ":older_woman_tone2:", - "aliases": ":grandma_tone2:" - }, - "1f475-1f3fd": { - "output": "1f475-1f3fd", - "name": "old woman: medium skin tone", - "alpha_code": ":older_woman_tone3:", - "aliases": ":grandma_tone3:" - }, - "1f475-1f3fe": { - "output": "1f475-1f3fe", - "name": "old woman: medium-dark skin tone", - "alpha_code": ":older_woman_tone4:", - "aliases": ":grandma_tone4:" - }, - "1f475-1f3ff": { - "output": "1f475-1f3ff", - "name": "old woman: dark skin tone", - "alpha_code": ":older_woman_tone5:", - "aliases": ":grandma_tone5:" - }, - "1f46e-1f3fb": { - "output": "1f46e-1f3fb", - "name": "police officer: light skin tone", - "alpha_code": ":police_officer_tone1:", - "aliases": ":cop_tone1:" - }, - "1f46e-1f3fc": { - "output": "1f46e-1f3fc", - "name": "police officer: medium-light skin tone", - "alpha_code": ":police_officer_tone2:", - "aliases": ":cop_tone2:" - }, - "1f46e-1f3fd": { - "output": "1f46e-1f3fd", - "name": "police officer: medium skin tone", - "alpha_code": ":police_officer_tone3:", - "aliases": ":cop_tone3:" - }, - "1f46e-1f3fe": { - "output": "1f46e-1f3fe", - "name": "police officer: medium-dark skin tone", - "alpha_code": ":police_officer_tone4:", - "aliases": ":cop_tone4:" - }, - "1f46e-1f3ff": { - "output": "1f46e-1f3ff", - "name": "police officer: dark skin tone", - "alpha_code": ":police_officer_tone5:", - "aliases": ":cop_tone5:" - }, - "1f477-1f3fb": { - "output": "1f477-1f3fb", - "name": "construction worker: light skin tone", - "alpha_code": ":construction_worker_tone1:", - "aliases": "" - }, - "1f477-1f3fc": { - "output": "1f477-1f3fc", - "name": "construction worker: medium-light skin tone", - "alpha_code": ":construction_worker_tone2:", - "aliases": "" - }, - "1f477-1f3fd": { - "output": "1f477-1f3fd", - "name": "construction worker: medium skin tone", - "alpha_code": ":construction_worker_tone3:", - "aliases": "" - }, - "1f477-1f3fe": { - "output": "1f477-1f3fe", - "name": "construction worker: medium-dark skin tone", - "alpha_code": ":construction_worker_tone4:", - "aliases": "" - }, - "1f477-1f3ff": { - "output": "1f477-1f3ff", - "name": "construction worker: dark skin tone", - "alpha_code": ":construction_worker_tone5:", - "aliases": "" - }, - "1f478-1f3fb": { - "output": "1f478-1f3fb", - "name": "princess: light skin tone", - "alpha_code": ":princess_tone1:", - "aliases": "" - }, - "1f478-1f3fc": { - "output": "1f478-1f3fc", - "name": "princess: medium-light skin tone", - "alpha_code": ":princess_tone2:", - "aliases": "" - }, - "1f478-1f3fd": { - "output": "1f478-1f3fd", - "name": "princess: medium skin tone", - "alpha_code": ":princess_tone3:", - "aliases": "" - }, - "1f478-1f3fe": { - "output": "1f478-1f3fe", - "name": "princess: medium-dark skin tone", - "alpha_code": ":princess_tone4:", - "aliases": "" - }, - "1f938-1f3fb": { - "output": "1f938-1f3fb", - "name": "person cartwheeling: light skin tone", - "alpha_code": ":person_doing_cartwheel_tone1:", - "aliases": ":cartwheel_tone1:" - }, - "1f478-1f3ff": { - "output": "1f478-1f3ff", - "name": "princess: dark skin tone", - "alpha_code": ":princess_tone5:", - "aliases": "" - }, - "1f482-1f3fb": { - "output": "1f482-1f3fb", - "name": "guard: light skin tone", - "alpha_code": ":guard_tone1:", - "aliases": ":guardsman_tone1:" - }, - "1f482-1f3fc": { - "output": "1f482-1f3fc", - "name": "guard: medium-light skin tone", - "alpha_code": ":guard_tone2:", - "aliases": ":guardsman_tone2:" - }, - "1f938-1f3fc": { - "output": "1f938-1f3fc", - "name": "person cartwheeling: medium-light skin tone", - "alpha_code": ":person_doing_cartwheel_tone2:", - "aliases": ":cartwheel_tone2:" - }, - "1f482-1f3fd": { - "output": "1f482-1f3fd", - "name": "guard: medium skin tone", - "alpha_code": ":guard_tone3:", - "aliases": ":guardsman_tone3:" - }, - "1f482-1f3fe": { - "output": "1f482-1f3fe", - "name": "guard: medium-dark skin tone", - "alpha_code": ":guard_tone4:", - "aliases": ":guardsman_tone4:" - }, - "1f482-1f3ff": { - "output": "1f482-1f3ff", - "name": "guard: dark skin tone", - "alpha_code": ":guard_tone5:", - "aliases": ":guardsman_tone5:" - }, - "1f938-1f3fd": { - "output": "1f938-1f3fd", - "name": "person cartwheeling: medium skin tone", - "alpha_code": ":person_doing_cartwheel_tone3:", - "aliases": ":cartwheel_tone3:" - }, - "1f47c-1f3fb": { - "output": "1f47c-1f3fb", - "name": "baby angel: light skin tone", - "alpha_code": ":angel_tone1:", - "aliases": "" - }, - "1f47c-1f3fc": { - "output": "1f47c-1f3fc", - "name": "baby angel: medium-light skin tone", - "alpha_code": ":angel_tone2:", - "aliases": "" - }, - "1f47c-1f3fd": { - "output": "1f47c-1f3fd", - "name": "baby angel: medium skin tone", - "alpha_code": ":angel_tone3:", - "aliases": "" - }, - "1f47c-1f3fe": { - "output": "1f47c-1f3fe", - "name": "baby angel: medium-dark skin tone", - "alpha_code": ":angel_tone4:", - "aliases": "" - }, - "1f47c-1f3ff": { - "output": "1f47c-1f3ff", - "name": "baby angel: dark skin tone", - "alpha_code": ":angel_tone5:", - "aliases": "" - }, - "1f647-1f3fb": { - "output": "1f647-1f3fb", - "name": "person bowing: light skin tone", - "alpha_code": ":person_bowing_tone1:", - "aliases": ":bow_tone1:" - }, - "1f647-1f3fc": { - "output": "1f647-1f3fc", - "name": "person bowing: medium-light skin tone", - "alpha_code": ":person_bowing_tone2:", - "aliases": ":bow_tone2:" - }, - "1f647-1f3fd": { - "output": "1f647-1f3fd", - "name": "person bowing: medium skin tone", - "alpha_code": ":person_bowing_tone3:", - "aliases": ":bow_tone3:" - }, - "1f647-1f3fe": { - "output": "1f647-1f3fe", - "name": "person bowing: medium-dark skin tone", - "alpha_code": ":person_bowing_tone4:", - "aliases": ":bow_tone4:" - }, - "1f647-1f3ff": { - "output": "1f647-1f3ff", - "name": "person bowing: dark skin tone", - "alpha_code": ":person_bowing_tone5:", - "aliases": ":bow_tone5:" - }, - "1f481-1f3fb": { - "output": "1f481-1f3fb", - "name": "person tipping hand: light skin tone", - "alpha_code": ":person_tipping_hand_tone1:", - "aliases": ":information_desk_person_tone1:" - }, - "1f481-1f3fc": { - "output": "1f481-1f3fc", - "name": "person tipping hand: medium-light skin tone", - "alpha_code": ":person_tipping_hand_tone2:", - "aliases": ":information_desk_person_tone2:" - }, - "1f481-1f3fd": { - "output": "1f481-1f3fd", - "name": "person tipping hand: medium skin tone", - "alpha_code": ":person_tipping_hand_tone3:", - "aliases": ":information_desk_person_tone3:" - }, - "1f938-1f3fe": { - "output": "1f938-1f3fe", - "name": "person cartwheeling: medium-dark skin tone", - "alpha_code": ":person_doing_cartwheel_tone4:", - "aliases": ":cartwheel_tone4:" - }, - "1f481-1f3fe": { - "output": "1f481-1f3fe", - "name": "person tipping hand: medium-dark skin tone", - "alpha_code": ":person_tipping_hand_tone4:", - "aliases": ":information_desk_person_tone4:" - }, - "1f481-1f3ff": { - "output": "1f481-1f3ff", - "name": "person tipping hand: dark skin tone", - "alpha_code": ":person_tipping_hand_tone5:", - "aliases": ":information_desk_person_tone5:" - }, - "1f645-1f3fb": { - "output": "1f645-1f3fb", - "name": "person gesturing NO: light skin tone", - "alpha_code": ":person_gesturing_no_tone1:", - "aliases": ":no_good_tone1:" - }, - "1f938-1f3ff": { - "output": "1f938-1f3ff", - "name": "person cartwheeling: dark skin tone", - "alpha_code": ":person_doing_cartwheel_tone5:", - "aliases": ":cartwheel_tone5:" - }, - "1f645-1f3fc": { - "output": "1f645-1f3fc", - "name": "person gesturing NO: medium-light skin tone", - "alpha_code": ":person_gesturing_no_tone2:", - "aliases": ":no_good_tone2:" - }, - "1f645-1f3fd": { - "output": "1f645-1f3fd", - "name": "person gesturing NO: medium skin tone", - "alpha_code": ":person_gesturing_no_tone3:", - "aliases": ":no_good_tone3:" - }, - "1f645-1f3fe": { - "output": "1f645-1f3fe", - "name": "person gesturing NO: medium-dark skin tone", - "alpha_code": ":person_gesturing_no_tone4:", - "aliases": ":no_good_tone4:" - }, - "1f645-1f3ff": { - "output": "1f645-1f3ff", - "name": "person gesturing NO: dark skin tone", - "alpha_code": ":person_gesturing_no_tone5:", - "aliases": ":no_good_tone5:" - }, - "1f646-1f3fb": { - "output": "1f646-1f3fb", - "name": "person gesturing OK: light skin tone", - "alpha_code": ":person_gesturing_ok_tone1:", - "aliases": ":ok_woman_tone1:" - }, - "1f646-1f3fc": { - "output": "1f646-1f3fc", - "name": "person gesturing OK: medium-light skin tone", - "alpha_code": ":person_gesturing_ok_tone2:", - "aliases": ":ok_woman_tone2:" - }, - "1f646-1f3fd": { - "output": "1f646-1f3fd", - "name": "person gesturing OK: medium skin tone", - "alpha_code": ":person_gesturing_ok_tone3:", - "aliases": ":ok_woman_tone3:" - }, - "1f646-1f3fe": { - "output": "1f646-1f3fe", - "name": "person gesturing OK: medium-dark skin tone", - "alpha_code": ":person_gesturing_ok_tone4:", - "aliases": ":ok_woman_tone4:" - }, - "1f646-1f3ff": { - "output": "1f646-1f3ff", - "name": "person gesturing OK: dark skin tone", - "alpha_code": ":person_gesturing_ok_tone5:", - "aliases": ":ok_woman_tone5:" - }, - "1f64b-1f3fb": { - "output": "1f64b-1f3fb", - "name": "person raising hand: light skin tone", - "alpha_code": ":person_raising_hand_tone1:", - "aliases": ":raising_hand_tone1:" - }, - "1f64b-1f3fc": { - "output": "1f64b-1f3fc", - "name": "person raising hand: medium-light skin tone", - "alpha_code": ":person_raising_hand_tone2:", - "aliases": ":raising_hand_tone2:" - }, - "1f64b-1f3fd": { - "output": "1f64b-1f3fd", - "name": "person raising hand: medium skin tone", - "alpha_code": ":person_raising_hand_tone3:", - "aliases": ":raising_hand_tone3:" - }, - "1f64b-1f3fe": { - "output": "1f64b-1f3fe", - "name": "person raising hand: medium-dark skin tone", - "alpha_code": ":person_raising_hand_tone4:", - "aliases": ":raising_hand_tone4:" - }, - "1f64b-1f3ff": { - "output": "1f64b-1f3ff", - "name": "person raising hand: dark skin tone", - "alpha_code": ":person_raising_hand_tone5:", - "aliases": ":raising_hand_tone5:" - }, - "1f64e-1f3fb": { - "output": "1f64e-1f3fb", - "name": "person pouting: light skin tone", - "alpha_code": ":person_pouting_tone1:", - "aliases": ":person_with_pouting_face_tone1:" - }, - "1f64e-1f3fc": { - "output": "1f64e-1f3fc", - "name": "person pouting: medium-light skin tone", - "alpha_code": ":person_pouting_tone2:", - "aliases": ":person_with_pouting_face_tone2:" - }, - "1f64e-1f3fd": { - "output": "1f64e-1f3fd", - "name": "person pouting: medium skin tone", - "alpha_code": ":person_pouting_tone3:", - "aliases": ":person_with_pouting_face_tone3:" - }, - "1f64e-1f3fe": { - "output": "1f64e-1f3fe", - "name": "person pouting: medium-dark skin tone", - "alpha_code": ":person_pouting_tone4:", - "aliases": ":person_with_pouting_face_tone4:" - }, - "1f64e-1f3ff": { - "output": "1f64e-1f3ff", - "name": "person pouting: dark skin tone", - "alpha_code": ":person_pouting_tone5:", - "aliases": ":person_with_pouting_face_tone5:" - }, - "1f64d-1f3fb": { - "output": "1f64d-1f3fb", - "name": "person frowning: light skin tone", - "alpha_code": ":person_frowning_tone1:", - "aliases": "" - }, - "1f64d-1f3fc": { - "output": "1f64d-1f3fc", - "name": "person frowning: medium-light skin tone", - "alpha_code": ":person_frowning_tone2:", - "aliases": "" - }, - "1f64d-1f3fd": { - "output": "1f64d-1f3fd", - "name": "person frowning: medium skin tone", - "alpha_code": ":person_frowning_tone3:", - "aliases": "" - }, - "1f64d-1f3fe": { - "output": "1f64d-1f3fe", - "name": "person frowning: medium-dark skin tone", - "alpha_code": ":person_frowning_tone4:", - "aliases": "" - }, - "1f64d-1f3ff": { - "output": "1f64d-1f3ff", - "name": "person frowning: dark skin tone", - "alpha_code": ":person_frowning_tone5:", - "aliases": "" - }, - "1f486-1f3fb": { - "output": "1f486-1f3fb", - "name": "person getting massage: light skin tone", - "alpha_code": ":person_getting_massage_tone1:", - "aliases": ":massage_tone1:" - }, - "1f486-1f3fc": { - "output": "1f486-1f3fc", - "name": "person getting massage: medium-light skin tone", - "alpha_code": ":person_getting_massage_tone2:", - "aliases": ":massage_tone2:" - }, - "1f486-1f3fd": { - "output": "1f486-1f3fd", - "name": "person getting massage: medium skin tone", - "alpha_code": ":person_getting_massage_tone3:", - "aliases": ":massage_tone3:" - }, - "1f486-1f3fe": { - "output": "1f486-1f3fe", - "name": "person getting massage: medium-dark skin tone", - "alpha_code": ":person_getting_massage_tone4:", - "aliases": ":massage_tone4:" - }, - "1f486-1f3ff": { - "output": "1f486-1f3ff", - "name": "person getting massage: dark skin tone", - "alpha_code": ":person_getting_massage_tone5:", - "aliases": ":massage_tone5:" - }, - "1f487-1f3fb": { - "output": "1f487-1f3fb", - "name": "person getting haircut: light skin tone", - "alpha_code": ":person_getting_haircut_tone1:", - "aliases": ":haircut_tone1:" - }, - "1f487-1f3fc": { - "output": "1f487-1f3fc", - "name": "person getting haircut: medium-light skin tone", - "alpha_code": ":person_getting_haircut_tone2:", - "aliases": ":haircut_tone2:" - }, - "1f487-1f3fd": { - "output": "1f487-1f3fd", - "name": "person getting haircut: medium skin tone", - "alpha_code": ":person_getting_haircut_tone3:", - "aliases": ":haircut_tone3:" - }, - "1f487-1f3fe": { - "output": "1f487-1f3fe", - "name": "person getting haircut: medium-dark skin tone", - "alpha_code": ":person_getting_haircut_tone4:", - "aliases": ":haircut_tone4:" - }, - "1f487-1f3ff": { - "output": "1f487-1f3ff", - "name": "person getting haircut: dark skin tone", - "alpha_code": ":person_getting_haircut_tone5:", - "aliases": ":haircut_tone5:" - }, - "1f64c-1f3fb": { - "output": "1f64c-1f3fb", - "name": "raising hands: light skin tone", - "alpha_code": ":raised_hands_tone1:", - "aliases": "" - }, - "1f64c-1f3fc": { - "output": "1f64c-1f3fc", - "name": "raising hands: medium-light skin tone", - "alpha_code": ":raised_hands_tone2:", - "aliases": "" - }, - "1f64c-1f3fd": { - "output": "1f64c-1f3fd", - "name": "raising hands: medium skin tone", - "alpha_code": ":raised_hands_tone3:", - "aliases": "" - }, - "1f64c-1f3fe": { - "output": "1f64c-1f3fe", - "name": "raising hands: medium-dark skin tone", - "alpha_code": ":raised_hands_tone4:", - "aliases": "" - }, - "1f64c-1f3ff": { - "output": "1f64c-1f3ff", - "name": "raising hands: dark skin tone", - "alpha_code": ":raised_hands_tone5:", - "aliases": "" - }, - "1f44f-1f3fb": { - "output": "1f44f-1f3fb", - "name": "clapping hands: light skin tone", - "alpha_code": ":clap_tone1:", - "aliases": "" - }, - "1f44f-1f3fc": { - "output": "1f44f-1f3fc", - "name": "clapping hands: medium-light skin tone", - "alpha_code": ":clap_tone2:", - "aliases": "" - }, - "1f44f-1f3fd": { - "output": "1f44f-1f3fd", - "name": "clapping hands: medium skin tone", - "alpha_code": ":clap_tone3:", - "aliases": "" - }, - "1f93d-1f3fb": { - "output": "1f93d-1f3fb", - "name": "person playing water polo: light skin tone", - "alpha_code": ":person_playing_water_polo_tone1:", - "aliases": ":water_polo_tone1:" - }, - "1f44f-1f3fe": { - "output": "1f44f-1f3fe", - "name": "clapping hands: medium-dark skin tone", - "alpha_code": ":clap_tone4:", - "aliases": "" - }, - "1f44f-1f3ff": { - "output": "1f44f-1f3ff", - "name": "clapping hands: dark skin tone", - "alpha_code": ":clap_tone5:", - "aliases": "" - }, - "1f93d-1f3fc": { - "output": "1f93d-1f3fc", - "name": "person playing water polo: medium-light skin tone", - "alpha_code": ":person_playing_water_polo_tone2:", - "aliases": ":water_polo_tone2:" - }, - "1f442-1f3fb": { - "output": "1f442-1f3fb", - "name": "ear: light skin tone", - "alpha_code": ":ear_tone1:", - "aliases": "" - }, - "1f442-1f3fc": { - "output": "1f442-1f3fc", - "name": "ear: medium-light skin tone", - "alpha_code": ":ear_tone2:", - "aliases": "" - }, - "1f442-1f3fd": { - "output": "1f442-1f3fd", - "name": "ear: medium skin tone", - "alpha_code": ":ear_tone3:", - "aliases": "" - }, - "1f442-1f3fe": { - "output": "1f442-1f3fe", - "name": "ear: medium-dark skin tone", - "alpha_code": ":ear_tone4:", - "aliases": "" - }, - "1f442-1f3ff": { - "output": "1f442-1f3ff", - "name": "ear: dark skin tone", - "alpha_code": ":ear_tone5:", - "aliases": "" - }, - "1f443-1f3fb": { - "output": "1f443-1f3fb", - "name": "nose: light skin tone", - "alpha_code": ":nose_tone1:", - "aliases": "" - }, - "1f443-1f3fc": { - "output": "1f443-1f3fc", - "name": "nose: medium-light skin tone", - "alpha_code": ":nose_tone2:", - "aliases": "" - }, - "1f443-1f3fd": { - "output": "1f443-1f3fd", - "name": "nose: medium skin tone", - "alpha_code": ":nose_tone3:", - "aliases": "" - }, - "1f443-1f3fe": { - "output": "1f443-1f3fe", - "name": "nose: medium-dark skin tone", - "alpha_code": ":nose_tone4:", - "aliases": "" - }, - "1f443-1f3ff": { - "output": "1f443-1f3ff", - "name": "nose: dark skin tone", - "alpha_code": ":nose_tone5:", - "aliases": "" - }, - "1f485-1f3fb": { - "output": "1f485-1f3fb", - "name": "nail polish: light skin tone", - "alpha_code": ":nail_care_tone1:", - "aliases": "" - }, - "1f485-1f3fc": { - "output": "1f485-1f3fc", - "name": "nail polish: medium-light skin tone", - "alpha_code": ":nail_care_tone2:", - "aliases": "" - }, - "1f485-1f3fd": { - "output": "1f485-1f3fd", - "name": "nail polish: medium skin tone", - "alpha_code": ":nail_care_tone3:", - "aliases": "" - }, - "1f485-1f3fe": { - "output": "1f485-1f3fe", - "name": "nail polish: medium-dark skin tone", - "alpha_code": ":nail_care_tone4:", - "aliases": "" - }, - "1f485-1f3ff": { - "output": "1f485-1f3ff", - "name": "nail polish: dark skin tone", - "alpha_code": ":nail_care_tone5:", - "aliases": "" - }, - "1f44b-1f3fb": { - "output": "1f44b-1f3fb", - "name": "waving hand: light skin tone", - "alpha_code": ":wave_tone1:", - "aliases": "" - }, - "1f44b-1f3fc": { - "output": "1f44b-1f3fc", - "name": "waving hand: medium-light skin tone", - "alpha_code": ":wave_tone2:", - "aliases": "" - }, - "1f44b-1f3fd": { - "output": "1f44b-1f3fd", - "name": "waving hand: medium skin tone", - "alpha_code": ":wave_tone3:", - "aliases": "" - }, - "1f44b-1f3fe": { - "output": "1f44b-1f3fe", - "name": "waving hand: medium-dark skin tone", - "alpha_code": ":wave_tone4:", - "aliases": "" - }, - "1f44b-1f3ff": { - "output": "1f44b-1f3ff", - "name": "waving hand: dark skin tone", - "alpha_code": ":wave_tone5:", - "aliases": "" - }, - "1f44d-1f3fb": { - "output": "1f44d-1f3fb", - "name": "thumbs up: light skin tone", - "alpha_code": ":thumbsup_tone1:", - "aliases": ":+1_tone1:|:thumbup_tone1:" - }, - "1f44d-1f3fc": { - "output": "1f44d-1f3fc", - "name": "thumbs up: medium-light skin tone", - "alpha_code": ":thumbsup_tone2:", - "aliases": ":+1_tone2:|:thumbup_tone2:" - }, - "1f44d-1f3fd": { - "output": "1f44d-1f3fd", - "name": "thumbs up: medium skin tone", - "alpha_code": ":thumbsup_tone3:", - "aliases": ":+1_tone3:|:thumbup_tone3:" - }, - "1f44d-1f3fe": { - "output": "1f44d-1f3fe", - "name": "thumbs up: medium-dark skin tone", - "alpha_code": ":thumbsup_tone4:", - "aliases": ":+1_tone4:|:thumbup_tone4:" - }, - "1f44d-1f3ff": { - "output": "1f44d-1f3ff", - "name": "thumbs up: dark skin tone", - "alpha_code": ":thumbsup_tone5:", - "aliases": ":+1_tone5:|:thumbup_tone5:" - }, - "1f44e-1f3fb": { - "output": "1f44e-1f3fb", - "name": "thumbs down: light skin tone", - "alpha_code": ":thumbsdown_tone1:", - "aliases": ":-1_tone1:|:thumbdown_tone1:" - }, - "1f44e-1f3fc": { - "output": "1f44e-1f3fc", - "name": "thumbs down: medium-light skin tone", - "alpha_code": ":thumbsdown_tone2:", - "aliases": ":-1_tone2:|:thumbdown_tone2:" - }, - "1f44e-1f3fd": { - "output": "1f44e-1f3fd", - "name": "thumbs down: medium skin tone", - "alpha_code": ":thumbsdown_tone3:", - "aliases": ":-1_tone3:|:thumbdown_tone3:" - }, - "1f44e-1f3fe": { - "output": "1f44e-1f3fe", - "name": "thumbs down: medium-dark skin tone", - "alpha_code": ":thumbsdown_tone4:", - "aliases": ":-1_tone4:|:thumbdown_tone4:" - }, - "1f44e-1f3ff": { - "output": "1f44e-1f3ff", - "name": "thumbs down: dark skin tone", - "alpha_code": ":thumbsdown_tone5:", - "aliases": ":-1_tone5:|:thumbdown_tone5:" - }, - "261d-1f3fb": { - "output": "261d-1f3fb", - "name": "index pointing up: light skin tone", - "alpha_code": ":point_up_tone1:", - "aliases": "" - }, - "261d-1f3fc": { - "output": "261d-1f3fc", - "name": "index pointing up: medium-light skin tone", - "alpha_code": ":point_up_tone2:", - "aliases": "" - }, - "261d-1f3fd": { - "output": "261d-1f3fd", - "name": "index pointing up: medium skin tone", - "alpha_code": ":point_up_tone3:", - "aliases": "" - }, - "261d-1f3fe": { - "output": "261d-1f3fe", - "name": "index pointing up: medium-dark skin tone", - "alpha_code": ":point_up_tone4:", - "aliases": "" - }, - "261d-1f3ff": { - "output": "261d-1f3ff", - "name": "index pointing up: dark skin tone", - "alpha_code": ":point_up_tone5:", - "aliases": "" - }, - "1f446-1f3fb": { - "output": "1f446-1f3fb", - "name": "backhand index pointing up: light skin tone", - "alpha_code": ":point_up_2_tone1:", - "aliases": "" - }, - "1f446-1f3fc": { - "output": "1f446-1f3fc", - "name": "backhand index pointing up: medium-light skin tone", - "alpha_code": ":point_up_2_tone2:", - "aliases": "" - }, - "1f446-1f3fd": { - "output": "1f446-1f3fd", - "name": "backhand index pointing up: medium skin tone", - "alpha_code": ":point_up_2_tone3:", - "aliases": "" - }, - "1f446-1f3fe": { - "output": "1f446-1f3fe", - "name": "backhand index pointing up: medium-dark skin tone", - "alpha_code": ":point_up_2_tone4:", - "aliases": "" - }, - "1f446-1f3ff": { - "output": "1f446-1f3ff", - "name": "backhand index pointing up: dark skin tone", - "alpha_code": ":point_up_2_tone5:", - "aliases": "" - }, - "1f447-1f3fb": { - "output": "1f447-1f3fb", - "name": "backhand index pointing down: light skin tone", - "alpha_code": ":point_down_tone1:", - "aliases": "" - }, - "1f447-1f3fc": { - "output": "1f447-1f3fc", - "name": "backhand index pointing down: medium-light skin tone", - "alpha_code": ":point_down_tone2:", - "aliases": "" - }, - "1f447-1f3fd": { - "output": "1f447-1f3fd", - "name": "backhand index pointing down: medium skin tone", - "alpha_code": ":point_down_tone3:", - "aliases": "" - }, - "1f447-1f3fe": { - "output": "1f447-1f3fe", - "name": "backhand index pointing down: medium-dark skin tone", - "alpha_code": ":point_down_tone4:", - "aliases": "" - }, - "1f447-1f3ff": { - "output": "1f447-1f3ff", - "name": "backhand index pointing down: dark skin tone", - "alpha_code": ":point_down_tone5:", - "aliases": "" - }, - "1f448-1f3fb": { - "output": "1f448-1f3fb", - "name": "backhand index pointing left: light skin tone", - "alpha_code": ":point_left_tone1:", - "aliases": "" - }, - "1f448-1f3fc": { - "output": "1f448-1f3fc", - "name": "backhand index pointing left: medium-light skin tone", - "alpha_code": ":point_left_tone2:", - "aliases": "" - }, - "1f448-1f3fd": { - "output": "1f448-1f3fd", - "name": "backhand index pointing left: medium skin tone", - "alpha_code": ":point_left_tone3:", - "aliases": "" - }, - "1f448-1f3fe": { - "output": "1f448-1f3fe", - "name": "backhand index pointing left: medium-dark skin tone", - "alpha_code": ":point_left_tone4:", - "aliases": "" - }, - "1f448-1f3ff": { - "output": "1f448-1f3ff", - "name": "backhand index pointing left: dark skin tone", - "alpha_code": ":point_left_tone5:", - "aliases": "" - }, - "1f449-1f3fb": { - "output": "1f449-1f3fb", - "name": "backhand index pointing right: light skin tone", - "alpha_code": ":point_right_tone1:", - "aliases": "" - }, - "1f449-1f3fc": { - "output": "1f449-1f3fc", - "name": "backhand index pointing right: medium-light skin tone", - "alpha_code": ":point_right_tone2:", - "aliases": "" - }, - "1f449-1f3fd": { - "output": "1f449-1f3fd", - "name": "backhand index pointing right: medium skin tone", - "alpha_code": ":point_right_tone3:", - "aliases": "" - }, - "1f449-1f3fe": { - "output": "1f449-1f3fe", - "name": "backhand index pointing right: medium-dark skin tone", - "alpha_code": ":point_right_tone4:", - "aliases": "" - }, - "1f449-1f3ff": { - "output": "1f449-1f3ff", - "name": "backhand index pointing right: dark skin tone", - "alpha_code": ":point_right_tone5:", - "aliases": "" - }, - "1f44c-1f3fb": { - "output": "1f44c-1f3fb", - "name": "OK hand: light skin tone", - "alpha_code": ":ok_hand_tone1:", - "aliases": "" - }, - "1f44c-1f3fc": { - "output": "1f44c-1f3fc", - "name": "OK hand: medium-light skin tone", - "alpha_code": ":ok_hand_tone2:", - "aliases": "" - }, - "1f93d-1f3fd": { - "output": "1f93d-1f3fd", - "name": "person playing water polo: medium skin tone", - "alpha_code": ":person_playing_water_polo_tone3:", - "aliases": ":water_polo_tone3:" - }, - "1f44c-1f3fd": { - "output": "1f44c-1f3fd", - "name": "OK hand: medium skin tone", - "alpha_code": ":ok_hand_tone3:", - "aliases": "" - }, - "1f44c-1f3fe": { - "output": "1f44c-1f3fe", - "name": "OK hand: medium-dark skin tone", - "alpha_code": ":ok_hand_tone4:", - "aliases": "" - }, - "1f93d-1f3fe": { - "output": "1f93d-1f3fe", - "name": "person playing water polo: medium-dark skin tone", - "alpha_code": ":person_playing_water_polo_tone4:", - "aliases": ":water_polo_tone4:" - }, - "1f44c-1f3ff": { - "output": "1f44c-1f3ff", - "name": "OK hand: dark skin tone", - "alpha_code": ":ok_hand_tone5:", - "aliases": "" - }, - "270c-1f3fb": { - "output": "270c-1f3fb", - "name": "victory hand: light skin tone", - "alpha_code": ":v_tone1:", - "aliases": "" - }, - "270c-1f3fc": { - "output": "270c-1f3fc", - "name": "victory hand: medium-light skin tone", - "alpha_code": ":v_tone2:", - "aliases": "" - }, - "270c-1f3fd": { - "output": "270c-1f3fd", - "name": "victory hand: medium skin tone", - "alpha_code": ":v_tone3:", - "aliases": "" - }, - "270c-1f3fe": { - "output": "270c-1f3fe", - "name": "victory hand: medium-dark skin tone", - "alpha_code": ":v_tone4:", - "aliases": "" - }, - "270c-1f3ff": { - "output": "270c-1f3ff", - "name": "victory hand: dark skin tone", - "alpha_code": ":v_tone5:", - "aliases": "" - }, - "1f44a-1f3fb": { - "output": "1f44a-1f3fb", - "name": "oncoming fist: light skin tone", - "alpha_code": ":punch_tone1:", - "aliases": "" - }, - "1f44a-1f3fc": { - "output": "1f44a-1f3fc", - "name": "oncoming fist: medium-light skin tone", - "alpha_code": ":punch_tone2:", - "aliases": "" - }, - "1f44a-1f3fd": { - "output": "1f44a-1f3fd", - "name": "oncoming fist: medium skin tone", - "alpha_code": ":punch_tone3:", - "aliases": "" - }, - "1f44a-1f3fe": { - "output": "1f44a-1f3fe", - "name": "oncoming fist: medium-dark skin tone", - "alpha_code": ":punch_tone4:", - "aliases": "" - }, - "1f44a-1f3ff": { - "output": "1f44a-1f3ff", - "name": "oncoming fist: dark skin tone", - "alpha_code": ":punch_tone5:", - "aliases": "" - }, - "270a-1f3fb": { - "output": "270a-1f3fb", - "name": "raised fist: light skin tone", - "alpha_code": ":fist_tone1:", - "aliases": "" - }, - "270a-1f3fc": { - "output": "270a-1f3fc", - "name": "raised fist: medium-light skin tone", - "alpha_code": ":fist_tone2:", - "aliases": "" - }, - "270a-1f3fd": { - "output": "270a-1f3fd", - "name": "raised fist: medium skin tone", - "alpha_code": ":fist_tone3:", - "aliases": "" - }, - "270a-1f3fe": { - "output": "270a-1f3fe", - "name": "raised fist: medium-dark skin tone", - "alpha_code": ":fist_tone4:", - "aliases": "" - }, - "270a-1f3ff": { - "output": "270a-1f3ff", - "name": "raised fist: dark skin tone", - "alpha_code": ":fist_tone5:", - "aliases": "" - }, - "270b-1f3fb": { - "output": "270b-1f3fb", - "name": "raised hand: light skin tone", - "alpha_code": ":raised_hand_tone1:", - "aliases": "" - }, - "270b-1f3fc": { - "output": "270b-1f3fc", - "name": "raised hand: medium-light skin tone", - "alpha_code": ":raised_hand_tone2:", - "aliases": "" - }, - "270b-1f3fd": { - "output": "270b-1f3fd", - "name": "raised hand: medium skin tone", - "alpha_code": ":raised_hand_tone3:", - "aliases": "" - }, - "270b-1f3fe": { - "output": "270b-1f3fe", - "name": "raised hand: medium-dark skin tone", - "alpha_code": ":raised_hand_tone4:", - "aliases": "" - }, - "270b-1f3ff": { - "output": "270b-1f3ff", - "name": "raised hand: dark skin tone", - "alpha_code": ":raised_hand_tone5:", - "aliases": "" - }, - "1f4aa-1f3fb": { - "output": "1f4aa-1f3fb", - "name": "flexed biceps: light skin tone", - "alpha_code": ":muscle_tone1:", - "aliases": "" - }, - "1f4aa-1f3fc": { - "output": "1f4aa-1f3fc", - "name": "flexed biceps: medium-light skin tone", - "alpha_code": ":muscle_tone2:", - "aliases": "" - }, - "1f4aa-1f3fd": { - "output": "1f4aa-1f3fd", - "name": "flexed biceps: medium skin tone", - "alpha_code": ":muscle_tone3:", - "aliases": "" - }, - "1f4aa-1f3fe": { - "output": "1f4aa-1f3fe", - "name": "flexed biceps: medium-dark skin tone", - "alpha_code": ":muscle_tone4:", - "aliases": "" - }, - "1f4aa-1f3ff": { - "output": "1f4aa-1f3ff", - "name": "flexed biceps: dark skin tone", - "alpha_code": ":muscle_tone5:", - "aliases": "" - }, - "1f450-1f3fb": { - "output": "1f450-1f3fb", - "name": "open hands: light skin tone", - "alpha_code": ":open_hands_tone1:", - "aliases": "" - }, - "1f450-1f3fc": { - "output": "1f450-1f3fc", - "name": "open hands: medium-light skin tone", - "alpha_code": ":open_hands_tone2:", - "aliases": "" - }, - "1f450-1f3fd": { - "output": "1f450-1f3fd", - "name": "open hands: medium skin tone", - "alpha_code": ":open_hands_tone3:", - "aliases": "" - }, - "1f450-1f3fe": { - "output": "1f450-1f3fe", - "name": "open hands: medium-dark skin tone", - "alpha_code": ":open_hands_tone4:", - "aliases": "" - }, - "1f450-1f3ff": { - "output": "1f450-1f3ff", - "name": "open hands: dark skin tone", - "alpha_code": ":open_hands_tone5:", - "aliases": "" - }, - "1f64f-1f3fb": { - "output": "1f64f-1f3fb", - "name": "folded hands: light skin tone", - "alpha_code": ":pray_tone1:", - "aliases": "" - }, - "1f93d-1f3ff": { - "output": "1f93d-1f3ff", - "name": "person playing water polo: dark skin tone", - "alpha_code": ":person_playing_water_polo_tone5:", - "aliases": ":water_polo_tone5:" - }, - "1f64f-1f3fc": { - "output": "1f64f-1f3fc", - "name": "folded hands: medium-light skin tone", - "alpha_code": ":pray_tone2:", - "aliases": "" - }, - "1f64f-1f3fd": { - "output": "1f64f-1f3fd", - "name": "folded hands: medium skin tone", - "alpha_code": ":pray_tone3:", - "aliases": "" - }, - "1f93e-1f3fb": { - "output": "1f93e-1f3fb", - "name": "person playing handball: light skin tone", - "alpha_code": ":person_playing_handball_tone1:", - "aliases": ":handball_tone1:" - }, - "1f64f-1f3fe": { - "output": "1f64f-1f3fe", - "name": "folded hands: medium-dark skin tone", - "alpha_code": ":pray_tone4:", - "aliases": "" - }, - "1f64f-1f3ff": { - "output": "1f64f-1f3ff", - "name": "folded hands: dark skin tone", - "alpha_code": ":pray_tone5:", - "aliases": "" - }, - "1f93e-1f3fc": { - "output": "1f93e-1f3fc", - "name": "person playing handball: medium-light skin tone", - "alpha_code": ":person_playing_handball_tone2:", - "aliases": ":handball_tone2:" - }, - "1f3c3-1f3fb": { - "output": "1f3c3-1f3fb", - "name": "person running: light skin tone", - "alpha_code": ":person_running_tone1:", - "aliases": ":runner_tone1:" - }, - "1f3c3-1f3fc": { - "output": "1f3c3-1f3fc", - "name": "person running: medium-light skin tone", - "alpha_code": ":person_running_tone2:", - "aliases": ":runner_tone2:" - }, - "1f3c3-1f3fd": { - "output": "1f3c3-1f3fd", - "name": "person running: medium skin tone", - "alpha_code": ":person_running_tone3:", - "aliases": ":runner_tone3:" - }, - "1f3c3-1f3fe": { - "output": "1f3c3-1f3fe", - "name": "person running: medium-dark skin tone", - "alpha_code": ":person_running_tone4:", - "aliases": ":runner_tone4:" - }, - "1f93e-1f3fd": { - "output": "1f93e-1f3fd", - "name": "person playing handball: medium skin tone", - "alpha_code": ":person_playing_handball_tone3:", - "aliases": ":handball_tone3:" - }, - "1f3c3-1f3ff": { - "output": "1f3c3-1f3ff", - "name": "person running: dark skin tone", - "alpha_code": ":person_running_tone5:", - "aliases": ":runner_tone5:" - }, - "1f6b6-1f3fb": { - "output": "1f6b6-1f3fb", - "name": "person walking: light skin tone", - "alpha_code": ":person_walking_tone1:", - "aliases": ":walking_tone1:" - }, - "1f6b6-1f3fc": { - "output": "1f6b6-1f3fc", - "name": "person walking: medium-light skin tone", - "alpha_code": ":person_walking_tone2:", - "aliases": ":walking_tone2:" - }, - "1f6b6-1f3fd": { - "output": "1f6b6-1f3fd", - "name": "person walking: medium skin tone", - "alpha_code": ":person_walking_tone3:", - "aliases": ":walking_tone3:" - }, - "1f6b6-1f3fe": { - "output": "1f6b6-1f3fe", - "name": "person walking: medium-dark skin tone", - "alpha_code": ":person_walking_tone4:", - "aliases": ":walking_tone4:" - }, - "1f6b6-1f3ff": { - "output": "1f6b6-1f3ff", - "name": "person walking: dark skin tone", - "alpha_code": ":person_walking_tone5:", - "aliases": ":walking_tone5:" - }, - "1f483-1f3fb": { - "output": "1f483-1f3fb", - "name": "woman dancing: light skin tone", - "alpha_code": ":dancer_tone1:", - "aliases": "" - }, - "1f93e-1f3fe": { - "output": "1f93e-1f3fe", - "name": "person playing handball: medium-dark skin tone", - "alpha_code": ":person_playing_handball_tone4:", - "aliases": ":handball_tone4:" - }, - "1f483-1f3fc": { - "output": "1f483-1f3fc", - "name": "woman dancing: medium-light skin tone", - "alpha_code": ":dancer_tone2:", - "aliases": "" - }, - "1f483-1f3fd": { - "output": "1f483-1f3fd", - "name": "woman dancing: medium skin tone", - "alpha_code": ":dancer_tone3:", - "aliases": "" - }, - "1f93e-1f3ff": { - "output": "1f93e-1f3ff", - "name": "person playing handball: dark skin tone", - "alpha_code": ":person_playing_handball_tone5:", - "aliases": ":handball_tone5:" - }, - "1f483-1f3fe": { - "output": "1f483-1f3fe", - "name": "woman dancing: medium-dark skin tone", - "alpha_code": ":dancer_tone4:", - "aliases": "" - }, - "1f483-1f3ff": { - "output": "1f483-1f3ff", - "name": "woman dancing: dark skin tone", - "alpha_code": ":dancer_tone5:", - "aliases": "" - }, - "1f939-1f3fb": { - "output": "1f939-1f3fb", - "name": "person juggling: light skin tone", - "alpha_code": ":person_juggling_tone1:", - "aliases": ":juggling_tone1:|:juggler_tone1:" - }, - "1f6a3-1f3fb": { - "output": "1f6a3-1f3fb", - "name": "person rowing boat: light skin tone", - "alpha_code": ":person_rowing_boat_tone1:", - "aliases": ":rowboat_tone1:" - }, - "1f6a3-1f3fc": { - "output": "1f6a3-1f3fc", - "name": "person rowing boat: medium-light skin tone", - "alpha_code": ":person_rowing_boat_tone2:", - "aliases": ":rowboat_tone2:" - }, - "1f6a3-1f3fd": { - "output": "1f6a3-1f3fd", - "name": "person rowing boat: medium skin tone", - "alpha_code": ":person_rowing_boat_tone3:", - "aliases": ":rowboat_tone3:" - }, - "1f6a3-1f3fe": { - "output": "1f6a3-1f3fe", - "name": "person rowing boat: medium-dark skin tone", - "alpha_code": ":person_rowing_boat_tone4:", - "aliases": ":rowboat_tone4:" - }, - "1f6a3-1f3ff": { - "output": "1f6a3-1f3ff", - "name": "person rowing boat: dark skin tone", - "alpha_code": ":person_rowing_boat_tone5:", - "aliases": ":rowboat_tone5:" - }, - "1f3ca-1f3fb": { - "output": "1f3ca-1f3fb", - "name": "person swimming: light skin tone", - "alpha_code": ":person_swimming_tone1:", - "aliases": ":swimmer_tone1:" - }, - "1f3ca-1f3fc": { - "output": "1f3ca-1f3fc", - "name": "person swimming: medium-light skin tone", - "alpha_code": ":person_swimming_tone2:", - "aliases": ":swimmer_tone2:" - }, - "1f939-1f3fc": { - "output": "1f939-1f3fc", - "name": "person juggling: medium-light skin tone", - "alpha_code": ":person_juggling_tone2:", - "aliases": ":juggling_tone2:|:juggler_tone2:" - }, - "1f3ca-1f3fd": { - "output": "1f3ca-1f3fd", - "name": "person swimming: medium skin tone", - "alpha_code": ":person_swimming_tone3:", - "aliases": ":swimmer_tone3:" - }, - "1f3ca-1f3fe": { - "output": "1f3ca-1f3fe", - "name": "person swimming: medium-dark skin tone", - "alpha_code": ":person_swimming_tone4:", - "aliases": ":swimmer_tone4:" - }, - "1f3ca-1f3ff": { - "output": "1f3ca-1f3ff", - "name": "person swimming: dark skin tone", - "alpha_code": ":person_swimming_tone5:", - "aliases": ":swimmer_tone5:" - }, - "1f939-1f3fd": { - "output": "1f939-1f3fd", - "name": "person juggling: medium skin tone", - "alpha_code": ":person_juggling_tone3:", - "aliases": ":juggling_tone3:|:juggler_tone3:" - }, - "1f3c4-1f3fb": { - "output": "1f3c4-1f3fb", - "name": "person surfing: light skin tone", - "alpha_code": ":person_surfing_tone1:", - "aliases": ":surfer_tone1:" - }, - "1f3c4-1f3fc": { - "output": "1f3c4-1f3fc", - "name": "person surfing: medium-light skin tone", - "alpha_code": ":person_surfing_tone2:", - "aliases": ":surfer_tone2:" - }, - "1f3c4-1f3fd": { - "output": "1f3c4-1f3fd", - "name": "person surfing: medium skin tone", - "alpha_code": ":person_surfing_tone3:", - "aliases": ":surfer_tone3:" - }, - "1f3c4-1f3fe": { - "output": "1f3c4-1f3fe", - "name": "person surfing: medium-dark skin tone", - "alpha_code": ":person_surfing_tone4:", - "aliases": ":surfer_tone4:" - }, - "1f3c4-1f3ff": { - "output": "1f3c4-1f3ff", - "name": "person surfing: dark skin tone", - "alpha_code": ":person_surfing_tone5:", - "aliases": ":surfer_tone5:" - }, - "1f6c0-1f3fb": { - "output": "1f6c0-1f3fb", - "name": "person taking bath: light skin tone", - "alpha_code": ":bath_tone1:", - "aliases": "" - }, - "1f6c0-1f3fc": { - "output": "1f6c0-1f3fc", - "name": "person taking bath: medium-light skin tone", - "alpha_code": ":bath_tone2:", - "aliases": "" - }, - "1f939-1f3fe": { - "output": "1f939-1f3fe", - "name": "person juggling: medium-dark skin tone", - "alpha_code": ":person_juggling_tone4:", - "aliases": ":juggling_tone4:|:juggler_tone4:" - }, - "1f6c0-1f3fd": { - "output": "1f6c0-1f3fd", - "name": "person taking bath: medium skin tone", - "alpha_code": ":bath_tone3:", - "aliases": "" - }, - "1f6c0-1f3fe": { - "output": "1f6c0-1f3fe", - "name": "person taking bath: medium-dark skin tone", - "alpha_code": ":bath_tone4:", - "aliases": "" - }, - "1f6c0-1f3ff": { - "output": "1f6c0-1f3ff", - "name": "person taking bath: dark skin tone", - "alpha_code": ":bath_tone5:", - "aliases": "" - }, - "1f939-1f3ff": { - "output": "1f939-1f3ff", - "name": "person juggling: dark skin tone", - "alpha_code": ":person_juggling_tone5:", - "aliases": ":juggling_tone5:|:juggler_tone5:" - }, - "1f6b4-1f3fb": { - "output": "1f6b4-1f3fb", - "name": "person biking: light skin tone", - "alpha_code": ":person_biking_tone1:", - "aliases": ":bicyclist_tone1:" - }, - "1f6b4-1f3fc": { - "output": "1f6b4-1f3fc", - "name": "person biking: medium-light skin tone", - "alpha_code": ":person_biking_tone2:", - "aliases": ":bicyclist_tone2:" - }, - "1f6b4-1f3fd": { - "output": "1f6b4-1f3fd", - "name": "person biking: medium skin tone", - "alpha_code": ":person_biking_tone3:", - "aliases": ":bicyclist_tone3:" - }, - "1f3f3-1f308": { - "output": "1f3f3-fe0f-200d-1f308", - "name": "rainbow flag", - "alpha_code": ":rainbow_flag:", - "aliases": ":gay_pride_flag:" - }, - "1f6b4-1f3fe": { - "output": "1f6b4-1f3fe", - "name": "person biking: medium-dark skin tone", - "alpha_code": ":person_biking_tone4:", - "aliases": ":bicyclist_tone4:" - }, - "1f6b4-1f3ff": { - "output": "1f6b4-1f3ff", - "name": "person biking: dark skin tone", - "alpha_code": ":person_biking_tone5:", - "aliases": ":bicyclist_tone5:" - }, - "1f6b5-1f3fb": { - "output": "1f6b5-1f3fb", - "name": "person mountain biking: light skin tone", - "alpha_code": ":person_mountain_biking_tone1:", - "aliases": ":mountain_bicyclist_tone1:" - }, - "1f6b5-1f3fc": { - "output": "1f6b5-1f3fc", - "name": "person mountain biking: medium-light skin tone", - "alpha_code": ":person_mountain_biking_tone2:", - "aliases": ":mountain_bicyclist_tone2:" - }, - "1f6b5-1f3fd": { - "output": "1f6b5-1f3fd", - "name": "person mountain biking: medium skin tone", - "alpha_code": ":person_mountain_biking_tone3:", - "aliases": ":mountain_bicyclist_tone3:" - }, - "1f6b5-1f3fe": { - "output": "1f6b5-1f3fe", - "name": "person mountain biking: medium-dark skin tone", - "alpha_code": ":person_mountain_biking_tone4:", - "aliases": ":mountain_bicyclist_tone4:" - }, - "1f6b5-1f3ff": { - "output": "1f6b5-1f3ff", - "name": "person mountain biking: dark skin tone", - "alpha_code": ":person_mountain_biking_tone5:", - "aliases": ":mountain_bicyclist_tone5:" - }, - "1f3c7-1f3fb": { - "output": "1f3c7-1f3fb", - "name": "horse racing: light skin tone", - "alpha_code": ":horse_racing_tone1:", - "aliases": "" - }, - "1f3c7-1f3fc": { - "output": "1f3c7-1f3fc", - "name": "horse racing: medium-light skin tone", - "alpha_code": ":horse_racing_tone2:", - "aliases": "" - }, - "1f3c7-1f3fd": { - "output": "1f3c7-1f3fd", - "name": "horse racing: medium skin tone", - "alpha_code": ":horse_racing_tone3:", - "aliases": "" - }, - "1f3c7-1f3fe": { - "output": "1f3c7-1f3fe", - "name": "horse racing: medium-dark skin tone", - "alpha_code": ":horse_racing_tone4:", - "aliases": "" - }, - "1f3c7-1f3ff": { - "output": "1f3c7-1f3ff", - "name": "horse racing: dark skin tone", - "alpha_code": ":horse_racing_tone5:", - "aliases": "" - }, - "270d-1f3fb": { - "output": "270d-1f3fb", - "name": "writing hand: light skin tone", - "alpha_code": ":writing_hand_tone1:", - "aliases": "" - }, - "270d-1f3fc": { - "output": "270d-1f3fc", - "name": "writing hand: medium-light skin tone", - "alpha_code": ":writing_hand_tone2:", - "aliases": "" - }, - "270d-1f3fd": { - "output": "270d-1f3fd", - "name": "writing hand: medium skin tone", - "alpha_code": ":writing_hand_tone3:", - "aliases": "" - }, - "270d-1f3fe": { - "output": "270d-1f3fe", - "name": "writing hand: medium-dark skin tone", - "alpha_code": ":writing_hand_tone4:", - "aliases": "" - }, - "270d-1f3ff": { - "output": "270d-1f3ff", - "name": "writing hand: dark skin tone", - "alpha_code": ":writing_hand_tone5:", - "aliases": "" - }, - "1f590-1f3fb": { - "output": "1f590-1f3fb", - "name": "raised hand with fingers splayed: light skin tone", - "alpha_code": ":hand_splayed_tone1:", - "aliases": ":raised_hand_with_fingers_splayed_tone1:" - }, - "1f590-1f3fc": { - "output": "1f590-1f3fc", - "name": "raised hand with fingers splayed: medium-light skin tone", - "alpha_code": ":hand_splayed_tone2:", - "aliases": ":raised_hand_with_fingers_splayed_tone2:" - }, - "1f590-1f3fd": { - "output": "1f590-1f3fd", - "name": "raised hand with fingers splayed: medium skin tone", - "alpha_code": ":hand_splayed_tone3:", - "aliases": ":raised_hand_with_fingers_splayed_tone3:" - }, - "1f590-1f3fe": { - "output": "1f590-1f3fe", - "name": "raised hand with fingers splayed: medium-dark skin tone", - "alpha_code": ":hand_splayed_tone4:", - "aliases": ":raised_hand_with_fingers_splayed_tone4:" - }, - "1f590-1f3ff": { - "output": "1f590-1f3ff", - "name": "raised hand with fingers splayed: dark skin tone", - "alpha_code": ":hand_splayed_tone5:", - "aliases": ":raised_hand_with_fingers_splayed_tone5:" - }, - "1f595-1f3fb": { - "output": "1f595-1f3fb", - "name": "middle finger: light skin tone", - "alpha_code": ":middle_finger_tone1:", - "aliases": ":reversed_hand_with_middle_finger_extended_tone1:" - }, - "1f595-1f3fc": { - "output": "1f595-1f3fc", - "name": "middle finger: medium-light skin tone", - "alpha_code": ":middle_finger_tone2:", - "aliases": ":reversed_hand_with_middle_finger_extended_tone2:" - }, - "1f595-1f3fd": { - "output": "1f595-1f3fd", - "name": "middle finger: medium skin tone", - "alpha_code": ":middle_finger_tone3:", - "aliases": ":reversed_hand_with_middle_finger_extended_tone3:" - }, - "1f595-1f3fe": { - "output": "1f595-1f3fe", - "name": "middle finger: medium-dark skin tone", - "alpha_code": ":middle_finger_tone4:", - "aliases": ":reversed_hand_with_middle_finger_extended_tone4:" - }, - "1f595-1f3ff": { - "output": "1f595-1f3ff", - "name": "middle finger: dark skin tone", - "alpha_code": ":middle_finger_tone5:", - "aliases": ":reversed_hand_with_middle_finger_extended_tone5:" - }, - "1f596-1f3fb": { - "output": "1f596-1f3fb", - "name": "vulcan salute: light skin tone", - "alpha_code": ":vulcan_tone1:", - "aliases": ":raised_hand_with_part_between_middle_and_ring_fingers_tone1:" - }, - "1f596-1f3fc": { - "output": "1f596-1f3fc", - "name": "vulcan salute: medium-light skin tone", - "alpha_code": ":vulcan_tone2:", - "aliases": ":raised_hand_with_part_between_middle_and_ring_fingers_tone2:" - }, - "1f596-1f3fd": { - "output": "1f596-1f3fd", - "name": "vulcan salute: medium skin tone", - "alpha_code": ":vulcan_tone3:", - "aliases": ":raised_hand_with_part_between_middle_and_ring_fingers_tone3:" - }, - "1f596-1f3fe": { - "output": "1f596-1f3fe", - "name": "vulcan salute: medium-dark skin tone", - "alpha_code": ":vulcan_tone4:", - "aliases": ":raised_hand_with_part_between_middle_and_ring_fingers_tone4:" - }, - "1f596-1f3ff": { - "output": "1f596-1f3ff", - "name": "vulcan salute: dark skin tone", - "alpha_code": ":vulcan_tone5:", - "aliases": ":raised_hand_with_part_between_middle_and_ring_fingers_tone5:" - }, - "1f468-1f468-1f466": { - "output": "1f468-200d-1f468-200d-1f466", - "name": "family: man, man, boy", - "alpha_code": ":family_mmb:", - "aliases": "" - }, - "1f468-1f468-1f466-1f466": { - "output": "1f468-200d-1f468-200d-1f466-200d-1f466", - "name": "family: man, man, boy, boy", - "alpha_code": ":family_mmbb:", - "aliases": "" - }, - "1f468-1f468-1f467": { - "output": "1f468-200d-1f468-200d-1f467", - "name": "family: man, man, girl", - "alpha_code": ":family_mmg:", - "aliases": "" - }, - "1f468-1f468-1f467-1f466": { - "output": "1f468-200d-1f468-200d-1f467-200d-1f466", - "name": "family: man, man, girl, boy", - "alpha_code": ":family_mmgb:", - "aliases": "" - }, - "1f468-1f468-1f467-1f467": { - "output": "1f468-200d-1f468-200d-1f467-200d-1f467", - "name": "family: man, man, girl, girl", - "alpha_code": ":family_mmgg:", - "aliases": "" - }, - "1f468-1f469-1f466-1f466": { - "output": "1f468-200d-1f469-200d-1f466-200d-1f466", - "name": "family: man, woman, boy, boy", - "alpha_code": ":family_mwbb:", - "aliases": "" - }, - "1f468-1f469-1f467": { - "output": "1f468-200d-1f469-200d-1f467", - "name": "family: man, woman, girl", - "alpha_code": ":family_mwg:", - "aliases": "" - }, - "1f468-1f469-1f467-1f466": { - "output": "1f468-200d-1f469-200d-1f467-200d-1f466", - "name": "family: man, woman, girl, boy", - "alpha_code": ":family_mwgb:", - "aliases": "" - }, - "1f468-1f469-1f467-1f467": { - "output": "1f468-200d-1f469-200d-1f467-200d-1f467", - "name": "family: man, woman, girl, girl", - "alpha_code": ":family_mwgg:", - "aliases": "" - }, - "1f469-1f469-1f466": { - "output": "1f469-200d-1f469-200d-1f466", - "name": "family: woman, woman, boy", - "alpha_code": ":family_wwb:", - "aliases": "" - }, - "1f469-1f469-1f466-1f466": { - "output": "1f469-200d-1f469-200d-1f466-200d-1f466", - "name": "family: woman, woman, boy, boy", - "alpha_code": ":family_wwbb:", - "aliases": "" - }, - "1f469-1f469-1f467": { - "output": "1f469-200d-1f469-200d-1f467", - "name": "family: woman, woman, girl", - "alpha_code": ":family_wwg:", - "aliases": "" - }, - "1f469-1f469-1f467-1f466": { - "output": "1f469-200d-1f469-200d-1f467-200d-1f466", - "name": "family: woman, woman, girl, boy", - "alpha_code": ":family_wwgb:", - "aliases": "" - }, - "1f469-1f469-1f467-1f467": { - "output": "1f469-200d-1f469-200d-1f467-200d-1f467", - "name": "family: woman, woman, girl, girl", - "alpha_code": ":family_wwgg:", - "aliases": "" - }, - "1f469-2764-1f469": { - "output": "1f469-200d-2764-fe0f-200d-1f469", - "name": "couple with heart: woman, woman", - "alpha_code": ":couple_ww:", - "aliases": ":couple_with_heart_ww:" - }, - "1f468-2764-1f468": { - "output": "1f468-200d-2764-fe0f-200d-1f468", - "name": "couple with heart: man, man", - "alpha_code": ":couple_mm:", - "aliases": ":couple_with_heart_mm:" - }, - "1f469-2764-1f48b-1f469": { - "output": "1f469-200d-2764-fe0f-200d-1f48b-200d-1f469", - "name": "kiss: woman, woman", - "alpha_code": ":kiss_ww:", - "aliases": ":couplekiss_ww:" - }, - "1f468-2764-1f48b-1f468": { - "output": "1f468-200d-2764-fe0f-200d-1f48b-200d-1f468", - "name": "kiss: man, man", - "alpha_code": ":kiss_mm:", - "aliases": ":couplekiss_mm:" - }, - "1f3fb": { - "output": "1f3fb", - "name": "light skin tone", - "alpha_code": ":tone1:", - "aliases": "" - }, - "1f3fc": { - "output": "1f3fc", - "name": "medium-light skin tone", - "alpha_code": ":tone2:", - "aliases": "" - }, - "1f3fd": { - "output": "1f3fd", - "name": "medium skin tone", - "alpha_code": ":tone3:", - "aliases": "" - }, - "1f3fe": { - "output": "1f3fe", - "name": "medium-dark skin tone", - "alpha_code": ":tone4:", - "aliases": "" - }, - "1f3ff": { - "output": "1f3ff", - "name": "dark skin tone", - "alpha_code": ":tone5:", - "aliases": "" - }, - "002a-20e3": { - "output": "002a-fe0f-20e3", - "name": "keycap: *", - "alpha_code": ":asterisk:", - "aliases": ":keycap_asterisk:" - }, - "23cf": { - "output": "23cf-fe0f", - "name": "eject button", - "alpha_code": ":eject:", - "aliases": ":eject_symbol:" - }, - "23ed": { - "output": "23ed-fe0f", - "name": "next track button", - "alpha_code": ":track_next:", - "aliases": ":next_track:" - }, - "23ee": { - "output": "23ee-fe0f", - "name": "last track button", - "alpha_code": ":track_previous:", - "aliases": ":previous_track:" - }, - "23ef": { - "output": "23ef-fe0f", - "name": "play or pause button", - "alpha_code": ":play_pause:", - "aliases": "" - }, - "1f441-1f5e8": { - "output": "1f441-fe0f-200d-1f5e8-fe0f", - "name": "eye in speech bubble", - "alpha_code": ":eye_in_speech_bubble:", - "aliases": "" - }, - "23f1": { - "output": "23f1-fe0f", - "name": "stopwatch", - "alpha_code": ":stopwatch:", - "aliases": "" - }, - "23f2": { - "output": "23f2-fe0f", - "name": "timer clock", - "alpha_code": ":timer:", - "aliases": ":timer_clock:" - }, - "23f8": { - "output": "23f8-fe0f", - "name": "pause button", - "alpha_code": ":pause_button:", - "aliases": ":double_vertical_bar:" - }, - "23f9": { - "output": "23f9-fe0f", - "name": "stop button", - "alpha_code": ":stop_button:", - "aliases": "" - }, - "23fa": { - "output": "23fa-fe0f", - "name": "record button", - "alpha_code": ":record_button:", - "aliases": "" - }, - "2602": { - "output": "2602-fe0f", - "name": "umbrella", - "alpha_code": ":umbrella2:", - "aliases": "" - }, - "2603": { - "output": "2603-fe0f", - "name": "snowman", - "alpha_code": ":snowman2:", - "aliases": "" - }, - "2604": { - "output": "2604-fe0f", - "name": "comet", - "alpha_code": ":comet:", - "aliases": "" - }, - "2618": { - "output": "2618-fe0f", - "name": "shamrock", - "alpha_code": ":shamrock:", - "aliases": "" - }, - "2620": { - "output": "2620-fe0f", - "name": "skull and crossbones", - "alpha_code": ":skull_crossbones:", - "aliases": ":skull_and_crossbones:" - }, - "2622": { - "output": "2622-fe0f", - "name": "radioactive", - "alpha_code": ":radioactive:", - "aliases": ":radioactive_sign:" - }, - "2623": { - "output": "2623-fe0f", - "name": "biohazard", - "alpha_code": ":biohazard:", - "aliases": ":biohazard_sign:" - }, - "2626": { - "output": "2626-fe0f", - "name": "orthodox cross", - "alpha_code": ":orthodox_cross:", - "aliases": "" - }, - "262a": { - "output": "262a-fe0f", - "name": "star and crescent", - "alpha_code": ":star_and_crescent:", - "aliases": "" - }, - "262e": { - "output": "262e-fe0f", - "name": "peace symbol", - "alpha_code": ":peace:", - "aliases": ":peace_symbol:" - }, - "262f": { - "output": "262f-fe0f", - "name": "yin yang", - "alpha_code": ":yin_yang:", - "aliases": "" - }, - "2638": { - "output": "2638-fe0f", - "name": "wheel of dharma", - "alpha_code": ":wheel_of_dharma:", - "aliases": "" - }, - "2639": { - "output": "2639-fe0f", - "name": "frowning face", - "alpha_code": ":frowning2:", - "aliases": ":white_frowning_face:" - }, - "2692": { - "output": "2692-fe0f", - "name": "hammer and pick", - "alpha_code": ":hammer_pick:", - "aliases": ":hammer_and_pick:" - }, - "2694": { - "output": "2694-fe0f", - "name": "crossed swords", - "alpha_code": ":crossed_swords:", - "aliases": "" - }, - "2696": { - "output": "2696-fe0f", - "name": "balance scale", - "alpha_code": ":scales:", - "aliases": "" - }, - "2697": { - "output": "2697-fe0f", - "name": "alembic", - "alpha_code": ":alembic:", - "aliases": "" - }, - "2699": { - "output": "2699-fe0f", - "name": "gear", - "alpha_code": ":gear:", - "aliases": "" - }, - "269b": { - "output": "269b-fe0f", - "name": "atom symbol", - "alpha_code": ":atom:", - "aliases": ":atom_symbol:" - }, - "269c": { - "output": "269c-fe0f", - "name": "fleur-de-lis", - "alpha_code": ":fleur-de-lis:", - "aliases": "" - }, - "26b0": { - "output": "26b0-fe0f", - "name": "coffin", - "alpha_code": ":coffin:", - "aliases": "" - }, - "26b1": { - "output": "26b1-fe0f", - "name": "funeral urn", - "alpha_code": ":urn:", - "aliases": ":funeral_urn:" - }, - "26c8": { - "output": "26c8-fe0f", - "name": "cloud with lightning and rain", - "alpha_code": ":thunder_cloud_rain:", - "aliases": ":thunder_cloud_and_rain:" - }, - "26cf": { - "output": "26cf-fe0f", - "name": "pick", - "alpha_code": ":pick:", - "aliases": "" - }, - "26d1": { - "output": "26d1-fe0f", - "name": "rescue worker\u2019s helmet", - "alpha_code": ":helmet_with_cross:", - "aliases": ":helmet_with_white_cross:" - }, - "26d3": { - "output": "26d3-fe0f", - "name": "chains", - "alpha_code": ":chains:", - "aliases": "" - }, - "26e9": { - "output": "26e9-fe0f", - "name": "shinto shrine", - "alpha_code": ":shinto_shrine:", - "aliases": "" - }, - "26f0": { - "output": "26f0-fe0f", - "name": "mountain", - "alpha_code": ":mountain:", - "aliases": "" - }, - "26f1": { - "output": "26f1-fe0f", - "name": "umbrella on ground", - "alpha_code": ":beach_umbrella:", - "aliases": ":umbrella_on_ground:" - }, - "26f4": { - "output": "26f4-fe0f", - "name": "ferry", - "alpha_code": ":ferry:", - "aliases": "" - }, - "26f7": { - "output": "26f7-fe0f", - "name": "skier", - "alpha_code": ":skier:", - "aliases": "" - }, - "26f8": { - "output": "26f8-fe0f", - "name": "ice skate", - "alpha_code": ":ice_skate:", - "aliases": "" - }, - "26f9": { - "output": "26f9-fe0f", - "name": "person bouncing ball", - "alpha_code": ":person_bouncing_ball:", - "aliases": ":basketball_player:|:person_with_ball:" - }, - "2721": { - "output": "2721-fe0f", - "name": "star of David", - "alpha_code": ":star_of_david:", - "aliases": "" - }, - "2763": { - "output": "2763-fe0f", - "name": "heavy heart exclamation", - "alpha_code": ":heart_exclamation:", - "aliases": ":heavy_heart_exclamation_mark_ornament:" - }, - "1f324": { - "output": "1f324-fe0f", - "name": "sun behind small cloud", - "alpha_code": ":white_sun_small_cloud:", - "aliases": ":white_sun_with_small_cloud:" - }, - "1f325": { - "output": "1f325-fe0f", - "name": "sun behind large cloud", - "alpha_code": ":white_sun_cloud:", - "aliases": ":white_sun_behind_cloud:" - }, - "1f326": { - "output": "1f326-fe0f", - "name": "sun behind rain cloud", - "alpha_code": ":white_sun_rain_cloud:", - "aliases": ":white_sun_behind_cloud_with_rain:" - }, - "1f5b1": { - "output": "1f5b1-fe0f", - "name": "computer mouse", - "alpha_code": ":mouse_three_button:", - "aliases": ":three_button_mouse:" - }, - "1f385-1f3fb": { - "output": "1f385-1f3fb", - "name": "Santa Claus: light skin tone", - "alpha_code": ":santa_tone1:", - "aliases": "" - }, - "1f385-1f3fc": { - "output": "1f385-1f3fc", - "name": "Santa Claus: medium-light skin tone", - "alpha_code": ":santa_tone2:", - "aliases": "" - }, - "1f385-1f3fd": { - "output": "1f385-1f3fd", - "name": "Santa Claus: medium skin tone", - "alpha_code": ":santa_tone3:", - "aliases": "" - }, - "1f385-1f3fe": { - "output": "1f385-1f3fe", - "name": "Santa Claus: medium-dark skin tone", - "alpha_code": ":santa_tone4:", - "aliases": "" - }, - "1f385-1f3ff": { - "output": "1f385-1f3ff", - "name": "Santa Claus: dark skin tone", - "alpha_code": ":santa_tone5:", - "aliases": "" - }, - "1f918-1f3fb": { - "output": "1f918-1f3fb", - "name": "sign of the horns: light skin tone", - "alpha_code": ":metal_tone1:", - "aliases": ":sign_of_the_horns_tone1:" - }, - "1f918-1f3fc": { - "output": "1f918-1f3fc", - "name": "sign of the horns: medium-light skin tone", - "alpha_code": ":metal_tone2:", - "aliases": ":sign_of_the_horns_tone2:" - }, - "1f918-1f3fd": { - "output": "1f918-1f3fd", - "name": "sign of the horns: medium skin tone", - "alpha_code": ":metal_tone3:", - "aliases": ":sign_of_the_horns_tone3:" - }, - "1f918-1f3fe": { - "output": "1f918-1f3fe", - "name": "sign of the horns: medium-dark skin tone", - "alpha_code": ":metal_tone4:", - "aliases": ":sign_of_the_horns_tone4:" - }, - "1f918-1f3ff": { - "output": "1f918-1f3ff", - "name": "sign of the horns: dark skin tone", - "alpha_code": ":metal_tone5:", - "aliases": ":sign_of_the_horns_tone5:" - }, - "1f3cb-1f3fb": { - "output": "1f3cb-1f3fb", - "name": "person lifting weights: light skin tone", - "alpha_code": ":person_lifting_weights_tone1:", - "aliases": ":lifter_tone1:|:weight_lifter_tone1:" - }, - "1f3cb-1f3fc": { - "output": "1f3cb-1f3fc", - "name": "person lifting weights: medium-light skin tone", - "alpha_code": ":person_lifting_weights_tone2:", - "aliases": ":lifter_tone2:|:weight_lifter_tone2:" - }, - "1f3cb-1f3fd": { - "output": "1f3cb-1f3fd", - "name": "person lifting weights: medium skin tone", - "alpha_code": ":person_lifting_weights_tone3:", - "aliases": ":lifter_tone3:|:weight_lifter_tone3:" - }, - "1f3cb-1f3fe": { - "output": "1f3cb-1f3fe", - "name": "person lifting weights: medium-dark skin tone", - "alpha_code": ":person_lifting_weights_tone4:", - "aliases": ":lifter_tone4:|:weight_lifter_tone4:" - }, - "1f3cb-1f3ff": { - "output": "1f3cb-1f3ff", - "name": "person lifting weights: dark skin tone", - "alpha_code": ":person_lifting_weights_tone5:", - "aliases": ":lifter_tone5:|:weight_lifter_tone5:" - }, - "26f9-1f3fb": { - "output": "26f9-1f3fb", - "name": "person bouncing ball: light skin tone", - "alpha_code": ":person_bouncing_ball_tone1:", - "aliases": ":basketball_player_tone1:|:person_with_ball_tone1:" - }, - "26f9-1f3fc": { - "output": "26f9-1f3fc", - "name": "person bouncing ball: medium-light skin tone", - "alpha_code": ":person_bouncing_ball_tone2:", - "aliases": ":basketball_player_tone2:|:person_with_ball_tone2:" - }, - "26f9-1f3fd": { - "output": "26f9-1f3fd", - "name": "person bouncing ball: medium skin tone", - "alpha_code": ":person_bouncing_ball_tone3:", - "aliases": ":basketball_player_tone3:|:person_with_ball_tone3:" - }, - "26f9-1f3fe": { - "output": "26f9-1f3fe", - "name": "person bouncing ball: medium-dark skin tone", - "alpha_code": ":person_bouncing_ball_tone4:", - "aliases": ":basketball_player_tone4:|:person_with_ball_tone4:" - }, - "26f9-1f3ff": { - "output": "26f9-1f3ff", - "name": "person bouncing ball: dark skin tone", - "alpha_code": ":person_bouncing_ball_tone5:", - "aliases": ":basketball_player_tone5:|:person_with_ball_tone5:" - }, - "1f643": { - "output": "1f643", - "name": "upside-down face", - "alpha_code": ":upside_down:", - "aliases": ":upside_down_face:" - }, - "1f911": { - "output": "1f911", - "name": "money-mouth face", - "alpha_code": ":money_mouth:", - "aliases": ":money_mouth_face:" - }, - "1f913": { - "output": "1f913", - "name": "nerd face", - "alpha_code": ":nerd:", - "aliases": ":nerd_face:" - }, - "1f917": { - "output": "1f917", - "name": "hugging face", - "alpha_code": ":hugging:", - "aliases": ":hugging_face:" - }, - "1f644": { - "output": "1f644", - "name": "face with rolling eyes", - "alpha_code": ":rolling_eyes:", - "aliases": ":face_with_rolling_eyes:" - }, - "1f914": { - "output": "1f914", - "name": "thinking face", - "alpha_code": ":thinking:", - "aliases": ":thinking_face:" - }, - "1f910": { - "output": "1f910", - "name": "zipper-mouth face", - "alpha_code": ":zipper_mouth:", - "aliases": ":zipper_mouth_face:" - }, - "1f912": { - "output": "1f912", - "name": "face with thermometer", - "alpha_code": ":thermometer_face:", - "aliases": ":face_with_thermometer:" - }, - "1f915": { - "output": "1f915", - "name": "face with head-bandage", - "alpha_code": ":head_bandage:", - "aliases": ":face_with_head_bandage:" - }, - "1f916": { - "output": "1f916", - "name": "robot face", - "alpha_code": ":robot:", - "aliases": ":robot_face:" - }, - "1f981": { - "output": "1f981", - "name": "lion face", - "alpha_code": ":lion_face:", - "aliases": ":lion:" - }, - "1f984": { - "output": "1f984", - "name": "unicorn face", - "alpha_code": ":unicorn:", - "aliases": ":unicorn_face:" - }, - "1f982": { - "output": "1f982", - "name": "scorpion", - "alpha_code": ":scorpion:", - "aliases": "" - }, - "1f980": { - "output": "1f980", - "name": "crab", - "alpha_code": ":crab:", - "aliases": "" - }, - "1f983": { - "output": "1f983", - "name": "turkey", - "alpha_code": ":turkey:", - "aliases": "" - }, - "1f9c0": { - "output": "1f9c0", - "name": "cheese wedge", - "alpha_code": ":cheese:", - "aliases": ":cheese_wedge:" - }, - "1f32d": { - "output": "1f32d", - "name": "hot dog", - "alpha_code": ":hotdog:", - "aliases": ":hot_dog:" - }, - "1f32e": { - "output": "1f32e", - "name": "taco", - "alpha_code": ":taco:", - "aliases": "" - }, - "1f32f": { - "output": "1f32f", - "name": "burrito", - "alpha_code": ":burrito:", - "aliases": "" - }, - "1f37f": { - "output": "1f37f", - "name": "popcorn", - "alpha_code": ":popcorn:", - "aliases": "" - }, - "1f37e": { - "output": "1f37e", - "name": "bottle with popping cork", - "alpha_code": ":champagne:", - "aliases": ":bottle_with_popping_cork:" - }, - "1f3f9": { - "output": "1f3f9", - "name": "bow and arrow", - "alpha_code": ":bow_and_arrow:", - "aliases": ":archery:" - }, - "1f3fa": { - "output": "1f3fa", - "name": "amphora", - "alpha_code": ":amphora:", - "aliases": "" - }, - "1f6d0": { - "output": "1f6d0", - "name": "place of worship", - "alpha_code": ":place_of_worship:", - "aliases": ":worship_symbol:" - }, - "1f54b": { - "output": "1f54b", - "name": "kaaba", - "alpha_code": ":kaaba:", - "aliases": "" - }, - "1f54c": { - "output": "1f54c", - "name": "mosque", - "alpha_code": ":mosque:", - "aliases": "" - }, - "1f54d": { - "output": "1f54d", - "name": "synagogue", - "alpha_code": ":synagogue:", - "aliases": "" - }, - "1f54e": { - "output": "1f54e", - "name": "menorah", - "alpha_code": ":menorah:", - "aliases": "" - }, - "1f4ff": { - "output": "1f4ff", - "name": "prayer beads", - "alpha_code": ":prayer_beads:", - "aliases": "" - }, - "1f3cf": { - "output": "1f3cf", - "name": "cricket game", - "alpha_code": ":cricket_game:", - "aliases": ":cricket_bat_ball:" - }, - "1f3d0": { - "output": "1f3d0", - "name": "volleyball", - "alpha_code": ":volleyball:", - "aliases": "" - }, - "1f3d1": { - "output": "1f3d1", - "name": "field hockey", - "alpha_code": ":field_hockey:", - "aliases": "" - }, - "1f3d2": { - "output": "1f3d2", - "name": "ice hockey", - "alpha_code": ":hockey:", - "aliases": "" - }, - "1f3d3": { - "output": "1f3d3", - "name": "ping pong", - "alpha_code": ":ping_pong:", - "aliases": ":table_tennis:" - }, - "1f3f8": { - "output": "1f3f8", - "name": "badminton", - "alpha_code": ":badminton:", - "aliases": "" - }, - "1f1e6-1f1fd": { - "output": "1f1e6-1f1fd", - "name": "\u00c5land Islands", - "alpha_code": ":flag_ax:", - "aliases": ":ax:" - }, - "1f1f9-1f1e6": { - "output": "1f1f9-1f1e6", - "name": "Tristan da Cunha", - "alpha_code": ":flag_ta:", - "aliases": ":ta:" - }, - "1f1ee-1f1f4": { - "output": "1f1ee-1f1f4", - "name": "British Indian Ocean Territory", - "alpha_code": ":flag_io:", - "aliases": ":io:" - }, - "1f1e7-1f1f6": { - "output": "1f1e7-1f1f6", - "name": "Caribbean Netherlands", - "alpha_code": ":flag_bq:", - "aliases": ":bq:" - }, - "1f1e8-1f1fd": { - "output": "1f1e8-1f1fd", - "name": "Christmas Island", - "alpha_code": ":flag_cx:", - "aliases": ":cx:" - }, - "1f1e8-1f1e8": { - "output": "1f1e8-1f1e8", - "name": "Cocos (Keeling) Islands", - "alpha_code": ":flag_cc:", - "aliases": ":cc:" - }, - "1f1ec-1f1ec": { - "output": "1f1ec-1f1ec", - "name": "Guernsey", - "alpha_code": ":flag_gg:", - "aliases": ":gg:" - }, - "1f1ee-1f1f2": { - "output": "1f1ee-1f1f2", - "name": "Isle of Man", - "alpha_code": ":flag_im:", - "aliases": ":im:" - }, - "1f1fe-1f1f9": { - "output": "1f1fe-1f1f9", - "name": "Mayotte", - "alpha_code": ":flag_yt:", - "aliases": ":yt:" - }, - "1f1f3-1f1eb": { - "output": "1f1f3-1f1eb", - "name": "Norfolk Island", - "alpha_code": ":flag_nf:", - "aliases": ":nf:" - }, - "1f1f5-1f1f3": { - "output": "1f1f5-1f1f3", - "name": "Pitcairn Islands", - "alpha_code": ":flag_pn:", - "aliases": ":pn:" - }, - "1f1e7-1f1f1": { - "output": "1f1e7-1f1f1", - "name": "St. Barth\u00e9lemy", - "alpha_code": ":flag_bl:", - "aliases": ":bl:" - }, - "1f1f5-1f1f2": { - "output": "1f1f5-1f1f2", - "name": "St. Pierre & Miquelon", - "alpha_code": ":flag_pm:", - "aliases": ":pm:" - }, - "1f1ec-1f1f8": { - "output": "1f1ec-1f1f8", - "name": "South Georgia & South Sandwich Islands", - "alpha_code": ":flag_gs:", - "aliases": ":gs:" - }, - "1f1f9-1f1f0": { - "output": "1f1f9-1f1f0", - "name": "Tokelau", - "alpha_code": ":flag_tk:", - "aliases": ":tk:" - }, - "1f1e7-1f1fb": { - "output": "1f1e7-1f1fb", - "name": "Bouvet Island", - "alpha_code": ":flag_bv:", - "aliases": ":bv:" - }, - "1f1ed-1f1f2": { - "output": "1f1ed-1f1f2", - "name": "Heard & McDonald Islands", - "alpha_code": ":flag_hm:", - "aliases": ":hm:" - }, - "1f1f8-1f1ef": { - "output": "1f1f8-1f1ef", - "name": "Svalbard & Jan Mayen", - "alpha_code": ":flag_sj:", - "aliases": ":sj:" - }, - "1f1fa-1f1f2": { - "output": "1f1fa-1f1f2", - "name": "U.S. Outlying Islands", - "alpha_code": ":flag_um:", - "aliases": ":um:" - }, - "1f1ee-1f1e8": { - "output": "1f1ee-1f1e8", - "name": "Canary Islands", - "alpha_code": ":flag_ic:", - "aliases": ":ic:" - }, - "1f1ea-1f1e6": { - "output": "1f1ea-1f1e6", - "name": "Ceuta & Melilla", - "alpha_code": ":flag_ea:", - "aliases": ":ea:" - }, - "1f1e8-1f1f5": { - "output": "1f1e8-1f1f5", - "name": "Clipperton Island", - "alpha_code": ":flag_cp:", - "aliases": ":cp:" - }, - "1f1e9-1f1ec": { - "output": "1f1e9-1f1ec", - "name": "Diego Garcia", - "alpha_code": ":flag_dg:", - "aliases": ":dg:" - }, - "1f1e6-1f1f8": { - "output": "1f1e6-1f1f8", - "name": "American Samoa", - "alpha_code": ":flag_as:", - "aliases": ":as:" - }, - "1f1e6-1f1f6": { - "output": "1f1e6-1f1f6", - "name": "Antarctica", - "alpha_code": ":flag_aq:", - "aliases": ":aq:" - }, - "1f1fb-1f1ec": { - "output": "1f1fb-1f1ec", - "name": "British Virgin Islands", - "alpha_code": ":flag_vg:", - "aliases": ":vg:" - }, - "1f1e8-1f1f0": { - "output": "1f1e8-1f1f0", - "name": "Cook Islands", - "alpha_code": ":flag_ck:", - "aliases": ":ck:" - }, - "1f1e8-1f1fc": { - "output": "1f1e8-1f1fc", - "name": "Cura\u00e7ao", - "alpha_code": ":flag_cw:", - "aliases": ":cw:" - }, - "1f1ea-1f1fa": { - "output": "1f1ea-1f1fa", - "name": "European Union", - "alpha_code": ":flag_eu:", - "aliases": ":eu:" - }, - "1f1ec-1f1eb": { - "output": "1f1ec-1f1eb", - "name": "French Guiana", - "alpha_code": ":flag_gf:", - "aliases": ":gf:" - }, - "1f1f9-1f1eb": { - "output": "1f1f9-1f1eb", - "name": "French Southern Territories", - "alpha_code": ":flag_tf:", - "aliases": ":tf:" - }, - "1f1ec-1f1f5": { - "output": "1f1ec-1f1f5", - "name": "Guadeloupe", - "alpha_code": ":flag_gp:", - "aliases": ":gp:" - }, - "1f1f2-1f1f6": { - "output": "1f1f2-1f1f6", - "name": "Martinique", - "alpha_code": ":flag_mq:", - "aliases": ":mq:" - }, - "1f1f2-1f1f5": { - "output": "1f1f2-1f1f5", - "name": "Northern Mariana Islands", - "alpha_code": ":flag_mp:", - "aliases": ":mp:" - }, - "1f1f7-1f1ea": { - "output": "1f1f7-1f1ea", - "name": "R\u00e9union", - "alpha_code": ":flag_re:", - "aliases": ":re:" - }, - "1f1f8-1f1fd": { - "output": "1f1f8-1f1fd", - "name": "Sint Maarten", - "alpha_code": ":flag_sx:", - "aliases": ":sx:" - }, - "1f1f8-1f1f8": { - "output": "1f1f8-1f1f8", - "name": "South Sudan", - "alpha_code": ":flag_ss:", - "aliases": ":ss:" - }, - "1f1f9-1f1e8": { - "output": "1f1f9-1f1e8", - "name": "Turks & Caicos Islands", - "alpha_code": ":flag_tc:", - "aliases": ":tc:" - }, - "1f1f2-1f1eb": { - "output": "1f1f2-1f1eb", - "name": "St. Martin", - "alpha_code": ":flag_mf:", - "aliases": ":mf:" - }, - "1f575-1f3fb": { - "output": "1f575-1f3fb", - "name": "detective: light skin tone", - "alpha_code": ":detective_tone1:", - "aliases": ":spy_tone1:|:sleuth_or_spy_tone1:" - }, - "1f575-1f3fc": { - "output": "1f575-1f3fc", - "name": "detective: medium-light skin tone", - "alpha_code": ":detective_tone2:", - "aliases": ":spy_tone2:|:sleuth_or_spy_tone2:" - }, - "1f575-1f3fd": { - "output": "1f575-1f3fd", - "name": "detective: medium skin tone", - "alpha_code": ":detective_tone3:", - "aliases": ":spy_tone3:|:sleuth_or_spy_tone3:" - }, - "1f575-1f3fe": { - "output": "1f575-1f3fe", - "name": "detective: medium-dark skin tone", - "alpha_code": ":detective_tone4:", - "aliases": ":spy_tone4:|:sleuth_or_spy_tone4:" - }, - "1f575-1f3ff": { - "output": "1f575-1f3ff", - "name": "detective: dark skin tone", - "alpha_code": ":detective_tone5:", - "aliases": ":spy_tone5:|:sleuth_or_spy_tone5:" - }, - "1f941": { - "output": "1f941", - "name": "drum", - "alpha_code": ":drum:", - "aliases": ":drum_with_drumsticks:" - }, - "1f990": { - "output": "1f990", - "name": "shrimp", - "alpha_code": ":shrimp:", - "aliases": "" - }, - "1f991": { - "output": "1f991", - "name": "squid", - "alpha_code": ":squid:", - "aliases": "" - }, - "1f95a": { - "output": "1f95a", - "name": "egg", - "alpha_code": ":egg:", - "aliases": "" - }, - "1f95b": { - "output": "1f95b", - "name": "glass of milk", - "alpha_code": ":milk:", - "aliases": ":glass_of_milk:" - }, - "1f95c": { - "output": "1f95c", - "name": "peanuts", - "alpha_code": ":peanuts:", - "aliases": ":shelled_peanut:" - }, - "1f95d": { - "output": "1f95d", - "name": "kiwi fruit", - "alpha_code": ":kiwi:", - "aliases": ":kiwifruit:" - }, - "1f95e": { - "output": "1f95e", - "name": "pancakes", - "alpha_code": ":pancakes:", - "aliases": "" - }, - "1f1fc": { - "output": "1f1fc", - "name": "regional indicator symbol letter w", - "alpha_code": ":regional_indicator_w:", - "aliases": "" - }, - "1f1fb": { - "output": "1f1fb", - "name": "regional indicator symbol letter v", - "alpha_code": ":regional_indicator_v:", - "aliases": "" - }, - "1f1fa": { - "output": "1f1fa", - "name": "regional indicator symbol letter u", - "alpha_code": ":regional_indicator_u:", - "aliases": "" - }, - "1f1f9": { - "output": "1f1f9", - "name": "regional indicator symbol letter t", - "alpha_code": ":regional_indicator_t:", - "aliases": "" - }, - "1f1f8": { - "output": "1f1f8", - "name": "regional indicator symbol letter s", - "alpha_code": ":regional_indicator_s:", - "aliases": "" - }, - "1f1f7": { - "output": "1f1f7", - "name": "regional indicator symbol letter r", - "alpha_code": ":regional_indicator_r:", - "aliases": "" - }, - "1f1f6": { - "output": "1f1f6", - "name": "regional indicator symbol letter q", - "alpha_code": ":regional_indicator_q:", - "aliases": "" - }, - "1f1f5": { - "output": "1f1f5", - "name": "regional indicator symbol letter p", - "alpha_code": ":regional_indicator_p:", - "aliases": "" - }, - "1f1f4": { - "output": "1f1f4", - "name": "regional indicator symbol letter o", - "alpha_code": ":regional_indicator_o:", - "aliases": "" - }, - "1f1f3": { - "output": "1f1f3", - "name": "regional indicator symbol letter n", - "alpha_code": ":regional_indicator_n:", - "aliases": "" - }, - "1f1f2": { - "output": "1f1f2", - "name": "regional indicator symbol letter m", - "alpha_code": ":regional_indicator_m:", - "aliases": "" - }, - "1f1f1": { - "output": "1f1f1", - "name": "regional indicator symbol letter l", - "alpha_code": ":regional_indicator_l:", - "aliases": "" - }, - "1f1f0": { - "output": "1f1f0", - "name": "regional indicator symbol letter k", - "alpha_code": ":regional_indicator_k:", - "aliases": "" - }, - "1f1ef": { - "output": "1f1ef", - "name": "regional indicator symbol letter j", - "alpha_code": ":regional_indicator_j:", - "aliases": "" - }, - "1f1ee": { - "output": "1f1ee", - "name": "regional indicator symbol letter i", - "alpha_code": ":regional_indicator_i:", - "aliases": "" - }, - "1f1ed": { - "output": "1f1ed", - "name": "regional indicator symbol letter h", - "alpha_code": ":regional_indicator_h:", - "aliases": "" - }, - "1f1ec": { - "output": "1f1ec", - "name": "regional indicator symbol letter g", - "alpha_code": ":regional_indicator_g:", - "aliases": "" - }, - "1f1eb": { - "output": "1f1eb", - "name": "regional indicator symbol letter f", - "alpha_code": ":regional_indicator_f:", - "aliases": "" - }, - "1f1ea": { - "output": "1f1ea", - "name": "regional indicator symbol letter e", - "alpha_code": ":regional_indicator_e:", - "aliases": "" - }, - "1f1e9": { - "output": "1f1e9", - "name": "regional indicator symbol letter d", - "alpha_code": ":regional_indicator_d:", - "aliases": "" - }, - "1f1e8": { - "output": "1f1e8", - "name": "regional indicator symbol letter c", - "alpha_code": ":regional_indicator_c:", - "aliases": "" - }, - "1f1e7": { - "output": "1f1e7", - "name": "regional indicator symbol letter b", - "alpha_code": ":regional_indicator_b:", - "aliases": "" - }, - "1f1e6": { - "output": "1f1e6", - "name": "regional indicator symbol letter a", - "alpha_code": ":regional_indicator_a:", - "aliases": "" - }, - "0039": { - "output": "0039-fe0f", - "name": "digit nine", - "alpha_code": ":digit_nine:", - "aliases": "" - }, - "0038": { - "output": "0038-fe0f", - "name": "digit eight", - "alpha_code": ":digit_eight:", - "aliases": "" - }, - "0037": { - "output": "0037-fe0f", - "name": "digit seven", - "alpha_code": ":digit_seven:", - "aliases": "" - }, - "0036": { - "output": "0036-fe0f", - "name": "digit six", - "alpha_code": ":digit_six:", - "aliases": "" - }, - "0035": { - "output": "0035-fe0f", - "name": "digit five", - "alpha_code": ":digit_five:", - "aliases": "" - }, - "0034": { - "output": "0034-fe0f", - "name": "digit four", - "alpha_code": ":digit_four:", - "aliases": "" - }, - "0033": { - "output": "0033-fe0f", - "name": "digit three", - "alpha_code": ":digit_three:", - "aliases": "" - }, - "0032": { - "output": "0032-fe0f", - "name": "digit two", - "alpha_code": ":digit_two:", - "aliases": "" - }, - "0031": { - "output": "0031-fe0f", - "name": "digit one", - "alpha_code": ":digit_one:", - "aliases": "" - }, - "0030": { - "output": "0030-fe0f", - "name": "digit zero", - "alpha_code": ":digit_zero:", - "aliases": "" - }, - "1f46f-2642": { - "output": "1f46f-200d-2642-fe0f", - "name": "men with bunny ears partying", - "alpha_code": ":men_with_bunny_ears_partying:", - "aliases": "" - }, - "1f46f-2640": { - "output": "1f46f-200d-2640-fe0f", - "name": "women with bunny ears partying", - "alpha_code": ":women_with_bunny_ears_partying:", - "aliases": "" - }, - "1f3c2-1f3fb": { - "output": "1f3c2-1f3fb", - "name": "snowboarder: light skin tone", - "alpha_code": ":snowboarder_tone1:", - "aliases": ":snowboarder_light_skin_tone:" - }, - "1f3cc-2642": { - "output": "1f3cc-fe0f-200d-2642-fe0f", - "name": "man golfing", - "alpha_code": ":man_golfing:", - "aliases": "" - }, - "1f3cc-1f3fb-2642": { - "output": "1f3cc-1f3fb-200d-2642-fe0f", - "name": "man golfing: light skin tone", - "alpha_code": ":man_golfing_tone1:", - "aliases": ":man_golfing_light_skin_tone:" - }, - "1f3cc-1f3fc-2642": { - "output": "1f3cc-1f3fc-200d-2642-fe0f", - "name": "man golfing: medium-light skin tone", - "alpha_code": ":man_golfing_tone2:", - "aliases": ":man_golfing_medium_light_skin_tone:" - }, - "1f3cc-1f3fd-2642": { - "output": "1f3cc-1f3fd-200d-2642-fe0f", - "name": "man golfing: medium skin tone", - "alpha_code": ":man_golfing_tone3:", - "aliases": ":man_golfing_medium_skin_tone:" - }, - "1f3cc-1f3fe-2642": { - "output": "1f3cc-1f3fe-200d-2642-fe0f", - "name": "man golfing: medium-dark skin tone", - "alpha_code": ":man_golfing_tone4:", - "aliases": ":man_golfing_medium_dark_skin_tone:" - }, - "1f3cc-1f3ff-2642": { - "output": "1f3cc-1f3ff-200d-2642-fe0f", - "name": "man golfing: dark skin tone", - "alpha_code": ":man_golfing_tone5:", - "aliases": ":man_golfing_dark_skin_tone:" - }, - "1f3cc-2640": { - "output": "1f3cc-fe0f-200d-2640-fe0f", - "name": "woman golfing", - "alpha_code": ":woman_golfing:", - "aliases": "" - }, - "1f3cc-1f3fb-2640": { - "output": "1f3cc-1f3fb-200d-2640-fe0f", - "name": "woman golfing: light skin tone", - "alpha_code": ":woman_golfing_tone1:", - "aliases": ":woman_golfing_light_skin_tone:" - }, - "1f3cc-1f3fc-2640": { - "output": "1f3cc-1f3fc-200d-2640-fe0f", - "name": "woman golfing: medium-light skin tone", - "alpha_code": ":woman_golfing_tone2:", - "aliases": ":woman_golfing_medium_light_skin_tone:" - }, - "1f3cc-1f3fd-2640": { - "output": "1f3cc-1f3fd-200d-2640-fe0f", - "name": "woman golfing: medium skin tone", - "alpha_code": ":woman_golfing_tone3:", - "aliases": ":woman_golfing_medium_skin_tone:" - }, - "1f3cc-1f3fe-2640": { - "output": "1f3cc-1f3fe-200d-2640-fe0f", - "name": "woman golfing: medium-dark skin tone", - "alpha_code": ":woman_golfing_tone4:", - "aliases": ":woman_golfing_medium_dark_skin_tone:" - }, - "1f3cc-1f3ff-2640": { - "output": "1f3cc-1f3ff-200d-2640-fe0f", - "name": "woman golfing: dark skin tone", - "alpha_code": ":woman_golfing_tone5:", - "aliases": ":woman_golfing_dark_skin_tone:" - }, - "1f93c-2642": { - "output": "1f93c-200d-2642-fe0f", - "name": "men wrestling", - "alpha_code": ":men_wrestling:", - "aliases": "" - }, - "1f93c-2640": { - "output": "1f93c-200d-2640-fe0f", - "name": "women wrestling", - "alpha_code": ":women_wrestling:", - "aliases": "" - }, - "1f939-1f3ff-2642": { - "output": "1f939-1f3ff-200d-2642-fe0f", - "name": "man juggling: dark skin tone", - "alpha_code": ":man_juggling_tone5:", - "aliases": ":man_juggling_dark_skin_tone:" - }, - "1f939-1f3fe-2642": { - "output": "1f939-1f3fe-200d-2642-fe0f", - "name": "man juggling: medium-dark skin tone", - "alpha_code": ":man_juggling_tone4:", - "aliases": ":man_juggling_medium_dark_skin_tone:" - }, - "1f939-1f3fd-2642": { - "output": "1f939-1f3fd-200d-2642-fe0f", - "name": "man juggling: medium skin tone", - "alpha_code": ":man_juggling_tone3:", - "aliases": ":man_juggling_medium_skin_tone:" - }, - "1f939-1f3fc-2642": { - "output": "1f939-1f3fc-200d-2642-fe0f", - "name": "man juggling: medium-light skin tone", - "alpha_code": ":man_juggling_tone2:", - "aliases": ":man_juggling_medium_light_skin_tone:" - }, - "1f939-1f3fb-2642": { - "output": "1f939-1f3fb-200d-2642-fe0f", - "name": "man juggling: light skin tone", - "alpha_code": ":man_juggling_tone1:", - "aliases": ":man_juggling_light_skin_tone:" - }, - "1f939-2642": { - "output": "1f939-200d-2642-fe0f", - "name": "man juggling", - "alpha_code": ":man_juggling:", - "aliases": "" - }, - "1f939-1f3ff-2640": { - "output": "1f939-1f3ff-200d-2640-fe0f", - "name": "woman juggling: dark skin tone", - "alpha_code": ":woman_juggling_tone5:", - "aliases": ":woman_juggling_dark_skin_tone:" - }, - "1f939-1f3fe-2640": { - "output": "1f939-1f3fe-200d-2640-fe0f", - "name": "woman juggling: medium-dark skin tone", - "alpha_code": ":woman_juggling_tone4:", - "aliases": ":woman_juggling_medium_dark_skin_tone:" - }, - "1f939-1f3fd-2640": { - "output": "1f939-1f3fd-200d-2640-fe0f", - "name": "woman juggling: medium skin tone", - "alpha_code": ":woman_juggling_tone3:", - "aliases": ":woman_juggling_medium_skin_tone:" - }, - "1f939-1f3fc-2640": { - "output": "1f939-1f3fc-200d-2640-fe0f", - "name": "woman juggling: medium-light skin tone", - "alpha_code": ":woman_juggling_tone2:", - "aliases": ":woman_juggling_medium_light_skin_tone:" - }, - "1f939-1f3fb-2640": { - "output": "1f939-1f3fb-200d-2640-fe0f", - "name": "woman juggling: light skin tone", - "alpha_code": ":woman_juggling_tone1:", - "aliases": ":woman_juggling_light_skin_tone:" - }, - "1f939-2640": { - "output": "1f939-200d-2640-fe0f", - "name": "woman juggling", - "alpha_code": ":woman_juggling:", - "aliases": "" - }, - "1f93e-1f3ff-2642": { - "output": "1f93e-1f3ff-200d-2642-fe0f", - "name": "man playing handball: dark skin tone", - "alpha_code": ":man_playing_handball_tone5:", - "aliases": ":man_playing_handball_dark_skin_tone:" - }, - "1f93e-1f3fe-2642": { - "output": "1f93e-1f3fe-200d-2642-fe0f", - "name": "man playing handball: medium-dark skin tone", - "alpha_code": ":man_playing_handball_tone4:", - "aliases": ":man_playing_handball_medium_dark_skin_tone:" - }, - "1f93e-1f3fd-2642": { - "output": "1f93e-1f3fd-200d-2642-fe0f", - "name": "man playing handball: medium skin tone", - "alpha_code": ":man_playing_handball_tone3:", - "aliases": ":man_playing_handball_medium_skin_tone:" - }, - "1f93e-1f3fc-2642": { - "output": "1f93e-1f3fc-200d-2642-fe0f", - "name": "man playing handball: medium-light skin tone", - "alpha_code": ":man_playing_handball_tone2:", - "aliases": ":man_playing_handball_medium_light_skin_tone:" - }, - "1f93e-1f3fb-2642": { - "output": "1f93e-1f3fb-200d-2642-fe0f", - "name": "man playing handball: light skin tone", - "alpha_code": ":man_playing_handball_tone1:", - "aliases": ":man_playing_handball_light_skin_tone:" - }, - "1f93e-2642": { - "output": "1f93e-200d-2642-fe0f", - "name": "man playing handball", - "alpha_code": ":man_playing_handball:", - "aliases": "" - }, - "1f93e-1f3ff-2640": { - "output": "1f93e-1f3ff-200d-2640-fe0f", - "name": "woman playing handball: dark skin tone", - "alpha_code": ":woman_playing_handball_tone5:", - "aliases": ":woman_playing_handball_dark_skin_tone:" - }, - "1f93e-1f3fe-2640": { - "output": "1f93e-1f3fe-200d-2640-fe0f", - "name": "woman playing handball: medium-dark skin tone", - "alpha_code": ":woman_playing_handball_tone4:", - "aliases": ":woman_playing_handball_medium_dark_skin_tone:" - }, - "1f93e-1f3fd-2640": { - "output": "1f93e-1f3fd-200d-2640-fe0f", - "name": "woman playing handball: medium skin tone", - "alpha_code": ":woman_playing_handball_tone3:", - "aliases": ":woman_playing_handball_medium_skin_tone:" - }, - "1f93e-1f3fc-2640": { - "output": "1f93e-1f3fc-200d-2640-fe0f", - "name": "woman playing handball: medium-light skin tone", - "alpha_code": ":woman_playing_handball_tone2:", - "aliases": ":woman_playing_handball_medium_light_skin_tone:" - }, - "1f93e-1f3fb-2640": { - "output": "1f93e-1f3fb-200d-2640-fe0f", - "name": "woman playing handball: light skin tone", - "alpha_code": ":woman_playing_handball_tone1:", - "aliases": ":woman_playing_handball_light_skin_tone:" - }, - "1f93e-2640": { - "output": "1f93e-200d-2640-fe0f", - "name": "woman playing handball", - "alpha_code": ":woman_playing_handball:", - "aliases": "" - }, - "1f93d-1f3ff-2642": { - "output": "1f93d-1f3ff-200d-2642-fe0f", - "name": "man playing water polo: dark skin tone", - "alpha_code": ":man_playing_water_polo_tone5:", - "aliases": ":man_playing_water_polo_dark_skin_tone:" - }, - "1f93d-1f3fe-2642": { - "output": "1f93d-1f3fe-200d-2642-fe0f", - "name": "man playing water polo: medium-dark skin tone", - "alpha_code": ":man_playing_water_polo_tone4:", - "aliases": ":man_playing_water_polo_medium_dark_skin_tone:" - }, - "1f93d-1f3fd-2642": { - "output": "1f93d-1f3fd-200d-2642-fe0f", - "name": "man playing water polo: medium skin tone", - "alpha_code": ":man_playing_water_polo_tone3:", - "aliases": ":man_playing_water_polo_medium_skin_tone:" - }, - "1f93d-1f3fc-2642": { - "output": "1f93d-1f3fc-200d-2642-fe0f", - "name": "man playing water polo: medium-light skin tone", - "alpha_code": ":man_playing_water_polo_tone2:", - "aliases": ":man_playing_water_polo_medium_light_skin_tone:" - }, - "1f93d-1f3fb-2642": { - "output": "1f93d-1f3fb-200d-2642-fe0f", - "name": "man playing water polo: light skin tone", - "alpha_code": ":man_playing_water_polo_tone1:", - "aliases": ":man_playing_water_polo_light_skin_tone:" - }, - "1f93d-2642": { - "output": "1f93d-200d-2642-fe0f", - "name": "man playing water polo", - "alpha_code": ":man_playing_water_polo:", - "aliases": "" - }, - "1f93d-1f3ff-2640": { - "output": "1f93d-1f3ff-200d-2640-fe0f", - "name": "woman playing water polo: dark skin tone", - "alpha_code": ":woman_playing_water_polo_tone5:", - "aliases": ":woman_playing_water_polo_dark_skin_tone:" - }, - "1f93d-1f3fe-2640": { - "output": "1f93d-1f3fe-200d-2640-fe0f", - "name": "woman playing water polo: medium-dark skin tone", - "alpha_code": ":woman_playing_water_polo_tone4:", - "aliases": ":woman_playing_water_polo_medium_dark_skin_tone:" - }, - "1f93d-1f3fd-2640": { - "output": "1f93d-1f3fd-200d-2640-fe0f", - "name": "woman playing water polo: medium skin tone", - "alpha_code": ":woman_playing_water_polo_tone3:", - "aliases": ":woman_playing_water_polo_medium_skin_tone:" - }, - "1f93d-1f3fc-2640": { - "output": "1f93d-1f3fc-200d-2640-fe0f", - "name": "woman playing water polo: medium-light skin tone", - "alpha_code": ":woman_playing_water_polo_tone2:", - "aliases": ":woman_playing_water_polo_medium_light_skin_tone:" - }, - "1f93d-1f3fb-2640": { - "output": "1f93d-1f3fb-200d-2640-fe0f", - "name": "woman playing water polo: light skin tone", - "alpha_code": ":woman_playing_water_polo_tone1:", - "aliases": ":woman_playing_water_polo_light_skin_tone:" - }, - "1f93d-2640": { - "output": "1f93d-200d-2640-fe0f", - "name": "woman playing water polo", - "alpha_code": ":woman_playing_water_polo:", - "aliases": "" - }, - "1f938-1f3ff-2642": { - "output": "1f938-1f3ff-200d-2642-fe0f", - "name": "man cartwheeling: dark skin tone", - "alpha_code": ":man_cartwheeling_tone5:", - "aliases": ":man_cartwheeling_dark_skin_tone:" - }, - "1f938-1f3fe-2642": { - "output": "1f938-1f3fe-200d-2642-fe0f", - "name": "man cartwheeling: medium-dark skin tone", - "alpha_code": ":man_cartwheeling_tone4:", - "aliases": ":man_cartwheeling_medium_dark_skin_tone:" - }, - "1f938-1f3fd-2642": { - "output": "1f938-1f3fd-200d-2642-fe0f", - "name": "man cartwheeling: medium skin tone", - "alpha_code": ":man_cartwheeling_tone3:", - "aliases": ":man_cartwheeling_medium_skin_tone:" - }, - "1f938-1f3fc-2642": { - "output": "1f938-1f3fc-200d-2642-fe0f", - "name": "man cartwheeling: medium-light skin tone", - "alpha_code": ":man_cartwheeling_tone2:", - "aliases": ":man_cartwheeling_medium_light_skin_tone:" - }, - "1f938-1f3fb-2642": { - "output": "1f938-1f3fb-200d-2642-fe0f", - "name": "man cartwheeling: light skin tone", - "alpha_code": ":man_cartwheeling_tone1:", - "aliases": ":man_cartwheeling_light_skin_tone:" - }, - "1f938-2642": { - "output": "1f938-200d-2642-fe0f", - "name": "man cartwheeling", - "alpha_code": ":man_cartwheeling:", - "aliases": "" - }, - "1f938-1f3ff-2640": { - "output": "1f938-1f3ff-200d-2640-fe0f", - "name": "woman cartwheeling: dark skin tone", - "alpha_code": ":woman_cartwheeling_tone5:", - "aliases": ":woman_cartwheeling_dark_skin_tone:" - }, - "1f938-1f3fe-2640": { - "output": "1f938-1f3fe-200d-2640-fe0f", - "name": "woman cartwheeling: medium-dark skin tone", - "alpha_code": ":woman_cartwheeling_tone4:", - "aliases": ":woman_cartwheeling_medium_dark_skin_tone:" - }, - "1f938-1f3fd-2640": { - "output": "1f938-1f3fd-200d-2640-fe0f", - "name": "woman cartwheeling: medium skin tone", - "alpha_code": ":woman_cartwheeling_tone3:", - "aliases": ":woman_cartwheeling_medium_skin_tone:" - }, - "1f938-1f3fc-2640": { - "output": "1f938-1f3fc-200d-2640-fe0f", - "name": "woman cartwheeling: medium-light skin tone", - "alpha_code": ":woman_cartwheeling_tone2:", - "aliases": ":woman_cartwheeling_medium_light_skin_tone:" - }, - "1f938-1f3fb-2640": { - "output": "1f938-1f3fb-200d-2640-fe0f", - "name": "woman cartwheeling: light skin tone", - "alpha_code": ":woman_cartwheeling_tone1:", - "aliases": ":woman_cartwheeling_light_skin_tone:" - }, - "1f938-2640": { - "output": "1f938-200d-2640-fe0f", - "name": "woman cartwheeling", - "alpha_code": ":woman_cartwheeling:", - "aliases": "" - }, - "1f6b6-1f3ff-2642": { - "output": "1f6b6-1f3ff-200d-2642-fe0f", - "name": "man walking: dark skin tone", - "alpha_code": ":man_walking_tone5:", - "aliases": ":man_walking_dark_skin_tone:" - }, - "1f6b6-1f3fe-2642": { - "output": "1f6b6-1f3fe-200d-2642-fe0f", - "name": "man walking: medium-dark skin tone", - "alpha_code": ":man_walking_tone4:", - "aliases": ":man_walking_medium_dark_skin_tone:" - }, - "1f6b6-1f3fd-2642": { - "output": "1f6b6-1f3fd-200d-2642-fe0f", - "name": "man walking: medium skin tone", - "alpha_code": ":man_walking_tone3:", - "aliases": ":man_walking_medium_skin_tone:" - }, - "1f6b6-1f3fc-2642": { - "output": "1f6b6-1f3fc-200d-2642-fe0f", - "name": "man walking: medium-light skin tone", - "alpha_code": ":man_walking_tone2:", - "aliases": ":man_walking_medium_light_skin_tone:" - }, - "1f6b6-1f3fb-2642": { - "output": "1f6b6-1f3fb-200d-2642-fe0f", - "name": "man walking: light skin tone", - "alpha_code": ":man_walking_tone1:", - "aliases": ":man_walking_light_skin_tone:" - }, - "1f6b6-2642": { - "output": "1f6b6-200d-2642-fe0f", - "name": "man walking", - "alpha_code": ":man_walking:", - "aliases": "" - }, - "1f6b6-1f3ff-2640": { - "output": "1f6b6-1f3ff-200d-2640-fe0f", - "name": "woman walking: dark skin tone", - "alpha_code": ":woman_walking_tone5:", - "aliases": ":woman_walking_dark_skin_tone:" - }, - "1f6b6-1f3fe-2640": { - "output": "1f6b6-1f3fe-200d-2640-fe0f", - "name": "woman walking: medium-dark skin tone", - "alpha_code": ":woman_walking_tone4:", - "aliases": ":woman_walking_medium_dark_skin_tone:" - }, - "1f6b6-1f3fd-2640": { - "output": "1f6b6-1f3fd-200d-2640-fe0f", - "name": "woman walking: medium skin tone", - "alpha_code": ":woman_walking_tone3:", - "aliases": ":woman_walking_medium_skin_tone:" - }, - "1f6b6-1f3fc-2640": { - "output": "1f6b6-1f3fc-200d-2640-fe0f", - "name": "woman walking: medium-light skin tone", - "alpha_code": ":woman_walking_tone2:", - "aliases": ":woman_walking_medium_light_skin_tone:" - }, - "1f6b6-1f3fb-2640": { - "output": "1f6b6-1f3fb-200d-2640-fe0f", - "name": "woman walking: light skin tone", - "alpha_code": ":woman_walking_tone1:", - "aliases": ":woman_walking_light_skin_tone:" - }, - "1f6b6-2640": { - "output": "1f6b6-200d-2640-fe0f", - "name": "woman walking", - "alpha_code": ":woman_walking:", - "aliases": "" - }, - "1f6b5-1f3ff-2642": { - "output": "1f6b5-1f3ff-200d-2642-fe0f", - "name": "man mountain biking: dark skin tone", - "alpha_code": ":man_mountain_biking_tone5:", - "aliases": ":man_mountain_biking_dark_skin_tone:" - }, - "1f6b5-1f3fe-2642": { - "output": "1f6b5-1f3fe-200d-2642-fe0f", - "name": "man mountain biking: medium-dark skin tone", - "alpha_code": ":man_mountain_biking_tone4:", - "aliases": ":man_mountain_biking_medium_dark_skin_tone:" - }, - "1f6b5-1f3fd-2642": { - "output": "1f6b5-1f3fd-200d-2642-fe0f", - "name": "man mountain biking: medium skin tone", - "alpha_code": ":man_mountain_biking_tone3:", - "aliases": ":man_mountain_biking_medium_skin_tone:" - }, - "1f6b5-1f3fc-2642": { - "output": "1f6b5-1f3fc-200d-2642-fe0f", - "name": "man mountain biking: medium-light skin tone", - "alpha_code": ":man_mountain_biking_tone2:", - "aliases": ":man_mountain_biking_medium_light_skin_tone:" - }, - "1f6b5-1f3fb-2642": { - "output": "1f6b5-1f3fb-200d-2642-fe0f", - "name": "man mountain biking: light skin tone", - "alpha_code": ":man_mountain_biking_tone1:", - "aliases": ":man_mountain_biking_light_skin_tone:" - }, - "1f6b5-2642": { - "output": "1f6b5-200d-2642-fe0f", - "name": "man mountain biking", - "alpha_code": ":man_mountain_biking:", - "aliases": "" - }, - "1f6b5-1f3ff-2640": { - "output": "1f6b5-1f3ff-200d-2640-fe0f", - "name": "woman mountain biking: dark skin tone", - "alpha_code": ":woman_mountain_biking_tone5:", - "aliases": ":woman_mountain_biking_dark_skin_tone:" - }, - "1f6b5-1f3fe-2640": { - "output": "1f6b5-1f3fe-200d-2640-fe0f", - "name": "woman mountain biking: medium-dark skin tone", - "alpha_code": ":woman_mountain_biking_tone4:", - "aliases": ":woman_mountain_biking_medium_dark_skin_tone:" - }, - "1f6b5-1f3fd-2640": { - "output": "1f6b5-1f3fd-200d-2640-fe0f", - "name": "woman mountain biking: medium skin tone", - "alpha_code": ":woman_mountain_biking_tone3:", - "aliases": ":woman_mountain_biking_medium_skin_tone:" - }, - "1f6b5-1f3fc-2640": { - "output": "1f6b5-1f3fc-200d-2640-fe0f", - "name": "woman mountain biking: medium-light skin tone", - "alpha_code": ":woman_mountain_biking_tone2:", - "aliases": ":woman_mountain_biking_medium_light_skin_tone:" - }, - "1f6b5-1f3fb-2640": { - "output": "1f6b5-1f3fb-200d-2640-fe0f", - "name": "woman mountain biking: light skin tone", - "alpha_code": ":woman_mountain_biking_tone1:", - "aliases": ":woman_mountain_biking_light_skin_tone:" - }, - "1f6b5-2640": { - "output": "1f6b5-200d-2640-fe0f", - "name": "woman mountain biking", - "alpha_code": ":woman_mountain_biking:", - "aliases": "" - }, - "1f6b4-1f3ff-2642": { - "output": "1f6b4-1f3ff-200d-2642-fe0f", - "name": "man biking: dark skin tone", - "alpha_code": ":man_biking_tone5:", - "aliases": ":man_biking_dark_skin_tone:" - }, - "1f6b4-1f3fe-2642": { - "output": "1f6b4-1f3fe-200d-2642-fe0f", - "name": "man biking: medium-dark skin tone", - "alpha_code": ":man_biking_tone4:", - "aliases": ":man_biking_medium_dark_skin_tone:" - }, - "1f6b4-1f3fd-2642": { - "output": "1f6b4-1f3fd-200d-2642-fe0f", - "name": "man biking: medium skin tone", - "alpha_code": ":man_biking_tone3:", - "aliases": ":man_biking_medium_skin_tone:" - }, - "1f6b4-1f3fc-2642": { - "output": "1f6b4-1f3fc-200d-2642-fe0f", - "name": "man biking: medium-light skin tone", - "alpha_code": ":man_biking_tone2:", - "aliases": ":man_biking_medium_light_skin_tone:" - }, - "1f6b4-1f3fb-2642": { - "output": "1f6b4-1f3fb-200d-2642-fe0f", - "name": "man biking: light skin tone", - "alpha_code": ":man_biking_tone1:", - "aliases": ":man_biking_light_skin_tone:" - }, - "1f6b4-2642": { - "output": "1f6b4-200d-2642-fe0f", - "name": "man biking", - "alpha_code": ":man_biking:", - "aliases": "" - }, - "1f6b4-1f3ff-2640": { - "output": "1f6b4-1f3ff-200d-2640-fe0f", - "name": "woman biking: dark skin tone", - "alpha_code": ":woman_biking_tone5:", - "aliases": ":woman_biking_dark_skin_tone:" - }, - "1f6b4-1f3fe-2640": { - "output": "1f6b4-1f3fe-200d-2640-fe0f", - "name": "woman biking: medium-dark skin tone", - "alpha_code": ":woman_biking_tone4:", - "aliases": ":woman_biking_medium_dark_skin_tone:" - }, - "1f6b4-1f3fd-2640": { - "output": "1f6b4-1f3fd-200d-2640-fe0f", - "name": "woman biking: medium skin tone", - "alpha_code": ":woman_biking_tone3:", - "aliases": ":woman_biking_medium_skin_tone:" - }, - "1f6b4-1f3fc-2640": { - "output": "1f6b4-1f3fc-200d-2640-fe0f", - "name": "woman biking: medium-light skin tone", - "alpha_code": ":woman_biking_tone2:", - "aliases": ":woman_biking_medium_light_skin_tone:" - }, - "1f6b4-1f3fb-2640": { - "output": "1f6b4-1f3fb-200d-2640-fe0f", - "name": "woman biking: light skin tone", - "alpha_code": ":woman_biking_tone1:", - "aliases": ":woman_biking_light_skin_tone:" - }, - "1f6b4-2640": { - "output": "1f6b4-200d-2640-fe0f", - "name": "woman biking", - "alpha_code": ":woman_biking:", - "aliases": "" - }, - "1f6a3-1f3ff-2642": { - "output": "1f6a3-1f3ff-200d-2642-fe0f", - "name": "man rowing boat: dark skin tone", - "alpha_code": ":man_rowing_boat_tone5:", - "aliases": ":man_rowing_boat_dark_skin_tone:" - }, - "1f6a3-1f3fe-2642": { - "output": "1f6a3-1f3fe-200d-2642-fe0f", - "name": "man rowing boat: medium-dark skin tone", - "alpha_code": ":man_rowing_boat_tone4:", - "aliases": ":man_rowing_boat_medium_dark_skin_tone:" - }, - "1f6a3-1f3fd-2642": { - "output": "1f6a3-1f3fd-200d-2642-fe0f", - "name": "man rowing boat: medium skin tone", - "alpha_code": ":man_rowing_boat_tone3:", - "aliases": ":man_rowing_boat_medium_skin_tone:" - }, - "1f6a3-1f3fc-2642": { - "output": "1f6a3-1f3fc-200d-2642-fe0f", - "name": "man rowing boat: medium-light skin tone", - "alpha_code": ":man_rowing_boat_tone2:", - "aliases": ":man_rowing_boat_medium_light_skin_tone:" - }, - "1f6a3-1f3fb-2642": { - "output": "1f6a3-1f3fb-200d-2642-fe0f", - "name": "man rowing boat: light skin tone", - "alpha_code": ":man_rowing_boat_tone1:", - "aliases": ":man_rowing_boat_light_skin_tone:" - }, - "1f6a3-2642": { - "output": "1f6a3-200d-2642-fe0f", - "name": "man rowing boat", - "alpha_code": ":man_rowing_boat:", - "aliases": "" - }, - "1f6a3-1f3ff-2640": { - "output": "1f6a3-1f3ff-200d-2640-fe0f", - "name": "woman rowing boat: dark skin tone", - "alpha_code": ":woman_rowing_boat_tone5:", - "aliases": ":woman_rowing_boat_dark_skin_tone:" - }, - "1f6a3-1f3fe-2640": { - "output": "1f6a3-1f3fe-200d-2640-fe0f", - "name": "woman rowing boat: medium-dark skin tone", - "alpha_code": ":woman_rowing_boat_tone4:", - "aliases": ":woman_rowing_boat_medium_dark_skin_tone:" - }, - "1f6a3-1f3fd-2640": { - "output": "1f6a3-1f3fd-200d-2640-fe0f", - "name": "woman rowing boat: medium skin tone", - "alpha_code": ":woman_rowing_boat_tone3:", - "aliases": ":woman_rowing_boat_medium_skin_tone:" - }, - "1f6a3-1f3fc-2640": { - "output": "1f6a3-1f3fc-200d-2640-fe0f", - "name": "woman rowing boat: medium-light skin tone", - "alpha_code": ":woman_rowing_boat_tone2:", - "aliases": ":woman_rowing_boat_medium_light_skin_tone:" - }, - "1f6a3-1f3fb-2640": { - "output": "1f6a3-1f3fb-200d-2640-fe0f", - "name": "woman rowing boat: light skin tone", - "alpha_code": ":woman_rowing_boat_tone1:", - "aliases": ":woman_rowing_boat_light_skin_tone:" - }, - "1f6a3-2640": { - "output": "1f6a3-200d-2640-fe0f", - "name": "woman rowing boat", - "alpha_code": ":woman_rowing_boat:", - "aliases": "" - }, - "1f3cb-1f3ff-2642": { - "output": "1f3cb-1f3ff-200d-2642-fe0f", - "name": "man lifting weights: dark skin tone", - "alpha_code": ":man_lifting_weights_tone5:", - "aliases": ":man_lifting_weights_dark_skin_tone:" - }, - "1f3cb-1f3fe-2642": { - "output": "1f3cb-1f3fe-200d-2642-fe0f", - "name": "man lifting weights: medium-dark skin tone", - "alpha_code": ":man_lifting_weights_tone4:", - "aliases": ":man_lifting_weights_medium_dark_skin_tone:" - }, - "1f3cb-1f3fd-2642": { - "output": "1f3cb-1f3fd-200d-2642-fe0f", - "name": "man lifting weights: medium skin tone", - "alpha_code": ":man_lifting_weights_tone3:", - "aliases": ":man_lifting_weights_medium_skin_tone:" - }, - "1f3cb-1f3fc-2642": { - "output": "1f3cb-1f3fc-200d-2642-fe0f", - "name": "man lifting weights: medium-light skin tone", - "alpha_code": ":man_lifting_weights_tone2:", - "aliases": ":man_lifting_weights_medium_light_skin_tone:" - }, - "1f3cb-1f3fb-2642": { - "output": "1f3cb-1f3fb-200d-2642-fe0f", - "name": "man lifting weights: light skin tone", - "alpha_code": ":man_lifting_weights_tone1:", - "aliases": ":man_lifting_weights_light_skin_tone:" - }, - "1f3cb-2642": { - "output": "1f3cb-fe0f-200d-2642-fe0f", - "name": "man lifting weights", - "alpha_code": ":man_lifting_weights:", - "aliases": "" - }, - "1f3cb-1f3ff-2640": { - "output": "1f3cb-1f3ff-200d-2640-fe0f", - "name": "woman lifting weights: dark skin tone", - "alpha_code": ":woman_lifting_weights_tone5:", - "aliases": ":woman_lifting_weights_dark_skin_tone:" - }, - "1f3cb-1f3fe-2640": { - "output": "1f3cb-1f3fe-200d-2640-fe0f", - "name": "woman lifting weights: medium-dark skin tone", - "alpha_code": ":woman_lifting_weights_tone4:", - "aliases": ":woman_lifting_weights_medium_dark_skin_tone:" - }, - "1f3cb-1f3fd-2640": { - "output": "1f3cb-1f3fd-200d-2640-fe0f", - "name": "woman lifting weights: medium skin tone", - "alpha_code": ":woman_lifting_weights_tone3:", - "aliases": ":woman_lifting_weights_medium_skin_tone:" - }, - "1f3cb-1f3fc-2640": { - "output": "1f3cb-1f3fc-200d-2640-fe0f", - "name": "woman lifting weights: medium-light skin tone", - "alpha_code": ":woman_lifting_weights_tone2:", - "aliases": ":woman_lifting_weights_medium_light_skin_tone:" - }, - "1f3cb-1f3fb-2640": { - "output": "1f3cb-1f3fb-200d-2640-fe0f", - "name": "woman lifting weights: light skin tone", - "alpha_code": ":woman_lifting_weights_tone1:", - "aliases": ":woman_lifting_weights_light_skin_tone:" - }, - "1f3cb-2640": { - "output": "1f3cb-fe0f-200d-2640-fe0f", - "name": "woman lifting weights", - "alpha_code": ":woman_lifting_weights:", - "aliases": "" - }, - "1f3ca-1f3ff-2642": { - "output": "1f3ca-1f3ff-200d-2642-fe0f", - "name": "man swimming: dark skin tone", - "alpha_code": ":man_swimming_tone5:", - "aliases": ":man_swimming_dark_skin_tone:" - }, - "1f3ca-1f3fe-2642": { - "output": "1f3ca-1f3fe-200d-2642-fe0f", - "name": "man swimming: medium-dark skin tone", - "alpha_code": ":man_swimming_tone4:", - "aliases": ":man_swimming_medium_dark_skin_tone:" - }, - "1f3ca-1f3fd-2642": { - "output": "1f3ca-1f3fd-200d-2642-fe0f", - "name": "man swimming: medium skin tone", - "alpha_code": ":man_swimming_tone3:", - "aliases": ":man_swimming_medium_skin_tone:" - }, - "1f3ca-1f3fc-2642": { - "output": "1f3ca-1f3fc-200d-2642-fe0f", - "name": "man swimming: medium-light skin tone", - "alpha_code": ":man_swimming_tone2:", - "aliases": ":man_swimming_medium_light_skin_tone:" - }, - "1f3ca-1f3fb-2642": { - "output": "1f3ca-1f3fb-200d-2642-fe0f", - "name": "man swimming: light skin tone", - "alpha_code": ":man_swimming_tone1:", - "aliases": ":man_swimming_light_skin_tone:" - }, - "1f3ca-2642": { - "output": "1f3ca-200d-2642-fe0f", - "name": "man swimming", - "alpha_code": ":man_swimming:", - "aliases": "" - }, - "1f3ca-1f3ff-2640": { - "output": "1f3ca-1f3ff-200d-2640-fe0f", - "name": "woman swimming: dark skin tone", - "alpha_code": ":woman_swimming_tone5:", - "aliases": ":woman_swimming_dark_skin_tone:" - }, - "1f3ca-1f3fe-2640": { - "output": "1f3ca-1f3fe-200d-2640-fe0f", - "name": "woman swimming: medium-dark skin tone", - "alpha_code": ":woman_swimming_tone4:", - "aliases": ":woman_swimming_medium_dark_skin_tone:" - }, - "1f3ca-1f3fd-2640": { - "output": "1f3ca-1f3fd-200d-2640-fe0f", - "name": "woman swimming: medium skin tone", - "alpha_code": ":woman_swimming_tone3:", - "aliases": ":woman_swimming_medium_skin_tone:" - }, - "1f3ca-1f3fc-2640": { - "output": "1f3ca-1f3fc-200d-2640-fe0f", - "name": "woman swimming: medium-light skin tone", - "alpha_code": ":woman_swimming_tone2:", - "aliases": ":woman_swimming_medium_light_skin_tone:" - }, - "1f3ca-1f3fb-2640": { - "output": "1f3ca-1f3fb-200d-2640-fe0f", - "name": "woman swimming: light skin tone", - "alpha_code": ":woman_swimming_tone1:", - "aliases": ":woman_swimming_light_skin_tone:" - }, - "1f3ca-2640": { - "output": "1f3ca-200d-2640-fe0f", - "name": "woman swimming", - "alpha_code": ":woman_swimming:", - "aliases": "" - }, - "1f3c4-1f3ff-2642": { - "output": "1f3c4-1f3ff-200d-2642-fe0f", - "name": "man surfing: dark skin tone", - "alpha_code": ":man_surfing_tone5:", - "aliases": ":man_surfing_dark_skin_tone:" - }, - "1f3c4-1f3fe-2642": { - "output": "1f3c4-1f3fe-200d-2642-fe0f", - "name": "man surfing: medium-dark skin tone", - "alpha_code": ":man_surfing_tone4:", - "aliases": ":man_surfing_medium_dark_skin_tone:" - }, - "1f3c4-1f3fd-2642": { - "output": "1f3c4-1f3fd-200d-2642-fe0f", - "name": "man surfing: medium skin tone", - "alpha_code": ":man_surfing_tone3:", - "aliases": ":man_surfing_medium_skin_tone:" - }, - "1f3c4-1f3fc-2642": { - "output": "1f3c4-1f3fc-200d-2642-fe0f", - "name": "man surfing: medium-light skin tone", - "alpha_code": ":man_surfing_tone2:", - "aliases": ":man_surfing_medium_light_skin_tone:" - }, - "1f3c4-1f3fb-2642": { - "output": "1f3c4-1f3fb-200d-2642-fe0f", - "name": "man surfing: light skin tone", - "alpha_code": ":man_surfing_tone1:", - "aliases": ":man_surfing_light_skin_tone:" - }, - "1f3c4-2642": { - "output": "1f3c4-200d-2642-fe0f", - "name": "man surfing", - "alpha_code": ":man_surfing:", - "aliases": "" - }, - "1f3c4-1f3ff-2640": { - "output": "1f3c4-1f3ff-200d-2640-fe0f", - "name": "woman surfing: dark skin tone", - "alpha_code": ":woman_surfing_tone5:", - "aliases": ":woman_surfing_dark_skin_tone:" - }, - "1f3c4-1f3fe-2640": { - "output": "1f3c4-1f3fe-200d-2640-fe0f", - "name": "woman surfing: medium-dark skin tone", - "alpha_code": ":woman_surfing_tone4:", - "aliases": ":woman_surfing_medium_dark_skin_tone:" - }, - "1f3c4-1f3fd-2640": { - "output": "1f3c4-1f3fd-200d-2640-fe0f", - "name": "woman surfing: medium skin tone", - "alpha_code": ":woman_surfing_tone3:", - "aliases": ":woman_surfing_medium_skin_tone:" - }, - "1f3c4-1f3fc-2640": { - "output": "1f3c4-1f3fc-200d-2640-fe0f", - "name": "woman surfing: medium-light skin tone", - "alpha_code": ":woman_surfing_tone2:", - "aliases": ":woman_surfing_medium_light_skin_tone:" - }, - "1f3c4-1f3fb-2640": { - "output": "1f3c4-1f3fb-200d-2640-fe0f", - "name": "woman surfing: light skin tone", - "alpha_code": ":woman_surfing_tone1:", - "aliases": ":woman_surfing_light_skin_tone:" - }, - "1f3c4-2640": { - "output": "1f3c4-200d-2640-fe0f", - "name": "woman surfing", - "alpha_code": ":woman_surfing:", - "aliases": "" - }, - "1f3c3-1f3ff-2642": { - "output": "1f3c3-1f3ff-200d-2642-fe0f", - "name": "man running: dark skin tone", - "alpha_code": ":man_running_tone5:", - "aliases": ":man_running_dark_skin_tone:" - }, - "1f3c3-1f3fe-2642": { - "output": "1f3c3-1f3fe-200d-2642-fe0f", - "name": "man running: medium-dark skin tone", - "alpha_code": ":man_running_tone4:", - "aliases": ":man_running_medium_dark_skin_tone:" - }, - "1f3c3-1f3fd-2642": { - "output": "1f3c3-1f3fd-200d-2642-fe0f", - "name": "man running: medium skin tone", - "alpha_code": ":man_running_tone3:", - "aliases": ":man_running_medium_skin_tone:" - }, - "1f3c3-1f3fc-2642": { - "output": "1f3c3-1f3fc-200d-2642-fe0f", - "name": "man running: medium-light skin tone", - "alpha_code": ":man_running_tone2:", - "aliases": ":man_running_medium_light_skin_tone:" - }, - "1f3c3-1f3fb-2642": { - "output": "1f3c3-1f3fb-200d-2642-fe0f", - "name": "man running: light skin tone", - "alpha_code": ":man_running_tone1:", - "aliases": ":man_running_light_skin_tone:" - }, - "1f3c3-2642": { - "output": "1f3c3-200d-2642-fe0f", - "name": "man running", - "alpha_code": ":man_running:", - "aliases": "" - }, - "1f3c3-1f3ff-2640": { - "output": "1f3c3-1f3ff-200d-2640-fe0f", - "name": "woman running: dark skin tone", - "alpha_code": ":woman_running_tone5:", - "aliases": ":woman_running_dark_skin_tone:" - }, - "1f3c3-1f3fe-2640": { - "output": "1f3c3-1f3fe-200d-2640-fe0f", - "name": "woman running: medium-dark skin tone", - "alpha_code": ":woman_running_tone4:", - "aliases": ":woman_running_medium_dark_skin_tone:" - }, - "1f3c3-1f3fd-2640": { - "output": "1f3c3-1f3fd-200d-2640-fe0f", - "name": "woman running: medium skin tone", - "alpha_code": ":woman_running_tone3:", - "aliases": ":woman_running_medium_skin_tone:" - }, - "1f3c3-1f3fc-2640": { - "output": "1f3c3-1f3fc-200d-2640-fe0f", - "name": "woman running: medium-light skin tone", - "alpha_code": ":woman_running_tone2:", - "aliases": ":woman_running_medium_light_skin_tone:" - }, - "1f3c3-1f3fb-2640": { - "output": "1f3c3-1f3fb-200d-2640-fe0f", - "name": "woman running: light skin tone", - "alpha_code": ":woman_running_tone1:", - "aliases": ":woman_running_light_skin_tone:" - }, - "1f3c3-2640": { - "output": "1f3c3-200d-2640-fe0f", - "name": "woman running", - "alpha_code": ":woman_running:", - "aliases": "" - }, - "26f9-1f3ff-2642": { - "output": "26f9-1f3ff-200d-2642-fe0f", - "name": "man bouncing ball: dark skin tone", - "alpha_code": ":man_bouncing_ball_tone5:", - "aliases": ":man_bouncing_ball_dark_skin_tone:" - }, - "26f9-1f3fe-2642": { - "output": "26f9-1f3fe-200d-2642-fe0f", - "name": "man bouncing ball: medium-dark skin tone", - "alpha_code": ":man_bouncing_ball_tone4:", - "aliases": ":man_bouncing_ball_medium_dark_skin_tone:" - }, - "26f9-1f3fd-2642": { - "output": "26f9-1f3fd-200d-2642-fe0f", - "name": "man bouncing ball: medium skin tone", - "alpha_code": ":man_bouncing_ball_tone3:", - "aliases": ":man_bouncing_ball_medium_skin_tone:" - }, - "26f9-1f3fc-2642": { - "output": "26f9-1f3fc-200d-2642-fe0f", - "name": "man bouncing ball: medium-light skin tone", - "alpha_code": ":man_bouncing_ball_tone2:", - "aliases": ":man_bouncing_ball_medium_light_skin_tone:" - }, - "26f9-1f3fb-2642": { - "output": "26f9-1f3fb-200d-2642-fe0f", - "name": "man bouncing ball: light skin tone", - "alpha_code": ":man_bouncing_ball_tone1:", - "aliases": ":man_bouncing_ball_light_skin_tone:" - }, - "26f9-2642": { - "output": "26f9-fe0f-200d-2642-fe0f", - "name": "man bouncing ball", - "alpha_code": ":man_bouncing_ball:", - "aliases": "" - }, - "26f9-1f3ff-2640": { - "output": "26f9-1f3ff-200d-2640-fe0f", - "name": "woman bouncing ball: dark skin tone", - "alpha_code": ":woman_bouncing_ball_tone5:", - "aliases": ":woman_bouncing_ball_dark_skin_tone:" - }, - "26f9-1f3fe-2640": { - "output": "26f9-1f3fe-200d-2640-fe0f", - "name": "woman bouncing ball: medium-dark skin tone", - "alpha_code": ":woman_bouncing_ball_tone4:", - "aliases": ":woman_bouncing_ball_medium_dark_skin_tone:" - }, - "26f9-1f3fd-2640": { - "output": "26f9-1f3fd-200d-2640-fe0f", - "name": "woman bouncing ball: medium skin tone", - "alpha_code": ":woman_bouncing_ball_tone3:", - "aliases": ":woman_bouncing_ball_medium_skin_tone:" - }, - "26f9-1f3fc-2640": { - "output": "26f9-1f3fc-200d-2640-fe0f", - "name": "woman bouncing ball: medium-light skin tone", - "alpha_code": ":woman_bouncing_ball_tone2:", - "aliases": ":woman_bouncing_ball_medium_light_skin_tone:" - }, - "26f9-1f3fb-2640": { - "output": "26f9-1f3fb-200d-2640-fe0f", - "name": "woman bouncing ball: light skin tone", - "alpha_code": ":woman_bouncing_ball_tone1:", - "aliases": ":woman_bouncing_ball_light_skin_tone:" - }, - "26f9-2640": { - "output": "26f9-fe0f-200d-2640-fe0f", - "name": "woman bouncing ball", - "alpha_code": ":woman_bouncing_ball:", - "aliases": "" - }, - "1f937-1f3ff-2642": { - "output": "1f937-1f3ff-200d-2642-fe0f", - "name": "man shrugging: dark skin tone", - "alpha_code": ":man_shrugging_tone5:", - "aliases": ":man_shrugging_dark_skin_tone:" - }, - "1f937-1f3fe-2642": { - "output": "1f937-1f3fe-200d-2642-fe0f", - "name": "man shrugging: medium-dark skin tone", - "alpha_code": ":man_shrugging_tone4:", - "aliases": ":man_shrugging_medium_dark_skin_tone:" - }, - "1f937-1f3fd-2642": { - "output": "1f937-1f3fd-200d-2642-fe0f", - "name": "man shrugging: medium skin tone", - "alpha_code": ":man_shrugging_tone3:", - "aliases": ":man_shrugging_medium_skin_tone:" - }, - "1f937-1f3fc-2642": { - "output": "1f937-1f3fc-200d-2642-fe0f", - "name": "man shrugging: medium-light skin tone", - "alpha_code": ":man_shrugging_tone2:", - "aliases": ":man_shrugging_medium_light_skin_tone:" - }, - "1f937-1f3fb-2642": { - "output": "1f937-1f3fb-200d-2642-fe0f", - "name": "man shrugging: light skin tone", - "alpha_code": ":man_shrugging_tone1:", - "aliases": ":man_shrugging_light_skin_tone:" - }, - "1f937-2642": { - "output": "1f937-200d-2642-fe0f", - "name": "man shrugging", - "alpha_code": ":man_shrugging:", - "aliases": "" - }, - "1f937-1f3ff-2640": { - "output": "1f937-1f3ff-200d-2640-fe0f", - "name": "woman shrugging: dark skin tone", - "alpha_code": ":woman_shrugging_tone5:", - "aliases": ":woman_shrugging_dark_skin_tone:" - }, - "1f937-1f3fe-2640": { - "output": "1f937-1f3fe-200d-2640-fe0f", - "name": "woman shrugging: medium-dark skin tone", - "alpha_code": ":woman_shrugging_tone4:", - "aliases": ":woman_shrugging_medium_dark_skin_tone:" - }, - "1f937-1f3fd-2640": { - "output": "1f937-1f3fd-200d-2640-fe0f", - "name": "woman shrugging: medium skin tone", - "alpha_code": ":woman_shrugging_tone3:", - "aliases": ":woman_shrugging_medium_skin_tone:" - }, - "1f937-1f3fc-2640": { - "output": "1f937-1f3fc-200d-2640-fe0f", - "name": "woman shrugging: medium-light skin tone", - "alpha_code": ":woman_shrugging_tone2:", - "aliases": ":woman_shrugging_medium_light_skin_tone:" - }, - "1f937-1f3fb-2640": { - "output": "1f937-1f3fb-200d-2640-fe0f", - "name": "woman shrugging: light skin tone", - "alpha_code": ":woman_shrugging_tone1:", - "aliases": ":woman_shrugging_light_skin_tone:" - }, - "1f937-2640": { - "output": "1f937-200d-2640-fe0f", - "name": "woman shrugging", - "alpha_code": ":woman_shrugging:", - "aliases": "" - }, - "1f926-1f3ff-2642": { - "output": "1f926-1f3ff-200d-2642-fe0f", - "name": "man facepalming: dark skin tone", - "alpha_code": ":man_facepalming_tone5:", - "aliases": ":man_facepalming_dark_skin_tone:" - }, - "1f926-1f3fe-2642": { - "output": "1f926-1f3fe-200d-2642-fe0f", - "name": "man facepalming: medium-dark skin tone", - "alpha_code": ":man_facepalming_tone4:", - "aliases": ":man_facepalming_medium_dark_skin_tone:" - }, - "1f926-1f3fd-2642": { - "output": "1f926-1f3fd-200d-2642-fe0f", - "name": "man facepalming: medium skin tone", - "alpha_code": ":man_facepalming_tone3:", - "aliases": ":man_facepalming_medium_skin_tone:" - }, - "1f926-1f3fc-2642": { - "output": "1f926-1f3fc-200d-2642-fe0f", - "name": "man facepalming: medium-light skin tone", - "alpha_code": ":man_facepalming_tone2:", - "aliases": ":man_facepalming_medium_light_skin_tone:" - }, - "1f926-1f3fb-2642": { - "output": "1f926-1f3fb-200d-2642-fe0f", - "name": "man facepalming: light skin tone", - "alpha_code": ":man_facepalming_tone1:", - "aliases": ":man_facepalming_light_skin_tone:" - }, - "1f926-2642": { - "output": "1f926-200d-2642-fe0f", - "name": "man facepalming", - "alpha_code": ":man_facepalming:", - "aliases": "" - }, - "1f926-1f3ff-2640": { - "output": "1f926-1f3ff-200d-2640-fe0f", - "name": "woman facepalming: dark skin tone", - "alpha_code": ":woman_facepalming_tone5:", - "aliases": ":woman_facepalming_dark_skin_tone:" - }, - "1f926-1f3fe-2640": { - "output": "1f926-1f3fe-200d-2640-fe0f", - "name": "woman facepalming: medium-dark skin tone", - "alpha_code": ":woman_facepalming_tone4:", - "aliases": ":woman_facepalming_medium_dark_skin_tone:" - }, - "1f926-1f3fd-2640": { - "output": "1f926-1f3fd-200d-2640-fe0f", - "name": "woman facepalming: medium skin tone", - "alpha_code": ":woman_facepalming_tone3:", - "aliases": ":woman_facepalming_medium_skin_tone:" - }, - "1f926-1f3fc-2640": { - "output": "1f926-1f3fc-200d-2640-fe0f", - "name": "woman facepalming: medium-light skin tone", - "alpha_code": ":woman_facepalming_tone2:", - "aliases": ":woman_facepalming_medium_light_skin_tone:" - }, - "1f926-1f3fb-2640": { - "output": "1f926-1f3fb-200d-2640-fe0f", - "name": "woman facepalming: light skin tone", - "alpha_code": ":woman_facepalming_tone1:", - "aliases": ":woman_facepalming_light_skin_tone:" - }, - "1f926-2640": { - "output": "1f926-200d-2640-fe0f", - "name": "woman facepalming", - "alpha_code": ":woman_facepalming:", - "aliases": "" - }, - "1f64e-1f3ff-2642": { - "output": "1f64e-1f3ff-200d-2642-fe0f", - "name": "man pouting: dark skin tone", - "alpha_code": ":man_pouting_tone5:", - "aliases": ":man_pouting_dark_skin_tone:" - }, - "1f64e-1f3fe-2642": { - "output": "1f64e-1f3fe-200d-2642-fe0f", - "name": "man pouting: medium-dark skin tone", - "alpha_code": ":man_pouting_tone4:", - "aliases": ":man_pouting_medium_dark_skin_tone:" - }, - "1f64e-1f3fd-2642": { - "output": "1f64e-1f3fd-200d-2642-fe0f", - "name": "man pouting: medium skin tone", - "alpha_code": ":man_pouting_tone3:", - "aliases": ":man_pouting_medium_skin_tone:" - }, - "1f64e-1f3fc-2642": { - "output": "1f64e-1f3fc-200d-2642-fe0f", - "name": "man pouting: medium-light skin tone", - "alpha_code": ":man_pouting_tone2:", - "aliases": ":man_pouting_medium_light_skin_tone:" - }, - "1f64e-1f3fb-2642": { - "output": "1f64e-1f3fb-200d-2642-fe0f", - "name": "man pouting: light skin tone", - "alpha_code": ":man_pouting_tone1:", - "aliases": ":man_pouting_light_skin_tone:" - }, - "1f64e-2642": { - "output": "1f64e-200d-2642-fe0f", - "name": "man pouting", - "alpha_code": ":man_pouting:", - "aliases": "" - }, - "1f64e-1f3ff-2640": { - "output": "1f64e-1f3ff-200d-2640-fe0f", - "name": "woman pouting: dark skin tone", - "alpha_code": ":woman_pouting_tone5:", - "aliases": ":woman_pouting_dark_skin_tone:" - }, - "1f64e-1f3fe-2640": { - "output": "1f64e-1f3fe-200d-2640-fe0f", - "name": "woman pouting: medium-dark skin tone", - "alpha_code": ":woman_pouting_tone4:", - "aliases": ":woman_pouting_medium_dark_skin_tone:" - }, - "1f64e-1f3fd-2640": { - "output": "1f64e-1f3fd-200d-2640-fe0f", - "name": "woman pouting: medium skin tone", - "alpha_code": ":woman_pouting_tone3:", - "aliases": ":woman_pouting_medium_skin_tone:" - }, - "1f64e-1f3fc-2640": { - "output": "1f64e-1f3fc-200d-2640-fe0f", - "name": "woman pouting: medium-light skin tone", - "alpha_code": ":woman_pouting_tone2:", - "aliases": ":woman_pouting_medium_light_skin_tone:" - }, - "1f64e-1f3fb-2640": { - "output": "1f64e-1f3fb-200d-2640-fe0f", - "name": "woman pouting: light skin tone", - "alpha_code": ":woman_pouting_tone1:", - "aliases": ":woman_pouting_light_skin_tone:" - }, - "1f64e-2640": { - "output": "1f64e-200d-2640-fe0f", - "name": "woman pouting", - "alpha_code": ":woman_pouting:", - "aliases": "" - }, - "1f64d-1f3ff-2642": { - "output": "1f64d-1f3ff-200d-2642-fe0f", - "name": "man frowning: dark skin tone", - "alpha_code": ":man_frowning_tone5:", - "aliases": ":man_frowning_dark_skin_tone:" - }, - "1f64d-1f3fe-2642": { - "output": "1f64d-1f3fe-200d-2642-fe0f", - "name": "man frowning: medium-dark skin tone", - "alpha_code": ":man_frowning_tone4:", - "aliases": ":man_frowning_medium_dark_skin_tone:" - }, - "1f64d-1f3fd-2642": { - "output": "1f64d-1f3fd-200d-2642-fe0f", - "name": "man frowning: medium skin tone", - "alpha_code": ":man_frowning_tone3:", - "aliases": ":man_frowning_medium_skin_tone:" - }, - "1f64d-1f3fc-2642": { - "output": "1f64d-1f3fc-200d-2642-fe0f", - "name": "man frowning: medium-light skin tone", - "alpha_code": ":man_frowning_tone2:", - "aliases": ":man_frowning_medium_light_skin_tone:" - }, - "1f64d-1f3fb-2642": { - "output": "1f64d-1f3fb-200d-2642-fe0f", - "name": "man frowning: light skin tone", - "alpha_code": ":man_frowning_tone1:", - "aliases": ":man_frowning_light_skin_tone:" - }, - "1f64d-2642": { - "output": "1f64d-200d-2642-fe0f", - "name": "man frowning", - "alpha_code": ":man_frowning:", - "aliases": "" - }, - "1f64d-1f3ff-2640": { - "output": "1f64d-1f3ff-200d-2640-fe0f", - "name": "woman frowning: dark skin tone", - "alpha_code": ":woman_frowning_tone5:", - "aliases": ":woman_frowning_dark_skin_tone:" - }, - "1f64d-1f3fe-2640": { - "output": "1f64d-1f3fe-200d-2640-fe0f", - "name": "woman frowning: medium-dark skin tone", - "alpha_code": ":woman_frowning_tone4:", - "aliases": ":woman_frowning_medium_dark_skin_tone:" - }, - "1f64d-1f3fd-2640": { - "output": "1f64d-1f3fd-200d-2640-fe0f", - "name": "woman frowning: medium skin tone", - "alpha_code": ":woman_frowning_tone3:", - "aliases": ":woman_frowning_medium_skin_tone:" - }, - "1f64d-1f3fc-2640": { - "output": "1f64d-1f3fc-200d-2640-fe0f", - "name": "woman frowning: medium-light skin tone", - "alpha_code": ":woman_frowning_tone2:", - "aliases": ":woman_frowning_medium_light_skin_tone:" - }, - "1f64d-1f3fb-2640": { - "output": "1f64d-1f3fb-200d-2640-fe0f", - "name": "woman frowning: light skin tone", - "alpha_code": ":woman_frowning_tone1:", - "aliases": ":woman_frowning_light_skin_tone:" - }, - "1f64d-2640": { - "output": "1f64d-200d-2640-fe0f", - "name": "woman frowning", - "alpha_code": ":woman_frowning:", - "aliases": "" - }, - "1f64b-1f3ff-2642": { - "output": "1f64b-1f3ff-200d-2642-fe0f", - "name": "man raising hand: dark skin tone", - "alpha_code": ":man_raising_hand_tone5:", - "aliases": ":man_raising_hand_dark_skin_tone:" - }, - "1f64b-1f3fe-2642": { - "output": "1f64b-1f3fe-200d-2642-fe0f", - "name": "man raising hand: medium-dark skin tone", - "alpha_code": ":man_raising_hand_tone4:", - "aliases": ":man_raising_hand_medium_dark_skin_tone:" - }, - "1f64b-1f3fd-2642": { - "output": "1f64b-1f3fd-200d-2642-fe0f", - "name": "man raising hand: medium skin tone", - "alpha_code": ":man_raising_hand_tone3:", - "aliases": ":man_raising_hand_medium_skin_tone:" - }, - "1f64b-1f3fc-2642": { - "output": "1f64b-1f3fc-200d-2642-fe0f", - "name": "man raising hand: medium-light skin tone", - "alpha_code": ":man_raising_hand_tone2:", - "aliases": ":man_raising_hand_medium_light_skin_tone:" - }, - "1f64b-1f3fb-2642": { - "output": "1f64b-1f3fb-200d-2642-fe0f", - "name": "man raising hand: light skin tone", - "alpha_code": ":man_raising_hand_tone1:", - "aliases": ":man_raising_hand_light_skin_tone:" - }, - "1f64b-2642": { - "output": "1f64b-200d-2642-fe0f", - "name": "man raising hand", - "alpha_code": ":man_raising_hand:", - "aliases": "" - }, - "1f64b-1f3ff-2640": { - "output": "1f64b-1f3ff-200d-2640-fe0f", - "name": "woman raising hand: dark skin tone", - "alpha_code": ":woman_raising_hand_tone5:", - "aliases": ":woman_raising_hand_dark_skin_tone:" - }, - "1f64b-1f3fe-2640": { - "output": "1f64b-1f3fe-200d-2640-fe0f", - "name": "woman raising hand: medium-dark skin tone", - "alpha_code": ":woman_raising_hand_tone4:", - "aliases": ":woman_raising_hand_medium_dark_skin_tone:" - }, - "1f64b-1f3fd-2640": { - "output": "1f64b-1f3fd-200d-2640-fe0f", - "name": "woman raising hand: medium skin tone", - "alpha_code": ":woman_raising_hand_tone3:", - "aliases": ":woman_raising_hand_medium_skin_tone:" - }, - "1f64b-1f3fc-2640": { - "output": "1f64b-1f3fc-200d-2640-fe0f", - "name": "woman raising hand: medium-light skin tone", - "alpha_code": ":woman_raising_hand_tone2:", - "aliases": ":woman_raising_hand_medium_light_skin_tone:" - }, - "1f64b-1f3fb-2640": { - "output": "1f64b-1f3fb-200d-2640-fe0f", - "name": "woman raising hand: light skin tone", - "alpha_code": ":woman_raising_hand_tone1:", - "aliases": ":woman_raising_hand_light_skin_tone:" - }, - "1f64b-2640": { - "output": "1f64b-200d-2640-fe0f", - "name": "woman raising hand", - "alpha_code": ":woman_raising_hand:", - "aliases": "" - }, - "1f647-1f3ff-2642": { - "output": "1f647-1f3ff-200d-2642-fe0f", - "name": "man bowing: dark skin tone", - "alpha_code": ":man_bowing_tone5:", - "aliases": ":man_bowing_dark_skin_tone:" - }, - "1f647-1f3fe-2642": { - "output": "1f647-1f3fe-200d-2642-fe0f", - "name": "man bowing: medium-dark skin tone", - "alpha_code": ":man_bowing_tone4:", - "aliases": ":man_bowing_medium_dark_skin_tone:" - }, - "1f647-1f3fd-2642": { - "output": "1f647-1f3fd-200d-2642-fe0f", - "name": "man bowing: medium skin tone", - "alpha_code": ":man_bowing_tone3:", - "aliases": ":man_bowing_medium_skin_tone:" - }, - "1f647-1f3fc-2642": { - "output": "1f647-1f3fc-200d-2642-fe0f", - "name": "man bowing: medium-light skin tone", - "alpha_code": ":man_bowing_tone2:", - "aliases": ":man_bowing_medium_light_skin_tone:" - }, - "1f647-1f3fb-2642": { - "output": "1f647-1f3fb-200d-2642-fe0f", - "name": "man bowing: light skin tone", - "alpha_code": ":man_bowing_tone1:", - "aliases": ":man_bowing_light_skin_tone:" - }, - "1f647-2642": { - "output": "1f647-200d-2642-fe0f", - "name": "man bowing", - "alpha_code": ":man_bowing:", - "aliases": "" - }, - "1f647-1f3ff-2640": { - "output": "1f647-1f3ff-200d-2640-fe0f", - "name": "woman bowing: dark skin tone", - "alpha_code": ":woman_bowing_tone5:", - "aliases": ":woman_bowing_dark_skin_tone:" - }, - "1f647-1f3fe-2640": { - "output": "1f647-1f3fe-200d-2640-fe0f", - "name": "woman bowing: medium-dark skin tone", - "alpha_code": ":woman_bowing_tone4:", - "aliases": ":woman_bowing_medium_dark_skin_tone:" - }, - "1f647-1f3fd-2640": { - "output": "1f647-1f3fd-200d-2640-fe0f", - "name": "woman bowing: medium skin tone", - "alpha_code": ":woman_bowing_tone3:", - "aliases": ":woman_bowing_medium_skin_tone:" - }, - "1f647-1f3fc-2640": { - "output": "1f647-1f3fc-200d-2640-fe0f", - "name": "woman bowing: medium-light skin tone", - "alpha_code": ":woman_bowing_tone2:", - "aliases": ":woman_bowing_medium_light_skin_tone:" - }, - "1f647-1f3fb-2640": { - "output": "1f647-1f3fb-200d-2640-fe0f", - "name": "woman bowing: light skin tone", - "alpha_code": ":woman_bowing_tone1:", - "aliases": ":woman_bowing_light_skin_tone:" - }, - "1f647-2640": { - "output": "1f647-200d-2640-fe0f", - "name": "woman bowing", - "alpha_code": ":woman_bowing:", - "aliases": "" - }, - "1f646-1f3ff-2642": { - "output": "1f646-1f3ff-200d-2642-fe0f", - "name": "man gesturing OK: dark skin tone", - "alpha_code": ":man_gesturing_ok_tone5:", - "aliases": ":man_gesturing_ok_dark_skin_tone:" - }, - "1f646-1f3fe-2642": { - "output": "1f646-1f3fe-200d-2642-fe0f", - "name": "man gesturing OK: medium-dark skin tone", - "alpha_code": ":man_gesturing_ok_tone4:", - "aliases": ":man_gesturing_ok_medium_dark_skin_tone:" - }, - "1f646-1f3fd-2642": { - "output": "1f646-1f3fd-200d-2642-fe0f", - "name": "man gesturing OK: medium skin tone", - "alpha_code": ":man_gesturing_ok_tone3:", - "aliases": ":man_gesturing_ok_medium_skin_tone:" - }, - "1f646-1f3fc-2642": { - "output": "1f646-1f3fc-200d-2642-fe0f", - "name": "man gesturing OK: medium-light skin tone", - "alpha_code": ":man_gesturing_ok_tone2:", - "aliases": ":man_gesturing_ok_medium_light_skin_tone:" - }, - "1f646-1f3fb-2642": { - "output": "1f646-1f3fb-200d-2642-fe0f", - "name": "man gesturing OK: light skin tone", - "alpha_code": ":man_gesturing_ok_tone1:", - "aliases": ":man_gesturing_ok_light_skin_tone:" - }, - "1f646-2642": { - "output": "1f646-200d-2642-fe0f", - "name": "man gesturing OK", - "alpha_code": ":man_gesturing_ok:", - "aliases": "" - }, - "1f646-1f3ff-2640": { - "output": "1f646-1f3ff-200d-2640-fe0f", - "name": "woman gesturing OK: dark skin tone", - "alpha_code": ":woman_gesturing_ok_tone5:", - "aliases": ":woman_gesturing_ok_dark_skin_tone:" - }, - "1f646-1f3fe-2640": { - "output": "1f646-1f3fe-200d-2640-fe0f", - "name": "woman gesturing OK: medium-dark skin tone", - "alpha_code": ":woman_gesturing_ok_tone4:", - "aliases": ":woman_gesturing_ok_medium_dark_skin_tone:" - }, - "1f646-1f3fd-2640": { - "output": "1f646-1f3fd-200d-2640-fe0f", - "name": "woman gesturing OK: medium skin tone", - "alpha_code": ":woman_gesturing_ok_tone3:", - "aliases": ":woman_gesturing_ok_medium_skin_tone:" - }, - "1f646-1f3fc-2640": { - "output": "1f646-1f3fc-200d-2640-fe0f", - "name": "woman gesturing OK: medium-light skin tone", - "alpha_code": ":woman_gesturing_ok_tone2:", - "aliases": ":woman_gesturing_ok_medium_light_skin_tone:" - }, - "1f646-1f3fb-2640": { - "output": "1f646-1f3fb-200d-2640-fe0f", - "name": "woman gesturing OK: light skin tone", - "alpha_code": ":woman_gesturing_ok_tone1:", - "aliases": ":woman_gesturing_ok_light_skin_tone:" - }, - "1f646-2640": { - "output": "1f646-200d-2640-fe0f", - "name": "woman gesturing OK", - "alpha_code": ":woman_gesturing_ok:", - "aliases": "" - }, - "1f645-1f3ff-2642": { - "output": "1f645-1f3ff-200d-2642-fe0f", - "name": "man gesturing NO: dark skin tone", - "alpha_code": ":man_gesturing_no_tone5:", - "aliases": ":man_gesturing_no_dark_skin_tone:" - }, - "1f645-1f3fe-2642": { - "output": "1f645-1f3fe-200d-2642-fe0f", - "name": "man gesturing NO: medium-dark skin tone", - "alpha_code": ":man_gesturing_no_tone4:", - "aliases": ":man_gesturing_no_medium_dark_skin_tone:" - }, - "1f645-1f3fd-2642": { - "output": "1f645-1f3fd-200d-2642-fe0f", - "name": "man gesturing NO: medium skin tone", - "alpha_code": ":man_gesturing_no_tone3:", - "aliases": ":man_gesturing_no_medium_skin_tone:" - }, - "1f645-1f3fc-2642": { - "output": "1f645-1f3fc-200d-2642-fe0f", - "name": "man gesturing NO: medium-light skin tone", - "alpha_code": ":man_gesturing_no_tone2:", - "aliases": ":man_gesturing_no_medium_light_skin_tone:" - }, - "1f645-1f3fb-2642": { - "output": "1f645-1f3fb-200d-2642-fe0f", - "name": "man gesturing NO: light skin tone", - "alpha_code": ":man_gesturing_no_tone1:", - "aliases": ":man_gesturing_no_light_skin_tone:" - }, - "1f645-2642": { - "output": "1f645-200d-2642-fe0f", - "name": "man gesturing NO", - "alpha_code": ":man_gesturing_no:", - "aliases": "" - }, - "1f645-1f3ff-2640": { - "output": "1f645-1f3ff-200d-2640-fe0f", - "name": "woman gesturing NO: dark skin tone", - "alpha_code": ":woman_gesturing_no_tone5:", - "aliases": ":woman_gesturing_no_dark_skin_tone:" - }, - "1f645-1f3fe-2640": { - "output": "1f645-1f3fe-200d-2640-fe0f", - "name": "woman gesturing NO: medium-dark skin tone", - "alpha_code": ":woman_gesturing_no_tone4:", - "aliases": ":woman_gesturing_no_medium_dark_skin_tone:" - }, - "1f645-1f3fd-2640": { - "output": "1f645-1f3fd-200d-2640-fe0f", - "name": "woman gesturing NO: medium skin tone", - "alpha_code": ":woman_gesturing_no_tone3:", - "aliases": ":woman_gesturing_no_medium_skin_tone:" - }, - "1f645-1f3fc-2640": { - "output": "1f645-1f3fc-200d-2640-fe0f", - "name": "woman gesturing NO: medium-light skin tone", - "alpha_code": ":woman_gesturing_no_tone2:", - "aliases": ":woman_gesturing_no_medium_light_skin_tone:" - }, - "1f645-1f3fb-2640": { - "output": "1f645-1f3fb-200d-2640-fe0f", - "name": "woman gesturing NO: light skin tone", - "alpha_code": ":woman_gesturing_no_tone1:", - "aliases": ":woman_gesturing_no_light_skin_tone:" - }, - "1f645-2640": { - "output": "1f645-200d-2640-fe0f", - "name": "woman gesturing NO", - "alpha_code": ":woman_gesturing_no:", - "aliases": "" - }, - "1f487-1f3ff-2642": { - "output": "1f487-1f3ff-200d-2642-fe0f", - "name": "man getting haircut: dark skin tone", - "alpha_code": ":man_getting_haircut_tone5:", - "aliases": ":man_getting_haircut_dark_skin_tone:" - }, - "1f487-1f3fe-2642": { - "output": "1f487-1f3fe-200d-2642-fe0f", - "name": "man getting haircut: medium-dark skin tone", - "alpha_code": ":man_getting_haircut_tone4:", - "aliases": ":man_getting_haircut_medium_dark_skin_tone:" - }, - "1f487-1f3fd-2642": { - "output": "1f487-1f3fd-200d-2642-fe0f", - "name": "man getting haircut: medium skin tone", - "alpha_code": ":man_getting_haircut_tone3:", - "aliases": ":man_getting_haircut_medium_skin_tone:" - }, - "1f487-1f3fc-2642": { - "output": "1f487-1f3fc-200d-2642-fe0f", - "name": "man getting haircut: medium-light skin tone", - "alpha_code": ":man_getting_haircut_tone2:", - "aliases": ":man_getting_haircut_medium_light_skin_tone:" - }, - "1f487-1f3fb-2642": { - "output": "1f487-1f3fb-200d-2642-fe0f", - "name": "man getting haircut: light skin tone", - "alpha_code": ":man_getting_haircut_tone1:", - "aliases": ":man_getting_haircut_light_skin_tone:" - }, - "1f487-2642": { - "output": "1f487-200d-2642-fe0f", - "name": "man getting haircut", - "alpha_code": ":man_getting_haircut:", - "aliases": "" - }, - "1f487-1f3ff-2640": { - "output": "1f487-1f3ff-200d-2640-fe0f", - "name": "woman getting haircut: dark skin tone", - "alpha_code": ":woman_getting_haircut_tone5:", - "aliases": ":woman_getting_haircut_dark_skin_tone:" - }, - "1f487-1f3fe-2640": { - "output": "1f487-1f3fe-200d-2640-fe0f", - "name": "woman getting haircut: medium-dark skin tone", - "alpha_code": ":woman_getting_haircut_tone4:", - "aliases": ":woman_getting_haircut_medium_dark_skin_tone:" - }, - "1f487-1f3fd-2640": { - "output": "1f487-1f3fd-200d-2640-fe0f", - "name": "woman getting haircut: medium skin tone", - "alpha_code": ":woman_getting_haircut_tone3:", - "aliases": ":woman_getting_haircut_medium_skin_tone:" - }, - "1f487-1f3fc-2640": { - "output": "1f487-1f3fc-200d-2640-fe0f", - "name": "woman getting haircut: medium-light skin tone", - "alpha_code": ":woman_getting_haircut_tone2:", - "aliases": ":woman_getting_haircut_medium_light_skin_tone:" - }, - "1f487-1f3fb-2640": { - "output": "1f487-1f3fb-200d-2640-fe0f", - "name": "woman getting haircut: light skin tone", - "alpha_code": ":woman_getting_haircut_tone1:", - "aliases": ":woman_getting_haircut_light_skin_tone:" - }, - "1f487-2640": { - "output": "1f487-200d-2640-fe0f", - "name": "woman getting haircut", - "alpha_code": ":woman_getting_haircut:", - "aliases": "" - }, - "1f486-1f3ff-2642": { - "output": "1f486-1f3ff-200d-2642-fe0f", - "name": "man getting massage: dark skin tone", - "alpha_code": ":man_getting_face_massage_tone5:", - "aliases": ":man_getting_face_massage_dark_skin_tone:" - }, - "1f486-1f3fe-2642": { - "output": "1f486-1f3fe-200d-2642-fe0f", - "name": "man getting massage: medium-dark skin tone", - "alpha_code": ":man_getting_face_massage_tone4:", - "aliases": ":man_getting_face_massage_medium_dark_skin_tone:" - }, - "1f486-1f3fd-2642": { - "output": "1f486-1f3fd-200d-2642-fe0f", - "name": "man getting massage: medium skin tone", - "alpha_code": ":man_getting_face_massage_tone3:", - "aliases": ":man_getting_face_massage_medium_skin_tone:" - }, - "1f486-1f3fc-2642": { - "output": "1f486-1f3fc-200d-2642-fe0f", - "name": "man getting massage: medium-light skin tone", - "alpha_code": ":man_getting_face_massage_tone2:", - "aliases": ":man_getting_face_massage_medium_light_skin_tone:" - }, - "1f486-1f3fb-2642": { - "output": "1f486-1f3fb-200d-2642-fe0f", - "name": "man getting massage: light skin tone", - "alpha_code": ":man_getting_face_massage_tone1:", - "aliases": ":man_getting_face_massage_light_skin_tone:" - }, - "1f486-2642": { - "output": "1f486-200d-2642-fe0f", - "name": "man getting massage", - "alpha_code": ":man_getting_face_massage:", - "aliases": "" - }, - "1f486-1f3ff-2640": { - "output": "1f486-1f3ff-200d-2640-fe0f", - "name": "woman getting massage: dark skin tone", - "alpha_code": ":woman_getting_face_massage_tone5:", - "aliases": ":woman_getting_face_massage_dark_skin_tone:" - }, - "1f486-1f3fe-2640": { - "output": "1f486-1f3fe-200d-2640-fe0f", - "name": "woman getting massage: medium-dark skin tone", - "alpha_code": ":woman_getting_face_massage_tone4:", - "aliases": ":woman_getting_face_massage_medium_dark_skin_tone:" - }, - "1f486-1f3fd-2640": { - "output": "1f486-1f3fd-200d-2640-fe0f", - "name": "woman getting massage: medium skin tone", - "alpha_code": ":woman_getting_face_massage_tone3:", - "aliases": ":woman_getting_face_massage_medium_skin_tone:" - }, - "1f486-1f3fc-2640": { - "output": "1f486-1f3fc-200d-2640-fe0f", - "name": "woman getting massage: medium-light skin tone", - "alpha_code": ":woman_getting_face_massage_tone2:", - "aliases": ":woman_getting_face_massage_medium_light_skin_tone:" - }, - "1f486-1f3fb-2640": { - "output": "1f486-1f3fb-200d-2640-fe0f", - "name": "woman getting massage: light skin tone", - "alpha_code": ":woman_getting_face_massage_tone1:", - "aliases": ":woman_getting_face_massage_light_skin_tone:" - }, - "1f486-2640": { - "output": "1f486-200d-2640-fe0f", - "name": "woman getting massage", - "alpha_code": ":woman_getting_face_massage:", - "aliases": "" - }, - "1f481-1f3ff-2642": { - "output": "1f481-1f3ff-200d-2642-fe0f", - "name": "man tipping hand: dark skin tone", - "alpha_code": ":man_tipping_hand_tone5:", - "aliases": ":man_tipping_hand_dark_skin_tone:" - }, - "1f481-1f3fe-2642": { - "output": "1f481-1f3fe-200d-2642-fe0f", - "name": "man tipping hand: medium-dark skin tone", - "alpha_code": ":man_tipping_hand_tone4:", - "aliases": ":man_tipping_hand_medium_dark_skin_tone:" - }, - "1f481-1f3fd-2642": { - "output": "1f481-1f3fd-200d-2642-fe0f", - "name": "man tipping hand: medium skin tone", - "alpha_code": ":man_tipping_hand_tone3:", - "aliases": ":man_tipping_hand_medium_skin_tone:" - }, - "1f481-1f3fc-2642": { - "output": "1f481-1f3fc-200d-2642-fe0f", - "name": "man tipping hand: medium-light skin tone", - "alpha_code": ":man_tipping_hand_tone2:", - "aliases": ":man_tipping_hand_medium_light_skin_tone:" - }, - "1f481-1f3fb-2642": { - "output": "1f481-1f3fb-200d-2642-fe0f", - "name": "man tipping hand: light skin tone", - "alpha_code": ":man_tipping_hand_tone1:", - "aliases": ":man_tipping_hand_light_skin_tone:" - }, - "1f481-2642": { - "output": "1f481-200d-2642-fe0f", - "name": "man tipping hand", - "alpha_code": ":man_tipping_hand:", - "aliases": "" - }, - "1f481-1f3ff-2640": { - "output": "1f481-1f3ff-200d-2640-fe0f", - "name": "woman tipping hand: dark skin tone", - "alpha_code": ":woman_tipping_hand_tone5:", - "aliases": ":woman_tipping_hand_dark_skin_tone:" - }, - "1f481-1f3fe-2640": { - "output": "1f481-1f3fe-200d-2640-fe0f", - "name": "woman tipping hand: medium-dark skin tone", - "alpha_code": ":woman_tipping_hand_tone4:", - "aliases": ":woman_tipping_hand_medium_dark_skin_tone:" - }, - "1f481-1f3fd-2640": { - "output": "1f481-1f3fd-200d-2640-fe0f", - "name": "woman tipping hand: medium skin tone", - "alpha_code": ":woman_tipping_hand_tone3:", - "aliases": ":woman_tipping_hand_medium_skin_tone:" - }, - "1f481-1f3fc-2640": { - "output": "1f481-1f3fc-200d-2640-fe0f", - "name": "woman tipping hand: medium-light skin tone", - "alpha_code": ":woman_tipping_hand_tone2:", - "aliases": ":woman_tipping_hand_medium_light_skin_tone:" - }, - "1f481-1f3fb-2640": { - "output": "1f481-1f3fb-200d-2640-fe0f", - "name": "woman tipping hand: light skin tone", - "alpha_code": ":woman_tipping_hand_tone1:", - "aliases": ":woman_tipping_hand_light_skin_tone:" - }, - "1f481-2640": { - "output": "1f481-200d-2640-fe0f", - "name": "woman tipping hand", - "alpha_code": ":woman_tipping_hand:", - "aliases": "" - }, - "1f471-1f3ff-2642": { - "output": "1f471-1f3ff-200d-2642-fe0f", - "name": "blond-haired man: dark skin tone", - "alpha_code": ":blond-haired_man_tone5:", - "aliases": ":blond-haired_man_dark_skin_tone:" - }, - "1f471-1f3fe-2642": { - "output": "1f471-1f3fe-200d-2642-fe0f", - "name": "blond-haired man: medium-dark skin tone", - "alpha_code": ":blond-haired_man_tone4:", - "aliases": ":blond-haired_man_medium_dark_skin_tone:" - }, - "1f471-1f3fd-2642": { - "output": "1f471-1f3fd-200d-2642-fe0f", - "name": "blond-haired man: medium skin tone", - "alpha_code": ":blond-haired_man_tone3:", - "aliases": ":blond-haired_man_medium_skin_tone:" - }, - "1f471-1f3fc-2642": { - "output": "1f471-1f3fc-200d-2642-fe0f", - "name": "blond-haired man: medium-light skin tone", - "alpha_code": ":blond-haired_man_tone2:", - "aliases": ":blond-haired_man_medium_light_skin_tone:" - }, - "1f471-1f3fb-2642": { - "output": "1f471-1f3fb-200d-2642-fe0f", - "name": "blond-haired man: light skin tone", - "alpha_code": ":blond-haired_man_tone1:", - "aliases": ":blond-haired_man_light_skin_tone:" - }, - "1f471-2642": { - "output": "1f471-200d-2642-fe0f", - "name": "blond-haired man", - "alpha_code": ":blond-haired_man:", - "aliases": "" - }, - "1f471-1f3ff-2640": { - "output": "1f471-1f3ff-200d-2640-fe0f", - "name": "blond-haired woman: dark skin tone", - "alpha_code": ":blond-haired_woman_tone5:", - "aliases": ":blond-haired_woman_dark_skin_tone:" - }, - "1f471-1f3fe-2640": { - "output": "1f471-1f3fe-200d-2640-fe0f", - "name": "blond-haired woman: medium-dark skin tone", - "alpha_code": ":blond-haired_woman_tone4:", - "aliases": ":blond-haired_woman_medium_dark_skin_tone:" - }, - "1f471-1f3fd-2640": { - "output": "1f471-1f3fd-200d-2640-fe0f", - "name": "blond-haired woman: medium skin tone", - "alpha_code": ":blond-haired_woman_tone3:", - "aliases": ":blond-haired_woman_medium_skin_tone:" - }, - "1f471-1f3fc-2640": { - "output": "1f471-1f3fc-200d-2640-fe0f", - "name": "blond-haired woman: medium-light skin tone", - "alpha_code": ":blond-haired_woman_tone2:", - "aliases": ":blond-haired_woman_medium_light_skin_tone:" - }, - "1f471-1f3fb-2640": { - "output": "1f471-1f3fb-200d-2640-fe0f", - "name": "blond-haired woman: light skin tone", - "alpha_code": ":blond-haired_woman_tone1:", - "aliases": ":blond-haired_woman_light_skin_tone:" - }, - "1f471-2640": { - "output": "1f471-200d-2640-fe0f", - "name": "blond-haired woman", - "alpha_code": ":blond-haired_woman:", - "aliases": "" - }, - "1f473-1f3ff-2642": { - "output": "1f473-1f3ff-200d-2642-fe0f", - "name": "man wearing turban: dark skin tone", - "alpha_code": ":man_wearing_turban_tone5:", - "aliases": ":man_wearing_turban_dark_skin_tone:" - }, - "1f473-1f3fe-2642": { - "output": "1f473-1f3fe-200d-2642-fe0f", - "name": "man wearing turban: medium-dark skin tone", - "alpha_code": ":man_wearing_turban_tone4:", - "aliases": ":man_wearing_turban_medium_dark_skin_tone:" - }, - "1f473-1f3fd-2642": { - "output": "1f473-1f3fd-200d-2642-fe0f", - "name": "man wearing turban: medium skin tone", - "alpha_code": ":man_wearing_turban_tone3:", - "aliases": ":man_wearing_turban_medium_skin_tone:" - }, - "1f473-1f3fc-2642": { - "output": "1f473-1f3fc-200d-2642-fe0f", - "name": "man wearing turban: medium-light skin tone", - "alpha_code": ":man_wearing_turban_tone2:", - "aliases": ":man_wearing_turban_medium_light_skin_tone:" - }, - "1f473-1f3fb-2642": { - "output": "1f473-1f3fb-200d-2642-fe0f", - "name": "man wearing turban: light skin tone", - "alpha_code": ":man_wearing_turban_tone1:", - "aliases": ":man_wearing_turban_light_skin_tone:" - }, - "1f473-2642": { - "output": "1f473-200d-2642-fe0f", - "name": "man wearing turban", - "alpha_code": ":man_wearing_turban:", - "aliases": "" - }, - "1f473-1f3ff-2640": { - "output": "1f473-1f3ff-200d-2640-fe0f", - "name": "woman wearing turban: dark skin tone", - "alpha_code": ":woman_wearing_turban_tone5:", - "aliases": ":woman_wearing_turban_dark_skin_tone:" - }, - "1f473-1f3fe-2640": { - "output": "1f473-1f3fe-200d-2640-fe0f", - "name": "woman wearing turban: medium-dark skin tone", - "alpha_code": ":woman_wearing_turban_tone4:", - "aliases": ":woman_wearing_turban_medium_dark_skin_tone:" - }, - "1f473-1f3fd-2640": { - "output": "1f473-1f3fd-200d-2640-fe0f", - "name": "woman wearing turban: medium skin tone", - "alpha_code": ":woman_wearing_turban_tone3:", - "aliases": ":woman_wearing_turban_medium_skin_tone:" - }, - "1f473-1f3fc-2640": { - "output": "1f473-1f3fc-200d-2640-fe0f", - "name": "woman wearing turban: medium-light skin tone", - "alpha_code": ":woman_wearing_turban_tone2:", - "aliases": ":woman_wearing_turban_medium_light_skin_tone:" - }, - "1f473-1f3fb-2640": { - "output": "1f473-1f3fb-200d-2640-fe0f", - "name": "woman wearing turban: light skin tone", - "alpha_code": ":woman_wearing_turban_tone1:", - "aliases": ":woman_wearing_turban_light_skin_tone:" - }, - "1f473-2640": { - "output": "1f473-200d-2640-fe0f", - "name": "woman wearing turban", - "alpha_code": ":woman_wearing_turban:", - "aliases": "" - }, - "1f482-1f3ff-2642": { - "output": "1f482-1f3ff-200d-2642-fe0f", - "name": "man guard: dark skin tone", - "alpha_code": ":man_guard_tone5:", - "aliases": ":man_guard_dark_skin_tone:" - }, - "1f482-1f3fe-2642": { - "output": "1f482-1f3fe-200d-2642-fe0f", - "name": "man guard: medium-dark skin tone", - "alpha_code": ":man_guard_tone4:", - "aliases": ":man_guard_medium_dark_skin_tone:" - }, - "1f482-1f3fd-2642": { - "output": "1f482-1f3fd-200d-2642-fe0f", - "name": "man guard: medium skin tone", - "alpha_code": ":man_guard_tone3:", - "aliases": ":man_guard_medium_skin_tone:" - }, - "1f482-1f3fc-2642": { - "output": "1f482-1f3fc-200d-2642-fe0f", - "name": "man guard: medium-light skin tone", - "alpha_code": ":man_guard_tone2:", - "aliases": ":man_guard_medium_light_skin_tone:" - }, - "1f482-1f3fb-2642": { - "output": "1f482-1f3fb-200d-2642-fe0f", - "name": "man guard: light skin tone", - "alpha_code": ":man_guard_tone1:", - "aliases": ":man_guard_light_skin_tone:" - }, - "1f482-2642": { - "output": "1f482-200d-2642-fe0f", - "name": "man guard", - "alpha_code": ":man_guard:", - "aliases": "" - }, - "1f482-1f3ff-2640": { - "output": "1f482-1f3ff-200d-2640-fe0f", - "name": "woman guard: dark skin tone", - "alpha_code": ":woman_guard_tone5:", - "aliases": ":woman_guard_dark_skin_tone:" - }, - "1f482-1f3fe-2640": { - "output": "1f482-1f3fe-200d-2640-fe0f", - "name": "woman guard: medium-dark skin tone", - "alpha_code": ":woman_guard_tone4:", - "aliases": ":woman_guard_medium_dark_skin_tone:" - }, - "1f482-1f3fd-2640": { - "output": "1f482-1f3fd-200d-2640-fe0f", - "name": "woman guard: medium skin tone", - "alpha_code": ":woman_guard_tone3:", - "aliases": ":woman_guard_medium_skin_tone:" - }, - "1f482-1f3fc-2640": { - "output": "1f482-1f3fc-200d-2640-fe0f", - "name": "woman guard: medium-light skin tone", - "alpha_code": ":woman_guard_tone2:", - "aliases": ":woman_guard_medium_light_skin_tone:" - }, - "1f482-1f3fb-2640": { - "output": "1f482-1f3fb-200d-2640-fe0f", - "name": "woman guard: light skin tone", - "alpha_code": ":woman_guard_tone1:", - "aliases": ":woman_guard_light_skin_tone:" - }, - "1f482-2640": { - "output": "1f482-200d-2640-fe0f", - "name": "woman guard", - "alpha_code": ":woman_guard:", - "aliases": "" - }, - "1f575-1f3ff-2642": { - "output": "1f575-1f3ff-200d-2642-fe0f", - "name": "man detective: dark skin tone", - "alpha_code": ":man_detective_tone5:", - "aliases": ":man_detective_dark_skin_tone:" - }, - "1f575-1f3fe-2642": { - "output": "1f575-1f3fe-200d-2642-fe0f", - "name": "man detective: medium-dark skin tone", - "alpha_code": ":man_detective_tone4:", - "aliases": ":man_detective_medium_dark_skin_tone:" - }, - "1f575-1f3fd-2642": { - "output": "1f575-1f3fd-200d-2642-fe0f", - "name": "man detective: medium skin tone", - "alpha_code": ":man_detective_tone3:", - "aliases": ":man_detective_medium_skin_tone:" - }, - "1f575-1f3fc-2642": { - "output": "1f575-1f3fc-200d-2642-fe0f", - "name": "man detective: medium-light skin tone", - "alpha_code": ":man_detective_tone2:", - "aliases": ":man_detective_medium_light_skin_tone:" - }, - "1f575-1f3fb-2642": { - "output": "1f575-1f3fb-200d-2642-fe0f", - "name": "man detective: light skin tone", - "alpha_code": ":man_detective_tone1:", - "aliases": ":man_detective_light_skin_tone:" - }, - "1f575-2642": { - "output": "1f575-fe0f-200d-2642-fe0f", - "name": "man detective", - "alpha_code": ":man_detective:", - "aliases": "" - }, - "1f575-1f3ff-2640": { - "output": "1f575-1f3ff-200d-2640-fe0f", - "name": "woman detective: dark skin tone", - "alpha_code": ":woman_detective_tone5:", - "aliases": ":woman_detective_dark_skin_tone:" - }, - "1f575-1f3fe-2640": { - "output": "1f575-1f3fe-200d-2640-fe0f", - "name": "woman detective: medium-dark skin tone", - "alpha_code": ":woman_detective_tone4:", - "aliases": ":woman_detective_medium_dark_skin_tone:" - }, - "1f575-1f3fd-2640": { - "output": "1f575-1f3fd-200d-2640-fe0f", - "name": "woman detective: medium skin tone", - "alpha_code": ":woman_detective_tone3:", - "aliases": ":woman_detective_medium_skin_tone:" - }, - "1f575-1f3fc-2640": { - "output": "1f575-1f3fc-200d-2640-fe0f", - "name": "woman detective: medium-light skin tone", - "alpha_code": ":woman_detective_tone2:", - "aliases": ":woman_detective_medium_light_skin_tone:" - }, - "1f575-1f3fb-2640": { - "output": "1f575-1f3fb-200d-2640-fe0f", - "name": "woman detective: light skin tone", - "alpha_code": ":woman_detective_tone1:", - "aliases": ":woman_detective_light_skin_tone:" - }, - "1f575-2640": { - "output": "1f575-fe0f-200d-2640-fe0f", - "name": "woman detective", - "alpha_code": ":woman_detective:", - "aliases": "" - }, - "1f477-1f3ff-2642": { - "output": "1f477-1f3ff-200d-2642-fe0f", - "name": "man construction worker: dark skin tone", - "alpha_code": ":man_construction_worker_tone5:", - "aliases": ":man_construction_worker_dark_skin_tone:" - }, - "1f477-1f3fe-2642": { - "output": "1f477-1f3fe-200d-2642-fe0f", - "name": "man construction worker: medium-dark skin tone", - "alpha_code": ":man_construction_worker_tone4:", - "aliases": ":man_construction_worker_medium_dark_skin_tone:" - }, - "1f477-1f3fd-2642": { - "output": "1f477-1f3fd-200d-2642-fe0f", - "name": "man construction worker: medium skin tone", - "alpha_code": ":man_construction_worker_tone3:", - "aliases": ":man_construction_worker_medium_skin_tone:" - }, - "1f477-1f3fc-2642": { - "output": "1f477-1f3fc-200d-2642-fe0f", - "name": "man construction worker: medium-light skin tone", - "alpha_code": ":man_construction_worker_tone2:", - "aliases": ":man_construction_worker_medium_light_skin_tone:" - }, - "1f477-1f3fb-2642": { - "output": "1f477-1f3fb-200d-2642-fe0f", - "name": "man construction worker: light skin tone", - "alpha_code": ":man_construction_worker_tone1:", - "aliases": ":man_construction_worker_light_skin_tone:" - }, - "1f477-2642": { - "output": "1f477-200d-2642-fe0f", - "name": "man construction worker", - "alpha_code": ":man_construction_worker:", - "aliases": "" - }, - "1f477-1f3ff-2640": { - "output": "1f477-1f3ff-200d-2640-fe0f", - "name": "woman construction worker: dark skin tone", - "alpha_code": ":woman_construction_worker_tone5:", - "aliases": ":woman_construction_worker_dark_skin_tone:" - }, - "1f477-1f3fe-2640": { - "output": "1f477-1f3fe-200d-2640-fe0f", - "name": "woman construction worker: medium-dark skin tone", - "alpha_code": ":woman_construction_worker_tone4:", - "aliases": ":woman_construction_worker_medium_dark_skin_tone:" - }, - "1f477-1f3fd-2640": { - "output": "1f477-1f3fd-200d-2640-fe0f", - "name": "woman construction worker: medium skin tone", - "alpha_code": ":woman_construction_worker_tone3:", - "aliases": ":woman_construction_worker_medium_skin_tone:" - }, - "1f477-1f3fc-2640": { - "output": "1f477-1f3fc-200d-2640-fe0f", - "name": "woman construction worker: medium-light skin tone", - "alpha_code": ":woman_construction_worker_tone2:", - "aliases": ":woman_construction_worker_medium_light_skin_tone:" - }, - "1f477-1f3fb-2640": { - "output": "1f477-1f3fb-200d-2640-fe0f", - "name": "woman construction worker: light skin tone", - "alpha_code": ":woman_construction_worker_tone1:", - "aliases": ":woman_construction_worker_light_skin_tone:" - }, - "1f477-2640": { - "output": "1f477-200d-2640-fe0f", - "name": "woman construction worker", - "alpha_code": ":woman_construction_worker:", - "aliases": "" - }, - "1f46e-1f3ff-2642": { - "output": "1f46e-1f3ff-200d-2642-fe0f", - "name": "man police officer: dark skin tone", - "alpha_code": ":man_police_officer_tone5:", - "aliases": ":man_police_officer_dark_skin_tone:" - }, - "1f46e-1f3fe-2642": { - "output": "1f46e-1f3fe-200d-2642-fe0f", - "name": "man police officer: medium-dark skin tone", - "alpha_code": ":man_police_officer_tone4:", - "aliases": ":man_police_officer_medium_dark_skin_tone:" - }, - "1f46e-1f3fd-2642": { - "output": "1f46e-1f3fd-200d-2642-fe0f", - "name": "man police officer: medium skin tone", - "alpha_code": ":man_police_officer_tone3:", - "aliases": ":man_police_officer_medium_skin_tone:" - }, - "1f46e-1f3fc-2642": { - "output": "1f46e-1f3fc-200d-2642-fe0f", - "name": "man police officer: medium-light skin tone", - "alpha_code": ":man_police_officer_tone2:", - "aliases": ":man_police_officer_medium_light_skin_tone:" - }, - "1f46e-1f3fb-2642": { - "output": "1f46e-1f3fb-200d-2642-fe0f", - "name": "man police officer: light skin tone", - "alpha_code": ":man_police_officer_tone1:", - "aliases": ":man_police_officer_light_skin_tone:" - }, - "1f46e-2642": { - "output": "1f46e-200d-2642-fe0f", - "name": "man police officer", - "alpha_code": ":man_police_officer:", - "aliases": "" - }, - "1f46e-1f3ff-2640": { - "output": "1f46e-1f3ff-200d-2640-fe0f", - "name": "woman police officer: dark skin tone", - "alpha_code": ":woman_police_officer_tone5:", - "aliases": ":woman_police_officer_dark_skin_tone:" - }, - "1f46e-1f3fe-2640": { - "output": "1f46e-1f3fe-200d-2640-fe0f", - "name": "woman police officer: medium-dark skin tone", - "alpha_code": ":woman_police_officer_tone4:", - "aliases": ":woman_police_officer_medium_dark_skin_tone:" - }, - "1f46e-1f3fd-2640": { - "output": "1f46e-1f3fd-200d-2640-fe0f", - "name": "woman police officer: medium skin tone", - "alpha_code": ":woman_police_officer_tone3:", - "aliases": ":woman_police_officer_medium_skin_tone:" - }, - "1f46e-1f3fc-2640": { - "output": "1f46e-1f3fc-200d-2640-fe0f", - "name": "woman police officer: medium-light skin tone", - "alpha_code": ":woman_police_officer_tone2:", - "aliases": ":woman_police_officer_medium_light_skin_tone:" - }, - "1f46e-1f3fb-2640": { - "output": "1f46e-1f3fb-200d-2640-fe0f", - "name": "woman police officer: light skin tone", - "alpha_code": ":woman_police_officer_tone1:", - "aliases": ":woman_police_officer_light_skin_tone:" - }, - "1f46e-2640": { - "output": "1f46e-200d-2640-fe0f", - "name": "woman police officer", - "alpha_code": ":woman_police_officer:", - "aliases": "" - }, - "1f468-1f3ff-1f4bb": { - "output": "1f468-1f3ff-200d-1f4bb", - "name": "man technologist: dark skin tone", - "alpha_code": ":man_technologist_tone5:", - "aliases": ":man_technologist_dark_skin_tone:" - }, - "1f468-1f3fe-1f4bb": { - "output": "1f468-1f3fe-200d-1f4bb", - "name": "man technologist: medium-dark skin tone", - "alpha_code": ":man_technologist_tone4:", - "aliases": ":man_technologist_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f4bb": { - "output": "1f468-1f3fd-200d-1f4bb", - "name": "man technologist: medium skin tone", - "alpha_code": ":man_technologist_tone3:", - "aliases": ":man_technologist_medium_skin_tone:" - }, - "1f468-1f3fc-1f4bb": { - "output": "1f468-1f3fc-200d-1f4bb", - "name": "man technologist: medium-light skin tone", - "alpha_code": ":man_technologist_tone2:", - "aliases": ":man_technologist_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f4bb": { - "output": "1f468-1f3fb-200d-1f4bb", - "name": "man technologist: light skin tone", - "alpha_code": ":man_technologist_tone1:", - "aliases": ":man_technologist_light_skin_tone:" - }, - "1f468-1f4bb": { - "output": "1f468-200d-1f4bb", - "name": "man technologist", - "alpha_code": ":man_technologist:", - "aliases": "" - }, - "1f469-1f3ff-1f4bb": { - "output": "1f469-1f3ff-200d-1f4bb", - "name": "woman technologist: dark skin tone", - "alpha_code": ":woman_technologist_tone5:", - "aliases": ":woman_technologist_dark_skin_tone:" - }, - "1f469-1f3fe-1f4bb": { - "output": "1f469-1f3fe-200d-1f4bb", - "name": "woman technologist: medium-dark skin tone", - "alpha_code": ":woman_technologist_tone4:", - "aliases": ":woman_technologist_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f4bb": { - "output": "1f469-1f3fd-200d-1f4bb", - "name": "woman technologist: medium skin tone", - "alpha_code": ":woman_technologist_tone3:", - "aliases": ":woman_technologist_medium_skin_tone:" - }, - "1f469-1f3fc-1f4bb": { - "output": "1f469-1f3fc-200d-1f4bb", - "name": "woman technologist: medium-light skin tone", - "alpha_code": ":woman_technologist_tone2:", - "aliases": ":woman_technologist_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f4bb": { - "output": "1f469-1f3fb-200d-1f4bb", - "name": "woman technologist: light skin tone", - "alpha_code": ":woman_technologist_tone1:", - "aliases": ":woman_technologist_light_skin_tone:" - }, - "1f469-1f4bb": { - "output": "1f469-200d-1f4bb", - "name": "woman technologist", - "alpha_code": ":woman_technologist:", - "aliases": "" - }, - "1f468-1f3ff-1f3eb": { - "output": "1f468-1f3ff-200d-1f3eb", - "name": "man teacher: dark skin tone", - "alpha_code": ":man_teacher_tone5:", - "aliases": ":man_teacher_dark_skin_tone:" - }, - "1f468-1f3fe-1f3eb": { - "output": "1f468-1f3fe-200d-1f3eb", - "name": "man teacher: medium-dark skin tone", - "alpha_code": ":man_teacher_tone4:", - "aliases": ":man_teacher_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f3eb": { - "output": "1f468-1f3fd-200d-1f3eb", - "name": "man teacher: medium skin tone", - "alpha_code": ":man_teacher_tone3:", - "aliases": ":man_teacher_medium_skin_tone:" - }, - "1f468-1f3fc-1f3eb": { - "output": "1f468-1f3fc-200d-1f3eb", - "name": "man teacher: medium-light skin tone", - "alpha_code": ":man_teacher_tone2:", - "aliases": ":man_teacher_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f3eb": { - "output": "1f468-1f3fb-200d-1f3eb", - "name": "man teacher: light skin tone", - "alpha_code": ":man_teacher_tone1:", - "aliases": ":man_teacher_light_skin_tone:" - }, - "1f468-1f3eb": { - "output": "1f468-200d-1f3eb", - "name": "man teacher", - "alpha_code": ":man_teacher:", - "aliases": "" - }, - "1f469-1f3ff-1f3eb": { - "output": "1f469-1f3ff-200d-1f3eb", - "name": "woman teacher: dark skin tone", - "alpha_code": ":woman_teacher_tone5:", - "aliases": ":woman_teacher_dark_skin_tone:" - }, - "1f469-1f3fe-1f3eb": { - "output": "1f469-1f3fe-200d-1f3eb", - "name": "woman teacher: medium-dark skin tone", - "alpha_code": ":woman_teacher_tone4:", - "aliases": ":woman_teacher_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f3eb": { - "output": "1f469-1f3fd-200d-1f3eb", - "name": "woman teacher: medium skin tone", - "alpha_code": ":woman_teacher_tone3:", - "aliases": ":woman_teacher_medium_skin_tone:" - }, - "1f469-1f3fc-1f3eb": { - "output": "1f469-1f3fc-200d-1f3eb", - "name": "woman teacher: medium-light skin tone", - "alpha_code": ":woman_teacher_tone2:", - "aliases": ":woman_teacher_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f3eb": { - "output": "1f469-1f3fb-200d-1f3eb", - "name": "woman teacher: light skin tone", - "alpha_code": ":woman_teacher_tone1:", - "aliases": ":woman_teacher_light_skin_tone:" - }, - "1f469-1f3eb": { - "output": "1f469-200d-1f3eb", - "name": "woman teacher", - "alpha_code": ":woman_teacher:", - "aliases": "" - }, - "1f468-1f3ff-1f393": { - "output": "1f468-1f3ff-200d-1f393", - "name": "man student: dark skin tone", - "alpha_code": ":man_student_tone5:", - "aliases": ":man_student_dark_skin_tone:" - }, - "1f468-1f3fe-1f393": { - "output": "1f468-1f3fe-200d-1f393", - "name": "man student: medium-dark skin tone", - "alpha_code": ":man_student_tone4:", - "aliases": ":man_student_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f393": { - "output": "1f468-1f3fd-200d-1f393", - "name": "man student: medium skin tone", - "alpha_code": ":man_student_tone3:", - "aliases": ":man_student_medium_skin_tone:" - }, - "1f468-1f3fc-1f393": { - "output": "1f468-1f3fc-200d-1f393", - "name": "man student: medium-light skin tone", - "alpha_code": ":man_student_tone2:", - "aliases": ":man_student_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f393": { - "output": "1f468-1f3fb-200d-1f393", - "name": "man student: light skin tone", - "alpha_code": ":man_student_tone1:", - "aliases": ":man_student_light_skin_tone:" - }, - "1f468-1f393": { - "output": "1f468-200d-1f393", - "name": "man student", - "alpha_code": ":man_student:", - "aliases": "" - }, - "1f469-1f3ff-1f393": { - "output": "1f469-1f3ff-200d-1f393", - "name": "woman student: dark skin tone", - "alpha_code": ":woman_student_tone5:", - "aliases": ":woman_student_dark_skin_tone:" - }, - "1f469-1f3fe-1f393": { - "output": "1f469-1f3fe-200d-1f393", - "name": "woman student: medium-dark skin tone", - "alpha_code": ":woman_student_tone4:", - "aliases": ":woman_student_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f393": { - "output": "1f469-1f3fd-200d-1f393", - "name": "woman student: medium skin tone", - "alpha_code": ":woman_student_tone3:", - "aliases": ":woman_student_medium_skin_tone:" - }, - "1f469-1f3fc-1f393": { - "output": "1f469-1f3fc-200d-1f393", - "name": "woman student: medium-light skin tone", - "alpha_code": ":woman_student_tone2:", - "aliases": ":woman_student_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f393": { - "output": "1f469-1f3fb-200d-1f393", - "name": "woman student: light skin tone", - "alpha_code": ":woman_student_tone1:", - "aliases": ":woman_student_light_skin_tone:" - }, - "1f469-1f393": { - "output": "1f469-200d-1f393", - "name": "woman student", - "alpha_code": ":woman_student:", - "aliases": "" - }, - "1f468-1f3ff-1f3a4": { - "output": "1f468-1f3ff-200d-1f3a4", - "name": "man singer: dark skin tone", - "alpha_code": ":man_singer_tone5:", - "aliases": ":man_singer_dark_skin_tone:" - }, - "1f468-1f3fe-1f3a4": { - "output": "1f468-1f3fe-200d-1f3a4", - "name": "man singer: medium-dark skin tone", - "alpha_code": ":man_singer_tone4:", - "aliases": ":man_singer_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f3a4": { - "output": "1f468-1f3fd-200d-1f3a4", - "name": "man singer: medium skin tone", - "alpha_code": ":man_singer_tone3:", - "aliases": ":man_singer_medium_skin_tone:" - }, - "1f468-1f3fc-1f3a4": { - "output": "1f468-1f3fc-200d-1f3a4", - "name": "man singer: medium-light skin tone", - "alpha_code": ":man_singer_tone2:", - "aliases": ":man_singer_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f3a4": { - "output": "1f468-1f3fb-200d-1f3a4", - "name": "man singer: light skin tone", - "alpha_code": ":man_singer_tone1:", - "aliases": ":man_singer_light_skin_tone:" - }, - "1f468-1f3a4": { - "output": "1f468-200d-1f3a4", - "name": "man singer", - "alpha_code": ":man_singer:", - "aliases": "" - }, - "1f469-1f3ff-1f3a4": { - "output": "1f469-1f3ff-200d-1f3a4", - "name": "woman singer: dark skin tone", - "alpha_code": ":woman_singer_tone5:", - "aliases": ":woman_singer_dark_skin_tone:" - }, - "1f469-1f3fe-1f3a4": { - "output": "1f469-1f3fe-200d-1f3a4", - "name": "woman singer: medium-dark skin tone", - "alpha_code": ":woman_singer_tone4:", - "aliases": ":woman_singer_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f3a4": { - "output": "1f469-1f3fd-200d-1f3a4", - "name": "woman singer: medium skin tone", - "alpha_code": ":woman_singer_tone3:", - "aliases": ":woman_singer_medium_skin_tone:" - }, - "1f469-1f3fc-1f3a4": { - "output": "1f469-1f3fc-200d-1f3a4", - "name": "woman singer: medium-light skin tone", - "alpha_code": ":woman_singer_tone2:", - "aliases": ":woman_singer_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f3a4": { - "output": "1f469-1f3fb-200d-1f3a4", - "name": "woman singer: light skin tone", - "alpha_code": ":woman_singer_tone1:", - "aliases": ":woman_singer_light_skin_tone:" - }, - "1f469-1f3a4": { - "output": "1f469-200d-1f3a4", - "name": "woman singer", - "alpha_code": ":woman_singer:", - "aliases": "" - }, - "1f468-1f3ff-1f52c": { - "output": "1f468-1f3ff-200d-1f52c", - "name": "man scientist: dark skin tone", - "alpha_code": ":man_scientist_tone5:", - "aliases": ":man_scientist_dark_skin_tone:" - }, - "1f468-1f3fe-1f52c": { - "output": "1f468-1f3fe-200d-1f52c", - "name": "man scientist: medium-dark skin tone", - "alpha_code": ":man_scientist_tone4:", - "aliases": ":man_scientist_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f52c": { - "output": "1f468-1f3fd-200d-1f52c", - "name": "man scientist: medium skin tone", - "alpha_code": ":man_scientist_tone3:", - "aliases": ":man_scientist_medium_skin_tone:" - }, - "1f468-1f3fc-1f52c": { - "output": "1f468-1f3fc-200d-1f52c", - "name": "man scientist: medium-light skin tone", - "alpha_code": ":man_scientist_tone2:", - "aliases": ":man_scientist_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f52c": { - "output": "1f468-1f3fb-200d-1f52c", - "name": "man scientist: light skin tone", - "alpha_code": ":man_scientist_tone1:", - "aliases": ":man_scientist_light_skin_tone:" - }, - "1f468-1f52c": { - "output": "1f468-200d-1f52c", - "name": "man scientist", - "alpha_code": ":man_scientist:", - "aliases": "" - }, - "1f469-1f3ff-1f52c": { - "output": "1f469-1f3ff-200d-1f52c", - "name": "woman scientist: dark skin tone", - "alpha_code": ":woman_scientist_tone5:", - "aliases": ":woman_scientist_dark_skin_tone:" - }, - "1f469-1f3fe-1f52c": { - "output": "1f469-1f3fe-200d-1f52c", - "name": "woman scientist: medium-dark skin tone", - "alpha_code": ":woman_scientist_tone4:", - "aliases": ":woman_scientist_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f52c": { - "output": "1f469-1f3fd-200d-1f52c", - "name": "woman scientist: medium skin tone", - "alpha_code": ":woman_scientist_tone3:", - "aliases": ":woman_scientist_medium_skin_tone:" - }, - "1f469-1f3fc-1f52c": { - "output": "1f469-1f3fc-200d-1f52c", - "name": "woman scientist: medium-light skin tone", - "alpha_code": ":woman_scientist_tone2:", - "aliases": ":woman_scientist_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f52c": { - "output": "1f469-1f3fb-200d-1f52c", - "name": "woman scientist: light skin tone", - "alpha_code": ":woman_scientist_tone1:", - "aliases": ":woman_scientist_light_skin_tone:" - }, - "1f469-1f52c": { - "output": "1f469-200d-1f52c", - "name": "woman scientist", - "alpha_code": ":woman_scientist:", - "aliases": "" - }, - "1f468-1f3ff-1f4bc": { - "output": "1f468-1f3ff-200d-1f4bc", - "name": "man office worker: dark skin tone", - "alpha_code": ":man_office_worker_tone5:", - "aliases": ":man_office_worker_dark_skin_tone:" - }, - "1f468-1f3fe-1f4bc": { - "output": "1f468-1f3fe-200d-1f4bc", - "name": "man office worker: medium-dark skin tone", - "alpha_code": ":man_office_worker_tone4:", - "aliases": ":man_office_worker_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f4bc": { - "output": "1f468-1f3fd-200d-1f4bc", - "name": "man office worker: medium skin tone", - "alpha_code": ":man_office_worker_tone3:", - "aliases": ":man_office_worker_medium_skin_tone:" - }, - "1f468-1f3fc-1f4bc": { - "output": "1f468-1f3fc-200d-1f4bc", - "name": "man office worker: medium-light skin tone", - "alpha_code": ":man_office_worker_tone2:", - "aliases": ":man_office_worker_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f4bc": { - "output": "1f468-1f3fb-200d-1f4bc", - "name": "man office worker: light skin tone", - "alpha_code": ":man_office_worker_tone1:", - "aliases": ":man_office_worker_light_skin_tone:" - }, - "1f468-1f4bc": { - "output": "1f468-200d-1f4bc", - "name": "man office worker", - "alpha_code": ":man_office_worker:", - "aliases": "" - }, - "1f469-1f3ff-1f4bc": { - "output": "1f469-1f3ff-200d-1f4bc", - "name": "woman office worker: dark skin tone", - "alpha_code": ":woman_office_worker_tone5:", - "aliases": ":woman_office_worker_dark_skin_tone:" - }, - "1f469-1f3fe-1f4bc": { - "output": "1f469-1f3fe-200d-1f4bc", - "name": "woman office worker: medium-dark skin tone", - "alpha_code": ":woman_office_worker_tone4:", - "aliases": ":woman_office_worker_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f4bc": { - "output": "1f469-1f3fd-200d-1f4bc", - "name": "woman office worker: medium skin tone", - "alpha_code": ":woman_office_worker_tone3:", - "aliases": ":woman_office_worker_medium_skin_tone:" - }, - "1f469-1f3fc-1f4bc": { - "output": "1f469-1f3fc-200d-1f4bc", - "name": "woman office worker: medium-light skin tone", - "alpha_code": ":woman_office_worker_tone2:", - "aliases": ":woman_office_worker_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f4bc": { - "output": "1f469-1f3fb-200d-1f4bc", - "name": "woman office worker: light skin tone", - "alpha_code": ":woman_office_worker_tone1:", - "aliases": ":woman_office_worker_light_skin_tone:" - }, - "1f469-1f4bc": { - "output": "1f469-200d-1f4bc", - "name": "woman office worker", - "alpha_code": ":woman_office_worker:", - "aliases": "" - }, - "1f468-1f3ff-1f527": { - "output": "1f468-1f3ff-200d-1f527", - "name": "man mechanic: dark skin tone", - "alpha_code": ":man_mechanic_tone5:", - "aliases": ":man_mechanic_dark_skin_tone:" - }, - "1f468-1f3fe-1f527": { - "output": "1f468-1f3fe-200d-1f527", - "name": "man mechanic: medium-dark skin tone", - "alpha_code": ":man_mechanic_tone4:", - "aliases": ":man_mechanic_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f527": { - "output": "1f468-1f3fd-200d-1f527", - "name": "man mechanic: medium skin tone", - "alpha_code": ":man_mechanic_tone3:", - "aliases": ":man_mechanic_medium_skin_tone:" - }, - "1f468-1f3fc-1f527": { - "output": "1f468-1f3fc-200d-1f527", - "name": "man mechanic: medium-light skin tone", - "alpha_code": ":man_mechanic_tone2:", - "aliases": ":man_mechanic_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f527": { - "output": "1f468-1f3fb-200d-1f527", - "name": "man mechanic: light skin tone", - "alpha_code": ":man_mechanic_tone1:", - "aliases": ":man_mechanic_light_skin_tone:" - }, - "1f468-1f527": { - "output": "1f468-200d-1f527", - "name": "man mechanic", - "alpha_code": ":man_mechanic:", - "aliases": "" - }, - "1f469-1f3ff-1f527": { - "output": "1f469-1f3ff-200d-1f527", - "name": "woman mechanic: dark skin tone", - "alpha_code": ":woman_mechanic_tone5:", - "aliases": ":woman_mechanic_dark_skin_tone:" - }, - "1f469-1f3fe-1f527": { - "output": "1f469-1f3fe-200d-1f527", - "name": "woman mechanic: medium-dark skin tone", - "alpha_code": ":woman_mechanic_tone4:", - "aliases": ":woman_mechanic_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f527": { - "output": "1f469-1f3fd-200d-1f527", - "name": "woman mechanic: medium skin tone", - "alpha_code": ":woman_mechanic_tone3:", - "aliases": ":woman_mechanic_medium_skin_tone:" - }, - "1f469-1f3fc-1f527": { - "output": "1f469-1f3fc-200d-1f527", - "name": "woman mechanic: medium-light skin tone", - "alpha_code": ":woman_mechanic_tone2:", - "aliases": ":woman_mechanic_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f527": { - "output": "1f469-1f3fb-200d-1f527", - "name": "woman mechanic: light skin tone", - "alpha_code": ":woman_mechanic_tone1:", - "aliases": ":woman_mechanic_light_skin_tone:" - }, - "1f469-1f527": { - "output": "1f469-200d-1f527", - "name": "woman mechanic", - "alpha_code": ":woman_mechanic:", - "aliases": "" - }, - "1f468-1f3ff-2695": { - "output": "1f468-1f3ff-200d-2695-fe0f", - "name": "man health worker: dark skin tone", - "alpha_code": ":man_health_worker_tone5:", - "aliases": ":man_health_worker_dark_skin_tone:" - }, - "1f468-1f3fe-2695": { - "output": "1f468-1f3fe-200d-2695-fe0f", - "name": "man health worker: medium-dark skin tone", - "alpha_code": ":man_health_worker_tone4:", - "aliases": ":man_health_worker_medium_dark_skin_tone:" - }, - "1f468-1f3fd-2695": { - "output": "1f468-1f3fd-200d-2695-fe0f", - "name": "man health worker: medium skin tone", - "alpha_code": ":man_health_worker_tone3:", - "aliases": ":man_health_worker_medium_skin_tone:" - }, - "1f468-1f3fc-2695": { - "output": "1f468-1f3fc-200d-2695-fe0f", - "name": "man health worker: medium-light skin tone", - "alpha_code": ":man_health_worker_tone2:", - "aliases": ":man_health_worker_medium_light_skin_tone:" - }, - "1f468-1f3fb-2695": { - "output": "1f468-1f3fb-200d-2695-fe0f", - "name": "man health worker: light skin tone", - "alpha_code": ":man_health_worker_tone1:", - "aliases": ":man_health_worker_light_skin_tone:" - }, - "1f468-2695": { - "output": "1f468-200d-2695-fe0f", - "name": "man health worker", - "alpha_code": ":man_health_worker:", - "aliases": "" - }, - "1f469-1f3ff-2695": { - "output": "1f469-1f3ff-200d-2695-fe0f", - "name": "woman health worker: dark skin tone", - "alpha_code": ":woman_health_worker_tone5:", - "aliases": ":woman_health_worker_dark_skin_tone:" - }, - "1f469-1f3fe-2695": { - "output": "1f469-1f3fe-200d-2695-fe0f", - "name": "woman health worker: medium-dark skin tone", - "alpha_code": ":woman_health_worker_tone4:", - "aliases": ":woman_health_worker_medium_dark_skin_tone:" - }, - "1f469-1f3fd-2695": { - "output": "1f469-1f3fd-200d-2695-fe0f", - "name": "woman health worker: medium skin tone", - "alpha_code": ":woman_health_worker_tone3:", - "aliases": ":woman_health_worker_medium_skin_tone:" - }, - "1f469-1f3fc-2695": { - "output": "1f469-1f3fc-200d-2695-fe0f", - "name": "woman health worker: medium-light skin tone", - "alpha_code": ":woman_health_worker_tone2:", - "aliases": ":woman_health_worker_medium_light_skin_tone:" - }, - "1f469-1f3fb-2695": { - "output": "1f469-1f3fb-200d-2695-fe0f", - "name": "woman health worker: light skin tone", - "alpha_code": ":woman_health_worker_tone1:", - "aliases": ":woman_health_worker_light_skin_tone:" - }, - "1f469-2695": { - "output": "1f469-200d-2695-fe0f", - "name": "woman health worker", - "alpha_code": ":woman_health_worker:", - "aliases": "" - }, - "1f468-1f3ff-1f3ed": { - "output": "1f468-1f3ff-200d-1f3ed", - "name": "man factory worker: dark skin tone", - "alpha_code": ":man_factory_worker_tone5:", - "aliases": ":man_factory_worker_dark_skin_tone:" - }, - "1f468-1f3fe-1f3ed": { - "output": "1f468-1f3fe-200d-1f3ed", - "name": "man factory worker: medium-dark skin tone", - "alpha_code": ":man_factory_worker_tone4:", - "aliases": ":man_factory_worker_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f3ed": { - "output": "1f468-1f3fd-200d-1f3ed", - "name": "man factory worker: medium skin tone", - "alpha_code": ":man_factory_worker_tone3:", - "aliases": ":man_factory_worker_medium_skin_tone:" - }, - "1f468-1f3fc-1f3ed": { - "output": "1f468-1f3fc-200d-1f3ed", - "name": "man factory worker: medium-light skin tone", - "alpha_code": ":man_factory_worker_tone2:", - "aliases": ":man_factory_worker_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f3ed": { - "output": "1f468-1f3fb-200d-1f3ed", - "name": "man factory worker: light skin tone", - "alpha_code": ":man_factory_worker_tone1:", - "aliases": ":man_factory_worker_light_skin_tone:" - }, - "1f468-1f3ed": { - "output": "1f468-200d-1f3ed", - "name": "man factory worker", - "alpha_code": ":man_factory_worker:", - "aliases": "" - }, - "1f469-1f3ff-1f3ed": { - "output": "1f469-1f3ff-200d-1f3ed", - "name": "woman factory worker: dark skin tone", - "alpha_code": ":woman_factory_worker_tone5:", - "aliases": ":woman_factory_worker_dark_skin_tone:" - }, - "1f469-1f3fe-1f3ed": { - "output": "1f469-1f3fe-200d-1f3ed", - "name": "woman factory worker: medium-dark skin tone", - "alpha_code": ":woman_factory_worker_tone4:", - "aliases": ":woman_factory_worker_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f3ed": { - "output": "1f469-1f3fd-200d-1f3ed", - "name": "woman factory worker: medium skin tone", - "alpha_code": ":woman_factory_worker_tone3:", - "aliases": ":woman_factory_worker_medium_skin_tone:" - }, - "1f469-1f3fc-1f3ed": { - "output": "1f469-1f3fc-200d-1f3ed", - "name": "woman factory worker: medium-light skin tone", - "alpha_code": ":woman_factory_worker_tone2:", - "aliases": ":woman_factory_worker_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f3ed": { - "output": "1f469-1f3fb-200d-1f3ed", - "name": "woman factory worker: light skin tone", - "alpha_code": ":woman_factory_worker_tone1:", - "aliases": ":woman_factory_worker_light_skin_tone:" - }, - "1f469-1f3ed": { - "output": "1f469-200d-1f3ed", - "name": "woman factory worker", - "alpha_code": ":woman_factory_worker:", - "aliases": "" - }, - "1f468-1f3ff-1f373": { - "output": "1f468-1f3ff-200d-1f373", - "name": "man cook: dark skin tone", - "alpha_code": ":man_cook_tone5:", - "aliases": ":man_cook_dark_skin_tone:" - }, - "1f468-1f3fe-1f373": { - "output": "1f468-1f3fe-200d-1f373", - "name": "man cook: medium-dark skin tone", - "alpha_code": ":man_cook_tone4:", - "aliases": ":man_cook_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f373": { - "output": "1f468-1f3fd-200d-1f373", - "name": "man cook: medium skin tone", - "alpha_code": ":man_cook_tone3:", - "aliases": ":man_cook_medium_skin_tone:" - }, - "1f468-1f3fc-1f373": { - "output": "1f468-1f3fc-200d-1f373", - "name": "man cook: medium-light skin tone", - "alpha_code": ":man_cook_tone2:", - "aliases": ":man_cook_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f373": { - "output": "1f468-1f3fb-200d-1f373", - "name": "man cook: light skin tone", - "alpha_code": ":man_cook_tone1:", - "aliases": ":man_cook_light_skin_tone:" - }, - "1f468-1f373": { - "output": "1f468-200d-1f373", - "name": "man cook", - "alpha_code": ":man_cook:", - "aliases": "" - }, - "1f469-1f3ff-1f373": { - "output": "1f469-1f3ff-200d-1f373", - "name": "woman cook: dark skin tone", - "alpha_code": ":woman_cook_tone5:", - "aliases": ":woman_cook_dark_skin_tone:" - }, - "1f469-1f3fe-1f373": { - "output": "1f469-1f3fe-200d-1f373", - "name": "woman cook: medium-dark skin tone", - "alpha_code": ":woman_cook_tone4:", - "aliases": ":woman_cook_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f373": { - "output": "1f469-1f3fd-200d-1f373", - "name": "woman cook: medium skin tone", - "alpha_code": ":woman_cook_tone3:", - "aliases": ":woman_cook_medium_skin_tone:" - }, - "1f469-1f3fc-1f373": { - "output": "1f469-1f3fc-200d-1f373", - "name": "woman cook: medium-light skin tone", - "alpha_code": ":woman_cook_tone2:", - "aliases": ":woman_cook_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f373": { - "output": "1f469-1f3fb-200d-1f373", - "name": "woman cook: light skin tone", - "alpha_code": ":woman_cook_tone1:", - "aliases": ":woman_cook_light_skin_tone:" - }, - "1f469-1f373": { - "output": "1f469-200d-1f373", - "name": "woman cook", - "alpha_code": ":woman_cook:", - "aliases": "" - }, - "1f468-1f3ff-1f33e": { - "output": "1f468-1f3ff-200d-1f33e", - "name": "man farmer: dark skin tone", - "alpha_code": ":man_farmer_tone5:", - "aliases": ":man_farmer_dark_skin_tone:" - }, - "1f468-1f3fe-1f33e": { - "output": "1f468-1f3fe-200d-1f33e", - "name": "man farmer: medium-dark skin tone", - "alpha_code": ":man_farmer_tone4:", - "aliases": ":man_farmer_medium_dark_skin_tone:" - }, - "1f468-1f3fd-1f33e": { - "output": "1f468-1f3fd-200d-1f33e", - "name": "man farmer: medium skin tone", - "alpha_code": ":man_farmer_tone3:", - "aliases": ":man_farmer_medium_skin_tone:" - }, - "1f468-1f3fc-1f33e": { - "output": "1f468-1f3fc-200d-1f33e", - "name": "man farmer: medium-light skin tone", - "alpha_code": ":man_farmer_tone2:", - "aliases": ":man_farmer_medium_light_skin_tone:" - }, - "1f468-1f3fb-1f33e": { - "output": "1f468-1f3fb-200d-1f33e", - "name": "man farmer: light skin tone", - "alpha_code": ":man_farmer_tone1:", - "aliases": ":man_farmer_light_skin_tone:" - }, - "1f468-1f33e": { - "output": "1f468-200d-1f33e", - "name": "man farmer", - "alpha_code": ":man_farmer:", - "aliases": "" - }, - "1f469-1f3ff-1f33e": { - "output": "1f469-1f3ff-200d-1f33e", - "name": "woman farmer: dark skin tone", - "alpha_code": ":woman_farmer_tone5:", - "aliases": ":woman_farmer_dark_skin_tone:" - }, - "1f469-1f3fe-1f33e": { - "output": "1f469-1f3fe-200d-1f33e", - "name": "woman farmer: medium-dark skin tone", - "alpha_code": ":woman_farmer_tone4:", - "aliases": ":woman_farmer_medium_dark_skin_tone:" - }, - "1f469-1f3fd-1f33e": { - "output": "1f469-1f3fd-200d-1f33e", - "name": "woman farmer: medium skin tone", - "alpha_code": ":woman_farmer_tone3:", - "aliases": ":woman_farmer_medium_skin_tone:" - }, - "1f469-1f3fc-1f33e": { - "output": "1f469-1f3fc-200d-1f33e", - "name": "woman farmer: medium-light skin tone", - "alpha_code": ":woman_farmer_tone2:", - "aliases": ":woman_farmer_medium_light_skin_tone:" - }, - "1f469-1f3fb-1f33e": { - "output": "1f469-1f3fb-200d-1f33e", - "name": "woman farmer: light skin tone", - "alpha_code": ":woman_farmer_tone1:", - "aliases": ":woman_farmer_light_skin_tone:" - }, - "1f469-1f33e": { - "output": "1f469-200d-1f33e", - "name": "woman farmer", - "alpha_code": ":woman_farmer:", - "aliases": "" - }, - "1f574-1f3fb": { - "output": "1f574-1f3fb", - "name": "man in business suit levitating: light skin tone", - "alpha_code": ":man_in_business_suit_levitating_tone1:", - "aliases": ":man_in_business_suit_levitating_light_skin_tone:" - }, - "1f574-1f3fc": { - "output": "1f574-1f3fc", - "name": "man in business suit levitating: medium-light skin tone", - "alpha_code": ":man_in_business_suit_levitating_tone2:", - "aliases": ":man_in_business_suit_levitating_medium_light_skin_tone:" - }, - "1f574-1f3fd": { - "output": "1f574-1f3fd", - "name": "man in business suit levitating: medium skin tone", - "alpha_code": ":man_in_business_suit_levitating_tone3:", - "aliases": ":man_in_business_suit_levitating_medium_skin_tone:" - }, - "1f574-1f3fe": { - "output": "1f574-1f3fe", - "name": "man in business suit levitating: medium-dark skin tone", - "alpha_code": ":man_in_business_suit_levitating_tone4:", - "aliases": ":man_in_business_suit_levitating_medium_dark_skin_tone:" - }, - "1f574-1f3ff": { - "output": "1f574-1f3ff", - "name": "man in business suit levitating: dark skin tone", - "alpha_code": ":man_in_business_suit_levitating_tone5:", - "aliases": ":man_in_business_suit_levitating_dark_skin_tone:" - }, - "1f6cc-1f3fb": { - "output": "1f6cc-1f3fb", - "name": "person in bed: light skin tone", - "alpha_code": ":person_in_bed_tone1:", - "aliases": ":person_in_bed_light_skin_tone:" - }, - "1f6cc-1f3fc": { - "output": "1f6cc-1f3fc", - "name": "person in bed: medium-light skin tone", - "alpha_code": ":person_in_bed_tone2:", - "aliases": ":person_in_bed_medium_light_skin_tone:" - }, - "1f6cc-1f3fd": { - "output": "1f6cc-1f3fd", - "name": "person in bed: medium skin tone", - "alpha_code": ":person_in_bed_tone3:", - "aliases": ":person_in_bed_medium_skin_tone:" - }, - "1f6cc-1f3fe": { - "output": "1f6cc-1f3fe", - "name": "person in bed: medium-dark skin tone", - "alpha_code": ":person_in_bed_tone4:", - "aliases": ":person_in_bed_medium_dark_skin_tone:" - }, - "1f6cc-1f3ff": { - "output": "1f6cc-1f3ff", - "name": "person in bed: dark skin tone", - "alpha_code": ":person_in_bed_tone5:", - "aliases": ":person_in_bed_dark_skin_tone:" - }, - "1f468-1f466": { - "output": "1f468-200d-1f466", - "name": "family: man, boy", - "alpha_code": ":family_man_boy:", - "aliases": "" - }, - "1f468-1f466-1f466": { - "output": "1f468-200d-1f466-200d-1f466", - "name": "family: man, boy, boy", - "alpha_code": ":family_man_boy_boy:", - "aliases": "" - }, - "1f468-1f467": { - "output": "1f468-200d-1f467", - "name": "family: man, girl", - "alpha_code": ":family_man_girl:", - "aliases": "" - }, - "1f468-1f467-1f466": { - "output": "1f468-200d-1f467-200d-1f466", - "name": "family: man, girl, boy", - "alpha_code": ":family_man_girl_boy:", - "aliases": "" - }, - "1f469-1f466": { - "output": "1f469-200d-1f466", - "name": "family: woman, boy", - "alpha_code": ":family_woman_boy:", - "aliases": "" - }, - "1f469-1f466-1f466": { - "output": "1f469-200d-1f466-200d-1f466", - "name": "family: woman, boy, boy", - "alpha_code": ":family_woman_boy_boy:", - "aliases": "" - }, - "1f469-1f467": { - "output": "1f469-200d-1f467", - "name": "family: woman, girl", - "alpha_code": ":family_woman_girl:", - "aliases": "" - }, - "1f469-1f467-1f466": { - "output": "1f469-200d-1f467-200d-1f466", - "name": "family: woman, girl, boy", - "alpha_code": ":family_woman_girl_boy:", - "aliases": "" - }, - "1f469-1f467-1f467": { - "output": "1f469-200d-1f467-200d-1f467", - "name": "family: woman, girl, girl", - "alpha_code": ":family_woman_girl_girl:", - "aliases": "" - }, - "1f468-2696": { - "output": "1f468-200d-2696-fe0f", - "name": "man judge", - "alpha_code": ":man_judge:", - "aliases": "" - }, - "1f468-1f3fb-2696": { - "output": "1f468-1f3fb-200d-2696-fe0f", - "name": "man judge: light skin tone", - "alpha_code": ":man_judge_tone1:", - "aliases": ":man_judge_light_skin_tone:" - }, - "1f468-1f3fc-2696": { - "output": "1f468-1f3fc-200d-2696-fe0f", - "name": "man judge: medium-light skin tone", - "alpha_code": ":man_judge_tone2:", - "aliases": ":man_judge_medium_light_skin_tone:" - }, - "1f468-1f3fd-2696": { - "output": "1f468-1f3fd-200d-2696-fe0f", - "name": "man judge: medium skin tone", - "alpha_code": ":man_judge_tone3:", - "aliases": ":man_judge_medium_skin_tone:" - }, - "1f468-1f3fe-2696": { - "output": "1f468-1f3fe-200d-2696-fe0f", - "name": "man judge: medium-dark skin tone", - "alpha_code": ":man_judge_tone4:", - "aliases": ":man_judge_medium_dark_skin_tone:" - }, - "1f468-1f3ff-2696": { - "output": "1f468-1f3ff-200d-2696-fe0f", - "name": "man judge: dark skin tone", - "alpha_code": ":man_judge_tone5:", - "aliases": ":man_judge_dark_skin_tone:" - }, - "1f469-2696": { - "output": "1f469-200d-2696-fe0f", - "name": "woman judge", - "alpha_code": ":woman_judge:", - "aliases": "" - }, - "1f469-1f3fb-2696": { - "output": "1f469-1f3fb-200d-2696-fe0f", - "name": "woman judge: light skin tone", - "alpha_code": ":woman_judge_tone1:", - "aliases": ":woman_judge_light_skin_tone:" - }, - "1f469-1f3fc-2696": { - "output": "1f469-1f3fc-200d-2696-fe0f", - "name": "woman judge: medium-light skin tone", - "alpha_code": ":woman_judge_tone2:", - "aliases": ":woman_judge_medium_light_skin_tone:" - }, - "1f469-1f3fd-2696": { - "output": "1f469-1f3fd-200d-2696-fe0f", - "name": "woman judge: medium skin tone", - "alpha_code": ":woman_judge_tone3:", - "aliases": ":woman_judge_medium_skin_tone:" - }, - "1f469-1f3fe-2696": { - "output": "1f469-1f3fe-200d-2696-fe0f", - "name": "woman judge: medium-dark skin tone", - "alpha_code": ":woman_judge_tone4:", - "aliases": ":woman_judge_medium_dark_skin_tone:" - }, - "1f469-1f3ff-2696": { - "output": "1f469-1f3ff-200d-2696-fe0f", - "name": "woman judge: dark skin tone", - "alpha_code": ":woman_judge_tone5:", - "aliases": ":woman_judge_dark_skin_tone:" - }, - "1f468-2708": { - "output": "1f468-200d-2708-fe0f", - "name": "man pilot", - "alpha_code": ":man_pilot:", - "aliases": "" - }, - "1f468-1f3fb-2708": { - "output": "1f468-1f3fb-200d-2708-fe0f", - "name": "man pilot: light skin tone", - "alpha_code": ":man_pilot_tone1:", - "aliases": ":man_pilot_light_skin_tone:" - }, - "1f468-1f3fc-2708": { - "output": "1f468-1f3fc-200d-2708-fe0f", - "name": "man pilot: medium-light skin tone", - "alpha_code": ":man_pilot_tone2:", - "aliases": ":man_pilot_medium_light_skin_tone:" - }, - "1f468-1f3fd-2708": { - "output": "1f468-1f3fd-200d-2708-fe0f", - "name": "man pilot: medium skin tone", - "alpha_code": ":man_pilot_tone3:", - "aliases": ":man_pilot_medium_skin_tone:" - }, - "1f468-1f3fe-2708": { - "output": "1f468-1f3fe-200d-2708-fe0f", - "name": "man pilot: medium-dark skin tone", - "alpha_code": ":man_pilot_tone4:", - "aliases": ":man_pilot_medium_dark_skin_tone:" - }, - "1f468-1f3ff-2708": { - "output": "1f468-1f3ff-200d-2708-fe0f", - "name": "man pilot: dark skin tone", - "alpha_code": ":man_pilot_tone5:", - "aliases": ":man_pilot_dark_skin_tone:" - }, - "1f469-2708": { - "output": "1f469-200d-2708-fe0f", - "name": "woman pilot", - "alpha_code": ":woman_pilot:", - "aliases": "" - }, - "1f469-1f3fb-2708": { - "output": "1f469-1f3fb-200d-2708-fe0f", - "name": "woman pilot: light skin tone", - "alpha_code": ":woman_pilot_tone1:", - "aliases": ":woman_pilot_light_skin_tone:" - }, - "1f469-1f3fc-2708": { - "output": "1f469-1f3fc-200d-2708-fe0f", - "name": "woman pilot: medium-light skin tone", - "alpha_code": ":woman_pilot_tone2:", - "aliases": ":woman_pilot_medium_light_skin_tone:" - }, - "1f469-1f3fd-2708": { - "output": "1f469-1f3fd-200d-2708-fe0f", - "name": "woman pilot: medium skin tone", - "alpha_code": ":woman_pilot_tone3:", - "aliases": ":woman_pilot_medium_skin_tone:" - }, - "1f469-1f3fe-2708": { - "output": "1f469-1f3fe-200d-2708-fe0f", - "name": "woman pilot: medium-dark skin tone", - "alpha_code": ":woman_pilot_tone4:", - "aliases": ":woman_pilot_medium_dark_skin_tone:" - }, - "1f469-1f3ff-2708": { - "output": "1f469-1f3ff-200d-2708-fe0f", - "name": "woman pilot: dark skin tone", - "alpha_code": ":woman_pilot_tone5:", - "aliases": ":woman_pilot_dark_skin_tone:" - }, - "1f468-1f3a8": { - "output": "1f468-200d-1f3a8", - "name": "man artist", - "alpha_code": ":man_artist:", - "aliases": "" - }, - "1f468-1f3fb-1f3a8": { - "output": "1f468-1f3fb-200d-1f3a8", - "name": "man artist: light skin tone", - "alpha_code": ":man_artist_tone1:", - "aliases": ":man_artist_light_skin_tone:" - }, - "1f468-1f3fc-1f3a8": { - "output": "1f468-1f3fc-200d-1f3a8", - "name": "man artist: medium-light skin tone", - "alpha_code": ":man_artist_tone2:", - "aliases": ":man_artist_medium_light_skin_tone:" - }, - "1f468-1f3fd-1f3a8": { - "output": "1f468-1f3fd-200d-1f3a8", - "name": "man artist: medium skin tone", - "alpha_code": ":man_artist_tone3:", - "aliases": ":man_artist_medium_skin_tone:" - }, - "1f468-1f3fe-1f3a8": { - "output": "1f468-1f3fe-200d-1f3a8", - "name": "man artist: medium-dark skin tone", - "alpha_code": ":man_artist_tone4:", - "aliases": ":man_artist_medium_dark_skin_tone:" - }, - "1f468-1f3ff-1f3a8": { - "output": "1f468-1f3ff-200d-1f3a8", - "name": "man artist: dark skin tone", - "alpha_code": ":man_artist_tone5:", - "aliases": ":man_artist_dark_skin_tone:" - }, - "1f469-1f3a8": { - "output": "1f469-200d-1f3a8", - "name": "woman artist", - "alpha_code": ":woman_artist:", - "aliases": "" - }, - "1f469-1f3fb-1f3a8": { - "output": "1f469-1f3fb-200d-1f3a8", - "name": "woman artist: light skin tone", - "alpha_code": ":woman_artist_tone1:", - "aliases": ":woman_artist_light_skin_tone:" - }, - "1f469-1f3fc-1f3a8": { - "output": "1f469-1f3fc-200d-1f3a8", - "name": "woman artist: medium-light skin tone", - "alpha_code": ":woman_artist_tone2:", - "aliases": ":woman_artist_medium_light_skin_tone:" - }, - "1f469-1f3fd-1f3a8": { - "output": "1f469-1f3fd-200d-1f3a8", - "name": "woman artist: medium skin tone", - "alpha_code": ":woman_artist_tone3:", - "aliases": ":woman_artist_medium_skin_tone:" - }, - "1f469-1f3fe-1f3a8": { - "output": "1f469-1f3fe-200d-1f3a8", - "name": "woman artist: medium-dark skin tone", - "alpha_code": ":woman_artist_tone4:", - "aliases": ":woman_artist_medium_dark_skin_tone:" - }, - "1f469-1f3ff-1f3a8": { - "output": "1f469-1f3ff-200d-1f3a8", - "name": "woman artist: dark skin tone", - "alpha_code": ":woman_artist_tone5:", - "aliases": ":woman_artist_dark_skin_tone:" - }, - "1f468-1f680": { - "output": "1f468-200d-1f680", - "name": "man astronaut", - "alpha_code": ":man_astronaut:", - "aliases": "" - }, - "1f468-1f3fb-1f680": { - "output": "1f468-1f3fb-200d-1f680", - "name": "man astronaut: light skin tone", - "alpha_code": ":man_astronaut_tone1:", - "aliases": ":man_astronaut_light_skin_tone:" - }, - "1f468-1f3fc-1f680": { - "output": "1f468-1f3fc-200d-1f680", - "name": "man astronaut: medium-light skin tone", - "alpha_code": ":man_astronaut_tone2:", - "aliases": ":man_astronaut_medium_light_skin_tone:" - }, - "1f468-1f3fd-1f680": { - "output": "1f468-1f3fd-200d-1f680", - "name": "man astronaut: medium skin tone", - "alpha_code": ":man_astronaut_tone3:", - "aliases": ":man_astronaut_medium_skin_tone:" - }, - "1f468-1f3fe-1f680": { - "output": "1f468-1f3fe-200d-1f680", - "name": "man astronaut: medium-dark skin tone", - "alpha_code": ":man_astronaut_tone4:", - "aliases": ":man_astronaut_medium_dark_skin_tone:" - }, - "1f468-1f3ff-1f680": { - "output": "1f468-1f3ff-200d-1f680", - "name": "man astronaut: dark skin tone", - "alpha_code": ":man_astronaut_tone5:", - "aliases": ":man_astronaut_dark_skin_tone:" - }, - "1f469-1f680": { - "output": "1f469-200d-1f680", - "name": "woman astronaut", - "alpha_code": ":woman_astronaut:", - "aliases": "" - }, - "1f469-1f3fb-1f680": { - "output": "1f469-1f3fb-200d-1f680", - "name": "woman astronaut: light skin tone", - "alpha_code": ":woman_astronaut_tone1:", - "aliases": ":woman_astronaut_light_skin_tone:" - }, - "1f469-1f3fc-1f680": { - "output": "1f469-1f3fc-200d-1f680", - "name": "woman astronaut: medium-light skin tone", - "alpha_code": ":woman_astronaut_tone2:", - "aliases": ":woman_astronaut_medium_light_skin_tone:" - }, - "1f469-1f3fd-1f680": { - "output": "1f469-1f3fd-200d-1f680", - "name": "woman astronaut: medium skin tone", - "alpha_code": ":woman_astronaut_tone3:", - "aliases": ":woman_astronaut_medium_skin_tone:" - }, - "1f469-1f3fe-1f680": { - "output": "1f469-1f3fe-200d-1f680", - "name": "woman astronaut: medium-dark skin tone", - "alpha_code": ":woman_astronaut_tone4:", - "aliases": ":woman_astronaut_medium_dark_skin_tone:" - }, - "1f469-1f3ff-1f680": { - "output": "1f469-1f3ff-200d-1f680", - "name": "woman astronaut: dark skin tone", - "alpha_code": ":woman_astronaut_tone5:", - "aliases": ":woman_astronaut_dark_skin_tone:" - }, - "1f468-1f692": { - "output": "1f468-200d-1f692", - "name": "man firefighter", - "alpha_code": ":man_firefighter:", - "aliases": "" - }, - "1f468-1f3fb-1f692": { - "output": "1f468-1f3fb-200d-1f692", - "name": "man firefighter: light skin tone", - "alpha_code": ":man_firefighter_tone1:", - "aliases": ":man_firefighter_light_skin_tone:" - }, - "1f468-1f3fc-1f692": { - "output": "1f468-1f3fc-200d-1f692", - "name": "man firefighter: medium-light skin tone", - "alpha_code": ":man_firefighter_tone2:", - "aliases": ":man_firefighter_medium_light_skin_tone:" - }, - "1f468-1f3fd-1f692": { - "output": "1f468-1f3fd-200d-1f692", - "name": "man firefighter: medium skin tone", - "alpha_code": ":man_firefighter_tone3:", - "aliases": ":man_firefighter_medium_skin_tone:" - }, - "1f468-1f3fe-1f692": { - "output": "1f468-1f3fe-200d-1f692", - "name": "man firefighter: medium-dark skin tone", - "alpha_code": ":man_firefighter_tone4:", - "aliases": ":man_firefighter_medium_dark_skin_tone:" - }, - "1f468-1f3ff-1f692": { - "output": "1f468-1f3ff-200d-1f692", - "name": "man firefighter: dark skin tone", - "alpha_code": ":man_firefighter_tone5:", - "aliases": ":man_firefighter_dark_skin_tone:" - }, - "1f469-1f692": { - "output": "1f469-200d-1f692", - "name": "woman firefighter", - "alpha_code": ":woman_firefighter:", - "aliases": "" - }, - "1f469-1f3fb-1f692": { - "output": "1f469-1f3fb-200d-1f692", - "name": "woman firefighter: light skin tone", - "alpha_code": ":woman_firefighter_tone1:", - "aliases": ":woman_firefighter_light_skin_tone:" - }, - "1f469-1f3fc-1f692": { - "output": "1f469-1f3fc-200d-1f692", - "name": "woman firefighter: medium-light skin tone", - "alpha_code": ":woman_firefighter_tone2:", - "aliases": ":woman_firefighter_medium_light_skin_tone:" - }, - "1f469-1f3fd-1f692": { - "output": "1f469-1f3fd-200d-1f692", - "name": "woman firefighter: medium skin tone", - "alpha_code": ":woman_firefighter_tone3:", - "aliases": ":woman_firefighter_medium_skin_tone:" - }, - "1f469-1f3fe-1f692": { - "output": "1f469-1f3fe-200d-1f692", - "name": "woman firefighter: medium-dark skin tone", - "alpha_code": ":woman_firefighter_tone4:", - "aliases": ":woman_firefighter_medium_dark_skin_tone:" - }, - "1f469-1f3ff-1f692": { - "output": "1f469-1f3ff-200d-1f692", - "name": "woman firefighter: dark skin tone", - "alpha_code": ":woman_firefighter_tone5:", - "aliases": ":woman_firefighter_dark_skin_tone:" - }, - "2640": { - "output": "2640-fe0f", - "name": "female sign", - "alpha_code": ":female_sign:", - "aliases": "" - }, - "2642": { - "output": "2642-fe0f", - "name": "male sign", - "alpha_code": ":male_sign:", - "aliases": "" - }, - "2695": { - "output": "2695-fe0f", - "name": "medical symbol", - "alpha_code": ":medical_symbol:", - "aliases": "" - }, - "1f1fa-1f1f3": { - "output": "1f1fa-1f1f3", - "name": "United Nations", - "alpha_code": ":united_nations:", - "aliases": "" - }, - "1f3c2-1f3fc": { - "output": "1f3c2-1f3fc", - "name": "snowboarder: medium-light skin tone", - "alpha_code": ":snowboarder_tone2:", - "aliases": ":snowboarder_medium_light_skin_tone:" - }, - "1f3c2-1f3fd": { - "output": "1f3c2-1f3fd", - "name": "snowboarder: medium skin tone", - "alpha_code": ":snowboarder_tone3:", - "aliases": ":snowboarder_medium_skin_tone:" - }, - "1f3c2-1f3fe": { - "output": "1f3c2-1f3fe", - "name": "snowboarder: medium-dark skin tone", - "alpha_code": ":snowboarder_tone4:", - "aliases": ":snowboarder_medium_dark_skin_tone:" - }, - "1f3c2-1f3ff": { - "output": "1f3c2-1f3ff", - "name": "snowboarder: dark skin tone", - "alpha_code": ":snowboarder_tone5:", - "aliases": ":snowboarder_dark_skin_tone:" - }, - "1f3cc-1f3fb": { - "output": "1f3cc-1f3fb", - "name": "person golfing: light skin tone", - "alpha_code": ":person_golfing_tone1:", - "aliases": ":person_golfing_light_skin_tone:" - }, - "1f3cc-1f3fc": { - "output": "1f3cc-1f3fc", - "name": "person golfing: medium-light skin tone", - "alpha_code": ":person_golfing_tone2:", - "aliases": ":person_golfing_medium_light_skin_tone:" - }, - "1f3cc-1f3fd": { - "output": "1f3cc-1f3fd", - "name": "person golfing: medium skin tone", - "alpha_code": ":person_golfing_tone3:", - "aliases": ":person_golfing_medium_skin_tone:" - }, - "1f3cc-1f3fe": { - "output": "1f3cc-1f3fe", - "name": "person golfing: medium-dark skin tone", - "alpha_code": ":person_golfing_tone4:", - "aliases": ":person_golfing_medium_dark_skin_tone:" - }, - "1f3cc-1f3ff": { - "output": "1f3cc-1f3ff", - "name": "person golfing: dark skin tone", - "alpha_code": ":person_golfing_tone5:", - "aliases": ":person_golfing_dark_skin_tone:" - }, - "1f468-1f467-1f467": { - "output": "1f468-200d-1f467-200d-1f467", - "name": "family: man, girl, girl", - "alpha_code": ":family_man_girl_girl:", - "aliases": "" - }, - "1f468-1f469-1f466": { - "output": "1f468-200d-1f469-200d-1f466", - "name": "family: man, woman, boy", - "alpha_code": ":family_man_woman_boy:", - "aliases": "" - }, - "1f469-2764-1f468": { - "output": "1f469-200d-2764-fe0f-200d-1f468", - "name": "couple with heart: woman, man", - "alpha_code": ":couple_with_heart_woman_man:", - "aliases": "" - }, - "1f469-2764-1f48b-1f468": { - "output": "1f469-200d-2764-fe0f-200d-1f48b-200d-1f468", - "name": "kiss: woman, man", - "alpha_code": ":kiss_woman_man:", - "aliases": "" - }, - "1f6f7": { - "output": "1f6f7", - "name": "sled", - "alpha_code": ":sled:", - "aliases": "" - }, - "1f6f8": { - "output": "1f6f8", - "name": "flying saucer", - "alpha_code": ":flying_saucer:", - "aliases": "" - }, - "1f91f": { - "output": "1f91f", - "name": "love-you gesture", - "alpha_code": ":love_you_gesture:", - "aliases": "" - }, - "1f928": { - "output": "1f928", - "name": "face with raised eyebrow", - "alpha_code": ":face_with_raised_eyebrow:", - "aliases": "" - }, - "1f929": { - "output": "1f929", - "name": "star-struck", - "alpha_code": ":star_struck:", - "aliases": "" - }, - "1f92a": { - "output": "1f92a", - "name": "crazy face", - "alpha_code": ":crazy_face:", - "aliases": "" - }, - "1f92b": { - "output": "1f92b", - "name": "shushing face", - "alpha_code": ":shushing_face:", - "aliases": "" - }, - "1f92c": { - "output": "1f92c", - "name": "face with symbols over mouth", - "alpha_code": ":face_with_symbols_over_mouth:", - "aliases": "" - }, - "1f92d": { - "output": "1f92d", - "name": "face with hand over mouth", - "alpha_code": ":face_with_hand_over_mouth:", - "aliases": "" - }, - "1f92e": { - "output": "1f92e", - "name": "face vomiting", - "alpha_code": ":face_vomiting:", - "aliases": "" - }, - "1f92f": { - "output": "1f92f", - "name": "exploding head", - "alpha_code": ":exploding_head:", - "aliases": "" - }, - "1f931": { - "output": "1f931", - "name": "breast-feeding", - "alpha_code": ":breast_feeding:", - "aliases": "" - }, - "1f932": { - "output": "1f932", - "name": "palms up together", - "alpha_code": ":palms_up_together:", - "aliases": "" - }, - "1f94c": { - "output": "1f94c", - "name": "curling stone", - "alpha_code": ":curling_stone:", - "aliases": "" - }, - "1f95f": { - "output": "1f95f", - "name": "dumpling", - "alpha_code": ":dumpling:", - "aliases": "" - }, - "1f960": { - "output": "1f960", - "name": "fortune cookie", - "alpha_code": ":fortune_cookie:", - "aliases": "" - }, - "1f961": { - "output": "1f961", - "name": "takeout box", - "alpha_code": ":takeout_box:", - "aliases": "" - }, - "1f962": { - "output": "1f962", - "name": "chopsticks", - "alpha_code": ":chopsticks:", - "aliases": "" - }, - "1f963": { - "output": "1f963", - "name": "bowl with spoon", - "alpha_code": ":bowl_with_spoon:", - "aliases": "" - }, - "1f964": { - "output": "1f964", - "name": "cup with straw", - "alpha_code": ":cup_with_straw:", - "aliases": "" - }, - "1f965": { - "output": "1f965", - "name": "coconut", - "alpha_code": ":coconut:", - "aliases": "" - }, - "1f966": { - "output": "1f966", - "name": "broccoli", - "alpha_code": ":broccoli:", - "aliases": "" - }, - "1f967": { - "output": "1f967", - "name": "pie", - "alpha_code": ":pie:", - "aliases": "" - }, - "1f968": { - "output": "1f968", - "name": "pretzel", - "alpha_code": ":pretzel:", - "aliases": "" - }, - "1f969": { - "output": "1f969", - "name": "cut of meat", - "alpha_code": ":cut_of_meat:", - "aliases": "" - }, - "1f96a": { - "output": "1f96a", - "name": "sandwich", - "alpha_code": ":sandwich:", - "aliases": "" - }, - "1f96b": { - "output": "1f96b", - "name": "canned food", - "alpha_code": ":canned_food:", - "aliases": "" - }, - "1f992": { - "output": "1f992", - "name": "giraffe", - "alpha_code": ":giraffe:", - "aliases": "" - }, - "1f993": { - "output": "1f993", - "name": "zebra", - "alpha_code": ":zebra:", - "aliases": "" - }, - "1f994": { - "output": "1f994", - "name": "hedgehog", - "alpha_code": ":hedgehog:", - "aliases": "" - }, - "1f995": { - "output": "1f995", - "name": "sauropod", - "alpha_code": ":sauropod:", - "aliases": "" - }, - "1f996": { - "output": "1f996", - "name": "T-Rex", - "alpha_code": ":t_rex:", - "aliases": "" - }, - "1f997": { - "output": "1f997", - "name": "cricket", - "alpha_code": ":cricket:", - "aliases": "" - }, - "1f9d0": { - "output": "1f9d0", - "name": "face with monocle", - "alpha_code": ":face_with_monocle:", - "aliases": "" - }, - "1f9d1": { - "output": "1f9d1", - "name": "adult", - "alpha_code": ":adult:", - "aliases": "" - }, - "1f9d2": { - "output": "1f9d2", - "name": "child", - "alpha_code": ":child:", - "aliases": "" - }, - "1f9d3": { - "output": "1f9d3", - "name": "older adult", - "alpha_code": ":older_adult:", - "aliases": "" - }, - "1f9d4": { - "output": "1f9d4", - "name": "bearded person", - "alpha_code": ":bearded_person:", - "aliases": "" - }, - "1f9d5": { - "output": "1f9d5", - "name": "woman with headscarf", - "alpha_code": ":woman_with_headscarf:", - "aliases": "" - }, - "1f9d6": { - "output": "1f9d6", - "name": "person in steamy room", - "alpha_code": ":person_in_steamy_room:", - "aliases": "" - }, - "1f9d7": { - "output": "1f9d7", - "name": "person climbing", - "alpha_code": ":person_climbing:", - "aliases": "" - }, - "1f9d8": { - "output": "1f9d8", - "name": "person in lotus position", - "alpha_code": ":person_in_lotus_position:", - "aliases": "" - }, - "1f9d9": { - "output": "1f9d9", - "name": "mage", - "alpha_code": ":mage:", - "aliases": "" - }, - "1f9da": { - "output": "1f9da", - "name": "fairy", - "alpha_code": ":fairy:", - "aliases": "" - }, - "1f9db": { - "output": "1f9db", - "name": "vampire", - "alpha_code": ":vampire:", - "aliases": "" - }, - "1f9dc": { - "output": "1f9dc", - "name": "merperson", - "alpha_code": ":merperson:", - "aliases": "" - }, - "1f9dd": { - "output": "1f9dd", - "name": "elf", - "alpha_code": ":elf:", - "aliases": "" - }, - "1f9de": { - "output": "1f9de", - "name": "genie", - "alpha_code": ":genie:", - "aliases": "" - }, - "1f9df": { - "output": "1f9df", - "name": "zombie", - "alpha_code": ":zombie:", - "aliases": "" - }, - "1f9e0": { - "output": "1f9e0", - "name": "brain", - "alpha_code": ":brain:", - "aliases": "" - }, - "1f9e1": { - "output": "1f9e1", - "name": "orange heart", - "alpha_code": ":orange_heart:", - "aliases": "" - }, - "1f9e2": { - "output": "1f9e2", - "name": "billed cap", - "alpha_code": ":billed_cap:", - "aliases": "" - }, - "1f9e3": { - "output": "1f9e3", - "name": "scarf", - "alpha_code": ":scarf:", - "aliases": "" - }, - "1f9e4": { - "output": "1f9e4", - "name": "gloves", - "alpha_code": ":gloves:", - "aliases": "" - }, - "1f9e5": { - "output": "1f9e5", - "name": "coat", - "alpha_code": ":coat:", - "aliases": "" - }, - "1f9e6": { - "output": "1f9e6", - "name": "socks", - "alpha_code": ":socks:", - "aliases": "" - }, - "1f3f4-e0067-e0062-e0065-e006e-e0067-e007f": { - "output": "1f3f4-e0067-e0062-e0065-e006e-e0067-e007f", - "name": "England", - "alpha_code": ":england:", - "aliases": "" - }, - "1f3f4-e0067-e0062-e0073-e0063-e0074-e007f": { - "output": "1f3f4-e0067-e0062-e0073-e0063-e0074-e007f", - "name": "Scotland", - "alpha_code": ":scotland:", - "aliases": "" - }, - "1f3f4-e0067-e0062-e0077-e006c-e0073-e007f": { - "output": "1f3f4-e0067-e0062-e0077-e006c-e0073-e007f", - "name": "Wales", - "alpha_code": ":wales:", - "aliases": "" - }, - "1f91f-1f3fb": { - "output": "1f91f-1f3fb", - "name": "love-you gesture: light skin tone", - "alpha_code": ":love_you_gesture_tone1:", - "aliases": ":love_you_gesture_light_skin_tone:" - }, - "1f91f-1f3fc": { - "output": "1f91f-1f3fc", - "name": "love-you gesture: medium-light skin tone", - "alpha_code": ":love_you_gesture_tone2:", - "aliases": ":love_you_gesture_medium_light_skin_tone:" - }, - "1f91f-1f3fd": { - "output": "1f91f-1f3fd", - "name": "love-you gesture: medium skin tone", - "alpha_code": ":love_you_gesture_tone3:", - "aliases": ":love_you_gesture_medium_skin_tone:" - }, - "1f91f-1f3fe": { - "output": "1f91f-1f3fe", - "name": "love-you gesture: medium-dark skin tone", - "alpha_code": ":love_you_gesture_tone4:", - "aliases": ":love_you_gesture_medium_dark_skin_tone:" - }, - "1f91f-1f3ff": { - "output": "1f91f-1f3ff", - "name": "love-you gesture: dark skin tone", - "alpha_code": ":love_you_gesture_tone5:", - "aliases": ":love_you_gesture_dark_skin_tone:" - }, - "1f931-1f3fb": { - "output": "1f931-1f3fb", - "name": "breast-feeding: light skin tone", - "alpha_code": ":breast_feeding_tone1:", - "aliases": ":breast_feeding_light_skin_tone:" - }, - "1f931-1f3fc": { - "output": "1f931-1f3fc", - "name": "breast-feeding: medium-light skin tone", - "alpha_code": ":breast_feeding_tone2:", - "aliases": ":breast_feeding_medium_light_skin_tone:" - }, - "1f931-1f3fd": { - "output": "1f931-1f3fd", - "name": "breast-feeding: medium skin tone", - "alpha_code": ":breast_feeding_tone3:", - "aliases": ":breast_feeding_medium_skin_tone:" - }, - "1f931-1f3fe": { - "output": "1f931-1f3fe", - "name": "breast-feeding: medium-dark skin tone", - "alpha_code": ":breast_feeding_tone4:", - "aliases": ":breast_feeding_medium_dark_skin_tone:" - }, - "1f931-1f3ff": { - "output": "1f931-1f3ff", - "name": "breast-feeding: dark skin tone", - "alpha_code": ":breast_feeding_tone5:", - "aliases": ":breast_feeding_dark_skin_tone:" - }, - "1f932-1f3fb": { - "output": "1f932-1f3fb", - "name": "palms up together: light skin tone", - "alpha_code": ":palms_up_together_tone1:", - "aliases": ":palms_up_together_light_skin_tone:" - }, - "1f932-1f3fc": { - "output": "1f932-1f3fc", - "name": "palms up together: medium-light skin tone", - "alpha_code": ":palms_up_together_tone2:", - "aliases": ":palms_up_together_medium_light_skin_tone:" - }, - "1f932-1f3fd": { - "output": "1f932-1f3fd", - "name": "palms up together: medium skin tone", - "alpha_code": ":palms_up_together_tone3:", - "aliases": ":palms_up_together_medium_skin_tone:" - }, - "1f932-1f3fe": { - "output": "1f932-1f3fe", - "name": "palms up together: medium-dark skin tone", - "alpha_code": ":palms_up_together_tone4:", - "aliases": ":palms_up_together_medium_dark_skin_tone:" - }, - "1f932-1f3ff": { - "output": "1f932-1f3ff", - "name": "palms up together: dark skin tone", - "alpha_code": ":palms_up_together_tone5:", - "aliases": ":palms_up_together_dark_skin_tone:" - }, - "1f9d1-1f3fb": { - "output": "1f9d1-1f3fb", - "name": "adult: light skin tone", - "alpha_code": ":adult_tone1:", - "aliases": ":adult_light_skin_tone:" - }, - "1f9d1-1f3fc": { - "output": "1f9d1-1f3fc", - "name": "adult: medium-light skin tone", - "alpha_code": ":adult_tone2:", - "aliases": ":adult_medium_light_skin_tone:" - }, - "1f9d1-1f3fd": { - "output": "1f9d1-1f3fd", - "name": "adult: medium skin tone", - "alpha_code": ":adult_tone3:", - "aliases": ":adult_medium_skin_tone:" - }, - "1f9d1-1f3fe": { - "output": "1f9d1-1f3fe", - "name": "adult: medium-dark skin tone", - "alpha_code": ":adult_tone4:", - "aliases": ":adult_medium_dark_skin_tone:" - }, - "1f9d1-1f3ff": { - "output": "1f9d1-1f3ff", - "name": "adult: dark skin tone", - "alpha_code": ":adult_tone5:", - "aliases": ":adult_dark_skin_tone:" - }, - "1f9d2-1f3fb": { - "output": "1f9d2-1f3fb", - "name": "child: light skin tone", - "alpha_code": ":child_tone1:", - "aliases": ":child_light_skin_tone:" - }, - "1f9d2-1f3fc": { - "output": "1f9d2-1f3fc", - "name": "child: medium-light skin tone", - "alpha_code": ":child_tone2:", - "aliases": ":child_medium_light_skin_tone:" - }, - "1f9d2-1f3fd": { - "output": "1f9d2-1f3fd", - "name": "child: medium skin tone", - "alpha_code": ":child_tone3:", - "aliases": ":child_medium_skin_tone:" - }, - "1f9d2-1f3fe": { - "output": "1f9d2-1f3fe", - "name": "child: medium-dark skin tone", - "alpha_code": ":child_tone4:", - "aliases": ":child_medium_dark_skin_tone:" - }, - "1f9d2-1f3ff": { - "output": "1f9d2-1f3ff", - "name": "child: dark skin tone", - "alpha_code": ":child_tone5:", - "aliases": ":child_dark_skin_tone:" - }, - "1f9d3-1f3fb": { - "output": "1f9d3-1f3fb", - "name": "older adult: light skin tone", - "alpha_code": ":older_adult_tone1:", - "aliases": ":older_adult_light_skin_tone:" - }, - "1f9d3-1f3fc": { - "output": "1f9d3-1f3fc", - "name": "older adult: medium-light skin tone", - "alpha_code": ":older_adult_tone2:", - "aliases": ":older_adult_medium_light_skin_tone:" - }, - "1f9d3-1f3fd": { - "output": "1f9d3-1f3fd", - "name": "older adult: medium skin tone", - "alpha_code": ":older_adult_tone3:", - "aliases": ":older_adult_medium_skin_tone:" - }, - "1f9d3-1f3fe": { - "output": "1f9d3-1f3fe", - "name": "older adult: medium-dark skin tone", - "alpha_code": ":older_adult_tone4:", - "aliases": ":older_adult_medium_dark_skin_tone:" - }, - "1f9d3-1f3ff": { - "output": "1f9d3-1f3ff", - "name": "older adult: dark skin tone", - "alpha_code": ":older_adult_tone5:", - "aliases": ":older_adult_dark_skin_tone:" - }, - "1f9d4-1f3fb": { - "output": "1f9d4-1f3fb", - "name": "bearded person: light skin tone", - "alpha_code": ":bearded_person_tone1:", - "aliases": ":bearded_person_light_skin_tone:" - }, - "1f9d4-1f3fc": { - "output": "1f9d4-1f3fc", - "name": "bearded person: medium-light skin tone", - "alpha_code": ":bearded_person_tone2:", - "aliases": ":bearded_person_medium_light_skin_tone:" - }, - "1f9d4-1f3fd": { - "output": "1f9d4-1f3fd", - "name": "bearded person: medium skin tone", - "alpha_code": ":bearded_person_tone3:", - "aliases": ":bearded_person_medium_skin_tone:" - }, - "1f9d4-1f3fe": { - "output": "1f9d4-1f3fe", - "name": "bearded person: medium-dark skin tone", - "alpha_code": ":bearded_person_tone4:", - "aliases": ":bearded_person_medium_dark_skin_tone:" - }, - "1f9d4-1f3ff": { - "output": "1f9d4-1f3ff", - "name": "bearded person: dark skin tone", - "alpha_code": ":bearded_person_tone5:", - "aliases": ":bearded_person_dark_skin_tone:" - }, - "1f9d5-1f3fb": { - "output": "1f9d5-1f3fb", - "name": "woman with headscarf: light skin tone", - "alpha_code": ":woman_with_headscarf_tone1:", - "aliases": ":woman_with_headscarf_light_skin_tone:" - }, - "1f9d5-1f3fc": { - "output": "1f9d5-1f3fc", - "name": "woman with headscarf: medium-light skin tone", - "alpha_code": ":woman_with_headscarf_tone2:", - "aliases": ":woman_with_headscarf_medium_light_skin_tone:" - }, - "1f9d5-1f3fd": { - "output": "1f9d5-1f3fd", - "name": "woman with headscarf: medium skin tone", - "alpha_code": ":woman_with_headscarf_tone3:", - "aliases": ":woman_with_headscarf_medium_skin_tone:" - }, - "1f9d5-1f3fe": { - "output": "1f9d5-1f3fe", - "name": "woman with headscarf: medium-dark skin tone", - "alpha_code": ":woman_with_headscarf_tone4:", - "aliases": ":woman_with_headscarf_medium_dark_skin_tone:" - }, - "1f9d5-1f3ff": { - "output": "1f9d5-1f3ff", - "name": "woman with headscarf: dark skin tone", - "alpha_code": ":woman_with_headscarf_tone5:", - "aliases": ":woman_with_headscarf_dark_skin_tone:" - }, - "1f9d6-1f3fb": { - "output": "1f9d6-1f3fb", - "name": "person in steamy room: light skin tone", - "alpha_code": ":person_in_steamy_room_tone1:", - "aliases": ":person_in_steamy_room_light_skin_tone:" - }, - "1f9d6-1f3fc": { - "output": "1f9d6-1f3fc", - "name": "person in steamy room: medium-light skin tone", - "alpha_code": ":person_in_steamy_room_tone2:", - "aliases": ":person_in_steamy_room_medium_light_skin_tone:" - }, - "1f9d6-1f3fd": { - "output": "1f9d6-1f3fd", - "name": "person in steamy room: medium skin tone", - "alpha_code": ":person_in_steamy_room_tone3:", - "aliases": ":person_in_steamy_room_medium_skin_tone:" - }, - "1f9d6-1f3fe": { - "output": "1f9d6-1f3fe", - "name": "person in steamy room: medium-dark skin tone", - "alpha_code": ":person_in_steamy_room_tone4:", - "aliases": ":person_in_steamy_room_medium_dark_skin_tone:" - }, - "1f9d6-1f3ff": { - "output": "1f9d6-1f3ff", - "name": "person in steamy room: dark skin tone", - "alpha_code": ":person_in_steamy_room_tone5:", - "aliases": ":person_in_steamy_room_dark_skin_tone:" - }, - "1f9d7-1f3fb": { - "output": "1f9d7-1f3fb", - "name": "person climbing: light skin tone", - "alpha_code": ":person_climbing_tone1:", - "aliases": ":person_climbing_light_skin_tone:" - }, - "1f9d7-1f3fc": { - "output": "1f9d7-1f3fc", - "name": "person climbing: medium-light skin tone", - "alpha_code": ":person_climbing_tone2:", - "aliases": ":person_climbing_medium_light_skin_tone:" - }, - "1f9d7-1f3fd": { - "output": "1f9d7-1f3fd", - "name": "person climbing: medium skin tone", - "alpha_code": ":person_climbing_tone3:", - "aliases": ":person_climbing_medium_skin_tone:" - }, - "1f9d7-1f3fe": { - "output": "1f9d7-1f3fe", - "name": "person climbing: medium-dark skin tone", - "alpha_code": ":person_climbing_tone4:", - "aliases": ":person_climbing_medium_dark_skin_tone:" - }, - "1f9d7-1f3ff": { - "output": "1f9d7-1f3ff", - "name": "person climbing: dark skin tone", - "alpha_code": ":person_climbing_tone5:", - "aliases": ":person_climbing_dark_skin_tone:" - }, - "1f9d8-1f3fb": { - "output": "1f9d8-1f3fb", - "name": "person in lotus position: light skin tone", - "alpha_code": ":person_in_lotus_position_tone1:", - "aliases": ":person_in_lotus_position_light_skin_tone:" - }, - "1f9d8-1f3fc": { - "output": "1f9d8-1f3fc", - "name": "person in lotus position: medium-light skin tone", - "alpha_code": ":person_in_lotus_position_tone2:", - "aliases": ":person_in_lotus_position_medium_light_skin_tone:" - }, - "1f9d8-1f3fd": { - "output": "1f9d8-1f3fd", - "name": "person in lotus position: medium skin tone", - "alpha_code": ":person_in_lotus_position_tone3:", - "aliases": ":person_in_lotus_position_medium_skin_tone:" - }, - "1f9d8-1f3fe": { - "output": "1f9d8-1f3fe", - "name": "person in lotus position: medium-dark skin tone", - "alpha_code": ":person_in_lotus_position_tone4:", - "aliases": ":person_in_lotus_position_medium_dark_skin_tone:" - }, - "1f9d8-1f3ff": { - "output": "1f9d8-1f3ff", - "name": "person in lotus position: dark skin tone", - "alpha_code": ":person_in_lotus_position_tone5:", - "aliases": ":person_in_lotus_position_dark_skin_tone:" - }, - "1f9d9-1f3fb": { - "output": "1f9d9-1f3fb", - "name": "mage: light skin tone", - "alpha_code": ":mage_tone1:", - "aliases": ":mage_light_skin_tone:" - }, - "1f9d9-1f3fc": { - "output": "1f9d9-1f3fc", - "name": "mage: medium-light skin tone", - "alpha_code": ":mage_tone2:", - "aliases": ":mage_medium_light_skin_tone:" - }, - "1f9d9-1f3fd": { - "output": "1f9d9-1f3fd", - "name": "mage: medium skin tone", - "alpha_code": ":mage_tone3:", - "aliases": ":mage_medium_skin_tone:" - }, - "1f9d9-1f3fe": { - "output": "1f9d9-1f3fe", - "name": "mage: medium-dark skin tone", - "alpha_code": ":mage_tone4:", - "aliases": ":mage_medium_dark_skin_tone:" - }, - "1f9d9-1f3ff": { - "output": "1f9d9-1f3ff", - "name": "mage: dark skin tone", - "alpha_code": ":mage_tone5:", - "aliases": ":mage_dark_skin_tone:" - }, - "1f9da-1f3fb": { - "output": "1f9da-1f3fb", - "name": "fairy: light skin tone", - "alpha_code": ":fairy_tone1:", - "aliases": ":fairy_light_skin_tone:" - }, - "1f9da-1f3fc": { - "output": "1f9da-1f3fc", - "name": "fairy: medium-light skin tone", - "alpha_code": ":fairy_tone2:", - "aliases": ":fairy_medium_light_skin_tone:" - }, - "1f9da-1f3fd": { - "output": "1f9da-1f3fd", - "name": "fairy: medium skin tone", - "alpha_code": ":fairy_tone3:", - "aliases": ":fairy_medium_skin_tone:" - }, - "1f9da-1f3fe": { - "output": "1f9da-1f3fe", - "name": "fairy: medium-dark skin tone", - "alpha_code": ":fairy_tone4:", - "aliases": ":fairy_medium_dark_skin_tone:" - }, - "1f9da-1f3ff": { - "output": "1f9da-1f3ff", - "name": "fairy: dark skin tone", - "alpha_code": ":fairy_tone5:", - "aliases": ":fairy_dark_skin_tone:" - }, - "1f9db-1f3fb": { - "output": "1f9db-1f3fb", - "name": "vampire: light skin tone", - "alpha_code": ":vampire_tone1:", - "aliases": ":vampire_light_skin_tone:" - }, - "1f9db-1f3fc": { - "output": "1f9db-1f3fc", - "name": "vampire: medium-light skin tone", - "alpha_code": ":vampire_tone2:", - "aliases": ":vampire_medium_light_skin_tone:" - }, - "1f9db-1f3fd": { - "output": "1f9db-1f3fd", - "name": "vampire: medium skin tone", - "alpha_code": ":vampire_tone3:", - "aliases": ":vampire_medium_skin_tone:" - }, - "1f9db-1f3fe": { - "output": "1f9db-1f3fe", - "name": "vampire: medium-dark skin tone", - "alpha_code": ":vampire_tone4:", - "aliases": ":vampire_medium_dark_skin_tone:" - }, - "1f9db-1f3ff": { - "output": "1f9db-1f3ff", - "name": "vampire: dark skin tone", - "alpha_code": ":vampire_tone5:", - "aliases": ":vampire_dark_skin_tone:" - }, - "1f9dc-1f3fb": { - "output": "1f9dc-1f3fb", - "name": "merperson: light skin tone", - "alpha_code": ":merperson_tone1:", - "aliases": ":merperson_light_skin_tone:" - }, - "1f9dc-1f3fc": { - "output": "1f9dc-1f3fc", - "name": "merperson: medium-light skin tone", - "alpha_code": ":merperson_tone2:", - "aliases": ":merperson_medium_light_skin_tone:" - }, - "1f9dc-1f3fd": { - "output": "1f9dc-1f3fd", - "name": "merperson: medium skin tone", - "alpha_code": ":merperson_tone3:", - "aliases": ":merperson_medium_skin_tone:" - }, - "1f9dc-1f3fe": { - "output": "1f9dc-1f3fe", - "name": "merperson: medium-dark skin tone", - "alpha_code": ":merperson_tone4:", - "aliases": ":merperson_medium_dark_skin_tone:" - }, - "1f9dc-1f3ff": { - "output": "1f9dc-1f3ff", - "name": "merperson: dark skin tone", - "alpha_code": ":merperson_tone5:", - "aliases": ":merperson_dark_skin_tone:" - }, - "1f9dd-1f3fb": { - "output": "1f9dd-1f3fb", - "name": "elf: light skin tone", - "alpha_code": ":elf_tone1:", - "aliases": ":elf_light_skin_tone:" - }, - "1f9dd-1f3fc": { - "output": "1f9dd-1f3fc", - "name": "elf: medium-light skin tone", - "alpha_code": ":elf_tone2:", - "aliases": ":elf_medium_light_skin_tone:" - }, - "1f9dd-1f3fd": { - "output": "1f9dd-1f3fd", - "name": "elf: medium skin tone", - "alpha_code": ":elf_tone3:", - "aliases": ":elf_medium_skin_tone:" - }, - "1f9dd-1f3fe": { - "output": "1f9dd-1f3fe", - "name": "elf: medium-dark skin tone", - "alpha_code": ":elf_tone4:", - "aliases": ":elf_medium_dark_skin_tone:" - }, - "1f9dd-1f3ff": { - "output": "1f9dd-1f3ff", - "name": "elf: dark skin tone", - "alpha_code": ":elf_tone5:", - "aliases": ":elf_dark_skin_tone:" - }, - "1f9d9-2640": { - "output": "1f9d9-200d-2640-fe0f", - "name": "woman mage", - "alpha_code": ":woman_mage:", - "aliases": "" - }, - "1f9d9-2642": { - "output": "1f9d9-200d-2642-fe0f", - "name": "man mage", - "alpha_code": ":man_mage:", - "aliases": "" - }, - "1f9d9-1f3fb-2640": { - "output": "1f9d9-1f3fb-200d-2640-fe0f", - "name": "woman mage: light skin tone", - "alpha_code": ":woman_mage_tone1:", - "aliases": ":woman_mage_light_skin_tone:" - }, - "1f9d9-1f3fb-2642": { - "output": "1f9d9-1f3fb-200d-2642-fe0f", - "name": "man mage: light skin tone", - "alpha_code": ":man_mage_tone1:", - "aliases": ":man_mage_light_skin_tone:" - }, - "1f9d9-1f3fc-2640": { - "output": "1f9d9-1f3fc-200d-2640-fe0f", - "name": "woman mage: medium-light skin tone", - "alpha_code": ":woman_mage_tone2:", - "aliases": ":woman_mage_medium_light_skin_tone:" - }, - "1f9d9-1f3fc-2642": { - "output": "1f9d9-1f3fc-200d-2642-fe0f", - "name": "man mage: medium-light skin tone", - "alpha_code": ":man_mage_tone2:", - "aliases": ":man_mage_medium_light_skin_tone:" - }, - "1f9d9-1f3fd-2640": { - "output": "1f9d9-1f3fd-200d-2640-fe0f", - "name": "woman mage: medium skin tone", - "alpha_code": ":woman_mage_tone3:", - "aliases": ":woman_mage_medium_skin_tone:" - }, - "1f9d9-1f3fd-2642": { - "output": "1f9d9-1f3fd-200d-2642-fe0f", - "name": "man mage: medium skin tone", - "alpha_code": ":man_mage_tone3:", - "aliases": ":man_mage_medium_skin_tone:" - }, - "1f9d9-1f3fe-2640": { - "output": "1f9d9-1f3fe-200d-2640-fe0f", - "name": "woman mage: medium-dark skin tone", - "alpha_code": ":woman_mage_tone4:", - "aliases": ":woman_mage_medium_dark_skin_tone:" - }, - "1f9d9-1f3fe-2642": { - "output": "1f9d9-1f3fe-200d-2642-fe0f", - "name": "man mage: medium-dark skin tone", - "alpha_code": ":man_mage_tone4:", - "aliases": ":man_mage_medium_dark_skin_tone:" - }, - "1f9d9-1f3ff-2640": { - "output": "1f9d9-1f3ff-200d-2640-fe0f", - "name": "woman mage: dark skin tone", - "alpha_code": ":woman_mage_tone5:", - "aliases": ":woman_mage_dark_skin_tone:" - }, - "1f9d9-1f3ff-2642": { - "output": "1f9d9-1f3ff-200d-2642-fe0f", - "name": "man mage: dark skin tone", - "alpha_code": ":man_mage_tone5:", - "aliases": ":man_mage_dark_skin_tone:" - }, - "1f9da-2640": { - "output": "1f9da-200d-2640-fe0f", - "name": "woman fairy", - "alpha_code": ":woman_fairy:", - "aliases": "" - }, - "1f9da-2642": { - "output": "1f9da-200d-2642-fe0f", - "name": "man fairy", - "alpha_code": ":man_fairy:", - "aliases": "" - }, - "1f9da-1f3fb-2640": { - "output": "1f9da-1f3fb-200d-2640-fe0f", - "name": "woman fairy: light skin tone", - "alpha_code": ":woman_fairy_tone1:", - "aliases": ":woman_fairy_light_skin_tone:" - }, - "1f9da-1f3fb-2642": { - "output": "1f9da-1f3fb-200d-2642-fe0f", - "name": "man fairy: light skin tone", - "alpha_code": ":man_fairy_tone1:", - "aliases": ":man_fairy_light_skin_tone:" - }, - "1f9da-1f3fc-2640": { - "output": "1f9da-1f3fc-200d-2640-fe0f", - "name": "woman fairy: medium-light skin tone", - "alpha_code": ":woman_fairy_tone2:", - "aliases": ":woman_fairy_medium_light_skin_tone:" - }, - "1f9da-1f3fc-2642": { - "output": "1f9da-1f3fc-200d-2642-fe0f", - "name": "man fairy: medium-light skin tone", - "alpha_code": ":man_fairy_tone2:", - "aliases": ":man_fairy_medium_light_skin_tone:" - }, - "1f9da-1f3fd-2640": { - "output": "1f9da-1f3fd-200d-2640-fe0f", - "name": "woman fairy: medium skin tone", - "alpha_code": ":woman_fairy_tone3:", - "aliases": ":woman_fairy_medium_skin_tone:" - }, - "1f9da-1f3fd-2642": { - "output": "1f9da-1f3fd-200d-2642-fe0f", - "name": "man fairy: medium skin tone", - "alpha_code": ":man_fairy_tone3:", - "aliases": ":man_fairy_medium_skin_tone:" - }, - "1f9da-1f3fe-2640": { - "output": "1f9da-1f3fe-200d-2640-fe0f", - "name": "woman fairy: medium-dark skin tone", - "alpha_code": ":woman_fairy_tone4:", - "aliases": ":woman_fairy_medium_dark_skin_tone:" - }, - "1f9da-1f3fe-2642": { - "output": "1f9da-1f3fe-200d-2642-fe0f", - "name": "man fairy: medium-dark skin tone", - "alpha_code": ":man_fairy_tone4:", - "aliases": ":man_fairy_medium_dark_skin_tone:" - }, - "1f9da-1f3ff-2640": { - "output": "1f9da-1f3ff-200d-2640-fe0f", - "name": "woman fairy: dark skin tone", - "alpha_code": ":woman_fairy_tone5:", - "aliases": ":woman_fairy_dark_skin_tone:" - }, - "1f9da-1f3ff-2642": { - "output": "1f9da-1f3ff-200d-2642-fe0f", - "name": "man fairy: dark skin tone", - "alpha_code": ":man_fairy_tone5:", - "aliases": ":man_fairy_dark_skin_tone:" - }, - "1f9db-2640": { - "output": "1f9db-200d-2640-fe0f", - "name": "woman vampire", - "alpha_code": ":woman_vampire:", - "aliases": "" - }, - "1f9db-2642": { - "output": "1f9db-200d-2642-fe0f", - "name": "man vampire", - "alpha_code": ":man_vampire:", - "aliases": "" - }, - "1f9db-1f3fb-2640": { - "output": "1f9db-1f3fb-200d-2640-fe0f", - "name": "woman vampire: light skin tone", - "alpha_code": ":woman_vampire_tone1:", - "aliases": ":woman_vampire_light_skin_tone:" - }, - "1f9db-1f3fb-2642": { - "output": "1f9db-1f3fb-200d-2642-fe0f", - "name": "man vampire: light skin tone", - "alpha_code": ":man_vampire_tone1:", - "aliases": ":man_vampire_light_skin_tone:" - }, - "1f9db-1f3fc-2640": { - "output": "1f9db-1f3fc-200d-2640-fe0f", - "name": "woman vampire: medium-light skin tone", - "alpha_code": ":woman_vampire_tone2:", - "aliases": ":woman_vampire_medium_light_skin_tone:" - }, - "1f9db-1f3fc-2642": { - "output": "1f9db-1f3fc-200d-2642-fe0f", - "name": "man vampire: medium-light skin tone", - "alpha_code": ":man_vampire_tone2:", - "aliases": ":man_vampire_medium_light_skin_tone:" - }, - "1f9db-1f3fd-2640": { - "output": "1f9db-1f3fd-200d-2640-fe0f", - "name": "woman vampire: medium skin tone", - "alpha_code": ":woman_vampire_tone3:", - "aliases": ":woman_vampire_medium_skin_tone:" - }, - "1f9db-1f3fd-2642": { - "output": "1f9db-1f3fd-200d-2642-fe0f", - "name": "man vampire: medium skin tone", - "alpha_code": ":man_vampire_tone3:", - "aliases": ":man_vampire_medium_skin_tone:" - }, - "1f9db-1f3fe-2640": { - "output": "1f9db-1f3fe-200d-2640-fe0f", - "name": "woman vampire: medium-dark skin tone", - "alpha_code": ":woman_vampire_tone4:", - "aliases": ":woman_vampire_medium_dark_skin_tone:" - }, - "1f9db-1f3fe-2642": { - "output": "1f9db-1f3fe-200d-2642-fe0f", - "name": "man vampire: medium-dark skin tone", - "alpha_code": ":man_vampire_tone4:", - "aliases": ":man_vampire_medium_dark_skin_tone:" - }, - "1f9db-1f3ff-2640": { - "output": "1f9db-1f3ff-200d-2640-fe0f", - "name": "woman vampire: dark skin tone", - "alpha_code": ":woman_vampire_tone5:", - "aliases": ":woman_vampire_dark_skin_tone:" - }, - "1f9db-1f3ff-2642": { - "output": "1f9db-1f3ff-200d-2642-fe0f", - "name": "man vampire: dark skin tone", - "alpha_code": ":man_vampire_tone5:", - "aliases": ":man_vampire_dark_skin_tone:" - }, - "1f9dc-2640": { - "output": "1f9dc-200d-2640-fe0f", - "name": "mermaid", - "alpha_code": ":mermaid:", - "aliases": "" - }, - "1f9dc-2642": { - "output": "1f9dc-200d-2642-fe0f", - "name": "merman", - "alpha_code": ":merman:", - "aliases": "" - }, - "1f9dc-1f3fb-2640": { - "output": "1f9dc-1f3fb-200d-2640-fe0f", - "name": "mermaid: light skin tone", - "alpha_code": ":mermaid_tone1:", - "aliases": ":mermaid_light_skin_tone:" - }, - "1f9dc-1f3fb-2642": { - "output": "1f9dc-1f3fb-200d-2642-fe0f", - "name": "merman: light skin tone", - "alpha_code": ":merman_tone1:", - "aliases": ":merman_light_skin_tone:" - }, - "1f9dc-1f3fc-2640": { - "output": "1f9dc-1f3fc-200d-2640-fe0f", - "name": "mermaid: medium-light skin tone", - "alpha_code": ":mermaid_tone2:", - "aliases": ":mermaid_medium_light_skin_tone:" - }, - "1f9dc-1f3fc-2642": { - "output": "1f9dc-1f3fc-200d-2642-fe0f", - "name": "merman: medium-light skin tone", - "alpha_code": ":merman_tone2:", - "aliases": ":merman_medium_light_skin_tone:" - }, - "1f9dc-1f3fd-2640": { - "output": "1f9dc-1f3fd-200d-2640-fe0f", - "name": "mermaid: medium skin tone", - "alpha_code": ":mermaid_tone3:", - "aliases": ":mermaid_medium_skin_tone:" - }, - "1f9dc-1f3fd-2642": { - "output": "1f9dc-1f3fd-200d-2642-fe0f", - "name": "merman: medium skin tone", - "alpha_code": ":merman_tone3:", - "aliases": ":merman_medium_skin_tone:" - }, - "1f9dc-1f3fe-2640": { - "output": "1f9dc-1f3fe-200d-2640-fe0f", - "name": "mermaid: medium-dark skin tone", - "alpha_code": ":mermaid_tone4:", - "aliases": ":mermaid_medium_dark_skin_tone:" - }, - "1f9dc-1f3fe-2642": { - "output": "1f9dc-1f3fe-200d-2642-fe0f", - "name": "merman: medium-dark skin tone", - "alpha_code": ":merman_tone4:", - "aliases": ":merman_medium_dark_skin_tone:" - }, - "1f9dc-1f3ff-2640": { - "output": "1f9dc-1f3ff-200d-2640-fe0f", - "name": "mermaid: dark skin tone", - "alpha_code": ":mermaid_tone5:", - "aliases": ":mermaid_dark_skin_tone:" - }, - "1f9dc-1f3ff-2642": { - "output": "1f9dc-1f3ff-200d-2642-fe0f", - "name": "merman: dark skin tone", - "alpha_code": ":merman_tone5:", - "aliases": ":merman_dark_skin_tone:" - }, - "1f9dd-2640": { - "output": "1f9dd-200d-2640-fe0f", - "name": "woman elf", - "alpha_code": ":woman_elf:", - "aliases": "" - }, - "1f9dd-2642": { - "output": "1f9dd-200d-2642-fe0f", - "name": "man elf", - "alpha_code": ":man_elf:", - "aliases": "" - }, - "1f9dd-1f3fb-2640": { - "output": "1f9dd-1f3fb-200d-2640-fe0f", - "name": "woman elf: light skin tone", - "alpha_code": ":woman_elf_tone1:", - "aliases": ":woman_elf_light_skin_tone:" - }, - "1f9dd-1f3fb-2642": { - "output": "1f9dd-1f3fb-200d-2642-fe0f", - "name": "man elf: light skin tone", - "alpha_code": ":man_elf_tone1:", - "aliases": ":man_elf_light_skin_tone:" - }, - "1f9dd-1f3fc-2640": { - "output": "1f9dd-1f3fc-200d-2640-fe0f", - "name": "woman elf: medium-light skin tone", - "alpha_code": ":woman_elf_tone2:", - "aliases": ":woman_elf_medium_light_skin_tone:" - }, - "1f9dd-1f3fc-2642": { - "output": "1f9dd-1f3fc-200d-2642-fe0f", - "name": "man elf: medium-light skin tone", - "alpha_code": ":man_elf_tone2:", - "aliases": ":man_elf_medium_light_skin_tone:" - }, - "1f9dd-1f3fd-2640": { - "output": "1f9dd-1f3fd-200d-2640-fe0f", - "name": "woman elf: medium skin tone", - "alpha_code": ":woman_elf_tone3:", - "aliases": ":woman_elf_medium_skin_tone:" - }, - "1f9dd-1f3fd-2642": { - "output": "1f9dd-1f3fd-200d-2642-fe0f", - "name": "man elf: medium skin tone", - "alpha_code": ":man_elf_tone3:", - "aliases": ":man_elf_medium_skin_tone:" - }, - "1f9dd-1f3fe-2640": { - "output": "1f9dd-1f3fe-200d-2640-fe0f", - "name": "woman elf: medium-dark skin tone", - "alpha_code": ":woman_elf_tone4:", - "aliases": ":woman_elf_medium_dark_skin_tone:" - }, - "1f9dd-1f3fe-2642": { - "output": "1f9dd-1f3fe-200d-2642-fe0f", - "name": "man elf: medium-dark skin tone", - "alpha_code": ":man_elf_tone4:", - "aliases": ":man_elf_medium_dark_skin_tone:" - }, - "1f9dd-1f3ff-2640": { - "output": "1f9dd-1f3ff-200d-2640-fe0f", - "name": "woman elf: dark skin tone", - "alpha_code": ":woman_elf_tone5:", - "aliases": ":woman_elf_dark_skin_tone:" - }, - "1f9dd-1f3ff-2642": { - "output": "1f9dd-1f3ff-200d-2642-fe0f", - "name": "man elf: dark skin tone", - "alpha_code": ":man_elf_tone5:", - "aliases": ":man_elf_dark_skin_tone:" - }, - "1f9de-2640": { - "output": "1f9de-200d-2640-fe0f", - "name": "woman genie", - "alpha_code": ":woman_genie:", - "aliases": "" - }, - "1f9de-2642": { - "output": "1f9de-200d-2642-fe0f", - "name": "man genie", - "alpha_code": ":man_genie:", - "aliases": "" - }, - "1f9df-2640": { - "output": "1f9df-200d-2640-fe0f", - "name": "woman zombie", - "alpha_code": ":woman_zombie:", - "aliases": "" - }, - "1f9df-2642": { - "output": "1f9df-200d-2642-fe0f", - "name": "man zombie", - "alpha_code": ":man_zombie:", - "aliases": "" - }, - "1f9d6-2640": { - "output": "1f9d6-200d-2640-fe0f", - "name": "woman in steamy room", - "alpha_code": ":woman_in_steamy_room:", - "aliases": "" - }, - "1f9d6-2642": { - "output": "1f9d6-200d-2642-fe0f", - "name": "man in steamy room", - "alpha_code": ":man_in_steamy_room:", - "aliases": "" - }, - "1f9d6-1f3fb-2640": { - "output": "1f9d6-1f3fb-200d-2640-fe0f", - "name": "woman in steamy room: light skin tone", - "alpha_code": ":woman_in_steamy_room_tone1:", - "aliases": ":woman_in_steamy_room_light_skin_tone:" - }, - "1f9d6-1f3fb-2642": { - "output": "1f9d6-1f3fb-200d-2642-fe0f", - "name": "man in steamy room: light skin tone", - "alpha_code": ":man_in_steamy_room_tone1:", - "aliases": ":man_in_steamy_room_light_skin_tone:" - }, - "1f9d6-1f3fc-2640": { - "output": "1f9d6-1f3fc-200d-2640-fe0f", - "name": "woman in steamy room: medium-light skin tone", - "alpha_code": ":woman_in_steamy_room_tone2:", - "aliases": ":woman_in_steamy_room_medium_light_skin_tone:" - }, - "1f9d6-1f3fc-2642": { - "output": "1f9d6-1f3fc-200d-2642-fe0f", - "name": "man in steamy room: medium-light skin tone", - "alpha_code": ":man_in_steamy_room_tone2:", - "aliases": ":man_in_steamy_room_medium_light_skin_tone:" - }, - "1f9d6-1f3fd-2640": { - "output": "1f9d6-1f3fd-200d-2640-fe0f", - "name": "woman in steamy room: medium skin tone", - "alpha_code": ":woman_in_steamy_room_tone3:", - "aliases": ":woman_in_steamy_room_medium_skin_tone:" - }, - "1f9d6-1f3fd-2642": { - "output": "1f9d6-1f3fd-200d-2642-fe0f", - "name": "man in steamy room: medium skin tone", - "alpha_code": ":man_in_steamy_room_tone3:", - "aliases": ":man_in_steamy_room_medium_skin_tone:" - }, - "1f9d6-1f3fe-2640": { - "output": "1f9d6-1f3fe-200d-2640-fe0f", - "name": "woman in steamy room: medium-dark skin tone", - "alpha_code": ":woman_in_steamy_room_tone4:", - "aliases": ":woman_in_steamy_room_medium_dark_skin_tone:" - }, - "1f9d6-1f3fe-2642": { - "output": "1f9d6-1f3fe-200d-2642-fe0f", - "name": "man in steamy room: medium-dark skin tone", - "alpha_code": ":man_in_steamy_room_tone4:", - "aliases": ":man_in_steamy_room_medium_dark_skin_tone:" - }, - "1f9d6-1f3ff-2640": { - "output": "1f9d6-1f3ff-200d-2640-fe0f", - "name": "woman in steamy room: dark skin tone", - "alpha_code": ":woman_in_steamy_room_tone5:", - "aliases": ":woman_in_steamy_room_dark_skin_tone:" - }, - "1f9d6-1f3ff-2642": { - "output": "1f9d6-1f3ff-200d-2642-fe0f", - "name": "man in steamy room: dark skin tone", - "alpha_code": ":man_in_steamy_room_tone5:", - "aliases": ":man_in_steamy_room_dark_skin_tone:" - }, - "1f9d7-2640": { - "output": "1f9d7-200d-2640-fe0f", - "name": "woman climbing", - "alpha_code": ":woman_climbing:", - "aliases": "" - }, - "1f9d7-2642": { - "output": "1f9d7-200d-2642-fe0f", - "name": "man climbing", - "alpha_code": ":man_climbing:", - "aliases": "" - }, - "1f9d7-1f3fb-2640": { - "output": "1f9d7-1f3fb-200d-2640-fe0f", - "name": "woman climbing: light skin tone", - "alpha_code": ":woman_climbing_tone1:", - "aliases": ":woman_climbing_light_skin_tone:" - }, - "1f9d7-1f3fb-2642": { - "output": "1f9d7-1f3fb-200d-2642-fe0f", - "name": "man climbing: light skin tone", - "alpha_code": ":man_climbing_tone1:", - "aliases": ":man_climbing_light_skin_tone:" - }, - "1f9d7-1f3fc-2640": { - "output": "1f9d7-1f3fc-200d-2640-fe0f", - "name": "woman climbing: medium-light skin tone", - "alpha_code": ":woman_climbing_tone2:", - "aliases": ":woman_climbing_medium_light_skin_tone:" - }, - "1f9d7-1f3fc-2642": { - "output": "1f9d7-1f3fc-200d-2642-fe0f", - "name": "man climbing: medium-light skin tone", - "alpha_code": ":man_climbing_tone2:", - "aliases": ":man_climbing_medium_light_skin_tone:" - }, - "1f9d7-1f3fd-2640": { - "output": "1f9d7-1f3fd-200d-2640-fe0f", - "name": "woman climbing: medium skin tone", - "alpha_code": ":woman_climbing_tone3:", - "aliases": ":woman_climbing_medium_skin_tone:" - }, - "1f9d7-1f3fd-2642": { - "output": "1f9d7-1f3fd-200d-2642-fe0f", - "name": "man climbing: medium skin tone", - "alpha_code": ":man_climbing_tone3:", - "aliases": ":man_climbing_medium_skin_tone:" - }, - "1f9d7-1f3fe-2640": { - "output": "1f9d7-1f3fe-200d-2640-fe0f", - "name": "woman climbing: medium-dark skin tone", - "alpha_code": ":woman_climbing_tone4:", - "aliases": ":woman_climbing_medium_dark_skin_tone:" - }, - "1f9d7-1f3fe-2642": { - "output": "1f9d7-1f3fe-200d-2642-fe0f", - "name": "man climbing: medium-dark skin tone", - "alpha_code": ":man_climbing_tone4:", - "aliases": ":man_climbing_medium_dark_skin_tone:" - }, - "1f9d7-1f3ff-2640": { - "output": "1f9d7-1f3ff-200d-2640-fe0f", - "name": "woman climbing: dark skin tone", - "alpha_code": ":woman_climbing_tone5:", - "aliases": ":woman_climbing_dark_skin_tone:" - }, - "1f9d7-1f3ff-2642": { - "output": "1f9d7-1f3ff-200d-2642-fe0f", - "name": "man climbing: dark skin tone", - "alpha_code": ":man_climbing_tone5:", - "aliases": ":man_climbing_dark_skin_tone:" - }, - "1f9d8-2640": { - "output": "1f9d8-200d-2640-fe0f", - "name": "woman in lotus position", - "alpha_code": ":woman_in_lotus_position:", - "aliases": "" - }, - "1f9d8-2642": { - "output": "1f9d8-200d-2642-fe0f", - "name": "man in lotus position", - "alpha_code": ":man_in_lotus_position:", - "aliases": "" - }, - "1f9d8-1f3fb-2640": { - "output": "1f9d8-1f3fb-200d-2640-fe0f", - "name": "woman in lotus position: light skin tone", - "alpha_code": ":woman_in_lotus_position_tone1:", - "aliases": ":woman_in_lotus_position_light_skin_tone:" - }, - "1f9d8-1f3fb-2642": { - "output": "1f9d8-1f3fb-200d-2642-fe0f", - "name": "man in lotus position: light skin tone", - "alpha_code": ":man_in_lotus_position_tone1:", - "aliases": ":man_in_lotus_position_light_skin_tone:" - }, - "1f9d8-1f3fc-2640": { - "output": "1f9d8-1f3fc-200d-2640-fe0f", - "name": "woman in lotus position: medium-light skin tone", - "alpha_code": ":woman_in_lotus_position_tone2:", - "aliases": ":woman_in_lotus_position_medium_light_skin_tone:" - }, - "1f9d8-1f3fc-2642": { - "output": "1f9d8-1f3fc-200d-2642-fe0f", - "name": "man in lotus position: medium-light skin tone", - "alpha_code": ":man_in_lotus_position_tone2:", - "aliases": ":man_in_lotus_position_medium_light_skin_tone:" - }, - "1f9d8-1f3fd-2640": { - "output": "1f9d8-1f3fd-200d-2640-fe0f", - "name": "woman in lotus position: medium skin tone", - "alpha_code": ":woman_in_lotus_position_tone3:", - "aliases": ":woman_in_lotus_position_medium_skin_tone:" - }, - "1f9d8-1f3fd-2642": { - "output": "1f9d8-1f3fd-200d-2642-fe0f", - "name": "man in lotus position: medium skin tone", - "alpha_code": ":man_in_lotus_position_tone3:", - "aliases": ":man_in_lotus_position_medium_skin_tone:" - }, - "1f9d8-1f3fe-2640": { - "output": "1f9d8-1f3fe-200d-2640-fe0f", - "name": "woman in lotus position: medium-dark skin tone", - "alpha_code": ":woman_in_lotus_position_tone4:", - "aliases": ":woman_in_lotus_position_medium_dark_skin_tone:" - }, - "1f9d8-1f3fe-2642": { - "output": "1f9d8-1f3fe-200d-2642-fe0f", - "name": "man in lotus position: medium-dark skin tone", - "alpha_code": ":man_in_lotus_position_tone4:", - "aliases": ":man_in_lotus_position_medium_dark_skin_tone:" - }, - "1f9d8-1f3ff-2640": { - "output": "1f9d8-1f3ff-200d-2640-fe0f", - "name": "woman in lotus position: dark skin tone", - "alpha_code": ":woman_in_lotus_position_tone5:", - "aliases": ":woman_in_lotus_position_dark_skin_tone:" - }, - "1f9d8-1f3ff-2642": { - "output": "1f9d8-1f3ff-200d-2642-fe0f", - "name": "man in lotus position: dark skin tone", - "alpha_code": ":man_in_lotus_position_tone5:", - "aliases": ":man_in_lotus_position_dark_skin_tone:" - } -} \ No newline at end of file diff --git a/Telegram/Resources/etc/qt_linux.conf b/Telegram/Resources/etc/qt_linux.conf deleted file mode 100644 index 6d80862b5..000000000 --- a/Telegram/Resources/etc/qt_linux.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Paths] -Libraries=:/gui/art diff --git a/Telegram/Resources/etc/qt_win.conf b/Telegram/Resources/etc/qt_win.conf deleted file mode 100644 index f26ffe77f..000000000 --- a/Telegram/Resources/etc/qt_win.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Platforms] -WindowsArguments = nomousefromtouch diff --git a/Telegram/Resources/fc-custom.conf b/Telegram/Resources/fc-custom.conf deleted file mode 100644 index ab5c18306..000000000 --- a/Telegram/Resources/fc-custom.conf +++ /dev/null @@ -1,57 +0,0 @@ - - - - /usr/share/fonts - /usr/local/share/fonts - ~/.fonts - ~/.local/share/fonts - /usr/X11R6/lib/X11/fonts - fonts - - - mono - - - monospace - - - - - sans serif - - - sans-serif - - - - - sans - - - sans-serif - - - /var/cache/fontconfig_11 - fontconfig_11 - ~/.fontconfig_11 - - - true - - - false - - - true - - - hintslight - - - lcddefault - - - rgb - - - diff --git a/Telegram/Resources/fonts/OpenSans-Bold.ttf b/Telegram/Resources/fonts/OpenSans-Bold.ttf deleted file mode 100644 index fd79d43be..000000000 Binary files a/Telegram/Resources/fonts/OpenSans-Bold.ttf and /dev/null differ diff --git a/Telegram/Resources/fonts/OpenSans-Regular.ttf b/Telegram/Resources/fonts/OpenSans-Regular.ttf deleted file mode 100644 index db433349b..000000000 Binary files a/Telegram/Resources/fonts/OpenSans-Regular.ttf and /dev/null differ diff --git a/Telegram/Resources/fonts/OpenSans-Semibold.ttf b/Telegram/Resources/fonts/OpenSans-Semibold.ttf deleted file mode 100644 index 1a7679e39..000000000 Binary files a/Telegram/Resources/fonts/OpenSans-Semibold.ttf and /dev/null differ diff --git a/Telegram/Resources/icons/box_button_back.png b/Telegram/Resources/icons/box_button_back.png deleted file mode 100644 index 9db1870f6..000000000 Binary files a/Telegram/Resources/icons/box_button_back.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_button_back@2x.png b/Telegram/Resources/icons/box_button_back@2x.png deleted file mode 100644 index b729fc279..000000000 Binary files a/Telegram/Resources/icons/box_button_back@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_button_back@3x.png b/Telegram/Resources/icons/box_button_back@3x.png deleted file mode 100644 index 5e5cf8b41..000000000 Binary files a/Telegram/Resources/icons/box_button_back@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_button_close.png b/Telegram/Resources/icons/box_button_close.png deleted file mode 100644 index 3b0402893..000000000 Binary files a/Telegram/Resources/icons/box_button_close.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_button_close@2x.png b/Telegram/Resources/icons/box_button_close@2x.png deleted file mode 100644 index fea726bdb..000000000 Binary files a/Telegram/Resources/icons/box_button_close@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_button_close@3x.png b/Telegram/Resources/icons/box_button_close@3x.png deleted file mode 100644 index e818a6a97..000000000 Binary files a/Telegram/Resources/icons/box_button_close@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_search.png b/Telegram/Resources/icons/box_search.png deleted file mode 100644 index 047352607..000000000 Binary files a/Telegram/Resources/icons/box_search.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_search@2x.png b/Telegram/Resources/icons/box_search@2x.png deleted file mode 100644 index 4d2c66f86..000000000 Binary files a/Telegram/Resources/icons/box_search@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/box_search@3x.png b/Telegram/Resources/icons/box_search@3x.png deleted file mode 100644 index 3b681f682..000000000 Binary files a/Telegram/Resources/icons/box_search@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/default_checkbox_check.png b/Telegram/Resources/icons/default_checkbox_check.png deleted file mode 100644 index 574f57123..000000000 Binary files a/Telegram/Resources/icons/default_checkbox_check.png and /dev/null differ diff --git a/Telegram/Resources/icons/default_checkbox_check@2x.png b/Telegram/Resources/icons/default_checkbox_check@2x.png deleted file mode 100644 index 6d3859c84..000000000 Binary files a/Telegram/Resources/icons/default_checkbox_check@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/default_checkbox_check@3x.png b/Telegram/Resources/icons/default_checkbox_check@3x.png deleted file mode 100644 index 46f67cbde..000000000 Binary files a/Telegram/Resources/icons/default_checkbox_check@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/dropdown_submenu_arrow.png b/Telegram/Resources/icons/dropdown_submenu_arrow.png deleted file mode 100644 index d7015e7e5..000000000 Binary files a/Telegram/Resources/icons/dropdown_submenu_arrow.png and /dev/null differ diff --git a/Telegram/Resources/icons/dropdown_submenu_arrow@2x.png b/Telegram/Resources/icons/dropdown_submenu_arrow@2x.png deleted file mode 100644 index 49ca1c393..000000000 Binary files a/Telegram/Resources/icons/dropdown_submenu_arrow@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/dropdown_submenu_arrow@3x.png b/Telegram/Resources/icons/dropdown_submenu_arrow@3x.png deleted file mode 100644 index 68130c224..000000000 Binary files a/Telegram/Resources/icons/dropdown_submenu_arrow@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/fade_horizontal.png b/Telegram/Resources/icons/fade_horizontal.png deleted file mode 100644 index f10b4f924..000000000 Binary files a/Telegram/Resources/icons/fade_horizontal.png and /dev/null differ diff --git a/Telegram/Resources/icons/fade_horizontal@2x.png b/Telegram/Resources/icons/fade_horizontal@2x.png deleted file mode 100644 index ed229a5b7..000000000 Binary files a/Telegram/Resources/icons/fade_horizontal@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/fade_horizontal@3x.png b/Telegram/Resources/icons/fade_horizontal@3x.png deleted file mode 100644 index 5f7f76e80..000000000 Binary files a/Telegram/Resources/icons/fade_horizontal@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_bottom.png b/Telegram/Resources/icons/profile_divider_bottom.png deleted file mode 100644 index 31fee84f9..000000000 Binary files a/Telegram/Resources/icons/profile_divider_bottom.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_bottom@2x.png b/Telegram/Resources/icons/profile_divider_bottom@2x.png deleted file mode 100644 index 87fb65621..000000000 Binary files a/Telegram/Resources/icons/profile_divider_bottom@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_bottom@3x.png b/Telegram/Resources/icons/profile_divider_bottom@3x.png deleted file mode 100644 index 99d87293e..000000000 Binary files a/Telegram/Resources/icons/profile_divider_bottom@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_left.png b/Telegram/Resources/icons/profile_divider_left.png deleted file mode 100644 index 9bcfd455e..000000000 Binary files a/Telegram/Resources/icons/profile_divider_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_left@2x.png b/Telegram/Resources/icons/profile_divider_left@2x.png deleted file mode 100644 index b4488556c..000000000 Binary files a/Telegram/Resources/icons/profile_divider_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_left@3x.png b/Telegram/Resources/icons/profile_divider_left@3x.png deleted file mode 100644 index ccf2312a9..000000000 Binary files a/Telegram/Resources/icons/profile_divider_left@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_top.png b/Telegram/Resources/icons/profile_divider_top.png deleted file mode 100644 index 6dcdc143c..000000000 Binary files a/Telegram/Resources/icons/profile_divider_top.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_top@2x.png b/Telegram/Resources/icons/profile_divider_top@2x.png deleted file mode 100644 index 5bc32a739..000000000 Binary files a/Telegram/Resources/icons/profile_divider_top@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/profile_divider_top@3x.png b/Telegram/Resources/icons/profile_divider_top@3x.png deleted file mode 100644 index 938e1e1c2..000000000 Binary files a/Telegram/Resources/icons/profile_divider_top@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_bottom.png b/Telegram/Resources/icons/round_shadow_bottom.png deleted file mode 100644 index 28ff21173..000000000 Binary files a/Telegram/Resources/icons/round_shadow_bottom.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_bottom@2x.png b/Telegram/Resources/icons/round_shadow_bottom@2x.png deleted file mode 100644 index a64ca5c8e..000000000 Binary files a/Telegram/Resources/icons/round_shadow_bottom@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_bottom@3x.png b/Telegram/Resources/icons/round_shadow_bottom@3x.png deleted file mode 100644 index ab45b1bf0..000000000 Binary files a/Telegram/Resources/icons/round_shadow_bottom@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_bottom_left.png b/Telegram/Resources/icons/round_shadow_bottom_left.png deleted file mode 100644 index 8beb9a7e1..000000000 Binary files a/Telegram/Resources/icons/round_shadow_bottom_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_bottom_left@2x.png b/Telegram/Resources/icons/round_shadow_bottom_left@2x.png deleted file mode 100644 index c1704521b..000000000 Binary files a/Telegram/Resources/icons/round_shadow_bottom_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_bottom_left@3x.png b/Telegram/Resources/icons/round_shadow_bottom_left@3x.png deleted file mode 100644 index 0e9606078..000000000 Binary files a/Telegram/Resources/icons/round_shadow_bottom_left@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_bottom.png b/Telegram/Resources/icons/round_shadow_box_bottom.png deleted file mode 100644 index 379c612d9..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_bottom.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_bottom@2x.png b/Telegram/Resources/icons/round_shadow_box_bottom@2x.png deleted file mode 100644 index 27561668a..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_bottom@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_bottom@3x.png b/Telegram/Resources/icons/round_shadow_box_bottom@3x.png deleted file mode 100644 index 5bd515309..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_bottom@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_bottom_left.png b/Telegram/Resources/icons/round_shadow_box_bottom_left.png deleted file mode 100644 index 3bb8de356..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_bottom_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_bottom_left@2x.png b/Telegram/Resources/icons/round_shadow_box_bottom_left@2x.png deleted file mode 100644 index f31b3eb92..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_bottom_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_bottom_left@3x.png b/Telegram/Resources/icons/round_shadow_box_bottom_left@3x.png deleted file mode 100644 index a8b2b8d0b..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_bottom_left@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_left.png b/Telegram/Resources/icons/round_shadow_box_left.png deleted file mode 100644 index 7f5e183c9..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_left@2x.png b/Telegram/Resources/icons/round_shadow_box_left@2x.png deleted file mode 100644 index 1e2807341..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_left@3x.png b/Telegram/Resources/icons/round_shadow_box_left@3x.png deleted file mode 100644 index f52dac893..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_left@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_top.png b/Telegram/Resources/icons/round_shadow_box_top.png deleted file mode 100644 index f2ff11208..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_top.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_top@2x.png b/Telegram/Resources/icons/round_shadow_box_top@2x.png deleted file mode 100644 index 37eb98892..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_top@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_top@3x.png b/Telegram/Resources/icons/round_shadow_box_top@3x.png deleted file mode 100644 index 96de2ada8..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_top@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_top_left.png b/Telegram/Resources/icons/round_shadow_box_top_left.png deleted file mode 100644 index a5736889a..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_top_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_top_left@2x.png b/Telegram/Resources/icons/round_shadow_box_top_left@2x.png deleted file mode 100644 index b67f40c1b..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_top_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_box_top_left@3x.png b/Telegram/Resources/icons/round_shadow_box_top_left@3x.png deleted file mode 100644 index d8e5c7fb1..000000000 Binary files a/Telegram/Resources/icons/round_shadow_box_top_left@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_left.png b/Telegram/Resources/icons/round_shadow_left.png deleted file mode 100644 index e7df24dc1..000000000 Binary files a/Telegram/Resources/icons/round_shadow_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_left@2x.png b/Telegram/Resources/icons/round_shadow_left@2x.png deleted file mode 100644 index 2f78de2ab..000000000 Binary files a/Telegram/Resources/icons/round_shadow_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_left@3x.png b/Telegram/Resources/icons/round_shadow_left@3x.png deleted file mode 100644 index 2431067e2..000000000 Binary files a/Telegram/Resources/icons/round_shadow_left@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_top.png b/Telegram/Resources/icons/round_shadow_top.png deleted file mode 100644 index 39edc4a4e..000000000 Binary files a/Telegram/Resources/icons/round_shadow_top.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_top@2x.png b/Telegram/Resources/icons/round_shadow_top@2x.png deleted file mode 100644 index af421f2a0..000000000 Binary files a/Telegram/Resources/icons/round_shadow_top@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_top@3x.png b/Telegram/Resources/icons/round_shadow_top@3x.png deleted file mode 100644 index 5e3c7b6ac..000000000 Binary files a/Telegram/Resources/icons/round_shadow_top@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_top_left.png b/Telegram/Resources/icons/round_shadow_top_left.png deleted file mode 100644 index 555aeb74d..000000000 Binary files a/Telegram/Resources/icons/round_shadow_top_left.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_top_left@2x.png b/Telegram/Resources/icons/round_shadow_top_left@2x.png deleted file mode 100644 index f8f634c11..000000000 Binary files a/Telegram/Resources/icons/round_shadow_top_left@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/round_shadow_top_left@3x.png b/Telegram/Resources/icons/round_shadow_top_left@3x.png deleted file mode 100644 index 16d3a6862..000000000 Binary files a/Telegram/Resources/icons/round_shadow_top_left@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/simple_close.png b/Telegram/Resources/icons/simple_close.png deleted file mode 100644 index 10f8b030e..000000000 Binary files a/Telegram/Resources/icons/simple_close.png and /dev/null differ diff --git a/Telegram/Resources/icons/simple_close@2x.png b/Telegram/Resources/icons/simple_close@2x.png deleted file mode 100644 index a53c4af64..000000000 Binary files a/Telegram/Resources/icons/simple_close@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/simple_close@3x.png b/Telegram/Resources/icons/simple_close@3x.png deleted file mode 100644 index 5a5f81703..000000000 Binary files a/Telegram/Resources/icons/simple_close@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/slide_shadow.png b/Telegram/Resources/icons/slide_shadow.png deleted file mode 100644 index 7fabf2120..000000000 Binary files a/Telegram/Resources/icons/slide_shadow.png and /dev/null differ diff --git a/Telegram/Resources/icons/slide_shadow@2x.png b/Telegram/Resources/icons/slide_shadow@2x.png deleted file mode 100644 index a0f886820..000000000 Binary files a/Telegram/Resources/icons/slide_shadow@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/slide_shadow@3x.png b/Telegram/Resources/icons/slide_shadow@3x.png deleted file mode 100644 index a67d341e0..000000000 Binary files a/Telegram/Resources/icons/slide_shadow@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_menu_dots.png b/Telegram/Resources/icons/title_menu_dots.png deleted file mode 100644 index 228a2a3bc..000000000 Binary files a/Telegram/Resources/icons/title_menu_dots.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_menu_dots@2x.png b/Telegram/Resources/icons/title_menu_dots@2x.png deleted file mode 100644 index 0020d07f1..000000000 Binary files a/Telegram/Resources/icons/title_menu_dots@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/title_menu_dots@3x.png b/Telegram/Resources/icons/title_menu_dots@3x.png deleted file mode 100644 index 029087a43..000000000 Binary files a/Telegram/Resources/icons/title_menu_dots@3x.png and /dev/null differ diff --git a/Telegram/Resources/langs/download.sh b/Telegram/Resources/langs/download.sh index 92f1ef1db..a4da69404 100755 --- a/Telegram/Resources/langs/download.sh +++ b/Telegram/Resources/langs/download.sh @@ -5,7 +5,7 @@ pushd `dirname $0` > /dev/null FullScriptPath=`pwd` popd > /dev/null -if [ ! -d "$FullScriptPath/../../../../TelegramPrivate" ]; then +if [ ! -d "$FullScriptPath/../../../../DesktopPrivate" ]; then echo "" echo "This script is for building the production version of Telegram Desktop." echo "" diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index dc0c67ad1..23642665f 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -410,6 +410,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_enable_animations" = "Enable animations"; "lng_settings_autoplay_gifs" = "Autoplay GIFs"; +"lng_settings_spellchecker" = "Spell checker"; +"lng_settings_system_spellchecker" = "Use system spell checker"; + "lng_backgrounds_header" = "Choose your new chat background"; "lng_theme_sure_keep" = "Keep this theme?"; "lng_theme_reverting#one" = "Reverting to the old theme in {count} second."; @@ -1591,6 +1594,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_formatting_link_url" = "URL"; "lng_formatting_link_create" = "Create"; +"lng_spellchecker_add" = "Add to Dictionary"; +"lng_spellchecker_remove" = "Remove from Dictionary"; +"lng_spellchecker_ignore" = "Ignore word"; + "lng_full_name" = "{first_name} {last_name}"; "lng_confirm_phone_link_invalid" = "This link is broken or has expired."; diff --git a/Telegram/Resources/langs/refresh.sh b/Telegram/Resources/langs/refresh.sh index 033b37382..cd705f35f 100755 --- a/Telegram/Resources/langs/refresh.sh +++ b/Telegram/Resources/langs/refresh.sh @@ -6,7 +6,7 @@ popd > /dev/null FileName="$1" -if [ ! -d "$FullScriptPath/../../../../TelegramPrivate" ]; then +if [ ! -d "$FullScriptPath/../../../../DesktopPrivate" ]; then echo "" echo "This script is for building the production version of Telegram Desktop." echo "" diff --git a/Telegram/Resources/langs/upload.sh b/Telegram/Resources/langs/upload.sh index e20706990..fcbf4f2a0 100755 --- a/Telegram/Resources/langs/upload.sh +++ b/Telegram/Resources/langs/upload.sh @@ -5,7 +5,7 @@ pushd `dirname $0` > /dev/null FullScriptPath=`pwd` popd > /dev/null -if [ ! -d "$FullScriptPath/../../../../TelegramPrivate" ]; then +if [ ! -d "$FullScriptPath/../../../../DesktopPrivate" ]; then echo "" echo "This script is for building the production version of Telegram Desktop." echo "" diff --git a/Telegram/Resources/qrc/fonts.qrc b/Telegram/Resources/qrc/fonts.qrc deleted file mode 100644 index 233b8d572..000000000 --- a/Telegram/Resources/qrc/fonts.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - ../fonts/OpenSans-Regular.ttf - ../fonts/OpenSans-Bold.ttf - ../fonts/OpenSans-Semibold.ttf - - diff --git a/Telegram/Resources/qrc/linux.qrc b/Telegram/Resources/qrc/linux.qrc deleted file mode 100644 index 164e8d4f2..000000000 --- a/Telegram/Resources/qrc/linux.qrc +++ /dev/null @@ -1,8 +0,0 @@ - - - ../etc/qt_linux.conf - - - ../fc-custom.conf - - diff --git a/Telegram/Resources/qrc/mac.qrc b/Telegram/Resources/qrc/mac.qrc deleted file mode 100644 index 03585ec03..000000000 --- a/Telegram/Resources/qrc/mac.qrc +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/Telegram/Resources/qrc/wnd.qrc b/Telegram/Resources/qrc/wnd.qrc deleted file mode 100644 index 447387bfb..000000000 --- a/Telegram/Resources/qrc/wnd.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - ../etc/qt_win.conf - - diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index e3c12c904..5baf29966 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -1078,6 +1078,10 @@ theme#f7d90ce0 flags:# creator:flags.0?true default:flags.1?true id:long access_ account.themesNotModified#f41eb622 = account.Themes; account.themes#7f676421 hash:int themes:Vector = account.Themes; +wallet.liteResponse#764386d7 response:bytes = wallet.LiteResponse; + +wallet.secretSalt#dd484d64 salt:bytes = wallet.KeySecretSalt; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1415,4 +1419,7 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua folders.editPeerFolders#6847d0ab folder_peers:Vector = Updates; folders.deleteFolder#1c295881 folder_id:int = Updates; -// LAYER 105 +wallet.sendLiteRequest#e2c9d33e body:bytes = wallet.LiteResponse; +wallet.getKeySecretSalt#b57f346 revoke:Bool = wallet.KeySecretSalt; + +// LAYER 106 diff --git a/Telegram/Resources/tl/mtproto.tl b/Telegram/Resources/tl/mtproto.tl index 1b26ca9a2..83a770292 100644 --- a/Telegram/Resources/tl/mtproto.tl +++ b/Telegram/Resources/tl/mtproto.tl @@ -1,6 +1,14 @@ // Core types (no need to gen) -//vector#1cb5c415 {t:Type} # [ t ] = Vector t; +int ? = Int; +long ? = Long; +double ? = Double; +string ? = String; + +vector {t:Type} # [ t ] = Vector t; + +int128 4*[ int ] = Int128; +int256 8*[ int ] = Int256; /////////////////////////////// /// Authorization key creation diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index 7904b4d0e..05919fb20 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -9,7 +9,7 @@ + Version="1.9.0.0" /> Telegram Desktop Telegram FZ-LLC diff --git a/Telegram/SourceFiles/_other/packer.cpp b/Telegram/SourceFiles/_other/packer.cpp index 971a78532..f13efda4f 100644 --- a/Telegram/SourceFiles/_other/packer.cpp +++ b/Telegram/SourceFiles/_other/packer.cpp @@ -35,8 +35,8 @@ v1/0UnkegO4jNkSY3ycDqn+T3NjxNxnL0EsKh7MjinyMUe3ZISzaIyrdq/8v4bvB\n\ extern const char *PrivateKey; extern const char *PrivateBetaKey; -#include "../../../../TelegramPrivate/packer_private.h" // RSA PRIVATE KEYS for update signing -#include "../../../../TelegramPrivate/alpha_private.h" // private key for alpha version file generation +#include "../../../../DesktopPrivate/packer_private.h" // RSA PRIVATE KEYS for update signing +#include "../../../../DesktopPrivate/alpha_private.h" // private key for alpha version file generation QString countAlphaVersionSignature(quint64 version); @@ -148,7 +148,7 @@ int main(int argc, char *argv[]) QString remove; int version = 0; - bool target32 = false; + bool targetosx = false; QFileInfoList files; for (int i = 0; i < argc; ++i) { if (string("-path") == argv[i] && i + 1 < argc) { @@ -157,7 +157,7 @@ int main(int argc, char *argv[]) files.push_back(info); if (remove.isEmpty()) remove = info.canonicalPath() + "/"; } else if (string("-target") == argv[i] && i + 1 < argc) { - target32 = (string("mac32") == argv[i + 1]); + targetosx = (string("osx") == argv[i + 1]); } else if (string("-version") == argv[i] && i + 1 < argc) { version = QString(argv[i + 1]).toInt(); } else if (string("-beta") == argv[i]) { @@ -466,7 +466,7 @@ int main(int argc, char *argv[]) #ifdef Q_OS_WIN QString outName(QString("tupdate%1").arg(AlphaVersion ? AlphaVersion : version)); #elif defined Q_OS_MAC - QString outName((target32 ? QString("tmac32upd%1") : QString("tmacupd%1")).arg(AlphaVersion ? AlphaVersion : version)); + QString outName((targetosx ? QString("tosxupd%1") : QString("tmacupd%1")).arg(AlphaVersion ? AlphaVersion : version)); #elif defined Q_OS_LINUX32 QString outName(QString("tlinux32upd%1").arg(AlphaVersion ? AlphaVersion : version)); #elif defined Q_OS_LINUX64 diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index e5ad1c9a6..b33afa76a 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "base/openssl_help.h" #include "base/unixtime.h" +#include "base/call_delayed.h" #include "observer_peer.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -361,7 +362,7 @@ void ApiWrap::requestTermsUpdate() { } const auto now = crl::now(); if (_termsUpdateSendAt && now < _termsUpdateSendAt) { - App::CallDelayed(_termsUpdateSendAt - now, _session, [=] { + base::call_delayed(_termsUpdateSendAt - now, _session, [=] { requestTermsUpdate(); }); return; @@ -1283,7 +1284,7 @@ void ApiWrap::gotUserFull( const auto &d = result.c_userFull(); if (user == _session->user() && !_session->validateSelf(d.vuser())) { constexpr auto kRequestUserAgainTimeout = crl::time(10000); - App::CallDelayed(kRequestUserAgainTimeout, _session, [=] { + base::call_delayed(kRequestUserAgainTimeout, _session, [=] { requestFullPeer(user); }); return; @@ -2810,7 +2811,7 @@ void ApiWrap::requestAttachedStickerSets(not_null photo) { : MTP_inputStickerSetShortName(setData->vshort_name()); Ui::show( Box(App::wnd()->sessionController(), setId), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }).fail([=](const RPCError &error) { Ui::show(Box(tr::lng_stickers_not_found(tr::now))); }).send(); @@ -4903,7 +4904,7 @@ void ApiWrap::editUploadedFile( _session->data().sendHistoryChangeNotifications(); Ui::show( Box(tr::lng_edit_media_invalid_file(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } else { sendMessageFail(error, peer); } diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 916b0ed02..e783d4a62 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -45,7 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_mediaview.h" #include "styles/style_chat_helpers.h" #include "styles/style_history.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" #include #include diff --git a/Telegram/SourceFiles/base/algorithm.h b/Telegram/SourceFiles/base/algorithm.h deleted file mode 100644 index fbf53e94c..000000000 --- a/Telegram/SourceFiles/base/algorithm.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -inline Type take(Type &value) { - return std::exchange(value, Type {}); -} - -template -inline Type duplicate(const Type &value) { - return value; -} - -template -inline constexpr size_t array_size(const Type(&)[Size]) { - return Size; -} - -template -inline bool contains(const Container &container, const T &value) { - const auto end = std::end(container); - return std::find(std::begin(container), end, value) != end; -} - -template -inline constexpr D up_cast(T object) { - using DV = std::decay_t; - using TV = std::decay_t; - if constexpr (std::is_base_of_v) { - return object; - } else { - return nullptr; - } -} - -// We need a custom comparator for set>::find to work with pointers. -// thanks to http://stackoverflow.com/questions/18939882/raw-pointer-lookup-for-sets-of-unique-ptrs -template -struct pointer_comparator { - using is_transparent = std::true_type; - - // helper does some magic in order to reduce the number of - // pairs of types we need to know how to compare: it turns - // everything into a pointer, and then uses `std::less` - // to do the comparison: - struct helper { - const T *ptr = nullptr; - helper() = default; - helper(const helper &other) = default; - helper(const T *p) : ptr(p) { - } - template - helper(const std::shared_ptr &other) : ptr(other.get()) { - } - template - helper(const std::unique_ptr &other) : ptr(other.get()) { - } - bool operator<(helper other) const { - return std::less()(ptr, other.ptr); - } - }; - - // without helper, we'd need 2^n different overloads, where - // n is the number of types we want to support (so, 8 with - // raw pointers, unique pointers, and shared pointers). That - // seems silly. - // && helps enforce rvalue use only - bool operator()(const helper &&lhs, const helper &&rhs) const { - return lhs < rhs; - } - -}; - -inline QString FromUtf8Safe(const char *string, int size = -1) { - if (!string || !size) { - return QString(); - } else if (size < 0) { - size = strlen(string); - } - const auto result = QString::fromUtf8(string, size); - const auto back = result.toUtf8(); - return (back.size() != size || memcmp(back.constData(), string, size)) - ? QString::fromLocal8Bit(string, size) - : result; -} - -inline QString FromUtf8Safe(const QByteArray &string) { - return FromUtf8Safe(string.constData(), string.size()); -} - -} // namespace base - -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 -QLatin1String qstr(const char(&string)[Size]) { - return QLatin1String(string, Size - 1); -} diff --git a/Telegram/SourceFiles/base/algorithm_tests.cpp b/Telegram/SourceFiles/base/algorithm_tests.cpp deleted file mode 100644 index 9e3df829f..000000000 --- a/Telegram/SourceFiles/base/algorithm_tests.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/index_based_iterator.h" - -TEST_CASE("index_based_iterator tests", "[base::algorithm]") { - auto v = std::vector(); - - v.insert(v.end(), { 1, 2, 3, 4, 5, 4, 3, 2, 1 }); - auto push_back_safe_remove_if = [](auto &v, auto predicate) { - auto begin = base::index_based_begin(v); - auto end = base::index_based_end(v); - auto from = std::remove_if(begin, end, predicate); - if (from != end) { - auto newEnd = base::index_based_end(v); - if (newEnd != end) { - REQUIRE(newEnd > end); - while (end != newEnd) { - *from++ = *end++; - } - } - v.erase(from.base(), newEnd.base()); - } - }; - SECTION("allows to push_back from predicate") { - push_back_safe_remove_if(v, [&v](int value) { - v.push_back(value); - return (value % 2) == 1; - }); - auto expected = std::vector { 2, 4, 4, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1 }; - REQUIRE(v == expected); - } - - SECTION("allows to push_back while removing all") { - push_back_safe_remove_if(v, [&v](int value) { - if (value == 5) { - v.push_back(value); - } - return true; - }); - auto expected = std::vector { 5 }; - REQUIRE(v == expected); - } -} \ No newline at end of file diff --git a/Telegram/SourceFiles/base/assertion.h b/Telegram/SourceFiles/base/assertion.h deleted file mode 100644 index d7907a583..000000000 --- a/Telegram/SourceFiles/base/assertion.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -// Ensures/Expects. -#include - -namespace base { -namespace assertion { - -// Client must define that method. -void log(const char *message, const char *file, int line); - -// Release build assertions. -inline constexpr void noop() { -} - -[[noreturn]] inline void fail( - const char *message, - const char *file, - int line) { - log(message, file, line); - - // Crash with access violation and generate crash report. - volatile auto nullptr_value = (int*)nullptr; - *nullptr_value = 0; - - // Silent the possible failure to comply noreturn warning. - std::abort(); -} - -constexpr const char* extract_basename(const char* path, size_t size) { - while (size != 0 && path[size - 1] != '/' && path[size - 1] != '\\') { - --size; - } - return path + size; -} - -} // namespace assertion -} // namespace base - -#if defined(__clang__) || defined(__GNUC__) -#define AssertUnlikelyHelper(x) __builtin_expect(!!(x), 0) -#else -#define AssertUnlikelyHelper(x) (!!(x)) -#endif - -#define AssertValidationCondition(condition, message, file, line)\ - ((AssertUnlikelyHelper(!(condition)))\ - ? ::base::assertion::fail(message, file, line)\ - : ::base::assertion::noop()) - -#define SOURCE_FILE_BASENAME (::base::assertion::extract_basename(\ - __FILE__,\ - sizeof(__FILE__))) - -#define AssertCustom(condition, message) (AssertValidationCondition(\ - condition,\ - message,\ - SOURCE_FILE_BASENAME,\ - __LINE__)) -#define Assert(condition) AssertCustom(condition, "\"" #condition "\"") - -// Define our own versions of Expects() and Ensures(). -// Let them crash with reports and logging. -#ifdef Expects -#undef Expects -#endif // Expects -#define Expects(condition) (AssertValidationCondition(\ - condition,\ - "\"" #condition "\"",\ - SOURCE_FILE_BASENAME,\ - __LINE__)) - -#ifdef Ensures -#undef Ensures -#endif // Ensures -#define Ensures(condition) (AssertValidationCondition(\ - condition,\ - "\"" #condition "\"",\ - SOURCE_FILE_BASENAME,\ - __LINE__)) - -#ifdef Unexpected -#undef Unexpected -#endif // Unexpected -#define Unexpected(message) (::base::assertion::fail(\ - "Unexpected: " message,\ - SOURCE_FILE_BASENAME,\ - __LINE__)) - -#ifdef _DEBUG -#define AssertIsDebug(...) -#endif // _DEBUG diff --git a/Telegram/SourceFiles/base/base_integration.h b/Telegram/SourceFiles/base/base_integration.h deleted file mode 100644 index 397e4736c..000000000 --- a/Telegram/SourceFiles/base/base_integration.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/basic_types.h" - -// Methods that must be implemented outside lib_base. - -namespace base { - -void EnterFromEventLoop(FnMut &&method); - -} // namespace diff --git a/Telegram/SourceFiles/base/base_pch.cpp b/Telegram/SourceFiles/base/base_pch.cpp deleted file mode 100644 index 33c7d3279..000000000 --- a/Telegram/SourceFiles/base/base_pch.cpp +++ /dev/null @@ -1,10 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/base_pch.h" - -// Precompiled header helper. diff --git a/Telegram/SourceFiles/base/base_pch.h b/Telegram/SourceFiles/base/base_pch.h deleted file mode 100644 index 933cf5b25..000000000 --- a/Telegram/SourceFiles/base/base_pch.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -#include "base/flat_map.h" -#include "base/flat_set.h" -#include "base/optional.h" -#include "base/openssl_help.h" diff --git a/Telegram/SourceFiles/base/basic_types.h b/Telegram/SourceFiles/base/basic_types.h deleted file mode 100644 index bd5ec4059..000000000 --- a/Telegram/SourceFiles/base/basic_types.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/build_config.h" -#include "base/ordered_set.h" -#include "base/unique_function.h" -#include "base/functors.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace func = base::functors; - -using gsl::not_null; -using index_type = gsl::index; -using size_type = gsl::index; - -template -using Fn = std::function; - -template -using FnMut = base::unique_function; - -//using uchar = unsigned char; // Qt has uchar -using int8 = qint8; -using uint8 = quint8; -using int16 = qint16; -using uint16 = quint16; -using int32 = qint32; -using uint32 = quint32; -using int64 = qint64; -using uint64 = quint64; -using float32 = float; -using float64 = double; - -using TimeId = int32; - -// Define specializations for QByteArray for Qt 5.3.2, because -// QByteArray in Qt 5.3.2 doesn't declare "pointer" subtype. -#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) -namespace gsl { - -template <> -inline span make_span(QByteArray &cont) { - return span(cont.data(), cont.size()); -} - -template <> -inline span make_span(const QByteArray &cont) { - return span(cont.constData(), cont.size()); -} - -} // namespace gsl -#endif // OS_MAC_OLD diff --git a/Telegram/SourceFiles/base/binary_guard.h b/Telegram/SourceFiles/base/binary_guard.h deleted file mode 100644 index 2f0978999..000000000 --- a/Telegram/SourceFiles/base/binary_guard.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/algorithm.h" - -#include - -namespace base { - -class binary_guard { -public: - binary_guard() = default; - binary_guard(binary_guard &&other); - binary_guard &operator=(binary_guard &&other); - ~binary_guard(); - - binary_guard &operator=(std::nullptr_t); - - bool alive() const; - binary_guard make_guard(); - - explicit operator bool() const; - -private: - void destroy(); - - std::atomic *_bothAlive = nullptr; - -}; - -inline binary_guard::binary_guard(binary_guard &&other) -: _bothAlive(base::take(other._bothAlive)) { -} - -inline binary_guard &binary_guard::operator=(binary_guard &&other) { - if (this != &other) { - destroy(); - _bothAlive = base::take(other._bothAlive); - } - return *this; -} - -inline binary_guard::~binary_guard() { - destroy(); -} - -inline binary_guard &binary_guard::operator=(std::nullptr_t) { - destroy(); - return *this; -} - -inline binary_guard::operator bool() const { - return alive(); -} - -inline bool binary_guard::alive() const { - return _bothAlive && _bothAlive->load(); -} - -inline void binary_guard::destroy() { - if (const auto both = base::take(_bothAlive)) { - auto old = true; - if (!both->compare_exchange_strong(old, false)) { - delete both; - } - } -} - -inline binary_guard binary_guard::make_guard() { - destroy(); - - auto result = binary_guard(); - _bothAlive = result._bothAlive = new std::atomic(true); - return result; -} - -} // namespace base - -namespace crl { - -template -struct guard_traits; - -template <> -struct guard_traits { - static base::binary_guard create(base::binary_guard value) { - return value; - } - static bool check(const base::binary_guard &guard) { - return guard.alive(); - } - -}; - -} // namespace crl diff --git a/Telegram/SourceFiles/base/build_config.h b/Telegram/SourceFiles/base/build_config.h deleted file mode 100644 index 3bcb5952a..000000000 --- a/Telegram/SourceFiles/base/build_config.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -// thanks Chromium - -#if defined(__APPLE__) -#define OS_MAC 1 -#elif defined(__linux__) // __APPLE__ -#define OS_LINUX 1 -#elif defined(_WIN32) // __APPLE__ || __linux__ -#define OS_WIN 1 -#else // __APPLE__ || __linux__ || _WIN32 -#error Please add support for your platform in base/build_config.h -#endif // else for __APPLE__ || __linux__ || _WIN32 - -// For access to standard POSIXish features, use OS_POSIX instead of a -// more specific macro. -#if defined(OS_MAC) || defined(OS_LINUX) -#define OS_POSIX 1 -#endif // OS_MAC || OS_LINUX - -// Compiler detection. -#if defined(__clang__) -#define COMPILER_CLANG 1 -#elif defined(__GNUC__) // __clang__ -#define COMPILER_GCC 1 -#elif defined(_MSC_VER) // __clang__ || __GNUC__ -#define COMPILER_MSVC 1 -#else // _MSC_VER || __clang__ || __GNUC__ -#error Please add support for your compiler in base/build_config.h -#endif // else for _MSC_VER || __clang__ || __GNUC__ - -// Processor architecture detection. -#if defined(_M_X64) || defined(__x86_64__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86_64 1 -#define ARCH_CPU_64_BITS 1 -#elif defined(_M_IX86) || defined(__i386__) -#define ARCH_CPU_X86_FAMILY 1 -#define ARCH_CPU_X86 1 -#define ARCH_CPU_32_BITS 1 -#elif defined(__aarch64__) -#define ARCH_CPU_64_BITS 1 -#elif defined(_M_ARM) || defined(__arm__) -#define ARCH_CPU_32_BITS 1 -#else -#error Please add support for your architecture in base/build_config.h -#endif - -#if defined(__GNUC__) -#define TG_FORCE_INLINE inline __attribute__((always_inline)) -#elif defined(_MSC_VER) -#define TG_FORCE_INLINE __forceinline -#else -#define TG_FORCE_INLINE inline -#endif - -#include -static_assert(CHAR_BIT == 8, "Not supported char size."); diff --git a/Telegram/SourceFiles/base/bytes.h b/Telegram/SourceFiles/base/bytes.h deleted file mode 100644 index 3810e1b4a..000000000 --- a/Telegram/SourceFiles/base/bytes.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/basic_types.h" -#include -#include -#include -#include - -namespace bytes { - -using type = gsl::byte; -using span = gsl::span; -using const_span = gsl::span; -using vector = std::vector; - -template -using array = std::array; - -inline span make_detached_span(QByteArray &container) { - return gsl::as_writeable_bytes(gsl::make_span(container)); -} - -template < - typename Container, - typename = std::enable_if_t< - !std::is_const_v - && !std::is_same_v>> -inline span make_span(Container &container) { - return gsl::as_writeable_bytes(gsl::make_span(container)); -} - -template -inline const_span make_span(const Container &container) { - return gsl::as_bytes(gsl::make_span(container)); -} - -template -inline span make_span(gsl::span container) { - return gsl::as_writeable_bytes(container); -} - -template -inline const_span make_span(gsl::span container) { - return gsl::as_bytes(container); -} - -template -inline span make_span(Type *value, std::size_t count) { - return gsl::as_writeable_bytes(gsl::make_span(value, count)); -} - -template -inline const_span make_span(const Type *value, std::size_t count) { - return gsl::as_bytes(gsl::make_span(value, count)); -} - -template -inline span object_as_span(Type *value) { - return bytes::make_span(value, 1); -} - -template -inline const_span object_as_span(const Type *value) { - return bytes::make_span(value, 1); -} - -template -inline vector make_vector(const Container &container) { - const auto buffer = bytes::make_span(container); - return { buffer.begin(), buffer.end() }; -} - -inline void copy(span destination, const_span source) { - Expects(destination.size() >= source.size()); - - memcpy(destination.data(), source.data(), source.size()); -} - -inline void move(span destination, const_span source) { - Expects(destination.size() >= source.size()); - - memmove(destination.data(), source.data(), source.size()); -} - -inline void set_with_const(span destination, type value) { - memset( - destination.data(), - gsl::to_integer(value), - destination.size()); -} - -inline int compare(const_span a, const_span b) { - const auto aSize = a.size(), bSize = b.size(); - return (aSize > bSize) - ? 1 - : (aSize < bSize) - ? -1 - : memcmp(a.data(), b.data(), aSize); -} - -namespace details { - -template -std::size_t spansLength(Arg &&arg) { - return bytes::make_span(arg).size(); -} - -template -std::size_t spansLength(Arg &&arg, Args &&...args) { - return bytes::make_span(arg).size() + spansLength(args...); -} - -template -void spansAppend(span destination, Arg &&arg) { - bytes::copy(destination, bytes::make_span(arg)); -} - -template -void spansAppend(span destination, Arg &&arg, Args &&...args) { - const auto data = bytes::make_span(arg); - bytes::copy(destination, data); - spansAppend(destination.subspan(data.size()), args...); -} - -} // namespace details - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -vector concatenate(Args &&...args) { - const auto size = details::spansLength(args...); - auto result = vector(size); - details::spansAppend(make_span(result), args...); - return result; -} - -template < - typename SpanRange> -vector concatenate(SpanRange args) { - auto size = std::size_t(0); - for (const auto &arg : args) { - size += bytes::make_span(arg).size(); - } - auto result = vector(size); - auto buffer = make_span(result); - for (const auto &arg : args) { - const auto part = bytes::make_span(arg); - bytes::copy(buffer, part); - buffer = buffer.subspan(part.size()); - } - return result; -} - -// Implemented in base/openssl_help.h -void set_random(span destination); - -} // namespace bytes diff --git a/Telegram/SourceFiles/base/concurrent_timer.cpp b/Telegram/SourceFiles/base/concurrent_timer.cpp deleted file mode 100644 index 7e523a0d1..000000000 --- a/Telegram/SourceFiles/base/concurrent_timer.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/concurrent_timer.h" - -#include -#include - -using namespace base::details; - -namespace base { -namespace details { -namespace { - -constexpr auto kCallDelayedEvent = QEvent::Type(QEvent::User + 1); -constexpr auto kCancelTimerEvent = QEvent::Type(QEvent::User + 2); -static_assert(kCancelTimerEvent < QEvent::MaxUser); - -ConcurrentTimerEnvironment *Environment/* = nullptr*/; -QMutex EnvironmentMutex; - -class CallDelayedEvent : public QEvent { -public: - CallDelayedEvent( - crl::time timeout, - Qt::TimerType type, - FnMut method); - - crl::time timeout() const; - Qt::TimerType type() const; - FnMut takeMethod(); - -private: - crl::time _timeout = 0; - Qt::TimerType _type = Qt::PreciseTimer; - FnMut _method; - -}; - -class CancelTimerEvent : public QEvent { -public: - CancelTimerEvent(); - -}; - -CallDelayedEvent::CallDelayedEvent( - crl::time timeout, - Qt::TimerType type, - FnMut method) -: QEvent(kCallDelayedEvent) -, _timeout(timeout) -, _type(type) -, _method(std::move(method)) { - Expects(_timeout >= 0 && _timeout < std::numeric_limits::max()); -} - -crl::time CallDelayedEvent::timeout() const { - return _timeout; -} - -Qt::TimerType CallDelayedEvent::type() const { - return _type; -} - -FnMut CallDelayedEvent::takeMethod() { - return base::take(_method); -} - -CancelTimerEvent::CancelTimerEvent() : QEvent(kCancelTimerEvent) { -} - -} // namespace - -class TimerObject : public QObject { -public: - TimerObject( - not_null thread, - not_null adjuster, - Fn adjust); - -protected: - bool event(QEvent *e) override; - -private: - void callDelayed(not_null e); - void callNow(); - void cancel(); - void adjust(); - - FnMut _next; - Fn _adjust; - int _timerId = 0; - -}; - -TimerObject::TimerObject( - not_null thread, - not_null adjuster, - Fn adjust) -: _adjust(std::move(adjust)) { - moveToThread(thread); - connect( - adjuster, - &QObject::destroyed, - this, - &TimerObject::adjust, - Qt::DirectConnection); -} - -bool TimerObject::event(QEvent *e) { - const auto type = e->type(); - switch (type) { - case kCallDelayedEvent: - callDelayed(static_cast(e)); - return true; - case kCancelTimerEvent: - cancel(); - return true; - case QEvent::Timer: - callNow(); - return true; - } - return QObject::event(e); -} - -void TimerObject::callDelayed(not_null e) { - cancel(); - - const auto timeout = e->timeout(); - const auto type = e->type(); - _next = e->takeMethod(); - if (timeout > 0) { - _timerId = startTimer(timeout, type); - } else { - base::take(_next)(); - } -} - -void TimerObject::cancel() { - if (const auto id = base::take(_timerId)) { - killTimer(id); - } - _next = nullptr; -} - -void TimerObject::callNow() { - auto next = base::take(_next); - cancel(); - next(); -} - -void TimerObject::adjust() { - if (_adjust) { - _adjust(); - } -} - -TimerObjectWrap::TimerObjectWrap(Fn adjust) { - QMutexLocker lock(&EnvironmentMutex); - - if (Environment) { - _value = Environment->createTimer(std::move(adjust)); - } -} - -TimerObjectWrap::~TimerObjectWrap() { - if (_value) { - QMutexLocker lock(&EnvironmentMutex); - - if (Environment) { - _value.release()->deleteLater(); - } - } -} - -void TimerObjectWrap::call( - crl::time timeout, - Qt::TimerType type, - FnMut method) { - sendEvent(std::make_unique( - timeout, - type, - std::move(method))); -} - -void TimerObjectWrap::cancel() { - sendEvent(std::make_unique()); -} - -void TimerObjectWrap::sendEvent(std::unique_ptr event) { - if (!_value) { - return; - } - QCoreApplication::postEvent( - _value.get(), - event.release(), - Qt::HighEventPriority); -} - -} // namespace details - -ConcurrentTimerEnvironment::ConcurrentTimerEnvironment() { - _thread.start(); - _adjuster.moveToThread(&_thread); - - acquire(); -} - -ConcurrentTimerEnvironment::~ConcurrentTimerEnvironment() { - _thread.quit(); - release(); - _thread.wait(); - QObject::disconnect(&_adjuster, &QObject::destroyed, nullptr, nullptr); -} - -std::unique_ptr ConcurrentTimerEnvironment::createTimer( - Fn adjust) { - return std::make_unique( - &_thread, - &_adjuster, - std::move(adjust)); -} - -void ConcurrentTimerEnvironment::Adjust() { - QMutexLocker lock(&EnvironmentMutex); - if (Environment) { - Environment->adjustTimers(); - } -} - -void ConcurrentTimerEnvironment::adjustTimers() { - QObject emitter; - QObject::connect( - &emitter, - &QObject::destroyed, - &_adjuster, - &QObject::destroyed, - Qt::QueuedConnection); -} - -void ConcurrentTimerEnvironment::acquire() { - Expects(Environment == nullptr); - - QMutexLocker lock(&EnvironmentMutex); - Environment = this; -} - -void ConcurrentTimerEnvironment::release() { - Expects(Environment == this); - - QMutexLocker lock(&EnvironmentMutex); - Environment = nullptr; -} - -ConcurrentTimer::ConcurrentTimer( - Fn)> runner, - Fn callback) -: _runner(std::move(runner)) -, _object(createAdjuster()) -, _callback(std::move(callback)) -, _type(Qt::PreciseTimer) -, _adjusted(false) { - setRepeat(Repeat::Interval); -} - -Fn ConcurrentTimer::createAdjuster() { - _guard = std::make_shared(true); - return [=, runner = _runner, guard = std::weak_ptr(_guard)] { - runner([=] { - if (!guard.lock()) { - return; - } - adjust(); - }); - }; -} - -void ConcurrentTimer::start( - crl::time timeout, - Qt::TimerType type, - Repeat repeat) { - _type = type; - setRepeat(repeat); - _adjusted = false; - setTimeout(timeout); - - cancelAndSchedule(_timeout); - _next = crl::now() + _timeout; -} - -void ConcurrentTimer::cancelAndSchedule(int timeout) { - auto method = [ - =, - runner = _runner, - guard = _running.make_guard() - ]() mutable { - if (!guard) { - return; - } - runner([=, guard = std::move(guard)] { - if (!guard) { - return; - } - timerEvent(); - }); - }; - _object.call(timeout, _type, std::move(method)); -} - -void ConcurrentTimer::timerEvent() { - if (repeat() == Repeat::Interval) { - if (_adjusted) { - start(_timeout, _type, repeat()); - } else { - _next = crl::now() + _timeout; - } - } else { - cancel(); - } - - if (_callback) { - _callback(); - } -} - -void ConcurrentTimer::cancel() { - _running = {}; - if (isActive()) { - _running = base::binary_guard(); - _object.cancel(); - } -} - -crl::time ConcurrentTimer::remainingTime() const { - if (!isActive()) { - return -1; - } - const auto now = crl::now(); - return (_next > now) ? (_next - now) : crl::time(0); -} - -void ConcurrentTimer::adjust() { - auto remaining = remainingTime(); - if (remaining >= 0) { - cancelAndSchedule(remaining); - _adjusted = true; - } -} - -void ConcurrentTimer::setTimeout(crl::time timeout) { - Expects(timeout >= 0 && timeout <= std::numeric_limits::max()); - - _timeout = static_cast(timeout); -} - -int ConcurrentTimer::timeout() const { - return _timeout; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/concurrent_timer.h b/Telegram/SourceFiles/base/concurrent_timer.h deleted file mode 100644 index 4020ee6ae..000000000 --- a/Telegram/SourceFiles/base/concurrent_timer.h +++ /dev/null @@ -1,146 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/binary_guard.h" -#include -#include -#include - -namespace base { -namespace details { - -class TimerObject; - -class TimerObjectWrap { -public: - explicit TimerObjectWrap(Fn adjust); - ~TimerObjectWrap(); - - void call( - crl::time timeout, - Qt::TimerType type, - FnMut method); - void cancel(); - -private: - void sendEvent(std::unique_ptr event); - - std::unique_ptr _value; - -}; - -} // namespace details - -class ConcurrentTimerEnvironment { -public: - ConcurrentTimerEnvironment(); - ~ConcurrentTimerEnvironment(); - - std::unique_ptr createTimer(Fn adjust); - - static void Adjust(); - -private: - void acquire(); - void release(); - void adjustTimers(); - - QThread _thread; - QObject _adjuster; - -}; - -class ConcurrentTimer { -public: - explicit ConcurrentTimer( - Fn)> runner, - Fn callback = nullptr); - - template - explicit ConcurrentTimer( - crl::weak_on_queue weak, - Fn callback = nullptr); - - static Qt::TimerType DefaultType(crl::time timeout) { - constexpr auto kThreshold = crl::time(1000); - return (timeout > kThreshold) ? Qt::CoarseTimer : Qt::PreciseTimer; - } - - void setCallback(Fn callback) { - _callback = std::move(callback); - } - - void callOnce(crl::time timeout) { - callOnce(timeout, DefaultType(timeout)); - } - - void callEach(crl::time timeout) { - callEach(timeout, DefaultType(timeout)); - } - - void callOnce(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::SingleShot); - } - - void callEach(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::Interval); - } - - bool isActive() const { - return _running.alive(); - } - - void cancel(); - crl::time remainingTime() const; - -private: - enum class Repeat : unsigned { - Interval = 0, - SingleShot = 1, - }; - Fn createAdjuster(); - void start(crl::time timeout, Qt::TimerType type, Repeat repeat); - void adjust(); - - void cancelAndSchedule(int timeout); - - void setTimeout(crl::time timeout); - int timeout() const; - - void timerEvent(); - - void setRepeat(Repeat repeat) { - _repeat = static_cast(repeat); - } - Repeat repeat() const { - return static_cast(_repeat); - } - - Fn)> _runner; - std::shared_ptr _guard; // Must be before _object. - details::TimerObjectWrap _object; - Fn _callback; - base::binary_guard _running; - crl::time _next = 0; - int _timeout = 0; - - Qt::TimerType _type : 2; - bool _adjusted : 1; - unsigned _repeat : 1; - -}; - -template -ConcurrentTimer::ConcurrentTimer( - crl::weak_on_queue weak, - Fn callback) -: ConcurrentTimer(weak.runner(), std::move(callback)) { -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/crc32hash.cpp b/Telegram/SourceFiles/base/crc32hash.cpp deleted file mode 100644 index 91cbf9920..000000000 --- a/Telegram/SourceFiles/base/crc32hash.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/crc32hash.h" - -namespace base { -namespace { - -class Crc32Table { -public: - Crc32Table() { - auto poly = std::uint32_t(0x04c11db7); - for (auto i = 0; i != 256; ++i) { - _data[i] = reflect(i, 8) << 24; - for (auto j = 0; j != 8; ++j) { - _data[i] = (_data[i] << 1) ^ (_data[i] & (1 << 31) ? poly : 0); - } - _data[i] = reflect(_data[i], 32); - } - } - - std::uint32_t operator[](int index) const { - return _data[index]; - } - -private: - std::uint32_t reflect(std::uint32_t val, char ch) { - auto result = std::uint32_t(0); - for (int i = 1; i < (ch + 1); ++i) { - if (val & 1) { - result |= 1 << (ch - i); - } - val >>= 1; - } - return result; - } - - std::uint32_t _data[256]; - -}; - -} // namespace - -std::int32_t crc32(const void *data, int len) { - static const auto kTable = Crc32Table(); - - const auto buffer = static_cast(data); - - auto crc = std::uint32_t(0xffffffff); - for (auto i = 0; i != len; ++i) { - crc = (crc >> 8) ^ kTable[(crc & 0xFF) ^ buffer[i]]; - } - - return static_cast(crc ^ 0xffffffff); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/enum_mask.h b/Telegram/SourceFiles/base/enum_mask.h deleted file mode 100644 index f943646c7..000000000 --- a/Telegram/SourceFiles/base/enum_mask.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { - -template -class enum_mask { - using Type = std::uint32_t; - -public: - static_assert(static_cast(Enum::kCount) <= 32, "We have only 32 bit."); - - enum_mask() = default; - enum_mask(Enum value) : _value(ToBit(value)) { - } - - enum_mask added(enum_mask other) const { - auto result = *this; - result.set(other); - return result; - } - void set(enum_mask other) { - _value |= other._value; - } - bool test(Enum value) const { - return _value & ToBit(value); - } - - explicit operator bool() const { - return _value != 0; - } - -private: - inline static Type ToBit(Enum value) { - return 1 << static_cast(value); - } - Type _value = 0; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/flags.h b/Telegram/SourceFiles/base/flags.h deleted file mode 100644 index e3116a334..000000000 --- a/Telegram/SourceFiles/base/flags.h +++ /dev/null @@ -1,351 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -class flags; - -template -struct extended_flags; - -template -using extended_flags_t = typename extended_flags::type; - -namespace details { - -struct flags_zero_helper_struct { -}; - -using flags_zero_helper = void(base::details::flags_zero_helper_struct::*)(); - -template ::type> -inline constexpr auto extended_flag_convert(ExtendedEnum value) { - return static_cast(value); -} - -template ::type> -inline constexpr auto extended_flags_convert(ExtendedEnum value) { - return flags(extended_flag_convert(value)); -} - -} // namespace details - -template -class flags { -public: - using Enum = EnumType; - using Type = std::underlying_type_t; - - constexpr flags() = default; - constexpr flags(details::flags_zero_helper) noexcept { - } - constexpr flags(Enum value) noexcept - : _value(static_cast(value)) { - } - static constexpr flags from_raw(Type value) noexcept { - return flags(static_cast(value)); - } - - constexpr auto value() const noexcept { - return _value; - } - constexpr operator Type() const noexcept { - return value(); - } - - constexpr auto &operator|=(flags b) noexcept { - _value |= b.value(); - return *this; - } - constexpr auto &operator&=(flags b) noexcept { - _value &= b.value(); - return *this; - } - constexpr auto &operator^=(flags b) noexcept { - _value ^= b.value(); - return *this; - } - - constexpr auto operator~() const noexcept { - return from_raw(~value()); - } - - constexpr auto operator|(flags b) const noexcept { - return (flags(*this) |= b); - } - constexpr auto operator&(flags b) const noexcept { - return (flags(*this) &= b); - } - constexpr auto operator^(flags b) const noexcept { - return (flags(*this) ^= b); - } - - constexpr auto operator|(Enum b) const noexcept { - return (flags(*this) |= b); - } - constexpr auto operator&(Enum b) const noexcept { - return (flags(*this) &= b); - } - constexpr auto operator^(Enum b) const noexcept { - return (flags(*this) ^= b); - } - - constexpr auto operator==(Enum b) const noexcept { - return (value() == static_cast(b)); - } - constexpr auto operator!=(Enum b) const noexcept { - return !(*this == b); - } - constexpr auto operator<(Enum b) const noexcept { - return value() < static_cast(b); - } - constexpr auto operator>(Enum b) const noexcept { - return (b < *this); - } - constexpr auto operator<=(Enum b) const noexcept { - return !(b < *this); - } - constexpr auto operator>=(Enum b) const noexcept { - return !(*this < b); - } - -private: - Type _value = 0; - -}; - -template -constexpr auto make_flags(Enum value) noexcept { - return flags(value); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(Enum a, flags b) noexcept { - return b | a; -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator&(Enum a, flags b) noexcept { - return b & a; -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator^(Enum a, flags b) noexcept { - return b ^ a; -} - -template ::type> -inline constexpr auto operator|(flags> a, ExtendedEnum b) { - return a | details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, flags> b) { - return b | a; -} - -template > -inline constexpr auto operator&(flags> a, ExtendedEnum b) { - return a & details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator&(ExtendedEnum a, flags> b) { - return b & a; -} - -template > -inline constexpr auto operator^(flags> a, ExtendedEnum b) { - return a ^ details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator^(ExtendedEnum a, flags> b) { - return b ^ a; -} - -template ::type> -inline constexpr auto &operator&=(flags> &a, ExtendedEnum b) { - return (a &= details::extended_flags_convert(b)); -} - -template ::type> -inline constexpr auto &operator|=(flags> &a, ExtendedEnum b) { - return (a |= details::extended_flags_convert(b)); -} - -template ::type> -inline constexpr auto &operator^=(flags> &a, ExtendedEnum b) { - return (a ^= details::extended_flags_convert(b)); -} - -template ::type> -inline constexpr auto operator==(flags> a, ExtendedEnum b) { - return a == details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator==(ExtendedEnum a, flags> b) { - return (b == a); -} - -template ::type> -inline constexpr auto operator!=(flags> a, ExtendedEnum b) { - return !(a == b); -} - -template ::type> -inline constexpr auto operator!=(ExtendedEnum a, flags> b) { - return !(a == b); -} - -template ::type> -inline constexpr auto operator<(flags> a, ExtendedEnum b) { - return a < details::extended_flags_convert(b); -} - -template ::type> -inline constexpr auto operator<(ExtendedEnum a, flags> b) { - return details::extended_flags_convert(a) < b; -} - -template ::type> -inline constexpr auto operator>(flags> a, ExtendedEnum b) { - return (b < a); -} - -template ::type> -inline constexpr auto operator>(ExtendedEnum a, flags> b) { - return (b < a); -} - -template ::type> -inline constexpr auto operator<=(flags> a, ExtendedEnum b) { - return !(b < a); -} - -template ::type> -inline constexpr auto operator<=(ExtendedEnum a, flags> b) { - return !(b < a); -} - -template ::type> -inline constexpr auto operator>=(flags> a, ExtendedEnum b) { - return !(a < b); -} - -template ::type> -inline constexpr auto operator>=(ExtendedEnum a, flags> b) { - return !(a < b); -} - -} // namespace base - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator!(Enum a) noexcept { - return !base::make_flags(a); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator~(Enum a) noexcept { - return ~base::make_flags(a); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(Enum a, Enum b) noexcept { - return base::make_flags(a) | b; -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(Enum a, base::details::flags_zero_helper) noexcept { - return base::make_flags(a); -} - -template ::value>, - typename = std::enable_if_t> -inline constexpr auto operator|(base::details::flags_zero_helper, Enum b) noexcept { - return base::make_flags(b); -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, ExtendedEnum b) { - return base::details::extended_flags_convert(a) | b; -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, typename base::extended_flags::type b) { - return base::details::extended_flags_convert(a) | b; -} - -template ::type> -inline constexpr auto operator|(typename base::extended_flags::type a, ExtendedEnum b) { - return b | a; -} - -template ::type> -inline constexpr auto operator|(base::details::flags_zero_helper, ExtendedEnum b) { - return 0 | base::details::extended_flag_convert(b); -} - -template ::type> -inline constexpr auto operator|(ExtendedEnum a, base::details::flags_zero_helper) { - return base::details::extended_flag_convert(a) | 0; -} - -template ::type> -inline constexpr auto operator~(ExtendedEnum b) { - return ~base::details::extended_flags_convert(b); -} diff --git a/Telegram/SourceFiles/base/flags_tests.cpp b/Telegram/SourceFiles/base/flags_tests.cpp deleted file mode 100644 index 786dc49c2..000000000 --- a/Telegram/SourceFiles/base/flags_tests.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/flags.h" - -namespace MethodNamespace { - -template -void TestFlags(Enum a, Enum b, Enum c) { - auto abc = a | b; - abc |= c; - auto test = abc != a; - CHECK(abc != a); - CHECK(abc != (a | b)); - CHECK((abc & a) == a); - CHECK((abc & b) == b); - CHECK((abc & c) == c); - CHECK((abc & ~a) == (b | c)); - CHECK((abc & ~(b | c)) == a); - CHECK((abc ^ a) == (abc & ~a)); - - auto another = a | b; - another |= c; - CHECK(abc == another); - another &= ~b; - CHECK(another == (a | c)); - another ^= a; - CHECK(another == c); - another = 0; - another = nullptr; - auto is_zero = ((another & abc) == 0); - CHECK(is_zero); - CHECK(!(another & abc)); - auto more = a | another; - auto just = a | 0; - CHECK(more == just); - CHECK(just); -} - -} // namespace MethodNamespace - -namespace FlagsNamespace { - -enum class Flag : int { - one = (1 << 0), - two = (1 << 1), - three = (1 << 2), -}; -inline constexpr auto is_flag_type(Flag) { return true; } - -class Class { -public: - enum class Public : long { - one = (1 << 2), - two = (1 << 1), - three = (1 << 0), - }; - friend inline constexpr auto is_flag_type(Public) { return true; } - - static void TestPrivate(); - -private: - enum class Private : long { - one = (1 << 0), - two = (1 << 1), - three = (1 << 2), - }; - friend inline constexpr auto is_flag_type(Private) { return true; } - -}; - -void Class::TestPrivate() { - MethodNamespace::TestFlags(Private::one, Private::two, Private::three); -} - -} // namespace FlagsNamespace - -namespace ExtendedNamespace { - -enum class Flag : int { - one = (1 << 3), - two = (1 << 4), - three = (1 << 5), -}; - -} // namespace ExtendedNamespace - -namespace base { - -template<> -struct extended_flags { - using type = FlagsNamespace::Flag; -}; - -} // namespace base - -TEST_CASE("flags operators on scoped enums", "[flags]") { - SECTION("testing non-member flags") { - MethodNamespace::TestFlags( - FlagsNamespace::Flag::one, - FlagsNamespace::Flag::two, - FlagsNamespace::Flag::three); - } - SECTION("testing public member flags") { - MethodNamespace::TestFlags( - FlagsNamespace::Class::Public::one, - FlagsNamespace::Class::Public::two, - FlagsNamespace::Class::Public::three); - } - SECTION("testing private member flags") { - FlagsNamespace::Class::TestPrivate(); - } - SECTION("testing extended flags") { - MethodNamespace::TestFlags( - ExtendedNamespace::Flag::one, - ExtendedNamespace::Flag::two, - ExtendedNamespace::Flag::three); - - auto onetwo = FlagsNamespace::Flag::one | ExtendedNamespace::Flag::two; - auto twoone = ExtendedNamespace::Flag::two | FlagsNamespace::Flag::one; - CHECK(onetwo == twoone); - } -} diff --git a/Telegram/SourceFiles/base/flat_map.h b/Telegram/SourceFiles/base/flat_map.h deleted file mode 100644 index 9c8a9bcd7..000000000 --- a/Telegram/SourceFiles/base/flat_map.h +++ /dev/null @@ -1,917 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "base/optional.h" - -namespace base { - -using std::begin; -using std::end; - -template < - typename Key, - typename Type, - typename Compare = std::less<>> -class flat_map; - -template < - typename Key, - typename Type, - typename Compare = std::less<>> -class flat_multi_map; - -template < - typename Me, - typename Key, - typename Type, - typename iterator_impl, - typename pointer_impl, - typename reference_impl> -class flat_multi_map_iterator_base_impl; - -template -struct flat_multi_map_pair_type { - using first_type = const Key; - using second_type = Value; - - constexpr flat_multi_map_pair_type() - : first() - , second() { - } - - template - constexpr flat_multi_map_pair_type(OtherKey &&key, OtherValue &&value) - : first(std::forward(key)) - , second(std::forward(value)) { - } - - flat_multi_map_pair_type(const flat_multi_map_pair_type &pair) - : first(pair.first) - , second(pair.second) { - } - - flat_multi_map_pair_type(flat_multi_map_pair_type &&pair) - : first(std::move(const_cast(pair.first))) - , second(std::move(pair.second)) { - } - - flat_multi_map_pair_type &operator=(const flat_multi_map_pair_type&) = delete; - flat_multi_map_pair_type &operator=(flat_multi_map_pair_type &&other) { - const_cast(first) = std::move(const_cast(other.first)); - second = std::move(other.second); - return *this; - } - - void swap(flat_multi_map_pair_type &other) { - using std::swap; - - if (this != &other) { - std::swap( - const_cast(first), - const_cast(other.first)); - std::swap(second, other.second); - } - } - - const Key first; - Value second; - -}; - -template < - typename Me, - typename Key, - typename Type, - typename iterator_impl, - typename pointer_impl, - typename reference_impl> -class flat_multi_map_iterator_base_impl { -public: - using iterator_category = typename iterator_impl::iterator_category; - - using pair_type = flat_multi_map_pair_type; - using value_type = pair_type; - using difference_type = typename iterator_impl::difference_type; - using pointer = pointer_impl; - using reference = reference_impl; - - flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl()) - : _impl(impl) { - } - - reference operator*() const { - return *_impl; - } - pointer operator->() const { - return std::addressof(**this); - } - Me &operator++() { - ++_impl; - return static_cast(*this); - } - Me operator++(int) { - return _impl++; - } - Me &operator--() { - --_impl; - return static_cast(*this); - } - Me operator--(int) { - return _impl--; - } - Me &operator+=(difference_type offset) { - _impl += offset; - return static_cast(*this); - } - Me operator+(difference_type offset) const { - return _impl + offset; - } - Me &operator-=(difference_type offset) { - _impl -= offset; - return static_cast(*this); - } - Me operator-(difference_type offset) const { - return _impl - offset; - } - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - difference_type operator-( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl - right._impl; - } - reference operator[](difference_type offset) const { - return _impl[offset]; - } - - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - bool operator==( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl == right._impl; - } - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - bool operator!=( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl != right._impl; - } - template < - typename other_me, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - bool operator<( - const flat_multi_map_iterator_base_impl< - other_me, - Key, - Type, - other_iterator_impl, - other_pointer_impl, - other_reference_impl> &right) const { - return _impl < right._impl; - } - -private: - iterator_impl _impl; - - template < - typename OtherKey, - typename OtherType, - typename OtherCompare> - friend class flat_multi_map; - - template < - typename OtherMe, - typename OtherKey, - typename OtherType, - typename other_iterator_impl, - typename other_pointer_impl, - typename other_reference_impl> - friend class flat_multi_map_iterator_base_impl; - -}; - -template -class flat_multi_map { -public: - class iterator; - class const_iterator; - class reverse_iterator; - class const_reverse_iterator; - -private: - using pair_type = flat_multi_map_pair_type; - using impl_t = std::deque; - - using iterator_base = flat_multi_map_iterator_base_impl< - iterator, - Key, - Type, - typename impl_t::iterator, - pair_type*, - pair_type&>; - using const_iterator_base = flat_multi_map_iterator_base_impl< - const_iterator, - Key, - Type, - typename impl_t::const_iterator, - const pair_type*, - const pair_type&>; - using reverse_iterator_base = flat_multi_map_iterator_base_impl< - reverse_iterator, - Key, - Type, - typename impl_t::reverse_iterator, - pair_type*, - pair_type&>; - using const_reverse_iterator_base = flat_multi_map_iterator_base_impl< - const_reverse_iterator, - Key, - Type, - typename impl_t::const_reverse_iterator, - const pair_type*, - const pair_type&>; - -public: - using value_type = pair_type; - using size_type = typename impl_t::size_type; - using difference_type = typename impl_t::difference_type; - using pointer = pair_type*; - using const_pointer = const pair_type*; - using reference = pair_type&; - using const_reference = const pair_type&; - - class iterator : public iterator_base { - public: - using iterator_base::iterator_base; - iterator() = default; - iterator(const iterator_base &other) : iterator_base(other) { - } - friend class const_iterator; - - }; - class const_iterator : public const_iterator_base { - public: - using const_iterator_base::const_iterator_base; - const_iterator() = default; - const_iterator(const_iterator_base other) : const_iterator_base(other) { - } - const_iterator(const iterator &other) : const_iterator_base(other._impl) { - } - - }; - class reverse_iterator : public reverse_iterator_base { - public: - using reverse_iterator_base::reverse_iterator_base; - reverse_iterator() = default; - reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) { - } - friend class const_reverse_iterator; - - }; - class const_reverse_iterator : public const_reverse_iterator_base { - public: - using const_reverse_iterator_base::const_reverse_iterator_base; - const_reverse_iterator() = default; - const_reverse_iterator(const_reverse_iterator_base other) : const_reverse_iterator_base(other) { - } - const_reverse_iterator(const reverse_iterator &other) : const_reverse_iterator_base(other._impl) { - } - - }; - - flat_multi_map() = default; - flat_multi_map(const flat_multi_map &other) = default; - flat_multi_map(flat_multi_map &&other) = default; - flat_multi_map &operator=(const flat_multi_map &other) { - auto copy = other; - return (*this = std::move(copy)); - } - flat_multi_map &operator=(flat_multi_map &&other) = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - flat_multi_map(Iterator first, Iterator last) - : _data(first, last) { - std::sort(std::begin(impl()), std::end(impl()), compare()); - } - - flat_multi_map(std::initializer_list iter) - : flat_multi_map(iter.begin(), iter.end()) { - } - - size_type size() const { - return impl().size(); - } - bool empty() const { - return impl().empty(); - } - void clear() { - impl().clear(); - } - - iterator begin() { - return impl().begin(); - } - iterator end() { - return impl().end(); - } - const_iterator begin() const { - return impl().begin(); - } - const_iterator end() const { - return impl().end(); - } - const_iterator cbegin() const { - return impl().cbegin(); - } - const_iterator cend() const { - return impl().cend(); - } - reverse_iterator rbegin() { - return impl().rbegin(); - } - reverse_iterator rend() { - return impl().rend(); - } - const_reverse_iterator rbegin() const { - return impl().rbegin(); - } - const_reverse_iterator rend() const { - return impl().rend(); - } - const_reverse_iterator crbegin() const { - return impl().crbegin(); - } - const_reverse_iterator crend() const { - return impl().crend(); - } - - reference front() { - return *begin(); - } - const_reference front() const { - return *begin(); - } - reference back() { - return *(end() - 1); - } - const_reference back() const { - return *(end() - 1); - } - - iterator insert(const value_type &value) { - if (empty() || compare()(value.first, front().first)) { - impl().push_front(value); - return begin(); - } else if (!compare()(value.first, back().first)) { - impl().push_back(value); - return (end() - 1); - } - auto where = getUpperBound(value.first); - return impl().insert(where, value); - } - iterator insert(value_type &&value) { - if (empty() || compare()(value.first, front().first)) { - impl().push_front(std::move(value)); - return begin(); - } else if (!compare()(value.first, back().first)) { - impl().push_back(std::move(value)); - return (end() - 1); - } - auto where = getUpperBound(value.first); - return impl().insert(where, std::move(value)); - } - template - iterator emplace(Args&&... args) { - return insert(value_type(std::forward(args)...)); - } - - bool removeOne(const Key &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return false; - } - auto where = getLowerBound(key); - if (compare()(key, where->first)) { - return false; - } - impl().erase(where); - return true; - } - int removeAll(const Key &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return 0; - } - auto range = getEqualRange(key); - if (range.first == range.second) { - return 0; - } - const auto result = (range.second - range.first); - impl().erase(range.first, range.second); - return result; - } - - iterator erase(const_iterator where) { - return impl().erase(where._impl); - } - iterator erase(const_iterator from, const_iterator till) { - return impl().erase(from._impl, till._impl); - } - int erase(const Key &key) { - return removeAll(key); - } - - iterator findFirst(const Key &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - const_iterator findFirst(const Key &key) const { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - template - iterator findFirst(const OtherKey &key) { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - template - const_iterator findFirst(const OtherKey &key) const { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return end(); - } - auto where = getLowerBound(key); - return compare()(key, where->first) ? impl().end() : where; - } - - bool contains(const Key &key) const { - return findFirst(key) != end(); - } - int count(const Key &key) const { - if (empty() - || compare()(key, front().first) - || compare()(back().first, key)) { - return 0; - } - auto range = getEqualRange(key); - return (range.second - range.first); - } - -private: - friend class flat_map; - - struct transparent_compare : Compare { - inline constexpr const Compare &initial() const noexcept { - return *this; - } - - template < - typename OtherType1, - typename OtherType2, - typename = std::enable_if_t< - !std::is_same_v, pair_type> && - !std::is_same_v, pair_type>>> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const { - return initial()( - std::forward(a), - std::forward(b)); - } - template < - typename OtherType1, - typename OtherType2> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const -> std::enable_if_t< - std::is_same_v, pair_type> && - std::is_same_v, pair_type>, bool> { - return initial()(a.first, b.first); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, pair_type>>> - inline constexpr auto operator()( - const pair_type &a, - OtherType &&b) const { - return operator()(a.first, std::forward(b)); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, pair_type>>> - inline constexpr auto operator()( - OtherType &&a, - const pair_type &b) const { - return operator()(std::forward(a), b.first); - } - - }; - struct Data : transparent_compare { - template - Data(Args &&...args) - : elements(std::forward(args)...) { - } - - impl_t elements; - }; - - Data _data; - const transparent_compare &compare() const noexcept { - return _data; - } - const impl_t &impl() const noexcept { - return _data.elements; - } - impl_t &impl() noexcept { - return _data.elements; - } - - template - typename impl_t::iterator getLowerBound(const OtherKey &key) { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - typename impl_t::const_iterator getLowerBound(const OtherKey &key) const { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - typename impl_t::iterator getUpperBound(const OtherKey &key) { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - typename impl_t::const_iterator getUpperBound(const OtherKey &key) const { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - std::pair< - typename impl_t::iterator, - typename impl_t::iterator - > getEqualRange(const OtherKey &key) { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - template - std::pair< - typename impl_t::const_iterator, - typename impl_t::const_iterator - > getEqualRange(const OtherKey &key) const { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - key, - compare()); - } - -}; - -template -class flat_map : private flat_multi_map { - using parent = flat_multi_map; - using pair_type = typename parent::pair_type; - -public: - using value_type = typename parent::value_type; - using size_type = typename parent::size_type; - using difference_type = typename parent::difference_type; - using pointer = typename parent::pointer; - using const_pointer = typename parent::const_pointer; - using reference = typename parent::reference; - using const_reference = typename parent::const_reference; - using iterator = typename parent::iterator; - using const_iterator = typename parent::const_iterator; - using reverse_iterator = typename parent::reverse_iterator; - using const_reverse_iterator = typename parent::const_reverse_iterator; - - flat_map() = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category - > - flat_map(Iterator first, Iterator last) : parent(first, last) { - finalize(); - } - - flat_map(std::initializer_list iter) : parent(iter.begin(), iter.end()) { - finalize(); - } - - using parent::parent; - using parent::size; - using parent::empty; - using parent::clear; - using parent::begin; - using parent::end; - using parent::cbegin; - using parent::cend; - using parent::rbegin; - using parent::rend; - using parent::crbegin; - using parent::crend; - using parent::front; - using parent::back; - using parent::erase; - using parent::contains; - - std::pair insert(const value_type &value) { - if (this->empty() || this->compare()(value.first, this->front().first)) { - this->impl().push_front(value); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, value.first)) { - this->impl().push_back(value); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(value.first); - if (this->compare()(value.first, where->first)) { - return { this->impl().insert(where, value), true }; - } - return { where, false }; - } - std::pair insert(value_type &&value) { - if (this->empty() || this->compare()(value.first, this->front().first)) { - this->impl().push_front(std::move(value)); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, value.first)) { - this->impl().push_back(std::move(value)); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(value.first); - if (this->compare()(value.first, where->first)) { - return { this->impl().insert(where, std::move(value)), true }; - } - return { where, false }; - } - std::pair insert_or_assign( - const Key &key, - const Type &value) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().emplace_front(key, value); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, key)) { - this->impl().emplace_back(key, value); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return { this->impl().insert(where, value_type(key, value)), true }; - } - where->second = value; - return { where, false }; - } - std::pair insert_or_assign( - const Key &key, - Type &&value) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().emplace_front(key, std::move(value)); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, key)) { - this->impl().emplace_back(key, std::move(value)); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return { this->impl().insert(where, value_type(key, std::move(value))), true }; - } - where->second = std::move(value); - return { where, false }; - } - template - std::pair emplace( - OtherKey &&key, - Args&&... args) { - return this->insert(value_type( - std::forward(key), - Type(std::forward(args)...))); - } - template - std::pair emplace_or_assign( - const Key &key, - Args&&... args) { - return this->insert_or_assign( - key, - Type(std::forward(args)...)); - } - template - std::pair try_emplace( - const Key &key, - Args&&... args) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().push_front(value_type( - key, - Type(std::forward(args)...))); - return { this->begin(), true }; - } else if (this->compare()(this->back().first, key)) { - this->impl().push_back(value_type( - key, - Type(std::forward(args)...))); - return { this->end() - 1, true }; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return { - this->impl().insert( - where, - value_type( - key, - Type(std::forward(args)...))), - true - }; - } - return { where, false }; - } - - bool remove(const Key &key) { - return this->removeOne(key); - } - - iterator find(const Key &key) { - return this->findFirst(key); - } - const_iterator find(const Key &key) const { - return this->findFirst(key); - } - template - iterator find(const OtherKey &key) { - return this->template findFirst(key); - } - template - const_iterator find(const OtherKey &key) const { - return this->template findFirst(key); - } - - Type &operator[](const Key &key) { - if (this->empty() || this->compare()(key, this->front().first)) { - this->impl().push_front({ key, Type() }); - return this->front().second; - } else if (this->compare()(this->back().first, key)) { - this->impl().push_back({ key, Type() }); - return this->back().second; - } - auto where = this->getLowerBound(key); - if (this->compare()(key, where->first)) { - return this->impl().insert(where, { key, Type() })->second; - } - return where->second; - } - - std::optional take(const Key &key) { - auto it = find(key); - if (it == this->end()) { - return std::nullopt; - } - auto result = std::move(it->second); - this->erase(it); - return std::move(result); - } - -private: - void finalize() { - this->impl().erase( - std::unique( - std::begin(this->impl()), - std::end(this->impl()), - [&](auto &&a, auto &&b) { - return !this->compare()(a, b); - } - ), - std::end(this->impl())); - } - -}; - -} // namespace base - -// Structured bindings support. -namespace std { - -template -class tuple_size> -: public integral_constant { -}; - -template -class tuple_element<0, base::flat_multi_map_pair_type> { -public: - using type = const Key; -}; - -template -class tuple_element<1, base::flat_multi_map_pair_type> { -public: - using type = Value; -}; - -} // namespace std - -// Structured bindings support. -namespace base { -namespace details { - -template -using flat_multi_map_pair_element = std::tuple_element_t< - N, - flat_multi_map_pair_type>; - -} // namespace details - -template -auto get(base::flat_multi_map_pair_type &value) --> details::flat_multi_map_pair_element & { - if constexpr (N == 0) { - return value.first; - } else { - return value.second; - } -} - -template -auto get(const base::flat_multi_map_pair_type &value) --> const details::flat_multi_map_pair_element & { - if constexpr (N == 0) { - return value.first; - } else { - return value.second; - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/flat_map_tests.cpp b/Telegram/SourceFiles/base/flat_map_tests.cpp deleted file mode 100644 index e1372c4ac..000000000 --- a/Telegram/SourceFiles/base/flat_map_tests.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/flat_map.h" -#include - -struct int_wrap { - int value; -}; -struct int_wrap_comparator { - inline bool operator()(const int_wrap &a, const int_wrap &b) const { - return a.value < b.value; - } -}; - -using namespace std; - -TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") { - base::flat_map v; - v.emplace(0, "a"); - v.emplace(5, "b"); - v.emplace(4, "d"); - v.emplace(2, "e"); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(prev->first < i->first); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.emplace(3, "c"); - REQUIRE(v.size() == 5); - REQUIRE(v.find(3) != v.end()); - checkSorted(); - } -} - -TEST_CASE("simple flat_maps tests", "[flat_map]") { - SECTION("copy constructor") { - base::flat_map v; - v.emplace(0, "a"); - v.emplace(2, "b"); - auto u = v; - REQUIRE(u.size() == 2); - REQUIRE(u.find(0) == u.begin()); - REQUIRE(u.find(2) == u.end() - 1); - } - SECTION("assignment") { - base::flat_map v, u; - v.emplace(0, "a"); - v.emplace(2, "b"); - u = v; - REQUIRE(u.size() == 2); - REQUIRE(u.find(0) == u.begin()); - REQUIRE(u.find(2) == u.end() - 1); - } -} - -TEST_CASE("flat_maps custom comparator", "[flat_map]") { - base::flat_map v; - v.emplace(int_wrap{ 0 }, "a"); - v.emplace(int_wrap{ 5 }, "b"); - v.emplace(int_wrap{ 4 }, "d"); - v.emplace(int_wrap{ 2 }, "e"); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(int_wrap_comparator()(prev->first, i->first)); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.emplace(int_wrap{ 3 }, "c"); - REQUIRE(v.size() == 5); - REQUIRE(v.find({ 3 }) != v.end()); - checkSorted(); - } -} - -TEST_CASE("flat_maps structured bindings", "[flat_map]") { - base::flat_map> v; - v.emplace(0, std::make_unique(0.)); - v.emplace(1, std::make_unique(1.)); - - SECTION("structred binded range-based for loop") { - for (const auto &[key, value] : v) { - REQUIRE(key == int(std::round(*value))); - } - } - - SECTION("non-const structured binded range-based for loop") { - base::flat_map second = { - { 1, 1 }, - { 2, 2 }, - { 2, 3 }, - { 3, 3 }, - }; - REQUIRE(second.size() == 3); - //for (auto [a, b] : second) { // #MSVC Bug, reported - // REQUIRE(a == b); - //} - for (const auto [a, b] : second) { - REQUIRE(a == b); - } - } -} diff --git a/Telegram/SourceFiles/base/flat_set.h b/Telegram/SourceFiles/base/flat_set.h deleted file mode 100644 index b72814c2e..000000000 --- a/Telegram/SourceFiles/base/flat_set.h +++ /dev/null @@ -1,720 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace base { - -using std::begin; -using std::end; - -template > -class flat_set; - -template > -class flat_multi_set; - -template -class flat_multi_set_iterator_impl; - -template -class flat_multi_set_iterator_impl { -public: - using iterator_category = typename iterator_impl::iterator_category; - - using value_type = Type; - using difference_type = typename iterator_impl::difference_type; - using pointer = const Type*; - using reference = const Type&; - - flat_multi_set_iterator_impl( - iterator_impl impl = iterator_impl()) - : _impl(impl) { - } - template - flat_multi_set_iterator_impl( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &other) - : _impl(other._impl) { - } - - reference operator*() const { - return *_impl; - } - pointer operator->() const { - return std::addressof(**this); - } - flat_multi_set_iterator_impl &operator++() { - ++_impl; - return *this; - } - flat_multi_set_iterator_impl operator++(int) { - return _impl++; - } - flat_multi_set_iterator_impl &operator--() { - --_impl; - return *this; - } - flat_multi_set_iterator_impl operator--(int) { - return _impl--; - } - flat_multi_set_iterator_impl &operator+=(difference_type offset) { - _impl += offset; - return *this; - } - flat_multi_set_iterator_impl operator+(difference_type offset) const { - return _impl + offset; - } - flat_multi_set_iterator_impl &operator-=(difference_type offset) { - _impl -= offset; - return *this; - } - flat_multi_set_iterator_impl operator-(difference_type offset) const { - return _impl - offset; - } - template - difference_type operator-( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl - right._impl; - } - reference operator[](difference_type offset) const { - return _impl[offset]; - } - - template - bool operator==( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl == right._impl; - } - template - bool operator!=( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl != right._impl; - } - template - bool operator<( - const flat_multi_set_iterator_impl< - Type, - other_iterator_impl> &right) const { - return _impl < right._impl; - } - -private: - iterator_impl _impl; - - template - friend class flat_multi_set; - - template - friend class flat_set; - - template < - typename OtherType, - typename other_iterator_impl> - friend class flat_multi_set_iterator_impl; - - Type &wrapped() { - return _impl->wrapped(); - } - -}; - -template -class flat_multi_set_const_wrap { -public: - constexpr flat_multi_set_const_wrap(const Type &value) - : _value(value) { - } - constexpr flat_multi_set_const_wrap(Type &&value) - : _value(std::move(value)) { - } - inline constexpr operator const Type&() const { - return _value; - } - constexpr Type &wrapped() { - return _value; - } - -private: - Type _value; - -}; - -template -class flat_multi_set { - using const_wrap = flat_multi_set_const_wrap; - using impl_t = std::deque; - -public: - using value_type = Type; - using size_type = typename impl_t::size_type; - using difference_type = typename impl_t::difference_type; - using pointer = const Type*; - using reference = const Type&; - - using iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::iterator>; - using const_iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::const_iterator>; - using reverse_iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::reverse_iterator>; - using const_reverse_iterator = flat_multi_set_iterator_impl< - Type, - typename impl_t::const_reverse_iterator>; - - flat_multi_set() = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - flat_multi_set(Iterator first, Iterator last) - : _data(first, last) { - std::sort(std::begin(impl()), std::end(impl()), compare()); - } - - flat_multi_set(std::initializer_list iter) - : flat_multi_set(iter.begin(), iter.end()) { - } - - size_type size() const { - return impl().size(); - } - bool empty() const { - return impl().empty(); - } - void clear() { - impl().clear(); - } - - iterator begin() { - return impl().begin(); - } - iterator end() { - return impl().end(); - } - const_iterator begin() const { - return impl().begin(); - } - const_iterator end() const { - return impl().end(); - } - const_iterator cbegin() const { - return impl().cbegin(); - } - const_iterator cend() const { - return impl().cend(); - } - reverse_iterator rbegin() { - return impl().rbegin(); - } - reverse_iterator rend() { - return impl().rend(); - } - const_reverse_iterator rbegin() const { - return impl().rbegin(); - } - const_reverse_iterator rend() const { - return impl().rend(); - } - const_reverse_iterator crbegin() const { - return impl().crbegin(); - } - const_reverse_iterator crend() const { - return impl().crend(); - } - - reference front() const { - return *begin(); - } - reference back() const { - return *(end() - 1); - } - - iterator insert(const Type &value) { - if (empty() || compare()(value, front())) { - impl().push_front(value); - return begin(); - } else if (!compare()(value, back())) { - impl().push_back(value); - return (end() - 1); - } - auto where = getUpperBound(value); - return impl().insert(where, value); - } - iterator insert(Type &&value) { - if (empty() || compare()(value, front())) { - impl().push_front(std::move(value)); - return begin(); - } else if (!compare()(value, back())) { - impl().push_back(std::move(value)); - return (end() - 1); - } - auto where = getUpperBound(value); - return impl().insert(where, std::move(value)); - } - template - iterator emplace(Args&&... args) { - return insert(Type(std::forward(args)...)); - } - - bool removeOne(const Type &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return false; - } - auto where = getLowerBound(value); - if (compare()(value, *where)) { - return false; - } - impl().erase(where); - return true; - } - int removeAll(const Type &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return 0; - } - auto range = getEqualRange(value); - if (range.first == range.second) { - return 0; - } - const auto result = (range.second - range.first); - impl().erase(range.first, range.second); - return result; - } - - iterator erase(const_iterator where) { - return impl().erase(where._impl); - } - iterator erase(const_iterator from, const_iterator till) { - return impl().erase(from._impl, till._impl); - } - int erase(const Type &value) { - return removeAll(value); - } - - iterator findFirst(const Type &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - const_iterator findFirst(const Type &value) const { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - template < - typename OtherType, - typename = typename Compare::is_transparent> - iterator findFirst(const OtherType &value) { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - template < - typename OtherType, - typename = typename Compare::is_transparent> - const_iterator findFirst(const OtherType &value) const { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return end(); - } - auto where = getLowerBound(value); - return compare()(value, *where) ? impl().end() : where; - } - - bool contains(const Type &value) const { - return findFirst(value) != end(); - } - int count(const Type &value) const { - if (empty() - || compare()(value, front()) - || compare()(back(), value)) { - return 0; - } - auto range = getEqualRange(value); - return (range.second - range.first); - } - - template - auto modify(iterator which, Action action) { - auto result = action(which.wrapped()); - for (auto i = which + 1, e = end(); i != e; ++i) { - if (compare()(*i, *which)) { - std::swap(i.wrapped(), which.wrapped()); - } else { - break; - } - } - for (auto i = which, b = begin(); i != b;) { - --i; - if (compare()(*which, *i)) { - std::swap(i.wrapped(), which.wrapped()); - } else { - break; - } - } - return result; - } - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - void merge(Iterator first, Iterator last) { - impl().insert(impl().end(), first, last); - std::sort(std::begin(impl()), std::end(impl()), compare()); - } - - void merge(const flat_multi_set &other) { - merge(other.begin(), other.end()); - } - - void merge(std::initializer_list list) { - merge(list.begin(), list.end()); - } - -private: - friend class flat_set; - - struct transparent_compare : Compare { - inline constexpr const Compare &initial() const noexcept { - return *this; - } - - template < - typename OtherType1, - typename OtherType2, - typename = std::enable_if_t< - !std::is_same_v, const_wrap> && - !std::is_same_v, const_wrap>>> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const { - return initial()( - std::forward(a), - std::forward(b)); - } - template < - typename OtherType1, - typename OtherType2> - inline constexpr auto operator()( - OtherType1 &&a, - OtherType2 &&b) const -> std::enable_if_t< - std::is_same_v, const_wrap> && - std::is_same_v, const_wrap>, bool> { - return initial()( - static_cast(a), - static_cast(b)); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, const_wrap>>> - inline constexpr auto operator()( - const const_wrap &a, - OtherType &&b) const { - return initial()( - static_cast(a), - std::forward(b)); - } - template < - typename OtherType, - typename = std::enable_if_t< - !std::is_same_v, const_wrap>>> - inline constexpr auto operator()( - OtherType &&a, - const const_wrap &b) const { - return initial()( - std::forward(a), - static_cast(b)); - } - - }; - struct Data : transparent_compare { - template - Data(Args &&...args) - : elements(std::forward(args)...) { - } - - impl_t elements; - }; - - Data _data; - const transparent_compare &compare() const { - return _data; - } - const impl_t &impl() const { - return _data.elements; - } - impl_t &impl() { - return _data.elements; - } - - typename impl_t::iterator getLowerBound(const Type &value) { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - typename impl_t::const_iterator getLowerBound(const Type &value) const { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - typename impl_t::iterator getLowerBound(const OtherType &value) { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - typename impl_t::const_iterator getLowerBound(const OtherType &value) const { - return std::lower_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - typename impl_t::iterator getUpperBound(const Type &value) { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - typename impl_t::const_iterator getUpperBound(const Type &value) const { - return std::upper_bound( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - std::pair< - typename impl_t::iterator, - typename impl_t::iterator - > getEqualRange(const Type &value) { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - std::pair< - typename impl_t::const_iterator, - typename impl_t::const_iterator - > getEqualRange(const Type &value) const { - return std::equal_range( - std::begin(impl()), - std::end(impl()), - value, - compare()); - } - -}; - -template -class flat_set : private flat_multi_set { - using parent = flat_multi_set; - -public: - using iterator = typename parent::iterator; - using const_iterator = typename parent::const_iterator; - using reverse_iterator = typename parent::reverse_iterator; - using const_reverse_iterator = typename parent::const_reverse_iterator; - using value_type = typename parent::value_type; - using size_type = typename parent::size_type; - using difference_type = typename parent::difference_type; - using pointer = typename parent::pointer; - using reference = typename parent::reference; - - flat_set() = default; - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category - > - flat_set(Iterator first, Iterator last) : parent(first, last) { - finalize(); - } - - flat_set(std::initializer_list iter) : parent(iter.begin(), iter.end()) { - finalize(); - } - - using parent::parent; - using parent::size; - using parent::empty; - using parent::clear; - using parent::begin; - using parent::end; - using parent::cbegin; - using parent::cend; - using parent::rbegin; - using parent::rend; - using parent::crbegin; - using parent::crend; - using parent::front; - using parent::back; - using parent::contains; - using parent::erase; - - std::pair insert(const Type &value) { - if (this->empty() || this->compare()(value, this->front())) { - this->impl().push_front(value); - return std::make_pair(this->begin(), true); - } else if (this->compare()(this->back(), value)) { - this->impl().push_back(value); - return std::make_pair(this->end() - 1, true); - } - auto where = this->getLowerBound(value); - if (this->compare()(value, *where)) { - return std::make_pair(this->impl().insert(where, value), true); - } - return std::make_pair(where, false); - } - std::pair insert(Type &&value) { - if (this->empty() || this->compare()(value, this->front())) { - this->impl().push_front(std::move(value)); - return std::make_pair(this->begin(), true); - } else if (this->compare()(this->back(), value)) { - this->impl().push_back(std::move(value)); - return std::make_pair(this->end() - 1, true); - } - auto where = this->getLowerBound(value); - if (this->compare()(value, *where)) { - return std::make_pair( - this->impl().insert(where, std::move(value)), - true); - } - return std::make_pair(where, false); - } - template - std::pair emplace(Args&&... args) { - return this->insert(Type(std::forward(args)...)); - } - - bool remove(const Type &value) { - return this->removeOne(value); - } - - iterator find(const Type &value) { - return this->findFirst(value); - } - const_iterator find(const Type &value) const { - return this->findFirst(value); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - iterator find(const OtherType &value) { - return this->findFirst(value); - } - template < - typename OtherType, - typename = typename Compare::is_transparent> - const_iterator find(const OtherType &value) const { - return this->findFirst(value); - } - - template - void modify(iterator which, Action action) { - action(which.wrapped()); - for (auto i = iterator(which + 1), e = end(); i != e; ++i) { - if (this->compare()(*i, *which)) { - std::swap(i.wrapped(), which.wrapped()); - } else if (!this->compare()(*which, *i)) { - erase(which); - return; - } else{ - break; - } - } - for (auto i = which, b = begin(); i != b;) { - --i; - if (this->compare()(*which, *i)) { - std::swap(i.wrapped(), which.wrapped()); - } else if (!this->compare()(*i, *which)) { - erase(which); - return; - } else { - break; - } - } - } - - template < - typename Iterator, - typename = typename std::iterator_traits::iterator_category> - void merge(Iterator first, Iterator last) { - parent::merge(first, last); - finalize(); - } - - void merge(const flat_multi_set &other) { - merge(other.begin(), other.end()); - } - - void merge(std::initializer_list list) { - merge(list.begin(), list.end()); - } - -private: - void finalize() { - this->impl().erase( - std::unique( - std::begin(this->impl()), - std::end(this->impl()), - [&](auto &&a, auto &&b) { - return !this->compare()(a, b); - } - ), - std::end(this->impl())); - } - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/flat_set_tests.cpp b/Telegram/SourceFiles/base/flat_set_tests.cpp deleted file mode 100644 index a73f1d226..000000000 --- a/Telegram/SourceFiles/base/flat_set_tests.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "catch.hpp" - -#include "base/flat_set.h" - -struct int_wrap { - int value; -}; -struct int_wrap_comparator { - using is_transparent = void; - inline bool operator()(const int &a, const int_wrap &b) const { - return a < b.value; - } - inline bool operator()(const int_wrap &a, const int_wrap &b) const { - return a.value < b.value; - } - inline bool operator()(const int_wrap &a, const int &b) const { - return a.value < b; - } - inline bool operator()(const int &a, const int &b) const { - return a < b; - } -}; - -TEST_CASE("flat_sets should keep items sorted", "[flat_set]") { - - base::flat_set v; - v.insert(0); - v.insert(5); - v.insert(4); - v.insert(2); - - REQUIRE(v.contains(4)); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(*prev < *i); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.insert(3); - REQUIRE(v.size() == 5); - REQUIRE(v.find(3) != v.end()); - checkSorted(); - } -} - -TEST_CASE("flat_sets with custom comparators", "[flat_set]") { - base::flat_set v; - v.insert({ 0 }); - v.insert({ 5 }); - v.insert({ 4 }); - v.insert({ 2 }); - - REQUIRE(v.find(4) != v.end()); - - auto checkSorted = [&] { - auto prev = v.begin(); - REQUIRE(prev != v.end()); - for (auto i = prev + 1; i != v.end(); prev = i, ++i) { - REQUIRE(prev->value < i->value); - } - }; - REQUIRE(v.size() == 4); - checkSorted(); - - SECTION("adding item puts it in the right position") { - v.insert({ 3 }); - REQUIRE(v.size() == 5); - REQUIRE(v.find(3) != v.end()); - checkSorted(); - } -} diff --git a/Telegram/SourceFiles/base/functors.h b/Telegram/SourceFiles/base/functors.h deleted file mode 100644 index 2a778a75b..000000000 --- a/Telegram/SourceFiles/base/functors.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { -namespace functors { - -struct abs_helper { - template < - typename Type, - typename = decltype(0 < std::declval()), - typename = decltype(-std::declval())> - constexpr Type operator()(Type value) const { - return (0 < value) ? value : (-value); - } -}; -constexpr auto abs = abs_helper{}; - -constexpr auto add = [](auto value) { - return [value](auto other) { - return value + other; - }; -}; - -struct negate_helper { - template < - typename Type, - typename = decltype(-std::declval())> - constexpr Type operator()(Type value) const { - return -value; - } -}; -constexpr auto negate = negate_helper{}; - -} // namespace functors -} // namespace base diff --git a/Telegram/SourceFiles/base/index_based_iterator.h b/Telegram/SourceFiles/base/index_based_iterator.h deleted file mode 100644 index a4db272d0..000000000 --- a/Telegram/SourceFiles/base/index_based_iterator.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/assertion.h" - -namespace base { - -template -class index_based_iterator { -public: - using iterator_category = std::random_access_iterator_tag; - - using value_type = typename Container::value_type; - using difference_type = typename Container::difference_type; - using pointer = std::conditional_t< - std::is_const_v, - typename Container::const_pointer, - typename Container::pointer>; - using reference = std::conditional_t< - std::is_const_v, - typename Container::const_reference, - typename Container::reference>; - using base_type = std::conditional_t< - std::is_const_v, - typename Container::const_iterator, - typename Container::iterator>; - - index_based_iterator(Container *container, base_type impl) - : _container(container) - , _index(impl - _container->begin()) { - } - - reference operator*() const { - return *(_container->begin() + _index); - } - pointer operator->() const { - return std::addressof(**this); - } - index_based_iterator &operator++() { - ++_index; - return *this; - } - index_based_iterator operator++(int) { - auto copy = *this; - ++*this; - return copy; - } - index_based_iterator &operator--() { - --_index; - return *this; - } - index_based_iterator operator--(int) { - auto copy = *this; - --*this; - return copy; - } - index_based_iterator &operator+=(difference_type offset) { - _index += offset; - return *this; - } - index_based_iterator operator+(difference_type offset) const { - auto copy = *this; - copy += offset; - return copy; - } - index_based_iterator &operator-=(difference_type offset) { - _index -= offset; - return *this; - } - index_based_iterator operator-(difference_type offset) const { - auto copy = *this; - copy -= offset; - return copy; - } - difference_type operator-(const index_based_iterator &other) const { - return _index - other._index; - } - reference operator[](difference_type offset) const { - return *(*this + offset); - } - - bool operator==(const index_based_iterator &other) const { - Expects(_container == other._container); - return _index == other._index; - } - bool operator!=(const index_based_iterator &other) const { - Expects(_container == other._container); - return _index != other._index; - } - bool operator<(const index_based_iterator &other) const { - Expects(_container == other._container); - return _index < other._index; - } - bool operator>(const index_based_iterator &other) const { - return other < *this; - } - bool operator<=(const index_based_iterator &other) const { - return !(other < *this); - } - bool operator>=(const index_based_iterator &other) const { - return !(*this < other); - } - - base_type base() const { - return _container->begin() + _index; - } - -private: - Container *_container = nullptr; - difference_type _index = 0; - -}; - -template -index_based_iterator index_based_begin(Container &container) { - return { &container, std::begin(container) }; -} - -template -index_based_iterator index_based_end(Container &container) { - return { &container, std::end(container) }; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/invoke_queued.h b/Telegram/SourceFiles/base/invoke_queued.h deleted file mode 100644 index a94efe527..000000000 --- a/Telegram/SourceFiles/base/invoke_queued.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -#include "base/basic_types.h" - -namespace base { - -class InvokeQueuedEvent : public QEvent { -public: - static constexpr auto kType = QEvent::Type(60666); - - explicit InvokeQueuedEvent(FnMut &&method) - : QEvent(kType) - , _method(std::move(method)) { - } - - void invoke() { - _method(); - } - -private: - FnMut _method; - -}; - -} // namespace base - -template -inline void InvokeQueued(const QObject *context, Lambda &&lambda) { - QCoreApplication::postEvent( - const_cast(context), - new base::InvokeQueuedEvent(std::forward(lambda))); -} - -class SingleQueuedInvokation : public QObject { -public: - SingleQueuedInvokation(Fn callback) : _callback(callback) { - } - void call() { - if (_pending.testAndSetAcquire(0, 1)) { - InvokeQueued(this, [this] { - if (_pending.testAndSetRelease(1, 0)) { - _callback(); - } - }); - } - } - -private: - Fn _callback; - QAtomicInt _pending = { 0 }; - -}; diff --git a/Telegram/SourceFiles/base/last_used_cache.h b/Telegram/SourceFiles/base/last_used_cache.h deleted file mode 100644 index 65d5fb4a3..000000000 --- a/Telegram/SourceFiles/base/last_used_cache.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace base { - -template -class last_used_cache { -public: - void up(Entry entry); - void remove(Entry entry); - void clear(); - - Entry take_lowest(); - -private: - std::list _queue; - std::unordered_map::iterator> _map; - -}; - -template -void last_used_cache::up(Entry entry) { - if (!_queue.empty() && _queue.back() == entry) { - return; - } - const auto i = _map.find(entry); - if (i != end(_map)) { - _queue.splice(end(_queue), _queue, i->second); - } else { - _map.emplace(entry, _queue.insert(end(_queue), entry)); - } -} - -template -void last_used_cache::remove(Entry entry) { - const auto i = _map.find(entry); - if (i != end(_map)) { - _queue.erase(i->second); - _map.erase(i); - } -} - -template -void last_used_cache::clear() { - _queue.clear(); - _map.clear(); -} - -template -Entry last_used_cache::take_lowest() { - if (_queue.empty()) { - return Entry(); - } - auto result = std::move(_queue.front()); - _queue.erase(begin(_queue)); - _map.erase(result); - return result; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/match_method.h b/Telegram/SourceFiles/base/match_method.h deleted file mode 100644 index 209494939..000000000 --- a/Telegram/SourceFiles/base/match_method.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -inline decltype(auto) match_method( - Data &&data, - Method &&method, - Methods &&...methods) { - using namespace rpl::details; - if constexpr (is_callable_plain_v) { - return std::forward(method)(std::forward(data)); - } else { - return match_method( - std::forward(data), - std::forward(methods)...); - } -} - -template < - typename Data1, - typename Data2, - typename Method, - typename ...Methods> -inline decltype(auto) match_method2( - Data1 &&data1, - Data2 &&data2, - Method &&method, - Methods &&...methods) { - using namespace rpl::details; - if constexpr (is_callable_plain_v) { - return std::forward(method)( - std::forward(data1), - std::forward(data2)); - } else { - return match_method2( - std::forward(data1), - std::forward(data2), - std::forward(methods)...); - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/object_ptr.h b/Telegram/SourceFiles/base/object_ptr.h deleted file mode 100644 index 714ee600a..000000000 --- a/Telegram/SourceFiles/base/object_ptr.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -// Smart pointer for QObject*, has move semantics, destroys object if it doesn't have a parent. -template -class object_ptr { -public: - object_ptr(std::nullptr_t) noexcept { - } - - // No default constructor, but constructors with at least - // one argument are simply make functions. - template - explicit object_ptr(Parent &&parent, Args&&... args) - : _object(new Object(std::forward(parent), std::forward(args)...)) { - } - static object_ptr fromRaw(Object *value) noexcept { - object_ptr result = { nullptr }; - result._object = value; - return result; - } - Object *release() noexcept { - return static_cast(base::take(_object).data()); - } - - object_ptr(const object_ptr &other) = delete; - object_ptr &operator=(const object_ptr &other) = delete; - object_ptr(object_ptr &&other) noexcept : _object(base::take(other._object)) { - } - object_ptr &operator=(object_ptr &&other) noexcept { - auto temp = std::move(other); - destroy(); - std::swap(_object, temp._object); - return *this; - } - - template < - typename OtherObject, - typename = std::enable_if_t< - std::is_base_of_v>> - object_ptr(object_ptr &&other) noexcept - : _object(base::take(other._object)) { - } - - template < - typename OtherObject, - typename = std::enable_if_t< - std::is_base_of_v>> - object_ptr &operator=(object_ptr &&other) noexcept { - _object = base::take(other._object); - return *this; - } - - object_ptr &operator=(std::nullptr_t) noexcept { - _object = nullptr; - return *this; - } - - // So we can pass this pointer to methods like connect(). - Object *data() const noexcept { - return static_cast(_object.data()); - } - operator Object*() const noexcept { - return data(); - } - - explicit operator bool() const noexcept { - return _object != nullptr; - } - - Object *operator->() const noexcept { - return data(); - } - Object &operator*() const noexcept { - return *data(); - } - - // Use that instead "= new Object(parent, ...)" - template - Object *create(Parent &&parent, Args&&... args) { - destroy(); - _object = new Object( - std::forward(parent), - std::forward(args)...); - return data(); - } - void destroy() noexcept { - delete base::take(_object); - } - void destroyDelayed() { - if (_object) { - if (auto widget = base::up_cast(data())) { - widget->hide(); - } - base::take(_object)->deleteLater(); - } - } - - ~object_ptr() noexcept { - if (auto pointer = _object) { - if (!pointer->parent()) { - destroy(); - } - } - } - -private: - template - friend class object_ptr; - - QPointer _object; - -}; diff --git a/Telegram/SourceFiles/base/observer.cpp b/Telegram/SourceFiles/base/observer.cpp deleted file mode 100644 index 1c1245071..000000000 --- a/Telegram/SourceFiles/base/observer.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/observer.h" - -namespace base { -namespace internal { -namespace { - -bool CantUseObservables = false; -void (*HandleDelayedMethod)() = nullptr; - -struct ObservableListWrap { - ~ObservableListWrap() { - CantUseObservables = true; - } - OrderedSet list; -}; - -ObservableListWrap &PendingObservables() { - static ObservableListWrap result; - return result; -} - -ObservableListWrap &ActiveObservables() { - static ObservableListWrap result; - return result; -} - -} // namespace - -void RegisterPendingObservable(ObservableCallHandlers *handlers) { - if (CantUseObservables) return; - PendingObservables().list.insert(handlers); - if (HandleDelayedMethod) { - HandleDelayedMethod(); - } -} - -void UnregisterActiveObservable(ObservableCallHandlers *handlers) { - if (CantUseObservables) return; - ActiveObservables().list.remove(handlers); -} - -void UnregisterObservable(ObservableCallHandlers *handlers) { - if (CantUseObservables) return; - PendingObservables().list.remove(handlers); - ActiveObservables().list.remove(handlers); -} - -} // namespace internal - -void InitObservables(void(*HandleDelayed)()) { - internal::HandleDelayedMethod = HandleDelayed; -} - -void HandleObservables() { - if (internal::CantUseObservables) return; - auto &active = internal::ActiveObservables().list; - qSwap(active, internal::PendingObservables().list); - while (!active.empty()) { - auto first = *active.begin(); - (*first)(); - if (!active.empty() && *active.begin() == first) { - active.erase(active.begin()); - } - } -} - -rpl::producer<> ObservableViewer(base::Observable &observable) { - return [&observable](const auto &consumer) { - auto lifetime = rpl::lifetime(); - lifetime.make_state( - observable.add_subscription([consumer]() { - consumer.put_next({}); - })); - return lifetime; - }; -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/observer.h b/Telegram/SourceFiles/base/observer.h deleted file mode 100644 index 75bc0e722..000000000 --- a/Telegram/SourceFiles/base/observer.h +++ /dev/null @@ -1,476 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include "base/type_traits.h" - -namespace base { -namespace internal { - -using ObservableCallHandlers = Fn; -void RegisterPendingObservable(ObservableCallHandlers *handlers); -void UnregisterActiveObservable(ObservableCallHandlers *handlers); -void UnregisterObservable(ObservableCallHandlers *handlers); - -template -struct SubscriptionHandlerHelper { - using type = Fn)>; -}; - -template <> -struct SubscriptionHandlerHelper { - using type = Fn; -}; - -template -using SubscriptionHandler = typename SubscriptionHandlerHelper::type; - -class BaseObservableData { -}; - -template -class CommonObservableData; - -template -class ObservableData; - -} // namespace internal - -class Subscription { -public: - Subscription() = default; - Subscription(const Subscription &) = delete; - Subscription &operator=(const Subscription &) = delete; - Subscription(Subscription &&other) : _node(base::take(other._node)), _removeAndDestroyMethod(other._removeAndDestroyMethod) { - } - Subscription &operator=(Subscription &&other) { - qSwap(_node, other._node); - qSwap(_removeAndDestroyMethod, other._removeAndDestroyMethod); - return *this; - } - explicit operator bool() const { - return (_node != nullptr); - } - void destroy() { - if (_node) { - (*_removeAndDestroyMethod)(base::take(_node)); - } - } - ~Subscription() { - destroy(); - } - -private: - struct Node { - Node(const std::shared_ptr &observable) - : observable(observable) { - } - Node *next = nullptr; - Node *prev = nullptr; - std::weak_ptr observable; - }; - using RemoveAndDestroyMethod = void(*)(Node*); - Subscription(Node *node, RemoveAndDestroyMethod removeAndDestroyMethod) - : _node(node) - , _removeAndDestroyMethod(removeAndDestroyMethod) { - } - - Node *_node = nullptr; - RemoveAndDestroyMethod _removeAndDestroyMethod; - - template - friend class internal::CommonObservableData; - - template - friend class internal::ObservableData; - -}; - -namespace internal { - -template -class BaseObservable; - -template -class CommonObservable { -public: - Subscription add_subscription(Handler &&handler) { - if (!_data) { - _data = std::make_shared>(this); - } - return _data->append(std::move(handler)); - } - -private: - std::shared_ptr> _data; - - friend class CommonObservableData; - friend class BaseObservable::is_fast_copy_type::value>; - -}; - -template -class BaseObservable : public internal::CommonObservable { -public: - void notify(EventType event, bool sync = false) { - if (this->_data) { - this->_data->notify(std::move(event), sync); - } - } - -}; - -template -class BaseObservable : public internal::CommonObservable { -public: - void notify(EventType &&event, bool sync = false) { - if (this->_data) { - this->_data->notify(std::move(event), sync); - } - } - void notify(const EventType &event, bool sync = false) { - if (this->_data) { - auto event_copy = event; - this->_data->notify(std::move(event_copy), sync); - } - } - -}; - -} // namespace internal - -namespace internal { - -template -class CommonObservableData : public BaseObservableData { -public: - CommonObservableData(CommonObservable *observable) : _observable(observable) { - } - - Subscription append(Handler &&handler) { - auto node = new Node(_observable->_data, std::move(handler)); - if (_begin) { - _end->next = node; - node->prev = _end; - _end = node; - } else { - _begin = _end = node; - } - return { _end, &CommonObservableData::removeAndDestroyNode }; - } - - bool empty() const { - return !_begin; - } - -private: - struct Node : public Subscription::Node { - Node( - const std::shared_ptr &observer, - Handler &&handler) - : Subscription::Node(observer) - , handler(std::move(handler)) { - } - Handler handler; - }; - - void remove(Subscription::Node *node) { - if (node->prev) { - node->prev->next = node->next; - } - if (node->next) { - node->next->prev = node->prev; - } - if (_begin == node) { - _begin = static_cast(node->next); - } - if (_end == node) { - _end = static_cast(node->prev); - } - if (_current == node) { - _current = static_cast(node->prev); - } else if (!_begin) { - _observable->_data.reset(); - } - } - - static void removeAndDestroyNode(Subscription::Node *node) { - if (const auto that = node->observable.lock()) { - static_cast(that.get())->remove(node); - } - delete static_cast(node); - } - - template - void notifyEnumerate(CallCurrent callCurrent) { - _current = _begin; - do { - callCurrent(); - if (_current) { - _current = static_cast(_current->next); - } else if (_begin) { - _current = _begin; - } else { - break; - } - } while (_current); - } - - bool destroyMeIfEmpty() const { - if (empty()) { - _observable->_data.reset(); - return true; - } - return false; - } - - CommonObservable *_observable = nullptr; - Node *_begin = nullptr; - Node *_current = nullptr; - Node *_end = nullptr; - ObservableCallHandlers _callHandlers; - - friend class ObservableData; - -}; - -template -class ObservableData : public CommonObservableData { -public: - using CommonObservableData::CommonObservableData; - - void notify(EventType &&event, bool sync) { - if (_handling) { - sync = false; - } - if (sync) { - _events.push_back(std::move(event)); - callHandlers(); - } else { - if (!this->_callHandlers) { - this->_callHandlers = [this]() { - callHandlers(); - }; - } - if (_events.empty()) { - RegisterPendingObservable(&this->_callHandlers); - } - _events.push_back(std::move(event)); - } - } - - ~ObservableData() { - UnregisterObservable(&this->_callHandlers); - } - -private: - void callHandlers() { - _handling = true; - auto events = base::take(_events); - for (auto &event : events) { - this->notifyEnumerate([this, &event]() { - this->_current->handler(event); - }); - if (this->destroyMeIfEmpty()) { - return; - } - } - _handling = false; - UnregisterActiveObservable(&this->_callHandlers); - } - - std::deque _events; - bool _handling = false; - -}; - -template -class ObservableData : public CommonObservableData { -public: - using CommonObservableData::CommonObservableData; - - void notify(bool sync) { - if (_handling) { - sync = false; - } - if (sync) { - ++_eventsCount; - callHandlers(); - } else { - if (!this->_callHandlers) { - this->_callHandlers = [this]() { - callHandlers(); - }; - } - if (!_eventsCount) { - RegisterPendingObservable(&this->_callHandlers); - } - ++_eventsCount; - } - } - - ~ObservableData() { - UnregisterObservable(&this->_callHandlers); - } - -private: - void callHandlers() { - _handling = true; - auto eventsCount = base::take(_eventsCount); - for (int i = 0; i != eventsCount; ++i) { - this->notifyEnumerate([this]() { - this->_current->handler(); - }); - if (this->destroyMeIfEmpty()) { - return; - } - } - _handling = false; - UnregisterActiveObservable(&this->_callHandlers); - } - - int _eventsCount = 0; - bool _handling = false; - -}; - -template -class BaseObservable::is_fast_copy_type::value> : public internal::CommonObservable { -public: - void notify(bool sync = false) { - if (this->_data) { - this->_data->notify(sync); - } - } - -}; - -} // namespace internal - -template > -class Observable : public internal::BaseObservable::is_fast_copy_type::value> { -public: - Observable() = default; - Observable(const Observable &other) = delete; - Observable(Observable &&other) = default; - Observable &operator=(const Observable &other) = delete; - Observable &operator=(Observable &&other) = default; - -}; - -template -class Variable { -public: - Variable(parameter_type startValue = Type()) : _value(startValue) { - } - Variable(Variable &&other) = default; - Variable &operator=(Variable &&other) = default; - - parameter_type value() const { - return _value; - } - - void setForced(parameter_type newValue, bool sync = false) { - _value = newValue; - changed().notify(_value, sync); - } - - void set(parameter_type newValue, bool sync = false) { - if (_value != newValue) { - setForced(newValue, sync); - } - } - - template - void process(Callback callback, bool sync = false) { - callback(_value); - changed().notify(_value, sync); - } - - Observable &changed() const { - return _changed; - } - -private: - Type _value; - mutable Observable _changed; - -}; - -class Subscriber { -protected: - template - int subscribe(base::Observable &observable, Lambda &&handler) { - _subscriptions.push_back(observable.add_subscription(std::forward(handler))); - return _subscriptions.size(); - } - - template - int subscribe(base::Observable *observable, Lambda &&handler) { - return subscribe(*observable, std::forward(handler)); - } - - template - int subscribe(const base::Variable &variable, Lambda &&handler) { - return subscribe(variable.changed(), std::forward(handler)); - } - - template - int subscribe(const base::Variable *variable, Lambda &&handler) { - return subscribe(variable->changed(), std::forward(handler)); - } - - void unsubscribe(int index) { - if (!index) return; - auto count = static_cast(_subscriptions.size()); - Assert(index > 0 && index <= count); - _subscriptions[index - 1].destroy(); - if (index == count) { - while (index > 0 && !_subscriptions[--index]) { - _subscriptions.pop_back(); - } - } - } - - ~Subscriber() { - auto subscriptions = base::take(_subscriptions); - for (auto &subscription : subscriptions) { - subscription.destroy(); - } - } - -private: - std::vector _subscriptions; - -}; - -void InitObservables(void(*HandleDelayed)()); -void HandleObservables(); - -template < - typename Type, - typename = std::enable_if_t>> -inline auto ObservableViewer(base::Observable &observable) { - return rpl::make_producer([&observable]( - const auto &consumer) { - auto lifetime = rpl::lifetime(); - lifetime.make_state( - observable.add_subscription([consumer](auto &&update) { - consumer.put_next_forward( - std::forward(update)); - })); - return lifetime; - }); -} - -rpl::producer<> ObservableViewer(base::Observable &observable); - -} // namespace base diff --git a/Telegram/SourceFiles/base/openssl_help.h b/Telegram/SourceFiles/base/openssl_help.h deleted file mode 100644 index f9ca3ccfb..000000000 --- a/Telegram/SourceFiles/base/openssl_help.h +++ /dev/null @@ -1,577 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/bytes.h" -#include "base/algorithm.h" -#include "base/basic_types.h" - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -} // extern "C" - -#ifdef small -#undef small -#endif // small - -namespace openssl { - -class Context { -public: - Context() : _data(BN_CTX_new()) { - } - Context(const Context &other) = delete; - Context(Context &&other) : _data(base::take(other._data)) { - } - Context &operator=(const Context &other) = delete; - Context &operator=(Context &&other) { - _data = base::take(other._data); - return *this; - } - ~Context() { - if (_data) { - BN_CTX_free(_data); - } - } - - BN_CTX *raw() const { - return _data; - } - -private: - BN_CTX *_data = nullptr; - -}; - -class BigNum { -public: - BigNum() = default; - BigNum(const BigNum &other) - : _data((other.failed() || other.isZero()) - ? nullptr - : BN_dup(other.raw())) - , _failed(other._failed) { - } - BigNum(BigNum &&other) - : _data(std::exchange(other._data, nullptr)) - , _failed(std::exchange(other._failed, false)) { - } - BigNum &operator=(const BigNum &other) { - if (other.failed()) { - _failed = true; - } else if (other.isZero()) { - clear(); - _failed = false; - } else if (!_data) { - _data = BN_dup(other.raw()); - _failed = false; - } else { - _failed = !BN_copy(raw(), other.raw()); - } - return *this; - } - BigNum &operator=(BigNum &&other) { - std::swap(_data, other._data); - std::swap(_failed, other._failed); - return *this; - } - ~BigNum() { - clear(); - } - - explicit BigNum(unsigned int word) : BigNum() { - setWord(word); - } - explicit BigNum(bytes::const_span bytes) : BigNum() { - setBytes(bytes); - } - - BigNum &setWord(unsigned int word) { - if (!word) { - clear(); - _failed = false; - } else { - _failed = !BN_set_word(raw(), word); - } - return *this; - } - BigNum &setBytes(bytes::const_span bytes) { - if (bytes.empty()) { - clear(); - _failed = false; - } else { - _failed = !BN_bin2bn( - reinterpret_cast(bytes.data()), - bytes.size(), - raw()); - } - return *this; - } - - BigNum &setAdd(const BigNum &a, const BigNum &b) { - if (a.failed() || b.failed()) { - _failed = true; - } else { - _failed = !BN_add(raw(), a.raw(), b.raw()); - } - return *this; - } - BigNum &setSub(const BigNum &a, const BigNum &b) { - if (a.failed() || b.failed()) { - _failed = true; - } else { - _failed = !BN_sub(raw(), a.raw(), b.raw()); - } - return *this; - } - BigNum &setMul( - const BigNum &a, - const BigNum &b, - const Context &context = Context()) { - if (a.failed() || b.failed()) { - _failed = true; - } else { - _failed = !BN_mul(raw(), a.raw(), b.raw(), context.raw()); - } - return *this; - } - BigNum &setModAdd( - const BigNum &a, - const BigNum &b, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || b.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || b.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_add(raw(), a.raw(), b.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModSub( - const BigNum &a, - const BigNum &b, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || b.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || b.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_sub(raw(), a.raw(), b.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModMul( - const BigNum &a, - const BigNum &b, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || b.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || b.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_mul(raw(), a.raw(), b.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModInverse( - const BigNum &a, - const BigNum &m, - const Context &context = Context()) { - if (a.failed() || m.failed()) { - _failed = true; - } else if (a.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_inverse(raw(), a.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - BigNum &setModExp( - const BigNum &base, - const BigNum &power, - const BigNum &m, - const Context &context = Context()) { - if (base.failed() || power.failed() || m.failed()) { - _failed = true; - } else if (base.isNegative() || power.isNegative() || m.isNegative()) { - _failed = true; - } else if (!BN_mod_exp(raw(), base.raw(), power.raw(), m.raw(), context.raw())) { - _failed = true; - } else if (isNegative()) { - _failed = true; - } else { - _failed = false; - } - return *this; - } - - [[nodiscard]] bool isZero() const { - return !failed() && (!_data || BN_is_zero(raw())); - } - - [[nodiscard]] bool isOne() const { - return !failed() && _data && BN_is_one(raw()); - } - - [[nodiscard]] bool isNegative() const { - return !failed() && _data && BN_is_negative(raw()); - } - - [[nodiscard]] bool isPrime(const Context &context = Context()) const { - if (failed() || !_data) { - return false; - } - constexpr auto kMillerRabinIterationCount = 30; - const auto result = BN_is_prime_ex( - raw(), - kMillerRabinIterationCount, - context.raw(), - nullptr); - if (result == 1) { - return true; - } else if (result != 0) { - _failed = true; - } - return false; - } - - BigNum &subWord(unsigned int word) { - if (failed()) { - return *this; - } else if (!BN_sub_word(raw(), word)) { - _failed = true; - } - return *this; - } - BigNum &divWord(BN_ULONG word, BN_ULONG *mod = nullptr) { - Expects(word != 0); - - const auto result = failed() - ? (BN_ULONG)-1 - : BN_div_word(raw(), word); - if (result == (BN_ULONG)-1) { - _failed = true; - } - if (mod) { - *mod = result; - } - return *this; - } - [[nodiscard]] BN_ULONG countModWord(BN_ULONG word) const { - Expects(word != 0); - - return failed() ? (BN_ULONG)-1 : BN_mod_word(raw(), word); - } - - [[nodiscard]] int bitsSize() const { - return failed() ? 0 : BN_num_bits(raw()); - } - [[nodiscard]] int bytesSize() const { - return failed() ? 0 : BN_num_bytes(raw()); - } - - [[nodiscard]] bytes::vector getBytes() const { - if (failed()) { - return {}; - } - auto length = BN_num_bytes(raw()); - auto result = bytes::vector(length); - auto resultSize = BN_bn2bin( - raw(), - reinterpret_cast(result.data())); - Assert(resultSize == length); - return result; - } - - [[nodiscard]] BIGNUM *raw() { - if (!_data) _data = BN_new(); - return _data; - } - [[nodiscard]] const BIGNUM *raw() const { - if (!_data) _data = BN_new(); - return _data; - } - [[nodiscard]] BIGNUM *takeRaw() { - return _failed - ? nullptr - : _data - ? std::exchange(_data, nullptr) - : BN_new(); - } - - [[nodiscard]] bool failed() const { - return _failed; - } - - [[nodiscard]] static BigNum Add(const BigNum &a, const BigNum &b) { - return BigNum().setAdd(a, b); - } - [[nodiscard]] static BigNum Sub(const BigNum &a, const BigNum &b) { - return BigNum().setSub(a, b); - } - [[nodiscard]] static BigNum Mul( - const BigNum &a, - const BigNum &b, - const Context &context = Context()) { - return BigNum().setMul(a, b, context); - } - [[nodiscard]] static BigNum ModAdd( - const BigNum &a, - const BigNum &b, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModAdd(a, b, mod, context); - } - [[nodiscard]] static BigNum ModSub( - const BigNum &a, - const BigNum &b, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModSub(a, b, mod, context); - } - [[nodiscard]] static BigNum ModMul( - const BigNum &a, - const BigNum &b, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModMul(a, b, mod, context); - } - [[nodiscard]] static BigNum ModInverse( - const BigNum &a, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModInverse(a, mod, context); - } - [[nodiscard]] static BigNum ModExp( - const BigNum &base, - const BigNum &power, - const BigNum &mod, - const Context &context = Context()) { - return BigNum().setModExp(base, power, mod, context); - } - [[nodiscard]] static BigNum Failed() { - auto result = BigNum(); - result._failed = true; - return result; - } - -private: - void clear() { - BN_clear_free(std::exchange(_data, nullptr)); - } - - mutable BIGNUM *_data = nullptr; - mutable bool _failed = false; - -}; - -namespace details { - -template -inline void ShaUpdate(Context context, Method method, Arg &&arg) { - const auto span = bytes::make_span(arg); - method(context, span.data(), span.size()); -} - -template -inline void ShaUpdate(Context context, Method method, Arg &&arg, Args &&...args) { - const auto span = bytes::make_span(arg); - method(context, span.data(), span.size()); - ShaUpdate(context, method, args...); -} - -template -inline bytes::vector Sha(Method method, bytes::const_span data) { - auto result = bytes::vector(Size); - method( - reinterpret_cast(data.data()), - data.size(), - reinterpret_cast(result.data())); - return result; -} - -template < - size_type Size, - typename Context, - typename Init, - typename Update, - typename Finalize, - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -bytes::vector Sha( - Context context, - Init init, - Update update, - Finalize finalize, - Args &&...args) { - auto result = bytes::vector(Size); - - init(&context); - ShaUpdate(&context, update, args...); - finalize(reinterpret_cast(result.data()), &context); - - return result; -} - -template < - size_type Size, - typename Evp> -bytes::vector Pbkdf2( - bytes::const_span password, - bytes::const_span salt, - int iterations, - Evp evp) { - auto result = bytes::vector(Size); - PKCS5_PBKDF2_HMAC( - reinterpret_cast(password.data()), - password.size(), - reinterpret_cast(salt.data()), - salt.size(), - iterations, - evp, - result.size(), - reinterpret_cast(result.data())); - return result; -} - -} // namespace details - -constexpr auto kSha1Size = size_type(SHA_DIGEST_LENGTH); -constexpr auto kSha256Size = size_type(SHA256_DIGEST_LENGTH); -constexpr auto kSha512Size = size_type(SHA512_DIGEST_LENGTH); - -inline bytes::vector Sha1(bytes::const_span data) { - return details::Sha(SHA1, data); -} - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -inline bytes::vector Sha1(Args &&...args) { - return details::Sha( - SHA_CTX(), - SHA1_Init, - SHA1_Update, - SHA1_Final, - args...); -} - -inline bytes::vector Sha256(bytes::const_span data) { - return details::Sha(SHA256, data); -} - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -inline bytes::vector Sha256(Args &&...args) { - return details::Sha( - SHA256_CTX(), - SHA256_Init, - SHA256_Update, - SHA256_Final, - args...); -} - -inline bytes::vector Sha512(bytes::const_span data) { - return details::Sha(SHA512, data); -} - -template < - typename ...Args, - typename = std::enable_if_t<(sizeof...(Args) > 1)>> -inline bytes::vector Sha512(Args &&...args) { - return details::Sha( - SHA512_CTX(), - SHA512_Init, - SHA512_Update, - SHA512_Final, - args...); -} - -inline void AddRandomSeed(bytes::const_span data) { - RAND_seed(data.data(), data.size()); -} - -template >> -[[nodiscard]] inline T RandomValue() { - unsigned char buffer[sizeof(T)]; - if (!RAND_bytes(buffer, sizeof(T))) { - Unexpected("Could not generate random bytes!"); - } - auto result = T(); - memcpy(&result, buffer, sizeof(T)); - return result; -} - -inline bytes::vector Pbkdf2Sha512( - bytes::const_span password, - bytes::const_span salt, - int iterations) { - return details::Pbkdf2( - password, - salt, - iterations, - EVP_sha512()); -} - -inline bytes::vector HmacSha256( - bytes::const_span key, - bytes::const_span data) { - auto result = bytes::vector(kSha256Size); - auto length = (unsigned int)kSha256Size; - - HMAC( - EVP_sha256(), - key.data(), - key.size(), - reinterpret_cast(data.data()), - data.size(), - reinterpret_cast(result.data()), - &length); - - return result; -} - -} // namespace openssl - -namespace bytes { - -inline void set_random(span destination) { - RAND_bytes( - reinterpret_cast(destination.data()), - destination.size()); -} - -} // namespace bytes diff --git a/Telegram/SourceFiles/base/optional.h b/Telegram/SourceFiles/base/optional.h deleted file mode 100644 index 2628ee5bb..000000000 --- a/Telegram/SourceFiles/base/optional.h +++ /dev/null @@ -1,171 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "base/variant.h" - -namespace base { - -template -class optional_variant { -public: - optional_variant() : _impl(std::nullopt) { - } - optional_variant(const optional_variant &other) : _impl(other._impl) { - } - optional_variant(optional_variant &&other) : _impl(std::move(other._impl)) { - } - template >::value>> - optional_variant(T &&value) : _impl(std::forward(value)) { - } - optional_variant &operator=(const optional_variant &other) { - _impl = other._impl; - return *this; - } - optional_variant &operator=(optional_variant &&other) { - _impl = std::move(other._impl); - return *this; - } - template >::value>> - optional_variant &operator=(T &&value) { - _impl = std::forward(value); - return *this; - } - - bool has_value() const { - return !is(); - } - explicit operator bool() const { - return has_value(); - } - bool operator==(const optional_variant &other) const { - return _impl == other._impl; - } - bool operator!=(const optional_variant &other) const { - return _impl != other._impl; - } - bool operator<(const optional_variant &other) const { - return _impl < other._impl; - } - bool operator<=(const optional_variant &other) const { - return _impl <= other._impl; - } - bool operator>(const optional_variant &other) const { - return _impl > other._impl; - } - bool operator>=(const optional_variant &other) const { - return _impl >= other._impl; - } - - template - T &set(Args &&...args) { - _impl.template set(std::forward(args)...); - return get_unchecked(); - } - void clear() { - _impl.template set(); - } - - template - decltype(auto) is() const { - return _impl.template is(); - } - template - decltype(auto) get_unchecked() { - return _impl.template get_unchecked(); - } - template - decltype(auto) get_unchecked() const { - return _impl.template get_unchecked(); - } - - template - decltype(auto) match(Methods &&...methods) { - return base::match(_impl, std::forward(methods)...); - } - template - decltype(auto) match(Methods &&...methods) const { - return base::match(_impl, std::forward(methods)...); - } - -private: - variant _impl; - -}; - -template -inline T *get_if(optional_variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -template -inline const T *get_if(const optional_variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -template -inline decltype(auto) match( - optional_variant &value, - Methods &&...methods) { - return value.match(std::forward(methods)...); -} - -template -inline decltype(auto) match( - const optional_variant &value, - Methods &&...methods) { - return value.match(std::forward(methods)...); -} - -template -struct optional_wrap_once { - using type = std::optional; -}; - -template -struct optional_wrap_once> { - using type = std::optional; -}; - -template -using optional_wrap_once_t = typename optional_wrap_once>::type; - -template -struct optional_chain_result { - using type = optional_wrap_once_t; -}; - -template <> -struct optional_chain_result { - using type = bool; -}; - -template -using optional_chain_result_t = typename optional_chain_result::type; - -template -optional_wrap_once_t make_optional(Type &&value) { - return optional_wrap_once_t { std::forward(value) }; -} - -} // namespace base - -template -inline auto operator|(const std::optional &value, Method method) --> base::optional_chain_result_t { - if constexpr (std::is_same_v) { - return value ? (method(*value), true) : false; - } else { - return value - ? base::optional_chain_result_t( - method(*value)) - : std::nullopt; - } -} diff --git a/Telegram/SourceFiles/base/ordered_set.h b/Telegram/SourceFiles/base/ordered_set.h deleted file mode 100644 index f9ea222d7..000000000 --- a/Telegram/SourceFiles/base/ordered_set.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#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: - OrderedSet() = default; - OrderedSet(const OrderedSet &other) = default; - OrderedSet(OrderedSet &&other) = default; - OrderedSet &operator=(const OrderedSet &other) = default; - OrderedSet &operator=(OrderedSet &&other) = default; - ~OrderedSet() = default; - - 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/base/overload.h b/Telegram/SourceFiles/base/overload.h deleted file mode 100644 index 33e3acae3..000000000 --- a/Telegram/SourceFiles/base/overload.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { -namespace details { - -// This implementation was taken from range-v3 library. -// It was modified so that more than one of passed function objects -// could be called with an argument list and the first one that -// matches gets used instead of a compile-time ambiguity error. -// -// This allows to write "default" visitor handlers with [](auto&&) syntax. - -template -constexpr bool is_callable_v = rpl::details::is_callable_plain_v; - -template -struct overloaded; - -template <> -struct overloaded<> { -}; - -template -struct overloaded - : private First - , private overloaded { - -private: - using Others = overloaded; - -public: - overloaded() = default; - - constexpr overloaded(First first, Rest... rest) - : First(std::move(first)) - , Others(std::move(rest)...) { - } - - template - auto operator()(Args&&... args) - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - - template - auto operator()(Args&&... args) const - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - - template < - typename... Args, - typename = std::enable_if_t>> - auto operator()(Args&&... args) - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - - template < - typename... Args, - typename = std::enable_if_t>> - auto operator()(Args&&... args) const - -> decltype(std::declval()(std::forward(args)...)) { - return static_cast(*this)(std::forward(args)...); - } - -}; - -} // namespace details - -template -Function overload(Function &&function) { - return std::forward(function); -} - -template 1)>> -auto overload(Functions ...functions) { - return details::overloaded(std::move(functions)...); -} - -} // namespace base - diff --git a/Telegram/SourceFiles/base/parse_helper.cpp b/Telegram/SourceFiles/base/parse_helper.cpp deleted file mode 100644 index 52f1b12c0..000000000 --- a/Telegram/SourceFiles/base/parse_helper.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/parse_helper.h" - -namespace base { -namespace parse { - -// inspired by https://github.com/sindresorhus/strip-json-comments -QByteArray stripComments(const QByteArray &content) { - enum class InsideComment { - None, - SingleLine, - MultiLine, - }; - auto insideComment = InsideComment::None; - auto insideString = false; - - QByteArray result; - auto begin = content.cbegin(), end = content.cend(), offset = begin; - auto feedContent = [&result, &offset, end](const char *ch) { - if (ch > offset) { - if (result.isEmpty()) result.reserve(end - offset - 2); - result.append(offset, ch - offset); - offset = ch; - } - }; - auto feedComment = [&result, &offset, end](const char *ch) { - if (ch > offset) { - if (result.isEmpty()) result.reserve(end - offset - 2); - result.append(' '); - offset = ch; - } - }; - for (auto ch = offset; ch != end;) { - auto currentChar = *ch; - auto nextChar = (ch + 1 == end) ? 0 : *(ch + 1); - - if (insideComment == InsideComment::None && currentChar == '"') { - auto escaped = ((ch > begin) && *(ch - 1) == '\\') && ((ch - 1 < begin) || *(ch - 2) != '\\'); - if (!escaped) { - insideString = !insideString; - } - } - if (insideString) { - ++ch; - continue; - } - - if (insideComment == InsideComment::None && currentChar == '/' && nextChar == '/') { - feedContent(ch); - insideComment = InsideComment::SingleLine; - ch += 2; - } else if (insideComment == InsideComment::SingleLine && currentChar == '\r' && nextChar == '\n') { - feedComment(ch); - ch += 2; - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::SingleLine && currentChar == '\n') { - feedComment(ch); - ++ch; - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::None && currentChar == '/' && nextChar == '*') { - feedContent(ch); - ch += 2; - insideComment = InsideComment::MultiLine; - } else if (insideComment == InsideComment::MultiLine && currentChar == '*' && nextChar == '/') { - ch += 2; - feedComment(ch); - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::MultiLine && currentChar == '\r' && nextChar == '\n') { - feedComment(ch); - ch += 2; - feedContent(ch); - } else if (insideComment == InsideComment::MultiLine && currentChar == '\n') { - feedComment(ch); - ++ch; - feedContent(ch); - } else { - ++ch; - } - } - - if (insideComment == InsideComment::MultiLine) { - // unexpected end of content - } - if (insideComment == InsideComment::None && end > offset) { - if (result.isEmpty()) { - return content; - } else { - result.append(offset, end - offset); - } - } - return result; -} - -} // namespace parse -} // namespace base diff --git a/Telegram/SourceFiles/base/parse_helper.h b/Telegram/SourceFiles/base/parse_helper.h deleted file mode 100644 index ce96690b0..000000000 --- a/Telegram/SourceFiles/base/parse_helper.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { -namespace parse { - -// Strip all C-style comments. -QByteArray stripComments(const QByteArray &content); - -inline bool skipWhitespaces(const char *&from, const char *end) { - Assert(from <= end); - while (from != end && ( - (*from == ' ') || - (*from == '\n') || - (*from == '\t') || - (*from == '\r'))) { - ++from; - } - return (from != end); -} - -inline QLatin1String readName(const char *&from, const char *end) { - Assert(from <= end); - auto start = from; - while (from != end && ( - (*from >= 'a' && *from <= 'z') || - (*from >= 'A' && *from <= 'Z') || - (*from >= '0' && *from <= '9') || - (*from == '_'))) { - ++from; - } - return QLatin1String(start, from - start); -} - -} // namespace parse -} // namespace base diff --git a/Telegram/SourceFiles/base/qt_connection.h b/Telegram/SourceFiles/base/qt_connection.h deleted file mode 100644 index 3fd5610c9..000000000 --- a/Telegram/SourceFiles/base/qt_connection.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/algorithm.h" - -#include - -namespace base { - -class qt_connection final { -public: - qt_connection(QMetaObject::Connection data = {}) : _data(data) { - } - qt_connection(qt_connection &&other) : _data(base::take(other._data)) { - } - qt_connection &operator=(qt_connection &&other) { - reset(base::take(other._data)); - return *this; - } - ~qt_connection() { - disconnect(); - } - - void release() { - _data = QMetaObject::Connection(); - } - void reset(QMetaObject::Connection data = {}) { - disconnect(); - _data = data; - } - -private: - void disconnect() { - if (_data) { - QObject::disconnect(base::take(_data)); - } - } - - QMetaObject::Connection _data; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/qt_signal_producer.h b/Telegram/SourceFiles/base/qt_signal_producer.h deleted file mode 100644 index 29a12a016..000000000 --- a/Telegram/SourceFiles/base/qt_signal_producer.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/base_integration.h" - -namespace base { - -// This method allows to create an rpl::producer from a Qt object -// and a signal with none or one reported value. -// -// QtSignalProducer(qtWindow, &QWindow::activeChanged) | rpl::start_ -// -// This producer values construct a custom event loop leave point. -// This means that all postponeCall's will be invoked right after -// the value processing by the current consumer finishes. -template -auto qt_signal_producer(Object *object, Signal signal); - -namespace details { - -template -struct qt_signal_argument; - -template -struct qt_signal_argument { - using type = Value; -}; - -template -struct qt_signal_argument { - using type = void; -}; - -} // namespace details - -template -auto qt_signal_producer(Object *object, Signal signal) { - using Value = typename details::qt_signal_argument::type; - static constexpr auto NoArgument = std::is_same_v; - using Produced = std::conditional_t< - NoArgument, - rpl::empty_value, - std::remove_const_t>>; - const auto guarded = QPointer(object); - return rpl::make_producer([=](auto consumer) { - if (!guarded) { - return rpl::lifetime(); - } - const auto connect = [&](auto &&handler) { - const auto listener = new QObject(guarded.data()); - QObject::connect( - guarded, - signal, - listener, - std::forward(handler)); - const auto weak = QPointer(listener); - return rpl::lifetime([=] { - if (weak) { - delete weak; - } - }); - }; - auto put = [=](const Produced &value) { - EnterFromEventLoop([&] { - consumer.put_next_copy(value); - }); - }; - if constexpr (NoArgument) { - return connect([put = std::move(put)] { put({}); }); - } else { - return connect(std::move(put)); - } - }); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/qthelp_regex.h b/Telegram/SourceFiles/base/qthelp_regex.h deleted file mode 100644 index 09441a74e..000000000 --- a/Telegram/SourceFiles/base/qthelp_regex.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/flags.h" - -namespace qthelp { - -class RegularExpressionMatch { -public: - RegularExpressionMatch(const QRegularExpressionMatch &other) = delete; - RegularExpressionMatch(const RegularExpressionMatch &other) = delete; - RegularExpressionMatch(QRegularExpressionMatch &&match) : data_(std::move(match)) { - } - RegularExpressionMatch(RegularExpressionMatch &&other) : data_(std::move(other.data_)) { - } - RegularExpressionMatch &operator=(const QRegularExpressionMatch &match) = delete; - RegularExpressionMatch &operator=(const RegularExpressionMatch &other) = delete; - RegularExpressionMatch &operator=(QRegularExpressionMatch &&match) { - data_ = std::move(match); - return *this; - } - RegularExpressionMatch &operator=(RegularExpressionMatch &&other) { - data_ = std::move(other.data_); - return *this; - } - QRegularExpressionMatch *operator->() { - return &data_; - } - const QRegularExpressionMatch *operator->() const { - return &data_; - } - bool valid() const { - return data_.hasMatch(); - } - explicit operator bool() const { - return valid(); - } - -private: - QRegularExpressionMatch data_; - -}; - -enum class RegExOption { - None = QRegularExpression::NoPatternOption, - CaseInsensitive = QRegularExpression::CaseInsensitiveOption, - DotMatchesEverything = QRegularExpression::DotMatchesEverythingOption, - Multiline = QRegularExpression::MultilineOption, - ExtendedSyntax = QRegularExpression::ExtendedPatternSyntaxOption, - InvertedGreediness = QRegularExpression::InvertedGreedinessOption, - DontCapture = QRegularExpression::DontCaptureOption, - UseUnicodeProperties = QRegularExpression::UseUnicodePropertiesOption, -#ifndef OS_MAC_OLD - OptimizeOnFirstUsage = QRegularExpression::OptimizeOnFirstUsageOption, - DontAutomaticallyOptimize = QRegularExpression::DontAutomaticallyOptimizeOption, -#endif // OS_MAC_OLD -}; -using RegExOptions = base::flags; -inline constexpr auto is_flag_type(RegExOption) { return true; }; - -inline RegularExpressionMatch regex_match(const QString &string, const QString &subject, RegExOptions options = 0) { - auto qtOptions = QRegularExpression::PatternOptions(static_cast(options)); - return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subject)); -} - -inline RegularExpressionMatch regex_match(const QString &string, const QStringRef &subjectRef, RegExOptions options = 0) { - auto qtOptions = QRegularExpression::PatternOptions(static_cast(options)); -#ifndef OS_MAC_OLD - return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subjectRef)); -#else // OS_MAC_OLD - return RegularExpressionMatch(QRegularExpression(string, qtOptions).match(subjectRef.toString())); -#endif // OS_MAC_OLD -} - -} // namespace qthelp diff --git a/Telegram/SourceFiles/base/qthelp_url.cpp b/Telegram/SourceFiles/base/qthelp_url.cpp deleted file mode 100644 index 0cdc486f8..000000000 --- a/Telegram/SourceFiles/base/qthelp_url.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/qthelp_url.h" - -namespace qthelp { -namespace { - -QRegularExpression CreateRegExp(const QString &expression) { - auto result = QRegularExpression( - expression, - QRegularExpression::UseUnicodePropertiesOption); -#ifndef OS_MAC_OLD - result.optimize(); -#endif // OS_MAC_OLD - return result; -} - -QString ExpressionDomain() { - // Matches any domain name, containing at least one '.', including "file.txt". - return QString::fromUtf8("(? url_parse_params( - const QString ¶ms, - UrlParamNameTransform transform) { - auto result = QMap(); - - const auto transformParamName = [transform](const QString &name) { - if (transform == UrlParamNameTransform::ToLower) { - return name.toLower(); - } - return name; - }; - for (const auto ¶m : params.split('&')) { - // Skip params without a name (starting with '='). - if (auto separatorPosition = param.indexOf('=')) { - const auto paramName = transformParamName( - (separatorPosition > 0) - ? param.mid(0, separatorPosition) - : param); - const auto paramValue = (separatorPosition > 0) - ? url_decode(param.mid(separatorPosition + 1)) - : QString(); - if (!result.contains(paramName)) { - result.insert(paramName, paramValue); - } - } - } - return result; -} - -bool is_ipv6(const QString &ip) { - //static const auto regexp = QRegularExpression("^[a-fA-F0-9:]+$"); - //return regexp.match(ip).hasMatch(); - return ip.indexOf('.') < 0 && ip.indexOf(':') >= 0; -} - -QString url_append_query_or_hash(const QString &url, const QString &add) { - const auto query = url.lastIndexOf('?'); - if (query < 0) { - return url + '?' + add; - } - const auto hash = url.lastIndexOf('#'); - return url - + (query >= 0 && query > url.lastIndexOf('#') ? '&' : '?') - + add; -} - -QString validate_url(const QString &value) { - const auto trimmed = value.trimmed(); - if (trimmed.isEmpty()) { - return QString(); - } - const auto match = RegExpDomainExplicit().match(trimmed); - if (!match.hasMatch()) { - const auto domain = RegExpDomain().match(trimmed); - if (!domain.hasMatch() || domain.capturedStart() != 0) { - return QString(); - } - return qstr("http://") + trimmed; - } else if (match.capturedStart() != 0) { - return QString(); - } - const auto protocolMatch = RegExpProtocol().match(trimmed); - Assert(protocolMatch.hasMatch()); - return IsGoodProtocol(protocolMatch.captured(1)) ? trimmed : QString(); -} - -} // namespace qthelp diff --git a/Telegram/SourceFiles/base/qthelp_url.h b/Telegram/SourceFiles/base/qthelp_url.h deleted file mode 100644 index fd8e460be..000000000 --- a/Telegram/SourceFiles/base/qthelp_url.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include - -namespace qthelp { - -const QRegularExpression &RegExpDomain(); -const QRegularExpression &RegExpDomainExplicit(); -QRegularExpression RegExpProtocol(); - -inline QString url_encode(const QString &part) { - return QString::fromLatin1(QUrl::toPercentEncoding(part)); -} - -inline QString url_decode(const QString &encoded) { - return QUrl::fromPercentEncoding(encoded.toUtf8()); -} - -enum class UrlParamNameTransform { - NoTransform, - ToLower, -}; -// Parses a string like "p1=v1&p2=v2&..&pn=vn" to a map. -QMap url_parse_params( - const QString ¶ms, - UrlParamNameTransform transform = UrlParamNameTransform::NoTransform); - -QString url_append_query_or_hash(const QString &url, const QString &add); - -bool is_ipv6(const QString &ip); - -QString validate_url(const QString &value); - -} // namespace qthelp diff --git a/Telegram/SourceFiles/base/runtime_composer.cpp b/Telegram/SourceFiles/base/runtime_composer.cpp deleted file mode 100644 index eec3cdca3..000000000 --- a/Telegram/SourceFiles/base/runtime_composer.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/runtime_composer.h" - -struct RuntimeComposerMetadatasMap { - std::map> data; - QMutex mutex; -}; - -const RuntimeComposerMetadata *GetRuntimeComposerMetadata(uint64 mask) { - static RuntimeComposerMetadatasMap RuntimeComposerMetadatas; - - QMutexLocker lock(&RuntimeComposerMetadatas.mutex); - auto i = RuntimeComposerMetadatas.data.find(mask); - if (i == end(RuntimeComposerMetadatas.data)) { - i = RuntimeComposerMetadatas.data.emplace( - mask, - std::make_unique(mask)).first; - } - return i->second.get(); -} - -const RuntimeComposerMetadata *RuntimeComposerBase::ZeroRuntimeComposerMetadata = GetRuntimeComposerMetadata(0); - -RuntimeComponentWrapStruct RuntimeComponentWraps[64]; - -QAtomicInt RuntimeComponentIndexLast; diff --git a/Telegram/SourceFiles/base/runtime_composer.h b/Telegram/SourceFiles/base/runtime_composer.h deleted file mode 100644 index 461f3888e..000000000 --- a/Telegram/SourceFiles/base/runtime_composer.h +++ /dev/null @@ -1,279 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -template -class RuntimeComposer; - -class RuntimeComposerBase; -typedef void(*RuntimeComponentConstruct)(void *location, RuntimeComposerBase *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 { - using RuntimeComponentBase = Base; - - RuntimeComponent() { - // While there is no std::aligned_alloc(). - static_assert(alignof(Type) <= alignof(std::max_align_t), "Components should align to std::max_align_t!"); - } - 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 MyIndex(0); - if (auto index = MyIndex.loadAcquire()) { - return index - 1; - } - while (true) { - auto last = RuntimeComponentIndexLast.loadAcquire(); - if (RuntimeComponentIndexLast.testAndSetOrdered(last, last + 1)) { - Assert(last < 64); - if (MyIndex.testAndSetOrdered(0, last + 1)) { - RuntimeComponentWraps[last] = RuntimeComponentWrapStruct( - sizeof(Type), - alignof(Type), - Type::RuntimeComponentConstruct, - Type::RuntimeComponentDestruct, - Type::RuntimeComponentMove); - } - break; - } - } - return MyIndex.loadAcquire() - 1; - } - static uint64 Bit() { - return (1ULL << Index()); - } - -protected: - static void RuntimeComponentConstruct(void *location, RuntimeComposerBase *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) : _mask(mask) { - for (int i = 0; i != 64; ++i) { - auto componentBit = (1ULL << i); - if (_mask & componentBit) { - auto componentSize = RuntimeComponentWraps[i].Size; - if (componentSize) { - auto componentAlign = RuntimeComponentWraps[i].Align; - if (auto badAlign = (size % componentAlign)) { - size += (componentAlign - badAlign); - } - offsets[i] = size; - size += componentSize; - accumulate_max(align, componentAlign); - } - } else if (_mask < componentBit) { - last = i; - break; - } - } - } - - // Meta pointer in the start. - std::size_t size = sizeof(const RuntimeComposerMetadata*); - std::size_t align = alignof(const RuntimeComposerMetadata*); - std::size_t offsets[64] = { 0 }; - int last = 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 RuntimeComposerBase { -public: - RuntimeComposerBase(uint64 mask = 0) : _data(zerodata()) { - if (mask) { - auto meta = GetRuntimeComposerMetadata(mask); - - auto data = operator new(meta->size); - Assert(data != nullptr); - - _data = data; - _meta() = meta; - for (int i = 0; i < meta->last; ++i) { - auto offset = meta->offsets[i]; - if (offset >= sizeof(_meta())) { - try { - auto constructAt = _dataptrunsafe(offset); - auto space = RuntimeComponentWraps[i].Size; - auto alignedAt = constructAt; - std::align(RuntimeComponentWraps[i].Align, space, alignedAt, space); - Assert(alignedAt == constructAt); - RuntimeComponentWraps[i].Construct(constructAt, this); - } catch (...) { - while (i > 0) { - --i; - offset = meta->offsets[--i]; - if (offset >= sizeof(_meta())) { - RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset)); - } - } - throw; - } - } - } - } - } - RuntimeComposerBase(const RuntimeComposerBase &other) = delete; - RuntimeComposerBase &operator=(const RuntimeComposerBase &other) = delete; - ~RuntimeComposerBase() { - if (_data != zerodata()) { - auto meta = _meta(); - for (int i = 0; i < meta->last; ++i) { - auto offset = meta->offsets[i]; - if (offset >= sizeof(_meta())) { - RuntimeComponentWraps[i].Destruct(_dataptrunsafe(offset)); - } - } - operator delete(_data); - } - } - -protected: - bool UpdateComponents(uint64 mask = 0) { - if (_meta()->equals(mask)) { - return false; - } - RuntimeComposerBase result(mask); - result.swap(*this); - if (_data != zerodata() && result._data != zerodata()) { - const auto meta = _meta(); - const auto wasmeta = result._meta(); - for (auto i = 0; i != meta->last; ++i) { - const auto offset = meta->offsets[i]; - const auto wasoffset = wasmeta->offsets[i]; - if (offset >= sizeof(_meta()) - && wasoffset >= sizeof(_meta())) { - RuntimeComponentWraps[i].Move( - _dataptrunsafe(offset), - result._dataptrunsafe(wasoffset)); - } - } - } - return true; - } - bool AddComponents(uint64 mask = 0) { - return UpdateComponents(_meta()->maskadd(mask)); - } - bool RemoveComponents(uint64 mask = 0) { - return UpdateComponents(_meta()->maskremove(mask)); - } - -private: - template - friend class RuntimeComposer; - - static const RuntimeComposerMetadata *ZeroRuntimeComposerMetadata; - static void *zerodata() { - return &ZeroRuntimeComposerMetadata; - } - - void *_dataptrunsafe(int skip) const { - return (char*)_data + skip; - } - void *_dataptr(int skip) const { - return (skip >= sizeof(_meta())) ? _dataptrunsafe(skip) : nullptr; - } - const RuntimeComposerMetadata *&_meta() const { - return *static_cast(_data); - } - void *_data = nullptr; - - void swap(RuntimeComposerBase &other) { - std::swap(_data, other._data); - } - -}; - -template -class RuntimeComposer : public RuntimeComposerBase { -public: - using RuntimeComposerBase::RuntimeComposerBase; - - template < - typename Type, - typename = std::enable_if_t>> - bool Has() const { - return (_meta()->offsets[Type::Index()] >= sizeof(_meta())); - } - - template < - typename Type, - typename = std::enable_if_t>> - Type *Get() { - return static_cast(_dataptr(_meta()->offsets[Type::Index()])); - } - template < - typename Type, - typename = std::enable_if_t>> - const Type *Get() const { - return static_cast(_dataptr(_meta()->offsets[Type::Index()])); - } - -}; diff --git a/Telegram/SourceFiles/base/tests_main.cpp b/Telegram/SourceFiles/base/tests_main.cpp deleted file mode 100644 index fbdcb56fe..000000000 --- a/Telegram/SourceFiles/base/tests_main.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#define CATCH_CONFIG_RUNNER -#include "catch.hpp" -#include "reporters/catch_reporter_compact.hpp" -#include - -int (*TestForkedMethod)()/* = nullptr*/; - -namespace base { -namespace assertion { - -// For Assert() / Expects() / Ensures() / Unexpected() to work. -void log(const char *message, const char *file, int line) { - std::cout << message << " (" << file << ":" << line << ")" << std::endl; -} - -} // namespace assertion -} // namespace base - -namespace Catch { - - struct MinimalReporter : CompactReporter { - MinimalReporter( ReporterConfig const& _config ) - : CompactReporter( _config ) - {} - - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - } - - private: - // Colour, message variants: - // - white: No tests ran. - // - red: Failed [both/all] N test cases, failed [both/all] M assertions. - // - white: Passed [both/all] N test cases (no assertions). - // - red: Failed N tests cases, failed M assertions. - // - green: Passed [both/all] N tests cases with M assertions. - - std::string bothOrAll( std::size_t count ) const { - return count == 1 ? std::string() : count == 2 ? "both " : "all " ; - } - - void printTotals( const Totals& totals ) const { - if( totals.testCases.total() == 0 ) { - } - else if( totals.testCases.failed == totals.testCases.total() ) { - Colour colour( Colour::ResultError ); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() ? - bothOrAll( totals.assertions.failed ) : std::string(); - stream << - "Failed " << bothOrAll( totals.testCases.failed ) - << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << qualify_assertions_failed << - pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else if( totals.assertions.total() == 0 ) { - stream << - "Passed " << bothOrAll( totals.testCases.total() ) - << pluralise( totals.testCases.total(), "test case" ) - << " (no assertions)."; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - stream << - "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else { - } - } - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "minimal", MinimalReporter ) - -} // end namespace Catch - -int main(int argc, const char *argv[]) { - auto touchFile = QString(); - for (auto i = 0; i != argc; ++i) { - if (argv[i] == QString("--touch") && i + 1 != argc) { - touchFile = QFile::decodeName(argv[++i]); - } else if (argv[i] == QString("--forked") && TestForkedMethod) { - return TestForkedMethod(); - } - } - const char *catch_argv[] = { - argv[0], - touchFile.isEmpty() ? "-b" : "-r", - touchFile.isEmpty() ? "-b" : "minimal" }; - constexpr auto catch_argc = sizeof(catch_argv) / sizeof(catch_argv[0]); - auto result = Catch::Session().run(catch_argc, catch_argv); - if (result == 0 && !touchFile.isEmpty()) { - QFile(touchFile).open(QIODevice::WriteOnly); - } - return (result < 0xff ? result : 0xff); -} - diff --git a/Telegram/SourceFiles/base/thread_safe_wrap.h b/Telegram/SourceFiles/base/thread_safe_wrap.h deleted file mode 100644 index 6d97151c7..000000000 --- a/Telegram/SourceFiles/base/thread_safe_wrap.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -class thread_safe_wrap { -public: - template - thread_safe_wrap(Args &&...args) : _value(std::forward(args)...) { - } - - template - auto with(Callback &&callback) { - QMutexLocker lock(&_mutex); - return callback(_value); - } - - template - auto with(Callback &&callback) const { - QMutexLocker lock(&_mutex); - return callback(_value); - } - -private: - T _value; - QMutex _mutex; - -}; - -template typename Container = std::deque> -class thread_safe_queue { -public: - template - void emplace(Args &&...args) { - _wrap.with([&](Container &value) { - value.emplace_back(std::forward(args)...); - }); - } - - Container take() { - return _wrap.with([&](Container &value) { - return std::exchange(value, Container()); - }); - } - -private: - thread_safe_wrap> _wrap; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/timer.cpp b/Telegram/SourceFiles/base/timer.cpp deleted file mode 100644 index 00204ad43..000000000 --- a/Telegram/SourceFiles/base/timer.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/timer.h" - -#include - -namespace base { -namespace { - -QObject *TimersAdjuster() { - static QObject adjuster; - return &adjuster; -} - -} // namespace - -Timer::Timer( - not_null thread, - Fn callback) -: Timer(std::move(callback)) { - moveToThread(thread); -} - -Timer::Timer(Fn callback) -: QObject(nullptr) -, _callback(std::move(callback)) -, _type(Qt::PreciseTimer) -, _adjusted(false) { - setRepeat(Repeat::Interval); - connect( - TimersAdjuster(), - &QObject::destroyed, - this, - [this] { adjust(); }, - Qt::QueuedConnection); -} - -void Timer::start(crl::time timeout, Qt::TimerType type, Repeat repeat) { - cancel(); - - _type = type; - setRepeat(repeat); - _adjusted = false; - setTimeout(timeout); - _timerId = startTimer(_timeout, _type); - if (_timerId) { - _next = crl::now() + _timeout; - } else { - _next = 0; - } -} - -void Timer::cancel() { - if (isActive()) { - killTimer(base::take(_timerId)); - } -} - -crl::time Timer::remainingTime() const { - if (!isActive()) { - return -1; - } - const auto now = crl::now(); - return (_next > now) ? (_next - now) : crl::time(0); -} - -void Timer::Adjust() { - QObject emitter; - connect( - &emitter, - &QObject::destroyed, - TimersAdjuster(), - &QObject::destroyed); -} - -void Timer::adjust() { - auto remaining = remainingTime(); - if (remaining >= 0) { - cancel(); - _timerId = startTimer(remaining, _type); - _adjusted = true; - } -} - -void Timer::setTimeout(crl::time timeout) { - Expects(timeout >= 0 && timeout <= std::numeric_limits::max()); - - _timeout = static_cast(timeout); -} - -int Timer::timeout() const { - return _timeout; -} - -void Timer::timerEvent(QTimerEvent *e) { - if (repeat() == Repeat::Interval) { - if (_adjusted) { - start(_timeout, _type, repeat()); - } else { - _next = crl::now() + _timeout; - } - } else { - cancel(); - } - - if (const auto onstack = _callback) { - onstack(); - } -} - -int DelayedCallTimer::call( - crl::time timeout, - FnMut callback, - Qt::TimerType type) { - Expects(timeout >= 0); - - if (!callback) { - return 0; - } - auto timerId = startTimer(static_cast(timeout), type); - if (timerId) { - _callbacks.emplace(timerId, std::move(callback)); - } - return timerId; -} - -void DelayedCallTimer::cancel(int callId) { - if (callId) { - killTimer(callId); - _callbacks.remove(callId); - } -} - -void DelayedCallTimer::timerEvent(QTimerEvent *e) { - auto timerId = e->timerId(); - killTimer(timerId); - - auto it = _callbacks.find(timerId); - if (it != _callbacks.end()) { - auto callback = std::move(it->second); - _callbacks.erase(it); - - callback(); - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/timer.h b/Telegram/SourceFiles/base/timer.h deleted file mode 100644 index 8ed2b3bb3..000000000 --- a/Telegram/SourceFiles/base/timer.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "base/flat_map.h" - -#include - -namespace base { - -class Timer final : private QObject { -public: - explicit Timer( - not_null thread, - Fn callback = nullptr); - explicit Timer(Fn callback = nullptr); - - static Qt::TimerType DefaultType(crl::time timeout) { - constexpr auto kThreshold = crl::time(1000); - return (timeout > kThreshold) ? Qt::CoarseTimer : Qt::PreciseTimer; - } - - void setCallback(Fn callback) { - _callback = std::move(callback); - } - - void callOnce(crl::time timeout) { - callOnce(timeout, DefaultType(timeout)); - } - - void callEach(crl::time timeout) { - callEach(timeout, DefaultType(timeout)); - } - - void callOnce(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::SingleShot); - } - - void callEach(crl::time timeout, Qt::TimerType type) { - start(timeout, type, Repeat::Interval); - } - - bool isActive() const { - return (_timerId != 0); - } - - void cancel(); - crl::time remainingTime() const; - - static void Adjust(); - -protected: - void timerEvent(QTimerEvent *e) override; - -private: - enum class Repeat : unsigned { - Interval = 0, - SingleShot = 1, - }; - void start(crl::time timeout, Qt::TimerType type, Repeat repeat); - void adjust(); - - void setTimeout(crl::time timeout); - int timeout() const; - - void setRepeat(Repeat repeat) { - _repeat = static_cast(repeat); - } - Repeat repeat() const { - return static_cast(_repeat); - } - - Fn _callback; - crl::time _next = 0; - int _timeout = 0; - int _timerId = 0; - - Qt::TimerType _type : 2; - bool _adjusted : 1; - unsigned _repeat : 1; - -}; - -class DelayedCallTimer final : private QObject { -public: - int call(crl::time timeout, FnMut callback) { - return call( - timeout, - std::move(callback), - Timer::DefaultType(timeout)); - } - - int call( - crl::time timeout, - FnMut callback, - Qt::TimerType type); - void cancel(int callId); - -protected: - void timerEvent(QTimerEvent *e) override; - -private: - base::flat_map> _callbacks; - -}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/type_traits.h b/Telegram/SourceFiles/base/type_traits.h deleted file mode 100644 index f322d4992..000000000 --- a/Telegram/SourceFiles/base/type_traits.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { - -template -struct custom_is_fast_copy_type : public std::false_type { -}; -// To make your own type a fast copy type just write: -// template <> -// struct base::custom_is_fast_copy_type : public std::true_type { -// }; - -namespace internal { - -template -struct type_list_contains; - -template -struct type_list_contains : public std::false_type { -}; - -template -struct type_list_contains : public std::integral_constant::value || type_list_contains::value> { -}; - -template -using is_std_unsigned_int = type_list_contains; - -template -using is_std_signed_int = type_list_contains; - -template -using is_std_integral = std::integral_constant::value || is_std_signed_int::value || type_list_contains::value>; - -template -using is_std_float = type_list_contains; - -template -using is_std_arith = std::integral_constant::value || is_std_float::value>; - -template -using is_std_fundamental = std::integral_constant::value || std::is_same::value>; - -template -struct is_pointer : public std::false_type { -}; - -template -struct is_pointer : public std::true_type { -}; - -template -struct is_member_pointer : public std::false_type { -}; - -template -struct is_member_pointer : public std::true_type { -}; - -template -using is_fast_copy_type = std::integral_constant::value || is_pointer::value || is_member_pointer::value || custom_is_fast_copy_type::value>; - -template -struct add_const_reference { - using type = const T &; -}; - -template <> -struct add_const_reference { - using type = void; -}; - -template -using add_const_reference_t = typename add_const_reference::type; - -template -struct remove_pointer { - using type = T; -}; - -template -struct remove_pointer { - using type = T; -}; - -template -using remove_pointer_t = typename remove_pointer::type; - -} // namespace internal - -template -struct type_traits { - using is_std_unsigned_int = internal::is_std_unsigned_int; - using is_std_signed_int = internal::is_std_signed_int; - using is_std_integral = internal::is_std_integral; - using is_std_float = internal::is_std_float; - using is_std_arith = internal::is_std_arith; - using is_std_fundamental = internal::is_std_fundamental; - using is_pointer = internal::is_pointer; - using is_member_pointer = internal::is_member_pointer; - using is_fast_copy_type = internal::is_fast_copy_type; - - using parameter_type = std::conditional_t>; - using pointed_type = internal::remove_pointer_t; -}; - -template -using parameter_type = typename type_traits::parameter_type; - -} // namespace base diff --git a/Telegram/SourceFiles/base/unique_any.h b/Telegram/SourceFiles/base/unique_any.h deleted file mode 100644 index c7ff4ea44..000000000 --- a/Telegram/SourceFiles/base/unique_any.h +++ /dev/null @@ -1,230 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { -namespace details { - -template -struct moveable_as_copyable_wrap { - moveable_as_copyable_wrap(Value &&other) - : value(std::move(other)) { - } - moveable_as_copyable_wrap &operator=(Value &&other) { - value = std::move(other); - return *this; - } - moveable_as_copyable_wrap(moveable_as_copyable_wrap &&other) - : value(std::move(other.value)) { - } - moveable_as_copyable_wrap( - const moveable_as_copyable_wrap &other) { - Unexpected("Attempt to copy-construct a move-only type."); - } - moveable_as_copyable_wrap &operator=( - moveable_as_copyable_wrap &&other) { - value = std::move(other.value); - return *this; - } - moveable_as_copyable_wrap &operator=( - const moveable_as_copyable_wrap &other) { - Unexpected("Attempt to copy-assign a move-only type."); - } - - Value value; - -}; - -template < - typename Value, - typename = std::enable_if_t< - std::is_move_constructible_v> - && !std::is_lvalue_reference_v>> -auto wrap_moveable_as_copyable(Value &&value) { - return moveable_as_copyable_wrap(std::move(value)); -} - -} // namespace details - -class unique_any; - -template -Value *any_cast(unique_any *value) noexcept; - -template -const Value *any_cast(const unique_any *value) noexcept; - -class unique_any final { -public: - // Construction and destruction [any.cons] - constexpr unique_any() noexcept { - } - - unique_any(const unique_any &other) = delete; - unique_any &operator=(const unique_any &other) = delete; - - unique_any(unique_any &&other) noexcept - : _impl(std::move(other._impl)) { - } - - unique_any &operator=(unique_any &&other) noexcept { - _impl = std::move(other._impl); - return *this; - } - - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any>>> - unique_any(Value &&other) - : unique_any( - std::forward(other), - std::is_copy_constructible>()) { - } - - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any>>> - unique_any &operator=(Value &&other) { - if constexpr (std::is_copy_constructible_v>) { - _impl = std::forward(other); - } else if constexpr (std::is_move_constructible_v> - && !std::is_lvalue_reference_v) { - _impl = details::wrap_moveable_as_copyable(std::move(other)); - } else { - static_assert( - false_t(Value{}), - "Bad value for base::unique_any."); - } - return *this; - } - - template < - typename Value, - typename ...Args, - typename = std::enable_if_t< - std::is_constructible_v, Args...> - && std::is_copy_constructible_v>>> - std::decay_t &emplace(Args &&...args) { - return _impl.emplace(std::forward(args)...); - } - - void reset() noexcept { - _impl.reset(); - } - - void swap(unique_any &other) noexcept { - _impl.swap(other._impl); - } - - bool has_value() const noexcept { - return _impl.has_value(); - } - - // Should check if it is a moveable_only wrap first. - //const std::type_info &type() const noexcept { - // return _impl.type(); - //} - -private: - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any> - && std::is_copy_constructible_v>>> - unique_any(Value &&other, std::true_type) - : _impl(std::forward(other)) { - } - - template < - typename Value, - typename = std::enable_if_t< - !std::is_same_v, unique_any> - && !std::is_copy_constructible_v> - && std::is_move_constructible_v> - && !std::is_lvalue_reference_v>> - unique_any(Value &&other, std::false_type) - : _impl(details::wrap_moveable_as_copyable(std::move(other))) { - } - - template < - typename Value, - typename ...Args> - friend unique_any make_any(Args &&...args); - - template - friend const Value *any_cast(const unique_any *value) noexcept; - - template - friend Value *any_cast(unique_any *value) noexcept; - - std::any _impl; - -}; - -inline void swap(unique_any &a, unique_any &b) noexcept { - a.swap(b); -} - -template < - typename Value, - typename ...Args> -inline auto make_any(Args &&...args) --> std::enable_if_t< - std::is_copy_constructible_v>, - unique_any> { - return std::make_any(std::forward(args)...); -} - -template < - typename Value, - typename ...Args> -inline auto make_any(Args &&...args) --> std::enable_if_t< - !std::is_copy_constructible_v> - && std::is_move_constructible_v>, - unique_any> { - return Value(std::forward(args)...); -} - -template -inline Value *any_cast(unique_any *value) noexcept { - if constexpr (std::is_copy_constructible_v) { - return std::any_cast(&value->_impl); - } else if constexpr (std::is_move_constructible_v) { - auto wrap = std::any_cast< - details::moveable_as_copyable_wrap - >(&value->_impl); - return wrap ? &wrap->value : nullptr; - } else { - static_assert( - false_t(Value{}), - "Bad type for base::any_cast."); - } -} - -template -inline const Value *any_cast(const unique_any *value) noexcept { - if constexpr (std::is_copy_constructible_v) { - return std::any_cast(&value->_impl); - } else if constexpr (std::is_move_constructible_v) { - auto wrap = std::any_cast< - details::moveable_as_copyable_wrap - >(&value->_impl); - return wrap ? &wrap->value : nullptr; - } else { - static_assert( - false_t(Value{}), - "Bad type for base::any_cast."); - } -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/unique_function.h b/Telegram/SourceFiles/base/unique_function.h deleted file mode 100644 index f1911be27..000000000 --- a/Telegram/SourceFiles/base/unique_function.h +++ /dev/null @@ -1,178 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -#ifndef Unexpected -#define Unexpected(message) std::abort() -#define UniqueFunctionUnexpected -#endif // Unexpected - -namespace base { -namespace details { - -template -class moveable_callable_wrap { -public: - static_assert( - std::is_move_constructible_v, - "Should be at least moveable."); - - moveable_callable_wrap(Callable &&other) - : _value(std::move(other)) { - } - moveable_callable_wrap &operator=(Callable &&other) { - _value = std::move(other); - return *this; - } - moveable_callable_wrap(moveable_callable_wrap &&other) - : _value(std::move(other._value)) { - } - moveable_callable_wrap( - const moveable_callable_wrap &other) - : _value(fail_construct()) { - } - moveable_callable_wrap &operator=( - moveable_callable_wrap &&other) { - _value = std::move(other._value); - return *this; - } - moveable_callable_wrap &operator=( - const moveable_callable_wrap &other) { - return fail_assign(); - } - - template - decltype(auto) operator()(Args &&...args) { - return _value(std::forward(args)...); - } - -private: - [[noreturn]] Callable fail_construct() { - Unexpected("Attempt to copy-construct a move-only type."); - } - [[noreturn]] moveable_callable_wrap &fail_assign() { - Unexpected("Attempt to copy-assign a move-only type."); - } - - Callable _value; - -}; - -} // namespace details - -template -class unique_function; - -template -class unique_function final { -public: - unique_function(std::nullptr_t = nullptr) noexcept { - } - unique_function(const unique_function &other) = delete; - unique_function &operator=(const unique_function &other) = delete; - - // Move construct / assign from the same type. - unique_function(unique_function &&other) - : _impl(std::move(other._impl)) { - } - unique_function &operator=(unique_function &&other) { - _impl = std::move(other._impl); - return *this; - } - - template < - typename Callable, - typename = std::enable_if_t< - std::is_convertible_v< - decltype(std::declval()( - std::declval()...)), - Return>>> - unique_function(Callable &&other) - : unique_function( - std::forward(other), - std::is_copy_constructible>{}) { - } - - template < - typename Callable, - typename = std::enable_if_t< - std::is_convertible_v< - decltype(std::declval()( - std::declval()...)), - Return>>> - unique_function &operator=(Callable &&other) { - using Decayed = std::decay_t; - if constexpr (std::is_copy_constructible_v) { - _impl = std::forward(other); - } else if constexpr (std::is_move_constructible_v) { - _impl = details::moveable_callable_wrap( - std::forward(other)); - } else { - static_assert(false_t(other), "Should be moveable."); - } - return *this; - } - - void swap(unique_function &other) { - _impl.swap(other._impl); - } - - Return operator()(Args ...args) { - return _impl(std::forward(args)...); - } - - explicit operator bool() const { - return _impl.operator bool(); - } - - friend inline bool operator==( - const unique_function &value, - std::nullptr_t) noexcept { - return value._impl == nullptr; - } - friend inline bool operator==( - std::nullptr_t, - const unique_function &value) noexcept { - return value._impl == nullptr; - } - friend inline bool operator!=( - const unique_function &value, - std::nullptr_t) noexcept { - return value._impl != nullptr; - } - friend inline bool operator!=( - std::nullptr_t, - const unique_function &value) noexcept { - return value._impl != nullptr; - } - -private: - template - unique_function(Callable &&other, std::true_type) - : _impl(std::forward(other)) { - } - - template - unique_function(Callable &&other, std::false_type) - : _impl(details::moveable_callable_wrap>( - std::forward(other))) { - } - - std::function _impl; - -}; - -} // namespace base - -#ifdef UniqueFunctionUnexpected -#undef UniqueFunctionUnexpected -#undef Unexpected -#endif // UniqueFunctionUnexpectedb - diff --git a/Telegram/SourceFiles/base/unique_qptr.h b/Telegram/SourceFiles/base/unique_qptr.h deleted file mode 100644 index 89bd2dc58..000000000 --- a/Telegram/SourceFiles/base/unique_qptr.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { - -template -class unique_qptr { -public: - unique_qptr() = default; - unique_qptr(std::nullptr_t) noexcept { - } - explicit unique_qptr(T *pointer) noexcept - : _object(pointer) { - } - - unique_qptr(const unique_qptr &other) = delete; - unique_qptr &operator=(const unique_qptr &other) = delete; - unique_qptr(unique_qptr &&other) noexcept - : _object(base::take(other._object)) { - } - unique_qptr &operator=(unique_qptr &&other) noexcept { - if (_object != other._object) { - destroy(); - _object = base::take(other._object); - } - return *this; - } - - template < - typename U, - typename = std::enable_if_t>> - unique_qptr(unique_qptr &&other) noexcept - : _object(base::take(other._object)) { - } - - template < - typename U, - typename = std::enable_if_t>> - unique_qptr &operator=(unique_qptr &&other) noexcept { - if (_object != other._object) { - destroy(); - _object = base::take(other._object); - } - return *this; - } - - unique_qptr &operator=(std::nullptr_t) noexcept { - destroy(); - return *this; - } - - template - explicit unique_qptr(std::in_place_t, Args &&...args) - : _object(new T(std::forward(args)...)) { - } - - template - T *emplace(Args &&...args) { - reset(new T(std::forward(args)...)); - return get(); - } - - void reset(T *value = nullptr) noexcept { - if (_object != value) { - destroy(); - _object = value; - } - } - - T *get() const noexcept { - return static_cast(_object.data()); - } - operator T*() const noexcept { - return get(); - } - - T *release() noexcept { - return static_cast(base::take(_object).data()); - } - - explicit operator bool() const noexcept { - return _object != nullptr; - } - - T *operator->() const noexcept { - return get(); - } - T &operator*() const noexcept { - return *get(); - } - - ~unique_qptr() noexcept { - destroy(); - } - -private: - void destroy() noexcept { - delete base::take(_object).data(); - } - - template - friend class unique_qptr; - - QPointer _object; - -}; - -template -inline unique_qptr make_unique_q(Args &&...args) { - return unique_qptr(std::in_place, std::forward(args)...); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/unixtime.cpp b/Telegram/SourceFiles/base/unixtime.cpp deleted file mode 100644 index d3185e190..000000000 --- a/Telegram/SourceFiles/base/unixtime.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "base/unixtime.h" - -#include -#include - -#ifdef Q_OS_WIN -#include -#elif defined Q_OS_MAC -#include -#else -#include -#endif - -namespace base { -namespace unixtime { -namespace { - -std::atomic ValueUpdated/* = false*/; -std::atomic ValueShift/* = 0*/; -std::atomic HttpValueValid/* = false*/; -std::atomic HttpValueShift/* = 0*/; - -class MsgIdManager { -public: - MsgIdManager(); - - void update(); - [[nodiscard]] uint64 next(); - -private: - void initialize(); - - QReadWriteLock _lock; - uint64 _startId = 0; - std::atomic _incrementedPart = 0; - uint64 _startCounter = 0; - uint64 _randomPart = 0; - float64 _multiplier = 0.; - -}; - -MsgIdManager GlobalMsgIdManager; - -[[nodiscard]] float64 GetMultiplier() { - // 0xFFFF0000 instead of 0x100000000 to make msgId grow slightly slower, - // than unixtime and we had time to reconfigure. - -#ifdef Q_OS_WIN - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); - return float64(0xFFFF0000L) / float64(li.QuadPart); -#elif defined Q_OS_MAC // Q_OS_WIN - mach_timebase_info_data_t tb = { 0, 0 }; - mach_timebase_info(&tb); - const auto frequency = (float64(tb.numer) / tb.denom) / 1000000.; - return frequency * (float64(0xFFFF0000L) / 1000.); -#else // Q_OS_MAC || Q_OS_WIN - return float64(0xFFFF0000L) / 1000000000.; -#endif // Q_OS_MAC || Q_OS_WIN -} - -[[nodiscard]] uint64 GetCounter() { -#ifdef Q_OS_WIN - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - return li.QuadPart; -#elif defined Q_OS_MAC // Q_OS_WIN - return mach_absolute_time(); -#else // Q_OS_MAC || Q_OS_WIN - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return 1000000000 * uint64(ts.tv_sec) + uint64(ts.tv_nsec); -#endif // Q_OS_MAC || Q_OS_WIN -} - -MsgIdManager::MsgIdManager() { - auto generator = std::mt19937(std::random_device()()); - auto distribution = std::uniform_int_distribution(); - _randomPart = distribution(generator); - _multiplier = GetMultiplier(); - initialize(); - - srand(uint32(_startCounter & 0xFFFFFFFFUL)); -} - -void MsgIdManager::update() { - QWriteLocker lock(&_lock); - initialize(); -} - -void MsgIdManager::initialize() { - _startCounter = GetCounter(); - _startId = ((uint64(uint32(now()))) << 32) | _randomPart; -} - -uint64 MsgIdManager::next() { - const auto counter = GetCounter(); - - QReadLocker lock(&_lock); - const auto delta = (counter - _startCounter); - const auto result = _startId + (uint64)floor(delta * _multiplier); - lock.unlock(); - - return (result & ~0x03L) + (_incrementedPart += 4); -} - -TimeId local() { - return (TimeId)time(nullptr); -} - -} // namespace - -TimeId now() { - return local() + ValueShift.load(); -} - -void update(TimeId now, bool force) { - if (force) { - ValueUpdated = true; - } else { - auto expected = false; - if (!ValueUpdated.compare_exchange_strong(expected, true)) { - return; - } - } - const auto shift = now + 1 - local(); - ValueShift = shift; - - HttpValueShift = 0; - HttpValueValid = false; - - GlobalMsgIdManager.update(); -} - -QDateTime parse(TimeId value) { - return (value > 0) - ? QDateTime::fromTime_t(value - ValueShift) - : QDateTime(); -} - -TimeId serialize(const QDateTime &date) { - return date.isNull() ? TimeId(0) : date.toTime_t() + ValueShift; -} - -bool http_valid() { - return HttpValueValid; -} - -TimeId http_now() { - return now() + HttpValueShift; -} - -void http_update(TimeId now) { - HttpValueShift = now - base::unixtime::now(); - HttpValueValid = true; -} - -void http_invalidate() { - HttpValueValid = false; -} - -uint64 mtproto_msg_id() { - return GlobalMsgIdManager.next(); -} - -} // namespace unixtime -} // namespace base diff --git a/Telegram/SourceFiles/base/unixtime.h b/Telegram/SourceFiles/base/unixtime.h deleted file mode 100644 index 9db64ed2a..000000000 --- a/Telegram/SourceFiles/base/unixtime.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "base/basic_types.h" - -class QDateTime; - -namespace base { -namespace unixtime { - -// All functions are thread-safe. - -[[nodiscard]] TimeId now(); -void update(TimeId now, bool force = false); - -[[nodiscard]] QDateTime parse(TimeId value); -[[nodiscard]] TimeId serialize(const QDateTime &date); - -[[nodiscard]] bool http_valid(); -[[nodiscard]] TimeId http_now(); -void http_update(TimeId now); -void http_invalidate(); - -[[nodiscard]] uint64 mtproto_msg_id(); - -} // namespace unixtime -} // namespace base diff --git a/Telegram/SourceFiles/base/value_ordering.h b/Telegram/SourceFiles/base/value_ordering.h deleted file mode 100644 index 941421bfa..000000000 --- a/Telegram/SourceFiles/base/value_ordering.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -namespace base { -namespace details { - -template < - typename Type, - typename Operator, - typename = decltype(Operator{}( - std::declval(), - std::declval()))> -char test_operator(const Type &, const Operator &); -int test_operator(...); - -template typename Operator> -struct has_operator - : std::bool_constant< - sizeof(test_operator( - std::declval(), - std::declval>() - )) == sizeof(char)> { -}; - -template < - typename Type, - template typename Operator> -constexpr bool has_operator_v - = has_operator::value; - -template -constexpr bool has_less_v = has_operator_v; - -template -constexpr bool has_greater_v = has_operator_v; - -template -constexpr bool has_less_equal_v = has_operator_v; - -template -constexpr bool has_greater_equal_v = has_operator_v; - -template -constexpr bool has_equal_to_v = has_operator_v; - -template -constexpr bool has_not_equal_to_v = has_operator_v; - -} // namespace details -} // namespace base - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator<(const ValueType &a, const ValueType &b) --> std::enable_if_t, bool> { - return value_ordering_helper(a) < value_ordering_helper(b); -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator>(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_greater_v - || base::details::has_less_v, - bool -> { - if constexpr (base::details::has_greater_v) { - return value_ordering_helper(a) > value_ordering_helper(b); - } else { - return value_ordering_helper(b) < value_ordering_helper(a); - } -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator<=(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_less_equal_v - || base::details::has_less_v, - bool -> { - if constexpr (base::details::has_less_equal_v) { - return value_ordering_helper(a) <= value_ordering_helper(b); - } else { - return !(value_ordering_helper(b) < value_ordering_helper(a)); - } -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator>=(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_greater_equal_v - || base::details::has_less_v, - bool -> { - if constexpr (base::details::has_greater_equal_v) { - return value_ordering_helper(a) >= value_ordering_helper(b); - } else { - return !(value_ordering_helper(a) < value_ordering_helper(b)); - } -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator==(const ValueType &a, const ValueType &b) --> std::enable_if_t, bool> { - return value_ordering_helper(a) == value_ordering_helper(b); -} - -template < - typename ValueType, - typename Helper = decltype( - value_ordering_helper(std::declval()))> -inline auto operator!=(const ValueType &a, const ValueType &b) --> std::enable_if_t< - base::details::has_not_equal_to_v - || base::details::has_equal_to_v, - bool -> { - if constexpr (base::details::has_not_equal_to_v) { - return value_ordering_helper(a) != value_ordering_helper(b); - } else { - return !(value_ordering_helper(a) == value_ordering_helper(b)); - } -} diff --git a/Telegram/SourceFiles/base/variant.h b/Telegram/SourceFiles/base/variant.h deleted file mode 100644 index e8539d4d2..000000000 --- a/Telegram/SourceFiles/base/variant.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -inline bool operator<(std::nullopt_t, std::nullopt_t) { - return false; -} -inline bool operator>(std::nullopt_t, std::nullopt_t) { - return false; -} -inline bool operator<=(std::nullopt_t, std::nullopt_t) { - return true; -} -inline bool operator>=(std::nullopt_t, std::nullopt_t) { - return true; -} -inline bool operator==(std::nullopt_t, std::nullopt_t) { - return true; -} -inline bool operator!=(std::nullopt_t, std::nullopt_t) { - return false; -} - -#include -#include -#include "base/match_method.h" -#include "base/assertion.h" - -// We use base::variant<> alias and base::get_if() helper while we don't have std::variant<>. -namespace base { - -template -using variant = mapbox::util::variant; - -template -inline T *get_if(variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -template -inline const T *get_if(const variant *v) { - return (v && v->template is()) ? &v->template get_unchecked() : nullptr; -} - -namespace type_list = rpl::details::type_list; - -template -struct normalized_variant { - using list = type_list::list; - using distinct = type_list::distinct_t; - using type = std::conditional_t< - type_list::size_v == 1, - type_list::get_t<0, distinct>, - type_list::extract_to_t>; -}; - -template -using normalized_variant_t - = typename normalized_variant::type; - -template -struct match_helper; - -template < - typename Type, - typename ...Types, - typename Variant, - typename ...Methods> -struct match_helper, Variant, Methods...> { - static decltype(auto) call(Variant &value, Methods &&...methods) { - if (const auto v = get_if(&value)) { - return match_method( - *v, - std::forward(methods)...); - } - return match_helper< - type_list::list, - Variant, - Methods...>::call( - value, - std::forward(methods)...); - } -}; - -template < - typename Type, - typename Variant, - typename ...Methods> -struct match_helper, Variant, Methods...> { - static decltype(auto) call(Variant &value, Methods &&...methods) { - if (const auto v = get_if(&value)) { - return match_method( - *v, - std::forward(methods)...); - } - Unexpected("Valueless variant in base::match()."); - } -}; - -template -inline decltype(auto) match( - variant &value, - Methods &&...methods) { - return match_helper< - type_list::list, - variant, - Methods...>::call(value, std::forward(methods)...); -} - -template -inline decltype(auto) match( - const variant &value, - Methods &&...methods) { - return match_helper< - type_list::list, - const variant, - Methods...>::call(value, std::forward(methods)...); -} - -} // namespace base diff --git a/Telegram/SourceFiles/base/virtual_method.h b/Telegram/SourceFiles/base/virtual_method.h deleted file mode 100644 index 9feda79c6..000000000 --- a/Telegram/SourceFiles/base/virtual_method.h +++ /dev/null @@ -1,704 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace base { - -template -class virtual_object; - -template -class virtual_method; - -template -class virtual_override; - -namespace virtual_methods { - -struct child_entry; -using is_parent_check = bool(*)(const child_entry &possible_parent); -struct child_entry { - is_parent_check check_is_parent; - int *table_index; -}; -using child_entries = std::vector; - -// Recursive method to find if some class is a child of some other class. -template -struct is_parent { - static inline bool check(const child_entry &possible_parent) { - // Generate a good error message if ConcreteObject is not a child of virtual_object<>. - using all_objects_must_derive_virtual_object = typename ConcreteObject::virtual_object_parent; - using ConcreteObjectParent = all_objects_must_derive_virtual_object; - return (possible_parent.check_is_parent == &is_parent::check) - || is_parent::check(possible_parent); - } -}; - -template <> -struct is_parent { - static inline bool check(const child_entry &possible_parent) { - return (possible_parent.check_is_parent == &is_parent::check); - } -}; - -// Just force the compiler not to optimize away the object that "enforce" points at. -inline void dont_optimize_away(void *enforce) { - static volatile void *result = nullptr; - if (result) { - result = enforce; - } -} - -template -struct dont_optimize_away_struct { -}; - -inline bool first_dispatch_fired(bool did_fire = false) { - static bool fired = false; - if (did_fire) { - fired = true; - } - return fired; -} - -template -class object_registrator { -public: - inline object_registrator() { - Assert(!first_dispatch_fired()); - Creator(child_entry { - &is_parent::check, - &_index, - }); - } - static inline int &Index() { - return _index; - } - -private: - static int _index; - -}; - -template -int object_registrator::_index = -1; - -class object_base { -protected: - virtual ~object_base() = default; - -}; - -template -struct multi_index_collector; -template -struct override_key_collector_helper; -template -struct table_fill_entry_helper; -template -struct table_count_size; - -} // namespace virtual_methods - -// This should be a base class for every child object in your hierarchy. -// It registers this child in the root virtual_objects classes list. -// Also it holds its own index in the classes list that is used for fast -// invoking of methods from the virtual tables in different virtual_methods. -template -class virtual_object : public ParentObject { -protected: - virtual ~virtual_object() { - virtual_methods::dont_optimize_away(&_virtual_object_registrator); - } - -private: - using virtual_object_parent = ParentObject; - - friend struct virtual_methods::is_parent; - template - friend struct virtual_methods::multi_index_collector; - template - friend struct virtual_methods::override_key_collector_helper; - template - friend class virtual_object; - template - friend class virtual_method; - - static inline void virtual_object_register_child(const virtual_methods::child_entry &entry) { - return ParentObject::virtual_object_register_child(entry); - } - - using virtual_object_registrator = virtual_methods::object_registrator; - static virtual_object_registrator _virtual_object_registrator; - using virtual_object_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct; - - static inline int &virtual_object_child_index_static() { - return virtual_object_registrator::Index(); - } - int &virtual_object_child_index() override { - return virtual_object_child_index_static(); - } - -}; - -template -typename virtual_object::virtual_object_registrator virtual_object::_virtual_object_registrator = {}; - -// This should be a base class for the root of the whole hierarchy. -// It holds the table of all child classes in a list. -// This list is used by virtual_methods to generate virtual table. -template -class virtual_object : public virtual_methods::object_base { -protected: - virtual ~virtual_object() { - virtual_methods::dont_optimize_away(&_virtual_object_registrator); - } - -private: - using virtual_object_parent = void; - - friend struct virtual_methods::is_parent; - template - friend struct virtual_methods::table_count_size; - template - friend struct virtual_methods::multi_index_collector; - template - friend struct virtual_methods::override_key_collector_helper; - template - friend struct virtual_methods::table_fill_entry_helper; - template - friend class virtual_object; - template - friend class virtual_method; - - static inline virtual_methods::child_entries &virtual_object_get_child_entries() { - static virtual_methods::child_entries entries; - return entries; - } - - // Registers a new child class. - // After that on the next call to virtual_method::virtual_method_prepare_table() will - // generate a new virtual table for that virtual method. - static inline void virtual_object_register_child(const virtual_methods::child_entry &entry) { - auto &entries = virtual_object_get_child_entries(); - for (auto i = entries.begin(), e = entries.end(); i != e; ++i) { - if (entry.check_is_parent(*i)) { - *entry.table_index = (i - entries.begin()); - i = entries.insert(i, entry); - for (++i, e = entries.end(); i != e; ++i) { - ++*(i->table_index); - } - return; - } - } - *entry.table_index = entries.size(); - entries.push_back(entry); - } - - using virtual_object_registrator = virtual_methods::object_registrator; - static virtual_object_registrator _virtual_object_registrator; - using virtual_object_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct; - - static inline int &virtual_object_child_index_static() { - return virtual_object_registrator::Index(); - } - virtual int &virtual_object_child_index() { - return virtual_object_child_index_static(); - } - -}; - -template -typename virtual_object::virtual_object_registrator virtual_object::_virtual_object_registrator = {}; - -namespace virtual_methods { - -template -struct is_virtual_argument : public std::integral_constant::is_pointer::value - ? std::is_base_of::pointed_type>::value - : false> { -}; - -template -class multi_int_wrap { -public: - inline multi_int_wrap(int *indices) : _indices(indices) { - } - inline multi_int_wrap subindex() const { - static_assert(N > 0, "Wrong multi_int_wrap created!"); - return multi_int_wrap(_indices + 1); - } - inline int ¤t() const { - return *_indices; - } - -private: - int *_indices; - -}; - -template -class multi_int_wrap<0, Instance> { -public: - inline multi_int_wrap(int *indices) { - } - inline int current() const { - return 1; - } - -}; - -template -using multi_index_wrap = multi_int_wrap; -template -using multi_size_wrap = multi_int_wrap; - -template -struct multi_index_collector { - static constexpr int N = sizeof...(ConcreteArgs) + 1; - static inline void call(multi_index_wrap indices, ConcreteArg arg, ConcreteArgs... args) { - indices.current() = computeIndex(is_virtual_argument(), arg); - multi_index_collector::call(indices.subindex(), args...); - } - - static inline int computeIndex(std::integral_constant, ConcreteArg arg) { - return 0; - } - static inline int computeIndex(std::integral_constant, ConcreteArg arg) { - return arg->virtual_object_child_index(); - } - -}; - -template <> -struct multi_index_collector<> { - static inline void call(multi_index_wrap<0> indices) { - } -}; - -template -class override_key; - -template -class multi_int { -public: - inline multi_int_wrap data_wrap() { - return multi_int_wrap(_indices); - } - - template - static inline multi_int collect(ConcreteArgs... args) { - multi_int result; - multi_index_collector::call(result.data_wrap(), args...); - return result; - } - - inline void reset() { - memset(_indices, 0, sizeof(_indices)); - } - - inline int value(int index) const { - return _indices[index]; - } - - inline void copy(multi_int_wrap other) { - memcpy(_indices, &other.current(), sizeof(_indices)); - } - -private: - int _indices[N] = { 0 }; - friend class override_key; - -}; - -template -using multi_index = multi_int; -template -using multi_size = multi_int; - -template -class table_data_wrap { -public: - inline table_data_wrap(Call *data, multi_size_wrap size) : _data(data), _size(size) { - } - inline table_data_wrap operator[](int index) const { - return table_data_wrap(_data + index * _size.subindex().current(), _size.subindex()); - } - inline Call &operator[](multi_index_wrap index) const { - return (*this)[index.current()][index.subindex()]; - } - inline int size() const { - return count_size(std::integral_constant()); - } - -private: - template - inline int count_size(std::integral_constant) const { - return _size.current() / _size.subindex().current(); - } - inline int count_size(std::integral_constant) const { - return _size.current(); - } - - Call *_data; - multi_size_wrap _size; - -}; - -template -class table_data_wrap { -public: - inline table_data_wrap(Call *data, multi_size_wrap<0> size) : _data(data) { - } - inline Call &operator[](multi_index_wrap<0> index) const { - return *_data; - } - -private: - Call *_data; - -}; - -template -class table_data_wrap; - -template -struct table_count_size { - static constexpr int N = sizeof...(Args) + 1; - static inline void call(multi_size_wrap index) { - auto subindex = index.subindex(); - table_count_size::call(subindex); - index.current() = count(is_virtual_argument()) * subindex.current(); - } - - static inline int count(std::integral_constant) { - return 1; - } - static inline int count(std::integral_constant) { - return base::type_traits::pointed_type::virtual_object_get_child_entries().size(); - } - -}; - -template <> -struct table_count_size<> { - static inline void call(multi_size_wrap<0> index) { - } -}; - -template -class table_data { -public: - inline table_data_wrap data_wrap() { - return table_data_wrap(_data.data(), _size.data_wrap()); - } - - inline Call &operator[](multi_index index) { - int flat_index = 0; - for (int i = 0; i != N - 1; ++i) { - flat_index += _size.value(i + 1) * index.value(i); - } - flat_index += index.value(N - 1); - return _data[flat_index]; - } - - template - inline bool changed() { - if (!_data.empty()) { - return false; - } - - multi_size size; - table_count_size::call(size.data_wrap()); - _size = size; - _data.resize(_size.value(0), nullptr); - return true; - } - -private: - std::vector _data; - multi_size _size; - -}; - -template -class table_data { -public: - inline table_data_wrap data_wrap() { - return table_data_wrap(&_call, multi_size_wrap<0>(nullptr)); - } - - inline Call &operator[](multi_index<0> index) { - return _call; - } - - inline bool changed() const { - return false; - } - -private: - Call _call = nullptr; - -}; - -template -struct table_fill_entry_helper; - -template -struct table_fill_entry_helper { - static constexpr int N = sizeof...(Args) + 1; - - static inline bool call(table_data_wrap table, multi_index_wrap index, Call &fill) { - auto start = index.current(); - for (auto i = start, count = table.size(); i != count; ++i) { - auto foundGoodType = good(is_virtual_argument(), start, index.current()); - if (foundGoodType) { - index.current() = i; - if (table_fill_entry_helper::call(table[i], index.subindex(), fill)) { - return true; - } - } - } - index.current() = start; - return false; - } - - static inline bool good(std::integral_constant, int start, int current) { - return (start == current); - } - static inline bool good(std::integral_constant, int start, int current) { - using BaseObject = typename base::type_traits::pointed_type; - auto &entries = BaseObject::virtual_object_get_child_entries(); - return (start == current) || entries[start].check_is_parent(entries[current]); - } - -}; - -template -struct table_fill_entry_helper { - static inline bool call(table_data_wrap table, multi_index_wrap<0> index, Call &fill) { - if (auto overrideMethod = table[index]) { - fill = overrideMethod; - return true; - } - return false; - } -}; - -template -struct table_fill_entry; - -template -struct table_fill_entry { - using Call = ReturnType(*)(BaseMethod*, Args...); - static inline void call(table_data_wrap table, multi_index_wrap index, Call &fill) { - table_fill_entry_helper::call(table, index, fill); - } -}; - -template -inline void fill_entry(table_data_wrap table, multi_index_wrap index, Call &fill) { - return virtual_methods::table_fill_entry::call(table, index, fill); -} - -template -struct override_key_collector_helper; - -template -struct override_key_collector_helper { - static inline void call(int **indices) { - setValue(is_virtual_argument(), indices); - override_key_collector_helper::call(indices); - } - - static inline void setValue(std::integral_constant, int **indices) { - indices[M] = nullptr; - } - static inline void setValue(std::integral_constant, int **indices) { - using ConcreteObject = typename base::type_traits::pointed_type; - using IsParentCheckStruct = is_parent; - using IsParentCheckPointer = decltype(&IsParentCheckStruct::check); - using override_key_collector_dont_optimize_away = dont_optimize_away_struct; - override_key_collector_dont_optimize_away dont_optimize_away_object; - (void)dont_optimize_away_object; - - // Check that is_parent<> can be instantiated. - // So every ConcreteObject is a valid child of virtual_object<>. - dont_optimize_away(reinterpret_cast(&IsParentCheckStruct::check)); - indices[M] = &ConcreteObject::virtual_object_child_index_static(); - } - -}; - -template -struct override_key_collector_helper { - static inline void call(int **indices) { - } -}; - -template -struct override_key_collector; - -template -struct override_key_collector { - static inline void call(int **indices) { - override_key_collector_helper<0, ConcreteArgs...>::call(indices); - } -}; - -template -class override_key { -public: - inline multi_index value() const { - multi_index result; - for (int i = 0; i != N; ++i) { - auto pointer = _indices[i]; - result._indices[i] = (pointer ? *pointer : 0); - } - return result; - } - - friend inline bool operator<(const override_key &k1, const override_key &k2) { - for (int i = 0; i != N; ++i) { - auto pointer1 = k1._indices[i], pointer2 = k2._indices[i]; - if (pointer1 < pointer2) { - return true; - } else if (pointer1 > pointer2) { - return false; - } - } - return false; - } - - template - inline void collect() { - override_key_collector::call(_indices); - } - -private: - int *_indices[N]; - -}; - -template -struct static_cast_helper; - -template -struct static_cast_helper { - static inline ReturnType call(BaseMethod *context, Args ...args) { - return ConcreteMethod::call(context, static_cast(args)...); - } -}; - -} // namespace virtual_methods - -// This is a base class for all your virtual methods. -// It dispatches a call to one of the registered virtual_overrides -// or calls the fallback method of the BaseMethod class. -template -class virtual_method { - static constexpr int N = sizeof...(Args); - using virtual_method_call = ReturnType(*)(BaseMethod *context, Args... args); - -public: - inline ReturnType call(Args... args) { - auto context = static_cast(this); - auto index = virtual_methods::multi_index::collect(args...); - auto &table = virtual_method_prepare_table(); - auto &entry = table[index]; - if (!entry) { - virtual_methods::fill_entry(table.data_wrap(), index.data_wrap(), entry); - if (!entry) { - entry = &virtual_method::virtual_method_base_instance; - } - } - return (*entry)(context, args...); - } - -private: - // This map of methods contains only the original registered overrides. - using virtual_method_override_key = virtual_methods::override_key; - using virtual_method_override_map = std::map; - static inline virtual_method_override_map &virtual_method_get_override_map() { - static virtual_method_override_map override_map; - return override_map; - } - - // This method generates and returns a virtual table which holds a method - // for any child in the hierarchy or nullptr if none of the virtual_overrides fit. - using virtual_method_table_data = virtual_methods::table_data; - static inline virtual_method_table_data &virtual_method_get_table_data() { - static virtual_method_table_data virtual_table; - return virtual_table; - } - - static inline virtual_method_table_data &virtual_method_prepare_table() { - auto &virtual_table = virtual_method_get_table_data(); - if (virtual_table.template changed()) { - virtual_methods::first_dispatch_fired(true); - - // The class hierarchy has changed - we need to generate the virtual table once again. - // All other handlers will be placed if they're called. - for (auto &i : virtual_method_get_override_map()) { - virtual_table[i.first.value()] = i.second; - } - } - return virtual_table; - } - - static ReturnType virtual_method_base_instance(BaseMethod *context, Args... args) { - return BaseMethod::default_call(context, args...); - } - - template - static ReturnType virtual_method_override_instance(BaseMethod *context, Args... args) { - return virtual_methods::static_cast_helper::call(context, args...); - } - - template - static inline void virtual_method_register_override() { - auto call = &virtual_method_override_instance; - - virtual_methods::override_key key; - key.template collect(); - - virtual_method_get_override_map()[key] = call; - } - - template - friend class virtual_override; - -}; - -template -class virtual_override { -protected: - virtual ~virtual_override() { - virtual_methods::dont_optimize_away(&_virtual_override_registrator); - } - -private: - class virtual_override_registrator { - public: - inline virtual_override_registrator() { - Assert(!virtual_methods::first_dispatch_fired()); - BaseMethod::template virtual_method_register_override(); - } - - }; - static virtual_override_registrator _virtual_override_registrator; - using virtual_override_dont_optimize_away_registrator = virtual_methods::dont_optimize_away_struct; - -}; - -template -typename virtual_override::virtual_override_registrator virtual_override::_virtual_override_registrator = {}; - -} // namespace base diff --git a/Telegram/SourceFiles/base/weak_ptr.h b/Telegram/SourceFiles/base/weak_ptr.h deleted file mode 100644 index d396501c7..000000000 --- a/Telegram/SourceFiles/base/weak_ptr.h +++ /dev/null @@ -1,325 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace base { - -class has_weak_ptr; - -namespace details { - -struct alive_tracker { - explicit alive_tracker(const has_weak_ptr *value) : value(value) { - } - - std::atomic counter = 1; - std::atomic value; -}; - -inline alive_tracker *check_and_increment(alive_tracker *tracker) noexcept { - if (tracker) { - ++tracker->counter; - } - return tracker; -} - -inline void decrement(alive_tracker *tracker) noexcept { - if (tracker->counter.fetch_sub(1) == 0) { - delete tracker; - } -} - -} // namespace details - -template -class weak_ptr; - -class has_weak_ptr { -public: - has_weak_ptr() = default; - has_weak_ptr(const has_weak_ptr &other) noexcept { - } - has_weak_ptr(has_weak_ptr &&other) noexcept { - } - has_weak_ptr &operator=(const has_weak_ptr &other) noexcept { - return *this; - } - has_weak_ptr &operator=(has_weak_ptr &&other) noexcept { - return *this; - } - - ~has_weak_ptr() { - if (const auto alive = _alive.load()) { - alive->value.store(nullptr); - details::decrement(alive); - } - } - - friend inline void invalidate_weak_ptrs(has_weak_ptr *object) { - if (auto alive = object->_alive.load()) { - if (object->_alive.compare_exchange_strong(alive, nullptr)) { - alive->value.store(nullptr); - details::decrement(alive); - } - } - } - -private: - template - friend class weak_ptr; - - details::alive_tracker *incrementAliveTracker() const { - auto current = _alive.load(); - if (!current) { - auto alive = std::make_unique(this); - if (_alive.compare_exchange_strong(current, alive.get())) { - return alive.release(); - } - } - ++current->counter; - return current; - } - - mutable std::atomic _alive = nullptr; - -}; - -template -class weak_ptr { -public: - weak_ptr() = default; - weak_ptr(T *value) - : _alive(value ? value->incrementAliveTracker() : nullptr) { - } - weak_ptr(const std::unique_ptr &value) - : weak_ptr(value.get()) { - } - weak_ptr(const std::shared_ptr &value) - : weak_ptr(value.get()) { - } - weak_ptr(const std::weak_ptr &value) - : weak_ptr(value.lock().get()) { - } - weak_ptr(const weak_ptr &other) noexcept - : _alive(details::check_and_increment(other._alive)) { - } - weak_ptr(weak_ptr &&other) noexcept - : _alive(std::exchange(other._alive, nullptr)) { - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr(const weak_ptr &other) noexcept - : _alive(details::check_and_increment(other._alive)) { - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr(weak_ptr &&other) noexcept - : _alive(std::exchange(other._alive, nullptr)) { - } - - weak_ptr &operator=(T *value) { - reset(value); - return *this; - } - weak_ptr &operator=(const std::unique_ptr &value) { - reset(value.get()); - return *this; - } - weak_ptr &operator=(const std::shared_ptr &value) { - reset(value.get()); - return *this; - } - weak_ptr &operator=(const std::weak_ptr &value) { - reset(value.lock().get()); - return *this; - } - weak_ptr &operator=(const weak_ptr &other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = details::check_and_increment(other._alive); - } - return *this; - } - weak_ptr &operator=(weak_ptr &&other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = std::exchange(other._alive, nullptr); - } - return *this; - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr &operator=(const weak_ptr &other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = details::check_and_increment(other._alive); - } - return *this; - } - template < - typename Other, - typename = std::enable_if_t< - std::is_base_of_v && !std::is_same_v>> - weak_ptr &operator=(weak_ptr &&other) noexcept { - if (_alive != other._alive) { - destroy(); - _alive = std::exchange(other._alive, nullptr); - } - return *this; - } - - ~weak_ptr() { - destroy(); - } - - T *get() const noexcept { - const auto strong = _alive ? _alive->value.load() : nullptr; - if constexpr (std::is_const_v) { - return static_cast(strong); - } else { - return const_cast(static_cast(strong)); - } - } - explicit operator bool() const noexcept { - return (_alive && _alive->value); - } - T &operator*() const noexcept { - return *get(); - } - T *operator->() const noexcept { - return get(); - } - - void reset(T *value = nullptr) { - if (get() != value) { - destroy(); - _alive = value ? value->incrementAliveTracker() : nullptr; - } - } - -private: - void destroy() noexcept { - if (_alive) { - details::decrement(_alive); - } - } - - details::alive_tracker *_alive = nullptr; - - template - friend class weak_ptr; - -}; - -template -inline bool operator==(const weak_ptr &pointer, std::nullptr_t) noexcept { - return (pointer.get() == nullptr); -} - -template -inline bool operator==(std::nullptr_t, const weak_ptr &pointer) noexcept { - return (pointer == nullptr); -} - -template -inline bool operator!=(const weak_ptr &pointer, std::nullptr_t) noexcept { - return !(pointer == nullptr); -} - -template -inline bool operator!=(std::nullptr_t, const weak_ptr &pointer) noexcept { - return !(pointer == nullptr); -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(T *value) { - return value; -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(const std::unique_ptr &value) { - return value; -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(const std::shared_ptr &value) { - return value; -} - -template < - typename T, - typename = std::enable_if_t>> -weak_ptr make_weak(const std::weak_ptr &value) { - return value; -} - -} // namespace base - -namespace crl { - -template -struct guard_traits; - -template -struct guard_traits, void> { - static base::weak_ptr create(const base::weak_ptr &value) { - return value; - } - static base::weak_ptr create(base::weak_ptr &&value) { - return std::move(value); - } - static bool check(const base::weak_ptr &guard) { - return guard.get() != nullptr; - } - -}; - -template -struct guard_traits< - T*, - std::enable_if_t< - std::is_base_of_v>>> { - static base::weak_ptr create(T *value) { - return value; - } - static bool check(const base::weak_ptr &guard) { - return guard.get() != nullptr; - } - -}; - -template -struct guard_traits< - gsl::not_null, - std::enable_if_t< - std::is_base_of_v>>> { - static base::weak_ptr create(gsl::not_null value) { - return value.get(); - } - static bool check(const base::weak_ptr &guard) { - return guard.get() != nullptr; - } - -}; - -} // namespace crl diff --git a/Telegram/SourceFiles/base/zlib_help.h b/Telegram/SourceFiles/base/zlib_help.h deleted file mode 100644 index 8c0147cdc..000000000 --- a/Telegram/SourceFiles/base/zlib_help.h +++ /dev/null @@ -1,410 +0,0 @@ -/* -WARNING! All changes made in this file will be lost! -Created from 'colors.palette' by 'codegen_style' - -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "zip.h" -#include "unzip.h" -#include "logs.h" - -#ifdef small -#undef small -#endif // small - -namespace zlib { -namespace internal { - -class InMemoryFile { -public: - InMemoryFile(const QByteArray &data = QByteArray()) : _data(data) { - } - - zlib_filefunc_def funcs() { - zlib_filefunc_def result; - result.opaque = this; - result.zopen_file = &InMemoryFile::Open; - result.zerror_file = &InMemoryFile::Error; - result.zread_file = &InMemoryFile::Read; - result.zwrite_file = &InMemoryFile::Write; - result.zclose_file = &InMemoryFile::Close; - result.zseek_file = &InMemoryFile::Seek; - result.ztell_file = &InMemoryFile::Tell; - return result; - } - - int error() const { - return _error; - } - - QByteArray result() const { - return _data; - } - -private: - voidpf open(const char *filename, int mode) { - if (mode & ZLIB_FILEFUNC_MODE_WRITE) { - if (mode & ZLIB_FILEFUNC_MODE_CREATE) { - _data.clear(); - } - _position = _data.size(); - _data.reserve(2 * 1024 * 1024); - } else if (mode & ZLIB_FILEFUNC_MODE_READ) { - _position = 0; - } - _error = 0; - return this; - } - - uLong read(voidpf stream, void* buf, uLong size) { - uLong toRead = 0; - if (!_error) { - if (_data.size() > int(_position)) { - toRead = qMin(size, uLong(_data.size() - _position)); - memcpy(buf, _data.constData() + _position, toRead); - _position += toRead; - } - if (toRead < size) { - _error = -1; - } - } - return toRead; - } - - uLong write(voidpf stream, const void* buf, uLong size) { - if (_data.size() < int(_position + size)) { - _data.resize(_position + size); - } - memcpy(_data.data() + _position, buf, size); - _position += size; - return size; - } - - int close(voidpf stream) { - auto result = _error; - _position = 0; - _error = 0; - return result; - } - - int error(voidpf stream) const { - return _error; - } - - long tell(voidpf stream) const { - return _position; - } - - long seek(voidpf stream, uLong offset, int origin) { - if (!_error) { - switch (origin) { - case ZLIB_FILEFUNC_SEEK_SET: _position = offset; break; - case ZLIB_FILEFUNC_SEEK_CUR: _position += offset; break; - case ZLIB_FILEFUNC_SEEK_END: _position = _data.size() + offset; break; - } - if (int(_position) > _data.size()) { - _error = -1; - } - } - return _error; - } - - static voidpf Open(voidpf opaque, const char* filename, int mode) { - return static_cast(opaque)->open(filename, mode); - } - - static uLong Read(voidpf opaque, voidpf stream, void* buf, uLong size) { - return static_cast(opaque)->read(stream, buf, size); - } - - static uLong Write(voidpf opaque, voidpf stream, const void* buf, uLong size) { - return static_cast(opaque)->write(stream, buf, size); - } - - static int Close(voidpf opaque, voidpf stream) { - return static_cast(opaque)->close(stream); - } - - static int Error(voidpf opaque, voidpf stream) { - return static_cast(opaque)->error(stream); - } - - static long Tell(voidpf opaque, voidpf stream) { - return static_cast(opaque)->tell(stream); - } - - static long Seek(voidpf opaque, voidpf stream, uLong offset, int origin) { - return static_cast(opaque)->seek(stream, offset, origin); - } - - uLong _position = 0; - int _error = 0; - QByteArray _data; - -}; - -} // namespace internal - -constexpr int kCaseSensitive = 1; -constexpr int kCaseInsensitive = 2; - -class FileToRead { -public: - FileToRead(const QByteArray &content) : _data(content) { - auto funcs = _data.funcs(); - if (!(_handle = unzOpen2(nullptr, &funcs))) { - _error = -1; - } - } - - int getGlobalInfo(unz_global_info *pglobal_info) { - if (error() == UNZ_OK) { - _error = _handle ? unzGetGlobalInfo(_handle, pglobal_info) : -1; - } - return _error; - } - - int locateFile(const char *szFileName, int iCaseSensitivity) { - if (error() == UNZ_OK) { - _error = _handle ? unzLocateFile(_handle, szFileName, iCaseSensitivity) : -1; - } - return error(); - } - - int goToFirstFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzGoToFirstFile(_handle) : -1; - } - return error(); - } - - int goToNextFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzGoToNextFile(_handle) : -1; - } - return error(); - } - - int getCurrentFileInfo( - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) { - if (error() == UNZ_OK) { - _error = _handle ? unzGetCurrentFileInfo( - _handle, - pfile_info, - szFileName, - fileNameBufferSize, - extraField, - extraFieldBufferSize, - szComment, - commentBufferSize - ) : -1; - } - return error(); - } - - QString getCurrentFileName() { - unz_file_info info = { 0 }; - constexpr auto kMaxName = 128; - char name[kMaxName + 1] = { 0 }; - const auto result = getCurrentFileInfo( - &info, - name, - kMaxName, - nullptr, - 0, - nullptr, - 0); - return (result == UNZ_OK) ? QString::fromUtf8(name) : QString(); - } - - int openCurrentFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzOpenCurrentFile(_handle) : -1; - } - return error(); - } - - int readCurrentFile(voidp buf, unsigned len) { - if (error() == UNZ_OK) { - auto result = _handle ? unzReadCurrentFile(_handle, buf, len) : -1; - if (result >= 0) { - return result; - } else { - _error = result; - } - } - return error(); - } - - int closeCurrentFile() { - if (error() == UNZ_OK) { - _error = _handle ? unzCloseCurrentFile(_handle) : -1; - } - return error(); - } - - QByteArray readCurrentFileContent(int fileSizeLimit) { - unz_file_info fileInfo = { 0 }; - if (getCurrentFileInfo(&fileInfo, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK) { - LOG(("Error: could not get current file info in a zip file.")); - return QByteArray(); - } - - auto size = fileInfo.uncompressed_size; - if (size > static_cast(fileSizeLimit)) { - if (_error == UNZ_OK) _error = -1; - LOG(("Error: current file is too large (should be less than %1, got %2) in a zip file.").arg(fileSizeLimit).arg(size)); - return QByteArray(); - } - if (openCurrentFile() != UNZ_OK) { - LOG(("Error: could not open current file in a zip file.")); - return QByteArray(); - } - - QByteArray result; - result.resize(size); - - auto couldRead = readCurrentFile(result.data(), size); - if (couldRead != static_cast(size)) { - LOG(("Error: could not read current file in a zip file, got %1.").arg(couldRead)); - return QByteArray(); - } - - if (closeCurrentFile() != UNZ_OK) { - LOG(("Error: could not close current file in a zip file.")); - return QByteArray(); - } - - return result; - } - - QByteArray readFileContent(const char *szFileName, int iCaseSensitivity, int fileSizeLimit) { - if (locateFile(szFileName, iCaseSensitivity) != UNZ_OK) { - LOG(("Error: could not locate '%1' in a zip file.").arg(szFileName)); - return QByteArray(); - } - return readCurrentFileContent(fileSizeLimit); - } - - void close() { - if (_handle && unzClose(_handle) != UNZ_OK && _error == UNZ_OK) { - _error = -1; - } - _handle = nullptr; - } - - int error() const { - if (auto dataError = _data.error()) { - return dataError; - } - return _error; - } - - void clearError() { - _error = UNZ_OK; - } - - ~FileToRead() { - close(); - } - -private: - internal::InMemoryFile _data; - unzFile _handle = nullptr; - int _error = 0; - -}; - -class FileToWrite { -public: - FileToWrite() { - auto funcs = _data.funcs(); - if (!(_handle = zipOpen2(nullptr, APPEND_STATUS_CREATE, nullptr, &funcs))) { - _error = -1; - } - } - - int openNewFile( - const char *filename, - const zip_fileinfo *zipfi, - const void *extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level - ) { - if (error() == ZIP_OK) { - _error = _handle ? zipOpenNewFileInZip( - _handle, - filename, - zipfi, - extrafield_local, - size_extrafield_local, - extrafield_global, - size_extrafield_global, - comment, - method, - level - ) : -1; - } - return error(); - } - - int writeInFile(const void* buf, unsigned len) { - if (error() == ZIP_OK) { - _error = _handle ? zipWriteInFileInZip(_handle, buf, len) : -1; - } - return error(); - } - - int closeFile() { - if (error() == ZIP_OK) { - _error = _handle ? zipCloseFileInZip(_handle) : -1; - } - return error(); - } - - void close() { - if (_handle && zipClose(_handle, nullptr) != ZIP_OK && _error == ZIP_OK) { - _error = -1; - } - _handle = nullptr; - } - - int error() const { - if (auto dataError = _data.error()) { - return dataError; - } - return _error; - } - - QByteArray result() const { - return _data.result(); - } - - ~FileToWrite() { - close(); - } - -private: - internal::InMemoryFile _data; - zipFile _handle = nullptr; - int _error = 0; - -}; - -} // namespace zlib diff --git a/Telegram/SourceFiles/boxes/about_box.cpp b/Telegram/SourceFiles/boxes/about_box.cpp index 04e58771e..cc887ef60 100644 --- a/Telegram/SourceFiles/boxes/about_box.cpp +++ b/Telegram/SourceFiles/boxes/about_box.cpp @@ -15,9 +15,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/text/text_utilities.h" #include "platform/platform_file_utilities.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "core/click_handler_types.h" #include "core/update_checker.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include @@ -108,8 +109,8 @@ void AboutBox::showVersionHistory() { auto url = qsl("https://tdesktop.com/"); if (Platform::IsWindows()) { url += qsl("win/%1.zip"); - } else if (Platform::IsMacOldBuild()) { - url += qsl("mac32/%1.zip"); + } else if (Platform::IsOSXBuild()) { + url += qsl("osx/%1.zip"); } else if (Platform::IsMac()) { url += qsl("mac/%1.zip"); } else if (Platform::IsLinux32Bit()) { diff --git a/Telegram/SourceFiles/boxes/about_box.h b/Telegram/SourceFiles/boxes/about_box.h index 4010000bb..3ec637de2 100644 --- a/Telegram/SourceFiles/boxes/about_box.h +++ b/Telegram/SourceFiles/boxes/about_box.h @@ -14,7 +14,7 @@ class LinkButton; class FlatLabel; } // namespace Ui -class AboutBox : public BoxContent { +class AboutBox : public Ui::BoxContent { public: AboutBox(QWidget*); diff --git a/Telegram/SourceFiles/boxes/abstract_box.cpp b/Telegram/SourceFiles/boxes/abstract_box.cpp index f4869e7d2..d9d7b7761 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.cpp +++ b/Telegram/SourceFiles/boxes/abstract_box.cpp @@ -7,606 +7,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/abstract_box.h" -#include "styles/style_boxes.h" -#include "styles/style_profile.h" -#include "storage/localstorage.h" -#include "lang/lang_keys.h" -#include "ui/effects/radial_animation.h" -#include "ui/widgets/buttons.h" -#include "ui/widgets/scroll_area.h" -#include "ui/widgets/labels.h" -#include "ui/widgets/shadow.h" -#include "ui/wrap/fade_wrap.h" -#include "ui/text/text_utilities.h" -#include "ui/painter.h" -#include "base/timer.h" #include "mainwidget.h" #include "mainwindow.h" #include "app.h" -struct AbstractBox::LoadingProgress { - LoadingProgress( - Fn &&callback, - const style::InfiniteRadialAnimation &st); - - Ui::InfiniteRadialAnimation animation; - base::Timer removeTimer; -}; - -AbstractBox::LoadingProgress::LoadingProgress( - Fn &&callback, - const style::InfiniteRadialAnimation &st) -: animation(std::move(callback), st) { -} - -void BoxContent::setTitle(rpl::producer title) { - getDelegate()->setTitle(std::move(title) | Ui::Text::ToWithEntities()); -} - -QPointer BoxContent::addButton( - rpl::producer text, - Fn clickCallback) { - return addButton( - std::move(text), - std::move(clickCallback), - st::defaultBoxButton); -} - -QPointer BoxContent::addLeftButton( - rpl::producer text, - Fn clickCallback) { - return getDelegate()->addLeftButton( - std::move(text), - std::move(clickCallback), - st::defaultBoxButton); -} - -void BoxContent::setInner(object_ptr inner) { - setInner(std::move(inner), st::boxLayerScroll); -} - -void BoxContent::setInner(object_ptr inner, const style::ScrollArea &st) { - if (inner) { - getDelegate()->setLayerType(true); - _scroll.create(this, st); - _scroll->setGeometryToLeft(0, _innerTopSkip, width(), 0); - _scroll->setOwnedWidget(std::move(inner)); - if (_topShadow) { - _topShadow->raise(); - _bottomShadow->raise(); - } else { - _topShadow.create(this); - _bottomShadow.create(this); - } - if (!_preparing) { - // We didn't set dimensions yet, this will be called from finishPrepare(); - finishScrollCreate(); - } - } else { - getDelegate()->setLayerType(false); - _scroll.destroyDelayed(); - _topShadow.destroyDelayed(); - _bottomShadow.destroyDelayed(); - } -} - -void BoxContent::finishPrepare() { - _preparing = false; - if (_scroll) { - finishScrollCreate(); - } - setInnerFocus(); -} - -void BoxContent::finishScrollCreate() { - Expects(_scroll != nullptr); - - if (!_scroll->isHidden()) { - _scroll->show(); - } - updateScrollAreaGeometry(); - connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll())); - connect(_scroll, SIGNAL(innerResized()), this, SLOT(onInnerResize())); -} - -void BoxContent::scrollToWidget(not_null widget) { - if (_scroll) { - _scroll->scrollToWidget(widget); - } -} - -void BoxContent::onScrollToY(int top, int bottom) { - if (_scroll) { - _scroll->scrollToY(top, bottom); - } -} - -void BoxContent::onDraggingScrollDelta(int delta) { - _draggingScrollDelta = _scroll ? delta : 0; - if (_draggingScrollDelta) { - if (!_draggingScrollTimer) { - _draggingScrollTimer.create(this); - _draggingScrollTimer->setSingleShot(false); - connect(_draggingScrollTimer, SIGNAL(timeout()), this, SLOT(onDraggingScrollTimer())); - } - _draggingScrollTimer->start(15); - } else { - _draggingScrollTimer.destroy(); - } -} - -void BoxContent::onDraggingScrollTimer() { - auto delta = (_draggingScrollDelta > 0) ? qMin(_draggingScrollDelta * 3 / 20 + 1, int32(Ui::kMaxScrollSpeed)) : qMax(_draggingScrollDelta * 3 / 20 - 1, -int32(Ui::kMaxScrollSpeed)); - _scroll->scrollToY(_scroll->scrollTop() + delta); -} - -void BoxContent::updateInnerVisibleTopBottom() { - if (auto widget = static_cast(_scroll ? _scroll->widget() : nullptr)) { - auto top = _scroll->scrollTop(); - widget->setVisibleTopBottom(top, top + _scroll->height()); - } -} - -void BoxContent::updateShadowsVisibility() { - if (!_scroll) return; - - auto top = _scroll->scrollTop(); - _topShadow->toggle( - (top > 0 || _innerTopSkip > 0), - anim::type::normal); - _bottomShadow->toggle( - (top < _scroll->scrollTopMax() || _innerBottomSkip > 0), - anim::type::normal); -} - -void BoxContent::onScroll() { - updateInnerVisibleTopBottom(); - updateShadowsVisibility(); -} - -void BoxContent::onInnerResize() { - updateInnerVisibleTopBottom(); - updateShadowsVisibility(); -} - -void BoxContent::setDimensionsToContent( - int newWidth, - not_null content) { - content->resizeToWidth(newWidth); - content->heightValue( - ) | rpl::start_with_next([=](int height) { - setDimensions(newWidth, height); - }, content->lifetime()); -} - -void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) { - if (_innerTopSkip != innerTopSkip) { - auto delta = innerTopSkip - _innerTopSkip; - _innerTopSkip = innerTopSkip; - if (_scroll && width() > 0) { - auto scrollTopWas = _scroll->scrollTop(); - updateScrollAreaGeometry(); - if (scrollBottomFixed) { - _scroll->scrollToY(scrollTopWas + delta); - } - } - } -} - -void BoxContent::setInnerBottomSkip(int innerBottomSkip) { - if (_innerBottomSkip != innerBottomSkip) { - auto delta = innerBottomSkip - _innerBottomSkip; - _innerBottomSkip = innerBottomSkip; - if (_scroll && width() > 0) { - updateScrollAreaGeometry(); - } - } -} - -void BoxContent::setInnerVisible(bool scrollAreaVisible) { - if (_scroll) { - _scroll->setVisible(scrollAreaVisible); - } -} - -QPixmap BoxContent::grabInnerCache() { - auto isTopShadowVisible = !_topShadow->isHidden(); - auto isBottomShadowVisible = !_bottomShadow->isHidden(); - if (isTopShadowVisible) _topShadow->setVisible(false); - if (isBottomShadowVisible) _bottomShadow->setVisible(false); - auto result = Ui::GrabWidget(this, _scroll->geometry()); - if (isTopShadowVisible) _topShadow->setVisible(true); - if (isBottomShadowVisible) _bottomShadow->setVisible(true); - return result; -} - -void BoxContent::resizeEvent(QResizeEvent *e) { - if (_scroll) { - updateScrollAreaGeometry(); - } -} - -void BoxContent::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape && !_closeByEscape) { - e->accept(); - } else { - RpWidget::keyPressEvent(e); - } -} - -void BoxContent::updateScrollAreaGeometry() { - auto newScrollHeight = height() - _innerTopSkip - _innerBottomSkip; - auto changed = (_scroll->height() != newScrollHeight); - _scroll->setGeometryToLeft(0, _innerTopSkip, width(), newScrollHeight); - _topShadow->entity()->resize(width(), st::lineWidth); - _topShadow->moveToLeft(0, _innerTopSkip); - _bottomShadow->entity()->resize(width(), st::lineWidth); - _bottomShadow->moveToLeft( - 0, - height() - _innerBottomSkip - st::lineWidth); - if (changed) { - updateInnerVisibleTopBottom(); - - auto top = _scroll->scrollTop(); - _topShadow->toggle( - (top > 0 || _innerTopSkip > 0), - anim::type::instant); - _bottomShadow->toggle( - (top < _scroll->scrollTopMax() || _innerBottomSkip > 0), - anim::type::instant); - } -} - -object_ptr BoxContent::doTakeInnerWidget() { - return _scroll->takeWidget(); -} - -void BoxContent::paintEvent(QPaintEvent *e) { - Painter p(this); - - if (testAttribute(Qt::WA_OpaquePaintEvent)) { - for (auto rect : e->region().rects()) { - p.fillRect(rect, st::boxBg); - } - } -} - -AbstractBox::AbstractBox( - not_null layer, - object_ptr content) -: LayerWidget(layer) -, _layer(layer) -, _content(std::move(content)) { - _content->setParent(this); - _content->setDelegate(this); - - _additionalTitle.changes( - ) | rpl::start_with_next([=] { - updateSize(); - update(); - }, lifetime()); -} - -AbstractBox::~AbstractBox() = default; - -void AbstractBox::setLayerType(bool layerType) { - _layerType = layerType; - updateTitlePosition(); -} - -int AbstractBox::titleHeight() const { - return _layerType ? st::boxLayerTitleHeight : st::boxTitleHeight; -} - -int AbstractBox::buttonsHeight() const { - const auto padding = _layerType - ? st::boxLayerButtonPadding - : st::boxButtonPadding; - return padding.top() + st::defaultBoxButton.height + padding.bottom(); -} - -int AbstractBox::buttonsTop() const { - const auto padding = _layerType - ? st::boxLayerButtonPadding - : st::boxButtonPadding; - return height() - padding.bottom() - st::defaultBoxButton.height; -} - -QRect AbstractBox::loadingRect() const { - const auto padding = _layerType - ? st::boxLayerButtonPadding - : st::boxButtonPadding; - const auto size = st::boxLoadingSize; - const auto skipx = _layerType - ? st::boxLayerTitlePosition.x() - : st::boxTitlePosition.x(); - const auto skipy = (st::defaultBoxButton.height - size) / 2; - return QRect( - skipx, - height() - padding.bottom() - skipy - size, - size, - size); -} - -void AbstractBox::paintEvent(QPaintEvent *e) { - Painter p(this); - auto clip = e->rect(); - auto paintTopRounded = clip.intersects(QRect(0, 0, width(), st::boxRadius)); - auto paintBottomRounded = clip.intersects(QRect(0, height() - st::boxRadius, width(), st::boxRadius)); - if (paintTopRounded || paintBottomRounded) { - auto parts = RectPart::None | 0; - if (paintTopRounded) parts |= RectPart::FullTop; - if (paintBottomRounded) parts |= RectPart::FullBottom; - App::roundRect(p, rect(), st::boxBg, BoxCorners, nullptr, parts); - } - auto other = e->region().intersected(QRect(0, st::boxRadius, width(), height() - 2 * st::boxRadius)); - if (!other.isEmpty()) { - for (auto rect : other.rects()) { - p.fillRect(rect, st::boxBg); - } - } - if (!_additionalTitle.current().isEmpty() - && clip.intersects(QRect(0, 0, width(), titleHeight()))) { - paintAdditionalTitle(p); - } - if (_loadingProgress) { - const auto rect = loadingRect(); - _loadingProgress->animation.draw( - p, - rect.topLeft(), - rect.size(), - width()); - } -} - -void AbstractBox::paintAdditionalTitle(Painter &p) { - p.setFont(st::boxLayerTitleAdditionalFont); - p.setPen(st::boxTitleAdditionalFg); - p.drawTextLeft(_titleLeft + (_title ? _title->width() : 0) + st::boxLayerTitleAdditionalSkip, _titleTop + st::boxTitleFont->ascent - st::boxLayerTitleAdditionalFont->ascent, width(), _additionalTitle.current()); -} - -void AbstractBox::parentResized() { - auto newHeight = countRealHeight(); - auto parentSize = parentWidget()->size(); - setGeometry((parentSize.width() - width()) / 2, (parentSize.height() - newHeight) / 2, width(), newHeight); - update(); -} - -void AbstractBox::setTitle(rpl::producer title) { - const auto wasTitle = hasTitle(); - if (title) { - _title.create(this, std::move(title), st::boxTitle); - _title->show(); - updateTitlePosition(); - } else { - _title.destroy(); - } - if (wasTitle != hasTitle()) { - updateSize(); - } -} - -void AbstractBox::setAdditionalTitle(rpl::producer additional) { - _additionalTitle = std::move(additional); -} - -void AbstractBox::setCloseByOutsideClick(bool close) { - _closeByOutsideClick = close; -} - -bool AbstractBox::closeByOutsideClick() const { - return _closeByOutsideClick; -} - -bool AbstractBox::hasTitle() const { - return (_title != nullptr) || !_additionalTitle.current().isEmpty(); -} - -void AbstractBox::showBox( - object_ptr box, - LayerOptions options, - anim::type animated) { - _layer->showBox(std::move(box), options, animated); -} - -void AbstractBox::updateSize() { - setDimensions(width(), _maxContentHeight); -} - -void AbstractBox::updateButtonsPositions() { - if (!_buttons.empty() || _leftButton) { - auto padding = _layerType ? st::boxLayerButtonPadding : st::boxButtonPadding; - auto right = padding.right(); - auto top = buttonsTop(); - if (_leftButton) { - _leftButton->moveToLeft(right, top); - } - for (const auto &button : _buttons) { - button->moveToRight(right, top); - right += button->width() + padding.left(); - } - } - if (_topButton) { - _topButton->moveToRight(0, 0); - } -} - -QPointer AbstractBox::outerContainer() { - return parentWidget(); -} - -void AbstractBox::updateTitlePosition() { - _titleLeft = _layerType ? st::boxLayerTitlePosition.x() : st::boxTitlePosition.x(); - _titleTop = _layerType ? st::boxLayerTitlePosition.y() : st::boxTitlePosition.y(); - if (_title) { - _title->resizeToWidth(qMin(_title->naturalWidth(), width() - _titleLeft * 2)); - _title->moveToLeft(_titleLeft, _titleTop); - } -} - -void AbstractBox::clearButtons() { - for (auto &button : base::take(_buttons)) { - button.destroy(); - } - _leftButton.destroy(); - _topButton = nullptr; -} - -QPointer AbstractBox::addButton( - rpl::producer text, - Fn clickCallback, - const style::RoundButton &st) { - _buttons.emplace_back(this, std::move(text), st); - auto result = QPointer(_buttons.back()); - result->setClickedCallback(std::move(clickCallback)); - result->show(); - result->widthValue( - ) | rpl::start_with_next([=] { - updateButtonsPositions(); - }, result->lifetime()); - return result; -} - -QPointer AbstractBox::addLeftButton( - rpl::producer text, - Fn clickCallback, - const style::RoundButton &st) { - _leftButton = object_ptr(this, std::move(text), st); - auto result = QPointer(_leftButton); - result->setClickedCallback(std::move(clickCallback)); - result->show(); - result->widthValue( - ) | rpl::start_with_next([=] { - updateButtonsPositions(); - }, result->lifetime()); - return result; -} - -QPointer AbstractBox::addTopButton(const style::IconButton &st, Fn clickCallback) { - _topButton = base::make_unique_q(this, st); - auto result = QPointer(_topButton.get()); - result->setClickedCallback(std::move(clickCallback)); - result->show(); - updateButtonsPositions(); - return result; -} - -void AbstractBox::showLoading(bool show) { - const auto &st = st::boxLoadingAnimation; - if (!show) { - if (_loadingProgress && !_loadingProgress->removeTimer.isActive()) { - _loadingProgress->removeTimer.callOnce( - st.sineDuration + st.sinePeriod); - _loadingProgress->animation.stop(); - } - return; - } - if (!_loadingProgress) { - const auto callback = [=] { - if (!anim::Disabled()) { - const auto t = st::boxLoadingAnimation.thickness; - update(loadingRect().marginsAdded({ t, t, t, t })); - } - }; - _loadingProgress = std::make_unique( - callback, - st::boxLoadingAnimation); - _loadingProgress->removeTimer.setCallback([=] { - _loadingProgress = nullptr; - }); - } else { - _loadingProgress->removeTimer.cancel(); - } - _loadingProgress->animation.start(); -} - - -void AbstractBox::setDimensions(int newWidth, int maxHeight, bool forceCenterPosition) { - _maxContentHeight = maxHeight; - - auto fullHeight = countFullHeight(); - if (width() != newWidth || _fullHeight != fullHeight) { - _fullHeight = fullHeight; - if (parentWidget()) { - auto oldGeometry = geometry(); - resize(newWidth, countRealHeight()); - auto newGeometry = geometry(); - auto parentHeight = parentWidget()->height(); - if (newGeometry.top() + newGeometry.height() + st::boxVerticalMargin > parentHeight - || forceCenterPosition) { - const auto top1 = parentHeight - int(st::boxVerticalMargin) - newGeometry.height(); - const auto top2 = (parentHeight - newGeometry.height()) / 2; - const auto newTop = forceCenterPosition - ? std::min(top1, top2) - : std::max(top1, top2); - if (newTop != newGeometry.top()) { - move(newGeometry.left(), newTop); - resizeEvent(0); - } - } - parentWidget()->update(oldGeometry.united(geometry()).marginsAdded(st::boxRoundShadow.extend)); - } else { - resize(newWidth, 0); - } - } -} - -int AbstractBox::countRealHeight() const { - return qMin(_fullHeight, parentWidget()->height() - 2 * st::boxVerticalMargin); -} - -int AbstractBox::countFullHeight() const { - return contentTop() + _maxContentHeight + buttonsHeight(); -} - -int AbstractBox::contentTop() const { - return hasTitle() ? titleHeight() : (_noContentMargin ? 0 : st::boxTopMargin); -} - -void AbstractBox::resizeEvent(QResizeEvent *e) { - updateButtonsPositions(); - updateTitlePosition(); - - auto top = contentTop(); - _content->resize(width(), height() - top - buttonsHeight()); - _content->moveToLeft(0, top); - - LayerWidget::resizeEvent(e); -} - -void AbstractBox::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Escape) { - closeBox(); - } else { - LayerWidget::keyPressEvent(e); - } -} - -BoxContentDivider::BoxContentDivider(QWidget *parent) -: BoxContentDivider(parent, st::rightsDividerHeight) { -} - -BoxContentDivider::BoxContentDivider(QWidget *parent, int height) -: RpWidget(parent) { - resize(width(), height); -} - -void BoxContentDivider::paintEvent(QPaintEvent *e) { - Painter p(this); - p.fillRect(e->rect(), st::contactsAboutBg); - auto dividerFillTop = myrtlrect(0, 0, width(), st::profileDividerTop.height()); - st::profileDividerTop.fill(p, dividerFillTop); - auto dividerFillBottom = myrtlrect(0, height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height()); - st::profileDividerBottom.fill(p, dividerFillBottom); -} - namespace Ui { namespace internal { void showBox( - object_ptr content, - LayerOptions options, - anim::type animated) { + object_ptr content, + LayerOptions options, + anim::type animated) { if (auto w = App::wnd()) { w->ui_showBox(std::move(content), options, animated); } diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h index 0a38b109d..95d15f038 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.h +++ b/Telegram/SourceFiles/boxes/abstract_box.h @@ -7,12 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "window/layer_widget.h" -#include "base/unique_qptr.h" -#include "base/flags.h" -#include "ui/effects/animation_value.h" -#include "ui/text/text_entity.h" -#include "ui/rp_widget.h" +#include "ui/layers/box_layer_widget.h" class Painter; @@ -30,413 +25,13 @@ class FlatLabel; class FadeShadow; } // namespace Ui -class BoxContent; - -class BoxContentDelegate { -public: - virtual void setLayerType(bool layerType) = 0; - virtual void setTitle(rpl::producer title) = 0; - virtual void setAdditionalTitle(rpl::producer additional) = 0; - virtual void setCloseByOutsideClick(bool close) = 0; - - virtual void clearButtons() = 0; - virtual QPointer addButton( - rpl::producer text, - Fn clickCallback, - const style::RoundButton &st) = 0; - virtual QPointer addLeftButton( - rpl::producer text, - Fn clickCallback, - const style::RoundButton &st) = 0; - virtual QPointer addTopButton( - const style::IconButton &st, - Fn clickCallback) = 0; - virtual void showLoading(bool show) = 0; - virtual void updateButtonsPositions() = 0; - - virtual void showBox( - object_ptr box, - LayerOptions options, - anim::type animated) = 0; - virtual void setDimensions( - int newWidth, - int maxHeight, - bool forceCenterPosition = false) = 0; - virtual void setNoContentMargin(bool noContentMargin) = 0; - virtual bool isBoxShown() const = 0; - virtual void closeBox() = 0; - - template - QPointer show( - object_ptr content, - LayerOptions options = LayerOption::KeepOther, - anim::type animated = anim::type::normal) { - auto result = QPointer(content.data()); - showBox(std::move(content), options, animated); - return result; - } - - virtual QPointer outerContainer() = 0; - -}; - -class BoxContent : public Ui::RpWidget { - Q_OBJECT - -public: - BoxContent() { - setAttribute(Qt::WA_OpaquePaintEvent); - } - - bool isBoxShown() const { - return getDelegate()->isBoxShown(); - } - void closeBox() { - getDelegate()->closeBox(); - } - - void setTitle(rpl::producer title); - void setTitle(rpl::producer title) { - getDelegate()->setTitle(std::move(title)); - } - void setAdditionalTitle(rpl::producer additional) { - getDelegate()->setAdditionalTitle(std::move(additional)); - } - void setCloseByEscape(bool close) { - _closeByEscape = close; - } - void setCloseByOutsideClick(bool close) { - getDelegate()->setCloseByOutsideClick(close); - } - - void scrollToWidget(not_null widget); - - void clearButtons() { - getDelegate()->clearButtons(); - } - QPointer addButton( - rpl::producer text, - Fn clickCallback = nullptr); - QPointer addLeftButton( - rpl::producer text, - Fn clickCallback = nullptr); - QPointer addTopButton( - const style::IconButton &st, - Fn clickCallback = nullptr) { - return getDelegate()->addTopButton(st, std::move(clickCallback)); - } - QPointer addButton( - rpl::producer text, - const style::RoundButton &st) { - return getDelegate()->addButton(std::move(text), nullptr, st); - } - QPointer addButton( - rpl::producer text, - Fn clickCallback, - const style::RoundButton &st) { - return getDelegate()->addButton( - std::move(text), - std::move(clickCallback), - st); - } - void showLoading(bool show) { - getDelegate()->showLoading(show); - } - void updateButtonsGeometry() { - getDelegate()->updateButtonsPositions(); - } - - virtual void setInnerFocus() { - setFocus(); - } - - rpl::producer<> boxClosing() const { - return _boxClosingStream.events(); - } - void notifyBoxClosing() { - _boxClosingStream.fire({}); - } - - void setDelegate(not_null newDelegate) { - _delegate = newDelegate; - _preparing = true; - prepare(); - finishPrepare(); - } - not_null getDelegate() const { - return _delegate; - } - -public slots: - void onScrollToY(int top, int bottom = -1); - - void onDraggingScrollDelta(int delta); - -protected: - virtual void prepare() = 0; - - void setLayerType(bool layerType) { - getDelegate()->setLayerType(layerType); - } - - void setNoContentMargin(bool noContentMargin) { - if (_noContentMargin != noContentMargin) { - _noContentMargin = noContentMargin; - setAttribute(Qt::WA_OpaquePaintEvent, !_noContentMargin); - } - getDelegate()->setNoContentMargin(noContentMargin); - } - void setDimensions( - int newWidth, - int maxHeight, - bool forceCenterPosition = false) { - getDelegate()->setDimensions( - newWidth, - maxHeight, - forceCenterPosition); - } - void setDimensionsToContent( - int newWidth, - not_null content); - void setInnerTopSkip(int topSkip, bool scrollBottomFixed = false); - void setInnerBottomSkip(int bottomSkip); - - template - QPointer setInnerWidget( - object_ptr inner, - const style::ScrollArea &st, - int topSkip = 0, - int bottomSkip = 0) { - auto result = QPointer(inner.data()); - setInnerTopSkip(topSkip); - setInnerBottomSkip(bottomSkip); - setInner(std::move(inner), st); - return result; - } - - template - QPointer setInnerWidget( - object_ptr inner, - int topSkip = 0, - int bottomSkip = 0) { - auto result = QPointer(inner.data()); - setInnerTopSkip(topSkip); - setInnerBottomSkip(bottomSkip); - setInner(std::move(inner)); - return result; - } - - template - object_ptr takeInnerWidget() { - return object_ptr::fromRaw( - static_cast(doTakeInnerWidget().release())); - } - - void setInnerVisible(bool scrollAreaVisible); - QPixmap grabInnerCache(); - - void resizeEvent(QResizeEvent *e) override; - void paintEvent(QPaintEvent *e) override; - void keyPressEvent(QKeyEvent *e) override; - -private slots: - void onScroll(); - void onInnerResize(); - - void onDraggingScrollTimer(); - -private: - void finishPrepare(); - void finishScrollCreate(); - void setInner(object_ptr inner); - void setInner(object_ptr inner, const style::ScrollArea &st); - void updateScrollAreaGeometry(); - void updateInnerVisibleTopBottom(); - void updateShadowsVisibility(); - object_ptr doTakeInnerWidget(); - - BoxContentDelegate *_delegate = nullptr; - - bool _preparing = false; - bool _noContentMargin = false; - bool _closeByEscape = true; - int _innerTopSkip = 0; - int _innerBottomSkip = 0; - object_ptr _scroll = { nullptr }; - object_ptr _topShadow = { nullptr }; - object_ptr _bottomShadow = { nullptr }; - - object_ptr _draggingScrollTimer = { nullptr }; - int _draggingScrollDelta = 0; - - rpl::event_stream<> _boxClosingStream; - -}; - -class AbstractBox : public Window::LayerWidget, public BoxContentDelegate { -public: - AbstractBox( - not_null layer, - object_ptr content); - ~AbstractBox(); - - void parentResized() override; - - void setLayerType(bool layerType) override; - void setTitle(rpl::producer title) override; - void setAdditionalTitle(rpl::producer additional) override; - void showBox( - object_ptr box, - LayerOptions options, - anim::type animated) override; - - void clearButtons() override; - QPointer addButton( - rpl::producer text, - Fn clickCallback, - const style::RoundButton &st) override; - QPointer addLeftButton( - rpl::producer text, - Fn clickCallback, - const style::RoundButton &st) override; - QPointer addTopButton( - const style::IconButton &st, - Fn clickCallback) override; - void showLoading(bool show) override; - void updateButtonsPositions() override; - QPointer outerContainer() override; - - void setDimensions( - int newWidth, - int maxHeight, - bool forceCenterPosition = false) override; - - void setNoContentMargin(bool noContentMargin) override { - if (_noContentMargin != noContentMargin) { - _noContentMargin = noContentMargin; - updateSize(); - } - } - - bool isBoxShown() const override { - return !isHidden(); - } - void closeBox() override { - closeLayer(); - } - - void setCloseByOutsideClick(bool close) override; - bool closeByOutsideClick() const override; - -protected: - void keyPressEvent(QKeyEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - void paintEvent(QPaintEvent *e) override; - - void doSetInnerFocus() override { - _content->setInnerFocus(); - } - void closeHook() override { - _content->notifyBoxClosing(); - } - -private: - struct LoadingProgress; - - void paintAdditionalTitle(Painter &p); - void updateTitlePosition(); - - [[nodiscard]] bool hasTitle() const; - [[nodiscard]] int titleHeight() const; - [[nodiscard]] int buttonsHeight() const; - [[nodiscard]] int buttonsTop() const; - [[nodiscard]] int contentTop() const; - [[nodiscard]] int countFullHeight() const; - [[nodiscard]] int countRealHeight() const; - [[nodiscard]] QRect loadingRect() const; - void updateSize(); - - not_null _layer; - int _fullHeight = 0; - - bool _noContentMargin = false; - int _maxContentHeight = 0; - object_ptr _content; - - object_ptr _title = { nullptr }; - Fn _titleFactory; - rpl::variable _additionalTitle; - int _titleLeft = 0; - int _titleTop = 0; - bool _layerType = false; - bool _closeByOutsideClick = true; - - std::vector> _buttons; - object_ptr _leftButton = { nullptr }; - base::unique_qptr _topButton = { nullptr }; - std::unique_ptr _loadingProgress; - -}; - -class BoxContentDivider : public Ui::RpWidget { -public: - BoxContentDivider(QWidget *parent); - BoxContentDivider(QWidget *parent, int height); - -protected: - void paintEvent(QPaintEvent *e) override; - -}; - -class BoxPointer { -public: - BoxPointer() = default; - BoxPointer(const BoxPointer &other) = default; - BoxPointer(BoxPointer &&other) : _value(base::take(other._value)) { - } - BoxPointer &operator=(const BoxPointer &other) { - if (_value != other._value) { - destroy(); - _value = other._value; - } - return *this; - } - BoxPointer &operator=(BoxPointer &&other) { - if (_value != other._value) { - destroy(); - _value = base::take(other._value); - } - return *this; - } - BoxPointer &operator=(BoxContent *other) { - if (_value != other) { - destroy(); - _value = other; - } - return *this; - } - ~BoxPointer() { - destroy(); - } - -private: - void destroy() { - if (const auto value = base::take(_value)) { - value->closeBox(); - } - } - - QPointer _value; - -}; - // Legacy global method. namespace Ui { namespace internal { void showBox( object_ptr content, - LayerOptions options, + Ui::LayerOptions options, anim::type animated); } // namespace internal @@ -444,7 +39,7 @@ void showBox( template QPointer show( object_ptr content, - LayerOptions options = LayerOption::CloseOther, + Ui::LayerOptions options = Ui::LayerOption::CloseOther, anim::type animated = anim::type::normal) { auto result = QPointer(content.data()); internal::showBox(std::move(content), options, animated); diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp index 728afe6ed..ed831de5f 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp @@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/add_contact_box.h" -#include "styles/style_boxes.h" -#include "styles/style_dialogs.h" #include "lang/lang_keys.h" #include "mtproto/sender.h" #include "base/flat_set.h" @@ -42,6 +40,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "observer_peer.h" #include "main/main_session.h" #include "facades.h" +#include "styles/style_layers.h" +#include "styles/style_boxes.h" +#include "styles/style_dialogs.h" #include #include @@ -164,7 +165,7 @@ void ShowAddParticipantsError( tr::lng_cant_invite_make_admin(tr::now), tr::lng_cancel(tr::now), makeAdmin), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } @@ -199,7 +200,7 @@ void ShowAddParticipantsError( } return tr::lng_failed_add_participant(tr::now); }(); - Ui::show(Box(text), LayerOption::KeepOther); + Ui::show(Box(text), Ui::LayerOption::KeepOther); } class RevokePublicLinkBox::Inner : public TWidget, private MTP::Sender { @@ -588,16 +589,16 @@ void GroupInfoBox::createGroup( } else if (error.type() == qstr("USERS_TOO_FEW")) { Ui::show( Box(tr::lng_cant_invite_privacy(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } else if (error.type() == qstr("PEER_FLOOD")) { Ui::show( Box( PeerFloodErrorText(PeerFloodType::InviteGroup)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } else if (error.type() == qstr("USER_RESTRICTED")) { Ui::show( Box(tr::lng_cant_do_this(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } }).send(); } @@ -636,7 +637,7 @@ void GroupInfoBox::submit() { Box( std::make_unique(_navigation), std::move(initBox)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } } @@ -765,7 +766,7 @@ SetupChannelBox::SetupChannelBox( st::defaultBoxCheckbox) , _aboutPublicWidth(st::boxWideWidth - st::boxPadding.left() - - st::boxButtonPadding.right() + - st::defaultBox.buttonPadding.right() - st::newGroupPadding.left() - st::defaultRadio.diameter - st::defaultBoxCheckbox.textPosition.x()) @@ -1031,7 +1032,7 @@ void SetupChannelBox::privacyChanged(Privacy value) { Box( &_channel->session(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } _link->show(); @@ -1126,14 +1127,14 @@ void SetupChannelBox::showRevokePublicLinkBoxForEdit() { const auto callback = [=] { Ui::show( Box(navigation, channel, existing), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }; closeBox(); Ui::show( Box( &channel->session(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } bool SetupChannelBox::onFirstCheckFail(const RPCError &error) { @@ -1344,7 +1345,7 @@ void RevokePublicLinkBox::prepare() { if (callback) { callback(); } - }), st::boxLayerScroll, _innerTop); + }), st::boxScroll, _innerTop); addButton(tr::lng_cancel(), [=] { closeBox(); }); @@ -1412,7 +1413,7 @@ void RevokePublicLinkBox::Inner::mouseReleaseEvent(QMouseEvent *e) { callback(); } }).send(); - })), LayerOption::KeepOther); + })), Ui::LayerOption::KeepOther); } } diff --git a/Telegram/SourceFiles/boxes/add_contact_box.h b/Telegram/SourceFiles/boxes/add_contact_box.h index 76231b4be..e97eff55e 100644 --- a/Telegram/SourceFiles/boxes/add_contact_box.h +++ b/Telegram/SourceFiles/boxes/add_contact_box.h @@ -54,7 +54,7 @@ void ShowAddParticipantsError( not_null chat, const std::vector> &users); -class AddContactBox : public BoxContent { +class AddContactBox : public Ui::BoxContent { public: AddContactBox(QWidget*, not_null session); AddContactBox( @@ -94,7 +94,7 @@ private: }; -class GroupInfoBox : public BoxContent, private MTP::Sender { +class GroupInfoBox : public Ui::BoxContent, private MTP::Sender { public: enum class Type { Group, @@ -140,7 +140,7 @@ private: }; class SetupChannelBox - : public BoxContent + : public Ui::BoxContent , public RPCSender , private base::Subscriber { public: @@ -209,7 +209,7 @@ private: }; -class EditNameBox : public BoxContent, public RPCSender { +class EditNameBox : public Ui::BoxContent, public RPCSender { public: EditNameBox(QWidget*, not_null user); @@ -238,7 +238,7 @@ private: }; class RevokePublicLinkBox - : public BoxContent + : public Ui::BoxContent , public RPCSender , private base::Subscriber { public: diff --git a/Telegram/SourceFiles/boxes/auto_download_box.cpp b/Telegram/SourceFiles/boxes/auto_download_box.cpp index 7ba178507..21d44e0c2 100644 --- a/Telegram/SourceFiles/boxes/auto_download_box.cpp +++ b/Telegram/SourceFiles/boxes/auto_download_box.cpp @@ -10,13 +10,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "main/main_session.h" #include "data/data_session.h" -#include "info/profile/info_profile_button.h" #include "ui/widgets/continuous_sliders.h" +#include "ui/widgets/buttons.h" #include "ui/wrap/vertical_layout.h" #include "ui/wrap/wrap.h" #include "storage/localstorage.h" #include "settings/settings_common.h" #include "export/view/export_view_settings.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_settings.h" diff --git a/Telegram/SourceFiles/boxes/auto_download_box.h b/Telegram/SourceFiles/boxes/auto_download_box.h index 50fefad68..617a4e203 100644 --- a/Telegram/SourceFiles/boxes/auto_download_box.h +++ b/Telegram/SourceFiles/boxes/auto_download_box.h @@ -19,7 +19,7 @@ enum class Source; } // namespace AutoDownload } // namespace Data -class AutoDownloadBox : public BoxContent { +class AutoDownloadBox : public Ui::BoxContent { public: AutoDownloadBox( QWidget*, diff --git a/Telegram/SourceFiles/boxes/auto_lock_box.cpp b/Telegram/SourceFiles/boxes/auto_lock_box.cpp index cc04ccb77..9cbfbbf25 100644 --- a/Telegram/SourceFiles/boxes/auto_lock_box.cpp +++ b/Telegram/SourceFiles/boxes/auto_lock_box.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "ui/widgets/checkbox.h" #include "facades.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" AutoLockBox::AutoLockBox(QWidget*, not_null session) diff --git a/Telegram/SourceFiles/boxes/auto_lock_box.h b/Telegram/SourceFiles/boxes/auto_lock_box.h index 903510236..13cd573d5 100644 --- a/Telegram/SourceFiles/boxes/auto_lock_box.h +++ b/Telegram/SourceFiles/boxes/auto_lock_box.h @@ -17,7 +17,7 @@ namespace Ui { class Radiobutton; } // namespace Ui -class AutoLockBox : public BoxContent { +class AutoLockBox : public Ui::BoxContent { public: AutoLockBox(QWidget*, not_null session); diff --git a/Telegram/SourceFiles/boxes/background_box.cpp b/Telegram/SourceFiles/boxes/background_box.cpp index 7dd55753b..9d91c177a 100644 --- a/Telegram/SourceFiles/boxes/background_box.cpp +++ b/Telegram/SourceFiles/boxes/background_box.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/confirm_box.h" #include "app.h" #include "styles/style_overview.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_chat_helpers.h" @@ -144,7 +145,7 @@ void BackgroundBox::prepare() { ) | rpl::start_with_next([=](const Data::WallPaper &paper) { Ui::show( Box(_session, paper), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }, _inner->lifetime()); _inner->removeRequests( @@ -154,7 +155,7 @@ void BackgroundBox::prepare() { } void BackgroundBox::removePaper(const Data::WallPaper &paper) { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto session = _session; const auto remove = [=, weak = Ui::MakeWeak(this)]{ if (*box) { @@ -176,7 +177,7 @@ void BackgroundBox::removePaper(const Data::WallPaper &paper) { tr::lng_selected_delete(tr::now), tr::lng_cancel(tr::now), remove), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } BackgroundBox::Inner::Inner( diff --git a/Telegram/SourceFiles/boxes/background_box.h b/Telegram/SourceFiles/boxes/background_box.h index 4dbfae467..dbfd8439e 100644 --- a/Telegram/SourceFiles/boxes/background_box.h +++ b/Telegram/SourceFiles/boxes/background_box.h @@ -17,7 +17,7 @@ namespace Data { class WallPaper; } // namespace Data -class BackgroundBox : public BoxContent { +class BackgroundBox : public Ui::BoxContent { public: BackgroundBox(QWidget*, not_null session); diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index 908efa695..61c3a1c05 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/background_preview_box.h" #include "app.h" #include "styles/style_history.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include diff --git a/Telegram/SourceFiles/boxes/background_preview_box.h b/Telegram/SourceFiles/boxes/background_preview_box.h index 879cc0d02..f0c929de1 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.h +++ b/Telegram/SourceFiles/boxes/background_preview_box.h @@ -24,7 +24,7 @@ class Checkbox; } // namespace Ui class BackgroundPreviewBox - : public BoxContent + : public Ui::BoxContent , private HistoryView::SimpleElementDelegate , private base::Subscriber { public: diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 3c49d234d..e2d9ae485 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -5,138 +5,31 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -using "basic.style"; +using "ui/basic.style"; +using "ui/layers/layers.style"; using "ui/widgets/widgets.style"; using "intro/intro.style"; -boxDuration: 200; -boxRadius: 3px; - -ServiceCheck { - margin: margins; - diameter: pixels; - shift: pixels; - thickness: pixels; - tip: point; - small: pixels; - large: pixels; - stroke: pixels; - color: color; +UserpicButton { + size: size; + photoSize: pixels; + photoPosition: point; + changeButton: RoundButton; + changeIcon: icon; + changeIconPosition: point; duration: int; + uploadHeight: pixels; + uploadBg: color; + uploadIcon: icon; + uploadIconPosition: point; } -boxButtonFont: font(boxFontSize semibold); -defaultBoxButton: RoundButton(defaultLightButton) { - width: -24px; - height: 36px; - font: boxButtonFont; -} - -boxTextStyle: TextStyle(defaultTextStyle) { - font: font(boxFontSize); - linkFont: font(boxFontSize); - linkFontOver: font(boxFontSize underline); -} - -boxLabelStyle: TextStyle(boxTextStyle) { - lineHeight: 22px; -} - -attentionBoxButton: RoundButton(defaultBoxButton) { - textFg: attentionButtonFg; - textFgOver: attentionButtonFgOver; - textBgOver: attentionButtonBgOver; - - ripple: RippleAnimation(defaultRippleAnimation) { - color: attentionButtonBgRipple; - } -} - -defaultBoxCheckbox: Checkbox(defaultCheckbox) { - width: -46px; - textPosition: point(12px, 1px); - style: boxTextStyle; -} - -boxRoundShadow: Shadow { - left: icon {{ "round_shadow_box_left", windowShadowFg }}; - topLeft: icon {{ "round_shadow_box_top_left", windowShadowFg }}; - top: icon {{ "round_shadow_box_top", windowShadowFg }}; - topRight: icon {{ "round_shadow_box_top_left-flip_horizontal", windowShadowFg }}; - right: icon {{ "round_shadow_box_left-flip_horizontal", windowShadowFg }}; - bottomRight: icon {{ "round_shadow_box_bottom_left-flip_horizontal", windowShadowFg }}; - bottom: icon {{ "round_shadow_box_bottom", windowShadowFg }}; - bottomLeft: icon {{ "round_shadow_box_bottom_left", windowShadowFg }}; - extend: margins(10px, 10px, 10px, 10px); - fallback: windowShadowFgFallback; -} - -boxTitleFont: font(17px semibold); -boxTitle: FlatLabel(defaultFlatLabel) { - textFg: boxTitleFg; - maxHeight: 24px; - style: TextStyle(defaultTextStyle) { - font: boxTitleFont; - linkFont: boxTitleFont; - linkFontOver: font(17px semibold underline); - } -} -boxTitlePosition: point(23px, 16px); -boxTitleHeight: 56px; -boxLayerTitlePosition: point(23px, 16px); -boxLayerTitleHeight: 56px; -boxLayerTitleAdditionalSkip: 9px; -boxLayerTitleAdditionalFont: normalFont; -boxLayerScroll: defaultSolidScroll; - -boxRowPadding: margins(23px, 0px, 23px, 0px); - -boxTopMargin: 6px; - -boxTitleClose: IconButton(defaultIconButton) { - width: boxTitleHeight; - height: boxTitleHeight; - - icon: boxTitleCloseIcon; - iconOver: boxTitleCloseIconOver; - - rippleAreaPosition: point(6px, 6px); - rippleAreaSize: 44px; - ripple: RippleAnimation(defaultRippleAnimation) { - color: windowBgOver; - } -} - -boxLinkButton: LinkButton(defaultLinkButton) { - font: boxTextFont; - overFont: font(boxFontSize underline); -} - -boxOptionListPadding: margins(0px, 0px, 0px, 0px); -boxOptionListSkip: 20px; -boxOptionInputSkip: 6px; - -boxVerticalMargin: 10px; -boxWidth: 320px; -boxWideWidth: 364px; -boxPadding: margins(23px, 30px, 23px, 8px); -boxMaxListHeight: 492px; -boxLittleSkip: 10px; -boxMediumSkip: 20px; - -boxButtonPadding: margins(8px, 12px, 13px, 12px); -boxLayerButtonPadding: margins(8px, 8px, 8px, 8px); -boxLabel: FlatLabel(defaultFlatLabel) { - minWidth: 274px; - align: align(topleft); - style: boxLabelStyle; -} -boxDividerLabel: FlatLabel(boxLabel) { - minWidth: 245px; - align: align(topleft); - textFg: windowSubTextFg; - style: defaultTextStyle; +FeedUserpicButton { + size: size; + innerSize: pixels; + innerPosition: point; + innerPart: UserpicButton; } countryRowHeight: 36px; @@ -149,7 +42,7 @@ countryRowBgOver: windowBgOver; countryRowCodeFg: windowSubTextFg; countryRowCodeFgOver: windowSubTextFgOver; countriesSkip: 12px; -countriesScroll: ScrollArea(boxLayerScroll) { +countriesScroll: ScrollArea(boxScroll) { deltat: 9px; deltab: 3px; } @@ -161,11 +54,27 @@ boxPhotoCompressedSkip: 20px; boxPhotoCaptionSkip: 8px; boxPhotoTextFg: windowSubTextFg; -boxLoadingAnimation: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) { - color: windowSubTextFg; - thickness: 2px; +defaultChangeUserpicIcon: icon {{ "new_chat_photo", activeButtonFg }}; +defaultUploadUserpicIcon: icon {{ "upload_chat_photo", msgDateImgFg }}; +defaultUserpicButton: UserpicButton { + size: size(76px, 76px); + photoSize: 76px; + photoPosition: point(-1px, -1px); + changeButton: defaultActiveButton; + changeIcon: defaultChangeUserpicIcon; + changeIconPosition: point(23px, 25px); + duration: 500; + uploadHeight: 24px; + uploadBg: msgDateImgBgOver; + uploadIcon: defaultUploadUserpicIcon; + uploadIconPosition: point(-1px, 1px); +} +defaultFeedUserpicButton: FeedUserpicButton { + size: size(76px, 76px); + innerSize: 76px; + innerPosition: point(-1px, -1px); + innerPart: defaultUserpicButton; } -boxLoadingSize: 20px; cropPointSize: 10px; cropSkip: 13px; @@ -224,24 +133,6 @@ contactUserIcon: icon {{ "settings_name", menuIconFg }}; contactPhoneIcon: icon {{ "settings_phone_number", menuIconFg }}; contactIconPosition: point(-5px, 23px); -contactsAddIconAbove: icon {{ "contacts_add", activeButtonFg, point(18px, 18px) }}; -contactsAdd: TwoIconButton { - width: 52px; - height: 52px; - - iconBelow: contactsAddIconBelow; - iconBelowOver: contactsAddIconBelowOver; - iconAbove: contactsAddIconAbove; - iconAboveOver: contactsAddIconAbove; - - rippleAreaPosition: point(5px, 5px); - rippleAreaSize: 42px; - ripple: RippleAnimation(defaultRippleAnimation) { - color: activeButtonBgRipple; - } -} -contactsAddPosition: point(14px, 8px); - contactPadding: margins(49px, 2px, 0px, 12px); contactSkip: 6px; contactPhoneSkip: 30px; @@ -461,7 +352,7 @@ membersAbout: FlatLabel(defaultFlatLabel) { style: boxLabelStyle; } -sessionsScroll: boxLayerScroll; +sessionsScroll: boxScroll; sessionsHeight: 350px; sessionHeight: 70px; sessionCurrentPadding: margins(0px, 7px, 0px, 4px); @@ -599,7 +490,7 @@ langsRadio: Radio(defaultRadio) { backgroundPadding: 10px; backgroundSize: size(108px, 193px); -backgroundScroll: ScrollArea(boxLayerScroll) { +backgroundScroll: ScrollArea(boxScroll) { deltax: 3px; width: 10px; deltat: 10px; @@ -743,7 +634,7 @@ rightsToggle: Toggle(defaultToggle) { stroke: 2px; duration: 120; } -rightsDividerHeight: 10px; +rightsDividerHeight: boxDividerHeight; rightsDividerMargin: margins(0px, 0px, 0px, 20px); rightsHeaderMargin: margins(23px, 0px, 23px, 8px); rightsToggleMargin: margins(23px, 8px, 23px, 8px); @@ -889,8 +780,8 @@ themesMenuToggle: IconButton(defaultIconButton) { width: 44px; height: 44px; - icon: icon {{ "title_menu_dots", menuIconFg }}; - iconOver: icon {{ "title_menu_dots", menuIconFgOver }}; + icon: menuToggleIcon; + iconOver: menuToggleIconOver; iconPosition: point(-1px, -1px); rippleAreaPosition: point(4px, 4px); @@ -961,7 +852,7 @@ createPollWarningPosition: point(16px, 6px); callSettingsButton: IconButton { width: 50px; - height: boxLayerTitleHeight; + height: boxTitleHeight; icon: icon {{ "menu_settings", boxTitleCloseFg }}; iconOver: icon {{ "menu_settings", boxTitleCloseFgOver }}; iconPosition: point(8px, -1px); diff --git a/Telegram/SourceFiles/boxes/calendar_box.h b/Telegram/SourceFiles/boxes/calendar_box.h index b718fcf0a..066d0425f 100644 --- a/Telegram/SourceFiles/boxes/calendar_box.h +++ b/Telegram/SourceFiles/boxes/calendar_box.h @@ -17,7 +17,7 @@ namespace Ui { class IconButton; } // namespace Ui -class CalendarBox : public BoxContent, private base::Subscriber { +class CalendarBox : public Ui::BoxContent, private base::Subscriber { public: CalendarBox( QWidget*, diff --git a/Telegram/SourceFiles/boxes/change_phone_box.cpp b/Telegram/SourceFiles/boxes/change_phone_box.cpp index 6b50813b7..9240fbf64 100644 --- a/Telegram/SourceFiles/boxes/change_phone_box.cpp +++ b/Telegram/SourceFiles/boxes/change_phone_box.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_user.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" namespace { @@ -61,7 +62,7 @@ void createErrorLabel( } // namespace -class ChangePhoneBox::EnterPhone : public BoxContent { +class ChangePhoneBox::EnterPhone : public Ui::BoxContent { public: EnterPhone(QWidget*, not_null session); @@ -89,7 +90,7 @@ private: }; -class ChangePhoneBox::EnterCode : public BoxContent { +class ChangePhoneBox::EnterCode : public Ui::BoxContent { public: EnterCode( QWidget*, @@ -214,7 +215,7 @@ void ChangePhoneBox::EnterPhone::sendPhoneDone(const QString &phoneNumber, const phoneCodeHash, codeLength, callTimeout), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } bool ChangePhoneBox::EnterPhone::sendPhoneFail(const QString &phoneNumber, const RPCError &error) { diff --git a/Telegram/SourceFiles/boxes/change_phone_box.h b/Telegram/SourceFiles/boxes/change_phone_box.h index 9eb6a8479..23a2feca1 100644 --- a/Telegram/SourceFiles/boxes/change_phone_box.h +++ b/Telegram/SourceFiles/boxes/change_phone_box.h @@ -13,7 +13,7 @@ namespace Main { class Session; } // namespace Main -class ChangePhoneBox : public BoxContent { +class ChangePhoneBox : public Ui::BoxContent { public: ChangePhoneBox(QWidget*, not_null session); diff --git a/Telegram/SourceFiles/boxes/confirm_box.cpp b/Telegram/SourceFiles/boxes/confirm_box.cpp index 1e6532f69..402facdc0 100644 --- a/Telegram/SourceFiles/boxes/confirm_box.cpp +++ b/Telegram/SourceFiles/boxes/confirm_box.cpp @@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/confirm_box.h" -#include "styles/style_boxes.h" #include "lang/lang_keys.h" #include "mainwidget.h" #include "mainwindow.h" @@ -36,6 +35,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "observer_peer.h" #include "facades.h" #include "app.h" +#include "styles/style_layers.h" +#include "styles/style_boxes.h" #include #include @@ -55,7 +56,7 @@ ConfirmBox::ConfirmBox( : _confirmText(tr::lng_box_ok(tr::now)) , _cancelText(tr::lng_cancel(tr::now)) , _confirmStyle(st::defaultBoxButton) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(std::move(confirmedCallback)) , _cancelledCallback(std::move(cancelledCallback)) { init(text); @@ -70,7 +71,7 @@ ConfirmBox::ConfirmBox( : _confirmText(confirmText) , _cancelText(tr::lng_cancel(tr::now)) , _confirmStyle(st::defaultBoxButton) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(std::move(confirmedCallback)) , _cancelledCallback(std::move(cancelledCallback)) { init(text); @@ -85,7 +86,7 @@ ConfirmBox::ConfirmBox( : _confirmText(confirmText) , _cancelText(tr::lng_cancel(tr::now)) , _confirmStyle(st::defaultBoxButton) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(std::move(confirmedCallback)) , _cancelledCallback(std::move(cancelledCallback)) { init(text); @@ -101,7 +102,7 @@ ConfirmBox::ConfirmBox( : _confirmText(confirmText) , _cancelText(tr::lng_cancel(tr::now)) , _confirmStyle(confirmStyle) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(std::move(confirmedCallback)) , _cancelledCallback(std::move(cancelledCallback)) { init(text); @@ -117,7 +118,7 @@ ConfirmBox::ConfirmBox( : _confirmText(confirmText) , _cancelText(cancelText) , _confirmStyle(st::defaultBoxButton) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(std::move(confirmedCallback)) , _cancelledCallback(std::move(cancelledCallback)) { init(text); @@ -134,7 +135,7 @@ ConfirmBox::ConfirmBox( : _confirmText(confirmText) , _cancelText(cancelText) , _confirmStyle(st::defaultBoxButton) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(std::move(confirmedCallback)) , _cancelledCallback(std::move(cancelledCallback)) { init(text); @@ -148,7 +149,7 @@ ConfirmBox::ConfirmBox( : _confirmText(doneText) , _confirmStyle(st::defaultBoxButton) , _informative(true) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(generateInformCallback(closedCallback)) , _cancelledCallback(generateInformCallback(closedCallback)) { init(text); @@ -162,7 +163,7 @@ ConfirmBox::ConfirmBox( : _confirmText(doneText) , _confirmStyle(st::defaultBoxButton) , _informative(true) -, _text(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) +, _text(st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) , _confirmedCallback(generateInformCallback(closedCallback)) , _cancelledCallback(generateInformCallback(closedCallback)) { init(text); @@ -219,7 +220,7 @@ void ConfirmBox::setMaxLineCount(int count) { } void ConfirmBox::textUpdated() { - _textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right(); + _textWidth = st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right(); _textHeight = _text.countHeight(_textWidth); if (_maxLineCount > 0) { accumulate_min(_textHeight, _maxLineCount * st::boxLabelStyle.lineHeight); @@ -323,7 +324,7 @@ InformBox::InformBox(QWidget*, const TextWithEntities &text, const QString &done MaxInviteBox::MaxInviteBox(QWidget*, not_null channel) : BoxContent() , _channel(channel) -, _text(st::boxLabelStyle, tr::lng_participant_invite_sorry(tr::now, lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()) { +, _text(st::boxLabelStyle, tr::lng_participant_invite_sorry(tr::now, lt_count, Global::ChatSizeMax()), _confirmBoxTextOptions, st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right()) { } void MaxInviteBox::prepare() { @@ -331,7 +332,7 @@ void MaxInviteBox::prepare() { addButton(tr::lng_box_ok(), [=] { closeBox(); }); - _textWidth = st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right(); + _textWidth = st::boxWidth - st::boxPadding.left() - st::defaultBox.buttonPadding.right(); _textHeight = qMin(_text.countHeight(_textWidth), 16 * st::boxLabelStyle.lineHeight); setDimensions(st::boxWidth, st::boxPadding.top() + _textHeight + st::boxTextFont->height + st::boxTextFont->height * 2 + st::newGroupLinkPadding.bottom()); diff --git a/Telegram/SourceFiles/boxes/confirm_box.h b/Telegram/SourceFiles/boxes/confirm_box.h index ce31a2078..07c4971c0 100644 --- a/Telegram/SourceFiles/boxes/confirm_box.h +++ b/Telegram/SourceFiles/boxes/confirm_box.h @@ -20,7 +20,7 @@ class EmptyUserpic; } // namespace Ui class InformBox; -class ConfirmBox : public BoxContent, public ClickHandlerHost { +class ConfirmBox : public Ui::BoxContent, public ClickHandlerHost { public: ConfirmBox(QWidget*, const QString &text, FnMut confirmedCallback = FnMut(), FnMut cancelledCallback = FnMut()); ConfirmBox(QWidget*, const QString &text, const QString &confirmText, FnMut confirmedCallback = FnMut(), FnMut cancelledCallback = FnMut()); @@ -95,7 +95,7 @@ public: }; -class MaxInviteBox : public BoxContent, private base::Subscriber { +class MaxInviteBox : public Ui::BoxContent, private base::Subscriber { public: MaxInviteBox(QWidget*, not_null channel); @@ -123,7 +123,7 @@ private: }; -class PinMessageBox : public BoxContent, public RPCSender { +class PinMessageBox : public Ui::BoxContent, public RPCSender { public: PinMessageBox(QWidget*, not_null peer, MsgId msgId); @@ -148,7 +148,7 @@ private: }; -class DeleteMessagesBox : public BoxContent, public RPCSender { +class DeleteMessagesBox : public Ui::BoxContent, public RPCSender { public: DeleteMessagesBox( QWidget*, @@ -202,7 +202,7 @@ private: }; class ConfirmInviteBox - : public BoxContent + : public Ui::BoxContent , public RPCSender , private base::Subscriber { public: @@ -238,7 +238,7 @@ private: }; -class ConfirmDontWarnBox : public BoxContent { +class ConfirmDontWarnBox : public Ui::BoxContent { public: ConfirmDontWarnBox( QWidget*, diff --git a/Telegram/SourceFiles/boxes/confirm_phone_box.cpp b/Telegram/SourceFiles/boxes/confirm_phone_box.cpp index ebd3810d6..8e4b8bf48 100644 --- a/Telegram/SourceFiles/boxes/confirm_phone_box.cpp +++ b/Telegram/SourceFiles/boxes/confirm_phone_box.cpp @@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/confirm_phone_box.h" -#include "styles/style_boxes.h" #include "boxes/confirm_box.h" #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" @@ -15,11 +14,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "core/click_handler_types.h" // UrlClickHandler #include "base/qthelp_url.h" // qthelp::url_encode -#include "platform/platform_info.h" // Platform::SystemVersionPretty +#include "base/platform/base_platform_info.h" #include "mainwidget.h" #include "numbers.h" #include "app.h" #include "lang/lang_keys.h" +#include "styles/style_layers.h" +#include "styles/style_boxes.h" namespace { @@ -54,7 +55,7 @@ Locale: ") + Platform::SystemLanguage(); } // namespace void ShowPhoneBannedError(const QString &phone) { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto close = [=] { if (*box) { (*box)->closeBox(); diff --git a/Telegram/SourceFiles/boxes/confirm_phone_box.h b/Telegram/SourceFiles/boxes/confirm_phone_box.h index 17aedd96c..d2963f960 100644 --- a/Telegram/SourceFiles/boxes/confirm_phone_box.h +++ b/Telegram/SourceFiles/boxes/confirm_phone_box.h @@ -85,7 +85,7 @@ private: }; -class ConfirmPhoneBox : public BoxContent, public RPCSender { +class ConfirmPhoneBox : public Ui::BoxContent, public RPCSender { public: static void start(const QString &phone, const QString &hash); diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp index ad9235dbf..e67b894c3 100644 --- a/Telegram/SourceFiles/boxes/connection_box.cpp +++ b/Telegram/SourceFiles/boxes/connection_box.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "storage/localstorage.h" #include "base/qthelp_url.h" +#include "base/call_delayed.h" #include "core/application.h" #include "main/main_account.h" #include "ui/widgets/checkbox.h" @@ -25,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/radial_animation.h" #include "ui/text_options.h" #include "facades.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_chat_helpers.h" #include "styles/style_info.h" @@ -134,7 +136,7 @@ private: }; -class ProxiesBox : public BoxContent { +class ProxiesBox : public Ui::BoxContent { public: using View = ProxiesBoxController::ItemView; @@ -166,7 +168,7 @@ private: }; -class ProxyBox : public BoxContent { +class ProxyBox : public Ui::BoxContent { public: ProxyBox( QWidget*, @@ -1029,7 +1031,7 @@ void ProxiesBoxController::ShowApplyConfirmation( if (const auto strong = box->data()) { strong->closeBox(); } - }), LayerOption::KeepOther); + }), Ui::LayerOption::KeepOther); } else { Ui::show(Box( (proxy.status() == ProxyData::Status::Unsupported @@ -1134,14 +1136,14 @@ void ProxiesBoxController::setupChecker(int id, const Checker &checker) { pointer->connect(pointer, &Connection::error, failed); } -object_ptr ProxiesBoxController::CreateOwningBox() { +object_ptr ProxiesBoxController::CreateOwningBox() { auto controller = std::make_unique(); auto box = controller->create(); Ui::AttachAsChild(box, std::move(controller)); return box; } -object_ptr ProxiesBoxController::create() { +object_ptr ProxiesBoxController::create() { auto result = Box(this); for (const auto &item : _list) { updateView(item); @@ -1249,7 +1251,7 @@ void ProxiesBoxController::setDeleted(int id, bool deleted) { updateView(*item); } -object_ptr ProxiesBoxController::editItemBox(int id) { +object_ptr ProxiesBoxController::editItemBox(int id) { return Box(findById(id)->data, [=](const ProxyData &result) { auto i = findById(id); auto j = ranges::find( @@ -1300,7 +1302,7 @@ void ProxiesBoxController::replaceItemValue( saveDelayed(); } -object_ptr ProxiesBoxController::addNewItemBox() { +object_ptr ProxiesBoxController::addNewItemBox() { return Box(ProxyData(), [=](const ProxyData &result) { auto j = ranges::find( _list, @@ -1436,7 +1438,7 @@ void ProxiesBoxController::share(const ProxyData &proxy) { ProxiesBoxController::~ProxiesBoxController() { if (_saveTimer.isActive()) { - App::CallDelayed( + base::call_delayed( kSaveSettingsDelayedTimeout, QCoreApplication::instance(), [] { Local::writeSettings(); }); diff --git a/Telegram/SourceFiles/boxes/connection_box.h b/Telegram/SourceFiles/boxes/connection_box.h index 66b0eaa80..37e7040f2 100644 --- a/Telegram/SourceFiles/boxes/connection_box.h +++ b/Telegram/SourceFiles/boxes/connection_box.h @@ -7,11 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "boxes/abstract_box.h" #include "base/timer.h" +#include "base/object_ptr.h" #include "mtproto/connection_abstract.h" namespace Ui { +class BoxContent; class InputField; class PortInput; class PasswordInput; @@ -32,8 +33,8 @@ public: Type type, const QMap &fields); - static object_ptr CreateOwningBox(); - object_ptr create(); + static object_ptr CreateOwningBox(); + object_ptr create(); enum class ItemState { Connecting, @@ -60,8 +61,8 @@ public: void restoreItem(int id); void shareItem(int id); void applyItem(int id); - object_ptr editItemBox(int id); - object_ptr addNewItemBox(); + object_ptr editItemBox(int id); + object_ptr addNewItemBox(); bool setProxySettings(ProxyData::Settings value); void setProxyForCalls(bool enabled); void setTryIPv6(bool enabled); diff --git a/Telegram/SourceFiles/boxes/create_poll_box.cpp b/Telegram/SourceFiles/boxes/create_poll_box.cpp index 617388bdc..ad9a1db47 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.cpp +++ b/Telegram/SourceFiles/boxes/create_poll_box.cpp @@ -17,13 +17,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "main/main_session.h" -#include "core/event_filter.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/message_field.h" #include "history/view/history_view_schedule_box.h" #include "settings/settings_common.h" #include "base/unique_qptr.h" -#include "facades.h" +#include "base/event_filter.h" +#include "base/call_delayed.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_settings.h" @@ -399,7 +400,7 @@ void Options::Option::destroy(FnMut done) { return; } _field->hide(anim::type::normal); - App::CallDelayed( + base::call_delayed( st::slideWrapDuration * 2, _field.get(), std::move(done)); @@ -521,14 +522,14 @@ void Options::addEmptyOption() { QObject::connect(field, &Ui::InputField::focused, [=] { _scrollToWidget.fire_copy(field); }); - Core::InstallEventFilter(field, [=](not_null event) { + base::install_event_filter(field, [=](not_null event) { if (event->type() != QEvent::KeyPress || !field->getLastText().isEmpty()) { - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; } const auto key = static_cast(event.get())->key(); if (key != Qt::Key_Backspace) { - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; } const auto index = findField(field); @@ -537,7 +538,7 @@ void Options::addEmptyOption() { } else { _backspaceInFront.fire({}); } - return Core::EventFilter::Result::Cancel; + return base::EventFilterResult::Cancel; }); _list.back().removeClicks( @@ -724,7 +725,7 @@ object_ptr CreatePollBox::setupContent() { this, SendMenuType::Scheduled, send), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }; const auto updateValid = [=] { valid->fire(isValidQuestion() && options->isValid()); diff --git a/Telegram/SourceFiles/boxes/create_poll_box.h b/Telegram/SourceFiles/boxes/create_poll_box.h index cc38e5af3..57b7fa789 100644 --- a/Telegram/SourceFiles/boxes/create_poll_box.h +++ b/Telegram/SourceFiles/boxes/create_poll_box.h @@ -21,7 +21,7 @@ namespace Main { class Session; } // namespace Main -class CreatePollBox : public BoxContent { +class CreatePollBox : public Ui::BoxContent { public: struct Result { PollData poll; diff --git a/Telegram/SourceFiles/boxes/download_path_box.cpp b/Telegram/SourceFiles/boxes/download_path_box.cpp index 073606cf0..a369317da 100644 --- a/Telegram/SourceFiles/boxes/download_path_box.cpp +++ b/Telegram/SourceFiles/boxes/download_path_box.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "platform/platform_specific.h" #include "facades.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" DownloadPathBox::DownloadPathBox(QWidget *parent) diff --git a/Telegram/SourceFiles/boxes/download_path_box.h b/Telegram/SourceFiles/boxes/download_path_box.h index e092ff0fb..4ff63efce 100644 --- a/Telegram/SourceFiles/boxes/download_path_box.h +++ b/Telegram/SourceFiles/boxes/download_path_box.h @@ -18,7 +18,7 @@ class Radioenum; class LinkButton; } // namespace Ui -class DownloadPathBox : public BoxContent { +class DownloadPathBox : public Ui::BoxContent { public: DownloadPathBox(QWidget *parent); diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 36868c467..306213f25 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/message_field.h" #include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_selector.h" -#include "core/event_filter.h" +#include "base/event_filter.h" #include "core/file_utilities.h" #include "core/mime_type.h" #include "data/data_document.h" @@ -29,9 +29,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "layout.h" #include "media/clip/media_clip_reader.h" #include "storage/storage_media_prepare.h" -#include "styles/style_boxes.h" -#include "styles/style_chat_helpers.h" -#include "styles/style_history.h" #include "ui/image/image.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/checkbox.h" @@ -42,6 +39,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "confirm_box.h" #include "facades.h" #include "app.h" +#include "styles/style_layers.h" +#include "styles/style_boxes.h" +#include "styles/style_chat_helpers.h" +#include "styles/style_history.h" #include @@ -267,6 +268,8 @@ EditCaptionBox::EditCaptionBox( _field->setEditLinkCallback( DefaultEditLinkCallback(&_controller->session(), _field)); + InitSpellchecker(&_controller->session(), _field); + auto r = object_ptr>( this, object_ptr( @@ -493,7 +496,7 @@ void EditCaptionBox::createEditMediaButton() { if (mimeType == qstr("image/webp")) { Ui::show( Box(tr::lng_edit_media_invalid_file(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return false; } return true; @@ -521,7 +524,7 @@ void EditCaptionBox::createEditMediaButton() { || file->type == Storage::PreparedFile::AlbumType::None) { Ui::show( Box(tr::lng_edit_media_album_error(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } @@ -551,7 +554,7 @@ void EditCaptionBox::createEditMediaButton() { if (!valid) { Ui::show( Box(tr::lng_edit_media_album_error(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } @@ -687,7 +690,7 @@ bool EditCaptionBox::fileFromClipboard(not_null data) { && _isAlbum) { Ui::show( Box(tr::lng_edit_media_album_error(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return false; } @@ -724,9 +727,9 @@ void EditCaptionBox::setupEmojiPanel() { const auto filterCallback = [=](not_null event) { emojiFilterForGeometry(event); - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; }; - _emojiFilter.reset(Core::InstallEventFilter(container, filterCallback)); + _emojiFilter.reset(base::install_event_filter(container, filterCallback)); _emojiToggle.create(this, st::boxAttachEmoji); _emojiToggle->installEventFilter(_emojiPanel); @@ -753,7 +756,7 @@ void EditCaptionBox::updateBoxSize() { } int EditCaptionBox::errorTopSkip() const { - return (st::boxButtonPadding.top() / 2); + return (st::defaultBox.buttonPadding.top() / 2); } void EditCaptionBox::paintEvent(QPaintEvent *e) { diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.h b/Telegram/SourceFiles/boxes/edit_caption_box.h index 5dde6f010..14e7cd5c3 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.h +++ b/Telegram/SourceFiles/boxes/edit_caption_box.h @@ -36,7 +36,7 @@ class SessionController; } // namespace Window class EditCaptionBox - : public BoxContent + : public Ui::BoxContent , public RPCSender , private base::Subscriber { public: diff --git a/Telegram/SourceFiles/boxes/edit_color_box.cpp b/Telegram/SourceFiles/boxes/edit_color_box.cpp index fae3a3574..b421aa800 100644 --- a/Telegram/SourceFiles/boxes/edit_color_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_color_box.cpp @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/shadow.h" #include "ui/widgets/input_fields.h" #include "ui/ui_utility.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "app.h" #include "styles/style_boxes.h" #include "styles/style_mediaview.h" diff --git a/Telegram/SourceFiles/boxes/edit_color_box.h b/Telegram/SourceFiles/boxes/edit_color_box.h index 46b8ccf20..28ad8cc5a 100644 --- a/Telegram/SourceFiles/boxes/edit_color_box.h +++ b/Telegram/SourceFiles/boxes/edit_color_box.h @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" -class EditColorBox : public BoxContent, private base::Subscriber { +class EditColorBox : public Ui::BoxContent, private base::Subscriber { public: enum class Mode { RGBA, diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index 1578716bd..03667da4e 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -14,7 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/vertical_layout.h" #include "history/history.h" #include "boxes/peer_list_controllers.h" -#include "info/profile/info_profile_button.h" #include "settings/settings_common.h" #include "settings/settings_privacy_security.h" #include "calls/calls_instance.h" @@ -27,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "window/window_session_controller.h" #include "styles/style_settings.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" namespace { @@ -170,7 +169,7 @@ void EditPrivacyBox::editExceptions( }; Ui::show( Box(std::move(controller), std::move(initBox)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } QVector EditPrivacyBox::collectResult() { diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.h b/Telegram/SourceFiles/boxes/edit_privacy_box.h index 80efbdbc0..1060157fd 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.h +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.h @@ -23,6 +23,10 @@ template class SlideWrap; } // namespace Ui +namespace Window { +class SessionController; +} // namespace Window + class EditPrivacyBox; class EditPrivacyController { @@ -96,7 +100,7 @@ private: }; -class EditPrivacyBox : public BoxContent, private MTP::Sender { +class EditPrivacyBox : public Ui::BoxContent, private MTP::Sender { public: using Value = ApiWrap::Privacy; using Option = Value::Option; diff --git a/Telegram/SourceFiles/boxes/generic_box.cpp b/Telegram/SourceFiles/boxes/generic_box.cpp deleted file mode 100644 index 0e49abcbb..000000000 --- a/Telegram/SourceFiles/boxes/generic_box.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "boxes/generic_box.h" - -#include "ui/wrap/vertical_layout.h" -#include "ui/wrap/padding_wrap.h" -#include "ui/wrap/wrap.h" -#include "styles/style_boxes.h" - -void GenericBox::prepare() { - _init(this); - - auto wrap = object_ptr(this, std::move(_content)); - setDimensionsToContent(_width ? _width : st::boxWidth, wrap.data()); - setInnerWidget(std::move(wrap)); -} - -void GenericBox::addSkip(int height) { - addRow(object_ptr(this, height)); -} diff --git a/Telegram/SourceFiles/boxes/generic_box.h b/Telegram/SourceFiles/boxes/generic_box.h deleted file mode 100644 index 8c02ccca6..000000000 --- a/Telegram/SourceFiles/boxes/generic_box.h +++ /dev/null @@ -1,154 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "boxes/abstract_box.h" -#include "ui/wrap/vertical_layout.h" - -#include - -namespace st { -extern const style::margins &boxRowPadding; -} // namespace st - -class GenericBox : public BoxContent { -public: - // InitMethod::operator()(not_null box, InitArgs...) - // init(box, args...) - template < - typename InitMethod, - typename ...InitArgs, - typename = decltype(std::declval>()( - std::declval>(), - std::declval>()...))> - GenericBox( - QWidget*, - InitMethod &&init, - InitArgs &&...args); - - void setWidth(int width) { - _width = width; - } - void setFocusCallback(Fn callback) { - _focus = callback; - } - - int rowsCount() const { - return _content->count(); - } - - template < - typename Widget, - typename = std::enable_if_t< - std::is_base_of_v>> - Widget *insertRow( - int atPosition, - object_ptr &&child, - const style::margins &margin = st::boxRowPadding) { - return _content->insert( - atPosition, - std::move(child), - margin); - } - - template < - typename Widget, - typename = std::enable_if_t< - std::is_base_of_v>> - Widget *addRow( - object_ptr &&child, - const style::margins &margin = st::boxRowPadding) { - return _content->add(std::move(child), margin); - } - - void addSkip(int height); - - void setInnerFocus() override { - if (_focus) { - _focus(); - } - } - -protected: - void prepare() override; - -private: - template - struct Initer { - template < - typename OtherMethod, - typename ...OtherArgs, - typename = std::enable_if_t< - std::is_constructible_v>> - Initer(OtherMethod &&method, OtherArgs &&...args); - - void operator()(not_null box); - - template - void call( - not_null box, - std::index_sequence); - - InitMethod method; - std::tuple args; - }; - - template - auto MakeIniter(InitMethod &&method, InitArgs &&...args) - -> Initer, std::decay_t...>; - - FnMut)> _init; - Fn _focus; - object_ptr _content; - int _width = 0; - -}; - -template -template -GenericBox::Initer::Initer( - OtherMethod &&method, - OtherArgs &&...args) -: method(std::forward(method)) -, args(std::forward(args)...) { -} - -template -inline void GenericBox::Initer::operator()( - not_null box) { - call(box, std::make_index_sequence()); -} - -template -template -inline void GenericBox::Initer::call( - not_null box, - std::index_sequence) { - std::invoke(method, box, std::get(std::move(args))...); -} - -template -inline auto GenericBox::MakeIniter(InitMethod &&method, InitArgs &&...args) --> Initer, std::decay_t...> { - return { - std::forward(method), - std::forward(args)... - }; -} - -template -inline GenericBox::GenericBox( - QWidget*, - InitMethod &&init, - InitArgs &&...args) -: _init( - MakeIniter( - std::forward(init), - std::forward(args)...)) -, _content(this) { -} diff --git a/Telegram/SourceFiles/boxes/language_box.cpp b/Telegram/SourceFiles/boxes/language_box.cpp index c85399cbf..135186d91 100644 --- a/Telegram/SourceFiles/boxes/language_box.cpp +++ b/Telegram/SourceFiles/boxes/language_box.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/multi_select.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/dropdown_menu.h" +#include "ui/widgets/box_content_divider.h" #include "ui/text/text_entity.h" #include "ui/wrap/vertical_layout.h" #include "ui/wrap/slide_wrap.h" @@ -27,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "lang/lang_instance.h" #include "lang/lang_cloud_manager.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_info.h" #include "styles/style_passport.h" @@ -334,8 +336,8 @@ void Rows::mousePressEvent(QMouseEvent *e) { QRect Rows::menuToggleArea() const { const auto size = st::topBarSearch.width; const auto top = (DefaultRowHeight() - size) / 2; - const auto skip = st::boxLayerScroll.width - - st::boxLayerScroll.deltax + const auto skip = st::boxScroll.width + - st::boxScroll.deltax + top; const auto left = width() - skip - size; return QRect(left, top, size, size); @@ -896,9 +898,9 @@ void Content::setupContent( }; const auto main = add(recent, false); const auto divider = content->add( - object_ptr>( + object_ptr>( content, - object_ptr(content))); + object_ptr(content))); const auto other = add(official, true); Ui::ResizeFitChild(this, content); @@ -1070,7 +1072,7 @@ void LanguageBox::prepare() { const auto [recent, official] = PrepareLists(); const auto inner = setInnerWidget( object_ptr(this, recent, official), - st::boxLayerScroll, + st::boxScroll, select->height()); inner->resizeToWidth(st::boxWidth); diff --git a/Telegram/SourceFiles/boxes/language_box.h b/Telegram/SourceFiles/boxes/language_box.h index 4cc3dd56b..92eeedd40 100644 --- a/Telegram/SourceFiles/boxes/language_box.h +++ b/Telegram/SourceFiles/boxes/language_box.h @@ -16,7 +16,7 @@ class MultiSelect; struct ScrollToRequest; } // namespace Ui -class LanguageBox : public BoxContent { +class LanguageBox : public Ui::BoxContent { public: LanguageBox(QWidget*) { } diff --git a/Telegram/SourceFiles/boxes/local_storage_box.cpp b/Telegram/SourceFiles/boxes/local_storage_box.cpp index 047dcc2cb..b850b4005 100644 --- a/Telegram/SourceFiles/boxes/local_storage_box.cpp +++ b/Telegram/SourceFiles/boxes/local_storage_box.cpp @@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "main/main_session.h" #include "layout.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" namespace { @@ -230,7 +231,7 @@ int LocalStorageBox::Row::resizeGetHeight(int newWidth) { newWidth); } _clear->moveToRight( - st::boxLayerButtonPadding.right(), + st::layerBox.buttonPadding.right(), (height - _clear->height()) / 2, newWidth); return height; diff --git a/Telegram/SourceFiles/boxes/local_storage_box.h b/Telegram/SourceFiles/boxes/local_storage_box.h index f00d83958..8f1d2401f 100644 --- a/Telegram/SourceFiles/boxes/local_storage_box.h +++ b/Telegram/SourceFiles/boxes/local_storage_box.h @@ -28,7 +28,7 @@ class LabelSimple; class MediaSlider; } // namespace Ui -class LocalStorageBox : public BoxContent { +class LocalStorageBox : public Ui::BoxContent { struct CreateTag { }; diff --git a/Telegram/SourceFiles/boxes/mute_settings_box.cpp b/Telegram/SourceFiles/boxes/mute_settings_box.cpp index cd0d46cf9..fb8b67b09 100644 --- a/Telegram/SourceFiles/boxes/mute_settings_box.cpp +++ b/Telegram/SourceFiles/boxes/mute_settings_box.cpp @@ -15,6 +15,7 @@ Copyright (C) 2017, Nicholas Guriev #include "ui/widgets/checkbox.h" #include "ui/widgets/labels.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" namespace { diff --git a/Telegram/SourceFiles/boxes/mute_settings_box.h b/Telegram/SourceFiles/boxes/mute_settings_box.h index fe5c1efc6..d91692410 100644 --- a/Telegram/SourceFiles/boxes/mute_settings_box.h +++ b/Telegram/SourceFiles/boxes/mute_settings_box.h @@ -12,7 +12,7 @@ Copyright (C) 2017, Nicholas Guriev /* This class implements a dialog-box with radio-buttons for pick duration of * turning off notifications from a chat. The widget is opened by a context menu * in the left list of dialogues. */ -class MuteSettingsBox : public BoxContent { +class MuteSettingsBox : public Ui::BoxContent { public: MuteSettingsBox(QWidget *parent, not_null peer); diff --git a/Telegram/SourceFiles/boxes/passcode_box.cpp b/Telegram/SourceFiles/boxes/passcode_box.cpp index ddc9e8de6..19f3d2f2e 100644 --- a/Telegram/SourceFiles/boxes/passcode_box.cpp +++ b/Telegram/SourceFiles/boxes/passcode_box.cpp @@ -22,8 +22,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "passport/passport_encryption.h" #include "passport/passport_panel_edit_contact.h" #include "facades.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" #include "styles/style_passport.h" +#include "styles/style_boxes.h" namespace { @@ -375,7 +376,7 @@ void PasscodeBox::validateEmail( Lang::Hard::EmailConfirmationExpired()); weak->getDelegate()->show( std::move(box), - LayerOption::CloseOther); + Ui::LayerOption::CloseOther); } } else { errors->fire(Lang::Hard::ServerError()); @@ -531,7 +532,7 @@ void PasscodeBox::submitOnlyCheckCloudPassword(const QString &oldPassword) { if (_cloudFields.turningOff && _cloudFields.notEmptyPassport) { Assert(!_cloudFields.customCheckCallback); - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto confirmed = [=] { send(); if (*box) { @@ -738,7 +739,7 @@ void PasscodeBox::changeCloudPassword( } void PasscodeBox::suggestSecretReset(const QString &newPassword) { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto resetSecretAndSave = [=] { checkPasswordHash([=](const Core::CloudPasswordResult &check) { resetSecret(check, newPassword, [=] { @@ -990,7 +991,7 @@ void RecoverBox::submit() { rpcFail(&RecoverBox::codeSubmitFail)); }); if (_notEmptyPassport) { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto confirmed = [=] { send(); if (*box) { @@ -1019,7 +1020,7 @@ void RecoverBox::codeSubmitDone( _passwordCleared.fire({}); getDelegate()->show( Box(tr::lng_cloud_password_removed(tr::now)), - LayerOption::CloseOther); + Ui::LayerOption::CloseOther); } bool RecoverBox::codeSubmitFail(const RPCError &error) { @@ -1039,7 +1040,7 @@ bool RecoverBox::codeSubmitFail(const RPCError &error) { _passwordCleared.fire({}); getDelegate()->show( Box(tr::lng_cloud_password_removed(tr::now)), - LayerOption::CloseOther); + Ui::LayerOption::CloseOther); return true; } else if (err == qstr("PASSWORD_RECOVERY_NA")) { closeBox(); @@ -1070,7 +1071,7 @@ RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern) { const auto errors = std::make_shared>(); const auto resent = std::make_shared>(); const auto requestId = std::make_shared(0); - const auto weak = std::make_shared>(); + const auto weak = std::make_shared>(); const auto reloads = std::make_shared>(); const auto cancels = std::make_shared>(); @@ -1084,7 +1085,7 @@ RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern) { if (*weak) { (*weak)->getDelegate()->show( Box(tr::lng_cloud_password_was_set(tr::now)), - LayerOption::CloseOther); + Ui::LayerOption::CloseOther); } }; const auto fail = [=](const RPCError &error) { @@ -1105,7 +1106,7 @@ RecoveryEmailValidation ConfirmRecoveryEmail(const QString &pattern) { Lang::Hard::EmailConfirmationExpired()); (*weak)->getDelegate()->show( std::move(box), - LayerOption::CloseOther); + Ui::LayerOption::CloseOther); } } else { errors->fire(Lang::Hard::ServerError()); diff --git a/Telegram/SourceFiles/boxes/passcode_box.h b/Telegram/SourceFiles/boxes/passcode_box.h index 7c907d523..a8ad5ea8c 100644 --- a/Telegram/SourceFiles/boxes/passcode_box.h +++ b/Telegram/SourceFiles/boxes/passcode_box.h @@ -25,7 +25,7 @@ namespace Core { struct CloudPasswordState; } // namespace Core -class PasscodeBox : public BoxContent, private MTP::Sender { +class PasscodeBox : public Ui::BoxContent, private MTP::Sender { public: PasscodeBox(QWidget*, not_null session, bool turningOff); @@ -133,7 +133,7 @@ private: QString _pattern; - QPointer _replacedBy; + QPointer _replacedBy; bool _turningOff = false; bool _cloudPwd = false; CloudFields _cloudFields; @@ -163,7 +163,7 @@ private: }; -class RecoverBox : public BoxContent, public RPCSender { +class RecoverBox : public Ui::BoxContent, public RPCSender { public: RecoverBox(QWidget*, const QString &pattern, bool notEmptyPassport); @@ -201,7 +201,7 @@ private: }; struct RecoveryEmailValidation { - object_ptr box; + object_ptr box; rpl::producer<> reloadRequests; rpl::producer<> cancelRequests; }; diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index 361222e1d..33721e8e4 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -7,10 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/peer_list_box.h" -#include -#include "styles/style_boxes.h" -#include "styles/style_dialogs.h" -#include "styles/style_widgets.h" #include "main/main_session.h" #include "mainwidget.h" #include "ui/widgets/multi_select.h" @@ -31,6 +27,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "base/unixtime.h" #include "window/themes/window_theme.h" +#include "styles/style_layers.h" +#include "styles/style_boxes.h" +#include "styles/style_dialogs.h" +#include "styles/style_widgets.h" + +#include auto PaintUserpicCallback( not_null peer, @@ -109,7 +111,7 @@ void PeerListBox::prepare() { this, _controller.get(), st::peerListBox), - st::boxLayerScroll)); + st::boxScroll)); content()->resizeToWidth(_controller->contentWidth()); _controller->setDelegate(this); diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index 636e789d8..eb99522dd 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -760,7 +760,7 @@ private: }; class PeerListBox - : public BoxContent + : public Ui::BoxContent , public PeerListContentDelegate { public: PeerListBox( diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index bad2a093e..190c2f372 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -464,7 +464,7 @@ void AddBotToGroupBoxController::shareBotGame(not_null chat) { }(); Ui::show( Box(confirmText, std::move(send)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void AddBotToGroupBoxController::addBotToGroup(not_null chat) { @@ -472,7 +472,7 @@ void AddBotToGroupBoxController::addBotToGroup(not_null chat) { if (!megagroup->canAddMembers()) { Ui::show( Box(tr::lng_error_cant_add_member(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } @@ -482,7 +482,7 @@ void AddBotToGroupBoxController::addBotToGroup(not_null chat) { auto confirmText = tr::lng_bot_sure_invite(tr::now, lt_group, chat->name); Ui::show( Box(confirmText, send), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } auto AddBotToGroupBoxController::createRow(not_null history) diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp index 0ae8fadbf..08c95bc72 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp @@ -98,13 +98,13 @@ void AddParticipantsBoxController::rowClicked(not_null row) { if (!_peer->isMegagroup()) { Ui::show( Box(_peer->asChannel()), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } } else if (count >= Global::ChatSizeMax() && count < Global::MegagroupSizeMax()) { Ui::show( Box(tr::lng_profile_add_more_after_create(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } } @@ -210,7 +210,7 @@ void AddParticipantsBoxController::Start( Box( std::move(controller), std::move(initBox)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void AddParticipantsBoxController::Start( @@ -251,7 +251,7 @@ void AddParticipantsBoxController::Start( Box( std::move(controller), std::move(initBox)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void AddParticipantsBoxController::Start( @@ -517,19 +517,19 @@ void AddSpecialBoxController::showAdmin( Box( tr::lng_sure_add_admin_unremove(tr::now), showAdminSure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else { Ui::show(Box( tr::lng_error_cant_add_admin_unban(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else { Ui::show(Box( tr::lng_error_cant_add_admin_invite(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else if (_additional.restrictedRights(user).has_value()) { @@ -540,13 +540,13 @@ void AddSpecialBoxController::showAdmin( Box( tr::lng_sure_add_admin_unremove(tr::now), showAdminSure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else { Ui::show(Box( tr::lng_error_cant_add_admin_unban(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else if (_additional.isExternal(user)) { @@ -560,13 +560,13 @@ void AddSpecialBoxController::showAdmin( Box( text, showAdminSure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else { Ui::show( Box(tr::lng_error_cant_add_admin_invite(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } @@ -597,7 +597,7 @@ void AddSpecialBoxController::showAdmin( }); box->setSaveCallback(SaveAdminCallback(_peer, user, done, fail)); } - _editParticipantBox = Ui::show(std::move(box), LayerOption::KeepOther); + _editParticipantBox = Ui::show(std::move(box), Ui::LayerOption::KeepOther); } void AddSpecialBoxController::editAdminDone( @@ -669,13 +669,13 @@ void AddSpecialBoxController::showRestricted( Box( tr::lng_sure_ban_admin(tr::now), showRestrictedSure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else { Ui::show( Box(tr::lng_error_cant_ban_admin(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } @@ -704,7 +704,7 @@ void AddSpecialBoxController::showRestricted( box->setSaveCallback( SaveRestrictedCallback(_peer, user, done, fail)); } - _editParticipantBox = Ui::show(std::move(box), LayerOption::KeepOther); + _editParticipantBox = Ui::show(std::move(box), Ui::LayerOption::KeepOther); } void AddSpecialBoxController::editRestrictedDone( @@ -759,13 +759,13 @@ void AddSpecialBoxController::kickUser( Box( tr::lng_sure_ban_admin(tr::now), kickUserSure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } else { Ui::show( Box(tr::lng_error_cant_ban_admin(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } } @@ -780,7 +780,7 @@ void AddSpecialBoxController::kickUser( user->name); _editBox = Ui::show( Box(text, kickUserSure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.h b/Telegram/SourceFiles/boxes/peers/add_participants_box.h index b1fab5a43..d15f474e8 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.h @@ -126,8 +126,8 @@ private: bool _allLoaded = false; ParticipantsAdditionalData _additional; std::unique_ptr _onlineSorter; - BoxPointer _editBox; - QPointer _editParticipantBox; + Ui::BoxPointer _editBox; + QPointer _editParticipantBox; AdminDoneCallback _adminDoneCallback; BannedDoneCallback _bannedDoneCallback; diff --git a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp index 5d2ce7e03..c7138e4af 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_contact_box.cpp @@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/peers/edit_contact_box.h" -#include "boxes/generic_box.h" #include "data/data_user.h" #include "data/data_session.h" #include "ui/wrap/vertical_layout.h" @@ -21,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "apiwrap.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_info.h" @@ -36,7 +36,7 @@ QString UserPhone(not_null user) { } void SendRequest( - QPointer box, + QPointer box, not_null user, bool sharePhone, const QString &first, @@ -82,7 +82,7 @@ void SendRequest( class Controller { public: Controller( - not_null box, + not_null box, not_null window, not_null user); @@ -99,7 +99,7 @@ private: not_null last, bool inverted); - not_null _box; + not_null _box; not_null _window; not_null _user; Ui::Checkbox *_sharePhone = nullptr; @@ -110,7 +110,7 @@ private: }; Controller::Controller( - not_null box, + not_null box, not_null window, not_null user) : _box(box) @@ -265,7 +265,7 @@ void Controller::setupSharePhoneNumber() { } // namespace void EditContactBox( - not_null box, + not_null box, not_null window, not_null user) { box->lifetime().make_state(box, window, user)->prepare(); diff --git a/Telegram/SourceFiles/boxes/peers/edit_contact_box.h b/Telegram/SourceFiles/boxes/peers/edit_contact_box.h index da19edcf4..3f3e2c776 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_contact_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_contact_box.h @@ -7,14 +7,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "ui/layers/generic_box.h" + class UserData; -class GenericBox; namespace Window { class Controller; } // namespace Window void EditContactBox( - not_null box, + not_null box, not_null window, not_null user); diff --git a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp index 2b059460c..d490a38f4 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp @@ -11,15 +11,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_chat.h" #include "ui/widgets/labels.h" +#include "ui/widgets/buttons.h" #include "ui/wrap/vertical_layout.h" #include "ui/text/text_utilities.h" // Ui::Text::ToUpper -#include "info/profile/info_profile_button.h" #include "boxes/peer_list_box.h" #include "boxes/confirm_box.h" #include "boxes/add_contact_box.h" #include "apiwrap.h" #include "facades.h" #include "main/main_session.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_info.h" @@ -145,7 +146,7 @@ void Controller::choose(not_null chat) { Ui::Text::RichLangValue)); } } - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto sure = [=] { if (*box) { (*box)->closeBox(); @@ -158,7 +159,7 @@ void Controller::choose(not_null chat) { text, tr::lng_manage_discussion_group_link(tr::now), sure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void Controller::choose(not_null chat) { @@ -177,7 +178,7 @@ void Controller::choose(not_null chat) { text.append(tr::lng_manage_discussion_group_warning( tr::now, Ui::Text::RichLangValue)); - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto sure = [=] { if (*box) { (*box)->closeBox(); @@ -193,7 +194,7 @@ void Controller::choose(not_null chat) { text, tr::lng_manage_discussion_group_link(tr::now), sure), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } object_ptr SetupAbout( @@ -243,7 +244,7 @@ object_ptr SetupCreateGroup( Fn callback) { Expects(channel->isBroadcast()); - auto result = object_ptr( + auto result = object_ptr( parent, tr::lng_manage_discussion_group_create( ) | Ui::Text::ToUpper(), @@ -256,7 +257,7 @@ object_ptr SetupCreateGroup( GroupInfoBox::Type::Megagroup, channel->name + " Chat", guarded), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }); return result; } @@ -265,7 +266,7 @@ object_ptr SetupUnlink( not_null parent, not_null channel, Fn callback) { - auto result = object_ptr( + auto result = object_ptr( parent, (channel->isBroadcast() ? tr::lng_manage_discussion_group_unlink @@ -277,7 +278,7 @@ object_ptr SetupUnlink( return result; } -object_ptr EditLinkedChatBox( +object_ptr EditLinkedChatBox( not_null navigation, not_null channel, ChannelData *chat, @@ -324,7 +325,7 @@ object_ptr EditLinkedChatBox( } // namespace -object_ptr EditLinkedChatBox( +object_ptr EditLinkedChatBox( not_null navigation, not_null channel, std::vector> &&chats, @@ -338,7 +339,7 @@ object_ptr EditLinkedChatBox( callback); } -object_ptr EditLinkedChatBox( +object_ptr EditLinkedChatBox( not_null navigation, not_null channel, not_null chat, diff --git a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.h b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.h index e40864935..cf36d107b 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.h @@ -7,20 +7,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "boxes/abstract_box.h" +#include "base/object_ptr.h" + +namespace Ui { +class BoxContent; +} // namespace Ui namespace Window { class SessionNavigation; } // namespace Window -object_ptr EditLinkedChatBox( +object_ptr EditLinkedChatBox( not_null navigation, not_null channel, not_null chat, bool canEdit, Fn callback); -object_ptr EditLinkedChatBox( +object_ptr EditLinkedChatBox( not_null navigation, not_null channel, std::vector> &&chats, diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp index ff10e04ba..c082c447f 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp @@ -15,15 +15,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" +#include "ui/widgets/box_content_divider.h" +#include "ui/layers/generic_box.h" #include "ui/toast/toast.h" #include "ui/text/text_utilities.h" #include "ui/text_options.h" #include "ui/special_buttons.h" #include "chat_helpers/emoji_suggestions_widget.h" -#include "info/profile/info_profile_button.h" #include "settings/settings_privacy_security.h" #include "boxes/calendar_box.h" -#include "boxes/generic_box.h" #include "boxes/confirm_box.h" #include "boxes/passcode_box.h" #include "boxes/peers/edit_peer_permissions_box.h" @@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "facades.h" #include "main/main_session.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_info.h" @@ -53,7 +54,7 @@ enum class PasswordErrorType { Later, }; -void SetCloudPassword(not_null box, not_null user) { +void SetCloudPassword(not_null box, not_null user) { user->session().api().passwordState( ) | rpl::start_with_next([=] { using namespace Settings; @@ -71,7 +72,7 @@ void SetCloudPassword(not_null box, not_null user) { } void TransferPasswordError( - not_null box, + not_null box, not_null user, PasswordErrorType error) { box->setTitle(tr::lng_rights_transfer_check()); @@ -299,7 +300,7 @@ void EditAdminBox::prepare() { : tr::lng_channel_add_admin()); addControl( - object_ptr(this), + object_ptr(this), st::rightsDividerMargin); const auto chat = peer()->asChat(); @@ -404,7 +405,7 @@ void EditAdminBox::prepare() { not_null EditAdminBox::addRankInput() { addControl( - object_ptr(this), + object_ptr(this), st::rightsRankMargin); addControl( @@ -474,7 +475,7 @@ not_null*> EditAdminBox::setupTransferButton( const auto container = wrap->entity(); container->add( - object_ptr(container), + object_ptr(container), { 0, st::infoProfileSkip, 0, st::infoProfileSkip }); container->add(EditPeerInfoBox::CreateButton( this, @@ -664,7 +665,7 @@ void EditRestrictedBox::prepare() { setTitle(tr::lng_rights_user_restrictions()); addControl( - object_ptr(this), + object_ptr(this), st::rightsDividerMargin); const auto chat = peer()->asChat(); @@ -708,7 +709,7 @@ void EditRestrictedBox::prepare() { addControl(std::move(checkboxes), QMargins()); _until = prepareRights.c_chatBannedRights().vuntil_date().v; - addControl(object_ptr(this), st::rightsUntilMargin); + addControl(object_ptr(this), st::rightsUntilMargin); addControl( object_ptr( this, @@ -759,7 +760,7 @@ void EditRestrictedBox::showRestrictUntil() { setRestrictUntil( static_cast(QDateTime(date).toTime_t())); }), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); _restrictUntilBox->setMaxDate( QDate::currentDate().addDays(kMaxRestrictDelayDays)); _restrictUntilBox->setMinDate(tomorrow); diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h index 1804aae46..7ef9e877e 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.h @@ -27,7 +27,7 @@ struct CloudPasswordResult; class CalendarBox; class PasscodeBox; -class EditParticipantBox : public BoxContent { +class EditParticipantBox : public Ui::BoxContent { public: EditParticipantBox( QWidget*, diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp index c040dbfce..af2cedbfe 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.cpp @@ -881,7 +881,7 @@ void ParticipantsBoxController::Start( }; Ui::show( Box(std::move(controller), initBox), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void ParticipantsBoxController::addNewItem() { @@ -914,7 +914,7 @@ void ParticipantsBoxController::addNewItem() { adminDone, restrictedDone), initBox), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void ParticipantsBoxController::addNewParticipants() { @@ -936,7 +936,7 @@ void ParticipantsBoxController::addNewParticipants() { channel, { already.begin(), already.end() }); } else { - Ui::show(Box(channel), LayerOption::KeepOther); + Ui::show(Box(channel), Ui::LayerOption::KeepOther); } } @@ -1483,7 +1483,7 @@ void ParticipantsBoxController::showAdmin(not_null user) { }); box->setSaveCallback(SaveAdminCallback(_peer, user, done, fail)); } - _editParticipantBox = Ui::show(std::move(box), LayerOption::KeepOther); + _editParticipantBox = Ui::show(std::move(box), Ui::LayerOption::KeepOther); } void ParticipantsBoxController::editAdminDone( @@ -1561,7 +1561,7 @@ void ParticipantsBoxController::showRestricted(not_null user) { box->setSaveCallback( SaveRestrictedCallback(_peer, user, done, fail)); } - _editParticipantBox = Ui::show(std::move(box), LayerOption::KeepOther); + _editParticipantBox = Ui::show(std::move(box), Ui::LayerOption::KeepOther); } void ParticipantsBoxController::editRestrictedDone( @@ -1629,7 +1629,7 @@ void ParticipantsBoxController::kickMember(not_null user) { text, tr::lng_box_remove(tr::now), crl::guard(this, [=] { kickMemberSure(user); })), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void ParticipantsBoxController::unkickMember(not_null user) { @@ -1672,7 +1672,7 @@ void ParticipantsBoxController::removeAdmin(not_null user) { user->firstName), tr::lng_box_remove(tr::now), crl::guard(this, [=] { removeAdminSure(user); })), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void ParticipantsBoxController::removeAdminSure(not_null user) { diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h index f9f5450f0..db271a3aa 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h @@ -245,9 +245,9 @@ private: bool _allLoaded = false; ParticipantsAdditionalData _additional; std::unique_ptr _onlineSorter; - BoxPointer _editBox; - BoxPointer _addBox; - QPointer _editParticipantBox; + Ui::BoxPointer _editBox; + Ui::BoxPointer _addBox; + QPointer _editParticipantBox; }; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.cpp index f82e4f5d4..fbf4de9bf 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.cpp @@ -13,13 +13,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat.h" #include "data/data_peer.h" #include "lang/lang_keys.h" -#include "styles/style_boxes.h" -#include "styles/style_info.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/labels.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" +#include "styles/style_layers.h" +#include "styles/style_info.h" namespace { diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.h index 984a061e8..a66065340 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_history_visibility_box.h @@ -15,7 +15,7 @@ enum class HistoryVisibility { Hidden, }; -class EditPeerHistoryVisibilityBox : public BoxContent { +class EditPeerHistoryVisibilityBox : public Ui::BoxContent { public: EditPeerHistoryVisibilityBox( QWidget*, diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 0a20237c7..d14fbde3d 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -24,21 +24,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer.h" #include "data/data_session.h" #include "history/admin_log/history_admin_log_section.h" -#include "info/profile/info_profile_button.h" #include "info/profile/info_profile_values.h" #include "lang/lang_keys.h" #include "mainwidget.h" #include "mainwindow.h" #include "mtproto/sender.h" #include "observer_peer.h" -#include "styles/style_boxes.h" -#include "styles/style_info.h" #include "ui/rp_widget.h" #include "ui/special_buttons.h" #include "ui/toast/toast.h" #include "ui/widgets/checkbox.h" +#include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/labels.h" +#include "ui/widgets/box_content_divider.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" @@ -46,6 +45,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/profile/info_profile_icon.h" #include "app.h" #include "facades.h" +#include "styles/style_layers.h" +#include "styles/style_boxes.h" +#include "styles/style_info.h" namespace { @@ -70,7 +72,7 @@ void AddSkip( container->add(object_ptr( container, top)); - container->add(object_ptr(container)); + container->add(object_ptr(container)); container->add(object_ptr( container, bottom)); @@ -91,7 +93,7 @@ void AddButtonWithCount( &icon)); } -object_ptr CreateButtonWithText( +object_ptr CreateButtonWithText( not_null parent, rpl::producer &&text, rpl::producer &&label, @@ -105,7 +107,7 @@ object_ptr CreateButtonWithText( nullptr); } -Info::Profile::Button *AddButtonWithText( +Ui::SettingsButton *AddButtonWithText( not_null parent, rpl::producer &&text, rpl::producer &&label, @@ -193,7 +195,7 @@ void SaveSlowmodeSeconds( void ShowEditPermissions(not_null peer) { const auto box = Ui::show( Box(peer), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); const auto saving = box->lifetime().make_state(0); const auto save = [=]( not_null peer, @@ -244,7 +246,7 @@ class Controller public: Controller( not_null navigation, - not_null box, + not_null box, not_null peer); object_ptr createContent(); @@ -330,7 +332,7 @@ private: std::optional _signaturesSavedValue; const not_null _navigation; - const not_null _box; + const not_null _box; not_null _peer; const bool _isGroup = false; @@ -351,7 +353,7 @@ private: Controller::Controller( not_null navigation, - not_null box, + not_null box, not_null peer) : _navigation(navigation) , _box(box) @@ -559,7 +561,7 @@ object_ptr Controller::createStickersEdit() { tr::lng_group_stickers_add(tr::now), st::editPeerInviteLinkButton) )->addClickHandler([=] { - Ui::show(Box(channel), LayerOption::KeepOther); + Ui::show(Box(channel), Ui::LayerOption::KeepOther); }); return std::move(result); @@ -602,13 +604,13 @@ void Controller::showEditPeerTypeBox( _privacySavedValue, _usernameSavedValue, error), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void Controller::showEditLinkedChatBox() { Expects(_peer->isChannel()); - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto channel = _peer->asChannel(); const auto callback = [=](ChannelData *result) { if (*box) { @@ -633,7 +635,7 @@ void Controller::showEditLinkedChatBox() { chat, canEdit, callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } else if (!canEdit || _linkedChatsRequestId) { return; @@ -660,7 +662,7 @@ void Controller::showEditLinkedChatBox() { channel, std::move(chats), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }).fail([=](const RPCError &error) { _linkedChatsRequestId = 0; }).send(); @@ -749,7 +751,7 @@ void Controller::fillInviteLinkButton() { Expects(_controls.buttonsLayout != nullptr); const auto buttonCallback = [=] { - Ui::show(Box(_peer), LayerOption::KeepOther); + Ui::show(Box(_peer), Ui::LayerOption::KeepOther); }; AddButtonWithText( @@ -807,7 +809,7 @@ void Controller::fillHistoryVisibilityButton() { _peer, boxCallback, *_historyVisibilitySavedValue), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }; AddButtonWithText( container, @@ -1429,7 +1431,7 @@ void Controller::deleteWithConfirmation() { tr::lng_box_delete(tr::now), st::attentionBoxButton, deleteCallback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void Controller::deleteChannel() { @@ -1476,14 +1478,14 @@ void EditPeerInfoBox::prepare() { std::move(content))); } -object_ptr EditPeerInfoBox::CreateButton( +object_ptr EditPeerInfoBox::CreateButton( not_null parent, rpl::producer &&text, rpl::producer &&count, Fn callback, - const style::InfoProfileCountButton &st, + const style::SettingsCountButton &st, const style::icon *icon) { - auto result = object_ptr( + auto result = object_ptr( parent, rpl::duplicate(text), st.button); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.h index 2346277ed..11ffd36ec 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.h @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" namespace style { -struct InfoProfileCountButton; +struct SettingsCountButton; } // namespace style namespace Window { @@ -20,15 +20,10 @@ class SessionNavigation; namespace Ui { class VerticalLayout; +class SettingsButton; } // namespace Ui -namespace Info { -namespace Profile { -class Button; -} // namespace Profile -} // namespace Info - -class EditPeerInfoBox : public BoxContent { +class EditPeerInfoBox : public Ui::BoxContent { public: EditPeerInfoBox( QWidget*, @@ -41,12 +36,12 @@ public: static bool Available(not_null peer); - [[nodiscard]] static object_ptr CreateButton( + [[nodiscard]] static object_ptr CreateButton( not_null parent, rpl::producer &&text, rpl::producer &&count, Fn callback, - const style::InfoProfileCountButton &st, + const style::SettingsCountButton &st, const style::icon *icon = nullptr); protected: diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp index 740033b46..c518e56f3 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp @@ -13,9 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/vertical_layout.h" #include "ui/widgets/labels.h" #include "ui/widgets/checkbox.h" +#include "ui/widgets/buttons.h" #include "ui/widgets/continuous_sliders.h" +#include "ui/widgets/box_content_divider.h" #include "ui/toast/toast.h" -#include "info/profile/info_profile_button.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_values.h" #include "boxes/peers/edit_participants_box.h" @@ -23,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "mainwindow.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_info.h" @@ -387,7 +389,7 @@ Fn EditPeerPermissionsBox::addSlowmodeSlider( channel ? channel->slowmodeSeconds() : 0); container->add( - object_ptr(container), + object_ptr(container), { 0, st::infoProfileSkip, 0, st::infoProfileSkip }); container->add( diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h index c62a28a56..4faf5e468 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h @@ -15,7 +15,7 @@ class RoundButton; class VerticalLayout; } // namespace Ui -class EditPeerPermissionsBox : public BoxContent { +class EditPeerPermissionsBox : public Ui::BoxContent { public: EditPeerPermissionsBox(QWidget*, not_null peer); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp index b00af3ac3..7c67aba61 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp @@ -24,8 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "mtproto/sender.h" #include "observer_peer.h" -#include "styles/style_boxes.h" -#include "styles/style_info.h" #include "ui/rp_widget.h" #include "ui/special_buttons.h" #include "ui/toast/toast.h" @@ -33,16 +31,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/checkbox.h" #include "ui/widgets/input_fields.h" #include "ui/widgets/labels.h" +#include "ui/widgets/box_content_divider.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" #include "ui/special_fields.h" #include "window/window_session_controller.h" -#include +#include "styles/style_layers.h" +#include "styles/style_boxes.h" +#include "styles/style_info.h" #include #include +#include + namespace { constexpr auto kUsernameCheckTimeout = crl::time(200); @@ -189,7 +192,7 @@ void Controller::createContent() { fillPrivaciesButtons(_wrap, _privacySavedValue); // Skip. - _wrap->add(object_ptr(_wrap)); + _wrap->add(object_ptr(_wrap)); // _wrap->add(createInviteLinkCreate()); _wrap->add(createInviteLinkEdit()); @@ -471,7 +474,7 @@ void Controller::askUsernameRevoke() { Box( &_peer->session(), std::move(revokeCallback)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void Controller::usernameChanged() { @@ -553,7 +556,7 @@ void Controller::exportInviteLink(const QString &confirmation) { auto box = Box( confirmation, std::move(callback)); - *boxPointer = Ui::show(std::move(box), LayerOption::KeepOther); + *boxPointer = Ui::show(std::move(box), Ui::LayerOption::KeepOther); } bool Controller::canEditInviteLink() const { diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h index 2d4dcf1cf..7e0e6c620 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h @@ -11,19 +11,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" namespace style { -struct InfoProfileCountButton; +struct SettingsCountButton; } // namespace style namespace Ui { class VerticalLayout; +class SettingsButton; } // namespace Ui -namespace Info { -namespace Profile { -class Button; -} // namespace Profile -} // namespace Info - enum class Privacy { HasUsername, NoUsername, @@ -35,7 +30,7 @@ enum class UsernameState { NotAvailable, }; -class EditPeerTypeBox : public BoxContent { +class EditPeerTypeBox : public Ui::BoxContent { public: // Edit just the invite link. EditPeerTypeBox(QWidget*, not_null peer); diff --git a/Telegram/SourceFiles/boxes/photo_crop_box.cpp b/Telegram/SourceFiles/boxes/photo_crop_box.cpp index 81b5347fa..918b9a41b 100644 --- a/Telegram/SourceFiles/boxes/photo_crop_box.cpp +++ b/Telegram/SourceFiles/boxes/photo_crop_box.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/ui_utility.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" PhotoCropBox::PhotoCropBox( diff --git a/Telegram/SourceFiles/boxes/photo_crop_box.h b/Telegram/SourceFiles/boxes/photo_crop_box.h index 2db2cd792..32ee55629 100644 --- a/Telegram/SourceFiles/boxes/photo_crop_box.h +++ b/Telegram/SourceFiles/boxes/photo_crop_box.h @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" -class PhotoCropBox : public BoxContent { +class PhotoCropBox : public Ui::BoxContent { public: PhotoCropBox(QWidget*, const QImage &img, const QString &title); diff --git a/Telegram/SourceFiles/boxes/rate_call_box.cpp b/Telegram/SourceFiles/boxes/rate_call_box.cpp index 30e7371b1..be102184b 100644 --- a/Telegram/SourceFiles/boxes/rate_call_box.cpp +++ b/Telegram/SourceFiles/boxes/rate_call_box.cpp @@ -8,8 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/rate_call_box.h" #include "lang/lang_keys.h" -#include "styles/style_boxes.h" -#include "styles/style_calls.h" #include "boxes/confirm_box.h" #include "ui/widgets/labels.h" #include "ui/widgets/buttons.h" @@ -17,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "main/main_session.h" #include "apiwrap.h" +#include "styles/style_layers.h" +#include "styles/style_calls.h" namespace { diff --git a/Telegram/SourceFiles/boxes/rate_call_box.h b/Telegram/SourceFiles/boxes/rate_call_box.h index 641afe177..9efaa4d53 100644 --- a/Telegram/SourceFiles/boxes/rate_call_box.h +++ b/Telegram/SourceFiles/boxes/rate_call_box.h @@ -20,7 +20,7 @@ namespace Main { class Session; } // namespace Main -class RateCallBox : public BoxContent, private MTP::Sender { +class RateCallBox : public Ui::BoxContent, private MTP::Sender { public: RateCallBox( QWidget*, diff --git a/Telegram/SourceFiles/boxes/report_box.cpp b/Telegram/SourceFiles/boxes/report_box.cpp index e94be583e..5ad271db2 100644 --- a/Telegram/SourceFiles/boxes/report_box.cpp +++ b/Telegram/SourceFiles/boxes/report_box.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/input_fields.h" #include "ui/toast/toast.h" #include "mainwindow.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_profile.h" diff --git a/Telegram/SourceFiles/boxes/report_box.h b/Telegram/SourceFiles/boxes/report_box.h index 3b48cd03d..d7afc3761 100644 --- a/Telegram/SourceFiles/boxes/report_box.h +++ b/Telegram/SourceFiles/boxes/report_box.h @@ -17,7 +17,7 @@ class Radioenum; class InputField; } // namespace Ui -class ReportBox : public BoxContent, public RPCSender { +class ReportBox : public Ui::BoxContent, public RPCSender { public: ReportBox(QWidget*, not_null peer); ReportBox(QWidget*, not_null peer, MessageIdsList ids); diff --git a/Telegram/SourceFiles/boxes/self_destruction_box.cpp b/Telegram/SourceFiles/boxes/self_destruction_box.cpp index 04b02d49d..79b5cf517 100644 --- a/Telegram/SourceFiles/boxes/self_destruction_box.cpp +++ b/Telegram/SourceFiles/boxes/self_destruction_box.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "apiwrap.h" #include "main/main_session.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" SelfDestructionBox::SelfDestructionBox( diff --git a/Telegram/SourceFiles/boxes/self_destruction_box.h b/Telegram/SourceFiles/boxes/self_destruction_box.h index f4128e821..475f59749 100644 --- a/Telegram/SourceFiles/boxes/self_destruction_box.h +++ b/Telegram/SourceFiles/boxes/self_destruction_box.h @@ -20,7 +20,7 @@ namespace Main { class Session; } // namespace Main -class SelfDestructionBox : public BoxContent, private MTP::Sender { +class SelfDestructionBox : public Ui::BoxContent, private MTP::Sender { public: SelfDestructionBox( QWidget*, diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index f4b3b1a4b..0f5a43054 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_schedule_box.h" #include "core/file_utilities.h" #include "core/mime_type.h" -#include "core/event_filter.h" +#include "base/event_filter.h" #include "ui/effects/animations.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/buttons.h" @@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "facades.h" #include "app.h" #include "styles/style_history.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_chat_helpers.h" @@ -1435,7 +1436,7 @@ void SendFilesBox::prepareAlbumPreview() { const auto wrap = Ui::CreateChild( this, - st::boxLayerScroll); + st::boxScroll); _albumPreview = wrap->setOwnedWidget(object_ptr( this, _list, @@ -1678,6 +1679,8 @@ void SendFilesBox::setupCaption() { _caption, &_controller->session()); + InitSpellchecker(&_controller->session(), _caption); + updateCaptionPlaceholder(); setupEmojiPanel(); } @@ -1705,9 +1708,9 @@ void SendFilesBox::setupEmojiPanel() { const auto filterCallback = [=](not_null event) { emojiFilterForGeometry(event); - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; }; - _emojiFilter.reset(Core::InstallEventFilter(container, filterCallback)); + _emojiFilter.reset(base::install_event_filter(container, filterCallback)); _emojiToggle.create(this, st::boxAttachEmoji); _emojiToggle->setVisible(!_caption->isHidden()); @@ -1981,7 +1984,7 @@ void SendFilesBox::sendScheduled() { const auto callback = [=](Api::SendOptions options) { send(options); }; Ui::show( HistoryView::PrepareScheduleBox(this, _sendMenuType, callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } SendFilesBox::~SendFilesBox() = default; diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index a3e6beda2..23f741295 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -48,7 +48,7 @@ enum class SendFilesWay { Files, }; -class SendFilesBox : public BoxContent { +class SendFilesBox : public Ui::BoxContent { public: enum class SendLimit { One, diff --git a/Telegram/SourceFiles/boxes/sessions_box.cpp b/Telegram/SourceFiles/boxes/sessions_box.cpp index 1ff16bdb9..91247790d 100644 --- a/Telegram/SourceFiles/boxes/sessions_box.cpp +++ b/Telegram/SourceFiles/boxes/sessions_box.cpp @@ -15,13 +15,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "base/unixtime.h" #include "boxes/confirm_box.h" -#include "info/profile/info_profile_button.h" #include "settings/settings_common.h" #include "ui/widgets/buttons.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/labels.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_info.h" #include "styles/style_settings.h" @@ -69,7 +69,7 @@ private: void setupContent(); QPointer _current; - QPointer _terminateAll; + QPointer _terminateAll; QPointer _incomplete; QPointer _list; @@ -320,7 +320,7 @@ void SessionsBox::terminateOne(uint64 hash) { tr::lng_settings_reset_button(tr::now), st::attentionBoxButton, callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void SessionsBox::terminateAll() { @@ -346,7 +346,7 @@ void SessionsBox::terminateAll() { tr::lng_settings_reset_button(tr::now), st::attentionBoxButton, callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } SessionsBox::Inner::Inner(QWidget *parent) @@ -368,7 +368,7 @@ void SessionsBox::Inner::setupContent() { object_ptr(content)))->setDuration(0); const auto terminateInner = terminateWrap->entity(); _terminateAll = terminateInner->add( - object_ptr( + object_ptr( terminateInner, tr::lng_sessions_terminate_all(), st::terminateSessionsButton)); diff --git a/Telegram/SourceFiles/boxes/sessions_box.h b/Telegram/SourceFiles/boxes/sessions_box.h index 4eaf6e6a6..b27ec5dd4 100644 --- a/Telegram/SourceFiles/boxes/sessions_box.h +++ b/Telegram/SourceFiles/boxes/sessions_box.h @@ -22,7 +22,7 @@ namespace Main { class Session; } // namespace Main -class SessionsBox : public BoxContent, private MTP::Sender { +class SessionsBox : public Ui::BoxContent, private MTP::Sender { public: SessionsBox(QWidget*, not_null session); diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 20b4ac99f..0f319b401 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_folder.h" #include "main/main_session.h" #include "core/application.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_history.h" @@ -206,6 +207,7 @@ void ShareBox::prepareCommentField() { field->setEditLinkCallback( DefaultEditLinkCallback(&_navigation->session(), field)); + InitSpellchecker(&_navigation->session(), field); Ui::SendPendingMoveResizeEvents(_comment); } @@ -479,7 +481,7 @@ void ShareBox::submitScheduled() { const auto callback = [=](Api::SendOptions options) { submit(options); }; Ui::show( HistoryView::PrepareScheduleBox(this, sendMenuType(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void ShareBox::copyLink() { diff --git a/Telegram/SourceFiles/boxes/share_box.h b/Telegram/SourceFiles/boxes/share_box.h index 69dc63b9c..55d223c04 100644 --- a/Telegram/SourceFiles/boxes/share_box.h +++ b/Telegram/SourceFiles/boxes/share_box.h @@ -52,7 +52,7 @@ void ShareGameScoreByHash( not_null session, const QString &hash); -class ShareBox : public BoxContent, public RPCSender { +class ShareBox : public Ui::BoxContent, public RPCSender { public: using CopyCallback = Fn; using SubmitCallback = Fn @@ -136,14 +136,14 @@ StickerSetBox::StickerSetBox( , _set(set) { } -QPointer StickerSetBox::Show( +QPointer StickerSetBox::Show( not_null controller, not_null document) { if (const auto sticker = document->sticker()) { if (sticker->set.type() != mtpc_inputStickerSetEmpty) { return Ui::show( Box(controller, sticker->set), - LayerOption::KeepOther).data(); + Ui::LayerOption::KeepOther).data(); } } return nullptr; @@ -630,7 +630,7 @@ void StickerSetBox::Inner::paintSticker( auto h = 1; if (element.animated && !document->dimensions.isEmpty()) { const auto request = Lottie::FrameRequest{ boundingBoxSize() * cIntRetinaFactor() }; - const auto size = request.size(document->dimensions) / cIntRetinaFactor(); + const auto size = request.size(document->dimensions, true) / cIntRetinaFactor(); w = std::max(size.width(), 1); h = std::max(size.height(), 1); } else { @@ -695,7 +695,7 @@ void StickerSetBox::Inner::install() { if (isMasksSet()) { Ui::show( Box(tr::lng_stickers_masks_pack(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } else if (_installRequest) { return; diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.h b/Telegram/SourceFiles/boxes/sticker_set_box.h index 4c5cc61fe..ae01ba020 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.h +++ b/Telegram/SourceFiles/boxes/sticker_set_box.h @@ -21,14 +21,14 @@ namespace Ui { class PlainShadow; } // namespace Ui -class StickerSetBox : public BoxContent, public RPCSender { +class StickerSetBox : public Ui::BoxContent, public RPCSender { public: StickerSetBox( QWidget*, not_null controller, const MTPInputStickerSet &set); - static QPointer Show( + static QPointer Show( not_null controller, not_null document); diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index a44cca08c..c426a2316 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "facades.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_chat_helpers.h" @@ -768,7 +769,7 @@ void StickersBox::Inner::resizeEvent(QResizeEvent *e) { void StickersBox::Inner::updateControlsGeometry() { if (_megagroupSet) { auto top = st::groupStickersFieldPadding.top(); - auto fieldLeft = st::boxLayerTitlePosition.x(); + auto fieldLeft = st::boxTitlePosition.x(); _megagroupSetField->setGeometryToLeft(fieldLeft, top, width() - fieldLeft - st::groupStickersFieldPadding.right(), _megagroupSetField->height()); top += _megagroupSetField->height() + st::groupStickersFieldPadding.bottom(); if (_megagroupSelectedRemove) { @@ -779,8 +780,8 @@ void StickersBox::Inner::updateControlsGeometry() { } _megagroupDivider->setGeometryToLeft(0, top, width(), _megagroupDivider->height()); top += _megagroupDivider->height(); - _megagroupSubTitle->resizeToNaturalWidth(width() - 2 * st::boxLayerTitlePosition.x()); - _megagroupSubTitle->moveToLeft(st::boxLayerTitlePosition.x(), top + st::boxLayerTitlePosition.y()); + _megagroupSubTitle->resizeToNaturalWidth(width() - 2 * st::boxTitlePosition.x()); + _megagroupSubTitle->moveToLeft(st::boxTitlePosition.x(), top + st::boxTitlePosition.y()); } } @@ -1302,7 +1303,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) { Box( App::wnd()->sessionController(), Stickers::inputSetId(*set)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } }; if (selectedIndex >= 0 && !_inDragArea) { @@ -1912,7 +1913,7 @@ void StickersBox::Inner::readVisibleSets() { } void StickersBox::Inner::updateScrollbarWidth() { - auto width = (_visibleBottom - _visibleTop < height()) ? (st::boxLayerScroll.width - st::boxLayerScroll.deltax) : 0; + auto width = (_visibleBottom - _visibleTop < height()) ? (st::boxScroll.width - st::boxScroll.deltax) : 0; if (_scrollbar != width) { _scrollbar = width; update(); diff --git a/Telegram/SourceFiles/boxes/stickers_box.h b/Telegram/SourceFiles/boxes/stickers_box.h index 1436e3b5a..d5aba39ed 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.h +++ b/Telegram/SourceFiles/boxes/stickers_box.h @@ -26,6 +26,7 @@ class RippleAnimation; class SettingsSlider; class SlideAnimation; class CrossButton; +class BoxContentDivider; } // namespace Ui namespace Main { @@ -33,7 +34,7 @@ class Session; } // namespace Main class StickersBox final - : public BoxContent + : public Ui::BoxContent , public RPCSender , private base::Subscriber { public: @@ -365,7 +366,7 @@ private: object_ptr _megagroupSetField = { nullptr }; object_ptr _megagroupSelectedShadow = { nullptr }; object_ptr _megagroupSelectedRemove = { nullptr }; - object_ptr _megagroupDivider = { nullptr }; + object_ptr _megagroupDivider = { nullptr }; object_ptr _megagroupSubTitle = { nullptr }; base::Timer _megagroupSetAddressChangedTimer; mtpRequestId _megagroupSetRequestId = 0; diff --git a/Telegram/SourceFiles/boxes/url_auth_box.cpp b/Telegram/SourceFiles/boxes/url_auth_box.cpp index 29c0d6aa8..65b504ce2 100644 --- a/Telegram/SourceFiles/boxes/url_auth_box.cpp +++ b/Telegram/SourceFiles/boxes/url_auth_box.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "apiwrap.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" void UrlAuthBox::Activate( @@ -85,7 +86,7 @@ void UrlAuthBox::Request( const auto bot = request.is_request_write_access() ? session->data().processUser(request.vbot()).get() : nullptr; - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto finishWithUrl = [=](const QString &url) { if (*box) { (*box)->closeBox(); @@ -122,7 +123,7 @@ void UrlAuthBox::Request( }; *box = Ui::show( Box(session, url, qs(request.vdomain()), bot, callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } UrlAuthBox::UrlAuthBox( diff --git a/Telegram/SourceFiles/boxes/url_auth_box.h b/Telegram/SourceFiles/boxes/url_auth_box.h index ddad3204f..4ac461326 100644 --- a/Telegram/SourceFiles/boxes/url_auth_box.h +++ b/Telegram/SourceFiles/boxes/url_auth_box.h @@ -16,7 +16,7 @@ namespace Main { class Session; } // namespace Main -class UrlAuthBox : public BoxContent { +class UrlAuthBox : public Ui::BoxContent { public: static void Activate( not_null message, diff --git a/Telegram/SourceFiles/boxes/username_box.cpp b/Telegram/SourceFiles/boxes/username_box.cpp index 55db8b294..f90b17391 100644 --- a/Telegram/SourceFiles/boxes/username_box.cpp +++ b/Telegram/SourceFiles/boxes/username_box.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "data/data_session.h" #include "data/data_user.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include diff --git a/Telegram/SourceFiles/boxes/username_box.h b/Telegram/SourceFiles/boxes/username_box.h index c1b1e8b65..2cc31dd52 100644 --- a/Telegram/SourceFiles/boxes/username_box.h +++ b/Telegram/SourceFiles/boxes/username_box.h @@ -18,7 +18,7 @@ namespace Main { class Session; } // namespace Main -class UsernameBox : public BoxContent, public RPCSender { +class UsernameBox : public Ui::BoxContent, public RPCSender { public: UsernameBox(QWidget*, not_null session); diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index 89a38ef8a..2aaeb9f4e 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -using "basic.style"; +using "ui/basic.style"; using "ui/widgets/widgets.style"; using "window/window.style"; diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 6b7b6fb9f..428ebf94f 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/openssl_help.h" #include "mtproto/connection.h" #include "media/audio/media_audio_track.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "calls/calls_panel.h" #include "data/data_user.h" #include "data/data_session.h" diff --git a/Telegram/SourceFiles/calls/calls_top_bar.cpp b/Telegram/SourceFiles/calls/calls_top_bar.cpp index bea980c4b..f4e0d76aa 100644 --- a/Telegram/SourceFiles/calls/calls_top_bar.cpp +++ b/Telegram/SourceFiles/calls/calls_top_bar.cpp @@ -22,14 +22,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "layout.h" #include "app.h" #include "styles/style_calls.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" namespace Calls { namespace { constexpr auto kUpdateDebugTimeoutMs = crl::time(500); -class DebugInfoBox : public BoxContent { +class DebugInfoBox : public Ui::BoxContent { public: DebugInfoBox(QWidget*, base::weak_ptr call); diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style index 54ab0796e..7aa5580d9 100644 --- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style +++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -using "basic.style"; +using "ui/basic.style"; using "boxes/boxes.style"; using "ui/widgets/widgets.style"; @@ -79,7 +79,7 @@ stickersFeaturedInstalled: icon {{ "send_control_save", lightButtonFg }}; stickersMaxHeight: 320px; stickersPadding: margins(19px, 13px, 19px, 13px); stickersSize: size(64px, 64px); -stickersScroll: ScrollArea(boxLayerScroll) { +stickersScroll: ScrollArea(boxScroll) { deltat: 19px; deltab: 9px; } diff --git a/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp b/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp index eb8f4f150..16803d6fb 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp @@ -7,11 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "chat_helpers/emoji_keywords.h" -#include "chat_helpers/emoji_suggestions_helper.h" +#include "emoji_suggestions_helper.h" #include "lang/lang_instance.h" #include "lang/lang_cloud_manager.h" #include "core/application.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "ui/emoji_config.h" #include "main/main_account.h" #include "main/main_session.h" diff --git a/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp b/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp index f3b6635e2..ad1f896fc 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.cpp @@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_account.h" #include "mainwidget.h" #include "app.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_chat_helpers.h" diff --git a/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.h b/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.h index 13dfdf6e5..316b06100 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_sets_manager.h @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui { namespace Emoji { -class ManageSetsBox : public BoxContent { +class ManageSetsBox : public Ui::BoxContent { public: explicit ManageSetsBox(QWidget*); diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_helper.h b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_helper.h deleted file mode 100644 index 0b4b55796..000000000 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_helper.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "emoji_suggestions.h" -#include "emoji_suggestions_data.h" - -namespace Ui { -namespace Emoji { - -inline utf16string QStringToUTF16(const QString &string) { - return utf16string( - reinterpret_cast(string.constData()), - string.size()); -} - -inline QString QStringFromUTF16(utf16string string) { - return QString::fromRawData( - reinterpret_cast(string.data()), - string.size()); -} - -constexpr auto kSuggestionMaxLength = internal::kReplacementMaxLength; - -} // namespace Emoji -} // namespace Ui diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index d2b763a4f..f5bee20f8 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_keywords.h" -#include "chat_helpers/emoji_suggestions_helper.h" +#include "emoji_suggestions_helper.h" #include "ui/effects/ripple_animation.h" #include "ui/widgets/shadow.h" #include "ui/widgets/inner_dropdown.h" @@ -17,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/ui_utility.h" #include "platform/platform_specific.h" #include "core/application.h" -#include "core/event_filter.h" +#include "base/event_filter.h" #include "main/main_session.h" #include "app.h" #include "styles/style_chat_helpers.h" @@ -525,17 +525,17 @@ SuggestionsController::SuggestionsController( const auto fieldCallback = [=](not_null event) { return fieldFilter(event) - ? Core::EventFilter::Result::Cancel - : Core::EventFilter::Result::Continue; + ? base::EventFilterResult::Cancel + : base::EventFilterResult::Continue; }; - _fieldFilter.reset(Core::InstallEventFilter(_field, fieldCallback)); + _fieldFilter.reset(base::install_event_filter(_field, fieldCallback)); const auto outerCallback = [=](not_null event) { return outerFilter(event) - ? Core::EventFilter::Result::Cancel - : Core::EventFilter::Result::Continue; + ? base::EventFilterResult::Cancel + : base::EventFilterResult::Continue; }; - _outerFilter.reset(Core::InstallEventFilter(outer, outerCallback)); + _outerFilter.reset(base::install_event_filter(outer, outerCallback)); QObject::connect( _field, diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index 781b0befa..57f648d9d 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -655,7 +655,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) { auto h = 1; if (sticker.animated && !document->dimensions.isEmpty()) { const auto request = Lottie::FrameRequest{ stickerBoundingBox() * cIntRetinaFactor() }; - const auto size = request.size(document->dimensions) / cIntRetinaFactor(); + const auto size = request.size(document->dimensions, true) / cIntRetinaFactor(); w = std::max(size.width(), 1); h = std::max(size.height(), 1); } else { diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index 93e4400e7..8895b0ee4 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -12,18 +12,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" // HistoryItem::originalText #include "base/qthelp_regex.h" #include "base/qthelp_url.h" +#include "base/event_filter.h" #include "boxes/abstract_box.h" #include "ui/wrap/vertical_layout.h" #include "ui/widgets/popup_menu.h" #include "ui/ui_utility.h" #include "data/data_session.h" #include "data/data_user.h" -#include "core/event_filter.h" #include "chat_helpers/emoji_suggestions_widget.h" #include "window/window_session_controller.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "main/main_session.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" #include "styles/style_history.h" @@ -57,7 +58,7 @@ public: }; -class EditLinkBox : public BoxContent { +class EditLinkBox : public Ui::BoxContent { public: EditLinkBox( QWidget*, @@ -126,6 +127,7 @@ void EditLinkBox::prepare() { getDelegate()->outerContainer(), text, _session); + InitSpellchecker(_session, text); const auto url = content->add( object_ptr( @@ -247,7 +249,7 @@ FncommitMarkdownLinkEdit(selection, text, link); } - }), LayerOption::KeepOther); + }), Ui::LayerOption::KeepOther); return true; }; } @@ -272,6 +274,23 @@ void InitMessageField( DefaultEditLinkCallback(&controller->session(), field)); } +void InitSpellchecker( + not_null session, + not_null field) { +#ifndef TDESKTOP_DISABLE_SPELLCHECK + const auto s = Ui::CreateChild( + field->rawTextEdit().get(), + session->settings().spellcheckerEnabledValue(), + field->documentContentsChanges()); + Spellchecker::SetPhrases({ { + { &ph::lng_spellchecker_add, tr::lng_spellchecker_add() }, + { &ph::lng_spellchecker_remove, tr::lng_spellchecker_remove() }, + { &ph::lng_spellchecker_ignore, tr::lng_spellchecker_ignore() }, + } }); + field->setExtendedContextMenu(s->contextMenuCreated()); +#endif // TDESKTOP_DISABLE_SPELLCHECK +} + bool HasSendText(not_null field) { const auto &text = field->getTextWithTags().text; for (const auto ch : text) { @@ -675,10 +694,10 @@ void SetupSendMenu( (*menu)->popup(QCursor::pos()); return true; }; - Core::InstallEventFilter(button, [=](not_null e) { + base::install_event_filter(button, [=](not_null e) { if (e->type() == QEvent::ContextMenu && showMenu()) { - return Core::EventFilter::Result::Cancel; + return base::EventFilterResult::Cancel; } - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; }); } diff --git a/Telegram/SourceFiles/chat_helpers/message_field.h b/Telegram/SourceFiles/chat_helpers/message_field.h index 8077c032b..874e15b8e 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.h +++ b/Telegram/SourceFiles/chat_helpers/message_field.h @@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" #include "base/qt_connection.h" +#ifndef TDESKTOP_DISABLE_SPELLCHECK +#include "spellcheck/spelling_highlighter.h" +#endif // TDESKTOP_DISABLE_SPELLCHECK + #include namespace Main { @@ -34,6 +38,11 @@ Fn controller, not_null field); + +void InitSpellchecker( + not_null session, + not_null field); + bool HasSendText(not_null field); struct InlineBotQuery { diff --git a/Telegram/SourceFiles/chat_helpers/stickers.cpp b/Telegram/SourceFiles/chat_helpers/stickers.cpp index 3fd8c702f..6cebd226f 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers.cpp @@ -82,7 +82,7 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) { toast.multiline = true; toast.padding = st::stickersToastPadding; Ui::Toast::Show(toast); -// Ui::show(Box(archived, &Auth()), LayerOption::KeepOther); +// Ui::show(Box(archived, &Auth()), Ui::LayerOption::KeepOther); Auth().data().notifyStickersUpdated(); } @@ -187,7 +187,7 @@ void UndoInstallLocally(uint64 setId) { Ui::show( Box(tr::lng_stickers_not_found(tr::now)), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } bool IsFaved(not_null document) { diff --git a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp index 10dae240e..5d8d86303 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp @@ -16,9 +16,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_session.h" #include "data/data_document.h" +#include "base/call_delayed.h" #include "apiwrap.h" #include "app.h" -#include "facades.h" #include "styles/style_history.h" #include @@ -612,7 +612,7 @@ base::flat_map> EmojiPack::collectStickers( } void EmojiPack::refreshDelayed() { - App::CallDelayed(details::kRefreshTimeout, _session, [=] { + base::call_delayed(details::kRefreshTimeout, _session, [=] { refresh(); }); } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index f88aebbac..e3cb75407 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -1677,7 +1677,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section, auto h = 1; if (sticker.animated && !document->dimensions.isEmpty()) { const auto request = Lottie::FrameRequest{ boundingBoxSize() * cIntRetinaFactor() }; - const auto size = request.size(document->dimensions) / cIntRetinaFactor(); + const auto size = request.size(document->dimensions, true) / cIntRetinaFactor(); w = std::max(size.width(), 1); h = std::max(size.height(), 1); } else { @@ -2775,7 +2775,7 @@ void StickersListWidget::displaySet(uint64 setId) { _displayingSet = true; checkHideWithBox(Ui::show( Box(_megagroupSet), - LayerOption::KeepOther).data()); + Ui::LayerOption::KeepOther).data()); return; } else if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) { setId = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid().v; @@ -2789,11 +2789,11 @@ void StickersListWidget::displaySet(uint64 setId) { _displayingSet = true; checkHideWithBox(Ui::show( Box(controller(), Stickers::inputSetId(*it)), - LayerOption::KeepOther).data()); + Ui::LayerOption::KeepOther).data()); } } -void StickersListWidget::checkHideWithBox(QPointer box) { +void StickersListWidget::checkHideWithBox(QPointer box) { if (!box) { return; } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index bfe030dbd..53c11c794 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -12,8 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/variant.h" #include "base/timer.h" -class BoxContent; - namespace Main { class Session; } // namespace Main @@ -25,6 +23,7 @@ class SessionController; namespace Ui { class LinkButton; class RippleAnimation; +class BoxContent; } // namespace Ui namespace Lottie { @@ -203,7 +202,7 @@ private: void setSection(Section section); void displaySet(uint64 setId); - void checkHideWithBox(QPointer box); + void checkHideWithBox(QPointer box); void installSet(uint64 setId); void removeMegagroupSet(bool locally); void removeSet(uint64 setId); diff --git a/Telegram/SourceFiles/codegen/common/basic_tokenized_file.cpp b/Telegram/SourceFiles/codegen/common/basic_tokenized_file.cpp deleted file mode 100644 index 6c98a2f5c..000000000 --- a/Telegram/SourceFiles/codegen/common/basic_tokenized_file.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/common/basic_tokenized_file.h" - -#include "codegen/common/logging.h" -#include "codegen/common/clean_file_reader.h" -#include "codegen/common/checked_utf8_string.h" - -using Token = codegen::common::BasicTokenizedFile::Token; -using Type = Token::Type; - -namespace codegen { -namespace common { -namespace { - -constexpr int kErrorUnterminatedStringLiteral = 201; -constexpr int kErrorIncorrectUtf8String = 202; -constexpr int kErrorIncorrectToken = 203; -constexpr int kErrorUnexpectedToken = 204; - -bool isDigitChar(char ch) { - return (ch >= '0') && (ch <= '9'); -} - -bool isNameChar(char ch) { - return isDigitChar(ch) || ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || (ch == '_'); -} - -bool isWhitespaceChar(char ch) { - return (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t'); -} - -Token invalidToken() { - return { Type::Invalid, QString(), ConstUtf8String(nullptr, 0), false }; -} - -} // namespace - -BasicTokenizedFile::BasicTokenizedFile(const QString &filepath) : reader_(filepath) { -} - -BasicTokenizedFile::BasicTokenizedFile(const QByteArray &content, const QString &filepath) : reader_(content, filepath) { -} - -bool BasicTokenizedFile::putBack() { - if (currentToken_ > 0) { - --currentToken_; - return true; - } - return false; -} - -Token BasicTokenizedFile::getAnyToken() { - if (currentToken_ >= tokens_.size()) { - if (readToken() == Type::Invalid) { - return invalidToken(); - } - } - return tokens_.at(currentToken_++); -} - -Token BasicTokenizedFile::getToken(Type typeCondition) { - if (auto token = getAnyToken()) { - if (token.type == typeCondition) { - return token; - } - putBack(); - } - return invalidToken(); -} - -Type BasicTokenizedFile::readToken() { - auto result = readOneToken(StartWithWhitespace::Allow); - - // Try to read double token. - if (result == Type::Int) { - if (readOneToken(StartWithWhitespace::Deny) == Type::Dot) { - // We got int and dot, so it is double already. - result = uniteLastTokens(Type::Double); - - // Try to read one more int (after dot). - if (readOneToken(StartWithWhitespace::Deny) == Type::Int) { - result = uniteLastTokens(Type::Double); - } - } - } else if (result == Type::Dot) { - if (readOneToken(StartWithWhitespace::Deny) == Type::Int) { - //We got dot and int, so it is double. - result = uniteLastTokens(Type::Double); - } - } - return result; -} - -Type BasicTokenizedFile::readOneToken(StartWithWhitespace condition) { - skipWhitespaces(); - if (tokenStartWhitespace_ && condition == StartWithWhitespace::Deny) { - return Type::Invalid; - } - if (reader_.atEnd()) { - return Type::Invalid; - } - - auto ch = reader_.currentChar(); - if (ch == '"') { - return readString(); - } else if (isNameChar(ch)) { - return readNameOrNumber(); - } - return readSingleLetter(); -} - -Type BasicTokenizedFile::saveToken(Type type, const QString &value) { - ConstUtf8String original = { tokenStart_, reader_.currentPtr() }; - tokens_.push_back({ type, value, original, tokenStartWhitespace_ }); - return type; -} - -Type BasicTokenizedFile::uniteLastTokens(Type type) { - auto size = tokens_.size(); - if (size < 2) { - return Type::Invalid; - } - - auto &token(tokens_[size - 2]); - auto originalFrom = token.original.data(); - auto originalTill = tokens_.back().original.end(); - token.type = type; - token.original = { originalFrom, originalTill }; - token.value += tokens_.back().value; - tokens_.pop_back(); - return type; -} - -QString BasicTokenizedFile::getCurrentLineComment() { - if (lineNumber_ > singleLineComments_.size()) { - reader_.logError(kErrorInternal, lineNumber_) << "internal tokenizer error (line number larger than comments list size)."; - failed_ = true; - return QString(); - } - auto commentBytes = singleLineComments_[lineNumber_ - 1].mid(2); // Skip "//" - CheckedUtf8String comment(commentBytes); - if (!comment.isValid()) { - reader_.logError(kErrorIncorrectUtf8String, lineNumber_) << "incorrect UTF-8 string in the comment."; - failed_ = true; - return QString(); - } - return comment.toString().trimmed(); -} - -Type BasicTokenizedFile::readNameOrNumber() { - while (!reader_.atEnd()) { - if (!isDigitChar(reader_.currentChar())) { - break; - } - reader_.skipChar(); - } - bool onlyDigits = true; - while (!reader_.atEnd()) { - if (!isNameChar(reader_.currentChar())) { - break; - } - onlyDigits = false; - reader_.skipChar(); - } - return saveToken(onlyDigits ? Type::Int : Type::Name); -} - -Type BasicTokenizedFile::readString() { - reader_.skipChar(); - auto offset = reader_.currentPtr(); - - QByteArray value; - while (!reader_.atEnd()) { - auto ch = reader_.currentChar(); - if (ch == '"') { - if (reader_.currentPtr() > offset) { - value.append(offset, reader_.currentPtr() - offset); - } - break; - } - if (ch == '\n') { - reader_.logError(kErrorUnterminatedStringLiteral, lineNumber_) << "unterminated string literal."; - failed_ = true; - return Type::Invalid; - } - if (ch == '\\') { - if (reader_.currentPtr() > offset) { - value.append(offset, reader_.currentPtr() - offset); - } - reader_.skipChar(); - ch = reader_.currentChar(); - if (reader_.atEnd() || ch == '\n') { - reader_.logError(kErrorUnterminatedStringLiteral, lineNumber_) << "unterminated string literal."; - failed_ = true; - return Type::Invalid; - } - offset = reader_.currentPtr() + 1; - if (ch == 'n') { - value.append('\n'); - } else if (ch == 't') { - value.append('\t'); - } else if (ch == '"') { - value.append('"'); - } else if (ch == '\\') { - value.append('\\'); - } - } - reader_.skipChar(); - } - if (reader_.atEnd()) { - reader_.logError(kErrorUnterminatedStringLiteral, lineNumber_) << "unterminated string literal."; - failed_ = true; - return Type::Invalid; - } - CheckedUtf8String checked(value); - if (!checked.isValid()) { - reader_.logError(kErrorIncorrectUtf8String, lineNumber_) << "incorrect UTF-8 string literal."; - failed_ = true; - return Type::Invalid; - } - reader_.skipChar(); - return saveToken(Type::String, checked.toString()); -} - -Type BasicTokenizedFile::readSingleLetter() { - auto type = singleLetterTokens_.value(reader_.currentChar(), Type::Invalid); - if (type == Type::Invalid) { - reader_.logError(kErrorIncorrectToken, lineNumber_) << "incorrect token '" << reader_.currentChar() << "'"; - return Type::Invalid; - } - - reader_.skipChar(); - return saveToken(type); -} - -void BasicTokenizedFile::skipWhitespaces() { - if (reader_.atEnd()) return; - - auto ch = reader_.currentChar(); - tokenStartWhitespace_ = isWhitespaceChar(ch); - if (tokenStartWhitespace_) { - do { - if (ch == '\n') { - ++lineNumber_; - } - reader_.skipChar(); - ch = reader_.currentChar(); - } while (!reader_.atEnd() && isWhitespaceChar(ch)); - } - tokenStart_ = reader_.currentPtr(); -} - -LogStream operator<<(LogStream &&stream, BasicTokenizedFile::Token::Type type) { - const char *value = "'invalid'"; - switch (type) { - case Type::Invalid: break; - case Type::Int: value = "'int'"; break; - case Type::Double: value = "'double'"; break; - case Type::String: value = "'string'"; break; - case Type::LeftParenthesis: value = "'('"; break; - case Type::RightParenthesis: value = "')'"; break; - case Type::LeftBrace: value = "'{'"; break; - case Type::RightBrace: value = "'}'"; break; - case Type::LeftBracket: value = "'['"; break; - case Type::RightBracket: value = "']'"; break; - case Type::Colon: value = "':'"; break; - case Type::Semicolon: value = "';'"; break; - case Type::Comma: value = "','"; break; - case Type::Dot: value = "'.'"; break; - case Type::Number: value = "'#'"; break; - case Type::Plus: value = "'+'"; break; - case Type::Minus: value = "'-'"; break; - case Type::Equals: value = "'='"; break; - case Type::Name: value = "'identifier'"; break; - } - return std::forward(stream) << value; -} - -LogStream BasicTokenizedFile::logError(int code) const { - return reader_.logError(code, lineNumber_); -} - -LogStream BasicTokenizedFile::logErrorUnexpectedToken() const { - if (currentToken_ < tokens_.size()) { - auto token = tokens_.at(currentToken_).original.toStdString(); - return logError(kErrorUnexpectedToken) << "unexpected token '" << token << "', expected "; - } - return logError(kErrorUnexpectedToken) << "unexpected token, expected "; -} - -BasicTokenizedFile::~BasicTokenizedFile() = default; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/basic_tokenized_file.h b/Telegram/SourceFiles/codegen/common/basic_tokenized_file.h deleted file mode 100644 index 55c736683..000000000 --- a/Telegram/SourceFiles/codegen/common/basic_tokenized_file.h +++ /dev/null @@ -1,156 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include - -#include "codegen/common/const_utf8_string.h" -#include "codegen/common/clean_file_reader.h" - -namespace codegen { -namespace common { - -class LogStream; - -// Interface for reading a cleaned from comments file by basic tokens. -class BasicTokenizedFile { -public: - explicit BasicTokenizedFile(const QString &filepath); - explicit BasicTokenizedFile(const QByteArray &content, const QString &filepath = QString()); - BasicTokenizedFile(const BasicTokenizedFile &other) = delete; - BasicTokenizedFile &operator=(const BasicTokenizedFile &other) = delete; - - struct Token { - // String - utf8 string converted to QString. - enum class Type { - Invalid = 0, - Int, - Double, - String, - LeftParenthesis, - RightParenthesis, - LeftBrace, - RightBrace, - LeftBracket, - RightBracket, - Colon, - Semicolon, - Comma, - Dot, - Number, - Plus, - Minus, - Equals, - And, - Or, - Name, // [0-9a-zA-Z_]+ with at least one letter. - }; - Type type; - QString value; - ConstUtf8String original; - bool hasLeftWhitespace; - - explicit operator bool() const { - return (type != Type::Invalid); - } - }; - - bool read() { - if (reader_.read()) { - singleLineComments_ = reader_.singleLineComments(); - return true; - } - return false; - } - bool atEnd() const { - return reader_.atEnd(); - } - - Token getAnyToken(); - Token getToken(Token::Type typeCondition); - bool putBack(); - bool failed() const { - return failed_; - } - - QString getCurrentLineComment(); - - // Log error to std::cerr with 'code' at the current position in file. - LogStream logError(int code) const; - LogStream logErrorUnexpectedToken() const; - - ~BasicTokenizedFile(); - -private: - using Type = Token::Type; - - void skipWhitespaces(); - - // Reads a token, including complex tokens, like double numbers. - Type readToken(); - - // Read exactly one token, applying condition on the whitespaces. - enum class StartWithWhitespace { - Allow, - Deny, - }; - Type readOneToken(StartWithWhitespace condition); - - // helpers - Type readNameOrNumber(); - Type readString(); - Type readSingleLetter(); - - Type saveToken(Type type, const QString &value = QString()); - Type uniteLastTokens(Type type); - - CleanFileReader reader_; - QList tokens_; - int currentToken_ = 0; - int lineNumber_ = 1; - bool failed_ = false; - QVector singleLineComments_; - - // Where the last (currently read) token has started. - const char *tokenStart_ = nullptr; - - // Did the last (currently read) token start with a whitespace. - bool tokenStartWhitespace_ = false; - - const QMap singleLetterTokens_ = { - { '(', Type::LeftParenthesis }, - { ')', Type::RightParenthesis }, - { '{', Type::LeftBrace }, - { '}', Type::RightBrace }, - { '[', Type::LeftBracket }, - { ']', Type::RightBracket }, - { ':', Type::Colon }, - { ';', Type::Semicolon }, - { ',', Type::Comma }, - { '.', Type::Dot }, - { '#', Type::Number }, - { '+', Type::Plus }, - { '-', Type::Minus }, - { '=', Type::Equals }, - { '&', Type::And }, - { '|', Type::Or }, - }; - -}; - -LogStream operator<<(LogStream &&stream, BasicTokenizedFile::Token::Type type); -template <> -LogStream operator<< (LogStream &&stream, BasicTokenizedFile::Token::Type &&value) = delete; -template <> -LogStream operator<< (LogStream &&stream, const BasicTokenizedFile::Token::Type &value) = delete; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/checked_utf8_string.cpp b/Telegram/SourceFiles/codegen/common/checked_utf8_string.cpp deleted file mode 100644 index 412671ac8..000000000 --- a/Telegram/SourceFiles/codegen/common/checked_utf8_string.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/common/checked_utf8_string.h" - -#include -#include - -#include "codegen/common/const_utf8_string.h" - -namespace codegen { -namespace common { - -CheckedUtf8String::CheckedUtf8String(const char *string, int size) { - if (size < 0) { - size = strlen(string); - } - if (!size) { // Valid empty string - return; - } - - QTextCodec::ConverterState state; - QTextCodec *codec = QTextCodec::codecForName("UTF-8"); - string_ = codec->toUnicode(string, size, &state); - if (state.invalidChars > 0) { - valid_ = false; - } -} - -CheckedUtf8String::CheckedUtf8String(const QByteArray &string) : CheckedUtf8String(string.constData(), string.size()) { -} - -CheckedUtf8String::CheckedUtf8String(const ConstUtf8String &string) : CheckedUtf8String(string.data(), string.size()) { -} - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/checked_utf8_string.h b/Telegram/SourceFiles/codegen/common/checked_utf8_string.h deleted file mode 100644 index a5f287e67..000000000 --- a/Telegram/SourceFiles/codegen/common/checked_utf8_string.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -class QByteArray; - -namespace codegen { -namespace common { - -class ConstUtf8String; - -// Parses a char sequence to a QString using UTF-8 codec. -// You can check for invalid UTF-8 sequence by isValid() method. -class CheckedUtf8String { -public: - CheckedUtf8String(const CheckedUtf8String &other) = default; - CheckedUtf8String &operator=(const CheckedUtf8String &other) = default; - - explicit CheckedUtf8String(const char *string, int size = -1); - explicit CheckedUtf8String(const QByteArray &string); - explicit CheckedUtf8String(const ConstUtf8String &string); - - bool isValid() const { - return valid_; - } - const QString &toString() const { - return string_; - } - -private: - QString string_; - bool valid_ = true; - -}; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/clean_file.cpp b/Telegram/SourceFiles/codegen/common/clean_file.cpp deleted file mode 100644 index d95ea1ef9..000000000 --- a/Telegram/SourceFiles/codegen/common/clean_file.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/common/clean_file.h" - -#include -#include - -#include "codegen/common/logging.h" - -namespace codegen { -namespace common { -namespace { - -bool readFile(const QString &filepath, QByteArray *outResult) { - QFile f(filepath); - if (!f.exists()) { - logError(kErrorFileNotFound, filepath) << ": error: file does not exist."; - return false; - } - auto limit = CleanFile::MaxSize; - if (f.size() > limit) { - logError(kErrorFileTooLarge, filepath) << "' is too large, size=" << f.size() << " > maxsize=" << limit; - return false; - } - if (!f.open(QIODevice::ReadOnly)) { - logError(kErrorFileNotOpened, filepath) << "' for read."; - return false; - } - *outResult = f.readAll(); - return true; -} - -} // namespace - - -CleanFile::CleanFile(const QString &filepath) -: filepath_(filepath) -, read_(true) { -} - -CleanFile::CleanFile(const QByteArray &content, const QString &filepath) -: filepath_(filepath) -, content_(content) -, read_(false) { -} - -bool CleanFile::read() { - if (read_) { - if (!readFile(filepath_, &content_)) { - return false; - } - } - filepath_ = QFileInfo(filepath_).absoluteFilePath(); - - enum class InsideComment { - None, - SingleLine, - MultiLine, - }; - auto insideComment = InsideComment::None; - bool insideString = false; - - const char *begin = content_.cbegin(), *end = content_.cend(), *offset = begin; - auto feedContent = [this, &offset, end](const char *ch) { - if (ch > offset) { - if (result_.isEmpty()) result_.reserve(end - offset - 2); - result_.append(offset, ch - offset); - offset = ch; - } - }; - - auto lineNumber = 0; - auto feedComment = [this, &offset, end, &lineNumber](const char *ch, bool save = false) { - if (ch > offset) { - if (save) { - singleLineComments_.resize(lineNumber + 1); - singleLineComments_[lineNumber] = QByteArray(offset, ch - offset); - } - if (result_.isEmpty()) { - result_.reserve(end - offset - 2); - } - result_.append(' '); - offset = ch; - } - }; - for (const char *ch = offset; ch != end;) { - char currentChar = *ch; - char nextChar = (ch + 1 == end) ? 0 : *(ch + 1); - - if (insideComment == InsideComment::None && currentChar == '"') { - bool escaped = ((ch > begin) && *(ch - 1) == '\\') && ((ch - 1 < begin) || *(ch - 2) != '\\'); - if (!escaped) { - insideString = !insideString; - } - } - if (insideString) { - if (currentChar == '\n') { - ++lineNumber; - } - ++ch; - continue; - } - - if (insideComment == InsideComment::None && currentChar == '/' && nextChar == '/') { - feedContent(ch); - insideComment = InsideComment::SingleLine; - ch += 2; - } else if (insideComment == InsideComment::SingleLine && currentChar == '\r' && nextChar == '\n') { - feedComment(ch, true); - ch += 2; - ++lineNumber; - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::SingleLine && currentChar == '\n') { - feedComment(ch, true); - ++ch; - ++lineNumber; - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::None && currentChar == '/' && nextChar == '*') { - feedContent(ch); - ch += 2; - insideComment = InsideComment::MultiLine; - } else if (insideComment == InsideComment::MultiLine && currentChar == '*' && nextChar == '/') { - ch += 2; - feedComment(ch); - insideComment = InsideComment::None; - } else if (insideComment == InsideComment::MultiLine && currentChar == '\r' && nextChar == '\n') { - feedComment(ch); - ch += 2; - ++lineNumber; - feedContent(ch); - } else if (insideComment == InsideComment::MultiLine && currentChar == '\n') { - feedComment(ch); - ++ch; - ++lineNumber; - feedContent(ch); - } else { - if (currentChar == '\n') { - ++lineNumber; - } - ++ch; - } - } - singleLineComments_.resize(lineNumber + 1); - - if (insideComment == InsideComment::MultiLine) { - common::logError(kErrorUnexpectedEndOfFile, filepath_); - return false; - } - if (insideComment == InsideComment::None && end > offset) { - if (result_.isEmpty()) { - result_ = content_; - } else { - result_.append(offset, end - offset); - } - } - return true; -} - -QVector CleanFile::singleLineComments() const { - return singleLineComments_; -} - -LogStream CleanFile::logError(int code, int line) const { - return common::logError(code, filepath_, line); -} - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/clean_file.h b/Telegram/SourceFiles/codegen/common/clean_file.h deleted file mode 100644 index e3936aa21..000000000 --- a/Telegram/SourceFiles/codegen/common/clean_file.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include - -#include "codegen/common/logging.h" - -namespace codegen { -namespace common { - -// Reads a file removing all C-style comments. -class CleanFile { -public: - explicit CleanFile(const QString &filepath); - explicit CleanFile(const QByteArray &content, const QString &filepath = QString()); - CleanFile(const CleanFile &other) = delete; - CleanFile &operator=(const CleanFile &other) = delete; - - bool read(); - QVector singleLineComments() const; - - const char *data() const { - return result_.constData(); - } - const char *end() const { - return result_.constEnd(); - } - - static constexpr int MaxSize = 10 * 1024 * 1024; - - // Log error to std::cerr with 'code' at line number 'line' in data(). - LogStream logError(int code, int line) const; - -private: - QString filepath_; - QByteArray content_, result_; - bool read_; - - QVector singleLineComments_; - -}; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/clean_file_reader.h b/Telegram/SourceFiles/codegen/common/clean_file_reader.h deleted file mode 100644 index be555d3e0..000000000 --- a/Telegram/SourceFiles/codegen/common/clean_file_reader.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include - -#include "codegen/common/clean_file.h" - -namespace codegen { -namespace common { - -// Wrapper allows you to read forward the CleanFile without overflow checks. -class CleanFileReader { -public: - explicit CleanFileReader(const QString &filepath) : file_(filepath) { - } - explicit CleanFileReader(const QByteArray &content, const QString &filepath = QString()) : file_(content, filepath) { - } - - bool read() { - if (!file_.read()) { - return false; - } - pos_ = file_.data(); - end_ = file_.end(); - return true; - } - bool atEnd() const { - return (pos_ == end_); - } - char currentChar() const { - return atEnd() ? 0 : *pos_; - } - bool skipChar() { - if (atEnd()) { - return false; - } - ++pos_; - return true; - } - const char *currentPtr() const { - return pos_; - } - int charsLeft() const { - return (end_ - pos_); - } - - QVector singleLineComments() const { - return file_.singleLineComments(); - } - - // Log error to std::cerr with 'code' at line number 'line' in data(). - LogStream logError(int code, int line) const { - return std::forward(file_.logError(code, line)); - } - - -private: - CleanFile file_; - const char *pos_ = nullptr; - const char *end_ = nullptr; - -}; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/const_utf8_string.h b/Telegram/SourceFiles/codegen/common/const_utf8_string.h deleted file mode 100644 index 1ac8af471..000000000 --- a/Telegram/SourceFiles/codegen/common/const_utf8_string.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include - -namespace codegen { -namespace common { - -// This is a simple wrapper around (const char*, size). -// Not null-terminated! It does not hold any ownership. -class ConstUtf8String { -public: - explicit ConstUtf8String(const char *string, int size = -1) : string_(string) { - if (size < 0) { - size = strlen(string); - } - size_ = size; - } - ConstUtf8String(const char *string, const char *end) : ConstUtf8String(string, end - string) { - } - - QByteArray toByteArray() const { - return QByteArray(string_, size_); - } - std::string toStdString() const { - return std::string(string_, size_); - } - QString toStringUnchecked() const { - return QString::fromUtf8(string_, size_); - } - bool empty() const { - return size_ == 0; - } - const char *data() const { - return string_; - } - int size() const { - return size_; - } - const char *end() const { - return data() + size(); - } - ConstUtf8String mid(int pos, int size = -1) { - return ConstUtf8String(string_ + pos, std::max(std::min(size, size_ - pos), 0)); - } - -private: - const char *string_; - int size_; - -}; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/cpp_file.cpp b/Telegram/SourceFiles/codegen/common/cpp_file.cpp deleted file mode 100644 index 842f1e8d2..000000000 --- a/Telegram/SourceFiles/codegen/common/cpp_file.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/common/cpp_file.h" - -#include -#include - -namespace codegen { -namespace common { -namespace { - -void writeLicense(QTextStream &stream, const ProjectInfo &project) { - stream << "\ -/*\n\ -WARNING! All changes made in this file will be lost!\n\ -Created from '" << project.source << "' by '" << project.name << "'\n\ -\n\ -This file is part of Telegram Desktop,\n\ -the official desktop application for the Telegram messaging service.\n\ -\n\ -For license and copyright information please follow this link:\n\ -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL\n\ -*/\n"; -} - -} // namespace - -CppFile::CppFile(const QString &path, const ProjectInfo &project) -: stream_(&content_) -, forceReGenerate_(project.forceReGenerate) { - bool cpp = path.toLower().endsWith(".cpp"); - - QFileInfo info(path); - info.dir().mkpath("."); - filepath_ = info.absoluteFilePath(); - - writeLicense(stream_, project); - if (cpp) { - include(info.baseName() + ".h").newline(); - } else { - stream() << "#pragma once"; - newline().newline(); - } -} - -CppFile &CppFile::include(const QString &header) { - stream() << "#include \"" << header << "\""; - return newline(); -} - -CppFile &CppFile::includeFromLibrary(const QString &header) { - stream() << "#include <" << header << ">"; - return newline(); -} - -CppFile &CppFile::pushNamespace(const QString &name) { - namespaces_.push_back(name); - - stream() << "namespace"; - if (!name.isEmpty()) { - stream() << ' ' << name; - } - stream() << " {"; - return newline(); -} - -CppFile &CppFile::popNamespace() { - if (namespaces_.isEmpty()) { - return *this; - } - auto name = namespaces_.back(); - namespaces_.pop_back(); - - stream() << "} // namespace"; - if (!name.isEmpty()) { - stream() << ' ' << name; - } - return newline(); -} - -bool CppFile::finalize() { - while (!namespaces_.isEmpty()) { - popNamespace(); - } - stream_.flush(); - - QFile file(filepath_); - if (!forceReGenerate_ && file.open(QIODevice::ReadOnly)) { - if (file.readAll() == content_) { - file.close(); - return true; - } - file.close(); - } - - if (!file.open(QIODevice::WriteOnly)) { - return false; - } - if (file.write(content_) != content_.size()) { - return false; - } - return true; -} - -} // namespace common -} // namespace codegen \ No newline at end of file diff --git a/Telegram/SourceFiles/codegen/common/cpp_file.h b/Telegram/SourceFiles/codegen/common/cpp_file.h deleted file mode 100644 index e2731b32a..000000000 --- a/Telegram/SourceFiles/codegen/common/cpp_file.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include - -namespace codegen { -namespace common { - -struct ProjectInfo { - QString name; - QString source; - bool forceReGenerate; -}; - -// Creates a file with license header and codegen warning. -class CppFile { -public: - // If "basepath" is empty the folder containing "path" will be chosen. - // File ending with .cpp will be treated as source, otherwise like header. - CppFile(const QString &path, const ProjectInfo &project); - - QTextStream &stream() { - return stream_; - } - - CppFile &newline() { - stream() << "\n"; - return *this; - } - CppFile &include(const QString &header); - CppFile &includeFromLibrary(const QString &header); - - // Empty name adds anonymous namespace. - CppFile &pushNamespace(const QString &name = QString()); - CppFile &popNamespace(); - - bool finalize(); - -private: - QString filepath_; - QByteArray content_; - QTextStream stream_; - QVector namespaces_; - bool forceReGenerate_; - -}; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/common/logging.cpp b/Telegram/SourceFiles/codegen/common/logging.cpp deleted file mode 100644 index 9e029e10c..000000000 --- a/Telegram/SourceFiles/codegen/common/logging.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/common/logging.h" - -#include -#include - -namespace codegen { -namespace common { -namespace { - -QString WorkingPath = "."; - -std::string relativeLocalPath(const QString &filepath) { - auto name = QFile::encodeName(QDir(WorkingPath).relativeFilePath(filepath)); - return name.constData(); -} - -} // namespace - -LogStream logError(int code, const QString &filepath, int line) { - std::cerr << relativeLocalPath(filepath); - if (line > 0) { - std::cerr << '(' << line << ')'; - } - std::cerr << ": error " << code << ": "; - return LogStream(std::cerr); -} - -void logSetWorkingPath(const QString &workingpath) { - WorkingPath = workingpath; -} - -} // namespace common -} // namespace codegen \ No newline at end of file diff --git a/Telegram/SourceFiles/codegen/common/logging.h b/Telegram/SourceFiles/codegen/common/logging.h deleted file mode 100644 index dc5e714cf..000000000 --- a/Telegram/SourceFiles/codegen/common/logging.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace codegen { -namespace common { - -// Common error codes. -constexpr int kErrorFileNotFound = 101; -constexpr int kErrorFileTooLarge = 102; -constexpr int kErrorFileNotOpened = 103; -constexpr int kErrorUnexpectedEndOfFile = 104; - -// Wrapper around std::ostream that adds '\n' to the end of the logging line. -class LogStream { -public: - enum NullType { - Null, - }; - explicit LogStream(NullType) : final_(false) { - } - explicit LogStream(std::ostream &stream) : stream_(&stream) { - } - LogStream(LogStream &&other) : stream_(other.stream_), final_(other.final_) { - other.final_ = false; - } - std::ostream *stream() const { - return stream_; - } - ~LogStream() { - if (final_) { - *stream_ << '\n'; - } - } - -private: - std::ostream *stream_ = nullptr; - bool final_ = true; - -}; - -template -LogStream operator<<(LogStream &&stream, T &&value) { - if (auto ostream = stream.stream()) { - *ostream << std::forward(value); - } - return std::forward(stream); -} - -// Outputs file name, line number and error code to std::err. Usage: -// logError(kErrorFileTooLarge, filepath) << "file too large, size=" << size; -LogStream logError(int code, const QString &filepath, int line = 0); - -void logSetWorkingPath(const QString &workingpath); - -static constexpr int kErrorInternal = 666; - -} // namespace common -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/data.cpp b/Telegram/SourceFiles/codegen/emoji/data.cpp deleted file mode 100644 index d60972171..000000000 --- a/Telegram/SourceFiles/codegen/emoji/data.cpp +++ /dev/null @@ -1,4030 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/emoji/data.h" - -namespace codegen { -namespace emoji { -namespace { - -using uint16 = quint16; -using uint32 = quint32; -using uint64 = quint64; - -using std::vector; -using std::map; -using std::set; -using std::find; -using std::make_pair; -using std::move; -using std::begin; -using std::end; - -using InputId = vector; -using InputCategory = vector; - -namespace old { -extern InputCategory ColoredEmoji; -extern InputCategory Category1; -extern InputCategory Category2; -extern InputCategory Category3; -extern InputCategory Category4; -extern InputCategory Category5; -extern InputCategory Category6; -extern InputCategory Category7; -} // namespace old - -// copied from emoji_box.cpp -struct Replace { - InputId code; - const char *replace; -}; - -Replace Replaces[] = { - { { 0xD83DDE0AU }, ":-)" }, - { { 0xD83DDE0DU }, "8-)" }, - { { 0x2764U }, "<3" }, -// { { 0xD83DDC8BU }, ":kiss:" }, -// { { 0xD83DDE01U }, ":grin:" }, -// { { 0xD83DDE02U }, ":joy:" }, - { { 0xD83DDE1AU }, ":-*" }, -// { { 0xD83DDE06U }, "xD" }, // Conflicts with typing xDDD... -// { { 0xD83DDC4DU }, ":like:" }, -// { { 0xD83DDC4EU }, ":dislike:" }, -// { { 0x261DU }, ":up:" }, -// { { 0x270CU }, ":v:" }, -// { { 0xD83DDC4CU }, ":ok:" }, - { { 0xD83DDE0EU }, "B-)" }, - { { 0xD83DDE03U }, ":-D" }, - { { 0xD83DDE09U }, ";-)" }, - { { 0xD83DDE1CU }, ";-P" }, - { { 0xD83DDE0BU }, ":-p" }, - { { 0xD83DDE14U }, "3(" }, - { { 0xD83DDE1EU }, ":-(" }, - { { 0xD83DDE0FU }, ":]" }, - { { 0xD83DDE22U }, ":'(" }, - { { 0xD83DDE2DU }, ":_(" }, - { { 0xD83DDE29U }, ":((" }, -// { { 0xD83DDE28U }, ":o" }, // Conflicts with typing :ok... - { { 0xD83DDE10U }, ":|" }, - { { 0xD83DDE0CU }, "3-)" }, - { { 0xD83DDE20U }, ">(" }, - { { 0xD83DDE21U }, ">((" }, - { { 0xD83DDE07U }, "O:)" }, - { { 0xD83DDE30U }, ";o" }, - { { 0xD83DDE33U }, "8|" }, - { { 0xD83DDE32U }, "8o" }, - { { 0xD83DDE37U }, ":X" }, - { { 0xD83DDE08U }, "}:)" }, -}; - -InputCategory PostfixRequired = { - { 0x2122U, 0xFE0FU, }, - { 0xA9U, 0xFE0FU, }, - { 0xAEU, 0xFE0FU, }, -}; - -using ColorId = uint32; -ColorId Colors[] = { - 0xD83CDFFBU, - 0xD83CDFFCU, - 0xD83CDFFDU, - 0xD83CDFFEU, - 0xD83CDFFFU, -}; - -constexpr auto ColorMask = 0xD83CDFFBU; -InputCategory ColoredEmoji = { - { 0xD83EDD32U, 0xD83CDFFBU, }, - { 0xD83DDC50U, 0xD83CDFFBU, }, - { 0xD83DDE4CU, 0xD83CDFFBU, }, - { 0xD83DDC4FU, 0xD83CDFFBU, }, - { 0xD83DDC4DU, 0xD83CDFFBU, }, - { 0xD83DDC4EU, 0xD83CDFFBU, }, - { 0xD83DDC4AU, 0xD83CDFFBU, }, - { 0x270AU, 0xD83CDFFBU, }, - { 0xD83EDD1BU, 0xD83CDFFBU, }, - { 0xD83EDD1CU, 0xD83CDFFBU, }, - { 0xD83EDD1EU, 0xD83CDFFBU, }, - { 0x270CU, 0xD83CDFFBU, }, - { 0xD83EDD1FU, 0xD83CDFFBU, }, - { 0xD83EDD18U, 0xD83CDFFBU, }, - { 0xD83DDC4CU, 0xD83CDFFBU, }, - { 0xD83DDC48U, 0xD83CDFFBU, }, - { 0xD83DDC49U, 0xD83CDFFBU, }, - { 0xD83DDC46U, 0xD83CDFFBU, }, - { 0xD83DDC47U, 0xD83CDFFBU, }, - { 0x261DU, 0xD83CDFFBU, }, - { 0x270BU, 0xD83CDFFBU, }, - { 0xD83EDD1AU, 0xD83CDFFBU, }, - { 0xD83DDD90U, 0xD83CDFFBU, }, - { 0xD83DDD96U, 0xD83CDFFBU, }, - { 0xD83DDC4BU, 0xD83CDFFBU, }, - { 0xD83EDD19U, 0xD83CDFFBU, }, - { 0xD83DDCAAU, 0xD83CDFFBU, }, - { 0xD83DDD95U, 0xD83CDFFBU, }, - { 0x270DU, 0xD83CDFFBU, }, - { 0xD83DDE4FU, 0xD83CDFFBU, }, - { 0xD83EDDB6U, 0xD83CDFFBU, }, - { 0xD83EDDB5U, 0xD83CDFFBU, }, - { 0xD83DDC42U, 0xD83CDFFBU, }, - { 0xD83DDC43U, 0xD83CDFFBU, }, - { 0xD83DDC76U, 0xD83CDFFBU, }, - { 0xD83DDC67U, 0xD83CDFFBU, }, - { 0xD83EDDD2U, 0xD83CDFFBU, }, - { 0xD83DDC66U, 0xD83CDFFBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, }, - { 0xD83EDDD1U, 0xD83CDFFBU, }, - { 0xD83DDC68U, 0xD83CDFFBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB1U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB1U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB0U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB0U, }, - { 0xD83DDC71U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC71U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB3U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB3U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB2U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83EDDB2U, }, - { 0xD83EDDD4U, 0xD83CDFFBU, }, - { 0xD83DDC75U, 0xD83CDFFBU, }, - { 0xD83EDDD3U, 0xD83CDFFBU, }, - { 0xD83DDC74U, 0xD83CDFFBU, }, - { 0xD83DDC72U, 0xD83CDFFBU, }, - { 0xD83DDC73U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC73U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDD5U, 0xD83CDFFBU, }, - { 0xD83DDC6EU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC6EU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC77U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC77U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC82U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC82U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDD75U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDD75U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83DDC70U, 0xD83CDFFBU, }, - { 0xD83EDD35U, 0xD83CDFFBU, }, - { 0xD83DDC78U, 0xD83CDFFBU, }, - { 0xD83EDD34U, 0xD83CDFFBU, }, - { 0xD83EDDB8U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDB8U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDB9U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDB9U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD36U, 0xD83CDFFBU, }, - { 0xD83CDF85U, 0xD83CDFFBU, }, - { 0xD83EDDD9U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD9U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDDU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDDU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDBU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDBU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDCU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDCU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDAU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDAU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC7CU, 0xD83CDFFBU, }, - { 0xD83EDD30U, 0xD83CDFFBU, }, - { 0xD83EDD31U, 0xD83CDFFBU, }, - { 0xD83DDE47U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE47U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC81U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC81U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE45U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE45U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE46U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE46U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4BU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE4BU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD26U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD26U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD37U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD37U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4EU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE4EU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4DU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE4DU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC87U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC87U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC86U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC86U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDD6U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD6U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC85U, 0xD83CDFFBU, }, - { 0xD83EDD33U, 0xD83CDFFBU, }, - { 0xD83DDC83U, 0xD83CDFFBU, }, - { 0xD83DDD7AU, 0xD83CDFFBU, }, - { 0xD83DDD74U, 0xD83CDFFBU, }, - { 0xD83DDEB6U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB6U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFC3U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC3U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFCBU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCBU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD38U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD38U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0x26F9U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0x26F9U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD3EU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3EU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFC7U, 0xD83CDFFBU, }, - { 0xD83EDDD8U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD8U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFC4U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC4U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFCAU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCAU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD3DU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3DU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEA3U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEA3U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDD7U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD7U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEB5U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB5U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEB4U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB4U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD39U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD39U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEC0U, 0xD83CDFFBU, }, -}; - -InputCategory Category1 = { - { 0xD83DDE00U, }, - { 0xD83DDE03U, }, - { 0xD83DDE04U, }, - { 0xD83DDE01U, }, - { 0xD83DDE06U, }, - { 0xD83DDE05U, }, - { 0xD83DDE02U, }, - { 0xD83EDD23U, }, - { 0x263AU, 0xFE0FU, }, - { 0xD83DDE0AU, }, - { 0xD83DDE07U, }, - { 0xD83DDE42U, }, - { 0xD83DDE43U, }, - { 0xD83DDE09U, }, - { 0xD83DDE0CU, }, - { 0xD83DDE0DU, }, - { 0xD83EDD70U, }, - { 0xD83DDE18U, }, - { 0xD83DDE17U, }, - { 0xD83DDE19U, }, - { 0xD83DDE1AU, }, - { 0xD83DDE0BU, }, - { 0xD83DDE1BU, }, - { 0xD83DDE1DU, }, - { 0xD83DDE1CU, }, - { 0xD83EDD2AU, }, - { 0xD83EDD28U, }, - { 0xD83EDDD0U, }, - { 0xD83EDD13U, }, - { 0xD83DDE0EU, }, - { 0xD83EDD29U, }, - { 0xD83EDD73U, }, - { 0xD83DDE0FU, }, - { 0xD83DDE12U, }, - { 0xD83DDE1EU, }, - { 0xD83DDE14U, }, - { 0xD83DDE1FU, }, - { 0xD83DDE15U, }, - { 0xD83DDE41U, }, - { 0x2639U, 0xFE0FU, }, - { 0xD83DDE23U, }, - { 0xD83DDE16U, }, - { 0xD83DDE2BU, }, - { 0xD83DDE29U, }, - { 0xD83EDD7AU, }, - { 0xD83DDE22U, }, - { 0xD83DDE2DU, }, - { 0xD83DDE24U, }, - { 0xD83DDE20U, }, - { 0xD83DDE21U, }, - { 0xD83EDD2CU, }, - { 0xD83EDD2FU, }, - { 0xD83DDE33U, }, - { 0xD83EDD75U, }, - { 0xD83EDD76U, }, - { 0xD83DDE31U, }, - { 0xD83DDE28U, }, - { 0xD83DDE30U, }, - { 0xD83DDE25U, }, - { 0xD83DDE13U, }, - { 0xD83EDD17U, }, - { 0xD83EDD14U, }, - { 0xD83EDD2DU, }, - { 0xD83EDD2BU, }, - { 0xD83EDD25U, }, - { 0xD83DDE36U, }, - { 0xD83DDE10U, }, - { 0xD83DDE11U, }, - { 0xD83DDE2CU, }, - { 0xD83DDE44U, }, - { 0xD83DDE2FU, }, - { 0xD83DDE26U, }, - { 0xD83DDE27U, }, - { 0xD83DDE2EU, }, - { 0xD83DDE32U, }, - { 0xD83DDE34U, }, - { 0xD83EDD24U, }, - { 0xD83DDE2AU, }, - { 0xD83DDE35U, }, - { 0xD83EDD10U, }, - { 0xD83EDD74U, }, - { 0xD83EDD22U, }, - { 0xD83EDD2EU, }, - { 0xD83EDD27U, }, - { 0xD83DDE37U, }, - { 0xD83EDD12U, }, - { 0xD83EDD15U, }, - { 0xD83EDD11U, }, - { 0xD83EDD20U, }, - { 0xD83DDE08U, }, - { 0xD83DDC7FU, }, - { 0xD83DDC79U, }, - { 0xD83DDC7AU, }, - { 0xD83EDD21U, }, - { 0xD83DDCA9U, }, - { 0xD83DDC7BU, }, - { 0xD83DDC80U, }, - { 0x2620U, 0xFE0FU, }, - { 0xD83DDC7DU, }, - { 0xD83DDC7EU, }, - { 0xD83EDD16U, }, - { 0xD83CDF83U, }, - { 0xD83DDE3AU, }, - { 0xD83DDE38U, }, - { 0xD83DDE39U, }, - { 0xD83DDE3BU, }, - { 0xD83DDE3CU, }, - { 0xD83DDE3DU, }, - { 0xD83DDE40U, }, - { 0xD83DDE3FU, }, - { 0xD83DDE3EU, }, - { 0xD83EDD32U, }, - { 0xD83DDC50U, }, - { 0xD83DDE4CU, }, - { 0xD83DDC4FU, }, - { 0xD83EDD1DU, }, - { 0xD83DDC4DU, }, - { 0xD83DDC4EU, }, - { 0xD83DDC4AU, }, - { 0x270AU, }, - { 0xD83EDD1BU, }, - { 0xD83EDD1CU, }, - { 0xD83EDD1EU, }, - { 0x270CU, 0xFE0FU, }, - { 0xD83EDD1FU, }, - { 0xD83EDD18U, }, - { 0xD83DDC4CU, }, - { 0xD83DDC48U, }, - { 0xD83DDC49U, }, - { 0xD83DDC46U, }, - { 0xD83DDC47U, }, - { 0x261DU, 0xFE0FU, }, - { 0x270BU, }, - { 0xD83EDD1AU, }, - { 0xD83DDD90U, }, - { 0xD83DDD96U, }, - { 0xD83DDC4BU, }, - { 0xD83EDD19U, }, - { 0xD83DDCAAU, }, - { 0xD83DDD95U, }, - { 0x270DU, 0xFE0FU, }, - { 0xD83DDE4FU, }, - { 0xD83EDDB6U, }, - { 0xD83EDDB5U, }, - { 0xD83DDC84U, }, - { 0xD83DDC8BU, }, - { 0xD83DDC44U, }, - { 0xD83EDDB7U, }, - { 0xD83DDC45U, }, - { 0xD83DDC42U, }, - { 0xD83DDC43U, }, - { 0xD83DDC63U, }, - { 0xD83DDC41U, }, - { 0xD83DDC40U, }, - { 0xD83EDDE0U, }, - { 0xD83DDDE3U, }, - { 0xD83DDC64U, }, - { 0xD83DDC65U, }, - { 0xD83DDC76U, }, - { 0xD83DDC67U, }, - { 0xD83EDDD2U, }, - { 0xD83DDC66U, }, - { 0xD83DDC69U, }, - { 0xD83EDDD1U, }, - { 0xD83DDC68U, }, - { 0xD83DDC69U, 0x200DU, 0xD83EDDB1U, }, - { 0xD83DDC68U, 0x200DU, 0xD83EDDB1U, }, - { 0xD83DDC69U, 0x200DU, 0xD83EDDB0U, }, - { 0xD83DDC68U, 0x200DU, 0xD83EDDB0U, }, - { 0xD83DDC71U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC71U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC69U, 0x200DU, 0xD83EDDB3U, }, - { 0xD83DDC68U, 0x200DU, 0xD83EDDB3U, }, - { 0xD83DDC69U, 0x200DU, 0xD83EDDB2U, }, - { 0xD83DDC68U, 0x200DU, 0xD83EDDB2U, }, - { 0xD83EDDD4U, }, - { 0xD83DDC75U, }, - { 0xD83EDDD3U, }, - { 0xD83DDC74U, }, - { 0xD83DDC72U, }, - { 0xD83DDC73U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC73U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDD5U, }, - { 0xD83DDC6EU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC6EU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC77U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC77U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC82U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC82U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDD75U, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDD75U, 0xFE0FU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC69U, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC68U, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC69U, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC68U, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC69U, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83DDC68U, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83DDC70U, }, - { 0xD83EDD35U, }, - { 0xD83DDC78U, }, - { 0xD83EDD34U, }, - { 0xD83EDDB8U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDB8U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDB9U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDB9U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD36U, }, - { 0xD83CDF85U, }, - { 0xD83EDDD9U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD9U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDDU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDDU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDFU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDFU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDEU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDEU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDCU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDCU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDDAU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDDAU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC7CU, }, - { 0xD83EDD30U, }, - { 0xD83EDD31U, }, - { 0xD83DDE47U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE47U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC81U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC81U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE45U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE45U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE46U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE46U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4BU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE4BU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD26U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD26U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD37U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD37U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4EU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE4EU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4DU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE4DU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC87U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC87U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC86U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC86U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDD6U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD6U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC85U, }, - { 0xD83EDD33U, }, - { 0xD83DDC83U, }, - { 0xD83DDD7AU, }, - { 0xD83DDC6FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC6FU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDD74U, }, - { 0xD83DDEB6U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB6U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFC3U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC3U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC6BU, }, - { 0xD83DDC6DU, }, - { 0xD83DDC6CU, }, - { 0xD83DDC91U, }, - { 0xD83DDC69U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC69U, }, - { 0xD83DDC68U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC68U, }, - { 0xD83DDC8FU, }, - { 0xD83DDC69U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC8BU, 0x200DU, 0xD83DDC69U, }, - { 0xD83DDC68U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC8BU, 0x200DU, 0xD83DDC68U, }, - { 0xD83DDC6AU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83EDDF6U, }, - { 0xD83EDDF5U, }, - { 0xD83EDDE5U, }, - { 0xD83EDD7CU, }, - { 0xD83DDC5AU, }, - { 0xD83DDC55U, }, - { 0xD83DDC56U, }, - { 0xD83DDC54U, }, - { 0xD83DDC57U, }, - { 0xD83DDC59U, }, - { 0xD83DDC58U, }, - { 0xD83EDD7FU, }, - { 0xD83DDC60U, }, - { 0xD83DDC61U, }, - { 0xD83DDC62U, }, - { 0xD83DDC5EU, }, - { 0xD83DDC5FU, }, - { 0xD83EDD7EU, }, - { 0xD83EDDE6U, }, - { 0xD83EDDE4U, }, - { 0xD83EDDE3U, }, - { 0xD83CDFA9U, }, - { 0xD83EDDE2U, }, - { 0xD83DDC52U, }, - { 0xD83CDF93U, }, - { 0x26D1U, }, - { 0xD83DDC51U, }, - { 0xD83DDC8DU, }, - { 0xD83DDC5DU, }, - { 0xD83DDC5BU, }, - { 0xD83DDC5CU, }, - { 0xD83DDCBCU, }, - { 0xD83CDF92U, }, - { 0xD83EDDF3U, }, - { 0xD83DDC53U, }, - { 0xD83DDD76U, }, - { 0xD83EDD7DU, }, - { 0xD83CDF02U, }, -}; - -InputCategory Category2 = { - { 0xD83DDC36U, }, - { 0xD83DDC31U, }, - { 0xD83DDC2DU, }, - { 0xD83DDC39U, }, - { 0xD83DDC30U, }, - { 0xD83EDD8AU, }, - { 0xD83DDC3BU, }, - { 0xD83DDC3CU, }, - { 0xD83DDC28U, }, - { 0xD83DDC2FU, }, - { 0xD83EDD81U, }, - { 0xD83DDC2EU, }, - { 0xD83DDC37U, }, - { 0xD83DDC3DU, }, - { 0xD83DDC38U, }, - { 0xD83DDC35U, }, - { 0xD83DDE48U, }, - { 0xD83DDE49U, }, - { 0xD83DDE4AU, }, - { 0xD83DDC12U, }, - { 0xD83DDC14U, }, - { 0xD83DDC27U, }, - { 0xD83DDC26U, }, - { 0xD83DDC24U, }, - { 0xD83DDC23U, }, - { 0xD83DDC25U, }, - { 0xD83EDD86U, }, - { 0xD83EDD85U, }, - { 0xD83EDD89U, }, - { 0xD83EDD87U, }, - { 0xD83DDC3AU, }, - { 0xD83DDC17U, }, - { 0xD83DDC34U, }, - { 0xD83EDD84U, }, - { 0xD83DDC1DU, }, - { 0xD83DDC1BU, }, - { 0xD83EDD8BU, }, - { 0xD83DDC0CU, }, - { 0xD83DDC1EU, }, - { 0xD83DDC1CU, }, - { 0xD83EDD9FU, }, - { 0xD83EDD97U, }, - { 0xD83DDD77U, }, - { 0xD83DDD78U, }, - { 0xD83EDD82U, }, - { 0xD83DDC22U, }, - { 0xD83DDC0DU, }, - { 0xD83EDD8EU, }, - { 0xD83EDD96U, }, - { 0xD83EDD95U, }, - { 0xD83DDC19U, }, - { 0xD83EDD91U, }, - { 0xD83EDD90U, }, - { 0xD83EDD9EU, }, - { 0xD83EDD80U, }, - { 0xD83DDC21U, }, - { 0xD83DDC20U, }, - { 0xD83DDC1FU, }, - { 0xD83DDC2CU, }, - { 0xD83DDC33U, }, - { 0xD83DDC0BU, }, - { 0xD83EDD88U, }, - { 0xD83DDC0AU, }, - { 0xD83DDC05U, }, - { 0xD83DDC06U, }, - { 0xD83EDD93U, }, - { 0xD83EDD8DU, }, - { 0xD83DDC18U, }, - { 0xD83EDD9BU, }, - { 0xD83EDD8FU, }, - { 0xD83DDC2AU, }, - { 0xD83DDC2BU, }, - { 0xD83EDD92U, }, - { 0xD83EDD98U, }, - { 0xD83DDC03U, }, - { 0xD83DDC02U, }, - { 0xD83DDC04U, }, - { 0xD83DDC0EU, }, - { 0xD83DDC16U, }, - { 0xD83DDC0FU, }, - { 0xD83DDC11U, }, - { 0xD83EDD99U, }, - { 0xD83DDC10U, }, - { 0xD83EDD8CU, }, - { 0xD83DDC15U, }, - { 0xD83DDC29U, }, - { 0xD83DDC08U, }, - { 0xD83DDC13U, }, - { 0xD83EDD83U, }, - { 0xD83EDD9AU, }, - { 0xD83EDD9CU, }, - { 0xD83EDDA2U, }, - { 0xD83DDD4AU, }, - { 0xD83DDC07U, }, - { 0xD83EDD9DU, }, - { 0xD83EDDA1U, }, - { 0xD83DDC01U, }, - { 0xD83DDC00U, }, - { 0xD83DDC3FU, }, - { 0xD83EDD94U, }, - { 0xD83DDC3EU, }, - { 0xD83DDC09U, }, - { 0xD83DDC32U, }, - { 0xD83CDF35U, }, - { 0xD83CDF84U, }, - { 0xD83CDF32U, }, - { 0xD83CDF33U, }, - { 0xD83CDF34U, }, - { 0xD83CDF31U, }, - { 0xD83CDF3FU, }, - { 0x2618U, 0xFE0FU, }, - { 0xD83CDF40U, }, - { 0xD83CDF8DU, }, - { 0xD83CDF8BU, }, - { 0xD83CDF43U, }, - { 0xD83CDF42U, }, - { 0xD83CDF41U, }, - { 0xD83CDF44U, }, - { 0xD83DDC1AU, }, - { 0xD83CDF3EU, }, - { 0xD83DDC90U, }, - { 0xD83CDF37U, }, - { 0xD83CDF39U, }, - { 0xD83EDD40U, }, - { 0xD83CDF3AU, }, - { 0xD83CDF38U, }, - { 0xD83CDF3CU, }, - { 0xD83CDF3BU, }, - { 0xD83CDF1EU, }, - { 0xD83CDF1DU, }, - { 0xD83CDF1BU, }, - { 0xD83CDF1CU, }, - { 0xD83CDF1AU, }, - { 0xD83CDF15U, }, - { 0xD83CDF16U, }, - { 0xD83CDF17U, }, - { 0xD83CDF18U, }, - { 0xD83CDF11U, }, - { 0xD83CDF12U, }, - { 0xD83CDF13U, }, - { 0xD83CDF14U, }, - { 0xD83CDF19U, }, - { 0xD83CDF0EU, }, - { 0xD83CDF0DU, }, - { 0xD83CDF0FU, }, - { 0xD83DDCABU, }, - { 0x2B50U, 0xFE0FU, }, - { 0xD83CDF1FU, }, - { 0x2728U, }, - { 0x26A1U, 0xFE0FU, }, - { 0x2604U, 0xFE0FU, }, - { 0xD83DDCA5U, }, - { 0xD83DDD25U, }, - { 0xD83CDF2AU, }, - { 0xD83CDF08U, }, - { 0x2600U, 0xFE0FU, }, - { 0xD83CDF24U, }, - { 0x26C5U, 0xFE0FU, }, - { 0xD83CDF25U, }, - { 0x2601U, 0xFE0FU, }, - { 0xD83CDF26U, }, - { 0xD83CDF27U, }, - { 0x26C8U, }, - { 0xD83CDF29U, }, - { 0xD83CDF28U, }, - { 0x2744U, 0xFE0FU, }, - { 0x2603U, 0xFE0FU, }, - { 0x26C4U, 0xFE0FU, }, - { 0xD83CDF2CU, }, - { 0xD83DDCA8U, }, - { 0xD83DDCA7U, }, - { 0xD83DDCA6U, }, - { 0x2614U, 0xFE0FU, }, - { 0x2602U, 0xFE0FU, }, - { 0xD83CDF0AU, }, - { 0xD83CDF2BU, }, -}; - -InputCategory Category3 = { - { 0xD83CDF4FU, }, - { 0xD83CDF4EU, }, - { 0xD83CDF50U, }, - { 0xD83CDF4AU, }, - { 0xD83CDF4BU, }, - { 0xD83CDF4CU, }, - { 0xD83CDF49U, }, - { 0xD83CDF47U, }, - { 0xD83CDF53U, }, - { 0xD83CDF48U, }, - { 0xD83CDF52U, }, - { 0xD83CDF51U, }, - { 0xD83EDD6DU, }, - { 0xD83CDF4DU, }, - { 0xD83EDD65U, }, - { 0xD83EDD5DU, }, - { 0xD83CDF45U, }, - { 0xD83CDF46U, }, - { 0xD83EDD51U, }, - { 0xD83EDD66U, }, - { 0xD83EDD6CU, }, - { 0xD83EDD52U, }, - { 0xD83CDF36U, }, - { 0xD83CDF3DU, }, - { 0xD83EDD55U, }, - { 0xD83EDD54U, }, - { 0xD83CDF60U, }, - { 0xD83EDD50U, }, - { 0xD83EDD6FU, }, - { 0xD83CDF5EU, }, - { 0xD83EDD56U, }, - { 0xD83EDD68U, }, - { 0xD83EDDC0U, }, - { 0xD83EDD5AU, }, - { 0xD83CDF73U, }, - { 0xD83EDD5EU, }, - { 0xD83EDD53U, }, - { 0xD83EDD69U, }, - { 0xD83CDF57U, }, - { 0xD83CDF56U, }, - { 0xD83EDDB4U, }, - { 0xD83CDF2DU, }, - { 0xD83CDF54U, }, - { 0xD83CDF5FU, }, - { 0xD83CDF55U, }, - { 0xD83EDD6AU, }, - { 0xD83EDD59U, }, - { 0xD83CDF2EU, }, - { 0xD83CDF2FU, }, - { 0xD83EDD57U, }, - { 0xD83EDD58U, }, - { 0xD83EDD6BU, }, - { 0xD83CDF5DU, }, - { 0xD83CDF5CU, }, - { 0xD83CDF72U, }, - { 0xD83CDF5BU, }, - { 0xD83CDF63U, }, - { 0xD83CDF71U, }, - { 0xD83EDD5FU, }, - { 0xD83CDF64U, }, - { 0xD83CDF59U, }, - { 0xD83CDF5AU, }, - { 0xD83CDF58U, }, - { 0xD83CDF65U, }, - { 0xD83EDD60U, }, - { 0xD83EDD6EU, }, - { 0xD83CDF62U, }, - { 0xD83CDF61U, }, - { 0xD83CDF67U, }, - { 0xD83CDF68U, }, - { 0xD83CDF66U, }, - { 0xD83EDD67U, }, - { 0xD83EDDC1U, }, - { 0xD83CDF70U, }, - { 0xD83CDF82U, }, - { 0xD83CDF6EU, }, - { 0xD83CDF6DU, }, - { 0xD83CDF6CU, }, - { 0xD83CDF6BU, }, - { 0xD83CDF7FU, }, - { 0xD83CDF69U, }, - { 0xD83CDF6AU, }, - { 0xD83CDF30U, }, - { 0xD83EDD5CU, }, - { 0xD83CDF6FU, }, - { 0xD83EDD5BU, }, - { 0xD83CDF7CU, }, - { 0x2615U, 0xFE0FU, }, - { 0xD83CDF75U, }, - { 0xD83EDD64U, }, - { 0xD83CDF76U, }, - { 0xD83CDF7AU, }, - { 0xD83CDF7BU, }, - { 0xD83EDD42U, }, - { 0xD83CDF77U, }, - { 0xD83EDD43U, }, - { 0xD83CDF78U, }, - { 0xD83CDF79U, }, - { 0xD83CDF7EU, }, - { 0xD83EDD44U, }, - { 0xD83CDF74U, }, - { 0xD83CDF7DU, }, - { 0xD83EDD63U, }, - { 0xD83EDD61U, }, - { 0xD83EDD62U, }, - { 0xD83EDDC2U, }, -}; - -InputCategory Category4 = { - { 0x26BDU, 0xFE0FU, }, - { 0xD83CDFC0U, }, - { 0xD83CDFC8U, }, - { 0x26BEU, 0xFE0FU, }, - { 0xD83EDD4EU, }, - { 0xD83CDFBEU, }, - { 0xD83CDFD0U, }, - { 0xD83CDFC9U, }, - { 0xD83EDD4FU, }, - { 0xD83CDFB1U, }, - { 0xD83CDFD3U, }, - { 0xD83CDFF8U, }, - { 0xD83CDFD2U, }, - { 0xD83CDFD1U, }, - { 0xD83EDD4DU, }, - { 0xD83CDFCFU, }, - { 0xD83EDD45U, }, - { 0x26F3U, 0xFE0FU, }, - { 0xD83CDFF9U, }, - { 0xD83CDFA3U, }, - { 0xD83EDD4AU, }, - { 0xD83EDD4BU, }, - { 0xD83CDFBDU, }, - { 0xD83DDEF9U, }, - { 0xD83DDEF7U, }, - { 0x26F8U, }, - { 0xD83EDD4CU, }, - { 0xD83CDFBFU, }, - { 0x26F7U, }, - { 0xD83CDFC2U, }, - { 0xD83CDFCBU, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCBU, 0xFE0FU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD3CU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3CU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD38U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD38U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0x26F9U, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0x26F9U, 0xFE0FU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD3AU, }, - { 0xD83EDD3EU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3EU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xFE0FU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFC7U, }, - { 0xD83EDDD8U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD8U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFC4U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC4U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFCAU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCAU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD3DU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3DU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEA3U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEA3U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDDD7U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDDD7U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEB5U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB5U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEB4U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB4U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFC6U, }, - { 0xD83EDD47U, }, - { 0xD83EDD48U, }, - { 0xD83EDD49U, }, - { 0xD83CDFC5U, }, - { 0xD83CDF96U, }, - { 0xD83CDFF5U, }, - { 0xD83CDF97U, }, - { 0xD83CDFABU, }, - { 0xD83CDF9FU, }, - { 0xD83CDFAAU, }, - { 0xD83EDD39U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD39U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFADU, }, - { 0xD83CDFA8U, }, - { 0xD83CDFACU, }, - { 0xD83CDFA4U, }, - { 0xD83CDFA7U, }, - { 0xD83CDFBCU, }, - { 0xD83CDFB9U, }, - { 0xD83EDD41U, }, - { 0xD83CDFB7U, }, - { 0xD83CDFBAU, }, - { 0xD83CDFB8U, }, - { 0xD83CDFBBU, }, - { 0xD83CDFB2U, }, - { 0x265FU, }, - { 0xD83CDFAFU, }, - { 0xD83CDFB3U, }, - { 0xD83CDFAEU, }, - { 0xD83CDFB0U, }, - { 0xD83EDDE9U, }, -}; - -InputCategory Category5 = { - { 0xD83DDE97U, }, - { 0xD83DDE95U, }, - { 0xD83DDE99U, }, - { 0xD83DDE8CU, }, - { 0xD83DDE8EU, }, - { 0xD83CDFCEU, }, - { 0xD83DDE93U, }, - { 0xD83DDE91U, }, - { 0xD83DDE92U, }, - { 0xD83DDE90U, }, - { 0xD83DDE9AU, }, - { 0xD83DDE9BU, }, - { 0xD83DDE9CU, }, - { 0xD83DDEF4U, }, - { 0xD83DDEB2U, }, - { 0xD83DDEF5U, }, - { 0xD83CDFCDU, }, - { 0xD83DDEA8U, }, - { 0xD83DDE94U, }, - { 0xD83DDE8DU, }, - { 0xD83DDE98U, }, - { 0xD83DDE96U, }, - { 0xD83DDEA1U, }, - { 0xD83DDEA0U, }, - { 0xD83DDE9FU, }, - { 0xD83DDE83U, }, - { 0xD83DDE8BU, }, - { 0xD83DDE9EU, }, - { 0xD83DDE9DU, }, - { 0xD83DDE84U, }, - { 0xD83DDE85U, }, - { 0xD83DDE88U, }, - { 0xD83DDE82U, }, - { 0xD83DDE86U, }, - { 0xD83DDE87U, }, - { 0xD83DDE8AU, }, - { 0xD83DDE89U, }, - { 0x2708U, 0xFE0FU, }, - { 0xD83DDEEBU, }, - { 0xD83DDEECU, }, - { 0xD83DDEE9U, }, - { 0xD83DDCBAU, }, - { 0xD83DDEF0U, }, - { 0xD83DDE80U, }, - { 0xD83DDEF8U, }, - { 0xD83DDE81U, }, - { 0xD83DDEF6U, }, - { 0x26F5U, 0xFE0FU, }, - { 0xD83DDEA4U, }, - { 0xD83DDEE5U, }, - { 0xD83DDEF3U, }, - { 0x26F4U, }, - { 0xD83DDEA2U, }, - { 0x2693U, 0xFE0FU, }, - { 0x26FDU, 0xFE0FU, }, - { 0xD83DDEA7U, }, - { 0xD83DDEA6U, }, - { 0xD83DDEA5U, }, - { 0xD83DDE8FU, }, - { 0xD83DDDFAU, }, - { 0xD83DDDFFU, }, - { 0xD83DDDFDU, }, - { 0xD83DDDFCU, }, - { 0xD83CDFF0U, }, - { 0xD83CDFEFU, }, - { 0xD83CDFDFU, }, - { 0xD83CDFA1U, }, - { 0xD83CDFA2U, }, - { 0xD83CDFA0U, }, - { 0x26F2U, 0xFE0FU, }, - { 0x26F1U, }, - { 0xD83CDFD6U, }, - { 0xD83CDFDDU, }, - { 0xD83CDFDCU, }, - { 0xD83CDF0BU, }, - { 0x26F0U, }, - { 0xD83CDFD4U, }, - { 0xD83DDDFBU, }, - { 0xD83CDFD5U, }, - { 0x26FAU, 0xFE0FU, }, - { 0xD83CDFE0U, }, - { 0xD83CDFE1U, }, - { 0xD83CDFD8U, }, - { 0xD83CDFDAU, }, - { 0xD83CDFD7U, }, - { 0xD83CDFEDU, }, - { 0xD83CDFE2U, }, - { 0xD83CDFECU, }, - { 0xD83CDFE3U, }, - { 0xD83CDFE4U, }, - { 0xD83CDFE5U, }, - { 0xD83CDFE6U, }, - { 0xD83CDFE8U, }, - { 0xD83CDFEAU, }, - { 0xD83CDFEBU, }, - { 0xD83CDFE9U, }, - { 0xD83DDC92U, }, - { 0xD83CDFDBU, }, - { 0x26EAU, 0xFE0FU, }, - { 0xD83DDD4CU, }, - { 0xD83DDD4DU, }, - { 0xD83DDD4BU, }, - { 0x26E9U, }, - { 0xD83DDEE4U, }, - { 0xD83DDEE3U, }, - { 0xD83DDDFEU, }, - { 0xD83CDF91U, }, - { 0xD83CDFDEU, }, - { 0xD83CDF05U, }, - { 0xD83CDF04U, }, - { 0xD83CDF20U, }, - { 0xD83CDF87U, }, - { 0xD83CDF86U, }, - { 0xD83CDF07U, }, - { 0xD83CDF06U, }, - { 0xD83CDFD9U, }, - { 0xD83CDF03U, }, - { 0xD83CDF0CU, }, - { 0xD83CDF09U, }, - { 0xD83CDF01U, }, -}; - -InputCategory Category6 = { - { 0x231AU, 0xFE0FU, }, - { 0xD83DDCF1U, }, - { 0xD83DDCF2U, }, - { 0xD83DDCBBU, }, - { 0x2328U, 0xFE0FU, }, - { 0xD83DDDA5U, }, - { 0xD83DDDA8U, }, - { 0xD83DDDB1U, }, - { 0xD83DDDB2U, }, - { 0xD83DDD79U, }, - { 0xD83DDDDCU, }, - { 0xD83DDCBDU, }, - { 0xD83DDCBEU, }, - { 0xD83DDCBFU, }, - { 0xD83DDCC0U, }, - { 0xD83DDCFCU, }, - { 0xD83DDCF7U, }, - { 0xD83DDCF8U, }, - { 0xD83DDCF9U, }, - { 0xD83CDFA5U, }, - { 0xD83DDCFDU, }, - { 0xD83CDF9EU, }, - { 0xD83DDCDEU, }, - { 0x260EU, 0xFE0FU, }, - { 0xD83DDCDFU, }, - { 0xD83DDCE0U, }, - { 0xD83DDCFAU, }, - { 0xD83DDCFBU, }, - { 0xD83CDF99U, }, - { 0xD83CDF9AU, }, - { 0xD83CDF9BU, }, - { 0xD83EDDEDU, }, - { 0x23F1U, }, - { 0x23F2U, }, - { 0x23F0U, }, - { 0xD83DDD70U, }, - { 0x231BU, 0xFE0FU, }, - { 0x23F3U, }, - { 0xD83DDCE1U, }, - { 0xD83DDD0BU, }, - { 0xD83DDD0CU, }, - { 0xD83DDCA1U, }, - { 0xD83DDD26U, }, - { 0xD83DDD6FU, }, - { 0xD83EDDEFU, }, - { 0xD83DDEE2U, }, - { 0xD83DDCB8U, }, - { 0xD83DDCB5U, }, - { 0xD83DDCB4U, }, - { 0xD83DDCB6U, }, - { 0xD83DDCB7U, }, - { 0xD83DDCB0U, }, - { 0xD83DDCB3U, }, - { 0xD83DDC8EU, }, - { 0x2696U, 0xFE0FU, }, - { 0xD83EDDF0U, }, - { 0xD83DDD27U, }, - { 0xD83DDD28U, }, - { 0x2692U, }, - { 0xD83DDEE0U, }, - { 0x26CFU, }, - { 0xD83DDD29U, }, - { 0x2699U, 0xFE0FU, }, - { 0xD83EDDF1U, }, - { 0x26D3U, }, - { 0xD83EDDF2U, }, - { 0xD83DDD2BU, }, - { 0xD83DDCA3U, }, - { 0xD83EDDE8U, }, - { 0xD83DDD2AU, }, - { 0xD83DDDE1U, }, - { 0x2694U, 0xFE0FU, }, - { 0xD83DDEE1U, }, - { 0xD83DDEACU, }, - { 0x26B0U, 0xFE0FU, }, - { 0x26B1U, 0xFE0FU, }, - { 0xD83CDFFAU, }, - { 0xD83DDD2EU, }, - { 0xD83DDCFFU, }, - { 0xD83EDDFFU, }, - { 0xD83DDC88U, }, - { 0x2697U, 0xFE0FU, }, - { 0xD83DDD2DU, }, - { 0xD83DDD2CU, }, - { 0xD83DDD73U, }, - { 0xD83DDC8AU, }, - { 0xD83DDC89U, }, - { 0xD83EDDECU, }, - { 0xD83EDDA0U, }, - { 0xD83EDDEBU, }, - { 0xD83EDDEAU, }, - { 0xD83CDF21U, }, - { 0xD83EDDF9U, }, - { 0xD83EDDFAU, }, - { 0xD83EDDFBU, }, - { 0xD83DDEBDU, }, - { 0xD83DDEB0U, }, - { 0xD83DDEBFU, }, - { 0xD83DDEC1U, }, - { 0xD83DDEC0U, }, - { 0xD83EDDFCU, }, - { 0xD83EDDFDU, }, - { 0xD83EDDF4U, }, - { 0xD83DDECEU, }, - { 0xD83DDD11U, }, - { 0xD83DDDDDU, }, - { 0xD83DDEAAU, }, - { 0xD83DDECBU, }, - { 0xD83DDECFU, }, - { 0xD83DDECCU, }, - { 0xD83EDDF8U, }, - { 0xD83DDDBCU, }, - { 0xD83DDECDU, }, - { 0xD83DDED2U, }, - { 0xD83CDF81U, }, - { 0xD83CDF88U, }, - { 0xD83CDF8FU, }, - { 0xD83CDF80U, }, - { 0xD83CDF8AU, }, - { 0xD83CDF89U, }, - { 0xD83CDF8EU, }, - { 0xD83CDFEEU, }, - { 0xD83CDF90U, }, - { 0xD83EDDE7U, }, - { 0x2709U, 0xFE0FU, }, - { 0xD83DDCE9U, }, - { 0xD83DDCE8U, }, - { 0xD83DDCE7U, }, - { 0xD83DDC8CU, }, - { 0xD83DDCE5U, }, - { 0xD83DDCE4U, }, - { 0xD83DDCE6U, }, - { 0xD83CDFF7U, }, - { 0xD83DDCEAU, }, - { 0xD83DDCEBU, }, - { 0xD83DDCECU, }, - { 0xD83DDCEDU, }, - { 0xD83DDCEEU, }, - { 0xD83DDCEFU, }, - { 0xD83DDCDCU, }, - { 0xD83DDCC3U, }, - { 0xD83DDCC4U, }, - { 0xD83DDCD1U, }, - { 0xD83EDDFEU, }, - { 0xD83DDCCAU, }, - { 0xD83DDCC8U, }, - { 0xD83DDCC9U, }, - { 0xD83DDDD2U, }, - { 0xD83DDDD3U, }, - { 0xD83DDCC6U, }, - { 0xD83DDCC5U, }, - { 0xD83DDDD1U, }, - { 0xD83DDCC7U, }, - { 0xD83DDDC3U, }, - { 0xD83DDDF3U, }, - { 0xD83DDDC4U, }, - { 0xD83DDCCBU, }, - { 0xD83DDCC1U, }, - { 0xD83DDCC2U, }, - { 0xD83DDDC2U, }, - { 0xD83DDDDEU, }, - { 0xD83DDCF0U, }, - { 0xD83DDCD3U, }, - { 0xD83DDCD4U, }, - { 0xD83DDCD2U, }, - { 0xD83DDCD5U, }, - { 0xD83DDCD7U, }, - { 0xD83DDCD8U, }, - { 0xD83DDCD9U, }, - { 0xD83DDCDAU, }, - { 0xD83DDCD6U, }, - { 0xD83DDD16U, }, - { 0xD83EDDF7U, }, - { 0xD83DDD17U, }, - { 0xD83DDCCEU, }, - { 0xD83DDD87U, }, - { 0xD83DDCD0U, }, - { 0xD83DDCCFU, }, - { 0xD83EDDEEU, }, - { 0xD83DDCCCU, }, - { 0xD83DDCCDU, }, - { 0x2702U, 0xFE0FU, }, - { 0xD83DDD8AU, }, - { 0xD83DDD8BU, }, - { 0x2712U, 0xFE0FU, }, - { 0xD83DDD8CU, }, - { 0xD83DDD8DU, }, - { 0xD83DDCDDU, }, - { 0x270FU, 0xFE0FU, }, - { 0xD83DDD0DU, }, - { 0xD83DDD0EU, }, - { 0xD83DDD0FU, }, - { 0xD83DDD10U, }, - { 0xD83DDD12U, }, - { 0xD83DDD13U, }, -}; - -InputCategory Category7 = { - { 0x2764U, 0xFE0FU, }, - { 0xD83EDDE1U, }, - { 0xD83DDC9BU, }, - { 0xD83DDC9AU, }, - { 0xD83DDC99U, }, - { 0xD83DDC9CU, }, - { 0xD83DDDA4U, }, - { 0xD83DDC94U, }, - { 0x2763U, 0xFE0FU, }, - { 0xD83DDC95U, }, - { 0xD83DDC9EU, }, - { 0xD83DDC93U, }, - { 0xD83DDC97U, }, - { 0xD83DDC96U, }, - { 0xD83DDC98U, }, - { 0xD83DDC9DU, }, - { 0xD83DDC9FU, }, - { 0x262EU, 0xFE0FU, }, - { 0x271DU, 0xFE0FU, }, - { 0x262AU, 0xFE0FU, }, - { 0xD83DDD49U, }, - { 0x2638U, 0xFE0FU, }, - { 0x2721U, 0xFE0FU, }, - { 0xD83DDD2FU, }, - { 0xD83DDD4EU, }, - { 0x262FU, 0xFE0FU, }, - { 0x2626U, 0xFE0FU, }, - { 0xD83DDED0U, }, - { 0x26CEU, }, - { 0x2648U, 0xFE0FU, }, - { 0x2649U, 0xFE0FU, }, - { 0x264AU, 0xFE0FU, }, - { 0x264BU, 0xFE0FU, }, - { 0x264CU, 0xFE0FU, }, - { 0x264DU, 0xFE0FU, }, - { 0x264EU, 0xFE0FU, }, - { 0x264FU, 0xFE0FU, }, - { 0x2650U, 0xFE0FU, }, - { 0x2651U, 0xFE0FU, }, - { 0x2652U, 0xFE0FU, }, - { 0x2653U, 0xFE0FU, }, - { 0xD83CDD94U, }, - { 0x269BU, 0xFE0FU, }, - { 0xD83CDE51U, }, - { 0x2622U, 0xFE0FU, }, - { 0x2623U, 0xFE0FU, }, - { 0xD83DDCF4U, }, - { 0xD83DDCF3U, }, - { 0xD83CDE36U, }, - { 0xD83CDE1AU, 0xFE0FU, }, - { 0xD83CDE38U, }, - { 0xD83CDE3AU, }, - { 0xD83CDE37U, 0xFE0FU, }, - { 0x2734U, 0xFE0FU, }, - { 0xD83CDD9AU, }, - { 0xD83DDCAEU, }, - { 0xD83CDE50U, }, - { 0x3299U, 0xFE0FU, }, - { 0x3297U, 0xFE0FU, }, - { 0xD83CDE34U, }, - { 0xD83CDE35U, }, - { 0xD83CDE39U, }, - { 0xD83CDE32U, }, - { 0xD83CDD70U, 0xFE0FU, }, - { 0xD83CDD71U, 0xFE0FU, }, - { 0xD83CDD8EU, }, - { 0xD83CDD91U, }, - { 0xD83CDD7EU, 0xFE0FU, }, - { 0xD83CDD98U, }, - { 0x274CU, }, - { 0x2B55U, 0xFE0FU, }, - { 0xD83DDED1U, }, - { 0x26D4U, 0xFE0FU, }, - { 0xD83DDCDBU, }, - { 0xD83DDEABU, }, - { 0xD83DDCAFU, }, - { 0xD83DDCA2U, }, - { 0x2668U, 0xFE0FU, }, - { 0xD83DDEB7U, }, - { 0xD83DDEAFU, }, - { 0xD83DDEB3U, }, - { 0xD83DDEB1U, }, - { 0xD83DDD1EU, }, - { 0xD83DDCF5U, }, - { 0xD83DDEADU, }, - { 0x2757U, 0xFE0FU, }, - { 0x2755U, }, - { 0x2753U, }, - { 0x2754U, }, - { 0x203CU, 0xFE0FU, }, - { 0x2049U, 0xFE0FU, }, - { 0xD83DDD05U, }, - { 0xD83DDD06U, }, - { 0x303DU, 0xFE0FU, }, - { 0x26A0U, 0xFE0FU, }, - { 0xD83DDEB8U, }, - { 0xD83DDD31U, }, - { 0x269CU, 0xFE0FU, }, - { 0xD83DDD30U, }, - { 0x267BU, 0xFE0FU, }, - { 0x2705U, }, - { 0xD83CDE2FU, 0xFE0FU, }, - { 0xD83DDCB9U, }, - { 0x2747U, 0xFE0FU, }, - { 0x2733U, 0xFE0FU, }, - { 0x274EU, }, - { 0xD83CDF10U, }, - { 0xD83DDCA0U, }, - { 0x24C2U, 0xFE0FU, }, - { 0xD83CDF00U, }, - { 0xD83DDCA4U, }, - { 0xD83CDFE7U, }, - { 0xD83DDEBEU, }, - { 0x267FU, 0xFE0FU, }, - { 0xD83CDD7FU, 0xFE0FU, }, - { 0xD83CDE33U, }, - { 0xD83CDE02U, 0xFE0FU, }, - { 0xD83DDEC2U, }, - { 0xD83DDEC3U, }, - { 0xD83DDEC4U, }, - { 0xD83DDEC5U, }, - { 0xD83DDEB9U, }, - { 0xD83DDEBAU, }, - { 0xD83DDEBCU, }, - { 0xD83DDEBBU, }, - { 0xD83DDEAEU, }, - { 0xD83CDFA6U, }, - { 0xD83DDCF6U, }, - { 0xD83CDE01U, }, - { 0xD83DDD23U, }, - { 0x2139U, 0xFE0FU, }, - { 0xD83DDD24U, }, - { 0xD83DDD21U, }, - { 0xD83DDD20U, }, - { 0xD83CDD96U, }, - { 0xD83CDD97U, }, - { 0xD83CDD99U, }, - { 0xD83CDD92U, }, - { 0xD83CDD95U, }, - { 0xD83CDD93U, }, - { 0x30U, 0xFE0FU, 0x20E3U, }, - { 0x31U, 0xFE0FU, 0x20E3U, }, - { 0x32U, 0xFE0FU, 0x20E3U, }, - { 0x33U, 0xFE0FU, 0x20E3U, }, - { 0x34U, 0xFE0FU, 0x20E3U, }, - { 0x35U, 0xFE0FU, 0x20E3U, }, - { 0x36U, 0xFE0FU, 0x20E3U, }, - { 0x37U, 0xFE0FU, 0x20E3U, }, - { 0x38U, 0xFE0FU, 0x20E3U, }, - { 0x39U, 0xFE0FU, 0x20E3U, }, - { 0xD83DDD1FU, }, - { 0xD83DDD22U, }, - { 0x23U, 0xFE0FU, 0x20E3U, }, - { 0x2AU, 0xFE0FU, 0x20E3U, }, - { 0x23CFU, 0xFE0FU, }, - { 0x25B6U, 0xFE0FU, }, - { 0x23F8U, }, - { 0x23EFU, }, - { 0x23F9U, }, - { 0x23FAU, }, - { 0x23EDU, }, - { 0x23EEU, }, - { 0x23E9U, }, - { 0x23EAU, }, - { 0x23EBU, }, - { 0x23ECU, }, - { 0x25C0U, 0xFE0FU, }, - { 0xD83DDD3CU, }, - { 0xD83DDD3DU, }, - { 0x27A1U, 0xFE0FU, }, - { 0x2B05U, 0xFE0FU, }, - { 0x2B06U, 0xFE0FU, }, - { 0x2B07U, 0xFE0FU, }, - { 0x2197U, 0xFE0FU, }, - { 0x2198U, 0xFE0FU, }, - { 0x2199U, 0xFE0FU, }, - { 0x2196U, 0xFE0FU, }, - { 0x2195U, 0xFE0FU, }, - { 0x2194U, 0xFE0FU, }, - { 0x21AAU, 0xFE0FU, }, - { 0x21A9U, 0xFE0FU, }, - { 0x2934U, 0xFE0FU, }, - { 0x2935U, 0xFE0FU, }, - { 0xD83DDD00U, }, - { 0xD83DDD01U, }, - { 0xD83DDD02U, }, - { 0xD83DDD04U, }, - { 0xD83DDD03U, }, - { 0xD83CDFB5U, }, - { 0xD83CDFB6U, }, - { 0x2795U, }, - { 0x2796U, }, - { 0x2797U, }, - { 0x2716U, 0xFE0FU, }, - { 0x267EU, }, - { 0xD83DDCB2U, }, - { 0xD83DDCB1U, }, - { 0x2122U, 0xFE0FU, }, - { 0xA9U, 0xFE0FU, }, - { 0xAEU, 0xFE0FU, }, - { 0xD83DDC41U, 0x200DU, 0xD83DDDE8U, }, - { 0xD83DDD1AU, }, - { 0xD83DDD19U, }, - { 0xD83DDD1BU, }, - { 0xD83DDD1DU, }, - { 0xD83DDD1CU, }, - { 0x3030U, 0xFE0FU, }, - { 0x27B0U, }, - { 0x27BFU, }, - { 0x2714U, 0xFE0FU, }, - { 0x2611U, 0xFE0FU, }, - { 0xD83DDD18U, }, - { 0x26AAU, 0xFE0FU, }, - { 0x26ABU, 0xFE0FU, }, - { 0xD83DDD34U, }, - { 0xD83DDD35U, }, - { 0xD83DDD3AU, }, - { 0xD83DDD3BU, }, - { 0xD83DDD38U, }, - { 0xD83DDD39U, }, - { 0xD83DDD36U, }, - { 0xD83DDD37U, }, - { 0xD83DDD33U, }, - { 0xD83DDD32U, }, - { 0x25AAU, 0xFE0FU, }, - { 0x25ABU, 0xFE0FU, }, - { 0x25FEU, 0xFE0FU, }, - { 0x25FDU, 0xFE0FU, }, - { 0x25FCU, 0xFE0FU, }, - { 0x25FBU, 0xFE0FU, }, - { 0x2B1BU, 0xFE0FU, }, - { 0x2B1CU, 0xFE0FU, }, - { 0xD83DDD08U, }, - { 0xD83DDD07U, }, - { 0xD83DDD09U, }, - { 0xD83DDD0AU, }, - { 0xD83DDD14U, }, - { 0xD83DDD15U, }, - { 0xD83DDCE3U, }, - { 0xD83DDCE2U, }, - { 0xD83DDCACU, }, - { 0xD83DDCADU, }, - { 0xD83DDDEFU, }, - { 0x2660U, 0xFE0FU, }, - { 0x2663U, 0xFE0FU, }, - { 0x2665U, 0xFE0FU, }, - { 0x2666U, 0xFE0FU, }, - { 0xD83CDCCFU, }, - { 0xD83CDFB4U, }, - { 0xD83CDC04U, 0xFE0FU, }, - { 0xD83DDD50U, }, - { 0xD83DDD51U, }, - { 0xD83DDD52U, }, - { 0xD83DDD53U, }, - { 0xD83DDD54U, }, - { 0xD83DDD55U, }, - { 0xD83DDD56U, }, - { 0xD83DDD57U, }, - { 0xD83DDD58U, }, - { 0xD83DDD59U, }, - { 0xD83DDD5AU, }, - { 0xD83DDD5BU, }, - { 0xD83DDD5CU, }, - { 0xD83DDD5DU, }, - { 0xD83DDD5EU, }, - { 0xD83DDD5FU, }, - { 0xD83DDD60U, }, - { 0xD83DDD61U, }, - { 0xD83DDD62U, }, - { 0xD83DDD63U, }, - { 0xD83DDD64U, }, - { 0xD83DDD65U, }, - { 0xD83DDD66U, }, - { 0xD83DDD67U, }, - -//}; -// -//InputCategory Category8 = { - - { 0xD83CDFF3U, 0xFE0FU, }, - { 0xD83CDFF4U, }, - { 0xD83CDFF4U, 0x200DU, 0x2620U, 0xFE0FU, }, - { 0xD83CDFC1U, }, - { 0xD83DDEA9U, }, - { 0xD83CDFF3U, 0xFE0FU, 0x200DU, 0xD83CDF08U, }, - { 0xD83CDDFAU, 0xD83CDDF3U, }, - { 0xD83CDDE6U, 0xD83CDDEBU, }, - { 0xD83CDDE6U, 0xD83CDDFDU, }, - { 0xD83CDDE6U, 0xD83CDDF1U, }, - { 0xD83CDDE9U, 0xD83CDDFFU, }, - { 0xD83CDDE6U, 0xD83CDDF8U, }, - { 0xD83CDDE6U, 0xD83CDDE9U, }, - { 0xD83CDDE6U, 0xD83CDDF4U, }, - { 0xD83CDDE6U, 0xD83CDDEEU, }, - { 0xD83CDDE6U, 0xD83CDDF6U, }, - { 0xD83CDDE6U, 0xD83CDDECU, }, - { 0xD83CDDE6U, 0xD83CDDF7U, }, - { 0xD83CDDE6U, 0xD83CDDF2U, }, - { 0xD83CDDE6U, 0xD83CDDFCU, }, - { 0xD83CDDE6U, 0xD83CDDFAU, }, - { 0xD83CDDE6U, 0xD83CDDF9U, }, - { 0xD83CDDE6U, 0xD83CDDFFU, }, - { 0xD83CDDE7U, 0xD83CDDF8U, }, - { 0xD83CDDE7U, 0xD83CDDEDU, }, - { 0xD83CDDE7U, 0xD83CDDE9U, }, - { 0xD83CDDE7U, 0xD83CDDE7U, }, - { 0xD83CDDE7U, 0xD83CDDFEU, }, - { 0xD83CDDE7U, 0xD83CDDEAU, }, - { 0xD83CDDE7U, 0xD83CDDFFU, }, - { 0xD83CDDE7U, 0xD83CDDEFU, }, - { 0xD83CDDE7U, 0xD83CDDF2U, }, - { 0xD83CDDE7U, 0xD83CDDF9U, }, - { 0xD83CDDE7U, 0xD83CDDF4U, }, - { 0xD83CDDE7U, 0xD83CDDE6U, }, - { 0xD83CDDE7U, 0xD83CDDFCU, }, - { 0xD83CDDE7U, 0xD83CDDF7U, }, - { 0xD83CDDEEU, 0xD83CDDF4U, }, - { 0xD83CDDFBU, 0xD83CDDECU, }, - { 0xD83CDDE7U, 0xD83CDDF3U, }, - { 0xD83CDDE7U, 0xD83CDDECU, }, - { 0xD83CDDE7U, 0xD83CDDEBU, }, - { 0xD83CDDE7U, 0xD83CDDEEU, }, - { 0xD83CDDF0U, 0xD83CDDEDU, }, - { 0xD83CDDE8U, 0xD83CDDF2U, }, - { 0xD83CDDE8U, 0xD83CDDE6U, }, - { 0xD83CDDEEU, 0xD83CDDE8U, }, - { 0xD83CDDE8U, 0xD83CDDFBU, }, - { 0xD83CDDE7U, 0xD83CDDF6U, }, - { 0xD83CDDF0U, 0xD83CDDFEU, }, - { 0xD83CDDE8U, 0xD83CDDEBU, }, - { 0xD83CDDF9U, 0xD83CDDE9U, }, - { 0xD83CDDE8U, 0xD83CDDF1U, }, - { 0xD83CDDE8U, 0xD83CDDF3U, }, - { 0xD83CDDE8U, 0xD83CDDFDU, }, - { 0xD83CDDE8U, 0xD83CDDE8U, }, - { 0xD83CDDE8U, 0xD83CDDF4U, }, - { 0xD83CDDF0U, 0xD83CDDF2U, }, - { 0xD83CDDE8U, 0xD83CDDECU, }, - { 0xD83CDDE8U, 0xD83CDDE9U, }, - { 0xD83CDDE8U, 0xD83CDDF0U, }, - { 0xD83CDDE8U, 0xD83CDDF7U, }, - { 0xD83CDDE8U, 0xD83CDDEEU, }, - { 0xD83CDDEDU, 0xD83CDDF7U, }, - { 0xD83CDDE8U, 0xD83CDDFAU, }, - { 0xD83CDDE8U, 0xD83CDDFCU, }, - { 0xD83CDDE8U, 0xD83CDDFEU, }, - { 0xD83CDDE8U, 0xD83CDDFFU, }, - { 0xD83CDDE9U, 0xD83CDDF0U, }, - { 0xD83CDDE9U, 0xD83CDDEFU, }, - { 0xD83CDDE9U, 0xD83CDDF2U, }, - { 0xD83CDDE9U, 0xD83CDDF4U, }, - { 0xD83CDDEAU, 0xD83CDDE8U, }, - { 0xD83CDDEAU, 0xD83CDDECU, }, - { 0xD83CDDF8U, 0xD83CDDFBU, }, - { 0xD83CDDECU, 0xD83CDDF6U, }, - { 0xD83CDDEAU, 0xD83CDDF7U, }, - { 0xD83CDDEAU, 0xD83CDDEAU, }, - { 0xD83CDDEAU, 0xD83CDDF9U, }, - { 0xD83CDDEAU, 0xD83CDDFAU, }, - { 0xD83CDDEBU, 0xD83CDDF0U, }, - { 0xD83CDDEBU, 0xD83CDDF4U, }, - { 0xD83CDDEBU, 0xD83CDDEFU, }, - { 0xD83CDDEBU, 0xD83CDDEEU, }, - { 0xD83CDDEBU, 0xD83CDDF7U, }, - { 0xD83CDDECU, 0xD83CDDEBU, }, - { 0xD83CDDF5U, 0xD83CDDEBU, }, - { 0xD83CDDF9U, 0xD83CDDEBU, }, - { 0xD83CDDECU, 0xD83CDDE6U, }, - { 0xD83CDDECU, 0xD83CDDF2U, }, - { 0xD83CDDECU, 0xD83CDDEAU, }, - { 0xD83CDDE9U, 0xD83CDDEAU, }, - { 0xD83CDDECU, 0xD83CDDEDU, }, - { 0xD83CDDECU, 0xD83CDDEEU, }, - { 0xD83CDDECU, 0xD83CDDF7U, }, - { 0xD83CDDECU, 0xD83CDDF1U, }, - { 0xD83CDDECU, 0xD83CDDE9U, }, - { 0xD83CDDECU, 0xD83CDDF5U, }, - { 0xD83CDDECU, 0xD83CDDFAU, }, - { 0xD83CDDECU, 0xD83CDDF9U, }, - { 0xD83CDDECU, 0xD83CDDECU, }, - { 0xD83CDDECU, 0xD83CDDF3U, }, - { 0xD83CDDECU, 0xD83CDDFCU, }, - { 0xD83CDDECU, 0xD83CDDFEU, }, - { 0xD83CDDEDU, 0xD83CDDF9U, }, - { 0xD83CDDEDU, 0xD83CDDF3U, }, - { 0xD83CDDEDU, 0xD83CDDF0U, }, - { 0xD83CDDEDU, 0xD83CDDFAU, }, - { 0xD83CDDEEU, 0xD83CDDF8U, }, - { 0xD83CDDEEU, 0xD83CDDF3U, }, - { 0xD83CDDEEU, 0xD83CDDE9U, }, - { 0xD83CDDEEU, 0xD83CDDF7U, }, - { 0xD83CDDEEU, 0xD83CDDF6U, }, - { 0xD83CDDEEU, 0xD83CDDEAU, }, - { 0xD83CDDEEU, 0xD83CDDF2U, }, - { 0xD83CDDEEU, 0xD83CDDF1U, }, - { 0xD83CDDEEU, 0xD83CDDF9U, }, - { 0xD83CDDEFU, 0xD83CDDF2U, }, - { 0xD83CDDEFU, 0xD83CDDF5U, }, - { 0xD83CDF8CU, }, - { 0xD83CDDEFU, 0xD83CDDEAU, }, - { 0xD83CDDEFU, 0xD83CDDF4U, }, - { 0xD83CDDF0U, 0xD83CDDFFU, }, - { 0xD83CDDF0U, 0xD83CDDEAU, }, - { 0xD83CDDF0U, 0xD83CDDEEU, }, - { 0xD83CDDFDU, 0xD83CDDF0U, }, - { 0xD83CDDF0U, 0xD83CDDFCU, }, - { 0xD83CDDF0U, 0xD83CDDECU, }, - { 0xD83CDDF1U, 0xD83CDDE6U, }, - { 0xD83CDDF1U, 0xD83CDDFBU, }, - { 0xD83CDDF1U, 0xD83CDDE7U, }, - { 0xD83CDDF1U, 0xD83CDDF8U, }, - { 0xD83CDDF1U, 0xD83CDDF7U, }, - { 0xD83CDDF1U, 0xD83CDDFEU, }, - { 0xD83CDDF1U, 0xD83CDDEEU, }, - { 0xD83CDDF1U, 0xD83CDDF9U, }, - { 0xD83CDDF1U, 0xD83CDDFAU, }, - { 0xD83CDDF2U, 0xD83CDDF4U, }, - { 0xD83CDDF2U, 0xD83CDDF0U, }, - { 0xD83CDDF2U, 0xD83CDDECU, }, - { 0xD83CDDF2U, 0xD83CDDFCU, }, - { 0xD83CDDF2U, 0xD83CDDFEU, }, - { 0xD83CDDF2U, 0xD83CDDFBU, }, - { 0xD83CDDF2U, 0xD83CDDF1U, }, - { 0xD83CDDF2U, 0xD83CDDF9U, }, - { 0xD83CDDF2U, 0xD83CDDEDU, }, - { 0xD83CDDF2U, 0xD83CDDF6U, }, - { 0xD83CDDF2U, 0xD83CDDF7U, }, - { 0xD83CDDF2U, 0xD83CDDFAU, }, - { 0xD83CDDFEU, 0xD83CDDF9U, }, - { 0xD83CDDF2U, 0xD83CDDFDU, }, - { 0xD83CDDEBU, 0xD83CDDF2U, }, - { 0xD83CDDF2U, 0xD83CDDE9U, }, - { 0xD83CDDF2U, 0xD83CDDE8U, }, - { 0xD83CDDF2U, 0xD83CDDF3U, }, - { 0xD83CDDF2U, 0xD83CDDEAU, }, - { 0xD83CDDF2U, 0xD83CDDF8U, }, - { 0xD83CDDF2U, 0xD83CDDE6U, }, - { 0xD83CDDF2U, 0xD83CDDFFU, }, - { 0xD83CDDF2U, 0xD83CDDF2U, }, - { 0xD83CDDF3U, 0xD83CDDE6U, }, - { 0xD83CDDF3U, 0xD83CDDF7U, }, - { 0xD83CDDF3U, 0xD83CDDF5U, }, - { 0xD83CDDF3U, 0xD83CDDF1U, }, - { 0xD83CDDF3U, 0xD83CDDE8U, }, - { 0xD83CDDF3U, 0xD83CDDFFU, }, - { 0xD83CDDF3U, 0xD83CDDEEU, }, - { 0xD83CDDF3U, 0xD83CDDEAU, }, - { 0xD83CDDF3U, 0xD83CDDECU, }, - { 0xD83CDDF3U, 0xD83CDDFAU, }, - { 0xD83CDDF3U, 0xD83CDDEBU, }, - { 0xD83CDDF0U, 0xD83CDDF5U, }, - { 0xD83CDDF2U, 0xD83CDDF5U, }, - { 0xD83CDDF3U, 0xD83CDDF4U, }, - { 0xD83CDDF4U, 0xD83CDDF2U, }, - { 0xD83CDDF5U, 0xD83CDDF0U, }, - { 0xD83CDDF5U, 0xD83CDDFCU, }, - { 0xD83CDDF5U, 0xD83CDDF8U, }, - { 0xD83CDDF5U, 0xD83CDDE6U, }, - { 0xD83CDDF5U, 0xD83CDDECU, }, - { 0xD83CDDF5U, 0xD83CDDFEU, }, - { 0xD83CDDF5U, 0xD83CDDEAU, }, - { 0xD83CDDF5U, 0xD83CDDEDU, }, - { 0xD83CDDF5U, 0xD83CDDF3U, }, - { 0xD83CDDF5U, 0xD83CDDF1U, }, - { 0xD83CDDF5U, 0xD83CDDF9U, }, - { 0xD83CDDF5U, 0xD83CDDF7U, }, - { 0xD83CDDF6U, 0xD83CDDE6U, }, - { 0xD83CDDF7U, 0xD83CDDEAU, }, - { 0xD83CDDF7U, 0xD83CDDF4U, }, - { 0xD83CDDF7U, 0xD83CDDFAU, }, - { 0xD83CDDF7U, 0xD83CDDFCU, }, - { 0xD83CDDFCU, 0xD83CDDF8U, }, - { 0xD83CDDF8U, 0xD83CDDF2U, }, - { 0xD83CDDF8U, 0xD83CDDF9U, }, - { 0xD83CDDF8U, 0xD83CDDE6U, }, - { 0xD83CDDF8U, 0xD83CDDF3U, }, - { 0xD83CDDF7U, 0xD83CDDF8U, }, - { 0xD83CDDF8U, 0xD83CDDE8U, }, - { 0xD83CDDF8U, 0xD83CDDF1U, }, - { 0xD83CDDF8U, 0xD83CDDECU, }, - { 0xD83CDDF8U, 0xD83CDDFDU, }, - { 0xD83CDDF8U, 0xD83CDDF0U, }, - { 0xD83CDDF8U, 0xD83CDDEEU, }, - { 0xD83CDDECU, 0xD83CDDF8U, }, - { 0xD83CDDF8U, 0xD83CDDE7U, }, - { 0xD83CDDF8U, 0xD83CDDF4U, }, - { 0xD83CDDFFU, 0xD83CDDE6U, }, - { 0xD83CDDF0U, 0xD83CDDF7U, }, - { 0xD83CDDF8U, 0xD83CDDF8U, }, - { 0xD83CDDEAU, 0xD83CDDF8U, }, - { 0xD83CDDF1U, 0xD83CDDF0U, }, - { 0xD83CDDE7U, 0xD83CDDF1U, }, - { 0xD83CDDF8U, 0xD83CDDEDU, }, - { 0xD83CDDF0U, 0xD83CDDF3U, }, - { 0xD83CDDF1U, 0xD83CDDE8U, }, - { 0xD83CDDF5U, 0xD83CDDF2U, }, - { 0xD83CDDFBU, 0xD83CDDE8U, }, - { 0xD83CDDF8U, 0xD83CDDE9U, }, - { 0xD83CDDF8U, 0xD83CDDF7U, }, - { 0xD83CDDF8U, 0xD83CDDFFU, }, - { 0xD83CDDF8U, 0xD83CDDEAU, }, - { 0xD83CDDE8U, 0xD83CDDEDU, }, - { 0xD83CDDF8U, 0xD83CDDFEU, }, - { 0xD83CDDF9U, 0xD83CDDFCU, }, - { 0xD83CDDF9U, 0xD83CDDEFU, }, - { 0xD83CDDF9U, 0xD83CDDFFU, }, - { 0xD83CDDF9U, 0xD83CDDEDU, }, - { 0xD83CDDF9U, 0xD83CDDF1U, }, - { 0xD83CDDF9U, 0xD83CDDECU, }, - { 0xD83CDDF9U, 0xD83CDDF0U, }, - { 0xD83CDDF9U, 0xD83CDDF4U, }, - { 0xD83CDDF9U, 0xD83CDDF9U, }, - { 0xD83CDDF9U, 0xD83CDDF3U, }, - { 0xD83CDDF9U, 0xD83CDDF7U, }, - { 0xD83CDDF9U, 0xD83CDDF2U, }, - { 0xD83CDDF9U, 0xD83CDDE8U, }, - { 0xD83CDDF9U, 0xD83CDDFBU, }, - { 0xD83CDDFBU, 0xD83CDDEEU, }, - { 0xD83CDDFAU, 0xD83CDDECU, }, - { 0xD83CDDFAU, 0xD83CDDE6U, }, - { 0xD83CDDE6U, 0xD83CDDEAU, }, - { 0xD83CDDECU, 0xD83CDDE7U, }, - { 0xD83CDFF4U, 0xDB40DC67U, 0xDB40DC62U, 0xDB40DC65U, 0xDB40DC6EU, 0xDB40DC67U, 0xDB40DC7FU, }, - { 0xD83CDFF4U, 0xDB40DC67U, 0xDB40DC62U, 0xDB40DC73U, 0xDB40DC63U, 0xDB40DC74U, 0xDB40DC7FU, }, - { 0xD83CDFF4U, 0xDB40DC67U, 0xDB40DC62U, 0xDB40DC77U, 0xDB40DC6CU, 0xDB40DC73U, 0xDB40DC7FU, }, - { 0xD83CDDFAU, 0xD83CDDF8U, }, - { 0xD83CDDFAU, 0xD83CDDFEU, }, - { 0xD83CDDFAU, 0xD83CDDFFU, }, - { 0xD83CDDFBU, 0xD83CDDFAU, }, - { 0xD83CDDFBU, 0xD83CDDE6U, }, - { 0xD83CDDFBU, 0xD83CDDEAU, }, - { 0xD83CDDFBU, 0xD83CDDF3U, }, - { 0xD83CDDFCU, 0xD83CDDEBU, }, - { 0xD83CDDEAU, 0xD83CDDEDU, }, - { 0xD83CDDFEU, 0xD83CDDEAU, }, - { 0xD83CDDFFU, 0xD83CDDF2U, }, - { 0xD83CDDFFU, 0xD83CDDFCU, }, -}; - -// Original data has those emoji only with gender symbols. -// But they should be displayed as emoji even without gender symbols. -// So we map which gender symbol to use for an emoji without one. -std::map WithoutGenderAliases = { - { { 0xD83EDD26U, }, 0x2642U }, - { { 0xD83EDD37U, }, 0x2640U }, - { { 0xD83EDD38U, }, 0x2642U }, - { { 0xD83EDD3CU, }, 0x2640U }, - { { 0xD83EDD3DU, }, 0x2642U }, - { { 0xD83EDD3EU, }, 0x2640U }, - { { 0xD83EDD39U, }, 0x2642U }, - { { 0xD83EDDB8U, }, 0x2640U }, - { { 0xD83EDDB9U, }, 0x2640U }, - { { 0xD83EDDD6U, }, 0x2642U }, - { { 0xD83EDDD7U, }, 0x2640U }, - { { 0xD83EDDD8U, }, 0x2640U }, - { { 0xD83EDDD9U, }, 0x2640U }, - { { 0xD83EDDDAU, }, 0x2640U }, - { { 0xD83EDDDBU, }, 0x2640U }, - { { 0xD83EDDDCU, }, 0x2642U }, - { { 0xD83EDDDDU, }, 0x2642U }, - { { 0xD83EDDDEU, }, 0x2642U }, - { { 0xD83EDDDFU, }, 0x2642U }, -}; - -// Some flags are sent as one string, but are rendered as a different too. -std::map FlagAliases = { - { { 0xD83CDDE8U, 0xD83CDDF5U, }, { 0xD83CDDEBU, 0xD83CDDF7U, } }, - { { 0xD83CDDE7U, 0xD83CDDFBU, }, { 0xD83CDDF3U, 0xD83CDDF4U, } }, - { { 0xD83CDDE6U, 0xD83CDDE8U, }, { 0xD83CDDF8U, 0xD83CDDEDU, } }, - - // This is different flag, but macOS shows that glyph :( - { { 0xD83CDDE9U, 0xD83CDDECU, }, { 0xD83CDDEEU, 0xD83CDDF4U, } }, - - { { 0xD83CDDF9U, 0xD83CDDE6U, }, { 0xD83CDDF8U, 0xD83CDDEDU, } }, - { { 0xD83CDDF2U, 0xD83CDDEBU, }, { 0xD83CDDEBU, 0xD83CDDF7U, } }, - { { 0xD83CDDEAU, 0xD83CDDE6U, }, { 0xD83CDDEAU, 0xD83CDDF8U, } }, -}; - -std::map> Aliases; // original -> list of aliased - -void AddAlias(const Id &original, const Id &aliased) { - Aliases[original].push_back(aliased); -} - -constexpr auto kErrorBadData = 401; - -void append(Id &id, uint32 code) { - if (auto first = static_cast((code >> 16) & 0xFFFFU)) { - id.append(QChar(first)); - } - id.append(QChar(static_cast(code & 0xFFFFU))); -} - -Id BareIdFromInput(const InputId &id) { - auto result = Id(); - for (const auto unicode : id) { - if (unicode != kPostfix) { - append(result, unicode); - } - } - return result; -} - -set fillVariatedIds() { - auto result = set(); - for (const auto &row : ColoredEmoji) { - auto variatedId = Id(); - if (row.size() < 2) { - logDataError() << "colored string should have at least two characters."; - return {}; - } - for (auto i = size_t(0), size = row.size(); i != size; ++i) { - auto code = row[i]; - if (i == 1) { - if (code != ColorMask) { - logDataError() << "color code should appear at index 1."; - return {}; - } - } else if (code == ColorMask) { - logDataError() << "color code should appear only at index 1."; - return {}; - } else if (code != kPostfix) { - append(variatedId, code); - } - } - result.emplace(variatedId); - } - return result; -} - -set fillPostfixRequiredIds() { - auto result = set(); - for (const auto &row : PostfixRequired) { - result.emplace(BareIdFromInput(row)); - } - return result; -} - -void appendCategory( - Data &result, - const InputCategory &category, - const set &variatedIds, - const set &postfixRequiredIds) { - result.categories.emplace_back(); - for (auto &id : category) { - auto emoji = Emoji(); - auto bareId = BareIdFromInput(id); - auto from = id.cbegin(), to = id.cend(); - if (to - from == 2 && *(to - 1) == kPostfix) { - emoji.postfixed = true; - --to; - } - for (auto i = from; i != to; ++i) { - auto code = *i; - if (find(begin(Colors), end(Colors), code) != end(Colors)) { - logDataError() << "color code found in a category emoji."; - result = Data(); - return; - } - append(emoji.id, code); - } - if (bareId.isEmpty()) { - logDataError() << "empty emoji id found."; - result = Data(); - return; - } - - auto it = result.map.find(bareId); - if (it == result.map.cend()) { - const auto index = result.list.size(); - it = result.map.emplace(bareId, index).first; - result.list.push_back(move(emoji)); - if (const auto a = Aliases.find(bareId); a != end(Aliases)) { - for (const auto &alias : a->second) { - const auto ok = result.map.emplace(alias, index).second; - if (!ok) { - logDataError() << "some emoji alias already in the map."; - result = Data(); - return; - } - } - } - if (postfixRequiredIds.find(bareId) != end(postfixRequiredIds)) { - result.postfixRequired.emplace(index); - } - } else if (result.list[it->second].postfixed != emoji.postfixed) { - logDataError() << "same emoji found with different postfixed property."; - result = Data(); - return; - } else if (result.list[it->second].id != emoji.id) { - logDataError() << "same emoji found with different id."; - result = Data(); - return; - } - if (variatedIds.find(bareId) != end(variatedIds)) { - result.list[it->second].variated = true; - - auto baseId = Id(); - if (*from == kPostfix) { - logDataError() << "bad first symbol in emoji."; - result = Data(); - return; - } - append(baseId, *from++); - for (auto color : Colors) { - auto colored = Emoji(); - colored.id = baseId; - colored.colored = true; - append(colored.id, color); - auto bareColoredId = colored.id; - for (auto i = from; i != to; ++i) { - append(colored.id, *i); - if (*i != kPostfix) { - append(bareColoredId, *i); - } - } - auto it = result.map.find(bareColoredId); - if (it == result.map.cend()) { - const auto index = result.list.size(); - it = result.map.emplace(bareColoredId, index).first; - result.list.push_back(move(colored)); - if (const auto a = Aliases.find(bareColoredId); a != end(Aliases)) { - for (const auto &alias : a->second) { - const auto ok = result.map.emplace(alias, index).second; - if (!ok) { - logDataError() << "some emoji alias already in the map."; - result = Data(); - return; - } - } - } - if (postfixRequiredIds.find(bareColoredId) != end(postfixRequiredIds)) { - result.postfixRequired.emplace(index); - } - } else if (result.list[it->second].postfixed != colored.postfixed) { - logDataError() << "same emoji found with different postfixed property."; - result = Data(); - return; - } else if (result.list[it->second].id != colored.id) { - logDataError() << "same emoji found with different id."; - result = Data(); - return; - } - } - } - result.categories.back().push_back(it->second); - } -} - -void fillReplaces(Data &result) { - for (auto &replace : Replaces) { - auto id = Id(); - for (auto code : replace.code) { - append(id, code); - } - auto it = result.map.find(id); - if (it == result.map.cend()) { - logDataError() << "emoji from replaces not found in the map."; - result = Data(); - return; - } - result.replaces.insert(make_pair(QString::fromUtf8(replace.replace), it->second)); - } -} - -bool AddItemBeforeItem(const InputId &add, const InputId &before) { - auto addToCategory = (InputCategory*)nullptr; - auto addBeforeIterator = InputCategory::iterator(); - for (auto category : { - &Category1, - &Category2, - &Category3, - &Category4, - &Category5, - &Category6, - &Category7, - }) { - for (auto i = category->begin(), e = category->end(); i != e; ++i) { - if (*i == add) { - return true; - } else if (*i == before) { - addToCategory = category; - addBeforeIterator = i; - } - } - } - if (!addToCategory) { - return false; - } - addToCategory->insert(addBeforeIterator, add); - return true; -} - -bool CheckOldInCurrent(std::set variatedIds) { - const auto categories = { - &Category1, - &Category2, - &Category3, - &Category4, - &Category5, - &Category6, - &Category7, - }; - const auto old = { - &old::Category1, - &old::Category2, - &old::Category3, - &old::Category4, - &old::Category5, - &old::Category6, - &old::Category7, - }; - const auto genders = { 0x2640U, 0x2642U }; - const auto addGender = [](const InputId &was, uint32 gender) { - auto result = was; - result.push_back(0x200DU); - result.push_back(gender); - result.push_back(0xFE0FU); - return result; - }; - const auto addGenderByIndex = [&](const InputId &was, int index) { - return addGender(was, *(begin(genders) + index)); - }; - const auto find = []( - const InputCategory &list, - const InputId &id) { - return (std::find(begin(list), end(list), id) != end(list)); - }; - const auto findInMany = [&]( - auto &&list, - const InputId &id) { - for (const auto current : list) { - if (find(*current, id)) { - return true; - } - } - return false; - }; - const auto emplaceColoredAlias = [](const InputId &real, const InputId &alias, uint32_t color) { - if (real.size() < 2 || alias.size() < 2 || real[1] != Colors[0] || alias[1] != Colors[0]) { - return false; - } - auto key = real; - key[1] = color; - auto value = alias; - value[1] = color; - AddAlias(BareIdFromInput(key), BareIdFromInput(value)); - return true; - }; - auto result = true; - for (auto c = begin(old); c != end(old); ++c) { - const auto category = *c; - for (auto i = begin(*category); i != end(*category); ++i) { - if (findInMany(categories, *i)) { - continue; - } - - // Some emoji were ending with 0xFE0FU and now are not. - if (i->back() == 0xFE0FU) { - auto other = *i; - other.pop_back(); - if (findInMany(categories, other)) { - continue; - } - } - - // Some emoji were not ending with 0xFE0FU and now are. - if (i->back() != 0xFE0FU) { - auto other = *i; - other.push_back(0xFE0FU); - if (findInMany(categories, other)) { - continue; - } - } - - // Some emoji were without gender symbol and now have gender symbol. - // Try adding 0x200DU, 0x2640U, 0xFE0FU or 0x200DU, 0x2642U, 0xFE0FU. - const auto otherGenderIndex = [&] { - for (auto g = begin(genders); g != end(genders); ++g) { - auto altered = *i; - altered.push_back(0x200DU); - altered.push_back(*g); - altered.push_back(0xFE0FU); - if (findInMany(old, altered)) { - return int(g - begin(genders)); - } - } - return -1; - }(); - if (otherGenderIndex < 0) { - common::logError(kErrorBadData, "input") - << "Bad data: old emoji (category " - << (c - begin(old)) - << ", index " - << (i - begin(*category)) - << ") not found in current."; - result = false; - continue; - } - - const auto genderIndex = (1 - otherGenderIndex); - const auto real = addGenderByIndex(*i, genderIndex); - const auto bare = BareIdFromInput(real); - if (!findInMany(categories, real)) { - common::logError(kErrorBadData, "input") - << "Bad data: old emoji (category " - << (c - begin(old)) - << ", index " - << (i - begin(*category)) - << ") not found in current with added gender: " - << genderIndex - << "."; - result = false; - } else { - AddAlias(bare, BareIdFromInput(*i)); - } - } - } - for (auto i = begin(old::ColoredEmoji); i != end(old::ColoredEmoji); ++i) { - if (find(ColoredEmoji, *i)) { - continue; - } - - const auto otherGenderIndex = [&] { - for (auto g = begin(genders); g != end(genders); ++g) { - auto altered = *i; - altered.push_back(0x200DU); - altered.push_back(*g); - altered.push_back(0xFE0FU); - if (find(old::ColoredEmoji, altered)) { - return int(g - begin(genders)); - } - } - return -1; - }(); - if (otherGenderIndex < 0) { - common::logError(kErrorBadData, "input") - << "Bad data: old colored emoji (index " - << (i - begin(old::ColoredEmoji)) - << ") not found in current."; - result = false; - continue; - } - - const auto genderIndex = (1 - otherGenderIndex); - const auto real = addGenderByIndex(*i, genderIndex); - const auto bare = BareIdFromInput(real); - if (!find(ColoredEmoji, real)) { - common::logError(kErrorBadData, "input") - << "Bad data: old colored emoji (index " - << (i - begin(old::ColoredEmoji)) - << ") not found in current with added gender: " - << genderIndex - << "."; - result = false; - continue; - } else { - for (const auto color : Colors) { - if (!emplaceColoredAlias(real, *i, color)) { - common::logError(kErrorBadData, "input") - << "Bad data: bad colored emoji."; - result = false; - break; - } - } - } - } - - for (const auto &entry : WithoutGenderAliases) { - const auto &inputId = entry.first; - const auto &gender = entry.second; - if (findInMany(categories, inputId)) { - continue; - } - const auto real = [&] { - auto result = addGender(inputId, gender); - if (findInMany(categories, result)) { - return result; - } - result.push_back(kPostfix); - return result; - }(); - const auto bare = BareIdFromInput(real); - if (!findInMany(categories, real)) { - common::logError(kErrorBadData, "input") - << "Bad data: without gender alias not found with gender."; - result = false; - } else { - AddAlias(bare, BareIdFromInput(inputId)); - } - if (variatedIds.find(bare) != variatedIds.end()) { - auto colorReal = real; - colorReal.insert(colorReal.begin() + 1, Colors[0]); - auto colorInput = inputId; - colorInput.insert(colorInput.begin() + 1, Colors[0]); - for (const auto color : Colors) { - if (!emplaceColoredAlias(colorReal, colorInput, color)) { - common::logError(kErrorBadData, "input") - << "Bad data: bad colored emoji."; - result = false; - break; - } - } - - } - } - - for (const auto &[inputId, real] : FlagAliases) { - AddAlias(BareIdFromInput(real), BareIdFromInput(inputId)); - } - - return result; -} - -} // namespace - -common::LogStream logDataError() { - return common::logError(kErrorBadData, "input") << "Bad data: "; -} - -Data PrepareData() { - Data result; - - const auto variatedIds = fillVariatedIds(); - const auto postfixRequiredIds = fillPostfixRequiredIds(); - if (variatedIds.empty() || postfixRequiredIds.empty()) { - return Data(); - } - - // Manually add :speech_left: emoji before eye-with-speech emoji. - if (!AddItemBeforeItem({ 0xD83DDDE8U }, { 0xD83DDC41U, 0x200DU, 0xD83DDDE8U })) { - return Data(); - } - - if (!CheckOldInCurrent(variatedIds)) { - return Data(); - } - - const auto categories = { - &Category1, - &Category2, - &Category3, - &Category4, - &Category5, - &Category6, - &Category7, - }; - for (const auto category : categories) { - appendCategory(result, *category, variatedIds, postfixRequiredIds); - if (result.list.empty()) { - return Data(); - } - } - - fillReplaces(result); - if (result.list.empty()) { - return Data(); - } - - return result; -} - -namespace { -namespace old { - -InputCategory ColoredEmoji = { - { 0xD83DDC50U, 0xD83CDFFBU, }, - { 0xD83DDE4CU, 0xD83CDFFBU, }, - { 0xD83DDC4FU, 0xD83CDFFBU, }, - { 0xD83DDE4FU, 0xD83CDFFBU, }, - { 0xD83DDC4DU, 0xD83CDFFBU, }, - { 0xD83DDC4EU, 0xD83CDFFBU, }, - { 0xD83DDC4AU, 0xD83CDFFBU, }, - { 0x270AU, 0xD83CDFFBU, }, - { 0xD83EDD1BU, 0xD83CDFFBU, }, - { 0xD83EDD1CU, 0xD83CDFFBU, }, - { 0xD83EDD1EU, 0xD83CDFFBU, }, - { 0x270CU, 0xD83CDFFBU, }, - { 0xD83EDD18U, 0xD83CDFFBU, }, - { 0xD83DDC4CU, 0xD83CDFFBU, }, - { 0xD83DDC48U, 0xD83CDFFBU, }, - { 0xD83DDC49U, 0xD83CDFFBU, }, - { 0xD83DDC46U, 0xD83CDFFBU, }, - { 0xD83DDC47U, 0xD83CDFFBU, }, - { 0x261DU, 0xD83CDFFBU, }, - { 0x270BU, 0xD83CDFFBU, }, - { 0xD83EDD1AU, 0xD83CDFFBU, }, - { 0xD83DDD90U, 0xD83CDFFBU, }, - { 0xD83DDD96U, 0xD83CDFFBU, }, - { 0xD83DDC4BU, 0xD83CDFFBU, }, - { 0xD83EDD19U, 0xD83CDFFBU, }, - { 0xD83DDCAAU, 0xD83CDFFBU, }, - { 0xD83DDD95U, 0xD83CDFFBU, }, - { 0x270DU, 0xD83CDFFBU, }, - { 0xD83EDD33U, 0xD83CDFFBU, }, - { 0xD83DDC85U, 0xD83CDFFBU, }, - { 0xD83DDC42U, 0xD83CDFFBU, }, - { 0xD83DDC43U, 0xD83CDFFBU, }, - { 0xD83DDC76U, 0xD83CDFFBU, }, - { 0xD83DDC66U, 0xD83CDFFBU, }, - { 0xD83DDC67U, 0xD83CDFFBU, }, - { 0xD83DDC68U, 0xD83CDFFBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, }, - { 0xD83DDC71U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC71U, 0xD83CDFFBU, }, - { 0xD83DDC74U, 0xD83CDFFBU, }, - { 0xD83DDC75U, 0xD83CDFFBU, }, - { 0xD83DDC72U, 0xD83CDFFBU, }, - { 0xD83DDC73U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC73U, 0xD83CDFFBU, }, - { 0xD83DDC6EU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC6EU, 0xD83CDFFBU, }, - { 0xD83DDC77U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC77U, 0xD83CDFFBU, }, - { 0xD83DDC82U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC82U, 0xD83CDFFBU, }, - { 0xD83DDD75U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDD75U, 0xD83CDFFBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC69U, 0xD83CDFFBU, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83DDC68U, 0xD83CDFFBU, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83EDD36U, 0xD83CDFFBU, }, - { 0xD83CDF85U, 0xD83CDFFBU, }, - { 0xD83DDC78U, 0xD83CDFFBU, }, - { 0xD83EDD34U, 0xD83CDFFBU, }, - { 0xD83DDC70U, 0xD83CDFFBU, }, - { 0xD83EDD35U, 0xD83CDFFBU, }, - { 0xD83DDC7CU, 0xD83CDFFBU, }, - { 0xD83EDD30U, 0xD83CDFFBU, }, - { 0xD83DDE47U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE47U, 0xD83CDFFBU, }, - { 0xD83DDC81U, 0xD83CDFFBU, }, - { 0xD83DDC81U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE45U, 0xD83CDFFBU, }, - { 0xD83DDE45U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE46U, 0xD83CDFFBU, }, - { 0xD83DDE46U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4BU, 0xD83CDFFBU, }, - { 0xD83DDE4BU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD26U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD26U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD37U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD37U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4EU, 0xD83CDFFBU, }, - { 0xD83DDE4EU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4DU, 0xD83CDFFBU, }, - { 0xD83DDE4DU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC87U, 0xD83CDFFBU, }, - { 0xD83DDC87U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC86U, 0xD83CDFFBU, }, - { 0xD83DDC86U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDD74U, 0xD83CDFFBU, }, - { 0xD83DDC83U, 0xD83CDFFBU, }, - { 0xD83DDD7AU, 0xD83CDFFBU, }, - { 0xD83DDEB6U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB6U, 0xD83CDFFBU, }, - { 0xD83CDFC3U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC3U, 0xD83CDFFBU, }, - { 0xD83CDFCBU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCBU, 0xD83CDFFBU, }, - { 0xD83EDD38U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD38U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0x26F9U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0x26F9U, 0xD83CDFFBU, }, - { 0xD83EDD3EU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3EU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xD83CDFFBU, }, - { 0xD83CDFC4U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC4U, 0xD83CDFFBU, }, - { 0xD83CDFCAU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCAU, 0xD83CDFFBU, }, - { 0xD83EDD3DU, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3DU, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEA3U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEA3U, 0xD83CDFFBU, }, - { 0xD83CDFC7U, 0xD83CDFFBU, }, - { 0xD83DDEB4U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB4U, 0xD83CDFFBU, }, - { 0xD83DDEB5U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB5U, 0xD83CDFFBU, }, - { 0xD83EDD39U, 0xD83CDFFBU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD39U, 0xD83CDFFBU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEC0U, 0xD83CDFFBU, }, -}; - -InputCategory Category1 = { - { 0xD83DDE00U, }, - { 0xD83DDE03U, }, - { 0xD83DDE04U, }, - { 0xD83DDE01U, }, - { 0xD83DDE06U, }, - { 0xD83DDE05U, }, - { 0xD83DDE02U, }, - { 0xD83EDD23U, }, - { 0x263AU, 0xFE0FU, }, - { 0xD83DDE0AU, }, - { 0xD83DDE07U, }, - { 0xD83DDE42U, }, - { 0xD83DDE43U, }, - { 0xD83DDE09U, }, - { 0xD83DDE0CU, }, - { 0xD83DDE0DU, }, - { 0xD83DDE18U, }, - { 0xD83DDE17U, }, - { 0xD83DDE19U, }, - { 0xD83DDE1AU, }, - { 0xD83DDE0BU, }, - { 0xD83DDE1CU, }, - { 0xD83DDE1DU, }, - { 0xD83DDE1BU, }, - { 0xD83EDD11U, }, - { 0xD83EDD17U, }, - { 0xD83EDD13U, }, - { 0xD83DDE0EU, }, - { 0xD83EDD21U, }, - { 0xD83EDD20U, }, - { 0xD83DDE0FU, }, - { 0xD83DDE12U, }, - { 0xD83DDE1EU, }, - { 0xD83DDE14U, }, - { 0xD83DDE1FU, }, - { 0xD83DDE15U, }, - { 0xD83DDE41U, }, - { 0x2639U, 0xFE0FU, }, - { 0xD83DDE23U, }, - { 0xD83DDE16U, }, - { 0xD83DDE2BU, }, - { 0xD83DDE29U, }, - { 0xD83DDE24U, }, - { 0xD83DDE20U, }, - { 0xD83DDE21U, }, - { 0xD83DDE36U, }, - { 0xD83DDE10U, }, - { 0xD83DDE11U, }, - { 0xD83DDE2FU, }, - { 0xD83DDE26U, }, - { 0xD83DDE27U, }, - { 0xD83DDE2EU, }, - { 0xD83DDE32U, }, - { 0xD83DDE35U, }, - { 0xD83DDE33U, }, - { 0xD83DDE31U, }, - { 0xD83DDE28U, }, - { 0xD83DDE30U, }, - { 0xD83DDE22U, }, - { 0xD83DDE25U, }, - { 0xD83EDD24U, }, - { 0xD83DDE2DU, }, - { 0xD83DDE13U, }, - { 0xD83DDE2AU, }, - { 0xD83DDE34U, }, - { 0xD83DDE44U, }, - { 0xD83EDD14U, }, - { 0xD83EDD25U, }, - { 0xD83DDE2CU, }, - { 0xD83EDD10U, }, - { 0xD83EDD22U, }, - { 0xD83EDD27U, }, - { 0xD83DDE37U, }, - { 0xD83EDD12U, }, - { 0xD83EDD15U, }, - { 0xD83DDE08U, }, - { 0xD83DDC7FU, }, - { 0xD83DDC79U, }, - { 0xD83DDC7AU, }, - { 0xD83DDCA9U, }, - { 0xD83DDC7BU, }, - { 0xD83DDC80U, }, - { 0x2620U, 0xFE0FU, }, - { 0xD83DDC7DU, }, - { 0xD83DDC7EU, }, - { 0xD83EDD16U, }, - { 0xD83CDF83U, }, - { 0xD83DDE3AU, }, - { 0xD83DDE38U, }, - { 0xD83DDE39U, }, - { 0xD83DDE3BU, }, - { 0xD83DDE3CU, }, - { 0xD83DDE3DU, }, - { 0xD83DDE40U, }, - { 0xD83DDE3FU, }, - { 0xD83DDE3EU, }, - { 0xD83DDC50U, }, - { 0xD83DDE4CU, }, - { 0xD83DDC4FU, }, - { 0xD83DDE4FU, }, - { 0xD83EDD1DU, }, - { 0xD83DDC4DU, }, - { 0xD83DDC4EU, }, - { 0xD83DDC4AU, }, - { 0x270AU, 0xFE0FU, }, - { 0xD83EDD1BU, }, - { 0xD83EDD1CU, }, - { 0xD83EDD1EU, }, - { 0x270CU, 0xFE0FU, }, - { 0xD83EDD18U, }, - { 0xD83DDC4CU, }, - { 0xD83DDC48U, }, - { 0xD83DDC49U, }, - { 0xD83DDC46U, }, - { 0xD83DDC47U, }, - { 0x261DU, 0xFE0FU, }, - { 0x270BU, 0xFE0FU, }, - { 0xD83EDD1AU, }, - { 0xD83DDD90U, }, - { 0xD83DDD96U, }, - { 0xD83DDC4BU, }, - { 0xD83EDD19U, }, - { 0xD83DDCAAU, }, - { 0xD83DDD95U, }, - { 0x270DU, 0xFE0FU, }, - { 0xD83EDD33U, }, - { 0xD83DDC85U, }, - { 0xD83DDC8DU, }, - { 0xD83DDC84U, }, - { 0xD83DDC8BU, }, - { 0xD83DDC44U, }, - { 0xD83DDC45U, }, - { 0xD83DDC42U, }, - { 0xD83DDC43U, }, - { 0xD83DDC63U, }, - { 0xD83DDC41U, }, - { 0xD83DDC40U, }, - { 0xD83DDDE3U, }, - { 0xD83DDC64U, }, - { 0xD83DDC65U, }, - { 0xD83DDC76U, }, - { 0xD83DDC66U, }, - { 0xD83DDC67U, }, - { 0xD83DDC68U, }, - { 0xD83DDC69U, }, - { 0xD83DDC71U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC71U, }, - { 0xD83DDC74U, }, - { 0xD83DDC75U, }, - { 0xD83DDC72U, }, - { 0xD83DDC73U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC73U, }, - { 0xD83DDC6EU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC6EU, }, - { 0xD83DDC77U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC77U, }, - { 0xD83DDC82U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDC82U, }, - { 0xD83DDD75U, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDD75U, 0xFE0FU, }, - { 0xD83DDC69U, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC68U, 0x200DU, 0x2695U, 0xFE0FU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDF3EU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDF73U, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDF93U, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFA4U, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFEBU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFEDU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDCBBU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDCBCU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDD27U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDD2CU, }, - { 0xD83DDC69U, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC68U, 0x200DU, 0xD83CDFA8U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDE92U, }, - { 0xD83DDC69U, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC68U, 0x200DU, 0x2708U, 0xFE0FU, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDE80U, }, - { 0xD83DDC69U, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83DDC68U, 0x200DU, 0x2696U, 0xFE0FU, }, - { 0xD83EDD36U, }, - { 0xD83CDF85U, }, - { 0xD83DDC78U, }, - { 0xD83EDD34U, }, - { 0xD83DDC70U, }, - { 0xD83EDD35U, }, - { 0xD83DDC7CU, }, - { 0xD83EDD30U, }, - { 0xD83DDE47U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDE47U, }, - { 0xD83DDC81U, }, - { 0xD83DDC81U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE45U, }, - { 0xD83DDE45U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE46U, }, - { 0xD83DDE46U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4BU, }, - { 0xD83DDE4BU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD26U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD26U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD37U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD37U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4EU, }, - { 0xD83DDE4EU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDE4DU, }, - { 0xD83DDE4DU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC87U, }, - { 0xD83DDC87U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDC86U, }, - { 0xD83DDC86U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDD74U, }, - { 0xD83DDC83U, }, - { 0xD83DDD7AU, }, - { 0xD83DDC6FU, }, - { 0xD83DDC6FU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEB6U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB6U, }, - { 0xD83CDFC3U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC3U, }, - { 0xD83DDC6BU, }, - { 0xD83DDC6DU, }, - { 0xD83DDC6CU, }, - { 0xD83DDC91U, }, - { 0xD83DDC69U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC69U, }, - { 0xD83DDC68U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC68U, }, - { 0xD83DDC8FU, }, - { 0xD83DDC69U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC8BU, 0x200DU, 0xD83DDC69U, }, - { 0xD83DDC68U, 0x200DU, 0x2764U, 0xFE0FU, 0x200DU, 0xD83DDC8BU, 0x200DU, 0xD83DDC68U, }, - { 0xD83DDC6AU, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC69U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC66U, 0x200DU, 0xD83DDC66U, }, - { 0xD83DDC68U, 0x200DU, 0xD83DDC67U, 0x200DU, 0xD83DDC67U, }, - { 0xD83DDC5AU, }, - { 0xD83DDC55U, }, - { 0xD83DDC56U, }, - { 0xD83DDC54U, }, - { 0xD83DDC57U, }, - { 0xD83DDC59U, }, - { 0xD83DDC58U, }, - { 0xD83DDC60U, }, - { 0xD83DDC61U, }, - { 0xD83DDC62U, }, - { 0xD83DDC5EU, }, - { 0xD83DDC5FU, }, - { 0xD83DDC52U, }, - { 0xD83CDFA9U, }, - { 0xD83CDF93U, }, - { 0xD83DDC51U, }, - { 0x26D1U, }, - { 0xD83CDF92U, }, - { 0xD83DDC5DU, }, - { 0xD83DDC5BU, }, - { 0xD83DDC5CU, }, - { 0xD83DDCBCU, }, - { 0xD83DDC53U, }, - { 0xD83DDD76U, }, - { 0xD83CDF02U, }, - { 0x2602U, 0xFE0FU, }, -}; - -InputCategory Category2 = { - { 0xD83DDC36U, }, - { 0xD83DDC31U, }, - { 0xD83DDC2DU, }, - { 0xD83DDC39U, }, - { 0xD83DDC30U, }, - { 0xD83EDD8AU, }, - { 0xD83DDC3BU, }, - { 0xD83DDC3CU, }, - { 0xD83DDC28U, }, - { 0xD83DDC2FU, }, - { 0xD83EDD81U, }, - { 0xD83DDC2EU, }, - { 0xD83DDC37U, }, - { 0xD83DDC3DU, }, - { 0xD83DDC38U, }, - { 0xD83DDC35U, }, - { 0xD83DDE48U, }, - { 0xD83DDE49U, }, - { 0xD83DDE4AU, }, - { 0xD83DDC12U, }, - { 0xD83DDC14U, }, - { 0xD83DDC27U, }, - { 0xD83DDC26U, }, - { 0xD83DDC24U, }, - { 0xD83DDC23U, }, - { 0xD83DDC25U, }, - { 0xD83EDD86U, }, - { 0xD83EDD85U, }, - { 0xD83EDD89U, }, - { 0xD83EDD87U, }, - { 0xD83DDC3AU, }, - { 0xD83DDC17U, }, - { 0xD83DDC34U, }, - { 0xD83EDD84U, }, - { 0xD83DDC1DU, }, - { 0xD83DDC1BU, }, - { 0xD83EDD8BU, }, - { 0xD83DDC0CU, }, - { 0xD83DDC1AU, }, - { 0xD83DDC1EU, }, - { 0xD83DDC1CU, }, - { 0xD83DDD77U, }, - { 0xD83DDD78U, }, - { 0xD83DDC22U, }, - { 0xD83DDC0DU, }, - { 0xD83EDD8EU, }, - { 0xD83EDD82U, }, - { 0xD83EDD80U, }, - { 0xD83EDD91U, }, - { 0xD83DDC19U, }, - { 0xD83EDD90U, }, - { 0xD83DDC20U, }, - { 0xD83DDC1FU, }, - { 0xD83DDC21U, }, - { 0xD83DDC2CU, }, - { 0xD83EDD88U, }, - { 0xD83DDC33U, }, - { 0xD83DDC0BU, }, - { 0xD83DDC0AU, }, - { 0xD83DDC06U, }, - { 0xD83DDC05U, }, - { 0xD83DDC03U, }, - { 0xD83DDC02U, }, - { 0xD83DDC04U, }, - { 0xD83EDD8CU, }, - { 0xD83DDC2AU, }, - { 0xD83DDC2BU, }, - { 0xD83DDC18U, }, - { 0xD83EDD8FU, }, - { 0xD83EDD8DU, }, - { 0xD83DDC0EU, }, - { 0xD83DDC16U, }, - { 0xD83DDC10U, }, - { 0xD83DDC0FU, }, - { 0xD83DDC11U, }, - { 0xD83DDC15U, }, - { 0xD83DDC29U, }, - { 0xD83DDC08U, }, - { 0xD83DDC13U, }, - { 0xD83EDD83U, }, - { 0xD83DDD4AU, }, - { 0xD83DDC07U, }, - { 0xD83DDC01U, }, - { 0xD83DDC00U, }, - { 0xD83DDC3FU, }, - { 0xD83DDC3EU, }, - { 0xD83DDC09U, }, - { 0xD83DDC32U, }, - { 0xD83CDF35U, }, - { 0xD83CDF84U, }, - { 0xD83CDF32U, }, - { 0xD83CDF33U, }, - { 0xD83CDF34U, }, - { 0xD83CDF31U, }, - { 0xD83CDF3FU, }, - { 0x2618U, 0xFE0FU, }, - { 0xD83CDF40U, }, - { 0xD83CDF8DU, }, - { 0xD83CDF8BU, }, - { 0xD83CDF43U, }, - { 0xD83CDF42U, }, - { 0xD83CDF41U, }, - { 0xD83CDF44U, }, - { 0xD83CDF3EU, }, - { 0xD83DDC90U, }, - { 0xD83CDF37U, }, - { 0xD83CDF39U, }, - { 0xD83EDD40U, }, - { 0xD83CDF3BU, }, - { 0xD83CDF3CU, }, - { 0xD83CDF38U, }, - { 0xD83CDF3AU, }, - { 0xD83CDF0EU, }, - { 0xD83CDF0DU, }, - { 0xD83CDF0FU, }, - { 0xD83CDF15U, }, - { 0xD83CDF16U, }, - { 0xD83CDF17U, }, - { 0xD83CDF18U, }, - { 0xD83CDF11U, }, - { 0xD83CDF12U, }, - { 0xD83CDF13U, }, - { 0xD83CDF14U, }, - { 0xD83CDF1AU, }, - { 0xD83CDF1DU, }, - { 0xD83CDF1EU, }, - { 0xD83CDF1BU, }, - { 0xD83CDF1CU, }, - { 0xD83CDF19U, }, - { 0xD83DDCABU, }, - { 0x2B50U, 0xFE0FU, }, - { 0xD83CDF1FU, }, - { 0x2728U, }, - { 0x26A1U, 0xFE0FU, }, - { 0xD83DDD25U, }, - { 0xD83DDCA5U, }, - { 0x2604U, 0xFE0FU, }, - { 0x2600U, 0xFE0FU, }, - { 0xD83CDF24U, }, - { 0x26C5U, 0xFE0FU, }, - { 0xD83CDF25U, }, - { 0xD83CDF26U, }, - { 0xD83CDF08U, }, - { 0x2601U, 0xFE0FU, }, - { 0xD83CDF27U, }, - { 0x26C8U, }, - { 0xD83CDF29U, }, - { 0xD83CDF28U, }, - { 0x2603U, 0xFE0FU, }, - { 0x26C4U, 0xFE0FU, }, - { 0x2744U, 0xFE0FU, }, - { 0xD83CDF2CU, }, - { 0xD83DDCA8U, }, - { 0xD83CDF2AU, }, - { 0xD83CDF2BU, }, - { 0xD83CDF0AU, }, - { 0xD83DDCA7U, }, - { 0xD83DDCA6U, }, - { 0x2614U, 0xFE0FU, }, -}; - -InputCategory Category3 = { - { 0xD83CDF4FU, }, - { 0xD83CDF4EU, }, - { 0xD83CDF50U, }, - { 0xD83CDF4AU, }, - { 0xD83CDF4BU, }, - { 0xD83CDF4CU, }, - { 0xD83CDF49U, }, - { 0xD83CDF47U, }, - { 0xD83CDF53U, }, - { 0xD83CDF48U, }, - { 0xD83CDF52U, }, - { 0xD83CDF51U, }, - { 0xD83CDF4DU, }, - { 0xD83EDD5DU, }, - { 0xD83EDD51U, }, - { 0xD83CDF45U, }, - { 0xD83CDF46U, }, - { 0xD83EDD52U, }, - { 0xD83EDD55U, }, - { 0xD83CDF3DU, }, - { 0xD83CDF36U, }, - { 0xD83EDD54U, }, - { 0xD83CDF60U, }, - { 0xD83CDF30U, }, - { 0xD83EDD5CU, }, - { 0xD83CDF6FU, }, - { 0xD83EDD50U, }, - { 0xD83CDF5EU, }, - { 0xD83EDD56U, }, - { 0xD83EDDC0U, }, - { 0xD83EDD5AU, }, - { 0xD83CDF73U, }, - { 0xD83EDD53U, }, - { 0xD83EDD5EU, }, - { 0xD83CDF64U, }, - { 0xD83CDF57U, }, - { 0xD83CDF56U, }, - { 0xD83CDF55U, }, - { 0xD83CDF2DU, }, - { 0xD83CDF54U, }, - { 0xD83CDF5FU, }, - { 0xD83EDD59U, }, - { 0xD83CDF2EU, }, - { 0xD83CDF2FU, }, - { 0xD83EDD57U, }, - { 0xD83EDD58U, }, - { 0xD83CDF5DU, }, - { 0xD83CDF5CU, }, - { 0xD83CDF72U, }, - { 0xD83CDF65U, }, - { 0xD83CDF63U, }, - { 0xD83CDF71U, }, - { 0xD83CDF5BU, }, - { 0xD83CDF59U, }, - { 0xD83CDF5AU, }, - { 0xD83CDF58U, }, - { 0xD83CDF62U, }, - { 0xD83CDF61U, }, - { 0xD83CDF67U, }, - { 0xD83CDF68U, }, - { 0xD83CDF66U, }, - { 0xD83CDF70U, }, - { 0xD83CDF82U, }, - { 0xD83CDF6EU, }, - { 0xD83CDF6DU, }, - { 0xD83CDF6CU, }, - { 0xD83CDF6BU, }, - { 0xD83CDF7FU, }, - { 0xD83CDF69U, }, - { 0xD83CDF6AU, }, - { 0xD83EDD5BU, }, - { 0xD83CDF7CU, }, - { 0x2615U, 0xFE0FU, }, - { 0xD83CDF75U, }, - { 0xD83CDF76U, }, - { 0xD83CDF7AU, }, - { 0xD83CDF7BU, }, - { 0xD83EDD42U, }, - { 0xD83CDF77U, }, - { 0xD83EDD43U, }, - { 0xD83CDF78U, }, - { 0xD83CDF79U, }, - { 0xD83CDF7EU, }, - { 0xD83EDD44U, }, - { 0xD83CDF74U, }, - { 0xD83CDF7DU, }, -}; - -InputCategory Category4 = { - { 0x26BDU, 0xFE0FU, }, - { 0xD83CDFC0U, }, - { 0xD83CDFC8U, }, - { 0x26BEU, 0xFE0FU, }, - { 0xD83CDFBEU, }, - { 0xD83CDFD0U, }, - { 0xD83CDFC9U, }, - { 0xD83CDFB1U, }, - { 0xD83CDFD3U, }, - { 0xD83CDFF8U, }, - { 0xD83EDD45U, }, - { 0xD83CDFD2U, }, - { 0xD83CDFD1U, }, - { 0xD83CDFCFU, }, - { 0x26F3U, 0xFE0FU, }, - { 0xD83CDFF9U, }, - { 0xD83CDFA3U, }, - { 0xD83EDD4AU, }, - { 0xD83EDD4BU, }, - { 0x26F8U, }, - { 0xD83CDFBFU, }, - { 0x26F7U, }, - { 0xD83CDFC2U, }, - { 0xD83CDFCBU, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCBU, 0xFE0FU, }, - { 0xD83EDD3AU, }, - { 0xD83EDD3CU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3CU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83EDD38U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD38U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0x26F9U, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0x26F9U, 0xFE0FU, }, - { 0xD83EDD3EU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3EU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xFE0FU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCCU, 0xFE0FU, }, - { 0xD83CDFC4U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFC4U, }, - { 0xD83CDFCAU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83CDFCAU, }, - { 0xD83EDD3DU, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD3DU, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83DDEA3U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEA3U, }, - { 0xD83CDFC7U, }, - { 0xD83DDEB4U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB4U, }, - { 0xD83DDEB5U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83DDEB5U, }, - { 0xD83CDFBDU, }, - { 0xD83CDFC5U, }, - { 0xD83CDF96U, }, - { 0xD83EDD47U, }, - { 0xD83EDD48U, }, - { 0xD83EDD49U, }, - { 0xD83CDFC6U, }, - { 0xD83CDFF5U, }, - { 0xD83CDF97U, }, - { 0xD83CDFABU, }, - { 0xD83CDF9FU, }, - { 0xD83CDFAAU, }, - { 0xD83EDD39U, 0x200DU, 0x2640U, 0xFE0FU, }, - { 0xD83EDD39U, 0x200DU, 0x2642U, 0xFE0FU, }, - { 0xD83CDFADU, }, - { 0xD83CDFA8U, }, - { 0xD83CDFACU, }, - { 0xD83CDFA4U, }, - { 0xD83CDFA7U, }, - { 0xD83CDFBCU, }, - { 0xD83CDFB9U, }, - { 0xD83EDD41U, }, - { 0xD83CDFB7U, }, - { 0xD83CDFBAU, }, - { 0xD83CDFB8U, }, - { 0xD83CDFBBU, }, - { 0xD83CDFB2U, }, - { 0xD83CDFAFU, }, - { 0xD83CDFB3U, }, - { 0xD83CDFAEU, }, - { 0xD83CDFB0U, }, -}; - -InputCategory Category5 = { - { 0xD83DDE97U, }, - { 0xD83DDE95U, }, - { 0xD83DDE99U, }, - { 0xD83DDE8CU, }, - { 0xD83DDE8EU, }, - { 0xD83CDFCEU, }, - { 0xD83DDE93U, }, - { 0xD83DDE91U, }, - { 0xD83DDE92U, }, - { 0xD83DDE90U, }, - { 0xD83DDE9AU, }, - { 0xD83DDE9BU, }, - { 0xD83DDE9CU, }, - { 0xD83DDEF4U, }, - { 0xD83DDEB2U, }, - { 0xD83DDEF5U, }, - { 0xD83CDFCDU, }, - { 0xD83DDEA8U, }, - { 0xD83DDE94U, }, - { 0xD83DDE8DU, }, - { 0xD83DDE98U, }, - { 0xD83DDE96U, }, - { 0xD83DDEA1U, }, - { 0xD83DDEA0U, }, - { 0xD83DDE9FU, }, - { 0xD83DDE83U, }, - { 0xD83DDE8BU, }, - { 0xD83DDE9EU, }, - { 0xD83DDE9DU, }, - { 0xD83DDE84U, }, - { 0xD83DDE85U, }, - { 0xD83DDE88U, }, - { 0xD83DDE82U, }, - { 0xD83DDE86U, }, - { 0xD83DDE87U, }, - { 0xD83DDE8AU, }, - { 0xD83DDE89U, }, - { 0xD83DDE81U, }, - { 0xD83DDEE9U, }, - { 0x2708U, 0xFE0FU, }, - { 0xD83DDEEBU, }, - { 0xD83DDEECU, }, - { 0xD83DDE80U, }, - { 0xD83DDEF0U, }, - { 0xD83DDCBAU, }, - { 0xD83DDEF6U, }, - { 0x26F5U, 0xFE0FU, }, - { 0xD83DDEE5U, }, - { 0xD83DDEA4U, }, - { 0xD83DDEF3U, }, - { 0x26F4U, }, - { 0xD83DDEA2U, }, - { 0x2693U, 0xFE0FU, }, - { 0xD83DDEA7U, }, - { 0x26FDU, 0xFE0FU, }, - { 0xD83DDE8FU, }, - { 0xD83DDEA6U, }, - { 0xD83DDEA5U, }, - { 0xD83DDDFAU, }, - { 0xD83DDDFFU, }, - { 0xD83DDDFDU, }, - { 0x26F2U, 0xFE0FU, }, - { 0xD83DDDFCU, }, - { 0xD83CDFF0U, }, - { 0xD83CDFEFU, }, - { 0xD83CDFDFU, }, - { 0xD83CDFA1U, }, - { 0xD83CDFA2U, }, - { 0xD83CDFA0U, }, - { 0x26F1U, }, - { 0xD83CDFD6U, }, - { 0xD83CDFDDU, }, - { 0x26F0U, }, - { 0xD83CDFD4U, }, - { 0xD83DDDFBU, }, - { 0xD83CDF0BU, }, - { 0xD83CDFDCU, }, - { 0xD83CDFD5U, }, - { 0x26FAU, 0xFE0FU, }, - { 0xD83DDEE4U, }, - { 0xD83DDEE3U, }, - { 0xD83CDFD7U, }, - { 0xD83CDFEDU, }, - { 0xD83CDFE0U, }, - { 0xD83CDFE1U, }, - { 0xD83CDFD8U, }, - { 0xD83CDFDAU, }, - { 0xD83CDFE2U, }, - { 0xD83CDFECU, }, - { 0xD83CDFE3U, }, - { 0xD83CDFE4U, }, - { 0xD83CDFE5U, }, - { 0xD83CDFE6U, }, - { 0xD83CDFE8U, }, - { 0xD83CDFEAU, }, - { 0xD83CDFEBU, }, - { 0xD83CDFE9U, }, - { 0xD83DDC92U, }, - { 0xD83CDFDBU, }, - { 0x26EAU, 0xFE0FU, }, - { 0xD83DDD4CU, }, - { 0xD83DDD4DU, }, - { 0xD83DDD4BU, }, - { 0x26E9U, }, - { 0xD83DDDFEU, }, - { 0xD83CDF91U, }, - { 0xD83CDFDEU, }, - { 0xD83CDF05U, }, - { 0xD83CDF04U, }, - { 0xD83CDF20U, }, - { 0xD83CDF87U, }, - { 0xD83CDF86U, }, - { 0xD83CDF07U, }, - { 0xD83CDF06U, }, - { 0xD83CDFD9U, }, - { 0xD83CDF03U, }, - { 0xD83CDF0CU, }, - { 0xD83CDF09U, }, - { 0xD83CDF01U, }, -}; - -InputCategory Category6 = { - { 0x231AU, 0xFE0FU, }, - { 0xD83DDCF1U, }, - { 0xD83DDCF2U, }, - { 0xD83DDCBBU, }, - { 0x2328U, 0xFE0FU, }, - { 0xD83DDDA5U, }, - { 0xD83DDDA8U, }, - { 0xD83DDDB1U, }, - { 0xD83DDDB2U, }, - { 0xD83DDD79U, }, - { 0xD83DDDDCU, }, - { 0xD83DDCBDU, }, - { 0xD83DDCBEU, }, - { 0xD83DDCBFU, }, - { 0xD83DDCC0U, }, - { 0xD83DDCFCU, }, - { 0xD83DDCF7U, }, - { 0xD83DDCF8U, }, - { 0xD83DDCF9U, }, - { 0xD83CDFA5U, }, - { 0xD83DDCFDU, }, - { 0xD83CDF9EU, }, - { 0xD83DDCDEU, }, - { 0x260EU, 0xFE0FU, }, - { 0xD83DDCDFU, }, - { 0xD83DDCE0U, }, - { 0xD83DDCFAU, }, - { 0xD83DDCFBU, }, - { 0xD83CDF99U, }, - { 0xD83CDF9AU, }, - { 0xD83CDF9BU, }, - { 0x23F1U, }, - { 0x23F2U, }, - { 0x23F0U, }, - { 0xD83DDD70U, }, - { 0x231BU, 0xFE0FU, }, - { 0x23F3U, }, - { 0xD83DDCE1U, }, - { 0xD83DDD0BU, }, - { 0xD83DDD0CU, }, - { 0xD83DDCA1U, }, - { 0xD83DDD26U, }, - { 0xD83DDD6FU, }, - { 0xD83DDDD1U, }, - { 0xD83DDEE2U, }, - { 0xD83DDCB8U, }, - { 0xD83DDCB5U, }, - { 0xD83DDCB4U, }, - { 0xD83DDCB6U, }, - { 0xD83DDCB7U, }, - { 0xD83DDCB0U, }, - { 0xD83DDCB3U, }, - { 0xD83DDC8EU, }, - { 0x2696U, 0xFE0FU, }, - { 0xD83DDD27U, }, - { 0xD83DDD28U, }, - { 0x2692U, }, - { 0xD83DDEE0U, }, - { 0x26CFU, }, - { 0xD83DDD29U, }, - { 0x2699U, 0xFE0FU, }, - { 0x26D3U, }, - { 0xD83DDD2BU, }, - { 0xD83DDCA3U, }, - { 0xD83DDD2AU, }, - { 0xD83DDDE1U, }, - { 0x2694U, 0xFE0FU, }, - { 0xD83DDEE1U, }, - { 0xD83DDEACU, }, - { 0x26B0U, 0xFE0FU, }, - { 0x26B1U, 0xFE0FU, }, - { 0xD83CDFFAU, }, - { 0xD83DDD2EU, }, - { 0xD83DDCFFU, }, - { 0xD83DDC88U, }, - { 0x2697U, 0xFE0FU, }, - { 0xD83DDD2DU, }, - { 0xD83DDD2CU, }, - { 0xD83DDD73U, }, - { 0xD83DDC8AU, }, - { 0xD83DDC89U, }, - { 0xD83CDF21U, }, - { 0xD83DDEBDU, }, - { 0xD83DDEB0U, }, - { 0xD83DDEBFU, }, - { 0xD83DDEC1U, }, - { 0xD83DDEC0U, }, - { 0xD83DDECEU, }, - { 0xD83DDD11U, }, - { 0xD83DDDDDU, }, - { 0xD83DDEAAU, }, - { 0xD83DDECBU, }, - { 0xD83DDECFU, }, - { 0xD83DDECCU, }, - { 0xD83DDDBCU, }, - { 0xD83DDECDU, }, - { 0xD83DDED2U, }, - { 0xD83CDF81U, }, - { 0xD83CDF88U, }, - { 0xD83CDF8FU, }, - { 0xD83CDF80U, }, - { 0xD83CDF8AU, }, - { 0xD83CDF89U, }, - { 0xD83CDF8EU, }, - { 0xD83CDFEEU, }, - { 0xD83CDF90U, }, - { 0x2709U, 0xFE0FU, }, - { 0xD83DDCE9U, }, - { 0xD83DDCE8U, }, - { 0xD83DDCE7U, }, - { 0xD83DDC8CU, }, - { 0xD83DDCE5U, }, - { 0xD83DDCE4U, }, - { 0xD83DDCE6U, }, - { 0xD83CDFF7U, }, - { 0xD83DDCEAU, }, - { 0xD83DDCEBU, }, - { 0xD83DDCECU, }, - { 0xD83DDCEDU, }, - { 0xD83DDCEEU, }, - { 0xD83DDCEFU, }, - { 0xD83DDCDCU, }, - { 0xD83DDCC3U, }, - { 0xD83DDCC4U, }, - { 0xD83DDCD1U, }, - { 0xD83DDCCAU, }, - { 0xD83DDCC8U, }, - { 0xD83DDCC9U, }, - { 0xD83DDDD2U, }, - { 0xD83DDDD3U, }, - { 0xD83DDCC6U, }, - { 0xD83DDCC5U, }, - { 0xD83DDCC7U, }, - { 0xD83DDDC3U, }, - { 0xD83DDDF3U, }, - { 0xD83DDDC4U, }, - { 0xD83DDCCBU, }, - { 0xD83DDCC1U, }, - { 0xD83DDCC2U, }, - { 0xD83DDDC2U, }, - { 0xD83DDDDEU, }, - { 0xD83DDCF0U, }, - { 0xD83DDCD3U, }, - { 0xD83DDCD4U, }, - { 0xD83DDCD2U, }, - { 0xD83DDCD5U, }, - { 0xD83DDCD7U, }, - { 0xD83DDCD8U, }, - { 0xD83DDCD9U, }, - { 0xD83DDCDAU, }, - { 0xD83DDCD6U, }, - { 0xD83DDD16U, }, - { 0xD83DDD17U, }, - { 0xD83DDCCEU, }, - { 0xD83DDD87U, }, - { 0xD83DDCD0U, }, - { 0xD83DDCCFU, }, - { 0xD83DDCCCU, }, - { 0xD83DDCCDU, }, - { 0x2702U, 0xFE0FU, }, - { 0xD83DDD8AU, }, - { 0xD83DDD8BU, }, - { 0x2712U, 0xFE0FU, }, - { 0xD83DDD8CU, }, - { 0xD83DDD8DU, }, - { 0xD83DDCDDU, }, - { 0x270FU, 0xFE0FU, }, - { 0xD83DDD0DU, }, - { 0xD83DDD0EU, }, - { 0xD83DDD0FU, }, - { 0xD83DDD10U, }, - { 0xD83DDD12U, }, - { 0xD83DDD13U, }, -}; - -InputCategory Category7 = { - { 0x2764U, 0xFE0FU, }, - { 0xD83DDC9BU, }, - { 0xD83DDC9AU, }, - { 0xD83DDC99U, }, - { 0xD83DDC9CU, }, - { 0xD83DDDA4U, }, - { 0xD83DDC94U, }, - { 0x2763U, 0xFE0FU, }, - { 0xD83DDC95U, }, - { 0xD83DDC9EU, }, - { 0xD83DDC93U, }, - { 0xD83DDC97U, }, - { 0xD83DDC96U, }, - { 0xD83DDC98U, }, - { 0xD83DDC9DU, }, - { 0xD83DDC9FU, }, - { 0x262EU, 0xFE0FU, }, - { 0x271DU, 0xFE0FU, }, - { 0x262AU, 0xFE0FU, }, - { 0xD83DDD49U, }, - { 0x2638U, 0xFE0FU, }, - { 0x2721U, 0xFE0FU, }, - { 0xD83DDD2FU, }, - { 0xD83DDD4EU, }, - { 0x262FU, 0xFE0FU, }, - { 0x2626U, 0xFE0FU, }, - { 0xD83DDED0U, }, - { 0x26CEU, }, - { 0x2648U, 0xFE0FU, }, - { 0x2649U, 0xFE0FU, }, - { 0x264AU, 0xFE0FU, }, - { 0x264BU, 0xFE0FU, }, - { 0x264CU, 0xFE0FU, }, - { 0x264DU, 0xFE0FU, }, - { 0x264EU, 0xFE0FU, }, - { 0x264FU, 0xFE0FU, }, - { 0x2650U, 0xFE0FU, }, - { 0x2651U, 0xFE0FU, }, - { 0x2652U, 0xFE0FU, }, - { 0x2653U, 0xFE0FU, }, - { 0xD83CDD94U, }, - { 0x269BU, 0xFE0FU, }, - { 0xD83CDE51U, }, - { 0x2622U, 0xFE0FU, }, - { 0x2623U, 0xFE0FU, }, - { 0xD83DDCF4U, }, - { 0xD83DDCF3U, }, - { 0xD83CDE36U, }, - { 0xD83CDE1AU, 0xFE0FU, }, - { 0xD83CDE38U, }, - { 0xD83CDE3AU, }, - { 0xD83CDE37U, }, - { 0x2734U, 0xFE0FU, }, - { 0xD83CDD9AU, }, - { 0xD83DDCAEU, }, - { 0xD83CDE50U, }, - { 0x3299U, 0xFE0FU, }, - { 0x3297U, 0xFE0FU, }, - { 0xD83CDE34U, }, - { 0xD83CDE35U, }, - { 0xD83CDE39U, }, - { 0xD83CDE32U, }, - { 0xD83CDD70U, 0xFE0FU, }, - { 0xD83CDD71U, 0xFE0FU, }, - { 0xD83CDD8EU, }, - { 0xD83CDD91U, }, - { 0xD83CDD7EU, 0xFE0FU, }, - { 0xD83CDD98U, }, - { 0x274CU, }, - { 0x2B55U, 0xFE0FU, }, - { 0xD83DDED1U, }, - { 0x26D4U, 0xFE0FU, }, - { 0xD83DDCDBU, }, - { 0xD83DDEABU, }, - { 0xD83DDCAFU, }, - { 0xD83DDCA2U, }, - { 0x2668U, 0xFE0FU, }, - { 0xD83DDEB7U, }, - { 0xD83DDEAFU, }, - { 0xD83DDEB3U, }, - { 0xD83DDEB1U, }, - { 0xD83DDD1EU, }, - { 0xD83DDCF5U, }, - { 0xD83DDEADU, }, - { 0x2757U, 0xFE0FU, }, - { 0x2755U, }, - { 0x2753U, }, - { 0x2754U, }, - { 0x203CU, 0xFE0FU, }, - { 0x2049U, 0xFE0FU, }, - { 0xD83DDD05U, }, - { 0xD83DDD06U, }, - { 0x303DU, 0xFE0FU, }, - { 0x26A0U, 0xFE0FU, }, - { 0xD83DDEB8U, }, - { 0xD83DDD31U, }, - { 0x269CU, 0xFE0FU, }, - { 0xD83DDD30U, }, - { 0x267BU, 0xFE0FU, }, - { 0x2705U, }, - { 0xD83CDE2FU, 0xFE0FU, }, - { 0xD83DDCB9U, }, - { 0x2747U, 0xFE0FU, }, - { 0x2733U, 0xFE0FU, }, - { 0x274EU, }, - { 0xD83CDF10U, }, - { 0xD83DDCA0U, }, - { 0x24C2U, 0xFE0FU, }, - { 0xD83CDF00U, }, - { 0xD83DDCA4U, }, - { 0xD83CDFE7U, }, - { 0xD83DDEBEU, }, - { 0x267FU, 0xFE0FU, }, - { 0xD83CDD7FU, 0xFE0FU, }, - { 0xD83CDE33U, }, - { 0xD83CDE02U, }, - { 0xD83DDEC2U, }, - { 0xD83DDEC3U, }, - { 0xD83DDEC4U, }, - { 0xD83DDEC5U, }, - { 0xD83DDEB9U, }, - { 0xD83DDEBAU, }, - { 0xD83DDEBCU, }, - { 0xD83DDEBBU, }, - { 0xD83DDEAEU, }, - { 0xD83CDFA6U, }, - { 0xD83DDCF6U, }, - { 0xD83CDE01U, }, - { 0xD83DDD23U, }, - { 0x2139U, 0xFE0FU, }, - { 0xD83DDD24U, }, - { 0xD83DDD21U, }, - { 0xD83DDD20U, }, - { 0xD83CDD96U, }, - { 0xD83CDD97U, }, - { 0xD83CDD99U, }, - { 0xD83CDD92U, }, - { 0xD83CDD95U, }, - { 0xD83CDD93U, }, - { 0x30U, 0xFE0FU, 0x20E3U, }, - { 0x31U, 0xFE0FU, 0x20E3U, }, - { 0x32U, 0xFE0FU, 0x20E3U, }, - { 0x33U, 0xFE0FU, 0x20E3U, }, - { 0x34U, 0xFE0FU, 0x20E3U, }, - { 0x35U, 0xFE0FU, 0x20E3U, }, - { 0x36U, 0xFE0FU, 0x20E3U, }, - { 0x37U, 0xFE0FU, 0x20E3U, }, - { 0x38U, 0xFE0FU, 0x20E3U, }, - { 0x39U, 0xFE0FU, 0x20E3U, }, - { 0xD83DDD1FU, }, - { 0xD83DDD22U, }, - { 0x23U, 0xFE0FU, 0x20E3U, }, - { 0x2AU, 0xFE0FU, 0x20E3U, }, - { 0x25B6U, 0xFE0FU, }, - { 0x23F8U, }, - { 0x23EFU, }, - { 0x23F9U, }, - { 0x23FAU, }, - { 0x23EDU, }, - { 0x23EEU, }, - { 0x23E9U, }, - { 0x23EAU, }, - { 0x23EBU, }, - { 0x23ECU, }, - { 0x25C0U, 0xFE0FU, }, - { 0xD83DDD3CU, }, - { 0xD83DDD3DU, }, - { 0x27A1U, 0xFE0FU, }, - { 0x2B05U, 0xFE0FU, }, - { 0x2B06U, 0xFE0FU, }, - { 0x2B07U, 0xFE0FU, }, - { 0x2197U, 0xFE0FU, }, - { 0x2198U, 0xFE0FU, }, - { 0x2199U, 0xFE0FU, }, - { 0x2196U, 0xFE0FU, }, - { 0x2195U, 0xFE0FU, }, - { 0x2194U, 0xFE0FU, }, - { 0x21AAU, 0xFE0FU, }, - { 0x21A9U, 0xFE0FU, }, - { 0x2934U, 0xFE0FU, }, - { 0x2935U, 0xFE0FU, }, - { 0xD83DDD00U, }, - { 0xD83DDD01U, }, - { 0xD83DDD02U, }, - { 0xD83DDD04U, }, - { 0xD83DDD03U, }, - { 0xD83CDFB5U, }, - { 0xD83CDFB6U, }, - { 0x2795U, }, - { 0x2796U, }, - { 0x2797U, }, - { 0x2716U, 0xFE0FU, }, - { 0xD83DDCB2U, }, - { 0xD83DDCB1U, }, - { 0x2122U, }, - { 0xA9U, }, - { 0xAEU, }, - { 0x3030U, }, - { 0x27B0U, }, - { 0x27BFU, }, - { 0xD83DDD1AU, }, - { 0xD83DDD19U, }, - { 0xD83DDD1BU, }, - { 0xD83DDD1DU, }, - { 0xD83DDD1CU, }, - { 0x2714U, 0xFE0FU, }, - { 0x2611U, 0xFE0FU, }, - { 0xD83DDD18U, }, - { 0x26AAU, 0xFE0FU, }, - { 0x26ABU, 0xFE0FU, }, - { 0xD83DDD34U, }, - { 0xD83DDD35U, }, - { 0xD83DDD3AU, }, - { 0xD83DDD3BU, }, - { 0xD83DDD38U, }, - { 0xD83DDD39U, }, - { 0xD83DDD36U, }, - { 0xD83DDD37U, }, - { 0xD83DDD33U, }, - { 0xD83DDD32U, }, - { 0x25AAU, 0xFE0FU, }, - { 0x25ABU, 0xFE0FU, }, - { 0x25FEU, 0xFE0FU, }, - { 0x25FDU, 0xFE0FU, }, - { 0x25FCU, 0xFE0FU, }, - { 0x25FBU, 0xFE0FU, }, - { 0x2B1BU, 0xFE0FU, }, - { 0x2B1CU, 0xFE0FU, }, - { 0xD83DDD08U, }, - { 0xD83DDD07U, }, - { 0xD83DDD09U, }, - { 0xD83DDD0AU, }, - { 0xD83DDD14U, }, - { 0xD83DDD15U, }, - { 0xD83DDCE3U, }, - { 0xD83DDCE2U, }, - { 0xD83DDC41U, 0x200DU, 0xD83DDDE8U, }, - { 0xD83DDCACU, }, - { 0xD83DDCADU, }, - { 0xD83DDDEFU, }, - { 0x2660U, 0xFE0FU, }, - { 0x2663U, 0xFE0FU, }, - { 0x2665U, 0xFE0FU, }, - { 0x2666U, 0xFE0FU, }, - { 0xD83CDCCFU, }, - { 0xD83CDFB4U, }, - { 0xD83CDC04U, 0xFE0FU, }, - { 0xD83DDD50U, }, - { 0xD83DDD51U, }, - { 0xD83DDD52U, }, - { 0xD83DDD53U, }, - { 0xD83DDD54U, }, - { 0xD83DDD55U, }, - { 0xD83DDD56U, }, - { 0xD83DDD57U, }, - { 0xD83DDD58U, }, - { 0xD83DDD59U, }, - { 0xD83DDD5AU, }, - { 0xD83DDD5BU, }, - { 0xD83DDD5CU, }, - { 0xD83DDD5DU, }, - { 0xD83DDD5EU, }, - { 0xD83DDD5FU, }, - { 0xD83DDD60U, }, - { 0xD83DDD61U, }, - { 0xD83DDD62U, }, - { 0xD83DDD63U, }, - { 0xD83DDD64U, }, - { 0xD83DDD65U, }, - { 0xD83DDD66U, }, - { 0xD83DDD67U, }, - -//}; -// -//InputCategory Category8 = { - - { 0xD83CDFF3U, }, - { 0xD83CDFF4U, }, - { 0xD83CDFC1U, }, - { 0xD83DDEA9U, }, - { 0xD83CDFF3U, 0xFE0FU, 0x200DU, 0xD83CDF08U, }, - { 0xD83CDDE6U, 0xD83CDDEBU, }, - { 0xD83CDDE6U, 0xD83CDDFDU, }, - { 0xD83CDDE6U, 0xD83CDDF1U, }, - { 0xD83CDDE9U, 0xD83CDDFFU, }, - { 0xD83CDDE6U, 0xD83CDDF8U, }, - { 0xD83CDDE6U, 0xD83CDDE9U, }, - { 0xD83CDDE6U, 0xD83CDDF4U, }, - { 0xD83CDDE6U, 0xD83CDDEEU, }, - { 0xD83CDDE6U, 0xD83CDDF6U, }, - { 0xD83CDDE6U, 0xD83CDDECU, }, - { 0xD83CDDE6U, 0xD83CDDF7U, }, - { 0xD83CDDE6U, 0xD83CDDF2U, }, - { 0xD83CDDE6U, 0xD83CDDFCU, }, - { 0xD83CDDE6U, 0xD83CDDFAU, }, - { 0xD83CDDE6U, 0xD83CDDF9U, }, - { 0xD83CDDE6U, 0xD83CDDFFU, }, - { 0xD83CDDE7U, 0xD83CDDF8U, }, - { 0xD83CDDE7U, 0xD83CDDEDU, }, - { 0xD83CDDE7U, 0xD83CDDE9U, }, - { 0xD83CDDE7U, 0xD83CDDE7U, }, - { 0xD83CDDE7U, 0xD83CDDFEU, }, - { 0xD83CDDE7U, 0xD83CDDEAU, }, - { 0xD83CDDE7U, 0xD83CDDFFU, }, - { 0xD83CDDE7U, 0xD83CDDEFU, }, - { 0xD83CDDE7U, 0xD83CDDF2U, }, - { 0xD83CDDE7U, 0xD83CDDF9U, }, - { 0xD83CDDE7U, 0xD83CDDF4U, }, - { 0xD83CDDE7U, 0xD83CDDE6U, }, - { 0xD83CDDE7U, 0xD83CDDFCU, }, - { 0xD83CDDE7U, 0xD83CDDF7U, }, - { 0xD83CDDEEU, 0xD83CDDF4U, }, - { 0xD83CDDFBU, 0xD83CDDECU, }, - { 0xD83CDDE7U, 0xD83CDDF3U, }, - { 0xD83CDDE7U, 0xD83CDDECU, }, - { 0xD83CDDE7U, 0xD83CDDEBU, }, - { 0xD83CDDE7U, 0xD83CDDEEU, }, - { 0xD83CDDF0U, 0xD83CDDEDU, }, - { 0xD83CDDE8U, 0xD83CDDF2U, }, - { 0xD83CDDE8U, 0xD83CDDE6U, }, - { 0xD83CDDEEU, 0xD83CDDE8U, }, - { 0xD83CDDE8U, 0xD83CDDFBU, }, - { 0xD83CDDE7U, 0xD83CDDF6U, }, - { 0xD83CDDF0U, 0xD83CDDFEU, }, - { 0xD83CDDE8U, 0xD83CDDEBU, }, - { 0xD83CDDF9U, 0xD83CDDE9U, }, - { 0xD83CDDE8U, 0xD83CDDF1U, }, - { 0xD83CDDE8U, 0xD83CDDF3U, }, - { 0xD83CDDE8U, 0xD83CDDFDU, }, - { 0xD83CDDE8U, 0xD83CDDE8U, }, - { 0xD83CDDE8U, 0xD83CDDF4U, }, - { 0xD83CDDF0U, 0xD83CDDF2U, }, - { 0xD83CDDE8U, 0xD83CDDECU, }, - { 0xD83CDDE8U, 0xD83CDDE9U, }, - { 0xD83CDDE8U, 0xD83CDDF0U, }, - { 0xD83CDDE8U, 0xD83CDDF7U, }, - { 0xD83CDDE8U, 0xD83CDDEEU, }, - { 0xD83CDDEDU, 0xD83CDDF7U, }, - { 0xD83CDDE8U, 0xD83CDDFAU, }, - { 0xD83CDDE8U, 0xD83CDDFCU, }, - { 0xD83CDDE8U, 0xD83CDDFEU, }, - { 0xD83CDDE8U, 0xD83CDDFFU, }, - { 0xD83CDDE9U, 0xD83CDDF0U, }, - { 0xD83CDDE9U, 0xD83CDDEFU, }, - { 0xD83CDDE9U, 0xD83CDDF2U, }, - { 0xD83CDDE9U, 0xD83CDDF4U, }, - { 0xD83CDDEAU, 0xD83CDDE8U, }, - { 0xD83CDDEAU, 0xD83CDDECU, }, - { 0xD83CDDF8U, 0xD83CDDFBU, }, - { 0xD83CDDECU, 0xD83CDDF6U, }, - { 0xD83CDDEAU, 0xD83CDDF7U, }, - { 0xD83CDDEAU, 0xD83CDDEAU, }, - { 0xD83CDDEAU, 0xD83CDDF9U, }, - { 0xD83CDDEAU, 0xD83CDDFAU, }, - { 0xD83CDDEBU, 0xD83CDDF0U, }, - { 0xD83CDDEBU, 0xD83CDDF4U, }, - { 0xD83CDDEBU, 0xD83CDDEFU, }, - { 0xD83CDDEBU, 0xD83CDDEEU, }, - { 0xD83CDDEBU, 0xD83CDDF7U, }, - { 0xD83CDDECU, 0xD83CDDEBU, }, - { 0xD83CDDF5U, 0xD83CDDEBU, }, - { 0xD83CDDF9U, 0xD83CDDEBU, }, - { 0xD83CDDECU, 0xD83CDDE6U, }, - { 0xD83CDDECU, 0xD83CDDF2U, }, - { 0xD83CDDECU, 0xD83CDDEAU, }, - { 0xD83CDDE9U, 0xD83CDDEAU, }, - { 0xD83CDDECU, 0xD83CDDEDU, }, - { 0xD83CDDECU, 0xD83CDDEEU, }, - { 0xD83CDDECU, 0xD83CDDF7U, }, - { 0xD83CDDECU, 0xD83CDDF1U, }, - { 0xD83CDDECU, 0xD83CDDE9U, }, - { 0xD83CDDECU, 0xD83CDDF5U, }, - { 0xD83CDDECU, 0xD83CDDFAU, }, - { 0xD83CDDECU, 0xD83CDDF9U, }, - { 0xD83CDDECU, 0xD83CDDECU, }, - { 0xD83CDDECU, 0xD83CDDF3U, }, - { 0xD83CDDECU, 0xD83CDDFCU, }, - { 0xD83CDDECU, 0xD83CDDFEU, }, - { 0xD83CDDEDU, 0xD83CDDF9U, }, - { 0xD83CDDEDU, 0xD83CDDF3U, }, - { 0xD83CDDEDU, 0xD83CDDF0U, }, - { 0xD83CDDEDU, 0xD83CDDFAU, }, - { 0xD83CDDEEU, 0xD83CDDF8U, }, - { 0xD83CDDEEU, 0xD83CDDF3U, }, - { 0xD83CDDEEU, 0xD83CDDE9U, }, - { 0xD83CDDEEU, 0xD83CDDF7U, }, - { 0xD83CDDEEU, 0xD83CDDF6U, }, - { 0xD83CDDEEU, 0xD83CDDEAU, }, - { 0xD83CDDEEU, 0xD83CDDF2U, }, - { 0xD83CDDEEU, 0xD83CDDF1U, }, - { 0xD83CDDEEU, 0xD83CDDF9U, }, - { 0xD83CDDEFU, 0xD83CDDF2U, }, - { 0xD83CDDEFU, 0xD83CDDF5U, }, - { 0xD83CDF8CU, }, - { 0xD83CDDEFU, 0xD83CDDEAU, }, - { 0xD83CDDEFU, 0xD83CDDF4U, }, - { 0xD83CDDF0U, 0xD83CDDFFU, }, - { 0xD83CDDF0U, 0xD83CDDEAU, }, - { 0xD83CDDF0U, 0xD83CDDEEU, }, - { 0xD83CDDFDU, 0xD83CDDF0U, }, - { 0xD83CDDF0U, 0xD83CDDFCU, }, - { 0xD83CDDF0U, 0xD83CDDECU, }, - { 0xD83CDDF1U, 0xD83CDDE6U, }, - { 0xD83CDDF1U, 0xD83CDDFBU, }, - { 0xD83CDDF1U, 0xD83CDDE7U, }, - { 0xD83CDDF1U, 0xD83CDDF8U, }, - { 0xD83CDDF1U, 0xD83CDDF7U, }, - { 0xD83CDDF1U, 0xD83CDDFEU, }, - { 0xD83CDDF1U, 0xD83CDDEEU, }, - { 0xD83CDDF1U, 0xD83CDDF9U, }, - { 0xD83CDDF1U, 0xD83CDDFAU, }, - { 0xD83CDDF2U, 0xD83CDDF4U, }, - { 0xD83CDDF2U, 0xD83CDDF0U, }, - { 0xD83CDDF2U, 0xD83CDDECU, }, - { 0xD83CDDF2U, 0xD83CDDFCU, }, - { 0xD83CDDF2U, 0xD83CDDFEU, }, - { 0xD83CDDF2U, 0xD83CDDFBU, }, - { 0xD83CDDF2U, 0xD83CDDF1U, }, - { 0xD83CDDF2U, 0xD83CDDF9U, }, - { 0xD83CDDF2U, 0xD83CDDEDU, }, - { 0xD83CDDF2U, 0xD83CDDF6U, }, - { 0xD83CDDF2U, 0xD83CDDF7U, }, - { 0xD83CDDF2U, 0xD83CDDFAU, }, - { 0xD83CDDFEU, 0xD83CDDF9U, }, - { 0xD83CDDF2U, 0xD83CDDFDU, }, - { 0xD83CDDEBU, 0xD83CDDF2U, }, - { 0xD83CDDF2U, 0xD83CDDE9U, }, - { 0xD83CDDF2U, 0xD83CDDE8U, }, - { 0xD83CDDF2U, 0xD83CDDF3U, }, - { 0xD83CDDF2U, 0xD83CDDEAU, }, - { 0xD83CDDF2U, 0xD83CDDF8U, }, - { 0xD83CDDF2U, 0xD83CDDE6U, }, - { 0xD83CDDF2U, 0xD83CDDFFU, }, - { 0xD83CDDF2U, 0xD83CDDF2U, }, - { 0xD83CDDF3U, 0xD83CDDE6U, }, - { 0xD83CDDF3U, 0xD83CDDF7U, }, - { 0xD83CDDF3U, 0xD83CDDF5U, }, - { 0xD83CDDF3U, 0xD83CDDF1U, }, - { 0xD83CDDF3U, 0xD83CDDE8U, }, - { 0xD83CDDF3U, 0xD83CDDFFU, }, - { 0xD83CDDF3U, 0xD83CDDEEU, }, - { 0xD83CDDF3U, 0xD83CDDEAU, }, - { 0xD83CDDF3U, 0xD83CDDECU, }, - { 0xD83CDDF3U, 0xD83CDDFAU, }, - { 0xD83CDDF3U, 0xD83CDDEBU, }, - { 0xD83CDDF0U, 0xD83CDDF5U, }, - { 0xD83CDDF2U, 0xD83CDDF5U, }, - { 0xD83CDDF3U, 0xD83CDDF4U, }, - { 0xD83CDDF4U, 0xD83CDDF2U, }, - { 0xD83CDDF5U, 0xD83CDDF0U, }, - { 0xD83CDDF5U, 0xD83CDDFCU, }, - { 0xD83CDDF5U, 0xD83CDDF8U, }, - { 0xD83CDDF5U, 0xD83CDDE6U, }, - { 0xD83CDDF5U, 0xD83CDDECU, }, - { 0xD83CDDF5U, 0xD83CDDFEU, }, - { 0xD83CDDF5U, 0xD83CDDEAU, }, - { 0xD83CDDF5U, 0xD83CDDEDU, }, - { 0xD83CDDF5U, 0xD83CDDF3U, }, - { 0xD83CDDF5U, 0xD83CDDF1U, }, - { 0xD83CDDF5U, 0xD83CDDF9U, }, - { 0xD83CDDF5U, 0xD83CDDF7U, }, - { 0xD83CDDF6U, 0xD83CDDE6U, }, - { 0xD83CDDF7U, 0xD83CDDEAU, }, - { 0xD83CDDF7U, 0xD83CDDF4U, }, - { 0xD83CDDF7U, 0xD83CDDFAU, }, - { 0xD83CDDF7U, 0xD83CDDFCU, }, - { 0xD83CDDFCU, 0xD83CDDF8U, }, - { 0xD83CDDF8U, 0xD83CDDF2U, }, - { 0xD83CDDF8U, 0xD83CDDF9U, }, - { 0xD83CDDF8U, 0xD83CDDE6U, }, - { 0xD83CDDF8U, 0xD83CDDF3U, }, - { 0xD83CDDF7U, 0xD83CDDF8U, }, - { 0xD83CDDF8U, 0xD83CDDE8U, }, - { 0xD83CDDF8U, 0xD83CDDF1U, }, - { 0xD83CDDF8U, 0xD83CDDECU, }, - { 0xD83CDDF8U, 0xD83CDDFDU, }, - { 0xD83CDDF8U, 0xD83CDDF0U, }, - { 0xD83CDDF8U, 0xD83CDDEEU, }, - { 0xD83CDDECU, 0xD83CDDF8U, }, - { 0xD83CDDF8U, 0xD83CDDE7U, }, - { 0xD83CDDF8U, 0xD83CDDF4U, }, - { 0xD83CDDFFU, 0xD83CDDE6U, }, - { 0xD83CDDF0U, 0xD83CDDF7U, }, - { 0xD83CDDF8U, 0xD83CDDF8U, }, - { 0xD83CDDEAU, 0xD83CDDF8U, }, - { 0xD83CDDF1U, 0xD83CDDF0U, }, - { 0xD83CDDE7U, 0xD83CDDF1U, }, - { 0xD83CDDF8U, 0xD83CDDEDU, }, - { 0xD83CDDF0U, 0xD83CDDF3U, }, - { 0xD83CDDF1U, 0xD83CDDE8U, }, - { 0xD83CDDF5U, 0xD83CDDF2U, }, - { 0xD83CDDFBU, 0xD83CDDE8U, }, - { 0xD83CDDF8U, 0xD83CDDE9U, }, - { 0xD83CDDF8U, 0xD83CDDF7U, }, - { 0xD83CDDF8U, 0xD83CDDFFU, }, - { 0xD83CDDF8U, 0xD83CDDEAU, }, - { 0xD83CDDE8U, 0xD83CDDEDU, }, - { 0xD83CDDF8U, 0xD83CDDFEU, }, - { 0xD83CDDF9U, 0xD83CDDFCU, }, - { 0xD83CDDF9U, 0xD83CDDEFU, }, - { 0xD83CDDF9U, 0xD83CDDFFU, }, - { 0xD83CDDF9U, 0xD83CDDEDU, }, - { 0xD83CDDF9U, 0xD83CDDF1U, }, - { 0xD83CDDF9U, 0xD83CDDECU, }, - { 0xD83CDDF9U, 0xD83CDDF0U, }, - { 0xD83CDDF9U, 0xD83CDDF4U, }, - { 0xD83CDDF9U, 0xD83CDDF9U, }, - { 0xD83CDDF9U, 0xD83CDDF3U, }, - { 0xD83CDDF9U, 0xD83CDDF7U, }, - { 0xD83CDDF9U, 0xD83CDDF2U, }, - { 0xD83CDDF9U, 0xD83CDDE8U, }, - { 0xD83CDDF9U, 0xD83CDDFBU, }, - { 0xD83CDDFBU, 0xD83CDDEEU, }, - { 0xD83CDDFAU, 0xD83CDDECU, }, - { 0xD83CDDFAU, 0xD83CDDE6U, }, - { 0xD83CDDE6U, 0xD83CDDEAU, }, - { 0xD83CDDECU, 0xD83CDDE7U, }, - { 0xD83CDDFAU, 0xD83CDDF8U, }, - { 0xD83CDDFAU, 0xD83CDDFEU, }, - { 0xD83CDDFAU, 0xD83CDDFFU, }, - { 0xD83CDDFBU, 0xD83CDDFAU, }, - { 0xD83CDDFBU, 0xD83CDDE6U, }, - { 0xD83CDDFBU, 0xD83CDDEAU, }, - { 0xD83CDDFBU, 0xD83CDDF3U, }, - { 0xD83CDDFCU, 0xD83CDDEBU, }, - { 0xD83CDDEAU, 0xD83CDDEDU, }, - { 0xD83CDDFEU, 0xD83CDDEAU, }, - { 0xD83CDDFFU, 0xD83CDDF2U, }, - { 0xD83CDDFFU, 0xD83CDDFCU, }, -}; - -} // namespace old -} // namespace -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/data.h b/Telegram/SourceFiles/codegen/emoji/data.h deleted file mode 100644 index eb8551f5e..000000000 --- a/Telegram/SourceFiles/codegen/emoji/data.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "codegen/common/logging.h" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace codegen { -namespace emoji { - -using Id = QString; -struct Emoji { - Id id; - bool postfixed = false; - bool variated = false; - bool colored = false; -}; - -struct Data { - std::vector list; - std::map> map; - std::set postfixRequired; - std::vector> categories; - std::map> replaces; -}; -Data PrepareData(); - -constexpr auto kPostfix = 0xFE0FU; - -common::LogStream logDataError(); - -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/generator.cpp b/Telegram/SourceFiles/codegen/emoji/generator.cpp deleted file mode 100644 index 2ef7b6a25..000000000 --- a/Telegram/SourceFiles/codegen/emoji/generator.cpp +++ /dev/null @@ -1,1024 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/emoji/generator.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef SUPPORT_IMAGE_GENERATION -Q_IMPORT_PLUGIN(QWebpPlugin) -#ifdef Q_OS_MAC -Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin) -#elif defined Q_OS_WIN -Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) -#else // !Q_OS_MAC && !Q_OS_WIN -Q_IMPORT_PLUGIN(QXcbIntegrationPlugin) -#endif // !Q_OS_MAC && !Q_OS_WIN -#endif // SUPPORT_IMAGE_GENERATION - -namespace codegen { -namespace emoji { -namespace { - -constexpr auto kErrorCantWritePath = 851; - -constexpr auto kOriginalBits = 12; -constexpr auto kIdSizeBits = 6; -constexpr auto kColumnBits = 5; -constexpr auto kRowBits = 7; - -common::ProjectInfo Project = { - "codegen_emoji", - "empty", - false, // forceReGenerate -}; - -QRect computeSourceRect(const QImage &image) { - auto size = image.width(); - auto result = QRect(2, 2, size - 4, size - 4); - auto top = 1, bottom = 1, left = 1, right = 1; - auto rgbBits = reinterpret_cast(image.constBits()); - for (auto i = 0; i != size; ++i) { - if (rgbBits[i] > 0 - || rgbBits[(size - 1) * size + i] > 0 - || rgbBits[i * size] > 0 - || rgbBits[i * size + (size - 1)] > 0) { - logDataError() << "Bad border."; - return QRect(); - } - if (rgbBits[1 * size + i] > 0) { - top = -1; - } else if (top > 0 && rgbBits[2 * size + i] > 0) { - top = 0; - } - if (rgbBits[(size - 2) * size + i] > 0) { - bottom = -1; - } else if (bottom > 0 && rgbBits[(size - 3) * size + i] > 0) { - bottom = 0; - } - if (rgbBits[i * size + 1] > 0) { - left = -1; - } else if (left > 0 && rgbBits[i * size + 2] > 0) { - left = 0; - } - if (rgbBits[i * size + (size - 2)] > 0) { - right = -1; - } else if (right > 0 && rgbBits[i * size + (size - 3)] > 0) { - right = 0; - } - } - if (top < 0) { - if (bottom <= 0) { - logDataError() << "Bad vertical :("; - return QRect(); - } else { - result.setY(result.y() + 1); - } - } else if (bottom < 0) { - if (top <= 0) { - logDataError() << "Bad vertical :("; - return QRect(); - } else { - result.setY(result.y() - 1); - } - } - if (left < 0) { - if (right <= 0) { - logDataError() << "Bad horizontal :("; - return QRect(); - } else { - result.setX(result.x() + 1); - } - } else if (right < 0) { - if (left <= 0) { - logDataError() << "Bad horizontal :("; - return QRect(); - } else { - result.setX(result.x() - 1); - } - } - return result; -} - -uint32 Crc32Table[256]; -class Crc32Initializer { -public: - Crc32Initializer() { - uint32 poly = 0x04C11DB7U; - for (auto i = 0; i != 256; ++i) { - Crc32Table[i] = reflect(i, 8) << 24; - for (auto j = 0; j != 8; ++j) { - Crc32Table[i] = (Crc32Table[i] << 1) ^ (Crc32Table[i] & (1 << 31) ? poly : 0); - } - Crc32Table[i] = reflect(Crc32Table[i], 32); - } - } - -private: - uint32 reflect(uint32 val, char ch) { - uint32 result = 0; - for (int i = 1; i < (ch + 1); ++i) { - if (val & 1) { - result |= 1 << (ch - i); - } - val >>= 1; - } - return result; - } - -}; - -uint32 countCrc32(const void *data, std::size_t size) { - static Crc32Initializer InitTable; - - auto buffer = static_cast(data); - auto result = uint32(0xFFFFFFFFU); - for (auto i = std::size_t(0); i != size; ++i) { - result = (result >> 8) ^ Crc32Table[(result & 0xFFU) ^ buffer[i]]; - } - return (result ^ 0xFFFFFFFFU); -} - -} // namespace - -Generator::Generator(const Options &options) : project_(Project) -#ifdef SUPPORT_IMAGE_GENERATION -, writeImages_(options.writeImages) -#endif // SUPPORT_IMAGE_GENERATION -, data_(PrepareData()) -, replaces_(PrepareReplaces(options.replacesPath)) { - QDir dir(options.outputPath); - if (!dir.mkpath(".")) { - common::logError(kErrorCantWritePath, "Command Line") << "can not open path for writing: " << dir.absolutePath().toStdString(); - data_ = Data(); - } - if (!CheckAndConvertReplaces(replaces_, data_)) { - replaces_ = Replaces(replaces_.filename); - } - - outputPath_ = dir.absolutePath() + "/emoji"; - spritePath_ = dir.absolutePath() + "/emoji"; - suggestionsPath_ = dir.absolutePath() + "/emoji_suggestions_data"; -} - -int Generator::generate() { - if (data_.list.empty() || replaces_.list.isEmpty()) { - return -1; - } - -#ifdef SUPPORT_IMAGE_GENERATION - if (writeImages_) { - return writeImages() ? 0 : -1; - } -#endif // SUPPORT_IMAGE_GENERATION - - if (!writeSource()) { - return -1; - } - if (!writeHeader()) { - return -1; - } - if (!writeSuggestionsSource()) { - return -1; - } - if (!writeSuggestionsHeader()) { - return -1; - } - - return 0; -} - -constexpr auto kEmojiInRow = 32; -constexpr auto kEmojiRowsInFile = 16; -constexpr auto kEmojiQuality = 99; -constexpr auto kEmojiSize = 72; -constexpr auto kEmojiFontSize = 72; -constexpr auto kEmojiDelta = 67; -constexpr auto kScaleFromLarge = true; - -#ifdef SUPPORT_IMAGE_GENERATION -QImage Generator::generateImage(int imageIndex) { - constexpr auto kLargeEmojiSize = 180; - constexpr auto kLargeEmojiFontSize = 180; - constexpr auto kLargeEmojiDelta = 167; - - auto emojiCount = int(data_.list.size()); - auto columnsCount = kEmojiInRow; - auto fullRowsCount = (emojiCount / columnsCount) + ((emojiCount % columnsCount) ? 1 : 0); - auto imagesCount = (fullRowsCount / kEmojiRowsInFile) + ((fullRowsCount % kEmojiRowsInFile) ? 1 : 0); - - auto sourceSize = kScaleFromLarge ? kLargeEmojiSize : kEmojiSize; - - auto font = QGuiApplication::font(); - font.setFamily(QStringLiteral("Apple Color Emoji")); - font.setPixelSize(kScaleFromLarge ? kLargeEmojiFontSize : kEmojiFontSize); - - auto singleSize = 4 + sourceSize; - const auto inFileShift = (imageIndex * kEmojiInRow * kEmojiRowsInFile); - if (inFileShift >= emojiCount) { - return QImage(); - } - const auto maxInFile = emojiCount - inFileShift; - const auto inFileCount = std::min(maxInFile, kEmojiInRow * kEmojiRowsInFile); - auto rowsCount = (inFileCount / columnsCount) + ((inFileCount % columnsCount) ? 1 : 0); - auto emojiImage = QImage(columnsCount * kEmojiSize, rowsCount * kEmojiSize, QImage::Format_ARGB32); - emojiImage.fill(Qt::transparent); - auto singleImage = QImage(singleSize, singleSize, QImage::Format_ARGB32); - { - QPainter p(&emojiImage); - p.setRenderHint(QPainter::SmoothPixmapTransform); - - auto column = 0; - auto row = 0; - for (auto i = 0; i != inFileCount; ++i) { - auto &emoji = data_.list[inFileShift + i]; - { - singleImage.fill(Qt::transparent); - - QPainter q(&singleImage); - q.setPen(QColor(0, 0, 0, 255)); - q.setFont(font); - const auto delta = kScaleFromLarge ? kLargeEmojiDelta : kEmojiDelta; - q.drawText(2, 2 + delta, emoji.id); - } - auto sourceRect = computeSourceRect(singleImage); - if (sourceRect.isEmpty()) { - return QImage(); - } - auto targetRect = QRect(column * kEmojiSize, row * kEmojiSize, kEmojiSize, kEmojiSize); - if (kScaleFromLarge) { - p.drawImage(targetRect, singleImage.copy(sourceRect).scaled(kEmojiSize, kEmojiSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - } else { - p.drawImage(targetRect, singleImage, sourceRect); - } - ++column; - if (column == columnsCount) { - column = 0; - ++row; - } - } - } - return emojiImage; -} - -bool Generator::writeImages() { - auto imageIndex = 0; - while (true) { - auto image = generateImage(imageIndex); - if (image.isNull()) { - break; - } - auto postfix = '_' + QString::number(imageIndex + 1); - auto filename = spritePath_ + postfix + ".webp"; - auto bytes = QByteArray(); - { - QBuffer buffer(&bytes); - if (!image.save(&buffer, "WEBP", kEmojiQuality)) { - logDataError() << "Could not save 'emoji" << postfix.toStdString() << ".webp'."; - return false; - } - } - auto needResave = !QFileInfo(filename).exists(); - if (!needResave) { - QFile file(filename); - if (!file.open(QIODevice::ReadOnly)) { - needResave = true; - } else { - auto already = file.readAll(); - if (already.size() != bytes.size() || memcmp(already.constData(), bytes.constData(), already.size())) { - needResave = true; - } - } - } - if (needResave) { - QFile file(filename); - if (!file.open(QIODevice::WriteOnly)) { - logDataError() << "Could not open 'emoji" << postfix.toStdString() << ".webp'."; - return false; - } else { - if (file.write(bytes) != bytes.size()) { - logDataError() << "Could not write 'emoji" << postfix.toStdString() << ".webp'."; - return false; - } - } - } - ++imageIndex; - } - return true; -} -#endif // SUPPORT_IMAGE_GENERATION - -bool Generator::writeSource() { - source_ = std::make_unique(outputPath_ + ".cpp", project_); - - source_->include("emoji_suggestions_data.h").include("ui/emoji_config.h").newline(); - source_->pushNamespace("Ui").pushNamespace("Emoji").pushNamespace(); - source_->stream() << "\ -\n\ -std::vector Items;\n\ -\n"; - if (!writeInitCode()) { - return false; - } - if (!writeSections()) { - return false; - } - if (!writeFindReplace()) { - return false; - } - if (!writeFind()) { - return false; - } - source_->popNamespace().newline().pushNamespace("internal"); - source_->stream() << "\ -\n\ -int FullCount() {\n\ - return Items.size();\n\ -}\n\ -\n\ -EmojiPtr ByIndex(int index) {\n\ - return (index >= 0 && index < Items.size()) ? &Items[index] : nullptr;\n\ -}\n\ -\n\ -EmojiPtr FindReplace(const QChar *start, const QChar *end, int *outLength) {\n\ - auto index = FindReplaceIndex(start, end, outLength);\n\ - return index ? &Items[index - 1] : nullptr;\n\ -}\n\ -\n\ -const std::vector> GetReplacementPairs() {\n\ - return ReplacementPairs;\n\ -}\n\ -\n\ -EmojiPtr Find(const QChar *start, const QChar *end, int *outLength) {\n\ - auto index = FindIndex(start, end, outLength);\n\ - return index ? &Items[index - 1] : nullptr;\n\ -}\n\ -\n\ -void Init() {\n\ - auto id = IdData;\n\ - auto takeString = [&id](int size) {\n\ - auto result = QString::fromRawData(reinterpret_cast(id), size);\n\ - id += size;\n\ - return result;\n\ - };\n\ -\n\ - Items.reserve(base::array_size(Data));\n\ - for (auto &data : Data) {\n\ - Items.emplace_back(\n\ - takeString(data.idSize),\n\ - data.original ? &Items[data.original - 1] : nullptr,\n\ - uint32(Items.size()),\n\ - data.postfixed ? true : false,\n\ - data.variated ? true : false,\n\ - One::CreationTag());\n\ - }\n\ - InitReplacements();\n\ -}\n\ -\n"; - source_->popNamespace(); - - if (!writeGetSections()) { - return false; - } - - return source_->finalize(); -} - -bool Generator::writeHeader() { - auto header = std::make_unique(outputPath_ + ".h", project_); - header->includeFromLibrary("QtCore/QChar"); - header->includeFromLibrary("QtCore/QString"); - header->includeFromLibrary("QtCore/QVector"); - header->newline(); - header->includeFromLibrary("vector"); - header->newline(); - - header->pushNamespace("Ui").pushNamespace("Emoji"); - header->stream() << "class One;\n"; - header->popNamespace().popNamespace().newline(); - - header->stream() << "\ -using EmojiPtr = const Ui::Emoji::One*;\n\ -using EmojiPack = QVector;\n\ -\n"; - - header->pushNamespace("Ui").pushNamespace("Emoji").pushNamespace("internal"); - header->stream() << "\ -\n\ -void Init();\n\ -\n\ -int FullCount();\n\ -EmojiPtr ByIndex(int index);\n\ -\n\ -EmojiPtr Find(const QChar *ch, const QChar *end, int *outLength = nullptr);\n\ -\n\ -const std::vector> GetReplacementPairs();\n\ -EmojiPtr FindReplace(const QChar *ch, const QChar *end, int *outLength = nullptr);\n\ -\n"; - header->popNamespace().stream() << "\ -\n\ -constexpr auto kPostfix = static_cast(0xFE0F);\n\ -\n\ -enum class Section {\n\ - Recent,\n\ - People,\n\ - Nature,\n\ - Food,\n\ - Activity,\n\ - Travel,\n\ - Objects,\n\ - Symbols,\n\ -};\n\ -\n\ -int GetSectionCount(Section section);\n\ -QVector GetSection(Section section);\n\ -\n"; - return header->finalize(); -} - -template -bool Generator::enumerateWholeList(Callback callback) { - auto index = 0; - auto variated = -1; - auto coloredCount = 0; - for (auto &item : data_.list) { - if (!callback(item.id, item.postfixed, item.variated, item.colored, variated)) { - return false; - } - if (coloredCount > 0 && (item.variated || !item.colored)) { - if (!colorsCount_) { - colorsCount_ = coloredCount; - } else if (colorsCount_ != coloredCount) { - logDataError() << "different colored emoji count exist."; - return false; - } - coloredCount = 0; - } - if (item.variated) { - variated = index; - } else if (item.colored) { - if (variated <= 0) { - logDataError() << "wrong order of colored items."; - return false; - } - ++coloredCount; - } else if (variated >= 0) { - variated = -1; - } - ++index; - } - return true; -} - -bool Generator::writeInitCode() { - source_->stream() << "\ -struct DataStruct {\n\ - uint32 original : " << kOriginalBits << ";\n\ - uint32 idSize : " << kIdSizeBits << ";\n\ - uint32 postfixed : 1;\n\ - uint32 variated : 1;\n\ -};\n\ -\n\ -const ushort IdData[] = {"; - startBinary(); - if (!enumerateWholeList([this](Id id, bool isPostfixed, bool isVariated, bool isColored, int original) { - return writeStringBinary(source_.get(), id); - })) { - return false; - } - if (_binaryFullLength >= std::numeric_limits::max()) { - logDataError() << "Too many IdData elements."; - return false; - } - source_->stream() << " };\n\ -\n\ -const DataStruct Data[] = {\n"; - if (!enumerateWholeList([this](Id id, bool isPostfixed, bool isVariated, bool isColored, int original) { - if (original + 1 >= (1 << kOriginalBits)) { - logDataError() << "Too many entries."; - return false; - } - if (id.size() >= (1 << kIdSizeBits)) { - logDataError() << "Too large id."; - return false; - } - source_->stream() << "\ - { uint32(" << (isColored ? (original + 1) : 0) << "), uint32(" << id.size() << "), uint32(" << (isPostfixed ? "1" : "0") << "), uint32(" << (isVariated ? "1" : "0") << ") },\n"; - return true; - })) { - return false; - } - - source_->stream() << "\ -};\n"; - - return true; -} - -bool Generator::writeSections() { - source_->stream() << "\ -const ushort SectionData[] = {"; - startBinary(); - for (auto &category : data_.categories) { - for (auto index : category) { - writeIntBinary(source_.get(), index); - } - } - source_->stream() << " };\n\ -\n\ -EmojiPack FillSection(int offset, int size) {\n\ - auto result = EmojiPack();\n\ - result.reserve(size);\n\ - for (auto index : gsl::make_span(SectionData + offset, size)) {\n\ - result.push_back(&Items[index]);\n\ - }\n\ - return result;\n\ -}\n\n"; - return true; -} - -bool Generator::writeGetSections() { - constexpr const char *sectionNames[] = { - "Section::People", - "Section::Nature", - "Section::Food", - "Section::Activity", - "Section::Travel", - "Section::Objects", - "Section::Symbols", - }; - source_->stream() << "\ -\n\ -int GetSectionCount(Section section) {\n\ - Expects(section != Section::Recent);\n\ -\n\ - switch (section) {\n"; - auto countIndex = 0; - for (auto name : sectionNames) { - if (countIndex >= int(data_.categories.size())) { - logDataError() << "category " << countIndex << " not found."; - return false; - } - source_->stream() << "\ - case " << name << ": return " << data_.categories[countIndex++].size() << ";\n"; - } - source_->stream() << "\ - }\n\ - return 0;\n\ -}\n\ -\n\ -EmojiPack GetSection(Section section) {\n\ - Expects(section != Section::Recent);\n\ -\n\ - switch (section) {\n"; - auto index = 0; - auto offset = 0; - for (auto name : sectionNames) { - if (index >= int(data_.categories.size())) { - logDataError() << "category " << index << " not found."; - return false; - } - auto &category = data_.categories[index++]; - source_->stream() << "\ -\n\ - case " << name << ": {\n\ - static auto result = FillSection(" << offset << ", " << category.size() << ");\n\ - return result;\n\ - } break;\n"; - offset += category.size(); - } - source_->stream() << "\ - }\n\ - return EmojiPack();\n\ -}\n\ -\n"; - return true; -} - -bool Generator::writeFindReplace() { - source_->stream() << "\ -\n\ -const std::vector> ReplacementPairs = {\n"; - for (const auto &[what, index] : data_.replaces) { - source_->stream() << "\ - { \"" << what << "\", " << index << " },\n"; - } - source_->stream() << "\ -};\n\ -\n\ -int FindReplaceIndex(const QChar *start, const QChar *end, int *outLength) {\n\ - auto ch = start;\n\ -\n"; - - if (!writeFindFromDictionary(data_.replaces)) { - return false; - } - - source_->stream() << "\ -}\n"; - - return true; -} - -bool Generator::writeFind() { - source_->stream() << "\ -\n\ -int FindIndex(const QChar *start, const QChar *end, int *outLength) {\n\ - auto ch = start;\n\ -\n"; - - if (!writeFindFromDictionary(data_.map, true, data_.postfixRequired)) { - return false; - } - - source_->stream() << "\ -}\n\ -\n"; - - return true; -} - -bool Generator::writeFindFromDictionary( - const std::map> &dictionary, - bool skipPostfixes, - const std::set &postfixRequired) { - auto tabs = [](int size) { - return QString(size, '\t'); - }; - - std::map uniqueFirstChars; - auto foundMax = 0, foundMin = 65535; - for (auto &item : dictionary) { - auto ch = item.first[0].unicode(); - if (foundMax < ch) foundMax = ch; - if (foundMin > ch) foundMin = ch; - uniqueFirstChars[ch] = 0; - } - - enum class UsedCheckType { - Switch, - If, - }; - auto checkTypes = QVector(); - auto chars = QString(); - auto tabsUsed = 1; - auto lengthsCounted = std::set(); - - auto writeSkipPostfix = [this, &tabs, skipPostfixes](int tabsCount) { - if (skipPostfixes) { - source_->stream() << tabs(tabsCount) << "if (++ch != end && ch->unicode() == kPostfix) ++ch;\n"; - } else { - source_->stream() << tabs(tabsCount) << "++ch;\n"; - } - }; - - // Returns true if at least one check was finished. - auto finishChecksTillKey = [this, &chars, &checkTypes, &tabsUsed, tabs](const QString &key) { - auto result = false; - while (!chars.isEmpty() && key.midRef(0, chars.size()) != chars) { - result = true; - - auto wasType = checkTypes.back(); - chars.resize(chars.size() - 1); - checkTypes.pop_back(); - if (wasType == UsedCheckType::Switch || wasType == UsedCheckType::If) { - --tabsUsed; - if (wasType == UsedCheckType::Switch) { - source_->stream() << tabs(tabsUsed) << "break;\n"; - } - if ((!chars.isEmpty() && key.midRef(0, chars.size()) != chars) || key == chars) { - source_->stream() << tabs(tabsUsed) << "}\n"; - } - } - } - return result; - }; - - // Check if we can use "if" for a check on "charIndex" in "it" (otherwise only "switch") - auto canUseIfForCheck = [](auto it, auto end, int charIndex) { - auto key = it->first; - auto i = it; - auto keyStart = key.mid(0, charIndex); - for (++i; i != end; ++i) { - auto nextKey = i->first; - if (nextKey.mid(0, charIndex) != keyStart) { - return true; - } else if (nextKey.size() > charIndex && nextKey[charIndex] != key[charIndex]) { - return false; - } - } - return true; - }; - - for (auto i = dictionary.cbegin(), e = dictionary.cend(); i != e; ++i) { - auto &item = *i; - auto key = item.first; - auto weContinueOldSwitch = finishChecksTillKey(key); - while (chars.size() != key.size()) { - auto checking = chars.size(); - auto partialKey = key.mid(0, checking); - if (dictionary.find(partialKey) != dictionary.cend()) { - if (lengthsCounted.find(partialKey) == end(lengthsCounted)) { - lengthsCounted.emplace(partialKey); - source_->stream() << tabs(tabsUsed) << "if (outLength) *outLength = (ch - start);\n"; - } - } - - auto keyChar = key[checking]; - auto keyCharString = "0x" + QString::number(keyChar.unicode(), 16); - auto usedIfForCheck = !weContinueOldSwitch && canUseIfForCheck(i, e, checking); - if (weContinueOldSwitch) { - weContinueOldSwitch = false; - } else if (!usedIfForCheck) { - source_->stream() << tabs(tabsUsed) << "if (ch != end) switch (ch->unicode()) {\n"; - } - if (usedIfForCheck) { - source_->stream() << tabs(tabsUsed) << "if (ch != end && ch->unicode() == " << keyCharString << ") {\n"; - checkTypes.push_back(UsedCheckType::If); - } else { - source_->stream() << tabs(tabsUsed) << "case " << keyCharString << ":\n"; - checkTypes.push_back(UsedCheckType::Switch); - } - writeSkipPostfix(++tabsUsed); - chars.push_back(keyChar); - } - - if (postfixRequired.find(item.second) != end(postfixRequired)) { - source_->stream() << tabs(tabsUsed) << "if ((ch - 1)->unicode() != kPostfix) {\n"; - source_->stream() << tabs(tabsUsed + 1) << "return 0;\n"; - source_->stream() << tabs(tabsUsed) << "}\n"; - } - if (lengthsCounted.find(key) == end(lengthsCounted)) { - lengthsCounted.emplace(key); - source_->stream() << tabs(tabsUsed) << "if (outLength) *outLength = (ch - start);\n"; - } - - source_->stream() << tabs(tabsUsed) << "return " << (item.second + 1) << ";\n"; - } - finishChecksTillKey(QString()); - - source_->stream() << "\ -\n\ - return 0;\n"; - return true; -} - -bool Generator::writeSuggestionsSource() { - suggestionsSource_ = std::make_unique(suggestionsPath_ + ".cpp", project_); - suggestionsSource_->stream() << "\ -#include \n\ -\n"; - suggestionsSource_->pushNamespace("Ui").pushNamespace("Emoji").pushNamespace("internal").pushNamespace(); - suggestionsSource_->stream() << "\ -\n"; - if (!writeReplacements()) { - return false; - } - suggestionsSource_->popNamespace().newline(); - if (!writeGetReplacements()) { - return false; - } - - return suggestionsSource_->finalize(); -} - -bool Generator::writeSuggestionsHeader() { - auto maxLength = 0; - for (auto &replace : replaces_.list) { - if (maxLength < replace.replacement.size()) { - maxLength = replace.replacement.size(); - } - } - auto header = std::make_unique(suggestionsPath_ + ".h", project_); - header->include("emoji_suggestions.h").newline(); - header->pushNamespace("Ui").pushNamespace("Emoji").pushNamespace("internal"); - header->stream() << "\ -\n\ -struct Replacement {\n\ - utf16string emoji;\n\ - utf16string replacement;\n\ - std::vector words;\n\ -};\n\ -\n\ -constexpr auto kReplacementMaxLength = " << maxLength << ";\n\ -\n\ -void InitReplacements();\n\ -const std::vector &GetAllReplacements();\n\ -const std::vector *GetReplacements(utf16char first);\n\ -utf16string GetReplacementEmoji(utf16string replacement);\n\ -\n"; - return header->finalize(); -} - -bool Generator::writeReplacements() { - QMap> byCharIndices; - suggestionsSource_->stream() << "\ -struct ReplacementStruct {\n\ - small emojiSize;\n\ - small replacementSize;\n\ - small wordsCount;\n\ -};\n\ -\n\ -const utf16char ReplacementData[] = {"; - startBinary(); - for (auto i = 0, size = replaces_.list.size(); i != size; ++i) { - auto &replace = replaces_.list[i]; - if (!writeStringBinary(suggestionsSource_.get(), replace.id)) { - return false; - } - if (!writeStringBinary(suggestionsSource_.get(), replace.replacement)) { - return false; - } - for (auto &word : replace.words) { - if (!writeStringBinary(suggestionsSource_.get(), word)) { - return false; - } - auto &index = byCharIndices[word[0]]; - if (index.isEmpty() || index.back() != i) { - index.push_back(i); - } - } - } - suggestionsSource_->stream() << " };\n\ -\n\ -const small ReplacementWordLengths[] = {"; - startBinary(); - for (auto &replace : replaces_.list) { - auto wordLengths = QStringList(); - for (auto &word : replace.words) { - writeIntBinary(suggestionsSource_.get(), word.size()); - } - } - suggestionsSource_->stream() << " };\n\ -\n\ -const ReplacementStruct ReplacementInitData[] = {\n"; - for (auto &replace : replaces_.list) { - suggestionsSource_->stream() << "\ - { small(" << replace.id.size() << "), small(" << replace.replacement.size() << "), small(" << replace.words.size() << ") },\n"; - } - suggestionsSource_->stream() << "};\n\ -\n\ -const medium ReplacementIndices[] = {"; - startBinary(); - for (auto &byCharIndex : byCharIndices) { - for (auto index : byCharIndex) { - writeIntBinary(suggestionsSource_.get(), index); - } - } - suggestionsSource_->stream() << " };\n\ -\n\ -struct ReplacementIndexStruct {\n\ - utf16char ch;\n\ - medium count;\n\ -};\n\ -\n\ -const internal::checksum ReplacementChecksums[] = {\n"; - startBinary(); - for (auto &replace : replaces_.list) { - writeUintBinary(suggestionsSource_.get(), countCrc32(replace.replacement.constData(), replace.replacement.size() * sizeof(QChar))); - } - suggestionsSource_->stream() << " };\n\ -\n\ -const ReplacementIndexStruct ReplacementIndexData[] = {\n"; - startBinary(); - for (auto i = byCharIndices.cbegin(), e = byCharIndices.cend(); i != e; ++i) { - suggestionsSource_->stream() << "\ - { utf16char(" << i.key().unicode() << "), medium(" << i.value().size() << ") },\n"; - } - suggestionsSource_->stream() << "};\n\ -\n\ -std::vector Replacements;\n\ -std::map> ReplacementsMap;\n\ -std::map ReplacementsHash;\n\ -\n"; - return true; -} - -bool Generator::writeGetReplacements() { - suggestionsSource_->stream() << "\ -void InitReplacements() {\n\ - if (!Replacements.empty()) {\n\ - return;\n\ - }\n\ - auto data = ReplacementData;\n\ - auto takeString = [&data](int size) {\n\ - auto result = utf16string(data, size);\n\ - data += size;\n\ - return result;\n\ - };\n\ - auto wordSize = ReplacementWordLengths;\n\ -\n\ - Replacements.reserve(" << replaces_.list.size() << ");\n\ - for (auto item : ReplacementInitData) {\n\ - auto emoji = takeString(item.emojiSize);\n\ - auto replacement = takeString(item.replacementSize);\n\ - auto words = std::vector();\n\ - words.reserve(item.wordsCount);\n\ - for (auto i = 0; i != item.wordsCount; ++i) {\n\ - words.push_back(takeString(*wordSize++));\n\ - }\n\ - Replacements.push_back({ std::move(emoji), std::move(replacement), std::move(words) });\n\ - }\n\ -\n\ - auto indices = ReplacementIndices;\n\ - auto items = &Replacements[0];\n\ - for (auto item : ReplacementIndexData) {\n\ - auto index = std::vector();\n\ - index.reserve(item.count);\n\ - for (auto i = 0; i != item.count; ++i) {\n\ - index.push_back(items + (*indices++));\n\ - }\n\ - ReplacementsMap.emplace(item.ch, std::move(index));\n\ - }\n\ -\n\ - for (auto checksum : ReplacementChecksums) {\n\ - ReplacementsHash.emplace(checksum, items++);\n\ - }\n\ -}\n\ -\n\ -const std::vector *GetReplacements(utf16char first) {\n\ - if (ReplacementsMap.empty()) {\n\ - InitReplacements();\n\ - }\n\ - auto it = ReplacementsMap.find(first);\n\ - return (it == ReplacementsMap.cend()) ? nullptr : &it->second;\n\ -}\n\ -\n\ -const std::vector &GetAllReplacements() {\n\ - return Replacements;\n\ -}\n\ -\n\ -utf16string GetReplacementEmoji(utf16string replacement) {\n\ - auto code = internal::countChecksum(replacement.data(), replacement.size() * sizeof(utf16char));\n\ - auto it = ReplacementsHash.find(code);\n\ - return (it == ReplacementsHash.cend()) ? utf16string() : it->second->emoji;\n\ -}\n\ -\n"; - return true; -} - -void Generator::startBinary() { - _binaryFullLength = _binaryCount = 0; -} - -bool Generator::writeStringBinary(common::CppFile *source, const QString &string) { - if (string.size() >= 256) { - logDataError() << "Too long string: " << string.toStdString(); - return false; - } - for (auto ch : string) { - if (_binaryFullLength > 0) source->stream() << ","; - if (!_binaryCount++) { - source->stream() << "\n"; - } else { - if (_binaryCount == 12) { - _binaryCount = 0; - } - source->stream() << " "; - } - source->stream() << "0x" << QString::number(ch.unicode(), 16); - ++_binaryFullLength; - } - return true; -} - -void Generator::writeIntBinary(common::CppFile *source, int data) { - if (_binaryFullLength > 0) source->stream() << ","; - if (!_binaryCount++) { - source->stream() << "\n"; - } else { - if (_binaryCount == 12) { - _binaryCount = 0; - } - source->stream() << " "; - } - source->stream() << data; - ++_binaryFullLength; -} - -void Generator::writeUintBinary(common::CppFile *source, uint32 data) { - if (_binaryFullLength > 0) source->stream() << ","; - if (!_binaryCount++) { - source->stream() << "\n"; - } else { - if (_binaryCount == 12) { - _binaryCount = 0; - } - source->stream() << " "; - } - source->stream() << "0x" << QString::number(data, 16).toUpper() << "U"; - ++_binaryFullLength; -} - -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/generator.h b/Telegram/SourceFiles/codegen/emoji/generator.h deleted file mode 100644 index b8c8541a7..000000000 --- a/Telegram/SourceFiles/codegen/emoji/generator.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include "codegen/common/cpp_file.h" -#include "codegen/emoji/options.h" -#include "codegen/emoji/data.h" -#include "codegen/emoji/replaces.h" - -namespace codegen { -namespace emoji { - -using uint32 = unsigned int; - -class Generator { -public: - Generator(const Options &options); - Generator(const Generator &other) = delete; - Generator &operator=(const Generator &other) = delete; - - int generate(); - -private: -#ifdef SUPPORT_IMAGE_GENERATION - QImage generateImage(int imageIndex); - bool writeImages(); -#endif // SUPPORT_IMAGE_GENERATION - - bool writeSource(); - bool writeHeader(); - bool writeSuggestionsSource(); - bool writeSuggestionsHeader(); - - template - bool enumerateWholeList(Callback callback); - - bool writeInitCode(); - bool writeSections(); - bool writeReplacements(); - bool writeGetSections(); - bool writeFindReplace(); - bool writeFind(); - bool writeFindFromDictionary( - const std::map> &dictionary, - bool skipPostfixes = false, - const std::set &postfixRequired = {}); - bool writeGetReplacements(); - void startBinary(); - bool writeStringBinary(common::CppFile *source, const QString &string); - void writeIntBinary(common::CppFile *source, int data); - void writeUintBinary(common::CppFile *source, uint32 data); - - const common::ProjectInfo &project_; - int colorsCount_ = 0; -#ifdef SUPPORT_IMAGE_GENERATION - bool writeImages_ = false; -#endif // SUPPORT_IMAGE_GENERATION - QString outputPath_; - QString spritePath_; - std::unique_ptr source_; - Data data_; - - QString suggestionsPath_; - std::unique_ptr suggestionsSource_; - Replaces replaces_; - - int _binaryFullLength = 0; - int _binaryCount = 0; - -}; - -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/main.cpp b/Telegram/SourceFiles/codegen/emoji/main.cpp deleted file mode 100644 index 3205055c2..000000000 --- a/Telegram/SourceFiles/codegen/emoji/main.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include - -#include "codegen/emoji/options.h" -#include "codegen/emoji/generator.h" - -int main(int argc, char *argv[]) { -#ifdef SUPPORT_IMAGE_GENERATION -#ifndef Q_OS_MAC -#error "Image generation is supported only on macOS" -#endif // Q_OS_MAC - QGuiApplication app(argc, argv); -#else // SUPPORT_IMAGE_GENERATION - QCoreApplication app(argc, argv); -#endif // SUPPORT_IMAGE_GENERATION - - auto options = codegen::emoji::parseOptions(); - - codegen::emoji::Generator generator(options); - return generator.generate(); -} diff --git a/Telegram/SourceFiles/codegen/emoji/options.cpp b/Telegram/SourceFiles/codegen/emoji/options.cpp deleted file mode 100644 index 4f11ed637..000000000 --- a/Telegram/SourceFiles/codegen/emoji/options.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/emoji/options.h" - -#include -#include -#include "codegen/common/logging.h" - -namespace codegen { -namespace emoji { -namespace { - -constexpr int kErrorOutputPathExpected = 902; -constexpr int kErrorReplacesPathExpected = 903; -constexpr int kErrorOneReplacesPathExpected = 904; - -} // namespace - -using common::logError; - -Options parseOptions() { - Options result; - auto args = QCoreApplication::instance()->arguments(); - for (int i = 1, count = args.size(); i < count; ++i) { // skip first - auto &arg = args.at(i); - - // Output path - if (arg == "-o") { - if (++i == count) { - logError(kErrorOutputPathExpected, "Command Line") << "output path expected after -o"; - return Options(); - } else { - result.outputPath = args.at(i); - } - } else if (arg.startsWith("-o")) { - result.outputPath = arg.mid(2); -#ifdef SUPPORT_IMAGE_GENERATION - } else if (arg == "--images") { - result.writeImages = true; -#endif // SUPPORT_IMAGE_GENERATION - } else if (result.replacesPath.isEmpty()) { - result.replacesPath = arg; - } else { - logError(kErrorOneReplacesPathExpected, "Command Line") << "only one replaces path expected"; - return Options(); - } - } - if (result.outputPath.isEmpty()) { - logError(kErrorOutputPathExpected, "Command Line") << "output path expected"; - return Options(); - } else if (result.replacesPath.isEmpty()) { - logError(kErrorReplacesPathExpected, "Command Line") << "replaces path expected"; - return Options(); - } - return result; -} - -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/options.h b/Telegram/SourceFiles/codegen/emoji/options.h deleted file mode 100644 index 6803ce657..000000000 --- a/Telegram/SourceFiles/codegen/emoji/options.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -#ifdef __APPLE__ -#define SUPPORT_IMAGE_GENERATION -#endif // __APPLE__ - -namespace codegen { -namespace emoji { - -struct Options { - QString outputPath = "."; - QString replacesPath; -#ifdef SUPPORT_IMAGE_GENERATION - bool writeImages = false; -#endif // SUPPORT_IMAGE_GENERATION -}; - -// Parsing failed if inputPath is empty in the result. -Options parseOptions(); - -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/replaces.cpp b/Telegram/SourceFiles/codegen/emoji/replaces.cpp deleted file mode 100644 index 3b5c237e7..000000000 --- a/Telegram/SourceFiles/codegen/emoji/replaces.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/emoji/replaces.h" - -#include "codegen/emoji/data.h" -#include -#include -#include -#include - -namespace codegen { -namespace emoji { -namespace { - -constexpr auto kErrorBadReplaces = 402; - -common::LogStream logReplacesError(const QString &filename) { - return common::logError(kErrorBadReplaces, filename) << "Bad data: "; -} - -auto RegExpCode = QRegularExpression("^:[\\+\\-a-z0-9_]+:$"); -auto RegExpTone = QRegularExpression("_tone[0-9]"); -auto RegExpHex = QRegularExpression("^[0-9a-f]+$"); - -class ReplacementWords { -public: - ReplacementWords(const QString &string); - QVector result() const; - -private: - friend ReplacementWords operator+(const ReplacementWords &a, const ReplacementWords &b); - - QMap wordsWithCounts_; - -}; - -ReplacementWords::ReplacementWords(const QString &string) { - auto feedWord = [this](QString &word) { - if (!word.isEmpty()) { - ++wordsWithCounts_[word]; - word.clear(); - } - }; - // Split by all non-letters-or-numbers. - // Leave '-' and '+' inside a word only if they're followed by a number. - auto word = QString(); - for (auto i = string.cbegin(), e = string.cend(); i != e; ++i) { - if (i->isLetterOrNumber()) { - word.append(*i); - continue; - } else if (*i == '-' || *i == '+') { - if (i + 1 != e && (i + 1)->isNumber()) { - word.append(*i); - continue; - } - } - feedWord(word); - } - feedWord(word); -} - -QVector ReplacementWords::result() const { - auto result = QVector(); - for (auto i = wordsWithCounts_.cbegin(), e = wordsWithCounts_.cend(); i != e; ++i) { - for (auto j = 0, count = i.value(); j != count; ++j) { - result.push_back(i.key()); - } - } - return result; -} - -ReplacementWords operator+(const ReplacementWords &a, const ReplacementWords &b) { - ReplacementWords result = a; - for (auto i = b.wordsWithCounts_.cbegin(), e = b.wordsWithCounts_.cend(); i != e; ++i) { - auto j = result.wordsWithCounts_.constFind(i.key()); - if (j == result.wordsWithCounts_.cend() || j.value() < i.value()) { - result.wordsWithCounts_[i.key()] = i.value(); - } - } - return result; -} - -bool AddReplacement(Replaces &result, const Id &id, const QString &replacement, const QString &name) { - auto replace = Replace(); - replace.id = id; - replace.replacement = replacement; - replace.words = (ReplacementWords(replacement)).result();// + ReplacementWords(name)).result(); - if (replace.words.isEmpty()) { - logReplacesError(result.filename) << "Child '" << replacement.toStdString() << "' has no words."; - return false; - } - result.list.push_back(replace); - return true; -} - -QString ComposeString(const std::initializer_list &chars) { - auto result = QString(); - result.reserve(chars.size()); - for (auto ch : chars) { - result.append(ch); - } - return result; -} - -const auto NotSupported = [] { - auto result = QSet(); - auto insert = [&result](auto... args) { - result.insert(ComposeString({ args... })); - }; - insert(0x0023, 0xFE0F); // :pound_symbol: - insert(0x002A, 0xFE0F); // :asterisk_symbol: - for (auto i = 0; i != 10; ++i) { - insert(0x0030 + i, 0xFE0F); // :digit_zero: ... :digit_nine: - } - for (auto i = 0; i != 5; ++i) { - insert(0xD83C, 0xDFFB + i); // :tone1: ... :tone5: - } - for (auto i = 0; i != 26; ++i) { - insert(0xD83C, 0xDDE6 + i); // :regional_indicator_a: ... :regional_indicator_z: - } - insert(0x2640, 0xFE0F); // :female_sign: - insert(0x2642, 0xFE0F); // :male_sign: - insert(0x2695, 0xFE0F); // :medical_symbol: - - return result; -}(); - -const auto ConvertMap = ([] { - auto result = QMap(); - auto insert = [&result](const std::initializer_list &from, const std::initializer_list &to) { - result.insert(ComposeString(from), ComposeString(to)); - }; - auto insertWithAdd = [&result](const std::initializer_list &from, const QString &added) { - auto code = ComposeString(from); - result.insert(code, code + added); - }; - auto maleModifier = ComposeString({ 0x200D, 0x2642, 0xFE0F }); - auto femaleModifier = ComposeString({ 0x200D, 0x2640, 0xFE0F }); - insertWithAdd({ 0xD83E, 0xDD26 }, maleModifier); - insertWithAdd({ 0xD83E, 0xDD37 }, femaleModifier); - insertWithAdd({ 0xD83E, 0xDD38 }, maleModifier); - insertWithAdd({ 0xD83E, 0xDD39 }, maleModifier); - insertWithAdd({ 0xD83E, 0xDD3C }, maleModifier); - insertWithAdd({ 0xD83E, 0xDD3D }, maleModifier); - insertWithAdd({ 0xD83E, 0xDD3E }, femaleModifier); - - // :kiss_woman_man: - insert({ 0xD83D, 0xDC69, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC8B, 0x200D, 0xD83D, 0xDC68 }, { 0xD83D, 0xDC8F }); - - // :family_man_woman_boy: - insert({ 0xD83D, 0xDC68, 0x200D, 0xD83D, 0xDC69, 0x200D, 0xD83D, 0xDC66 }, { 0xD83D, 0xDC6A }); - - // :couple_with_heart_woman_man: - insert({ 0xD83D, 0xDC69, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 }, { 0xD83D, 0xDC91 }); - - auto insertFlag = [insert](char ch1, char ch2, char ch3, char ch4) { - insert({ 0xD83C, 0xDDE6 + (ch1 - 'a'), 0xD83C, 0xDDe6 + (ch2 - 'a') }, { 0xD83C, 0xDDE6 + (ch3 - 'a'), 0xD83C, 0xDDe6 + (ch4 - 'a') }); - }; - insertFlag('a', 'c', 's', 'h'); - insertFlag('b', 'v', 'n', 'o'); - insertFlag('c', 'p', 'f', 'r'); - insertFlag('d', 'g', 'i', 'o'); - insertFlag('e', 'a', 'e', 's'); - insertFlag('h', 'm', 'a', 'u'); - insertFlag('m', 'f', 'f', 'r'); - insertFlag('s', 'j', 'n', 'o'); - insertFlag('t', 'a', 's', 'h'); - insertFlag('u', 'm', 'u', 's'); - - return result; -})(); - -// Empty string result means we should skip this one. -QString ConvertEmojiId(const Id &id, const QString &replacement) { - if (RegExpTone.match(replacement).hasMatch()) { - return QString(); - } - if (NotSupported.contains(id)) { - return QString(); - } - return ConvertMap.value(id, id); -} - -} // namespace - -Replaces PrepareReplaces(const QString &filename) { - auto result = Replaces(filename); - auto content = ([filename] { - QFile f(filename); - return f.open(QIODevice::ReadOnly) ? f.readAll() : QByteArray(); - })(); - if (content.isEmpty()) { - logReplacesError(filename) << "Could not read data."; - return result; - } - auto error = QJsonParseError(); - auto document = QJsonDocument::fromJson(content, &error); - if (error.error != QJsonParseError::NoError) { - logReplacesError(filename) << "Could not parse data (" << int(error.error) << "): " << error.errorString().toStdString(); - return result; - } - if (!document.isObject()) { - logReplacesError(filename) << "Root object not found."; - return result; - } - auto list = document.object(); - for (auto i = list.constBegin(), e = list.constEnd(); i != e; ++i) { - if (!(*i).isObject()) { - logReplacesError(filename) << "Child object not found."; - return Replaces(filename); - } - auto childKey = i.key(); - auto child = (*i).toObject(); - auto failed = false; - auto getString = [filename, childKey, &child, &failed](const QString &key) { - auto it = child.constFind(key); - if (it == child.constEnd() || !(*it).isString()) { - logReplacesError(filename) << "Child '" << childKey.toStdString() << "' field not found: " << key.toStdString(); - failed = true; - return QString(); - } - return (*it).toString(); - }; - auto idParts = getString("output").split('-'); - auto name = getString("name"); - auto replacement = getString("alpha_code"); - auto aliases = getString("aliases").split('|'); - const auto Exceptions = { ":shrug:" }; - for (const auto &exception : Exceptions) { - const auto index = aliases.indexOf(exception); - if (index >= 0) { - aliases.removeAt(index); - } - } - if (aliases.size() == 1 && aliases[0].isEmpty()) { - aliases.clear(); - } - if (failed) { - return Replaces(filename); - } - if (!RegExpCode.match(replacement).hasMatch()) { - logReplacesError(filename) << "Child '" << childKey.toStdString() << "' alpha_code invalid: " << replacement.toStdString(); - return Replaces(filename); - } - for (auto &alias : aliases) { - if (!RegExpCode.match(alias).hasMatch()) { - logReplacesError(filename) << "Child '" << childKey.toStdString() << "' alias invalid: " << alias.toStdString(); - return Replaces(filename); - } - } - auto id = Id(); - for (auto &idPart : idParts) { - auto ok = true; - auto utf32 = idPart.toInt(&ok, 0x10); - if (!ok || !RegExpHex.match(idPart).hasMatch()) { - logReplacesError(filename) << "Child '" << childKey.toStdString() << "' output part invalid: " << idPart.toStdString(); - return Replaces(filename); - } - if (utf32 >= 0 && utf32 < 0x10000) { - auto ch = QChar(ushort(utf32)); - if (ch.isLowSurrogate() || ch.isHighSurrogate()) { - logReplacesError(filename) << "Child '" << childKey.toStdString() << "' output part invalid: " << idPart.toStdString(); - return Replaces(filename); - } - id.append(ch); - } else if (utf32 >= 0x10000 && utf32 <= 0x10FFFF) { - auto hi = ((utf32 - 0x10000) / 0x400) + 0xD800; - auto lo = ((utf32 - 0x10000) % 0x400) + 0xDC00; - id.append(QChar(ushort(hi))); - id.append(QChar(ushort(lo))); - } else { - logReplacesError(filename) << "Child '" << childKey.toStdString() << "' output part invalid: " << idPart.toStdString(); - return Replaces(filename); - } - } - id = ConvertEmojiId(id, replacement); - if (id.isEmpty()) { - continue; - } - if (!AddReplacement(result, id, replacement, name)) { - return Replaces(filename); - } - for (auto &alias : aliases) { - if (!AddReplacement(result, id, alias, name)) { - return Replaces(filename); - } - } - } - if (!AddReplacement(result, ComposeString({ 0xD83D, 0xDC4D }), ":like:", "thumbs up")) { - return Replaces(filename); - } - if (!AddReplacement(result, ComposeString({ 0xD83D, 0xDC4E }), ":dislike:", "thumbs down")) { - return Replaces(filename); - } - if (!AddReplacement(result, ComposeString({ 0xD83E, 0xDD14 }), ":hmm:", "thinking")) { - return Replaces(filename); - } - if (!AddReplacement(result, ComposeString({ 0xD83E, 0xDD73 }), ":party:", "celebration")) { - return Replaces(filename); - } - return result; -} - -bool CheckAndConvertReplaces(Replaces &replaces, const Data &data) { - auto result = Replaces(replaces.filename); - auto sorted = QMap(); - auto findId = [&data](const Id &id) { - return data.map.find(id) != data.map.cend(); - }; - auto findAndSort = [findId, &data, &sorted](Id id, const Replace &replace) { - if (!findId(id)) { - id.replace(QChar(0xFE0F), QString()); - if (!findId(id)) { - return false; - } - } - auto it = data.map.find(id); - id = data.list[it->second].id; - if (data.list[it->second].postfixed) { - id += QChar(kPostfix); - } - auto inserted = sorted.insertMulti(id, replace); - inserted.value().id = id; - return true; - }; - - // Find all replaces in data.map, adjust id if necessary. - // Store all replaces in sorted map to find them fast afterwards. - auto maleModifier = ComposeString({ 0x200D, 0x2642, 0xFE0F }); - auto femaleModifier = ComposeString({ 0x200D, 0x2640, 0xFE0F }); - for (auto &replace : replaces.list) { - if (findAndSort(replace.id, replace)) { - continue; - } - if (replace.id.endsWith(maleModifier)) { - auto defaultId = replace.id.mid(0, replace.id.size() - maleModifier.size()); - if (findAndSort(defaultId, replace)) { - continue; - } - } else if (replace.id.endsWith(femaleModifier)) { - auto defaultId = replace.id.mid(0, replace.id.size() - femaleModifier.size()); - if (findAndSort(defaultId, replace)) { - continue; - } - } else if (findId(replace.id + maleModifier)) { - if (findId(replace.id + femaleModifier)) { - logReplacesError(replaces.filename) << "Replace '" << replace.replacement.toStdString() << "' ambiguous."; - return false; - } else { - findAndSort(replace.id + maleModifier, replace); - continue; - } - } else if (findAndSort(replace.id + femaleModifier, replace)) { - continue; - } - logReplacesError(replaces.filename) << "Replace '" << replace.replacement.toStdString() << "' not found."; - return false; - } - - // Go through all categories and put all replaces in order of emoji in categories. - result.list.reserve(replaces.list.size()); - for (auto &category : data.categories) { - for (auto index : category) { - auto id = data.list[index].id; - if (data.list[index].postfixed) { - id += QChar(kPostfix); - } - for (auto it = sorted.find(id); it != sorted.cend(); sorted.erase(it), it = sorted.find(id)) { - result.list.push_back(it.value()); - } - } - } - if (result.list.size() != replaces.list.size()) { - logReplacesError(replaces.filename) << "Some were not found."; - return false; - } - if (!sorted.isEmpty()) { - logReplacesError(replaces.filename) << "Weird."; - return false; - } - replaces = std::move(result); - return true; -} - -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/emoji/replaces.h b/Telegram/SourceFiles/codegen/emoji/replaces.h deleted file mode 100644 index 9156eee8b..000000000 --- a/Telegram/SourceFiles/codegen/emoji/replaces.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "codegen/common/logging.h" -#include "codegen/emoji/data.h" -#include - -namespace codegen { -namespace emoji { - -struct Replace { - Id id; - QString replacement; - QVector words; -}; - -struct Replaces { - Replaces(const QString &filename) : filename(filename) { - } - QString filename; - QVector list; -}; - -Replaces PrepareReplaces(const QString &filename); -bool CheckAndConvertReplaces(Replaces &replaces, const Data &data); - -} // namespace emoji -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/generator.cpp b/Telegram/SourceFiles/codegen/lang/generator.cpp deleted file mode 100644 index 400a5638c..000000000 --- a/Telegram/SourceFiles/codegen/lang/generator.cpp +++ /dev/null @@ -1,593 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/lang/generator.h" - -#include -#include -#include -#include -#include -#include - -namespace codegen { -namespace lang { -namespace { - -char hexChar(uchar ch) { - if (ch < 10) { - return '0' + ch; - } else if (ch < 16) { - return 'a' + (ch - 10); - } - return '0'; -} - -char hexSecondChar(char ch) { - return hexChar((*reinterpret_cast(&ch)) & 0x0F); -} - -char hexFirstChar(char ch) { - return hexChar((*reinterpret_cast(&ch)) >> 4); -} - -QString stringToEncodedString(const QString &str) { - QString result, lineBreak = "\\\n"; - result.reserve(str.size() * 8); - bool writingHexEscapedCharacters = false, startOnNewLine = false; - int lastCutSize = 0; - auto utf = str.toUtf8(); - for (auto ch : utf) { - if (result.size() - lastCutSize > 80) { - startOnNewLine = true; - result.append(lineBreak); - lastCutSize = result.size(); - } - if (ch == '\n') { - writingHexEscapedCharacters = false; - result.append("\\n"); - } else if (ch == '\t') { - writingHexEscapedCharacters = false; - result.append("\\t"); - } else if (ch == '"' || ch == '\\') { - writingHexEscapedCharacters = false; - result.append('\\').append(ch); - } else if (ch < 32 || static_cast(ch) > 127) { - writingHexEscapedCharacters = true; - result.append("\\x").append(hexFirstChar(ch)).append(hexSecondChar(ch)); - } else { - if (writingHexEscapedCharacters) { - writingHexEscapedCharacters = false; - result.append("\"\""); - } - result.append(ch); - } - } - return '"' + (startOnNewLine ? lineBreak : QString()) + result + '"'; -} - -QString stringToEncodedString(const std::string &str) { - return stringToEncodedString(QString::fromStdString(str)); -} - -QString stringToBinaryArray(const std::string &str) { - QStringList rows, chars; - chars.reserve(13); - rows.reserve(1 + (str.size() / 13)); - for (uchar ch : str) { - if (chars.size() > 12) { - rows.push_back(chars.join(", ")); - chars.clear(); - } - chars.push_back(QString("0x") + hexFirstChar(ch) + hexSecondChar(ch)); - } - if (!chars.isEmpty()) { - rows.push_back(chars.join(", ")); - } - return QString("{") + ((rows.size() > 1) ? '\n' : ' ') + rows.join(",\n") + " }"; -} - -} // namespace - -Generator::Generator(const LangPack &langpack, const QString &destBasePath, const common::ProjectInfo &project) -: langpack_(langpack) -, basePath_(destBasePath) -, baseName_(QFileInfo(basePath_).baseName()) -, project_(project) { -} - -bool Generator::writeHeader() { - header_ = std::make_unique(basePath_ + ".h", project_); - header_->include("lang/lang_tag.h").include("lang/lang_values.h").newline(); - - writeHeaderForwardDeclarations(); - writeHeaderTagTypes(); - writeHeaderInterface(); - writeHeaderReactiveInterface(); - - return header_->finalize(); -} - -void Generator::writeHeaderForwardDeclarations() { - header_->pushNamespace("Lang").stream() << "\ -\n\ -inline constexpr auto kTagsCount = ushort(" << langpack_.tags.size() << ");\n\ -inline constexpr auto kKeysCount = ushort(" << langpack_.entries.size() << ");\n\ -\n"; - header_->popNamespace().newline(); -} - -void Generator::writeHeaderTagTypes() { - auto index = 0; - for (auto &tag : langpack_.tags) { - if (tag.tag == kPluralTags[0]) { - auto elements = QStringList(); - header_->stream() - << "enum lngtag_" << tag.tag << " : int { "; - for (auto i = 0; i != kPluralTags.size(); ++i) { - elements.push_back("lt_" + kPluralTags[i] + " = " + QString::number(index + i * 1000)); - } - header_->stream() << elements.join(", ") << " };\n"; - ++index; - } else { - header_->stream() << "enum lngtag_" << tag.tag << " : int { lt_" << tag.tag << " = " << index++ << " };\n"; - } - } - header_->newline(); -} - -void Generator::writeHeaderInterface() { - header_->pushNamespace("Lang").stream() << "\ -\n\ -ushort GetTagIndex(QLatin1String tag);\n\ -ushort GetKeyIndex(QLatin1String key);\n\ -bool IsTagReplaced(ushort key, ushort tag);\n\ -QString GetOriginalValue(ushort key);\n\ -\n"; - writeHeaderTagValueLookup(); - header_->popNamespace().newline(); -} - -void Generator::writeHeaderTagValueLookup() { - header_->pushNamespace("details").stream() << "\ -\n\ -template \n\ -struct TagData;\n\ -\n\ -template \n\ -inline constexpr ushort TagValue() {\n\ - return TagData::value;\n\ -}\n\ -\n"; - - for (auto &tag : langpack_.tags) { - header_->stream() << "template <> struct TagData : std::integral_constant {};\n"; - } - - header_->newline().popNamespace(); -} - -void Generator::writeHeaderReactiveInterface() { - header_->pushNamespace("tr"); - - writeHeaderProducersInterface(); - writeHeaderProducersInstances(); - - header_->popNamespace().newline(); -} - -void Generator::writeHeaderProducersInterface() { - header_->pushNamespace("details").stream() << "\ -\n\ -struct Identity {\n\ - QString operator()(const QString &value) const {\n\ - return value;\n\ - }\n\ -};\n\ -\n"; - - header_->popNamespace().newline(); - header_->stream() << "\ -struct now_t {\n\ -};\n\ -\n\ -inline constexpr now_t now{};\n\ -\n\ -inline auto to_count() {\n\ - return rpl::map([](auto value) {\n\ - return float64(value);\n\ - });\n\ -}\n\ -\n\ -template \n\ -using S = std::decay_t()(QString()))>;\n\ -\n\ -template \n\ -struct phrase;\n\ -\n"; - std::set producersDeclared; - for (auto &entry : langpack_.entries) { - const auto isPlural = !entry.keyBase.isEmpty(); - const auto &key = entry.key; - auto tags = QStringList(); - auto producerArgs = QStringList(); - auto currentArgs = QStringList(); - auto values = QStringList(); - values.push_back("base"); - values.push_back("std::move(p)"); - for (auto &tagData : entry.tags) { - const auto &tag = tagData.tag; - const auto isPluralTag = isPlural && (tag == kPluralTags[0]); - tags.push_back("lngtag_" + tag); - const auto type1 = "lngtag_" + tag; - const auto arg1 = type1 + (isPluralTag ? " type" : ""); - const auto producerType2 = (isPluralTag ? "rpl::producer " : "rpl::producer> "); - const auto producerArg2 = producerType2 + tag + "__val"; - const auto currentType2 = (isPluralTag ? "float64 " : "const S

&"); - const auto currentArg2 = currentType2 + tag + "__val"; - producerArgs.push_back(arg1 + ", " + producerArg2); - currentArgs.push_back(arg1 + ", " + currentArg2); - if (isPluralTag) { - values.push_back("type"); - } - values.push_back(tag + "__val"); - } - producerArgs.push_back("P p = P()"); - currentArgs.push_back("P p = P()"); - if (!producersDeclared.emplace(tags.join(',')).second) { - continue; - } - header_->stream() << "\ -template <>\n\ -struct phrase<" << tags.join(", ") << "> {\n\ - template \n\ - rpl::producer> operator()(" << producerArgs.join(", ") << ") const {\n\ - return ::Lang::details::Producer<" << tags.join(", ") << ">::template Combine(" << values.join(", ") << ");\n\ - }\n\ -\n\ - template \n\ - S

operator()(now_t, " << currentArgs.join(", ") << ") const {\n\ - return ::Lang::details::Producer<" << tags.join(", ") << ">::template Current(" << values.join(", ") << ");\n\ - }\n\ -\n\ - ushort base;\n\ -};\n\ -\n"; - } -} - -void Generator::writeHeaderProducersInstances() { - auto index = 0; - for (auto &entry : langpack_.entries) { - const auto isPlural = !entry.keyBase.isEmpty(); - const auto &key = entry.key; - auto tags = QStringList(); - for (auto &tagData : entry.tags) { - const auto &tag = tagData.tag; - tags.push_back("lngtag_" + tag); - } - if (!isPlural || key == ComputePluralKey(entry.keyBase, 0)) { - header_->stream() << "\ -inline constexpr phrase<" << tags.join(", ") << "> " << (isPlural ? entry.keyBase : key) << "{ ushort(" << index << ") };\n"; - } - ++index; - } - header_->newline(); -} - -bool Generator::writeSource() { - source_ = std::make_unique(basePath_ + ".cpp", project_); - - source_->include("lang/lang_keys.h").pushNamespace("Lang").pushNamespace(); - - source_->stream() << "\ -QChar DefaultData[] = {"; - auto count = 0; - auto fulllength = 0; - for (auto &entry : langpack_.entries) { - for (auto ch : entry.value) { - if (fulllength > 0) source_->stream() << ","; - if (!count++) { - source_->stream() << "\n"; - } else { - if (count == 12) { - count = 0; - } - source_->stream() << " "; - } - source_->stream() << "0x" << QString::number(ch.unicode(), 16); - ++fulllength; - } - } - source_->stream() << " };\n\ -\n\ -int Offsets[] = {"; - count = 0; - auto offset = 0; - auto writeOffset = [this, &count, &offset] { - if (offset > 0) source_->stream() << ","; - if (!count++) { - source_->stream() << "\n"; - } else { - if (count == 12) { - count = 0; - } - source_->stream() << " "; - } - source_->stream() << offset; - }; - for (auto &entry : langpack_.entries) { - writeOffset(); - offset += entry.value.size(); - } - writeOffset(); - source_->stream() << " };\n"; - source_->popNamespace().stream() << "\ -\n\ -ushort GetTagIndex(QLatin1String tag) {\n\ - auto size = tag.size();\n\ - auto data = tag.data();\n"; - - auto tagsSet = std::set>(); - for (auto &tag : langpack_.tags) { - tagsSet.insert(tag.tag); - } - - writeSetSearch(tagsSet, [](const QString &tag) { - return "ushort(lt_" + tag + ")"; - }, "kTagsCount"); - - source_->stream() << "\ -}\n\ -\n\ -ushort GetKeyIndex(QLatin1String key) {\n\ - auto size = key.size();\n\ - auto data = key.data();\n"; - - auto index = 0; - auto indices = std::map(); - for (auto &entry : langpack_.entries) { - indices.emplace(getFullKey(entry), QString::number(index++)); - } - const auto indexOfKey = [&](const QString &full) { - const auto i = indices.find(full); - if (i == indices.end()) { - return QString(); - } - return i->second; - }; - - auto taggedKeys = std::map(); - auto keysSet = std::set>(); - for (auto &entry : langpack_.entries) { - if (!entry.keyBase.isEmpty()) { - for (auto i = 0; i != kPluralPartCount; ++i) { - auto keyName = entry.keyBase + '#' + kPluralParts[i]; - taggedKeys.emplace(keyName, ComputePluralKey(entry.keyBase, i)); - keysSet.insert(keyName); - } - } else { - auto full = getFullKey(entry); - if (full != entry.key) { - taggedKeys.emplace(entry.key, full); - } - keysSet.insert(entry.key); - } - } - - writeSetSearch(keysSet, [&](const QString &key) { - auto it = taggedKeys.find(key); - const auto name = (it != taggedKeys.end()) ? it->second : key; - return indexOfKey(name); - }, "kKeysCount"); - header_->popNamespace().newline(); - - source_->stream() << "\ -}\n\ -\n\ -bool IsTagReplaced(ushort key, ushort tag) {\n\ - switch (key) {\n"; - - auto lastWrittenPluralEntry = QString(); - for (auto &entry : langpack_.entries) { - if (entry.tags.empty()) { - continue; - } - if (!entry.keyBase.isEmpty()) { - if (entry.keyBase == lastWrittenPluralEntry) { - continue; - } - lastWrittenPluralEntry = entry.keyBase; - for (auto i = 0; i != kPluralPartCount; ++i) { - source_->stream() << "\ - case " << indexOfKey(ComputePluralKey(entry.keyBase, i)) << ":" << ((i + 1 == kPluralPartCount) ? " {" : "") << "\n"; - } - } else { - source_->stream() << "\ - case " << indexOfKey(getFullKey(entry)) << ": {\n"; - } - source_->stream() << "\ - switch (tag) {\n"; - for (auto &tag : entry.tags) { - source_->stream() << "\ - case lt_" << tag.tag << ":\n"; - } - source_->stream() << "\ - return true;\n\ - }\n\ - } break;\n"; - } - - source_->stream() << "\ - }\ -\n\ - return false;\n\ -}\n\ -\n\ -QString GetOriginalValue(ushort key) {\n\ - Expects(key < kKeysCount);\n\ -\n\ - const auto offset = Offsets[key];\n\ - return QString::fromRawData(DefaultData + offset, Offsets[key + 1] - offset);\n\ -}\n\ -\n"; - - return source_->finalize(); -} - -template -void Generator::writeSetSearch(const std::set> &set, ComputeResult computeResult, const QString &invalidResult) { - auto tabs = [](int size) { - return QString(size, '\t'); - }; - - enum class UsedCheckType { - Switch, - If, - UpcomingIf, - }; - auto checkTypes = QVector(); - auto checkLengthHistory = QVector(); - auto chars = QString(); - auto tabsUsed = 1; - - // Returns true if at least one check was finished. - auto finishChecksTillKey = [this, &chars, &checkTypes, &checkLengthHistory, &tabsUsed, tabs](const QString &key) { - auto result = false; - while (!chars.isEmpty() && key.midRef(0, chars.size()) != chars) { - result = true; - - auto wasType = checkTypes.back(); - chars.resize(chars.size() - 1); - checkTypes.pop_back(); - if (wasType == UsedCheckType::Switch || wasType == UsedCheckType::If) { - --tabsUsed; - if (wasType == UsedCheckType::Switch) { - source_->stream() << tabs(tabsUsed) << "break;\n"; - } - if ((!chars.isEmpty() && key.midRef(0, chars.size()) != chars) || key == chars) { - source_->stream() << tabs(tabsUsed) << "}\n"; - checkLengthHistory.pop_back(); - } - } - } - return result; - }; - - // Check if we can use "if" for a check on "charIndex" in "it" (otherwise only "switch") - auto canUseIfForCheck = [](auto it, auto end, int charIndex) { - auto key = *it; - auto i = it; - auto keyStart = key.mid(0, charIndex); - for (++i; i != end; ++i) { - auto nextKey = *i; - if (nextKey.mid(0, charIndex) != keyStart) { - return true; - } else if (nextKey.size() > charIndex && nextKey[charIndex] != key[charIndex]) { - return false; - } - } - return true; - }; - - auto countMinimalLength = [](auto it, auto end, int charIndex) { - auto key = *it; - auto i = it; - auto keyStart = key.mid(0, charIndex); - auto result = key.size(); - for (++i; i != end; ++i) { - auto nextKey = *i; - if (nextKey.mid(0, charIndex) != keyStart) { - break; - } else if (nextKey.size() > charIndex && result > nextKey.size()) { - result = nextKey.size(); - } - } - return result; - }; - - for (auto i = set.begin(), e = set.end(); i != e; ++i) { - // If we use just "auto" here and "name" becomes mutable, - // the operator[] will return QCharRef instead of QChar, - // and "auto ch = name[index]" will behave like "auto &ch =", - // if you assign something to "ch" after that you'll change "name" (!) - const auto name = *i; - - auto weContinueOldSwitch = finishChecksTillKey(name); - while (chars.size() != name.size()) { - auto checking = chars.size(); - auto partialKey = name.mid(0, checking); - - auto keyChar = name[checking]; - auto usedIfForCheckCount = 0; - auto minimalLengthCheck = countMinimalLength(i, e, checking); - for (; checking + usedIfForCheckCount != name.size(); ++usedIfForCheckCount) { - if (!canUseIfForCheck(i, e, checking + usedIfForCheckCount) - || countMinimalLength(i, e, checking + usedIfForCheckCount) != minimalLengthCheck) { - break; - } - } - auto usedIfForCheck = !weContinueOldSwitch && (usedIfForCheckCount > 0); - const auto checkedLength = checkLengthHistory.isEmpty() - ? 0 - : checkLengthHistory.back(); - const auto requiredLength = qMax( - minimalLengthCheck, - checkedLength); - auto checkLengthCondition = QString(); - if (weContinueOldSwitch) { - weContinueOldSwitch = false; - } else { - checkLengthCondition = (requiredLength > checkedLength) ? ("size >= " + QString::number(requiredLength)) : QString(); - if (!usedIfForCheck) { - source_->stream() << tabs(tabsUsed) << (checkLengthCondition.isEmpty() ? QString() : ("if (" + checkLengthCondition + ") ")) << "switch (data[" << checking << "]) {\n"; - checkLengthHistory.push_back(requiredLength); - } - } - if (usedIfForCheck) { - auto conditions = QStringList(); - if (usedIfForCheckCount > 1) { - conditions.push_back("!memcmp(data + " + QString::number(checking) + ", \"" + name.mid(checking, usedIfForCheckCount) + "\", " + QString::number(usedIfForCheckCount) + ")"); - } else { - conditions.push_back("data[" + QString::number(checking) + "] == '" + keyChar + "'"); - } - if (!checkLengthCondition.isEmpty()) { - conditions.push_front(checkLengthCondition); - } - source_->stream() << tabs(tabsUsed) << "if (" << conditions.join(" && ") << ") {\n"; - checkLengthHistory.push_back(requiredLength); - checkTypes.push_back(UsedCheckType::If); - for (auto i = 1; i != usedIfForCheckCount; ++i) { - checkTypes.push_back(UsedCheckType::UpcomingIf); - chars.push_back(keyChar); - keyChar = name[checking + i]; - } - } else { - source_->stream() << tabs(tabsUsed) << "case '" << keyChar << "':\n"; - checkTypes.push_back(UsedCheckType::Switch); - } - ++tabsUsed; - chars.push_back(keyChar); - } - source_->stream() << tabs(tabsUsed) << "return (size == " << chars.size() << ") ? " << computeResult(name) << " : " << invalidResult << ";\n"; - } - finishChecksTillKey(QString()); - - source_->stream() << "\ -\n\ - return " << invalidResult << ";\n"; -} - -QString Generator::getFullKey(const LangPack::Entry &entry) { - if (!entry.keyBase.isEmpty() || entry.tags.empty()) { - return entry.key; - } - return entry.key + "__tagged"; -} - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/generator.h b/Telegram/SourceFiles/codegen/lang/generator.h deleted file mode 100644 index e60e370c2..000000000 --- a/Telegram/SourceFiles/codegen/lang/generator.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "codegen/common/cpp_file.h" -#include "codegen/lang/parsed_file.h" - -namespace codegen { -namespace lang { - -class Generator { -public: - Generator(const LangPack &langpack, const QString &destBasePath, const common::ProjectInfo &project); - Generator(const Generator &other) = delete; - Generator &operator=(const Generator &other) = delete; - - bool writeHeader(); - bool writeSource(); - -private: - void writeHeaderForwardDeclarations(); - void writeHeaderTagTypes(); - void writeHeaderInterface(); - void writeHeaderTagValueLookup(); - void writeHeaderReactiveInterface(); - void writeHeaderProducersInterface(); - void writeHeaderProducersInstances(); - - QString getFullKey(const LangPack::Entry &entry); - - template - void writeSetSearch(const std::set> &set, ComputeResult computeResult, const QString &invalidResult); - - const LangPack &langpack_; - QString basePath_, baseName_; - const common::ProjectInfo &project_; - std::unique_ptr source_, header_; - -}; - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/main.cpp b/Telegram/SourceFiles/codegen/lang/main.cpp deleted file mode 100644 index 4ebdf9a59..000000000 --- a/Telegram/SourceFiles/codegen/lang/main.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include - -#include "codegen/lang/options.h" -#include "codegen/lang/processor.h" - -int main(int argc, char *argv[]) { - QCoreApplication app(argc, argv); - - auto options = codegen::lang::parseOptions(); - if (options.inputPath.isEmpty()) { - return -1; - } - - codegen::lang::Processor processor(options); - return processor.launch(); -} diff --git a/Telegram/SourceFiles/codegen/lang/options.cpp b/Telegram/SourceFiles/codegen/lang/options.cpp deleted file mode 100644 index 0400acdc2..000000000 --- a/Telegram/SourceFiles/codegen/lang/options.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/lang/options.h" - -#include -#include -#include -#include "codegen/common/logging.h" - -namespace codegen { -namespace lang { -namespace { - -constexpr int kErrorOutputPathExpected = 902; -constexpr int kErrorInputPathExpected = 903; -constexpr int kErrorSingleInputPathExpected = 904; -constexpr int kErrorWorkingPathExpected = 905; - -} // namespace - -using common::logError; - -Options parseOptions() { - Options result; - auto args = QCoreApplication::instance()->arguments(); - for (int i = 1, count = args.size(); i < count; ++i) { // skip first - auto &arg = args.at(i); - - // Output path - if (arg == "-o") { - if (++i == count) { - logError(kErrorOutputPathExpected, "Command Line") << "output path expected after -o"; - return Options(); - } else { - result.outputPath = args.at(i); - } - } else if (arg.startsWith("-o")) { - result.outputPath = arg.mid(2); - - // Working path - } else if (arg == "-w") { - if (++i == count) { - logError(kErrorWorkingPathExpected, "Command Line") << "working path expected after -w"; - return Options(); - } else { - common::logSetWorkingPath(args.at(i)); - } - } else if (arg.startsWith("-w")) { - common::logSetWorkingPath(arg.mid(2)); - - // Input path - } else { - if (result.inputPath.isEmpty()) { - result.inputPath = arg; - } else { - logError(kErrorSingleInputPathExpected, "Command Line") << "only one input path expected"; - return Options(); - } - } - } - if (result.inputPath.isEmpty()) { - logError(kErrorInputPathExpected, "Command Line") << "input path expected"; - return Options(); - } - return result; -} - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/options.h b/Telegram/SourceFiles/codegen/lang/options.h deleted file mode 100644 index 8db15ca10..000000000 --- a/Telegram/SourceFiles/codegen/lang/options.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace codegen { -namespace lang { - -struct Options { - QString outputPath = "."; - QString inputPath; -}; - -// Parsing failed if inputPath is empty in the result. -Options parseOptions(); - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/parsed_file.cpp b/Telegram/SourceFiles/codegen/lang/parsed_file.cpp deleted file mode 100644 index 551c55aef..000000000 --- a/Telegram/SourceFiles/codegen/lang/parsed_file.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/lang/parsed_file.h" - -#include -#include -#include -#include -#include -#include "codegen/common/basic_tokenized_file.h" -#include "codegen/common/logging.h" - -namespace codegen { -namespace lang { -namespace { - -using BasicToken = codegen::common::BasicTokenizedFile::Token; -using BasicType = BasicToken::Type; - -constexpr int kErrorBadString = 806; - -bool ValidateAnsiString(const QString &value) { - for (auto ch : value) { - if (ch.unicode() > 127) { - return false; - } - } - return true; -} - -bool ValidateKey(const QString &key) { - static const auto validator = QRegularExpression("^[a-z0-9_.-]+(#(one|other))?$", QRegularExpression::CaseInsensitiveOption); - if (!validator.match(key).hasMatch()) { - return false; - } - if (key.indexOf("__") >= 0) { - return false; - } - return true; -} - -bool ValidateTag(const QString &tag) { - static const auto validator = QRegularExpression("^[a-z0-9_]+$", QRegularExpression::CaseInsensitiveOption); - if (!validator.match(tag).hasMatch()) { - return false; - } - if (tag.indexOf("__") >= 0) { - return false; - } - return true; -} - -QString PrepareCommandString(int index) { - static const QChar TextCommand(0x0010); - static const QChar TextCommandLangTag(0x0020); - auto result = QString(4, TextCommand); - result[1] = TextCommandLangTag; - result[2] = QChar(0x0020 + ushort(index)); - return result; -} - -} // namespace - -const std::array kPluralParts = { { - "zero", - "one", - "two", - "few", - "many", - "other", -} }; - -const std::array kPluralTags = { { - "count", - "count_short", - "count_decimal", -} }; - -QString ComputePluralKey(const QString &base, int index) { - return base + "__plural" + QString::number(index); -} - -ParsedFile::ParsedFile(const Options &options) -: filePath_(options.inputPath) -, file_(filePath_) -, options_(options) { -} - -bool ParsedFile::read() { - if (!file_.read()) { - return false; - } - - do { - if (auto keyToken = file_.getToken(BasicType::String)) { - if (ValidateKey(keyToken.value)) { - if (auto equals = file_.getToken(BasicType::Equals)) { - if (auto valueToken = file_.getToken(BasicType::String)) { - assertNextToken(BasicType::Semicolon); - addEntity(keyToken.value, valueToken.value); - continue; - } else { - logErrorUnexpectedToken() << "string value for '" << keyToken.value.toStdString() << "' key"; - } - } else { - logErrorUnexpectedToken() << "'=' for '" << keyToken.value.toStdString() << "' key"; - } - } else { - logErrorUnexpectedToken() << "string key name (/^[a-z0-9_.-]+(#(one|other))?$/i)"; - } - } - if (file_.atEnd()) { - break; - } - logErrorUnexpectedToken() << "ansi string key name"; - } while (!failed()); - - fillPluralTags(); - - return !failed(); -} - -void ParsedFile::fillPluralTags() { - auto count = result_.entries.size(); - for (auto i = 0; i != count;) { - auto &baseEntry = result_.entries[i]; - if (baseEntry.keyBase.isEmpty()) { - ++i; - continue; - } - logAssert(i + kPluralPartCount < count); - - // Accumulate all tags from all plural variants. - auto tags = std::vector(); - for (auto j = i; j != i + kPluralPartCount; ++j) { - if (tags.empty()) { - tags = result_.entries[j].tags; - } else { - for (auto &tag : result_.entries[j].tags) { - if (std::find(tags.begin(), tags.end(), tag) == tags.end()) { - tags.push_back(tag); - } - } - } - } - logAssert(!tags.empty()); - logAssert(tags.front().tag == kPluralTags[0]); - - // Set this tags list to all plural variants. - for (auto j = i; j != i + kPluralPartCount; ++j) { - result_.entries[j].tags = tags; - } - - i += kPluralPartCount; - } -} - -BasicToken ParsedFile::assertNextToken(BasicToken::Type type) { - auto result = file_.getToken(type); - if (!result) { - logErrorUnexpectedToken() << type; - } - return result; -} - -common::LogStream ParsedFile::logErrorBadString() { - return logError(kErrorBadString); -} - -QString ParsedFile::extractTagsData(const QString &value, LangPack *to) { - auto tagStart = value.indexOf('{'); - if (tagStart < 0) { - return value; - } - - auto tagEnd = 0; - auto finalValue = QString(); - finalValue.reserve(value.size() * 2); - while (tagStart >= 0) { - if (tagStart > tagEnd) { - finalValue.append(value.midRef(tagEnd, tagStart - tagEnd)); - } - ++tagStart; - tagEnd = value.indexOf('}', tagStart); - if (tagEnd < 0) { - logErrorBadString() << "unexpected end of value, end of tag expected."; - return value; - } - finalValue.append(extractTagData(value.mid(tagStart, tagEnd - tagStart), to)); - ++tagEnd; - tagStart = value.indexOf('{', tagEnd); - } - if (tagEnd < value.size()) { - finalValue.append(value.midRef(tagEnd)); - } - return finalValue; -} - -QString ParsedFile::extractTagData(const QString &tagText, LangPack *to) { - auto numericPart = tagText.indexOf(':'); - auto tag = (numericPart > 0) ? tagText.mid(0, numericPart) : tagText; - if (!ValidateTag(tag)) { - logErrorBadString() << "bad tag characters: '" << tagText.toStdString() << "'"; - return QString(); - } - for (auto &previousTag : to->tags) { - if (previousTag.tag == tag) { - logErrorBadString() << "duplicate found for tag '" << tagText.toStdString() << "'"; - return QString(); - } - } - auto index = 0; - auto tagIndex = result_.tags.size(); - for (auto &alreadyTag : result_.tags) { - if (alreadyTag.tag == tag) { - tagIndex = index; - break; - } - ++index; - } - if (tagIndex == result_.tags.size()) { - result_.tags.push_back({ tag }); - } - if (numericPart > 0) { - auto numericParts = tagText.mid(numericPart + 1).split('|'); - if (numericParts.size() != 3) { - logErrorBadString() << "bad option count for plural key part in tag: '" << tagText.toStdString() << "'"; - return QString(); - } - auto index = 0; - for (auto &part : numericParts) { - auto numericPartEntry = LangPack::Entry(); - numericPartEntry.key = tag + QString::number(index++); - if (part.indexOf('#') != part.lastIndexOf('#')) { - logErrorBadString() << "bad option for plural key part in tag: '" << tagText.toStdString() << "', too many '#'."; - return QString(); - } - numericPartEntry.value = part.replace('#', PrepareCommandString(tagIndex)); - to->entries.push_back(numericPartEntry); - } - } - to->tags.push_back({ tag }); - return PrepareCommandString(tagIndex); -} - -void ParsedFile::addEntity(QString key, const QString &value) { - auto pluralPartOffset = key.indexOf('#'); - auto pluralIndex = -1; - if (pluralPartOffset >= 0) { - auto pluralPart = key.mid(pluralPartOffset + 1); - pluralIndex = std::find(kPluralParts.begin(), kPluralParts.end(), pluralPart) - kPluralParts.begin(); - if (pluralIndex < 0 || pluralIndex >= kPluralParts.size()) { - logErrorBadString() << "bad plural part for key '" << key.toStdString() << "': '" << pluralPart.toStdString() << "'"; - return; - } - key = key.mid(0, pluralPartOffset); - } - auto checkKey = [this](const QString &key) { - for (auto &entry : result_.entries) { - if (entry.key == key) { - if (entry.keyBase.isEmpty() || !entry.tags.empty()) { - // Empty tags in plural entry means it was not encountered yet. - logErrorBadString() << "duplicate found for key '" << key.toStdString() << "'"; - return false; - } - } - } - return true; - }; - if (!checkKey(key)) { - return; - } - auto tagsData = LangPack(); - auto entry = LangPack::Entry(); - entry.key = key; - entry.value = extractTagsData(value, &tagsData); - entry.tags = tagsData.tags; - if (pluralIndex >= 0) { - logAssert(tagsData.entries.empty()); - - entry.keyBase = entry.key; - entry.key = ComputePluralKey(entry.keyBase, pluralIndex); - if (!checkKey(entry.key)) { - return; - } - auto baseIndex = -1; - auto alreadyCount = result_.entries.size(); - for (auto i = 0; i != alreadyCount; ++i) { - if (result_.entries[i].keyBase == entry.keyBase) { - // This is not the first appearance of this plural key. - baseIndex = i; - break; - } - } - if (baseIndex < 0) { - baseIndex = result_.entries.size(); - for (auto i = 0; i != kPluralPartCount; ++i) { - auto addingEntry = LangPack::Entry(); - addingEntry.keyBase = entry.keyBase; - addingEntry.key = ComputePluralKey(entry.keyBase, i); - result_.entries.push_back(addingEntry); - } - } - auto entryIndex = baseIndex + pluralIndex; - logAssert(entryIndex < result_.entries.size()); - auto &realEntry = result_.entries[entryIndex]; - logAssert(realEntry.key == entry.key); - realEntry.value = entry.value; - - // Add all new tags to the existing ones. - realEntry.tags = std::vector(1, LangPack::Tag{ kPluralTags[0] }); - - for (auto &tag : entry.tags) { - if (std::find(realEntry.tags.begin(), realEntry.tags.end(), tag) == realEntry.tags.end()) { - realEntry.tags.push_back(tag); - } - } - } else { - result_.entries.push_back(entry); - for (auto &tag : entry.tags) { - const auto plural = std::find(std::begin(kPluralTags), std::end(kPluralTags), tag.tag); - if (plural != std::end(kPluralTags)) { - logErrorBadString() << "plural tag '" << tag.tag.toStdString() << "' used in non-plural key '" << key.toStdString() << "'"; - } - } - for (auto &tagEntry : tagsData.entries) { - auto taggedEntry = LangPack::Entry(); - taggedEntry.key = key + "__" + tagEntry.key; - taggedEntry.value = tagEntry.value; - result_.entries.push_back(taggedEntry); - } - } -} - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/parsed_file.h b/Telegram/SourceFiles/codegen/lang/parsed_file.h deleted file mode 100644 index 948eb247d..000000000 --- a/Telegram/SourceFiles/codegen/lang/parsed_file.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include -#include "codegen/common/basic_tokenized_file.h" -#include "codegen/lang/options.h" - -namespace codegen { -namespace lang { - -constexpr auto kPluralPartCount = 6; -extern const std::array kPluralParts; - -constexpr auto kPluralTagsCount = 3; -extern const std::array kPluralTags; - -QString ComputePluralKey(const QString &base, int index); - -struct LangPack { - struct Tag { - QString tag; - }; - struct Entry { - QString key; - QString value; - QString keyBase; // Empty for not plural entries. - std::vector tags; - }; - std::vector entries; - std::vector tags; - -}; - -inline bool operator==(const LangPack::Tag &a, const LangPack::Tag &b) { - return a.tag == b.tag; -} - -inline bool operator!=(const LangPack::Tag &a, const LangPack::Tag &b) { - return !(a == b); -} - -// Parses an input file to the internal struct. -class ParsedFile { -public: - explicit ParsedFile(const Options &options); - ParsedFile(const ParsedFile &other) = delete; - ParsedFile &operator=(const ParsedFile &other) = delete; - - bool read(); - - LangPack getResult() { - return result_; - } - -private: - bool failed() const { - return failed_ || file_.failed(); - } - - // Log error to std::cerr with 'code' at the current position in file. - common::LogStream logError(int code) { - failed_ = true; - return file_.logError(code); - } - common::LogStream logErrorUnexpectedToken() { - failed_ = true; - return file_.logErrorUnexpectedToken(); - } - common::LogStream logErrorBadString(); - common::LogStream logAssert(bool assertion) { - if (!assertion) { - return logError(common::kErrorInternal) << "internal - "; - } - return common::LogStream(common::LogStream::Null); - } - - // Read next token and fire unexpected token error if it is not of "type". - using BasicToken = common::BasicTokenizedFile::Token; - BasicToken assertNextToken(BasicToken::Type type); - - void addEntity(QString key, const QString &value); - QString extractTagsData(const QString &value, LangPack *to); - QString extractTagData(const QString &tag, LangPack *to); - - void fillPluralTags(); - - QString filePath_; - common::BasicTokenizedFile file_; - Options options_; - bool failed_ = false; - LangPack result_; - -}; - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/processor.cpp b/Telegram/SourceFiles/codegen/lang/processor.cpp deleted file mode 100644 index 6f1d4b2cf..000000000 --- a/Telegram/SourceFiles/codegen/lang/processor.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/lang/processor.h" - -#include -#include -#include "codegen/common/cpp_file.h" -#include "codegen/lang/parsed_file.h" -#include "codegen/lang/generator.h" - -namespace codegen { -namespace lang { -namespace { - -constexpr int kErrorCantWritePath = 821; - -} // namespace - -Processor::Processor(const Options &options) -: parser_(std::make_unique(options)) -, options_(options) { -} - -int Processor::launch() { - if (!parser_->read()) { - return -1; - } - - if (!write(parser_->getResult())) { - return -1; - } - - return 0; -} - -bool Processor::write(const LangPack &langpack) const { - bool forceReGenerate = false; - QDir dir(options_.outputPath); - if (!dir.mkpath(".")) { - common::logError(kErrorCantWritePath, "Command Line") << "can not open path for writing: " << dir.absolutePath().toStdString(); - return false; - } - - QFileInfo srcFile(options_.inputPath); - QString dstFilePath = dir.absolutePath() + "/lang_auto"; - - common::ProjectInfo project = { - "codegen_style", - srcFile.fileName(), - forceReGenerate - }; - - Generator generator(langpack, dstFilePath, project); - if (!generator.writeHeader()) { - return false; - } - if (!generator.writeSource()) { - return false; - } - return true; -} - -Processor::~Processor() = default; - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/lang/processor.h b/Telegram/SourceFiles/codegen/lang/processor.h deleted file mode 100644 index d5a0d6832..000000000 --- a/Telegram/SourceFiles/codegen/lang/processor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "codegen/lang/options.h" - -namespace codegen { -namespace lang { -class ParsedFile; -struct LangPack; - -// Walks through a file, parses it and generates the output. -class Processor { -public: - explicit Processor(const Options &options); - Processor(const Processor &other) = delete; - Processor &operator=(const Processor &other) = delete; - - // Returns 0 on success. - int launch(); - - ~Processor(); - -private: - bool write(const LangPack &langpack) const; - - std::unique_ptr parser_; - const Options &options_; - -}; - -} // namespace lang -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/generator.cpp b/Telegram/SourceFiles/codegen/numbers/generator.cpp deleted file mode 100644 index 052b19d59..000000000 --- a/Telegram/SourceFiles/codegen/numbers/generator.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/numbers/generator.h" - -#include -#include -#include - -namespace codegen { -namespace numbers { -namespace { - -} // namespace - -Generator::Generator(const Rules &rules, const QString &destBasePath, const common::ProjectInfo &project) -: rules_(rules) -, basePath_(destBasePath) -, project_(project) { -} - -bool Generator::writeHeader() { - header_ = std::make_unique(basePath_ + ".h", project_); - - header_->stream() << "QVector phoneNumberParse(const QString &number);\n"; - - return header_->finalize(); -} - -bool Generator::writeSource() { - source_ = std::make_unique(basePath_ + ".cpp", project_); - - source_->stream() << "\ -QVector phoneNumberParse(const QString &number) {\n\ - QVector result;\n\ -\n\ - int32 len = number.size();\n\ - if (len > 0) switch (number.at(0).unicode()) {\n"; - - QString already; - for (auto i = rules_.data.cend(), e = rules_.data.cbegin(); i != e;) { - --i; - QString k = i.key(); - bool onlyLastChanged = true; - while (!already.isEmpty() && (already.size() > k.size() || !already.endsWith(k.at(already.size() - 1)))) { - if (!onlyLastChanged) { - source_->stream() << QString("\t").repeated(1 + already.size()) << "}\n"; - source_->stream() << QString("\t").repeated(already.size()) << "break;\n"; - } - already = already.mid(0, already.size() - 1); - onlyLastChanged = false; - } - if (already == k) { - source_->stream() << QString("\t").repeated(1 + already.size()) << "}\n"; - } else { - bool onlyFirstCheck = true; - while (already.size() < k.size()) { - if (!onlyFirstCheck) source_->stream() << QString("\t").repeated(1 + already.size()) << "if (len > " << already.size() << ") switch (number.at(" << already.size() << ").unicode()) {\n"; - source_->stream() << QString("\t").repeated(1 + already.size()) << "case '" << k.at(already.size()).toLatin1() << "':\n"; - already.push_back(k.at(already.size())); - onlyFirstCheck = false; - } - } - if (i.value().isEmpty()) { - source_->stream() << QString("\t").repeated(1 + already.size()) << "return QVector(1, " << k.size() << ");\n"; - } else { - source_->stream() << QString("\t").repeated(1 + already.size()) << "result.reserve(" << (i.value().size() + 1) << ");\n"; - source_->stream() << QString("\t").repeated(1 + already.size()) << "result.push_back(" << k.size() << ");\n"; - for (int j = 0, l = i.value().size(); j < l; ++j) { - source_->stream() << QString("\t").repeated(1 + already.size()) << "result.push_back(" << i.value().at(j) << ");\n"; - } - source_->stream() << QString("\t").repeated(1 + already.size()) << "return result;\n"; - } - } - bool onlyLastChanged = true; - while (!already.isEmpty()) { - if (!onlyLastChanged) { - source_->stream() << QString("\t").repeated(1 + already.size()) << "}\n"; - } - already = already.mid(0, already.size() - 1); - onlyLastChanged = false; - } - source_->stream() << "\ - }\n\ -\n\ - return result;\n\ -}\n"; - - return source_->finalize(); -} - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/generator.h b/Telegram/SourceFiles/codegen/numbers/generator.h deleted file mode 100644 index f673f1688..000000000 --- a/Telegram/SourceFiles/codegen/numbers/generator.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include "codegen/common/cpp_file.h" -#include "codegen/numbers/parsed_file.h" - -namespace codegen { -namespace numbers { - -class Generator { -public: - Generator(const Rules &rules, const QString &destBasePath, const common::ProjectInfo &project); - Generator(const Generator &other) = delete; - Generator &operator=(const Generator &other) = delete; - - bool writeHeader(); - bool writeSource(); - -private: - const Rules &rules_; - QString basePath_; - const common::ProjectInfo &project_; - std::unique_ptr source_, header_; - -}; - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/main.cpp b/Telegram/SourceFiles/codegen/numbers/main.cpp deleted file mode 100644 index 888c0ec4d..000000000 --- a/Telegram/SourceFiles/codegen/numbers/main.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include - -#include "codegen/numbers/options.h" -#include "codegen/numbers/processor.h" - -int main(int argc, char *argv[]) { - QCoreApplication app(argc, argv); - - auto options = codegen::numbers::parseOptions(); - if (options.inputPath.isEmpty()) { - return -1; - } - - codegen::numbers::Processor processor(options); - return processor.launch(); -} diff --git a/Telegram/SourceFiles/codegen/numbers/options.cpp b/Telegram/SourceFiles/codegen/numbers/options.cpp deleted file mode 100644 index 45d8deb54..000000000 --- a/Telegram/SourceFiles/codegen/numbers/options.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/numbers/options.h" - -#include -#include -#include "codegen/common/logging.h" - -namespace codegen { -namespace numbers { -namespace { - -constexpr int kErrorOutputPathExpected = 902; -constexpr int kErrorInputPathExpected = 903; -constexpr int kErrorSingleInputPathExpected = 904; -constexpr int kErrorWorkingPathExpected = 905; - -} // namespace - -using common::logError; - -Options parseOptions() { - Options result; - auto args = QCoreApplication::instance()->arguments(); - for (auto i = 1, count = args.size(); i < count; ++i) { // skip first - auto &arg = args.at(i); - - // Output path - if (arg == "-o") { - if (++i == count) { - logError(kErrorOutputPathExpected, "Command Line") << "output path expected after -o"; - return Options(); - } else { - result.outputPath = args.at(i); - } - } else if (arg.startsWith("-o")) { - result.outputPath = arg.mid(2); - - // Working path - } else if (arg == "-w") { - if (++i == count) { - logError(kErrorWorkingPathExpected, "Command Line") << "working path expected after -w"; - return Options(); - } else { - common::logSetWorkingPath(args.at(i)); - } - } else if (arg.startsWith("-w")) { - common::logSetWorkingPath(arg.mid(2)); - - // Input path - } else { - if (result.inputPath.isEmpty()) { - result.inputPath = arg; - } else { - logError(kErrorSingleInputPathExpected, "Command Line") << "only one input path expected"; - return Options(); - } - } - } - if (result.inputPath.isEmpty()) { - logError(kErrorInputPathExpected, "Command Line") << "input path expected"; - return Options(); - } - return result; -} - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/options.h b/Telegram/SourceFiles/codegen/numbers/options.h deleted file mode 100644 index 8cd549469..000000000 --- a/Telegram/SourceFiles/codegen/numbers/options.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace codegen { -namespace numbers { - -struct Options { - QString outputPath = "."; - QString inputPath; -}; - -// Parsing failed if inputPath is empty in the result. -Options parseOptions(); - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/parsed_file.cpp b/Telegram/SourceFiles/codegen/numbers/parsed_file.cpp deleted file mode 100644 index a554a9ac7..000000000 --- a/Telegram/SourceFiles/codegen/numbers/parsed_file.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/numbers/parsed_file.h" - -#include -#include -#include -#include -#include "codegen/common/basic_tokenized_file.h" -#include "codegen/common/logging.h" -#include "codegen/common/clean_file_reader.h" -#include "codegen/common/checked_utf8_string.h" - -using BasicToken = codegen::common::BasicTokenizedFile::Token; -using BasicType = BasicToken::Type; - -namespace codegen { -namespace numbers { -namespace { - -QByteArray replaceStrings(const QString &filepath) { - common::CleanFileReader reader(filepath); - if (!reader.read()) { - return QByteArray(); - } - common::CheckedUtf8String string(reader.currentPtr(), reader.charsLeft()); - if (!string.isValid()) { - return QByteArray(); - } - - QStringList lines = string.toString().split('\n'); - for (auto &line : lines) { - auto match = QRegularExpression("^(\\d+;[A-Z]+;)([^;]+)(;.*)?$").match(line); - if (match.hasMatch()) { - line = match.captured(1) + '"' + match.captured(2) + '"' + match.captured(3); - } - } - return lines.join('\n').toUtf8(); -} - -} // namespace - -ParsedFile::ParsedFile(const Options &options) -: content_(replaceStrings(options.inputPath)) -, file_(content_, options.inputPath) -, options_(options) { -} - -bool ParsedFile::read() { - if (content_.isEmpty() || !file_.read()) { - return false; - } - - auto filepath = QFileInfo(options_.inputPath).absoluteFilePath(); - do { - if (auto code = file_.getToken(BasicType::Int)) { - if (!file_.getToken(BasicType::Semicolon)) { - logErrorUnexpectedToken() << "';'"; - return false; - } - if (!file_.getToken(BasicType::Name)) { - logErrorUnexpectedToken() << "country code"; - return false; - } - if (!file_.getToken(BasicType::Semicolon)) { - logErrorUnexpectedToken() << "';'"; - return false; - } - if (!file_.getToken(BasicType::String)) { - logErrorUnexpectedToken() << "country name"; - return false; - } - if (file_.getToken(BasicType::Semicolon)) { - if (auto firstPart = file_.getToken(BasicType::Int)) { - if (firstPart.original.toByteArray() != code.original.toByteArray()) { - file_.putBack(); - result_.data.insert(code.original.toStringUnchecked(), Rule()); - continue; - } - - Rule rule; - while (auto part = file_.getToken(BasicType::Name)) { - rule.push_back(part.original.size()); - } - result_.data.insert(code.original.toStringUnchecked(), rule); - if (rule.isEmpty()) { - logErrorUnexpectedToken() << "bad phone pattern"; - return false; - } - - if (!file_.getToken(BasicType::Semicolon)) { - logErrorUnexpectedToken() << "';'"; - return false; - } - if (!file_.getToken(BasicType::Int)) { - logErrorUnexpectedToken() << "country phone len"; - return false; - } - file_.getToken(BasicType::Semicolon); - continue; - } else { - logErrorUnexpectedToken() << "country phone pattern"; - return false; - } - } else if (file_.getToken(BasicType::Int)) { - file_.putBack(); - result_.data.insert(code.original.toStringUnchecked(), Rule()); - continue; - } else { - logErrorUnexpectedToken() << "country phone pattern"; - return false; - } - } - if (file_.atEnd()) { - break; - } - logErrorUnexpectedToken() << "numbers rule"; - } while (!failed()); - - if (failed()) { - result_.data.clear(); - } - return !failed(); -} - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/parsed_file.h b/Telegram/SourceFiles/codegen/numbers/parsed_file.h deleted file mode 100644 index dc2212899..000000000 --- a/Telegram/SourceFiles/codegen/numbers/parsed_file.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "codegen/common/basic_tokenized_file.h" -#include "codegen/numbers/options.h" - -namespace codegen { -namespace numbers { - -using Rule = QVector; -struct Rules { - QMap data; -}; - -// Parses an input file to the internal struct. -class ParsedFile { -public: - explicit ParsedFile(const Options &options); - ParsedFile(const ParsedFile &other) = delete; - ParsedFile &operator=(const ParsedFile &other) = delete; - - bool read(); - - Rules getResult() { - return result_; - } - -private: - - bool failed() const { - return failed_ || file_.failed(); - } - - // Log error to std::cerr with 'code' at the current position in file. - common::LogStream logError(int code) { - failed_ = true; - return file_.logError(code); - } - common::LogStream logErrorUnexpectedToken() { - failed_ = true; - return file_.logErrorUnexpectedToken(); - } - - QByteArray content_; - common::BasicTokenizedFile file_; - Options options_; - bool failed_ = false; - Rules result_; - -}; - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/processor.cpp b/Telegram/SourceFiles/codegen/numbers/processor.cpp deleted file mode 100644 index 4859ed701..000000000 --- a/Telegram/SourceFiles/codegen/numbers/processor.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/numbers/processor.h" - -#include -#include -#include "codegen/common/cpp_file.h" -#include "codegen/numbers/parsed_file.h" -#include "codegen/numbers/generator.h" - -namespace codegen { -namespace numbers { -namespace { - -constexpr int kErrorCantWritePath = 851; - -} // namespace - -Processor::Processor(const Options &options) -: parser_(std::make_unique(options)) -, options_(options) { -} - -int Processor::launch() { - if (!parser_->read()) { - return -1; - } - - auto result = parser_->getResult(); - if (!write(result)) { - return -1; - } - - return 0; -} - -bool Processor::write(const Rules &rules) const { - QDir dir(options_.outputPath); - if (!dir.mkpath(".")) { - common::logError(kErrorCantWritePath, "Command Line") << "can not open path for writing: " << dir.absolutePath().toStdString(); - return false; - } - - QFileInfo srcFile(options_.inputPath); - QString dstFilePath = dir.absolutePath() + "/numbers"; - - common::ProjectInfo project = { - "codegen_style", - srcFile.fileName(), - false, // forceReGenerate - }; - - Generator generator(rules, dstFilePath, project); - if (!generator.writeHeader()) { - return false; - } - if (!generator.writeSource()) { - return false; - } - - return true; -} - -Processor::~Processor() = default; - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/numbers/processor.h b/Telegram/SourceFiles/codegen/numbers/processor.h deleted file mode 100644 index 762185f62..000000000 --- a/Telegram/SourceFiles/codegen/numbers/processor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "codegen/numbers/options.h" - -namespace codegen { -namespace numbers { -class ParsedFile; -struct Rules; - -// Walks through a file, parses it and generates number formatter. -class Processor { -public: - explicit Processor(const Options &options); - Processor(const Processor &other) = delete; - Processor &operator=(const Processor &other) = delete; - - // Returns 0 on success. - int launch(); - - ~Processor(); - -private: - bool write(const Rules &rules) const; - - std::unique_ptr parser_; - const Options &options_; - -}; - -} // namespace numbers -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py index 4159cdbaf..08e546979 100644 --- a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py +++ b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py @@ -7,1155 +7,88 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL ''' import glob, re, binascii, os, sys -input_files = [] -output_path = '' -next_output_path = False -for arg in sys.argv[1:]: - if next_output_path: - next_output_path = False - output_path = arg - elif arg == '-o': - next_output_path = True - elif re.match(r'^-o(.+)', arg): - output_path = arg[2:] - else: - input_files.append(arg) - -if len(input_files) == 0: - print('Input file required.') - sys.exit(1) -if output_path == '': - print('Output path required.') - sys.exit(1) - -output_header = output_path + '/scheme.h' -output_source = output_path + '/scheme.cpp' - -# define some checked flag conversions -# the key flag type should be a subset of the value flag type -# with exact the same names, then the key flag can be implicitly -# casted to the value flag type -parentFlags = {}; -parentFlagsList = []; -def addChildParentFlags(child, parent): - parentFlagsList.append(child); - parentFlags[child] = parent; -addChildParentFlags('MTPDmessageService', 'MTPDmessage'); -addChildParentFlags('MTPDupdateShortMessage', 'MTPDmessage'); -addChildParentFlags('MTPDupdateShortChatMessage', 'MTPDmessage'); -addChildParentFlags('MTPDupdateShortSentMessage', 'MTPDmessage'); -addChildParentFlags('MTPDreplyKeyboardHide', 'MTPDreplyKeyboardMarkup'); -addChildParentFlags('MTPDreplyKeyboardForceReply', 'MTPDreplyKeyboardMarkup'); -addChildParentFlags('MTPDinputPeerNotifySettings', 'MTPDpeerNotifySettings'); -addChildParentFlags('MTPDpeerNotifySettings', 'MTPDinputPeerNotifySettings'); -addChildParentFlags('MTPDchannelForbidden', 'MTPDchannel'); -addChildParentFlags('MTPDdialogFolder', 'MTPDdialog'); - -# this is a map (key flags -> map (flag name -> flag bit)) -# each key flag of parentFlags should be a subset of the value flag here -parentFlagsCheck = {}; - -countedTypeIdExceptions = {}; -countedTypeIdExceptions['channel#c88974ac'] = True -countedTypeIdExceptions['ipPortSecret#37982646'] = True -countedTypeIdExceptions['accessPointRule#4679b65f'] = True -countedTypeIdExceptions['help.configSimple#5a592a6c'] = True - -renamedTypes = {}; -renamedTypes['passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow'] = 'passwordKdfAlgoModPow'; - -lines = []; -layer = ''; -layerIndex = 0; -funcs = 0 -types = 0; -consts = 0 -funcsNow = 0 -enums = []; -funcsDict = {}; -funcsList = []; -typesDict = {}; -TypesDict = {}; -typesList = []; -boxed = {}; -funcsText = ''; -typesText = ''; -dataTexts = ''; -creatorProxyText = ''; -factories = ''; -flagOperators = ''; -methods = ''; -inlineMethods = ''; -visitorMethods = ''; -textSerializeInit = ''; -textSerializeMethods = ''; -forwards = ''; -forwTypedefs = ''; - -for input_file in input_files: - lines.append('---types---') - with open(input_file) as f: - for line in f: - layerline = re.match(r'// LAYER (\d+)', line) - if (layerline): - layerIndex = int(layerline.group(1)); - layer = 'inline constexpr mtpPrime CurrentLayer = mtpPrime(' + str(layerIndex) + ');'; - else: - lines.append(line); - -for line in lines: - nocomment = re.match(r'^(.*?)//', line) - if (nocomment): - line = nocomment.group(1); - if (re.match(r'\-\-\-functions\-\-\-', line)): - funcsNow = 1; - continue; - if (re.match(r'\-\-\-types\-\-\-', line)): - funcsNow = 0; - continue; - if (re.match(r'^\s*$', line)): - continue; - - nametype = re.match(r'([a-zA-Z\.0-9_]+)(#[0-9a-f]+)?([^=]*)=\s*([a-zA-Z\.<>0-9_]+);', line); - if (not nametype): - if (not re.match(r'vector#1cb5c415 \{t:Type\} # \[ t \] = Vector t;', line)): - print('Bad line found: ' + line); - sys.exit(1); - continue; - - originalname = nametype.group(1); - name = originalname; - if (name in renamedTypes): - name = renamedTypes[name]; - nameInd = name.find('.'); - if (nameInd >= 0): - Name = name[0:nameInd] + '_' + name[nameInd + 1:nameInd + 2].upper() + name[nameInd + 2:]; - name = name.replace('.', '_'); - else: - Name = name[0:1].upper() + name[1:]; - typeid = nametype.group(2); - if (typeid and len(typeid) > 0): - typeid = typeid[1:]; # Skip '#' - while (typeid and len(typeid) > 0 and typeid[0] == '0'): - typeid = typeid[1:]; - - cleanline = nametype.group(1) + nametype.group(3) + '= ' + nametype.group(4); - cleanline = re.sub(r' [a-zA-Z0-9_]+\:flags\.[0-9]+\?true', '', cleanline); - cleanline = cleanline.replace('<', ' ').replace('>', ' ').replace(' ', ' '); - cleanline = re.sub(r'^ ', '', cleanline); - cleanline = re.sub(r' $', '', cleanline); - cleanline = cleanline.replace(':bytes ', ':string '); - cleanline = cleanline.replace('?bytes ', '?string '); - cleanline = cleanline.replace('{', ''); - cleanline = cleanline.replace('}', ''); - countTypeId = binascii.crc32(binascii.a2b_qp(cleanline)); - if (countTypeId < 0): - countTypeId += 2 ** 32; - countTypeId = re.sub(r'^0x|L$', '', hex(countTypeId)); - if (typeid and len(typeid) > 0): - typeid = typeid; - if (typeid != countTypeId): - key = originalname + '#' + typeid; - if (not key in countedTypeIdExceptions): - print('Warning: counted ' + countTypeId + ' mismatch with provided ' + typeid + ' (' + key + ', ' + cleanline + ')'); - continue; - else: - typeid = countTypeId; - - typeid = '0x' + typeid; - - params = nametype.group(3); - restype = nametype.group(4); - if (restype.find('<') >= 0): - templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', restype); - if (templ): - vectemplate = templ.group(2); - if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)): - restype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'): - restype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - else: - foundmeta = ''; - for metatype in typesDict: - for typedata in typesDict[metatype]: - if (typedata[0] == vectemplate): - foundmeta = metatype; - break; - if (len(foundmeta) > 0): - break; - if (len(foundmeta) > 0): - ptype = templ.group(1) + 'MTP' + foundmeta.replace('.', '_') + '>'; - else: - print('Bad vector param: ' + vectemplate); - sys.exit(1); - else: - print('Bad template type: ' + restype); - sys.exit(1); - resType = restype.replace('.', '_'); - if (restype.find('.') >= 0): - parts = re.match(r'([a-z]+)\.([A-Z][A-Za-z0-9<>\._]+)', restype) - if (parts): - restype = parts.group(1) + '_' + parts.group(2)[0:1].lower() + parts.group(2)[1:]; - else: - print('Bad result type name with dot: ' + restype); - sys.exit(1); - else: - if (re.match(r'^[A-Z]', restype)): - restype = restype[:1].lower() + restype[1:]; - else: - print('Bad result type name: ' + restype); - sys.exit(1); - - boxed[resType] = restype; - boxed[Name] = name; - - enums.append('\tmtpc_' + name + ' = ' + typeid); - - paramsList = params.strip().split(' '); - prms = {}; - conditions = {}; - trivialConditions = {}; # true type - prmsList = []; - conditionsList = []; - isTemplate = hasFlags = hasTemplate = ''; - for param in paramsList: - if (re.match(r'^\s*$', param)): - continue; - templ = re.match(r'^{([A-Za-z]+):Type}$', param); - if (templ): - hasTemplate = templ.group(1); - continue; - pnametype = re.match(r'([a-zA-Z_][a-zA-Z0-9_]*):([A-Za-z0-9<>\._]+|![a-zA-Z]+|\#|[a-z_][a-z0-9_]*\.[0-9]+\?[A-Za-z0-9<>\._]+)$', param); - if (not pnametype): - print('Bad param found: "' + param + '" in line: ' + line); - sys.exit(1); - pname = pnametype.group(1); - ptypewide = pnametype.group(2); - if (re.match(r'^!([a-zA-Z]+)$', ptypewide)): - if ('!' + hasTemplate == ptypewide): - isTemplate = pname; - ptype = 'TQueryType'; - else: - print('Bad template param name: "' + param + '" in line: ' + line); - sys.exit(1); - elif (ptypewide == '#'): - hasFlags = pname; - if funcsNow: - ptype = 'flags'; - else: - ptype = 'flags'; - else: - ptype = ptypewide; - if (ptype.find('?') >= 0): - pmasktype = re.match(r'([a-z_][a-z0-9_]*)\.([0-9]+)\?([A-Za-z0-9<>\._]+)', ptype); - if (not pmasktype or pmasktype.group(1) != hasFlags): - print('Bad param found: "' + param + '" in line: ' + line); - sys.exit(1); - ptype = pmasktype.group(3); - if (ptype.find('<') >= 0): - templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype); - if (templ): - vectemplate = templ.group(2); - if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - else: - foundmeta = ''; - for metatype in typesDict: - for typedata in typesDict[metatype]: - if (typedata[0] == vectemplate): - foundmeta = metatype; - break; - if (len(foundmeta) > 0): - break; - if (len(foundmeta) > 0): - ptype = templ.group(1) + 'MTP' + foundmeta.replace('.', '_') + '>'; - else: - print('Bad vector param: ' + vectemplate); - sys.exit(1); - else: - print('Bad template type: ' + ptype); - sys.exit(1); - if (not pname in conditions): - conditionsList.append(pname); - conditions[pname] = pmasktype.group(2); - if (ptype == 'true'): - trivialConditions[pname] = 1; - elif (ptype.find('<') >= 0): - templ = re.match(r'^([vV]ector<)([A-Za-z0-9\._]+)>$', ptype); - if (templ): - vectemplate = templ.group(2); - if (re.match(r'^[A-Z]', vectemplate) or re.match(r'^[a-zA-Z0-9]+\.[A-Z]', vectemplate)): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - elif (vectemplate == 'int' or vectemplate == 'long' or vectemplate == 'string' or vectemplate == 'bytes'): - ptype = templ.group(1) + 'MTP' + vectemplate.replace('.', '_') + '>'; - else: - foundmeta = ''; - for metatype in typesDict: - for typedata in typesDict[metatype]: - if (typedata[0] == vectemplate): - foundmeta = metatype; - break; - if (len(foundmeta) > 0): - break; - if (len(foundmeta) > 0): - ptype = templ.group(1) + 'MTP' + foundmeta.replace('.', '_') + '>'; - else: - print('Bad vector param: ' + vectemplate); - sys.exit(1); - else: - print('Bad template type: ' + ptype); - sys.exit(1); - prmsList.append(pname); - prms[pname] = ptype.replace('.', '_'); - - if (isTemplate == '' and resType == 'X'): - print('Bad response type "X" in "' + name +'" in line: ' + line); - sys.exit(1); - - if funcsNow: - methodBodies = '' - if (isTemplate != ''): - funcsText += '\ntemplate '; - funcsText += '\nclass MTP' + name + ' { // RPC method \'' + nametype.group(1) + '\'\n'; # class - - funcsText += 'public:\n'; - - prmsStr = []; - prmsInit = []; - prmsNames = []; - if (hasFlags != ''): - funcsText += '\tenum class Flag : uint32 {\n'; - maxbit = 0; - parentFlagsCheck['MTP' + name] = {}; - for paramName in conditionsList: - funcsText += '\t\tf_' + paramName + ' = (1U << ' + conditions[paramName] + '),\n'; - parentFlagsCheck['MTP' + name][paramName] = conditions[paramName]; - maxbit = max(maxbit, int(conditions[paramName])); - if (maxbit > 0): - funcsText += '\n'; - funcsText += '\t\tMAX_FIELD = (1U << ' + str(maxbit) + '),\n'; - funcsText += '\t};\n'; - funcsText += '\tusing Flags = base::flags;\n'; - funcsText += '\tfriend inline constexpr bool is_flag_type(Flag) { return true; };\n'; - funcsText += '\n'; - - if (len(prms) > len(trivialConditions)): - for paramName in prmsList: - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - prmsInit.append('_' + paramName + '(' + paramName + '_)'); - prmsNames.append(paramName + '_'); - if (paramName == isTemplate): - ptypeFull = paramType; - else: - ptypeFull = 'MTP' + paramType; - if (paramType in ['int', 'Int', 'bool', 'Bool', 'flags']): - prmsStr.append(ptypeFull + ' ' + paramName + '_'); - else: - prmsStr.append('const ' + ptypeFull + ' &' + paramName + '_'); - - funcsText += '\tMTP' + name + '();\n';# = default; # constructor - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'MTP' + name + '::MTP' + name + '() = default;\n'; - else: - methodBodies += 'MTP' + name + '::MTP' + name + '() = default;\n'; - if (len(prms) > len(trivialConditions)): - funcsText += '\tMTP' + name + '(' + ', '.join(prmsStr) + ');\n'; - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'MTP' + name + '::MTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n'; - else: - methodBodies += 'MTP' + name + '::MTP' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n'; - - funcsText += '\n'; - funcsText += '\tuint32 innerLength() const;\n'; # count size - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'uint32 MTP' + name + '::innerLength() const {\n'; - else: - methodBodies += 'uint32 MTP' + name + '::innerLength() const {\n'; - size = []; - for k in prmsList: - v = prms[k]; - if (k in conditionsList): - if (not k in trivialConditions): - size.append('((_' + hasFlags + '.v & Flag::f_' + k + ') ? _' + k + '.innerLength() : 0)'); - else: - size.append('_' + k + '.innerLength()'); - if (not len(size)): - size.append('0'); - methodBodies += '\treturn ' + ' + '.join(size) + ';\n'; - methodBodies += '}\n'; - - funcsText += '\tmtpTypeId type() const {\n\t\treturn mtpc_' + name + ';\n\t}\n'; # type id - - funcsText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_' + name + ');\n'; # read method - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'bool MTP' + name + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n'; - else: - methodBodies += 'bool MTP' + name + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n'; - readFunc = '' - for k in prmsList: - v = prms[k]; - if (k in conditionsList): - if (not k in trivialConditions): - readFunc += '\t\t&& ((_' + hasFlags + '.v & Flag::f_' + k + ') ? _' + k + '.read(from, end) : ((_' + k + ' = MTP' + v + '()), true))\n'; - else: - readFunc += '\t\t&& _' + k + '.read(from, end)\n'; - if readFunc != '': - methodBodies += '\treturn' + readFunc[4:len(readFunc)-1] + ';\n'; - else: - methodBodies += '\treturn true;\n'; - methodBodies += '}\n'; - - funcsText += '\tvoid write(mtpBuffer &to) const;\n'; # write method - if (isTemplate != ''): - methodBodies += 'template \n' - methodBodies += 'void MTP' + name + '::write(mtpBuffer &to) const {\n'; - else: - methodBodies += 'void MTP' + name + '::write(mtpBuffer &to) const {\n'; - for k in prmsList: - v = prms[k]; - if (k in conditionsList): - if (not k in trivialConditions): - methodBodies += '\tif (_' + hasFlags + '.v & Flag::f_' + k + ') _' + k + '.write(to);\n'; - else: - methodBodies += '\t_' + k + '.write(to);\n'; - methodBodies += '}\n'; - - if (isTemplate != ''): - funcsText += '\n\tusing ResponseType = typename TQueryType::ResponseType;\n\n'; - inlineMethods += methodBodies; - else: - funcsText += '\n\tusing ResponseType = MTP' + resType + ';\n\n'; # method return type - methods += methodBodies; - - if (len(prms) > len(trivialConditions)): - funcsText += 'private:\n'; - for paramName in prmsList: - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - if (paramName == isTemplate): - ptypeFull = paramType; - else: - ptypeFull = 'MTP' + paramType; - funcsText += '\t' + ptypeFull + ' _' + paramName + ';\n'; - funcsText += '\n'; - - funcsText += '};\n'; # class ending - if (isTemplate != ''): - funcsText += 'template \n'; - funcsText += 'using MTP' + Name + ' = MTPBoxed>;\n'; - else: - funcsText += 'using MTP' + Name + ' = MTPBoxed;\n'; - funcs = funcs + 1; - - if (not restype in funcsDict): - funcsList.append(restype); - funcsDict[restype] = []; -# TypesDict[restype] = resType; - funcsDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions, isTemplate]); - else: - if (isTemplate != ''): - print('Template types not allowed: "' + resType + '" in line: ' + line); - continue; - if (not restype in typesDict): - typesList.append(restype); - typesDict[restype] = []; - TypesDict[restype] = resType; - typesDict[restype].append([name, typeid, prmsList, prms, hasFlags, conditionsList, conditions, trivialConditions, isTemplate]); - - consts = consts + 1; - -# text serialization: types and funcs -def addTextSerialize(lst, dct, dataLetter): - result = ''; - for restype in lst: - v = dct[restype]; - for data in v: - name = data[0]; - prmsList = data[2]; - prms = data[3]; - hasFlags = data[4]; - conditionsList = data[5]; - conditions = data[6]; - trivialConditions = data[7]; - isTemplate = data[8]; - - templateArgument = '' - if (isTemplate != ''): - templateArgument = '' - - result += 'bool Serialize_' + name + '(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n'; - if (len(conditions)): - result += '\tauto flag = MTP' + dataLetter + name + templateArgument + '::Flags::from_raw(iflag);\n\n'; - if (len(prms)): - result += '\tif (stage) {\n'; - result += '\t\tto.add(",\\n").addSpaces(lev);\n'; - result += '\t} else {\n'; - result += '\t\tto.add("{ ' + name + '");\n'; - result += '\t\tto.add("\\n").addSpaces(lev);\n'; - result += '\t}\n'; - result += '\tswitch (stage) {\n'; - stage = 0; - for k in prmsList: - v = prms[k]; - result += '\tcase ' + str(stage) + ': to.add(" ' + k + ': "); ++stages.back(); '; - if (k == hasFlags): - result += 'if (start >= end) return false; else flags.back() = *start; '; - if (k in trivialConditions): - result += 'if (flag & MTP' + dataLetter + name + templateArgument + '::Flag::f_' + k + ') { '; - result += 'to.add("YES [ BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); '; - result += '} else { to.add("[ SKIPPED BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); } '; - else: - if (k in conditions): - result += 'if (flag & MTP' + dataLetter + name + templateArgument + '::Flag::f_' + k + ') { '; - result += 'types.push_back('; - vtypeget = re.match(r'^[Vv]ector', v); - if (vtypeget): - if (not re.match(r'^[A-Z]', v)): - result += 'mtpc_vector'; - else: - result += '0'; - restype = vtypeget.group(1); - try: - if boxed[restype]: - restype = 0; - except KeyError: - if re.match(r'^[A-Z]', restype): - restype = 0; - else: - restype = v; - try: - if boxed[restype]: - restype = 0; - except KeyError: - if re.match(r'^[A-Z]', restype): - restype = 0; - if (restype): - try: - conses = typesDict[restype]; - if (len(conses) > 1): - print('Complex bare type found: "' + restype + '" trying to serialize "' + k + '" of type "' + v + '"'); - continue; - if (vtypeget): - result += '); vtypes.push_back('; - result += 'mtpc_' + conses[0][0]; - if (not vtypeget): - result += '); vtypes.push_back(0'; - except KeyError: - if (vtypeget): - result += '); vtypes.push_back('; - if (re.match(r'^flags<', restype)): - result += 'mtpc_flags'; - else: - result += 'mtpc_' + restype + '+0'; - if (not vtypeget): - result += '); vtypes.push_back(0'; - else: - if (not vtypeget): - result += '0'; - result += '); vtypes.push_back(0'; - result += '); stages.push_back(0); flags.push_back(0); '; - if (k in conditions): - result += '} else { to.add("[ SKIPPED BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); } '; - result += 'break;\n'; - stage = stage + 1; - result += '\tdefault: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n'; - result += '\t}\n'; - else: - result += '\tto.add("{ ' + name + ' }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();\n'; - result += '\treturn true;\n'; - result += '}\n\n'; - return result; - -# text serialization: types and funcs -def addTextSerializeInit(lst, dct): - result = ''; - for restype in lst: - v = dct[restype]; - for data in v: - name = data[0]; - result += '\tresult.insert(mtpc_' + name + ', Serialize_' + name + ');\n'; - return result; - -textSerializeMethods += addTextSerialize(typesList, typesDict, 'D'); -textSerializeInit += addTextSerializeInit(typesList, typesDict) + '\n'; -textSerializeMethods += addTextSerialize(funcsList, funcsDict, ''); -textSerializeInit += addTextSerializeInit(funcsList, funcsDict) + '\n'; - -for restype in typesList: - v = typesDict[restype]; - resType = TypesDict[restype]; - withData = 0; - creatorsDeclarations = ''; - creatorsBodies = ''; - flagDeclarations = ''; - constructsText = ''; - constructsBodies = ''; - - forwards += 'class MTP' + restype + ';\n'; - forwTypedefs += 'using MTP' + resType + ' = MTPBoxed;\n'; - - withType = (len(v) > 1); - switchLines = ''; - friendDecl = ''; - getters = ''; - visitor = ''; - reader = ''; - writer = ''; - sizeList = []; - sizeFast = ''; - newFast = ''; - sizeCases = ''; - for data in v: - name = data[0]; - typeid = data[1]; - prmsList = data[2]; - prms = data[3]; - hasFlags = data[4]; - conditionsList = data[5]; - conditions = data[6]; - trivialConditions = data[7]; - - dataText = ''; - if (len(prms) > len(trivialConditions)): - withData = 1; - dataText += '\nclass MTPD' + name + ' : public MTP::internal::TypeData {\n'; # data class - else: - dataText += '\nclass MTPD' + name + ' {\n'; # empty data class for visitors - dataText += 'public:\n'; - dataText += '\ttemplate \n'; - dataText += '\tstatic constexpr bool Is() { return std::is_same_v, MTPD' + name + '>; };\n\n'; - sizeList = []; - creatorParams = []; - creatorParamsList = []; - readText = ''; - writeText = ''; - - if (hasFlags != ''): - dataText += '\tenum class Flag : uint32 {\n'; - maxbit = 0; - parentFlagsCheck['MTPD' + name] = {}; - for paramName in conditionsList: - dataText += '\t\tf_' + paramName + ' = (1U << ' + conditions[paramName] + '),\n'; - parentFlagsCheck['MTPD' + name][paramName] = conditions[paramName]; - maxbit = max(maxbit, int(conditions[paramName])); - if (maxbit > 0): - dataText += '\n'; - dataText += '\t\tMAX_FIELD = (1U << ' + str(maxbit) + '),\n'; - dataText += '\t};\n'; - dataText += '\tusing Flags = base::flags;\n'; - dataText += '\tfriend inline constexpr bool is_flag_type(Flag) { return true; };\n'; - dataText += '\n'; - if (len(conditions)): - for paramName in conditionsList: - if (paramName in trivialConditions): - dataText += '\t[[nodiscard]] bool is_' + paramName + '() const;\n'; - constructsBodies += 'bool MTPD' + name + '::is_' + paramName + '() const {\n'; - constructsBodies += '\treturn _' + hasFlags + '.v & Flag::f_' + paramName + ';\n'; - constructsBodies += '}\n'; - dataText += '\n'; - - switchLines += '\tcase mtpc_' + name + ': '; # for by-type-id type constructor - getters += '\t[[nodiscard]] const MTPD' + name + ' &c_' + name + '() const;\n'; # const getter - visitor += '\tcase mtpc_' + name + ': return base::match_method(c_' + name + '(), std::forward(method), std::forward(methods)...);\n'; - - forwards += 'class MTPD' + name + ';\n'; # data class forward declaration - if (len(prms) > len(trivialConditions)): - dataText += '\tMTPD' + name + '();\n'; # default constructor - switchLines += 'setData(new MTPD' + name + '()); '; - - constructsBodies += 'MTPD' + name + '::MTPD' + name + '() = default;\n'; - constructsBodies += 'const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n'; - if (withType): - constructsBodies += '\tExpects(_type == mtpc_' + name + ');\n\n'; - constructsBodies += '\treturn queryData();\n'; - constructsBodies += '}\n'; - - constructsText += '\texplicit MTP' + restype + '(const MTPD' + name + ' *data);\n'; # by-data type constructor - constructsBodies += 'MTP' + restype + '::MTP' + restype + '(const MTPD' + name + ' *data) : TypeDataOwner(data)'; - if (withType): - constructsBodies += ', _type(mtpc_' + name + ')'; - constructsBodies += ' {\n}\n'; - - dataText += '\tMTPD' + name + '('; # params constructor - prmsStr = []; - prmsInit = []; - for paramName in prmsList: - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - - if (paramType in ['int', 'Int', 'bool', 'Bool']): - prmsStr.append('MTP' + paramType + ' ' + paramName + '_'); - creatorParams.append('MTP' + paramType + ' ' + paramName + '_'); - else: - prmsStr.append('const MTP' + paramType + ' &' + paramName + '_'); - creatorParams.append('const MTP' + paramType + ' &' + paramName + '_'); - creatorParamsList.append(paramName + '_'); - prmsInit.append('_' + paramName + '(' + paramName + '_)'); - if (paramName in conditions): - readText += '\t\t&& (v' + paramName + '() ? _' + paramName + '.read(from, end) : ((_' + paramName + ' = MTP' + paramType + '()), true))\n'; - writeText += '\t\tif (const auto v' + paramName + ' = v.v' + paramName + '()) v' + paramName + '->write(to);\n'; - sizeList.append('(v.v' + paramName + '() ? v.v' + paramName + '()->innerLength() : 0)'); - else: - readText += '\t\t&& _' + paramName + '.read(from, end)\n'; - writeText += '\t\tv.v' + paramName + '().write(to);\n'; - sizeList.append('v.v' + paramName + '().innerLength()'); - - dataText += ', '.join(prmsStr) + ');\n'; - - constructsBodies += 'MTPD' + name + '::MTPD' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n'; - - dataText += '\n'; - dataText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end);\n'; - dataText += '\n'; - - constructsBodies += 'bool MTPD' + name + '::read(const mtpPrime *&from, const mtpPrime *end) {\n'; - if readText != '': - constructsBodies += '\treturn' + readText[4:len(readText)-1] + ';\n'; - else: - constructsBodies += '\treturn true;\n'; - constructsBodies += '}\n'; - - if len(prmsList) > 0: - for paramName in prmsList: # getters - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - if (paramName in conditions): - dataText += '\t[[nodiscard]] MTP::conditional v' + paramName + '() const;\n'; - constructsBodies += 'MTP::conditional MTPD' + name + '::v' + paramName + '() const {\n'; - constructsBodies += '\treturn (_' + hasFlags + '.v & Flag::f_' + paramName + ') ? &_' + paramName + ' : nullptr;\n'; - constructsBodies += '}\n'; - else: - dataText += '\t[[nodiscard]] const MTP' + paramType + ' &v' + paramName + '() const;\n'; - constructsBodies += 'const MTP' + paramType + ' &MTPD' + name + '::v' + paramName + '() const {\n'; - constructsBodies += '\treturn _' + paramName + ';\n'; - constructsBodies += '}\n'; - dataText += '\n'; - dataText += 'private:\n'; - for paramName in prmsList: # fields declaration - if (paramName in trivialConditions): - continue; - paramType = prms[paramName]; - dataText += '\tMTP' + paramType + ' _' + paramName + ';\n'; - dataText += '\n'; - sizeCases += '\tcase mtpc_' + name + ': {\n'; - sizeCases += '\t\tconst MTPD' + name + ' &v(c_' + name + '());\n'; - sizeCases += '\t\treturn ' + ' + '.join(sizeList) + ';\n'; - sizeCases += '\t}\n'; - sizeFast = '\tconst MTPD' + name + ' &v(c_' + name + '());\n\treturn ' + ' + '.join(sizeList) + ';\n'; - newFast = 'new MTPD' + name + '()'; - else: - constructsBodies += 'const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n'; - if (withType): - constructsBodies += '\tExpects(_type == mtpc_' + name + ');\n\n'; - constructsBodies += '\tstatic const MTPD' + name + ' result;\n'; - constructsBodies += '\treturn result;\n'; - constructsBodies += '}\n'; - - sizeFast = '\treturn 0;\n'; - - switchLines += 'break;\n'; - dataText += '};\n'; # class ending - - dataTexts += dataText; # add data class - - if (not friendDecl): - friendDecl += '\tfriend class MTP::internal::TypeCreator;\n'; - creatorProxyText += '\tinline static MTP' + restype + ' new_' + name + '(' + ', '.join(creatorParams) + ') {\n'; - if (len(prms) > len(trivialConditions)): # creator with params - creatorProxyText += '\t\treturn MTP' + restype + '(new MTPD' + name + '(' + ', '.join(creatorParamsList) + '));\n'; - else: - if (withType): # creator by type - creatorProxyText += '\t\treturn MTP' + restype + '(mtpc_' + name + ');\n'; - else: # single creator - creatorProxyText += '\t\treturn MTP' + restype + '();\n'; - creatorProxyText += '\t}\n'; - creatorsDeclarations += 'MTP' + restype + ' MTP_' + name + '(' + ', '.join(creatorParams) + ');\n'; - creatorsBodies += 'MTP' + restype + ' MTP_' + name + '(' + ', '.join(creatorParams) + ') {\n'; - creatorsBodies += '\treturn MTP::internal::TypeCreator::new_' + name + '(' + ', '.join(creatorParamsList) + ');\n'; - creatorsBodies += '}\n'; - - if (withType): - reader += '\tcase mtpc_' + name + ': _type = cons; '; # read switch line - if (len(prms) > len(trivialConditions)): - reader += '{\n'; - reader += '\t\tif (const auto data = new MTPD' + name + '(); data->read(from, end)) {\n'; - reader += '\t\t\tsetData(data);\n'; - reader += '\t\t} else {\n'; - reader += '\t\t\tdelete data;\n'; - reader += '\t\t\treturn false;\n'; - reader += '\t\t}\n'; - reader += '\t} break;\n'; - - writer += '\tcase mtpc_' + name + ': {\n'; # write switch line - writer += '\t\tconst MTPD' + name + ' &v = c_' + name + '();\n'; - writer += writeText; - writer += '\t} break;\n'; - else: - reader += 'break;\n'; - else: - if (len(prms) > len(trivialConditions)): - reader += '\tif (const auto data = new MTPD' + name + '(); data->read(from, end)) {\n'; - reader += '\t\tsetData(data);\n'; - reader += '\t} else {\n'; - reader += '\t\tdelete data;\n'; - reader += '\t\treturn false;\n'; - reader += '\t}\n'; - - writer += '\tconst MTPD' + name + ' &v = c_' + name + '();\n'; - writer += writeText; - - forwards += '\n'; - - typesText += '\nclass MTP' + restype; # type class declaration - if (withData): - typesText += ' : private MTP::internal::TypeDataOwner'; # if has data fields - typesText += ' {\n'; - typesText += 'public:\n'; - typesText += '\tMTP' + restype + '();\n'; # default constructor - if (withData and not withType): - methods += '\nMTP' + restype + '::MTP' + restype + '() : TypeDataOwner(' + newFast + ') {\n}\n'; - else: - methods += '\nMTP' + restype + '::MTP' + restype + '() = default;\n'; - - typesText += getters; - typesText += '\n'; - typesText += '\ttemplate \n'; - typesText += '\tdecltype(auto) match(Method &&method, Methods &&...methods) const;\n'; - visitorMethods += 'template \n'; - visitorMethods += 'decltype(auto) MTP' + restype + '::match(Method &&method, Methods &&...methods) const {\n'; - if (withType): - visitorMethods += '\tswitch (_type) {\n'; - visitorMethods += visitor; - visitorMethods += '\t}\n'; - visitorMethods += '\tUnexpected("Type in MTP' + restype + '::match.");\n'; - else: - visitorMethods += '\treturn base::match_method(c_' + v[0][0] + '(), std::forward(method), std::forward(methods)...);\n'; - visitorMethods += '}\n\n'; - - typesText += '\n\tuint32 innerLength() const;\n'; # size method - methods += '\nuint32 MTP' + restype + '::innerLength() const {\n'; - if (withType and sizeCases): - methods += '\tswitch (_type) {\n'; - methods += sizeCases; - methods += '\t}\n'; - methods += '\treturn 0;\n'; - else: - methods += sizeFast; - methods += '}\n'; - - typesText += '\tmtpTypeId type() const;\n'; # type id method - methods += 'mtpTypeId MTP' + restype + '::type() const {\n'; - if (withType): - methods += '\tExpects(_type != 0);\n\n'; - methods += '\treturn _type;\n'; - else: - methods += '\treturn mtpc_' + v[0][0] + ';\n'; - methods += '}\n'; - - typesText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons'; # read method - if (not withType): - typesText += ' = mtpc_' + name; - typesText += ');\n'; - methods += 'bool MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n'; - if (withData): - if not (withType): - methods += '\tif (cons != mtpc_' + v[0][0] + ') return false;\n'; - if (withType): - methods += '\tswitch (cons) {\n' - methods += reader; - methods += '\tdefault: return false;\n'; - methods += '\t}\n'; - else: - methods += reader; - methods += '\treturn true;\n'; - methods += '}\n'; - - typesText += '\tvoid write(mtpBuffer &to) const;\n'; # write method - methods += 'void MTP' + restype + '::write(mtpBuffer &to) const {\n'; - if (withType and writer != ''): - methods += '\tswitch (_type) {\n'; - methods += writer; - methods += '\t}\n'; - else: - methods += writer; - methods += '}\n'; - - typesText += '\n\tusing ResponseType = void;\n'; # no response types declared - - typesText += '\nprivate:\n'; # private constructors - if (withType): # by-type-id constructor - typesText += '\texplicit MTP' + restype + '(mtpTypeId type);\n'; - methods += 'MTP' + restype + '::MTP' + restype + '(mtpTypeId type) : '; - methods += '_type(type)'; - methods += ' {\n'; - methods += '\tswitch (type) {\n'; # type id check - methods += switchLines; - methods += '\tdefault: Unexpected("Type in MTP' + restype + '::MTP' + restype + '.");\n'; - methods += '\t}\n'; - methods += '}\n'; # by-type-id constructor end - - if (withData): - typesText += constructsText; - methods += constructsBodies; - - if (friendDecl): - typesText += '\n' + friendDecl; - - if (withType): - typesText += '\n\tmtpTypeId _type = 0;\n'; # type field var - - typesText += '};\n'; # type class ended - - flagOperators += flagDeclarations; - factories += creatorsDeclarations; - methods += creatorsBodies; - typesText += 'using MTP' + resType + ' = MTPBoxed;\n'; # boxed type definition - -flagOperators += '\n' - -for childName in parentFlagsList: - parentName = parentFlags[childName]; - for flag in parentFlagsCheck[childName]: -# -# 'channelForbidden' has 'until_date' flag and 'channel' doesn't have it. -# But as long as flags don't collide this is not a problem. -# -# if (not flag in parentFlagsCheck[parentName]): -# print('Flag ' + flag + ' not found in ' + parentName + ' which should be a flags-parent of ' + childName); -# sys.exit(1); -# - if (flag in parentFlagsCheck[parentName]): - if (parentFlagsCheck[childName][flag] != parentFlagsCheck[parentName][flag]): - print('Flag ' + flag + ' has different value in ' + parentName + ' which should be a flags-parent of ' + childName); - sys.exit(1); - else: - parentFlagsCheck[parentName][flag] = parentFlagsCheck[childName][flag]; - flagOperators += 'inline ' + parentName + '::Flags mtpCastFlags(' + childName + '::Flags flags) { return static_cast<' + parentName + '::Flag>(flags.value()); }\n'; - flagOperators += 'inline ' + parentName + '::Flags mtpCastFlags(MTPflags<' + childName + '::Flags> flags) { return mtpCastFlags(flags.v); }\n'; - -# manual types added here -textSerializeMethods += '\ -bool _serialize_rpc_result(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\ - if (stage) {\n\ - to.add(",\\n").addSpaces(lev);\n\ - } else {\n\ - to.add("{ rpc_result");\n\ - to.add("\\n").addSpaces(lev);\n\ - }\n\ - switch (stage) {\n\ - case 0: to.add(" req_msg_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 1: to.add(" result: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\ - }\n\ - return true;\n\ -}\n\ -\n\ -bool _serialize_msg_container(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\ - if (stage) {\n\ - to.add(",\\n").addSpaces(lev);\n\ - } else {\n\ - to.add("{ msg_container");\n\ - to.add("\\n").addSpaces(lev);\n\ - }\n\ - switch (stage) {\n\ - case 0: to.add(" messages: "); ++stages.back(); types.push_back(mtpc_vector); vtypes.push_back(mtpc_core_message); stages.push_back(0); flags.push_back(0); break;\n\ - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\ - }\n\ - return true;\n\ -}\n\ -\n\ -bool _serialize_core_message(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\ - if (stage) {\n\ - to.add(",\\n").addSpaces(lev);\n\ - } else {\n\ - to.add("{ core_message");\n\ - to.add("\\n").addSpaces(lev);\n\ - }\n\ - switch (stage) {\n\ - case 0: to.add(" msg_id: "); ++stages.back(); types.push_back(mtpc_long); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 1: to.add(" seq_no: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 2: to.add(" bytes: "); ++stages.back(); types.push_back(mtpc_int); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - case 3: to.add(" body: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\ - default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\ - }\n\ - return true;\n\ -}\n\ -\n'; - -textSerializeInit += '\ - result.insert(mtpc_rpc_result, _serialize_rpc_result);\n\ - result.insert(mtpc_msg_container, _serialize_msg_container);\n\ - result.insert(mtpc_core_message, _serialize_core_message);\n'; - -# module itself - -header = '\ -/*\n\ -WARNING! All changes made in this file will be lost!\n\ -Created from \'' + os.path.basename(input_file) + '\' by \'codegen_scheme\'\n\ -\n\ -This file is part of Telegram Desktop,\n\ -the official desktop application for the Telegram messaging service.\n\ -\n\ -For license and copyright information please follow this link:\n\ -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL\n\ -*/\n\ -#pragma once\n\ -\n\ -#include "mtproto/core_types.h"\n\ -#include "base/flags.h"\n\ -\n\ -// Creator current layer and proxy class declaration\n\ -namespace MTP {\n\ -namespace internal {\n\ -\n\ -' + layer + '\n\ -\n\ -class TypeCreator;\n\ -\n\ -} // namespace internal\n\ -} // namespace MTP\n\ -\n\ -// Type id constants\n\ -enum {\n\ -' + ',\n'.join(enums) + '\n\ -};\n\ -\n\ -// Type forward declarations\n\ -' + forwards + '\n\ -// Boxed types definitions\n\ -' + forwTypedefs + '\n\ -// Type classes definitions\n\ -' + typesText + '\n\ -// Type constructors with data\n\ -' + dataTexts + '\n\ -// RPC methods\n\ -' + funcsText + '\n\ -// Template methods definition\n\ -' + inlineMethods + '\n\ -// Visitor definition\n\ -' + visitorMethods + '\n\ -// Flag operators definition\n\ -' + flagOperators + '\n\ -// Factory methods declaration\n\ -' + factories + '\n\ -// Human-readable text serialization\n\ -[[nodiscard]] bool mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons);\n' - -source = '\ -/*\n\ -WARNING! All changes made in this file will be lost!\n\ -Created from \'' + os.path.basename(input_file) + '\' by \'codegen_scheme\'\n\ -\n\ -This file is part of Telegram Desktop,\n\ -the official desktop application for the Telegram messaging service.\n\ -\n\ -For license and copyright information please follow this link:\n\ -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL\n\ -*/\n\ -#include "scheme.h"\n\ -\n\ -// Creator proxy class definition\n\ -namespace MTP {\n\ -namespace internal {\n\ -\n\ -class TypeCreator {\n\ -public:\n\ -' + creatorProxyText + '\n\ -};\n\ -\n\ -} // namespace internal\n\ -} // namespace MTP\n\ -\n\ -// Methods definition\n\ -' + methods + '\n\ -\n\ -using Types = QVector;\n\ -using StagesFlags = QVector;\n\ -\n\ -' + textSerializeMethods + '\n\ -namespace {\n\ -\n\ -using TextSerializer = bool (*)(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag);\n\ -using TextSerializers = QMap;\n\ -\n\ -QMap createTextSerializers() {\n\ - auto result = QMap();\n\ -\n\ -' + textSerializeInit + '\n\ - return result;\n\ -}\n\ -\n\ -} // namespace\n\ -\n\ -bool mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons) {\n\ - static auto serializers = createTextSerializers();\n\ -\n\ - QVector types, vtypes;\n\ - QVector stages, flags;\n\ - types.reserve(20); vtypes.reserve(20); stages.reserve(20); flags.reserve(20);\n\ - types.push_back(mtpTypeId(cons)); vtypes.push_back(mtpTypeId(vcons)); stages.push_back(0); flags.push_back(0);\n\ -\n\ - mtpTypeId type = cons, vtype = vcons;\n\ - int32 stage = 0, flag = 0;\n\ -\n\ - while (!types.isEmpty()) {\n\ - type = types.back();\n\ - vtype = vtypes.back();\n\ - stage = stages.back();\n\ - flag = flags.back();\n\ - if (!type) {\n\ - if (from >= end) {\n\ - to.error("insufficient data");\n\ - return false;\n\ - } else if (stage) {\n\ - to.error("unknown type on stage > 0");\n\ - return false;\n\ - }\n\ - types.back() = type = *from;\n\ - ++from;\n\ - }\n\ -\n\ - int32 lev = level + types.size() - 1;\n\ - auto it = serializers.constFind(type);\n\ - if (it != serializers.cend()) {\n\ - if (!(*it.value())(to, stage, lev, types, vtypes, stages, flags, from, end, flag)) {\n\ - to.error();\n\ - return false;\n\ - }\n\ - } else if (mtpTextSerializeCore(to, from, end, type, lev, vtype)) {\n\ - types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();\n\ - } else {\n\ - to.error();\n\ - return false;\n\ - }\n\ - }\n\ - return true;\n\ -}\n'; - -already_header = '' -if os.path.isfile(output_header): - with open(output_header, 'r') as already: - already_header = already.read() -if already_header != header: - with open(output_header, 'w') as out: - out.write(header) - -already_source = '' -if os.path.isfile(output_source): - with open(output_source, 'r') as already: - already_source = already.read() -if already_source != source: - with open(output_source, 'w') as out: - out.write(source) +sys.dont_write_bytecode = True +scriptPath = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(scriptPath + '/../../../lib_tl/tl') +from generate_tl import generate + +generate({ + 'namespaces': { + 'creator': 'MTP::internal', + }, + 'prefixes': { + 'type': 'MTP', + 'data': 'MTPD', + 'id': 'mtpc', + 'construct': 'MTP_', + }, + 'types': { + 'prime': 'mtpPrime', + 'typeId': 'mtpTypeId', + 'buffer': 'mtpBuffer', + }, + 'sections': [ + 'serialization', + 'read-write', + ], + + # define some checked flag conversions + # the key flag type should be a subset of the value flag type + # with exact the same names, then the key flag can be implicitly + # casted to the value flag type + 'flagInheritance': { + 'messageService': 'message', + 'updateShortMessage': 'message', + 'updateShortChatMessage': 'message', + 'updateShortSentMessage': 'message', + 'replyKeyboardHide': 'replyKeyboardMarkup', + 'replyKeyboardForceReply': 'replyKeyboardMarkup', + 'inputPeerNotifySettings': 'peerNotifySettings', + 'peerNotifySettings': 'inputPeerNotifySettings', + 'channelForbidden': 'channel', + 'dialogFolder': 'dialog', + }, + + 'typeIdExceptions': [ + 'channel#c88974ac', + 'ipPortSecret#37982646', + 'accessPointRule#4679b65f', + 'help.configSimple#5a592a6c', + ], + + 'renamedTypes': { + 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow': 'passwordKdfAlgoModPow', + }, + + 'skip': [ + 'int ? = Int;', + 'long ? = Long;', + 'double ? = Double;', + 'string ? = String;', + + 'vector {t:Type} # [ t ] = Vector t;', + + 'int128 4*[ int ] = Int128;', + 'int256 8*[ int ] = Int256;', + + 'vector#1cb5c415 {t:Type} # [ t ] = Vector t;', + ], + 'builtin': [ + 'int', + 'long', + 'double', + 'string', + 'bytes', + 'int128', + 'int256', + ], + 'builtinTemplates': [ + 'vector', + 'flags', + ], + 'synonyms': { + 'bytes': 'string', + }, + 'builtinInclude': 'mtproto/core_types.h', + +}) diff --git a/Telegram/SourceFiles/codegen/style/generator.cpp b/Telegram/SourceFiles/codegen/style/generator.cpp deleted file mode 100644 index 385cc1140..000000000 --- a/Telegram/SourceFiles/codegen/style/generator.cpp +++ /dev/null @@ -1,1343 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/style/generator.h" - -#include "base/crc32hash.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include "codegen/style/parsed_file.h" - -using Module = codegen::style::structure::Module; -using Struct = codegen::style::structure::Struct; -using Variable = codegen::style::structure::Variable; -using Tag = codegen::style::structure::TypeTag; - -namespace codegen { -namespace style { -namespace { - -constexpr int kErrorBadIconSize = 861; - -const auto kMustBeContrast = std::map{ - { "dialogsMenuIconFg", "dialogsBg" }, - { "windowBoldFg", "windowBg" }, -}; - -char hexChar(uchar ch) { - if (ch < 10) { - return '0' + ch; - } else if (ch < 16) { - return 'a' + (ch - 10); - } - return '0'; -} - -char hexSecondChar(char ch) { - return hexChar((*reinterpret_cast(&ch)) & 0x0F); -} - -char hexFirstChar(char ch) { - return hexChar((*reinterpret_cast(&ch)) >> 4); -} - -QString stringToEncodedString(const QString &str) { - QString result, lineBreak = "\\\n"; - result.reserve(str.size() * 8); - bool writingHexEscapedCharacters = false, startOnNewLine = false; - int lastCutSize = 0; - auto utf = str.toUtf8(); - for (auto ch : utf) { - if (result.size() - lastCutSize > 80) { - startOnNewLine = true; - result.append(lineBreak); - lastCutSize = result.size(); - } - if (ch == '\n') { - writingHexEscapedCharacters = false; - result.append("\\n"); - } else if (ch == '\t') { - writingHexEscapedCharacters = false; - result.append("\\t"); - } else if (ch == '"' || ch == '\\') { - writingHexEscapedCharacters = false; - result.append('\\').append(ch); - } else if (ch < 32 || static_cast(ch) > 127) { - writingHexEscapedCharacters = true; - result.append("\\x").append(hexFirstChar(ch)).append(hexSecondChar(ch)); - } else { - if (writingHexEscapedCharacters) { - writingHexEscapedCharacters = false; - result.append("\"\""); - } - result.append(ch); - } - } - return '"' + (startOnNewLine ? lineBreak : QString()) + result + '"'; -} - -QString stringToEncodedString(const std::string &str) { - return stringToEncodedString(QString::fromStdString(str)); -} - -QString stringToBinaryArray(const std::string &str) { - QStringList rows, chars; - chars.reserve(13); - rows.reserve(1 + (str.size() / 13)); - for (uchar ch : str) { - if (chars.size() > 12) { - rows.push_back(chars.join(", ")); - chars.clear(); - } - chars.push_back(QString("0x") + hexFirstChar(ch) + hexSecondChar(ch)); - } - if (!chars.isEmpty()) { - rows.push_back(chars.join(", ")); - } - return QString("{") + ((rows.size() > 1) ? '\n' : ' ') + rows.join(",\n") + " }"; -} - -QString pxValueName(int value) { - QString result = "px"; - if (value < 0) { - value = -value; - result += 'm'; - } - return result + QString::number(value); -} - -QString moduleBaseName(const structure::Module &module) { - auto moduleInfo = QFileInfo(module.filepath()); - auto moduleIsPalette = (moduleInfo.suffix() == "palette"); - return moduleIsPalette ? "palette" : "style_" + moduleInfo.baseName(); -} - -QString colorFallbackName(structure::Value value) { - auto copy = value.copyOf(); - if (!copy.isEmpty()) { - return copy.back(); - } - return value.Color().fallback; -} - -QChar paletteColorPart(uchar part) { - part = (part & 0x0F); - if (part >= 10) { - return 'a' + (part - 10); - } - return '0' + part; -} - -QString paletteColorComponent(uchar value) { - return QString() + paletteColorPart(value >> 4) + paletteColorPart(value); -} - -QString paletteColorValue(const structure::data::color &value) { - auto result = paletteColorComponent(value.red) + paletteColorComponent(value.green) + paletteColorComponent(value.blue); - if (value.alpha != 255) result += paletteColorComponent(value.alpha); - return result; -} - -} // namespace - -Generator::Generator(const structure::Module &module, const QString &destBasePath, const common::ProjectInfo &project, bool isPalette) -: module_(module) -, basePath_(destBasePath) -, baseName_(QFileInfo(basePath_).baseName()) -, project_(project) -, isPalette_(isPalette) { -} - -bool Generator::writeHeader() { - header_ = std::make_unique(basePath_ + ".h", project_); - - header_->include("ui/style/style_core.h").newline(); - - if (!writeHeaderRequiredIncludes()) { - return false; - } - if (!writeHeaderStyleNamespace()) { - return false; - } - if (!writeRefsDeclarations()) { - return false; - } - - return header_->finalize(); -} - -bool Generator::writeSource() { - source_ = std::make_unique(basePath_ + ".cpp", project_); - - writeIncludesInSource(); - - if (module_.hasVariables()) { - source_->pushNamespace().newline(); - source_->stream() << "\ -bool inited = false;\n\ -\n\ -class Module_" << baseName_ << " : public style::internal::ModuleBase {\n\ -public:\n\ - Module_" << baseName_ << "() { style::internal::registerModule(this); }\n\ -\n\ - void start(int scale) override {\n\ - style::internal::init_" << baseName_ << "(scale);\n\ - }\n\ -};\n\ -Module_" << baseName_ << " registrator;\n"; - if (isPalette_) { - source_->newline(); - source_->stream() << "style::palette _palette;\n"; - } else { - if (!writeVariableDefinitions()) { - return false; - } - } - source_->newline().popNamespace(); - - source_->newline().pushNamespace("st"); - if (!writeRefsDefinition()) { - return false; - } - - source_->popNamespace().newline().pushNamespace("style"); - if (isPalette_) { - writeSetPaletteColor(); - } - source_->pushNamespace("internal").newline(); - if (!writeVariableInit()) { - return false; - } - } - - return source_->finalize(); -} - -// Empty result means an error. -QString Generator::typeToString(structure::Type type) const { - switch (type.tag) { - case Tag::Invalid: return QString(); - case Tag::Int: return "int"; - case Tag::Double: return "double"; - case Tag::Pixels: return "int"; - case Tag::String: return "QString"; - case Tag::Color: return "style::color"; - case Tag::Point: return "style::point"; - case Tag::Size: return "style::size"; - case Tag::Align: return "style::align"; - case Tag::Margins: return "style::margins"; - case Tag::Font: return "style::font"; - case Tag::Icon: return "style::icon"; - case Tag::Struct: return "style::" + type.name.back(); - } - return QString(); -} - -// Empty result means an error. -QString Generator::typeToDefaultValue(structure::Type type) const { - switch (type.tag) { - case Tag::Invalid: return QString(); - case Tag::Int: return "0"; - case Tag::Double: return "0."; - case Tag::Pixels: return "0"; - case Tag::String: return "QString()"; - case Tag::Color: return "{ Qt::Uninitialized }"; - case Tag::Point: return "{ 0, 0 }"; - case Tag::Size: return "{ 0, 0 }"; - case Tag::Align: return "style::al_topleft"; - case Tag::Margins: return "{ 0, 0, 0, 0 }"; - case Tag::Font: return "{ Qt::Uninitialized }"; - case Tag::Icon: return "{ Qt::Uninitialized }"; - case Tag::Struct: { - if (auto realType = module_.findStruct(type.name)) { - QStringList fields; - for (auto field : realType->fields) { - fields.push_back(typeToDefaultValue(field.type)); - } - return "{ " + fields.join(", ") + " }"; - } - return QString(); - } break; - } - return QString(); -} - -// Empty result means an error. -QString Generator::valueAssignmentCode(structure::Value value) const { - auto copy = value.copyOf(); - if (!copy.isEmpty()) { - return "st::" + copy.back(); - } - - switch (value.type().tag) { - case Tag::Invalid: return QString(); - case Tag::Int: return QString("%1").arg(value.Int()); - case Tag::Double: return QString("%1").arg(value.Double()); - case Tag::Pixels: return pxValueName(value.Int()); - case Tag::String: return QString("QString::fromUtf8(%1)").arg(stringToEncodedString(value.String())); - case Tag::Color: { - auto v(value.Color()); - if (v.red == v.green && v.red == v.blue && v.red == 0 && v.alpha == 255) { - return QString("st::windowFg"); - } else if (v.red == v.green && v.red == v.blue && v.red == 255 && v.alpha == 0) { - return QString("st::transparent"); - } else { - common::logError(common::kErrorInternal, "") << "bad color value"; - return QString(); - } - } break; - case Tag::Point: { - auto v(value.Point()); - return QString("{ %1, %2 }").arg(pxValueName(v.x)).arg(pxValueName(v.y)); - } break; - case Tag::Size: { - auto v(value.Size()); - return QString("{ %1, %2 }").arg(pxValueName(v.width)).arg(pxValueName(v.height)); - } break; - case Tag::Align: return QString("style::al_%1").arg(value.String().c_str()); - case Tag::Margins: { - auto v(value.Margins()); - return QString("{ %1, %2, %3, %4 }").arg(pxValueName(v.left)).arg(pxValueName(v.top)).arg(pxValueName(v.right)).arg(pxValueName(v.bottom)); - } break; - case Tag::Font: { - auto v(value.Font()); - QString family = "0"; - if (!v.family.empty()) { - auto familyIndex = fontFamilies_.value(v.family, -1); - if (familyIndex < 0) { - return QString(); - } - family = QString("font%1index").arg(familyIndex); - } - return QString("{ %1, %2, %3 }").arg(pxValueName(v.size)).arg(v.flags).arg(family); - } break; - case Tag::Icon: { - auto v(value.Icon()); - if (v.parts.empty()) return QString("{}"); - - QStringList parts; - for (const auto &part : v.parts) { - auto maskIndex = iconMasks_.value(part.filename, -1); - if (maskIndex < 0) { - return QString(); - } - auto color = valueAssignmentCode(part.color); - auto offset = valueAssignmentCode(part.offset); - parts.push_back(QString("MonoIcon{ &iconMask%1, %2, %3 }").arg(maskIndex).arg(color).arg(offset)); - } - return QString("{ %1 }").arg(parts.join(", ")); - } break; - case Tag::Struct: { - if (!value.Fields()) return QString(); - - QStringList fields; - for (auto field : *value.Fields()) { - fields.push_back(valueAssignmentCode(field.variable.value)); - } - return "{ " + fields.join(", ") + " }"; - } break; - } - return QString(); -} - -bool Generator::writeHeaderRequiredIncludes() { - std::function findInIncludes = [&](const Module &module, const structure::FullName &name) { - auto result = QString(); - module.enumIncludes([&](const Module &included) { - if (Module::findStructInModule(name, included)) { - result = moduleBaseName(included); - return false; - } - result = findInIncludes(included, name); - return true; - }); - return result; - }; - - auto includes = QStringList(); - const auto written = module_.enumStructs([&](const Struct &value) -> bool { - for (const auto &field : value.fields) { - if (field.type.tag == structure::TypeTag::Struct) { - const auto name = field.type.name; - if (!module_.findStructInModule(name, module_)) { - const auto base = findInIncludes(module_, name); - if (base.isEmpty()) { - return false; - } - if (!includes.contains(base)) { - includes.push_back(base); - } - } - } - } - return true; - }); - if (!written) { - return false; - } else if (includes.isEmpty()) { - return true; - } - for (const auto base : includes) { - header_->include(base + ".h"); - } - header_->newline(); - return true; -} - -bool Generator::writeHeaderStyleNamespace() { - if (!module_.hasStructs() && !module_.hasVariables()) { - return true; - } - header_->pushNamespace("style"); - - if (module_.hasVariables()) { - header_->pushNamespace("internal").newline(); - header_->stream() << "void init_" << baseName_ << "(int scale);\n\n"; - header_->popNamespace(); - } - bool wroteForwardDeclarations = writeStructsForwardDeclarations(); - if (module_.hasStructs()) { - if (!wroteForwardDeclarations) { - header_->newline(); - } - if (!writeStructsDefinitions()) { - return false; - } - } else if (isPalette_) { - if (!wroteForwardDeclarations) { - header_->newline(); - } - if (!writePaletteDefinition()) { - return false; - } - } - - header_->popNamespace().newline(); - return true; -} - -bool Generator::writePaletteDefinition() { - header_->stream() << "\ -class palette {\n\ -public:\n\ - palette() = default;\n\ - palette(const palette &other) = delete;\n\ -\n\ - QByteArray save() const;\n\ - bool load(const QByteArray &cache);\n\ -\n\ - enum class SetResult {\n\ - Ok,\n\ - KeyNotFound,\n\ - ValueNotFound,\n\ - Duplicate,\n\ - };\n\ - SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\ - SetResult setColor(QLatin1String name, QLatin1String from);\n\ - void reset() {\n\ - clear();\n\ - finalize();\n\ - }\n\ -\n\ - // Created not inited, should be finalized before usage.\n\ - void finalize();\n\ -\n\ - int indexOfColor(color c) const;\n\ - color colorAtIndex(int index) const;\n\ -\n\ - inline const color &get_transparent() const { return _colors[0]; }; // special color\n"; - - int indexInPalette = 1; - if (!module_.enumVariables([&](const Variable &variable) -> bool { - auto name = variable.name.back(); - if (variable.value.type().tag != structure::TypeTag::Color) { - return false; - } - - auto index = (indexInPalette++); - header_->stream() << "\tinline const color &get_" << name << "() const { return _colors[" << index << "]; };\n"; - return true; - })) return false; - - auto count = indexInPalette; - header_->stream() << "\ -\n\ - palette &operator=(const palette &other) {\n\ - auto wasReady = _ready;\n\ - for (int i = 0; i != kCount; ++i) {\n\ - if (other._status[i] == Status::Loaded) {\n\ - if (_status[i] == Status::Initial) {\n\ - new (data(i)) internal::ColorData(*other.data(i));\n\ - } else {\n\ - *data(i) = *other.data(i);\n\ - }\n\ - } else if (_status[i] != Status::Initial) {\n\ - data(i)->~ColorData();\n\ - _status[i] = Status::Initial;\n\ - _ready = false;\n\ - }\n\ - }\n\ - if (wasReady && !_ready) {\n\ - finalize();\n\ - }\n\ - return *this;\n\ - }\n\ -\n\ - static int32 Checksum();\n\ -\n\ - ~palette() {\n\ - clear();\n\ - }\n\ -\n\ -private:\n\ - static constexpr auto kCount = " << count << ";\n\ -\n\ - void clear() {\n\ - for (int i = 0; i != kCount; ++i) {\n\ - if (_status[i] != Status::Initial) {\n\ - data(i)->~ColorData();\n\ - _status[i] = Status::Initial;\n\ - _ready = false;\n\ - }\n\ - }\n\ - }\n\ -\n\ - struct TempColorData { uchar r, g, b, a; };\n\ - void compute(int index, int fallbackIndex, TempColorData value) {\n\ - if (_status[index] == Status::Initial) {\n\ - if (fallbackIndex >= 0 && _status[fallbackIndex] == Status::Loaded) {\n\ - _status[index] = Status::Loaded;\n\ - new (data(index)) internal::ColorData(*data(fallbackIndex));\n\ - } else {\n\ - _status[index] = Status::Created;\n\ - new (data(index)) internal::ColorData(value.r, value.g, value.b, value.a);\n\ - }\n\ - }\n\ - }\n\ -\n\ - internal::ColorData *data(int index) {\n\ - return reinterpret_cast(_data) + index;\n\ - }\n\ -\n\ - const internal::ColorData *data(int index) const {\n\ - return reinterpret_cast(_data) + index;\n\ - }\n\ -\n\ - void setData(int index, const internal::ColorData &value) {\n\ - if (_status[index] == Status::Initial) {\n\ - new (data(index)) internal::ColorData(value);\n\ - } else {\n\ - *data(index) = value;\n\ - }\n\ - _status[index] = Status::Loaded;\n\ - }\n\ -\n\ - enum class Status {\n\ - Initial,\n\ - Created,\n\ - Loaded,\n\ - };\n\ -\n\ - alignas(alignof(internal::ColorData)) char _data[sizeof(internal::ColorData) * kCount];\n\ -\n\ - color _colors[kCount] = {\n"; - for (int i = 0; i != count; ++i) { - header_->stream() << "\t\tdata(" << i << "),\n"; - } - header_->stream() << "\ - };\n\ - Status _status[kCount] = { Status::Initial };\n\ - bool _ready = false;\n\ -\n\ -};\n\ -\n\ -namespace main_palette {\n\ -\n\ -QByteArray save();\n\ -bool load(const QByteArray &cache);\n\ -palette::SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);\n\ -palette::SetResult setColor(QLatin1String name, QLatin1String from);\n\ -void apply(const palette &other);\n\ -void reset();\n\ -int indexOfColor(color c);\n\ -\n\ -struct row {\n\ -\tQLatin1String name;\n\ -\tQLatin1String value;\n\ -\tQLatin1String fallback;\n\ -\tQLatin1String description;\n\ -};\n\ -QList data();\n\ -\n\ -} // namespace main_palette\n"; - - return true; -} - -bool Generator::writeStructsForwardDeclarations() { - bool hasNoExternalStructs = module_.enumVariables([&](const Variable &value) -> bool { - if (value.value.type().tag == structure::TypeTag::Struct) { - if (!module_.findStructInModule(value.value.type().name, module_)) { - return false; - } - } - return true; - }); - if (hasNoExternalStructs) { - return false; - } - - header_->newline(); - std::set alreadyDeclaredTypes; - bool result = module_.enumVariables([&](const Variable &value) -> bool { - if (value.value.type().tag == structure::TypeTag::Struct) { - if (!module_.findStructInModule(value.value.type().name, module_)) { - if (alreadyDeclaredTypes.find(value.value.type().name.back()) == alreadyDeclaredTypes.end()) { - header_->stream() << "struct " << value.value.type().name.back() << ";\n"; - alreadyDeclaredTypes.emplace(value.value.type().name.back()); - } - } - } - return true; - }); - header_->newline(); - return result; -} - -bool Generator::writeStructsDefinitions() { - if (!module_.hasStructs()) { - return true; - } - - bool result = module_.enumStructs([&](const Struct &value) -> bool { - header_->stream() << "\ -struct " << value.name.back() << " {\n"; - for (auto &field : value.fields) { - auto type = typeToString(field.type); - if (type.isEmpty()) { - return false; - } - header_->stream() << "\t" << type << " " << field.name.back() << ";\n"; - } - header_->stream() << "\ -};\n\n"; - return true; - }); - - return result; -} - -bool Generator::writeRefsDeclarations() { - if (!module_.hasVariables()) { - return true; - } - - header_->pushNamespace("st"); - - if (isPalette_) { - header_->stream() << "extern const style::color &transparent; // special color\n"; - } - bool result = module_.enumVariables([&](const Variable &value) -> bool { - auto name = value.name.back(); - auto type = typeToString(value.value.type()); - if (type.isEmpty()) { - return false; - } - - header_->stream() << "extern const " << type << " &" << name << ";\n"; - return true; - }); - - header_->popNamespace(); - - return result; -} - -bool Generator::writeIncludesInSource() { - if (!module_.hasIncludes()) { - return true; - } - - auto includes = QStringList(); - std::function collector = [&](const Module &module) { - module.enumIncludes(collector); - auto base = moduleBaseName(module); - if (!includes.contains(base)) { - includes.push_back(base); - } - return true; - }; - auto result = module_.enumIncludes(collector); - for (auto base : includes) { - source_->include(base + ".h"); - } - source_->newline(); - return result; -} - -bool Generator::writeVariableDefinitions() { - if (!module_.hasVariables()) { - return true; - } - - source_->newline(); - bool result = module_.enumVariables([&](const Variable &variable) -> bool { - auto name = variable.name.back(); - auto type = typeToString(variable.value.type()); - if (type.isEmpty()) { - return false; - } - source_->stream() << type << " _" << name << " = " << typeToDefaultValue(variable.value.type()) << ";\n"; - return true; - }); - return result; -} - -bool Generator::writeRefsDefinition() { - if (!module_.hasVariables()) { - return true; - } - - if (isPalette_) { - source_->stream() << "const style::color &transparent(_palette.get_transparent()); // special color\n"; - } - bool result = module_.enumVariables([&](const Variable &variable) -> bool { - auto name = variable.name.back(); - auto type = typeToString(variable.value.type()); - if (type.isEmpty()) { - return false; - } - source_->stream() << "const " << type << " &" << name << "("; - if (isPalette_) { - source_->stream() << "_palette.get_" << name << "()"; - } else { - source_->stream() << "_" << name; - } - source_->stream() << ");\n"; - return true; - }); - return result; -} - -bool Generator::writeSetPaletteColor() { - source_->newline(); - source_->stream() << "\n\ -int palette::indexOfColor(style::color c) const {\n\ - auto start = data(0);\n\ - if (c._data >= start && c._data < start + kCount) {\n\ - return static_cast(c._data - start);\n\ - }\n\ - return -1;\n\ -}\n\ -\n\ -color palette::colorAtIndex(int index) const {\n\ - Assert(_ready);\n\ - Assert(index >= 0 && index < kCount);\n\ - return _colors[index];\n\ -}\n\ -\n\ -void palette::finalize() {\n\ - if (_ready) return;\n\ - _ready = true;\n\ -\n\ - compute(0, -1, { 255, 255, 255, 0}); // special color\n"; - - QList names; - module_.enumVariables([&](const Variable &variable) -> bool { - names.push_back(variable.name); - return true; - }); - - QString dataRows; - int indexInPalette = 1; - QByteArray checksumString; - checksumString.append("&transparent:{ 255, 255, 255, 0 }"); - auto result = module_.enumVariables([&](const Variable &variable) -> bool { - auto name = variable.name.back(); - auto index = indexInPalette++; - paletteIndices_.emplace(name, index); - if (variable.value.type().tag != structure::TypeTag::Color) { - return false; - } - auto color = variable.value.Color(); - auto fallbackIterator = paletteIndices_.find(colorFallbackName(variable.value)); - auto fallbackIndex = (fallbackIterator == paletteIndices_.end()) ? -1 : fallbackIterator->second; - auto assignment = QString("{ %1, %2, %3, %4 }").arg(color.red).arg(color.green).arg(color.blue).arg(color.alpha); - source_->stream() << "\tcompute(" << index << ", " << fallbackIndex << ", " << assignment << ");\n"; - checksumString.append('&' + name + ':' + assignment); - - auto isCopy = !variable.value.copyOf().isEmpty(); - auto colorString = paletteColorValue(color); - auto fallbackName = QString(); - if (fallbackIndex > 0) { - auto fallbackVariable = module_.findVariableInModule(names[fallbackIndex - 1], module_); - if (fallbackVariable && fallbackVariable->value.type().tag == structure::TypeTag::Color) { - fallbackName = fallbackVariable->name.back(); - } - } - auto value = isCopy ? fallbackName : '#' + colorString; - if (value.isEmpty()) { - return false; - } - - dataRows.append("\tresult.push_back({ qstr(\"" + name + "\"), qstr(\"" + value + "\"), qstr(\"" + (isCopy ? QString() : fallbackName) + "\"), qstr(" + stringToEncodedString(variable.description.toStdString()) + ") });\n"); - return true; - }); - if (!result) { - return false; - } - auto count = indexInPalette; - auto checksum = base::crc32(checksumString.constData(), checksumString.size()); - - source_->stream() << "\n\n"; - for (const auto &[over, under] : kMustBeContrast) { - const auto overIndex = paletteIndices_.find(over); - const auto underIndex = paletteIndices_.find(under); - if (overIndex == paletteIndices_.end() || underIndex == paletteIndices_.end()) { - return false; - } - source_->stream() << "\tinternal::EnsureContrast(*data(" << overIndex->second << "), *data(" << underIndex->second << "));\n"; - } - source_->stream() << "\ -}\n\ -\n\ -int32 palette::Checksum() {\n\ - return " << checksum << ";\n\ -}\n"; - - source_->newline().pushNamespace().newline(); - source_->stream() << "\ -int getPaletteIndex(QLatin1String name) {\n\ - auto size = name.size();\n\ - auto data = name.data();\n"; - - auto tabs = [](int size) { - return QString(size, '\t'); - }; - - enum class UsedCheckType { - Switch, - If, - UpcomingIf, - }; - auto checkTypes = QVector(); - auto checkLengthHistory = QVector(1, 0); - auto chars = QString(); - auto tabsUsed = 1; - - // Returns true if at least one check was finished. - auto finishChecksTillKey = [&](const QString &key) { - auto result = false; - while (!chars.isEmpty() && key.midRef(0, chars.size()) != chars) { - result = true; - - auto wasType = checkTypes.back(); - chars.resize(chars.size() - 1); - checkTypes.pop_back(); - checkLengthHistory.pop_back(); - if (wasType == UsedCheckType::Switch || wasType == UsedCheckType::If) { - --tabsUsed; - if (wasType == UsedCheckType::Switch) { - source_->stream() << tabs(tabsUsed) << "break;\n"; - } - if ((!chars.isEmpty() && key.midRef(0, chars.size()) != chars) || key == chars) { - source_->stream() << tabs(tabsUsed) << "}\n"; - } - } - } - return result; - }; - - // Check if we can use "if" for a check on "charIndex" in "it" (otherwise only "switch") - auto canUseIfForCheck = [](auto it, auto end, int charIndex) { - auto key = it->first; - auto i = it; - auto keyStart = key.mid(0, charIndex); - for (++i; i != end; ++i) { - auto nextKey = i->first; - if (nextKey.mid(0, charIndex) != keyStart) { - return true; - } else if (nextKey.size() > charIndex && nextKey[charIndex] != key[charIndex]) { - return false; - } - } - return true; - }; - - auto countMinimalLength = [](auto it, auto end, int charIndex) { - auto key = it->first; - auto i = it; - auto keyStart = key.mid(0, charIndex); - auto result = key.size(); - for (++i; i != end; ++i) { - auto nextKey = i->first; - if (nextKey.mid(0, charIndex) != keyStart) { - break; - } else if (nextKey.size() > charIndex && result > nextKey.size()) { - result = nextKey.size(); - } - } - return result; - }; - - for (auto i = paletteIndices_.begin(), e = paletteIndices_.end(); i != e; ++i) { - auto name = i->first; - auto index = i->second; - - auto weContinueOldSwitch = finishChecksTillKey(name); - while (chars.size() != name.size()) { - auto checking = chars.size(); - auto partialKey = name.mid(0, checking); - - auto keyChar = name[checking]; - auto usedIfForCheckCount = 0; - auto minimalLengthCheck = countMinimalLength(i, e, checking); - for (; checking + usedIfForCheckCount != name.size(); ++usedIfForCheckCount) { - if (!canUseIfForCheck(i, e, checking + usedIfForCheckCount) - || countMinimalLength(i, e, checking + usedIfForCheckCount) != minimalLengthCheck) { - break; - } - } - auto usedIfForCheck = !weContinueOldSwitch && (usedIfForCheckCount > 0); - auto checkLengthCondition = QString(); - if (weContinueOldSwitch) { - weContinueOldSwitch = false; - } else { - checkLengthCondition = (minimalLengthCheck > checkLengthHistory.back()) ? ("size >= " + QString::number(minimalLengthCheck)) : QString(); - if (!usedIfForCheck) { - source_->stream() << tabs(tabsUsed) << (checkLengthCondition.isEmpty() ? QString() : ("if (" + checkLengthCondition + ") ")) << "switch (data[" << checking << "]) {\n"; - } - } - if (usedIfForCheck) { - auto conditions = QStringList(); - if (usedIfForCheckCount > 1) { - conditions.push_back("!memcmp(data + " + QString::number(checking) + ", \"" + name.mid(checking, usedIfForCheckCount) + "\", " + QString::number(usedIfForCheckCount) + ")"); - } else { - conditions.push_back("data[" + QString::number(checking) + "] == '" + keyChar + "'"); - } - if (!checkLengthCondition.isEmpty()) { - conditions.push_front(checkLengthCondition); - } - source_->stream() << tabs(tabsUsed) << "if (" << conditions.join(" && ") << ") {\n"; - checkTypes.push_back(UsedCheckType::If); - for (auto i = 1; i != usedIfForCheckCount; ++i) { - checkTypes.push_back(UsedCheckType::UpcomingIf); - chars.push_back(keyChar); - checkLengthHistory.push_back(qMax(minimalLengthCheck, checkLengthHistory.back())); - keyChar = name[checking + i]; - } - } else { - source_->stream() << tabs(tabsUsed) << "case '" << keyChar << "':\n"; - checkTypes.push_back(UsedCheckType::Switch); - } - ++tabsUsed; - chars.push_back(keyChar); - checkLengthHistory.push_back(qMax(minimalLengthCheck, checkLengthHistory.back())); - } - source_->stream() << tabs(tabsUsed) << "return (size == " << chars.size() << ") ? " << index << " : -1;\n"; - } - finishChecksTillKey(QString()); - - source_->stream() << "\ -\n\ - return -1;\n\ -}\n"; - - source_->newline().popNamespace().newline(); - source_->stream() << "\ -QByteArray palette::save() const {\n\ - if (!_ready) const_cast(this)->finalize();\n\ -\n\ - auto result = QByteArray(" << (count * 4) << ", Qt::Uninitialized);\n\ - for (auto i = 0, index = 0; i != " << count << "; ++i) {\n\ - result[index++] = static_cast(data(i)->c.red());\n\ - result[index++] = static_cast(data(i)->c.green());\n\ - result[index++] = static_cast(data(i)->c.blue());\n\ - result[index++] = static_cast(data(i)->c.alpha());\n\ - }\n\ - return result;\n\ -}\n\ -\n\ -bool palette::load(const QByteArray &cache) {\n\ - if (cache.size() != " << (count * 4) << ") return false;\n\ -\n\ - auto p = reinterpret_cast(cache.constData());\n\ - for (auto i = 0; i != " << count << "; ++i) {\n\ - setData(i, { p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3] });\n\ - }\n\ - return true;\n\ -}\n\ -\n\ -palette::SetResult palette::setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\ - auto nameIndex = getPaletteIndex(name);\n\ - if (nameIndex < 0) return SetResult::KeyNotFound;\n\ - auto duplicate = (_status[nameIndex] != Status::Initial);\n\ -\n\ - setData(nameIndex, { r, g, b, a });\n\ - return duplicate ? SetResult::Duplicate : SetResult::Ok;\n\ -}\n\ -\n\ -palette::SetResult palette::setColor(QLatin1String name, QLatin1String from) {\n\ - auto nameIndex = getPaletteIndex(name);\n\ - if (nameIndex < 0) return SetResult::KeyNotFound;\n\ - auto duplicate = (_status[nameIndex] != Status::Initial);\n\ -\n\ - auto fromIndex = getPaletteIndex(from);\n\ - if (fromIndex < 0 || _status[fromIndex] != Status::Loaded) return SetResult::ValueNotFound;\n\ -\n\ - setData(nameIndex, *data(fromIndex));\n\ - return duplicate ? SetResult::Duplicate : SetResult::Ok;\n\ -}\n\ -\n\ -namespace main_palette {\n\ -\n\ -QByteArray save() {\n\ - return _palette.save();\n\ -}\n\ -\n\ -bool load(const QByteArray &cache) {\n\ - if (_palette.load(cache)) {\n\ - style::internal::resetIcons();\n\ - return true;\n\ - }\n\ - return false;\n\ -}\n\ -\n\ -palette::SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) {\n\ - return _palette.setColor(name, r, g, b, a);\n\ -}\n\ -\n\ -palette::SetResult setColor(QLatin1String name, QLatin1String from) {\n\ - return _palette.setColor(name, from);\n\ -}\n\ -\n\ -void apply(const palette &other) {\n\ - _palette = other;\n\ - style::internal::resetIcons();\n\ -}\n\ -\n\ -void reset() {\n\ - _palette.reset();\n\ - style::internal::resetIcons();\n\ -}\n\ -\n\ -int indexOfColor(color c) {\n\ - return _palette.indexOfColor(c);\n\ -}\n\ -\n\ -QList data() {\n\ - auto result = QList();\n\ - result.reserve(" << count << ");\n\ -\n\ -" << dataRows << "\n\ - return result;\n\ -}\n\ -\n\ -} // namespace main_palette\n\ -\n"; - - return result; -} - -bool Generator::writeVariableInit() { - if (!module_.hasVariables()) { - return true; - } - - if (!collectUniqueValues()) { - return false; - } - bool hasUniqueValues = (!pxValues_.isEmpty() || !fontFamilies_.isEmpty() || !iconMasks_.isEmpty()); - if (hasUniqueValues) { - source_->pushNamespace(); - if (!writePxValuesInit()) { - return false; - } - if (!writeFontFamiliesInit()) { - return false; - } - if (!writeIconValues()) { - return false; - } - source_->popNamespace().newline(); - } - - source_->stream() << "\ -void init_" << baseName_ << "(int scale) {\n\ - if (inited) return;\n\ - inited = true;\n\n"; - - if (module_.hasIncludes()) { - bool writtenAtLeastOne = false; - bool result = module_.enumIncludes([&](const Module &module) -> bool { - if (module.hasVariables()) { - source_->stream() << "\tinit_" + moduleBaseName(module) + "(scale);\n"; - writtenAtLeastOne = true; - } - return true; - }); - if (!result) { - return false; - } - if (writtenAtLeastOne) { - source_->newline(); - } - } - - if (!pxValues_.isEmpty() || !fontFamilies_.isEmpty()) { - if (!pxValues_.isEmpty()) { - source_->stream() << "\tinitPxValues(scale);\n"; - } - if (!fontFamilies_.isEmpty()) { - source_->stream() << "\tinitFontFamilies();\n"; - } - source_->newline(); - } - - if (isPalette_) { - source_->stream() << "\t_palette.finalize();\n"; - } else if (!module_.enumVariables([&](const Variable &variable) -> bool { - auto name = variable.name.back(); - auto value = valueAssignmentCode(variable.value); - if (value.isEmpty()) { - return false; - } - source_->stream() << "\t_" << name << " = " << value << ";\n"; - return true; - })) { - return false; - } - source_->stream() << "\ -}\n\n"; - return true; -} - -bool Generator::writePxValuesInit() { - if (pxValues_.isEmpty()) { - return true; - } - - for (auto i = pxValues_.cbegin(), e = pxValues_.cend(); i != e; ++i) { - source_->stream() << "int " << pxValueName(i.key()) << " = " << i.key() << ";\n"; - } - source_->stream() << "\ -void initPxValues(int scale) {\n"; - for (auto it = pxValues_.cbegin(), e = pxValues_.cend(); it != e; ++it) { - auto value = it.key(); - source_->stream() << "\t" << pxValueName(value) << " = ConvertScale(" << value << ", scale);\n"; - } - source_->stream() << "\ -}\n\n"; - return true; -} - -bool Generator::writeFontFamiliesInit() { - if (fontFamilies_.isEmpty()) { - return true; - } - - for (auto familyIndex : fontFamilies_) { - source_->stream() << "int font" << familyIndex << "index;\n"; - } - source_->stream() << "void initFontFamilies() {\n"; - for (auto i = fontFamilies_.cbegin(), e = fontFamilies_.cend(); i != e; ++i) { - auto family = stringToEncodedString(i.key()); - source_->stream() << "\tfont" << i.value() << "index = style::internal::registerFontFamily(" << family << ");\n"; - } - source_->stream() << "}\n\n"; - return true; -} - -namespace { - -QByteArray iconMaskValueSize(int width, int height) { - QByteArray result; - QLatin1String generateTag("GENERATE:"); - result.append(generateTag.data(), generateTag.size()); - QLatin1String sizeTag("SIZE:"); - result.append(sizeTag.data(), sizeTag.size()); - { - QDataStream stream(&result, QIODevice::Append); - stream.setVersion(QDataStream::Qt_5_1); - stream << qint32(width) << qint32(height); - } - return result; -} - -QByteArray iconMaskValuePng(QString filepath) { - QByteArray result; - - QFileInfo fileInfo(filepath); - auto directory = fileInfo.dir(); - auto nameAndModifiers = fileInfo.fileName().split('-'); - filepath = directory.filePath(nameAndModifiers[0]); - auto modifiers = nameAndModifiers.mid(1); - - const auto readImage = [&](const QString &postfix) { - const auto path = filepath + postfix + ".png"; - auto result = QImage(path); - if (result.isNull()) { - common::logError(common::kErrorFileNotOpened, path) << "could not open icon file"; - return QImage(); - } else if (result.format() != QImage::Format_RGB32) { - result = std::move(result).convertToFormat(QImage::Format_RGB32); - } - result.setDevicePixelRatio(1.); - return result; - }; - auto png1x = readImage(""); - auto png2x = readImage("@2x"); - auto png3x = readImage("@3x"); - if (png1x.isNull() || png2x.isNull() || png3x.isNull()) { - return result; - } - if (png1x.width() * 2 != png2x.width() - || png1x.height() * 2 != png2x.height() - || png1x.width() * 3 != png3x.width() - || png1x.height() * 3 != png3x.height()) { - common::logError(kErrorBadIconSize, filepath + ".png") - << "bad icons size, 1x: " - << png1x.width() << "x" << png1x.height() - << ", 2x: " - << png2x.width() << "x" << png2x.height() - << ", 3x: " - << png3x.width() << "x" << png3x.height(); - return result; - } - for (const auto modifierName : modifiers) { - if (const auto modifier = GetModifier(modifierName)) { - modifier(png1x); - modifier(png2x); - modifier(png3x); - } else { - common::logError(common::kErrorInternal, filepath) << "modifier should be valid here, name: " << modifierName.toStdString(); - return result; - } - } - QImage composed(png3x.width(), png3x.height() + png2x.height(), QImage::Format_RGB32); - composed.fill(Qt::black); - { - QPainter p(&composed); - p.drawImage(0, 0, png1x); - p.drawImage(png1x.width(), 0, png2x); - p.drawImage(0, png2x.height(), png3x); - } - { - QBuffer buffer(&result); - composed.save(&buffer, "PNG"); - } - return result; -} - -} // namespace - -bool Generator::writeIconValues() { - if (iconMasks_.isEmpty()) { - return true; - } - - for (auto i = iconMasks_.cbegin(), e = iconMasks_.cend(); i != e; ++i) { - QString filePath = i.key(); - QByteArray maskData; - QImage png100x, png200x; - if (filePath.startsWith("size://")) { - QStringList dimensions = filePath.mid(7).split(','); - if (dimensions.size() < 2 || dimensions.at(0).toInt() <= 0 || dimensions.at(1).toInt() <= 0) { - common::logError(common::kErrorFileNotOpened, filePath) << "bad dimensions"; - return false; - } - maskData = iconMaskValueSize(dimensions.at(0).toInt(), dimensions.at(1).toInt()); - } else { - maskData = iconMaskValuePng(filePath); - } - if (maskData.isEmpty()) { - return false; - } - source_->stream() << "const uchar iconMask" << i.value() << "Data[] = " << stringToBinaryArray(std::string(maskData.constData(), maskData.size())) << ";\n"; - source_->stream() << "IconMask iconMask" << i.value() << "(iconMask" << i.value() << "Data);\n\n"; - } - return true; -} - -bool Generator::collectUniqueValues() { - int fontFamilyIndex = 0; - int iconMaskIndex = 0; - std::function collector = [this, &collector, &fontFamilyIndex, &iconMaskIndex](const Variable &variable) { - auto value = variable.value; - if (!value.copyOf().isEmpty()) { - return true; - } - - switch (value.type().tag) { - case Tag::Invalid: - case Tag::Int: - case Tag::Double: - case Tag::String: - case Tag::Color: - case Tag::Align: break; - case Tag::Pixels: pxValues_.insert(value.Int(), true); break; - case Tag::Point: { - auto v(value.Point()); - pxValues_.insert(v.x, true); - pxValues_.insert(v.y, true); - } break; - case Tag::Size: { - auto v(value.Size()); - pxValues_.insert(v.width, true); - pxValues_.insert(v.height, true); - } break; - case Tag::Margins: { - auto v(value.Margins()); - pxValues_.insert(v.left, true); - pxValues_.insert(v.top, true); - pxValues_.insert(v.right, true); - pxValues_.insert(v.bottom, true); - } break; - case Tag::Font: { - auto v(value.Font()); - pxValues_.insert(v.size, true); - if (!v.family.empty() && !fontFamilies_.contains(v.family)) { - fontFamilies_.insert(v.family, ++fontFamilyIndex); - } - } break; - case Tag::Icon: { - auto v(value.Icon()); - for (auto &part : v.parts) { - pxValues_.insert(part.offset.Point().x, true); - pxValues_.insert(part.offset.Point().y, true); - if (!iconMasks_.contains(part.filename)) { - iconMasks_.insert(part.filename, ++iconMaskIndex); - } - } - } break; - case Tag::Struct: { - auto fields = variable.value.Fields(); - if (!fields) { - return false; - } - - for (auto field : *fields) { - if (!collector(field.variable)) { - return false; - } - } - } break; - } - return true; - }; - return module_.enumVariables(collector); -} - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/generator.h b/Telegram/SourceFiles/codegen/style/generator.h deleted file mode 100644 index 062c0cbc8..000000000 --- a/Telegram/SourceFiles/codegen/style/generator.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include -#include "codegen/common/cpp_file.h" -#include "codegen/style/structure_types.h" - -namespace codegen { -namespace style { -namespace structure { -class Module; -} // namespace structure - -class Generator { -public: - Generator(const structure::Module &module, const QString &destBasePath, const common::ProjectInfo &project, bool isPalette); - Generator(const Generator &other) = delete; - Generator &operator=(const Generator &other) = delete; - - bool writeHeader(); - bool writeSource(); - -private: - QString typeToString(structure::Type type) const; - QString typeToDefaultValue(structure::Type type) const; - QString valueAssignmentCode(structure::Value value) const; - - bool writeHeaderRequiredIncludes(); - bool writeHeaderStyleNamespace(); - bool writeStructsForwardDeclarations(); - bool writeStructsDefinitions(); - bool writePaletteDefinition(); - bool writeRefsDeclarations(); - - bool writeIncludesInSource(); - bool writeVariableDefinitions(); - bool writeRefsDefinition(); - bool writeSetPaletteColor(); - bool writeVariableInit(); - bool writePxValuesInit(); - bool writeFontFamiliesInit(); - bool writeIconValues(); - bool writeIconsInit(); - - bool collectUniqueValues(); - - const structure::Module &module_; - QString basePath_, baseName_; - const common::ProjectInfo &project_; - std::unique_ptr source_, header_; - bool isPalette_ = false; - - QMap pxValues_; - QMap fontFamilies_; - QMap iconMasks_; // icon file -> index - std::map> paletteIndices_; - -}; - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/main.cpp b/Telegram/SourceFiles/codegen/style/main.cpp deleted file mode 100644 index 27b0cc78c..000000000 --- a/Telegram/SourceFiles/codegen/style/main.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include - -#include "codegen/style/options.h" -#include "codegen/style/processor.h" - -int main(int argc, char *argv[]) { - QCoreApplication app(argc, argv); - - auto options = codegen::style::parseOptions(); - if (options.inputPath.isEmpty()) { - return -1; - } - - codegen::style::Processor processor(options); - return processor.launch(); -} diff --git a/Telegram/SourceFiles/codegen/style/module.cpp b/Telegram/SourceFiles/codegen/style/module.cpp deleted file mode 100644 index 120a8a4f4..000000000 --- a/Telegram/SourceFiles/codegen/style/module.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/style/module.h" - -namespace codegen { -namespace style { -namespace structure { -namespace { - -QString fullNameKey(const FullName &name) { - return name.join('.'); -} - -} // namespace - -Module::Module(const QString &fullpath) : fullpath_(fullpath) { -} - -void Module::addIncluded(std::unique_ptr &&value) { - included_.push_back(std::move(value)); -} - -bool Module::addStruct(const Struct &value) { - if (findStruct(value.name)) { - return false; - } - structsByName_.insert(fullNameKey(value.name), structs_.size()); - structs_.push_back(value); - return true; -} - -const Struct *Module::findStruct(const FullName &name) const { - if (auto result = findStructInModule(name, *this)) { - return result; - } - for (const auto &module : included_) { - if (auto result = module->findStruct(name)) { - return result; - } - } - return nullptr; -} - -bool Module::addVariable(const Variable &value) { - if (findVariable(value.name)) { - return false; - } - variablesByName_.insert(fullNameKey(value.name), variables_.size()); - variables_.push_back(value); - return true; -} - -const Variable *Module::findVariable(const FullName &name, bool *outFromThisModule) const { - if (auto result = findVariableInModule(name, *this)) { - if (outFromThisModule) *outFromThisModule = true; - return result; - } - for (const auto &module : included_) { - if (auto result = module->findVariable(name)) { - if (outFromThisModule) *outFromThisModule = false; - return result; - } - } - return nullptr; -} - -const Struct *Module::findStructInModule(const FullName &name, const Module &module) { - auto index = module.structsByName_.value(fullNameKey(name), -1); - if (index < 0) { - return nullptr; - } - return &module.structs_.at(index); -} - -const Variable *Module::findVariableInModule(const FullName &name, const Module &module) { - auto index = module.variablesByName_.value(fullNameKey(name), -1); - if (index < 0) { - return nullptr; - } - return &module.variables_.at(index); -} - -} // namespace structure -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/module.h b/Telegram/SourceFiles/codegen/style/module.h deleted file mode 100644 index b97916526..000000000 --- a/Telegram/SourceFiles/codegen/style/module.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include "codegen/style/structure_types.h" - -namespace codegen { -namespace style { -namespace structure { - -class Module { -public: - - explicit Module(const QString &fullpath); - - QString filepath() const { - return fullpath_; - } - - void addIncluded(std::unique_ptr &&value); - - bool hasIncludes() const { - return !included_.empty(); - } - template - bool enumIncludes(F functor) const { - for (const auto &module : included_) { - if (!functor(*module)) { - return false; - } - } - return true; - } - - // Returns false if there is a struct with such name already. - bool addStruct(const Struct &value); - // Returns nullptr if there is no such struct in result_ or any of included modules. - const Struct *findStruct(const FullName &name) const; - bool hasStructs() const { - return !structs_.isEmpty(); - } - - template - bool enumStructs(F functor) const { - for (const auto &value : structs_) { - if (!functor(value)) { - return false; - } - } - return true; - } - - // Returns false if there is a variable with such name already. - bool addVariable(const Variable &value); - // Returns nullptr if there is no such variable in result_ or any of included modules. - const Variable *findVariable(const FullName &name, bool *outFromThisModule = nullptr) const; - bool hasVariables() const { - return !variables_.isEmpty(); - } - - template - bool enumVariables(F functor) const { - for (const auto &value : variables_) { - if (!functor(value)) { - return false; - } - } - return true; - } - - explicit operator bool() const { - return !fullpath_.isEmpty(); - } - - static const Struct *findStructInModule(const FullName &name, const Module &module); - static const Variable *findVariableInModule(const FullName &name, const Module &module); - -private: - QString fullpath_; - std::vector> included_; - QList structs_; - QList variables_; - QMap structsByName_; - QMap variablesByName_; - -}; - -} // namespace structure -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/options.cpp b/Telegram/SourceFiles/codegen/style/options.cpp deleted file mode 100644 index 434a6f4d4..000000000 --- a/Telegram/SourceFiles/codegen/style/options.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/style/options.h" - -#include -#include -#include -#include "codegen/common/logging.h" - -namespace codegen { -namespace style { -namespace { - -constexpr int kErrorIncludePathExpected = 901; -constexpr int kErrorOutputPathExpected = 902; -constexpr int kErrorInputPathExpected = 903; -constexpr int kErrorSingleInputPathExpected = 904; -constexpr int kErrorWorkingPathExpected = 905; - -} // namespace - -using common::logError; - -Options parseOptions() { - Options result; - auto args = QCoreApplication::instance()->arguments(); - for (int i = 1, count = args.size(); i < count; ++i) { // skip first - auto &arg = args.at(i); - - // Include paths - if (arg == "-I") { - if (++i == count) { - logError(kErrorIncludePathExpected, "Command Line") << "include path expected after -I"; - return Options(); - } else { - result.includePaths.push_back(args.at(i)); - } - } else if (arg.startsWith("-I")) { - result.includePaths.push_back(arg.mid(2)); - - // Output path - } else if (arg == "-o") { - if (++i == count) { - logError(kErrorOutputPathExpected, "Command Line") << "output path expected after -o"; - return Options(); - } else { - result.outputPath = args.at(i); - } - } else if (arg.startsWith("-o")) { - result.outputPath = arg.mid(2); - - // Working path - } else if (arg == "-w") { - if (++i == count) { - logError(kErrorWorkingPathExpected, "Command Line") << "working path expected after -w"; - return Options(); - } else { - common::logSetWorkingPath(args.at(i)); - } - } else if (arg.startsWith("-w")) { - common::logSetWorkingPath(arg.mid(2)); - - // Input path - } else { - if (result.inputPath.isEmpty()) { - result.inputPath = arg; - } else { - logError(kErrorSingleInputPathExpected, "Command Line") << "only one input path expected"; - return Options(); - } - } - } - if (result.inputPath.isEmpty()) { - logError(kErrorInputPathExpected, "Command Line") << "input path expected"; - return Options(); - } - result.isPalette = (QFileInfo(result.inputPath).suffix() == "palette"); - return result; -} - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/options.h b/Telegram/SourceFiles/codegen/style/options.h deleted file mode 100644 index b25a23c30..000000000 --- a/Telegram/SourceFiles/codegen/style/options.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include - -namespace codegen { -namespace style { - -struct Options { - QStringList includePaths = { "." }; - QString outputPath = "."; - QString inputPath; - bool isPalette = false; -}; - -// Parsing failed if inputPath is empty in the result. -Options parseOptions(); - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/parsed_file.cpp b/Telegram/SourceFiles/codegen/style/parsed_file.cpp deleted file mode 100644 index 3a9c29934..000000000 --- a/Telegram/SourceFiles/codegen/style/parsed_file.cpp +++ /dev/null @@ -1,840 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/style/parsed_file.h" - -#include -#include -#include -#include -#include "codegen/common/basic_tokenized_file.h" -#include "codegen/common/logging.h" - -using BasicToken = codegen::common::BasicTokenizedFile::Token; -using BasicType = BasicToken::Type; - -namespace codegen { -namespace style { - -using structure::logFullName; - -namespace { - -constexpr int kErrorInIncluded = 801; -constexpr int kErrorTypeMismatch = 802; -constexpr int kErrorUnknownField = 803; -constexpr int kErrorIdentifierNotFound = 804; -constexpr int kErrorAlreadyDefined = 805; -constexpr int kErrorBadString = 806; -constexpr int kErrorIconDuplicate = 807; -constexpr int kErrorBadIconModifier = 808; -constexpr int kErrorCyclicDependency = 809; - -QString findInputFile(const Options &options) { - for (const auto &dir : options.includePaths) { - QString tryPath = QDir(dir).absolutePath() + '/' + options.inputPath; - if (QFileInfo(tryPath).exists()) { - return tryPath; - } - } - return options.inputPath; -} - -QString tokenValue(const BasicToken &token) { - if (token.type == BasicType::String) { - return token.value; - } - return token.original.toStringUnchecked(); -} - -bool isValidColor(const QString &str) { - auto len = str.size(); - if (len != 6 && len != 8) { - return false; - } - - for (auto ch : str) { - auto code = ch.unicode(); - if ((code < '0' || code > '9') && (code < 'a' || code > 'f')) { - return false; - } - } - return true; -} - -uchar toGray(uchar r, uchar g, uchar b) { - return qMax(qMin(int(0.21 * r + 0.72 * g + 0.07 * b), 255), 0); -} - -uchar readHexUchar(QChar ch) { - auto code = ch.unicode(); - return (code >= '0' && code <= '9') ? ((code - '0') & 0xFF) : ((code + 10 - 'a') & 0xFF); -} - -uchar readHexUchar(QChar char1, QChar char2) { - return ((readHexUchar(char1) & 0x0F) << 4) | (readHexUchar(char2) & 0x0F); -} - -structure::data::color convertWebColor(const QString &str, const QString &fallback = QString()) { - uchar r = 0, g = 0, b = 0, a = 255; - if (isValidColor(str)) { - r = readHexUchar(str.at(0), str.at(1)); - g = readHexUchar(str.at(2), str.at(3)); - b = readHexUchar(str.at(4), str.at(5)); - if (str.size() == 8) { - a = readHexUchar(str.at(6), str.at(7)); - } - } - return { r, g, b, a, fallback }; -} - -structure::data::color convertIntColor(int r, int g, int b, int a) { - return { uchar(r & 0xFF), uchar(g & 0xFF), uchar(b & 0xFF), uchar(a & 0xFF) }; -} - -std::string logType(const structure::Type &type) { - if (type.tag == structure::TypeTag::Struct) { - return "struct " + logFullName(type.name); - } - static auto builtInTypes = new QMap { - { structure::TypeTag::Int , "int" }, - { structure::TypeTag::Double , "double" }, - { structure::TypeTag::Pixels , "pixels" }, - { structure::TypeTag::String , "string" }, - { structure::TypeTag::Color , "color" }, - { structure::TypeTag::Point , "point" }, - { structure::TypeTag::Size , "size" }, - { structure::TypeTag::Align , "align" }, - { structure::TypeTag::Margins , "margins" }, - { structure::TypeTag::Font , "font" }, - }; - return builtInTypes->value(type.tag, "invalid"); -} - -bool validateAnsiString(const QString &value) { - for (auto ch : value) { - if (ch.unicode() > 127) { - return false; - } - } - return true; -} - -bool validateAlignString(const QString &value) { - return QRegularExpression("^[a-z_]+$").match(value).hasMatch(); -} - -} // namespace - -Modifier GetModifier(const QString &name) { - static QMap modifiers; - if (modifiers.empty()) { - modifiers.insert("invert", [](QImage &image) { - image.invertPixels(); - }); - modifiers.insert("flip_horizontal", [](QImage &image) { - image = image.mirrored(true, false); - }); - modifiers.insert("flip_vertical", [](QImage &image) { - image = image.mirrored(false, true); - }); - } - return modifiers.value(name); -} - -ParsedFile::ParsedFile( - const Options &options, - std::vector includeStack) -: filePath_(findInputFile(options)) -, file_(filePath_) -, options_(options) -, includeStack_(includeStack) { -} - -bool ParsedFile::read() { - if (std::find(begin(includeStack_), end(includeStack_), filePath_) - != end(includeStack_)) { - logError(kErrorCyclicDependency) << "include cycle detected."; - return false; - } else if (!file_.read()) { - return false; - } - - auto absolutePath = QFileInfo(filePath_).absoluteFilePath(); - module_ = std::make_unique(absolutePath); - do { - if (auto startToken = file_.getToken(BasicType::Name)) { - if (tokenValue(startToken) == "using") { - if (auto includedResult = readIncluded()) { - module_->addIncluded(std::move(includedResult)); - continue; - } - } else if (auto braceOpen = file_.getToken(BasicType::LeftBrace)) { - if (auto structResult = readStruct(tokenValue(startToken))) { - if (module_->addStruct(structResult)) { - continue; - } - logError(kErrorAlreadyDefined) << "struct '" << logFullName(structResult.name) << "' already defined"; - break; - } - } else if (auto colonToken = file_.getToken(BasicType::Colon)) { - if (auto variableResult = readVariable(tokenValue(startToken))) { - if (module_->addVariable(variableResult)) { - continue; - } - logError(kErrorAlreadyDefined) << "variable '" << logFullName(variableResult.name) << "' already defined"; - break; - } - } - } - if (file_.atEnd()) { - break; - } - logErrorUnexpectedToken() << "using keyword, or struct definition, or variable definition"; - } while (!failed()); - - if (failed()) { - module_ = nullptr; - } - return !failed(); -} - -common::LogStream ParsedFile::logErrorTypeMismatch() { - return logError(kErrorTypeMismatch) << "type mismatch: "; -} - -ParsedFile::ModulePtr ParsedFile::readIncluded() { - if (auto usingFile = assertNextToken(BasicType::String)) { - if (assertNextToken(BasicType::Semicolon)) { - auto includeStack = includeStack_; - includeStack.push_back(filePath_); - ParsedFile included( - includedOptions(tokenValue(usingFile)), - includeStack); - if (included.read()) { - return included.getResult(); - } else { - logError(kErrorInIncluded) << "error while parsing '" << tokenValue(usingFile).toStdString() << "'"; - } - } - } - return nullptr; -} - -structure::Struct ParsedFile::readStruct(const QString &name) { - if (options_.isPalette) { - logErrorUnexpectedToken() << "unique color variable for the palette"; - return {}; - } - - structure::Struct result = { composeFullName(name) }; - do { - if (auto fieldName = file_.getToken(BasicType::Name)) { - if (auto field = readStructField(tokenValue(fieldName))) { - result.fields.push_back(field); - } - } else if (assertNextToken(BasicType::RightBrace)) { - if (result.fields.isEmpty()) { - logErrorUnexpectedToken() << "at least one field in struct"; - } - break; - } - } while (!failed()); - return result; -} - -structure::Variable ParsedFile::readVariable(const QString &name) { - structure::Variable result = { composeFullName(name) }; - if (auto value = readValue()) { - result.value = value; - if (options_.isPalette && value.type().tag != structure::TypeTag::Color) { - logErrorUnexpectedToken() << "unique color variable for the palette"; - return {}; - } - if (value.type().tag != structure::TypeTag::Struct || !value.copyOf().empty()) { - assertNextToken(BasicType::Semicolon); - result.description = file_.getCurrentLineComment(); - } - } - return result; -} - -structure::StructField ParsedFile::readStructField(const QString &name) { - structure::StructField result = { composeFullName(name) }; - if (auto colonToken = assertNextToken(BasicType::Colon)) { - if (auto type = readType()) { - result.type = type; - assertNextToken(BasicType::Semicolon); - } - } - return result; -} - -structure::Type ParsedFile::readType() { - structure::Type result; - if (auto nameToken = assertNextToken(BasicType::Name)) { - auto name = tokenValue(nameToken); - if (auto builtInType = typeNames_.value(name.toStdString())) { - result = builtInType; - } else { - auto fullName = composeFullName(name); - if (module_->findStruct(fullName)) { - result.tag = structure::TypeTag::Struct; - result.name = fullName; - } else { - logError(kErrorIdentifierNotFound) << "type name '" << logFullName(fullName) << "' not found"; - } - } - } - return result; -} - -structure::Value ParsedFile::readValue() { - if (auto colorValue = readColorValue()) { - return colorValue; - } else if (auto pointValue = readPointValue()) { - return pointValue; - } else if (auto sizeValue = readSizeValue()) { - return sizeValue; - } else if (auto alignValue = readAlignValue()) { - return alignValue; - } else if (auto marginsValue = readMarginsValue()) { - return marginsValue; - } else if (auto fontValue = readFontValue()) { - return fontValue; - } else if (auto iconValue = readIconValue()) { - return iconValue; - } else if (auto numericValue = readNumericValue()) { - return numericValue; - } else if (auto stringValue = readStringValue()) { - return stringValue; - } else if (auto structValue = readStructValue()) { - return structValue; - } else if (auto copyValue = readCopyValue()) { - return copyValue; - } else { - logErrorUnexpectedToken() << "variable value"; - } - return {}; -} - -structure::Value ParsedFile::readStructValue() { - if (auto structName = file_.getToken(BasicType::Name)) { - if (auto result = defaultConstructedStruct(composeFullName(tokenValue(structName)))) { - if (file_.getToken(BasicType::LeftParenthesis)) { - if (!readStructParents(result)) { - return {}; - } - } - if (assertNextToken(BasicType::LeftBrace)) { - readStructValueInner(result); - } - return result; - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::defaultConstructedStruct(const structure::FullName &structName) { - if (auto pattern = module_->findStruct(structName)) { - QList fields; - fields.reserve(pattern->fields.size()); - for (const auto &fieldType : pattern->fields) { - fields.push_back({ - { // variable - fieldType.name, - { fieldType.type, Qt::Uninitialized }, // value - }, - structure::data::field::Status::Uninitialized, // status - }); - } - return { structName, fields }; - } - return {}; -} - -void ParsedFile::applyStructParent(structure::Value &result, const structure::FullName &parentName) { - bool fromTheSameModule = false; - if (auto parent = module_->findVariable(parentName, &fromTheSameModule)) { - if (parent->value.type() != result.type()) { - logErrorTypeMismatch() << "parent '" << logFullName(parentName) << "' has type '" << logType(parent->value.type()) << "' while child value has type " << logType(result.type()); - return; - } - - const auto *srcFields(parent->value.Fields()); - auto *dstFields(result.Fields()); - if (!srcFields || !dstFields) { - logAssert(false) << "struct data check failed"; - return; - } - - logAssert(srcFields->size() == dstFields->size()) << "struct size check failed"; - for (int i = 0, s = srcFields->size(); i != s; ++i) { - const auto &srcField(srcFields->at(i)); - auto &dstField((*dstFields)[i]); - using Status = structure::data::field::Status; - if (srcField.status == Status::Explicit || - dstField.status == Status::Uninitialized) { - const auto &srcValue(srcField.variable.value); - auto &dstValue(dstField.variable.value); - logAssert(srcValue.type() == dstValue.type()) << "struct field type check failed"; - - // Optimization: don't let the style files to contain unnamed inherited - // icons from the other (included) style files, because they will - // duplicate the binary data across different style c++ source files. - // - // Example: - // a.style has "A: Struct { icon: icon { ..file.. } };" and - // b.style has "B: Struct(A) { .. };" with non-overriden icon field. - // Then both style_a.cpp and style_b.cpp will contain binary data of "file". - if (!fromTheSameModule - && srcValue.type().tag == structure::TypeTag::Icon - && !srcValue.Icon().parts.empty() - && srcValue.copyOf().isEmpty()) { - logError(kErrorIconDuplicate) << "an unnamed icon field '" << logFullName(srcField.variable.name) << "' is inherited from parent '" << logFullName(parentName) << "'"; - return; - } - dstValue = srcValue; - dstField.status = Status::Implicit; - } - } - } else { - logError(kErrorIdentifierNotFound) << "parent '" << logFullName(parentName) << "' not found"; - } -} - -bool ParsedFile::readStructValueInner(structure::Value &result) { - do { - if (auto fieldName = file_.getToken(BasicType::Name)) { - if (!assertNextToken(BasicType::Colon)) { - return false; - } - - if (auto field = readVariable(tokenValue(fieldName))) { - if (!assignStructField(result, field)) { - return false; - } - } - } else if (assertNextToken(BasicType::RightBrace)) { - return true; - } - } while (!failed()); - return false; -} - -bool ParsedFile::assignStructField(structure::Value &result, const structure::Variable &field) { - auto *fields = result.Fields(); - if (!fields) { - logAssert(false) << "struct data check failed"; - return false; - } - for (auto &already : *fields) { - if (already.variable.name == field.name) { - if (already.variable.value.type() == field.value.type()) { - already.variable.value = field.value; - already.status = structure::data::field::Status::Explicit; - return true; - } else { - logErrorTypeMismatch() << "field '" << logFullName(already.variable.name) << "' has type '" << logType(already.variable.value.type()) << "' while value has type '" << logType(field.value.type()) << "'"; - return false; - } - } - } - logError(kErrorUnknownField) << "field '" << logFullName(field.name) << "' was not found in struct of type '" << logType(result.type()) << "'"; - return false; -} - -bool ParsedFile::readStructParents(structure::Value &result) { - do { - if (auto parentName = assertNextToken(BasicType::Name)) { - applyStructParent(result, composeFullName(tokenValue(parentName))); - if (file_.getToken(BasicType::RightParenthesis)) { - return true; - } else { - assertNextToken(BasicType::Comma); - } - } else { - logErrorUnexpectedToken() << "struct variable parent"; - } - } while (!failed()); - return false; -} - -structure::Value ParsedFile::readPositiveValue() { - auto numericToken = file_.getAnyToken(); - if (numericToken.type == BasicType::Int) { - return { structure::TypeTag::Int, tokenValue(numericToken).toInt() }; - } else if (numericToken.type == BasicType::Double) { - return { structure::TypeTag::Double, tokenValue(numericToken).toDouble() }; - } else if (numericToken.type == BasicType::Name) { - auto value = tokenValue(numericToken); - auto match = QRegularExpression("^\\d+px$").match(value); - if (match.hasMatch()) { - return { structure::TypeTag::Pixels, value.mid(0, value.size() - 2).toInt() }; - } - } - file_.putBack(); - return {}; -} - -structure::Value ParsedFile::readNumericValue() { - if (auto value = readPositiveValue()) { - return value; - } else if (auto minusToken = file_.getToken(BasicType::Minus)) { - if (auto positiveValue = readNumericValue()) { - return { positiveValue.type().tag, -positiveValue.Int() }; - } - logErrorUnexpectedToken() << "numeric value"; - } - return {}; -} - -structure::Value ParsedFile::readStringValue() { - if (auto stringToken = file_.getToken(BasicType::String)) { - auto value = tokenValue(stringToken); - if (validateAnsiString(value)) { - return { structure::TypeTag::String, stringToken.value.toStdString() }; - } - logError(kErrorBadString) << "unicode symbols are not supported"; - } - return {}; -} - -structure::Value ParsedFile::readColorValue() { - if (auto numberSign = file_.getToken(BasicType::Number)) { - if (options_.isPalette) { - auto color = file_.getAnyToken(); - if (color.type == BasicType::Int || color.type == BasicType::Name) { - auto chars = tokenValue(color).toLower(); - if (isValidColor(chars)) { - if (auto fallbackSeparator = file_.getToken(BasicType::Or)) { - if (options_.isPalette) { - if (auto fallbackName = file_.getToken(BasicType::Name)) { - structure::FullName name = { tokenValue(fallbackName) }; - if (auto variable = module_->findVariableInModule(name, *module_)) { - return { convertWebColor(chars, tokenValue(fallbackName)) }; - } else { - logError(kErrorIdentifierNotFound) << "fallback color name"; - } - } else { - logErrorUnexpectedToken() << "fallback color name"; - } - } else { - logErrorUnexpectedToken() << "';', color fallbacks are only allowed in palette module"; - } - } else { - return { convertWebColor(chars) }; - } - } - } else { - logErrorUnexpectedToken() << "color value in #ccc, #ccca, #cccccc or #ccccccaa format"; - } - } else { - logErrorUnexpectedToken() << "color value alias, unique color values are only allowed in palette module"; - } - } else if (auto transparentName = file_.getToken(BasicType::Name)) { - if (tokenValue(transparentName) == "transparent") { - return { structure::data::color { 255, 255, 255, 0 } }; - } - file_.putBack(); - } - - return {}; -} - -structure::Value ParsedFile::readPointValue() { - if (auto font = file_.getToken(BasicType::Name)) { - if (tokenValue(font) == "point") { - assertNextToken(BasicType::LeftParenthesis); - - auto x = readNumericOrNumericCopyValue(); assertNextToken(BasicType::Comma); - auto y = readNumericOrNumericCopyValue(); - if (x.type().tag != structure::TypeTag::Pixels || - y.type().tag != structure::TypeTag::Pixels) { - logErrorTypeMismatch() << "expected two px values for the point"; - } - - assertNextToken(BasicType::RightParenthesis); - - return { structure::data::point { x.Int(), y.Int() } }; - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::readSizeValue() { - if (auto font = file_.getToken(BasicType::Name)) { - if (tokenValue(font) == "size") { - assertNextToken(BasicType::LeftParenthesis); - - auto w = readNumericOrNumericCopyValue(); assertNextToken(BasicType::Comma); - auto h = readNumericOrNumericCopyValue(); - if (w.type().tag != structure::TypeTag::Pixels || - h.type().tag != structure::TypeTag::Pixels) { - logErrorTypeMismatch() << "expected two px values for the size"; - } - - assertNextToken(BasicType::RightParenthesis); - - return { structure::data::size { w.Int(), h.Int() } }; - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::readAlignValue() { - if (auto font = file_.getToken(BasicType::Name)) { - if (tokenValue(font) == "align") { - assertNextToken(BasicType::LeftParenthesis); - - auto align = tokenValue(assertNextToken(BasicType::Name)); - - assertNextToken(BasicType::RightParenthesis); - - if (validateAlignString(align)) { - return { structure::TypeTag::Align, align.toStdString() }; - } else { - logError(kErrorBadString) << "bad align string"; - } - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::readMarginsValue() { - if (auto font = file_.getToken(BasicType::Name)) { - if (tokenValue(font) == "margins") { - assertNextToken(BasicType::LeftParenthesis); - - auto l = readNumericOrNumericCopyValue(); assertNextToken(BasicType::Comma); - auto t = readNumericOrNumericCopyValue(); assertNextToken(BasicType::Comma); - auto r = readNumericOrNumericCopyValue(); assertNextToken(BasicType::Comma); - auto b = readNumericOrNumericCopyValue(); - if (l.type().tag != structure::TypeTag::Pixels || - t.type().tag != structure::TypeTag::Pixels || - r.type().tag != structure::TypeTag::Pixels || - b.type().tag != structure::TypeTag::Pixels) { - logErrorTypeMismatch() << "expected four px values for the margins"; - } - - assertNextToken(BasicType::RightParenthesis); - - return { structure::data::margins { l.Int(), t.Int(), r.Int(), b.Int() } }; - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::readFontValue() { - if (auto font = file_.getToken(BasicType::Name)) { - if (tokenValue(font) == "font") { - assertNextToken(BasicType::LeftParenthesis); - - int flags = 0; - structure::Value family, size; - do { - if (auto formatToken = file_.getToken(BasicType::Name)) { - if (tokenValue(formatToken) == "bold") { - flags |= structure::data::font::Bold; - } else if (tokenValue(formatToken) == "italic") { - flags |= structure::data::font::Italic; - } else if (tokenValue(formatToken) == "underline") { - flags |= structure::data::font::Underline; - } else { - file_.putBack(); - } - } - if (auto familyValue = readStringOrStringCopyValue()) { - family = familyValue; - } else if (auto sizeValue = readNumericOrNumericCopyValue()) { - size = sizeValue; - } else if (file_.getToken(BasicType::RightParenthesis)) { - break; - } else { - logErrorUnexpectedToken() << "font family, font size or ')'"; - } - } while (!failed()); - - if (size.type().tag != structure::TypeTag::Pixels) { - logErrorTypeMismatch() << "px value for the font size expected"; - } - return { structure::data::font { family.String(), size.Int(), flags } }; - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::readIconValue() { - if (auto font = file_.getToken(BasicType::Name)) { - if (tokenValue(font) == "icon") { - std::vector parts; - if (file_.getToken(BasicType::LeftBrace)) { // complex icon - do { - if (file_.getToken(BasicType::RightBrace)) { - break; - } else if (file_.getToken(BasicType::LeftBrace)) { - if (auto part = readMonoIconFields()) { - assertNextToken(BasicType::RightBrace); - parts.push_back(part); - file_.getToken(BasicType::Comma); - continue; - } - return {}; - } else { - logErrorUnexpectedToken() << "icon part or '}'"; - return {}; - } - } while (true); - - } else if (file_.getToken(BasicType::LeftParenthesis)) { // short icon - if (auto theOnlyPart = readMonoIconFields()) { - assertNextToken(BasicType::RightParenthesis); - parts.push_back(theOnlyPart); - } - } - - return { structure::data::icon { parts } }; - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::readCopyValue() { - if (auto copyName = file_.getToken(BasicType::Name)) { - structure::FullName name = { tokenValue(copyName) }; - if (auto variable = module_->findVariable(name)) { - return variable->value.makeCopy(variable->name); - } - file_.putBack(); - } - return {}; -} - -structure::Value ParsedFile::readNumericOrNumericCopyValue() { - if (auto result = readNumericValue()) { - return result; - } else if (auto copy = readCopyValue()) { - auto type = copy.type().tag; - if (type == structure::TypeTag::Int - || type == structure::TypeTag::Double - || type == structure::TypeTag::Pixels) { - return copy; - } else { - file_.putBack(); - } - } - return {}; -} - -structure::Value ParsedFile::readStringOrStringCopyValue() { - if (auto result = readStringValue()) { - return result; - } else if (auto copy = readCopyValue()) { - auto type = copy.type().tag; - if (type == structure::TypeTag::String) { - return copy; - } else { - file_.putBack(); - } - } - return {}; -} - -structure::data::monoicon ParsedFile::readMonoIconFields() { - structure::data::monoicon result; - result.filename = readMonoIconFilename(); - if (!result.filename.isEmpty() && file_.getToken(BasicType::Comma)) { - if (auto color = readValue()) { - if (color.type().tag == structure::TypeTag::Color) { - result.color = color; - if (file_.getToken(BasicType::Comma)) { - if (auto offset = readValue()) { - if (offset.type().tag == structure::TypeTag::Point) { - result.offset = offset; - } else { - logErrorUnexpectedToken() << "icon offset"; - } - } else { - logErrorUnexpectedToken() << "icon offset"; - } - } else { - result.offset = { structure::data::point { 0, 0 } }; - } - } else { - logErrorUnexpectedToken() << "icon color"; - } - } else { - logErrorUnexpectedToken() << "icon color"; - } - } - return result; -} - -QString ParsedFile::readMonoIconFilename() { - if (auto filename = readValue()) { - if (filename.type().tag == structure::TypeTag::String) { - auto fullpath = QString::fromStdString(filename.String()); - auto pathAndModifiers = fullpath.split('-'); - auto filepath = pathAndModifiers[0]; - auto modifiers = pathAndModifiers.mid(1); - for (auto modifierName : modifiers) { - if (!GetModifier(modifierName)) { - logError(kErrorBadIconModifier) << "unknown modifier: " << modifierName.toStdString(); - return QString(); - } - } - for (auto &path : options_.includePaths) { - QFileInfo fileinfo(path + '/' + filepath + ".png"); - if (fileinfo.exists()) { - return path + '/' + fullpath; - } - } - for (auto &path : options_.includePaths) { - QFileInfo fileinfo(path + "/icons/" + filepath + ".png"); - if (fileinfo.exists()) { - return path + "/icons/" + fullpath; - } - } - logError(common::kErrorFileNotFound) << "could not open icon file '" << filename.String() << "'"; - } else if (filename.type().tag == structure::TypeTag::Size) { - return QString("size://%1,%2").arg(filename.Size().width).arg(filename.Size().height); - } - } - logErrorUnexpectedToken() << "icon filename or rect size"; - return QString(); -} - -BasicToken ParsedFile::assertNextToken(BasicToken::Type type) { - auto result = file_.getToken(type); - if (!result) { - logErrorUnexpectedToken() << type; - } - return result; -} - -Options ParsedFile::includedOptions(const QString &filepath) { - auto result = options_; - result.inputPath = filepath; - result.includePaths[0] = QFileInfo(filePath_).dir().absolutePath(); - result.isPalette = (QFileInfo(filepath).suffix() == "palette"); - return result; -} - -// Compose context-dependent full name. -structure::FullName ParsedFile::composeFullName(const QString &name) { - return { name }; -} - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/parsed_file.h b/Telegram/SourceFiles/codegen/style/parsed_file.h deleted file mode 100644 index 6b95d1ffb..000000000 --- a/Telegram/SourceFiles/codegen/style/parsed_file.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include "codegen/common/basic_tokenized_file.h" -#include "codegen/style/options.h" -#include "codegen/style/module.h" - -namespace codegen { -namespace style { - -using Modifier = std::function; -Modifier GetModifier(const QString &name); - -// Parses an input file to the internal struct. -class ParsedFile { -public: - explicit ParsedFile( - const Options &options, - std::vector includeStack = {}); - ParsedFile(const ParsedFile &other) = delete; - ParsedFile &operator=(const ParsedFile &other) = delete; - - bool read(); - - using ModulePtr = std::unique_ptr; - ModulePtr getResult() { - return std::move(module_); - } - -private: - bool failed() const { - return failed_ || file_.failed(); - } - - // Log error to std::cerr with 'code' at the current position in file. - common::LogStream logError(int code) { - failed_ = true; - return file_.logError(code); - } - common::LogStream logErrorUnexpectedToken() { - failed_ = true; - return file_.logErrorUnexpectedToken(); - } - common::LogStream logErrorTypeMismatch(); - common::LogStream logAssert(bool assertion) { - if (!assertion) { - return logError(common::kErrorInternal) << "internal - "; - } - return common::LogStream(common::LogStream::Null); - } - - // Helper methods for context-dependent reading. - ModulePtr readIncluded(); - structure::Struct readStruct(const QString &name); - structure::Variable readVariable(const QString &name); - - structure::StructField readStructField(const QString &name); - structure::Type readType(); - structure::Value readValue(); - - structure::Value readStructValue(); - structure::Value defaultConstructedStruct(const structure::FullName &name); - void applyStructParent(structure::Value &result, const structure::FullName &parentName); - bool readStructValueInner(structure::Value &result); - bool assignStructField(structure::Value &result, const structure::Variable &field); - bool readStructParents(structure::Value &result); - - // Simple methods for reading value types. - structure::Value readPositiveValue(); - structure::Value readNumericValue(); - structure::Value readStringValue(); - structure::Value readColorValue(); - structure::Value readPointValue(); - structure::Value readSizeValue(); - structure::Value readAlignValue(); - structure::Value readMarginsValue(); - structure::Value readFontValue(); - structure::Value readIconValue(); - structure::Value readCopyValue(); - - structure::Value readNumericOrNumericCopyValue(); - structure::Value readStringOrStringCopyValue(); - - structure::data::monoicon readMonoIconFields(); - QString readMonoIconFilename(); - - // Read next token and fire unexpected token error if it is not of "type". - using BasicToken = common::BasicTokenizedFile::Token; - BasicToken assertNextToken(BasicToken::Type type); - - // Look through include directories in options_ and find absolute include path. - Options includedOptions(const QString &filepath); - - // Compose context-dependent full name. - structure::FullName composeFullName(const QString &name); - - QString filePath_; - common::BasicTokenizedFile file_; - Options options_; - bool failed_ = false; - ModulePtr module_; - - std::vector includeStack_; - - QMap typeNames_ = { - { "int" , { structure::TypeTag::Int } }, - { "double" , { structure::TypeTag::Double } }, - { "pixels" , { structure::TypeTag::Pixels } }, - { "string" , { structure::TypeTag::String } }, - { "color" , { structure::TypeTag::Color } }, - { "point" , { structure::TypeTag::Point } }, - { "size" , { structure::TypeTag::Size } }, - { "align" , { structure::TypeTag::Align } }, - { "margins" , { structure::TypeTag::Margins } }, - { "font" , { structure::TypeTag::Font } }, - { "icon" , { structure::TypeTag::Icon } }, - }; - -}; - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/processor.cpp b/Telegram/SourceFiles/codegen/style/processor.cpp deleted file mode 100644 index 2c1bc1df8..000000000 --- a/Telegram/SourceFiles/codegen/style/processor.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/style/processor.h" - -#include -#include -#include "codegen/common/cpp_file.h" -#include "codegen/style/parsed_file.h" -#include "codegen/style/generator.h" - -namespace codegen { -namespace style { -namespace { - -constexpr int kErrorCantWritePath = 821; - -QString destFileBaseName(const structure::Module &module) { - return "style_" + QFileInfo(module.filepath()).baseName(); -} - -} // namespace - -Processor::Processor(const Options &options) -: parser_(std::make_unique(options)) -, options_(options) { -} - -int Processor::launch() { - if (!parser_->read()) { - return -1; - } - - auto module = parser_->getResult(); - if (!write(*module)) { - return -1; - } - - return 0; -} - -bool Processor::write(const structure::Module &module) const { - bool forceReGenerate = false; - QDir dir(options_.outputPath); - if (!dir.mkpath(".")) { - common::logError(kErrorCantWritePath, "Command Line") << "can not open path for writing: " << dir.absolutePath().toStdString(); - return false; - } - - QFileInfo srcFile(module.filepath()); - QString dstFilePath = dir.absolutePath() + '/' + (options_.isPalette ? "palette" : destFileBaseName(module)); - - common::ProjectInfo project = { - "codegen_style", - srcFile.fileName(), - forceReGenerate - }; - - Generator generator(module, dstFilePath, project, options_.isPalette); - if (!generator.writeHeader()) { - return false; - } - if (!generator.writeSource()) { - return false; - } - return true; -} - -Processor::~Processor() = default; - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/processor.h b/Telegram/SourceFiles/codegen/style/processor.h deleted file mode 100644 index 8d4d35b97..000000000 --- a/Telegram/SourceFiles/codegen/style/processor.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include "codegen/style/options.h" - -namespace codegen { -namespace style { -namespace structure { -class Module; -} // namespace structure -class ParsedFile; - -// Walks through a file, parses it and parses dependency files if necessary. -// Uses Generator class to produce the final output. -class Processor { -public: - explicit Processor(const Options &options); - Processor(const Processor &other) = delete; - Processor &operator=(const Processor &other) = delete; - - // Returns 0 on success. - int launch(); - - ~Processor(); - -private: - bool write(const structure::Module &module) const; - - std::unique_ptr parser_; - const Options &options_; - -}; - -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/structure_types.cpp b/Telegram/SourceFiles/codegen/style/structure_types.cpp deleted file mode 100644 index 9ce705408..000000000 --- a/Telegram/SourceFiles/codegen/style/structure_types.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "codegen/style/structure_types.h" - -namespace codegen { -namespace style { -namespace structure { - -struct Value::DataTypes { - class TInt : public DataBase { - public: - TInt(int value) : value_(value) { - } - int Int() const override { return value_; } - - private: - int value_; - - }; - - class TDouble : public DataBase { - public: - TDouble(double value) : value_(value) { - } - double Double() const override { return value_; } - - private: - double value_; - - }; - - class TString : public DataBase { - public: - TString(std::string value) : value_(value) { - } - std::string String() const override { return value_; } - - private: - std::string value_; - - }; - - class TPoint : public DataBase { - public: - TPoint(data::point value) : value_(value) { - } - data::point Point() const override { return value_; } - - private: - data::point value_; - - }; - - class TSize : public DataBase { - public: - TSize(data::size value) : value_(value) { - } - data::size Size() const override { return value_; } - - private: - data::size value_; - - }; - - class TColor : public DataBase { - public: - TColor(data::color value) : value_(value) { - } - data::color Color() const override { return value_; } - - private: - data::color value_; - - }; - - class TMargins : public DataBase { - public: - TMargins(data::margins value) : value_(value) { - } - data::margins Margins() const override { return value_; } - - private: - data::margins value_; - - }; - - class TFont : public DataBase { - public: - TFont(data::font value) : value_(value) { - } - data::font Font() const override { return value_; } - - private: - data::font value_; - - }; - - class TIcon : public DataBase { - public: - TIcon(data::icon value) : value_(value) { - } - data::icon Icon() const override { return value_; } - - private: - data::icon value_; - - }; - - class TFields : public DataBase { - public: - TFields(data::fields value) : value_(value) { - } - const data::fields *Fields() const override { return &value_; } - data::fields *Fields() override { return &value_; } - - private: - data::fields value_; - - }; -}; - -Value::Value() : Value(TypeTag::Invalid, std::make_shared()) { -} - -Value::Value(data::point value) : Value(TypeTag::Point, std::make_shared(value)) { -} - -Value::Value(data::size value) : Value(TypeTag::Size, std::make_shared(value)) { -} - -Value::Value(data::color value) : Value(TypeTag::Color, std::make_shared(value)) { -} - -Value::Value(data::margins value) : Value(TypeTag::Margins, std::make_shared(value)) { -} - -Value::Value(data::font value) : Value(TypeTag::Font, std::make_shared(value)) { -} - -Value::Value(data::icon value) : Value(TypeTag::Icon, std::make_shared(value)) { -} - -Value::Value(const FullName &type, data::fields value) -: type_ { TypeTag::Struct, type } -, data_(std::make_shared(value)) { -} - -Value::Value(TypeTag type, double value) : Value(type, std::make_shared(value)) { - if (type_.tag != TypeTag::Double) { - type_.tag = TypeTag::Invalid; - data_ = std::make_shared(); - } -} - -Value::Value(TypeTag type, int value) : Value(type, std::make_shared(value)) { - if (type_.tag != TypeTag::Int && type_.tag != TypeTag::Pixels) { - type_.tag = TypeTag::Invalid; - data_ = std::make_shared(); - } -} - -Value::Value(TypeTag type, std::string value) : Value(type, std::make_shared(value)) { - if (type_.tag != TypeTag::String && - type_.tag != TypeTag::Align) { - type_.tag = TypeTag::Invalid; - data_ = std::make_shared(); - } -} - -Value::Value(Type type, Qt::Initialization) : type_(type) { - switch (type_.tag) { - case TypeTag::Invalid: data_ = std::make_shared(); break; - case TypeTag::Int: data_ = std::make_shared(0); break; - case TypeTag::Double: data_ = std::make_shared(0.); break; - case TypeTag::Pixels: data_ = std::make_shared(0); break; - case TypeTag::String: data_ = std::make_shared(""); break; - case TypeTag::Color: data_ = std::make_shared(data::color { 0, 0, 0, 255 }); break; - case TypeTag::Point: data_ = std::make_shared(data::point { 0, 0 }); break; - case TypeTag::Size: data_ = std::make_shared(data::size { 0, 0 }); break; - case TypeTag::Align: data_ = std::make_shared("topleft"); break; - case TypeTag::Margins: data_ = std::make_shared(data::margins { 0, 0, 0, 0 }); break; - case TypeTag::Font: data_ = std::make_shared(data::font { "", 13, 0 }); break; - case TypeTag::Icon: data_ = std::make_shared(data::icon {}); break; - case TypeTag::Struct: data_ = std::make_shared(data::fields {}); break; - } -} - -Value::Value(TypeTag type, std::shared_ptr &&data) : type_ { type }, data_(std::move(data)) { -} - -} // namespace structure -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/codegen/style/structure_types.h b/Telegram/SourceFiles/codegen/style/structure_types.h deleted file mode 100644 index de6392c06..000000000 --- a/Telegram/SourceFiles/codegen/style/structure_types.h +++ /dev/null @@ -1,230 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include -#include -#include -#include -#include - -namespace codegen { -namespace style { -namespace structure { - -// List of names, like overview.document.bg -using FullName = QStringList; -inline std::string logFullName(const FullName &name) { - return name.join('.').toStdString(); -} - -struct Variable; -class Value; - -enum class TypeTag { - Invalid, - Int, - Double, - Pixels, - String, - Color, - Point, - Size, - Align, - Margins, - Font, - Icon, - Struct, -}; - -struct Type { - TypeTag tag; - FullName name; // only for type == ClassType::Struct - - explicit operator bool() const { - return (tag != TypeTag::Invalid); - } -}; -inline bool operator==(const Type &a, const Type &b) { - return (a.tag == b.tag) && (a.name == b.name); -} -inline bool operator!=(const Type &a, const Type &b) { - return !(a == b); -} - -namespace data { - -struct point { - int x, y; -}; - -struct size { - int width, height; -}; - -struct color { - uchar red, green, blue, alpha; - QString fallback; -}; - -struct margins { - int left, top, right, bottom; -}; - -struct font { - enum Flag { - Bold = 0x01, - Italic = 0x02, - Underline = 0x04, - }; - std::string family; - int size; - int flags; -}; - -struct monoicon; -struct icon { - std::vector parts; -}; - -struct field; // defined after Variable is defined -using fields = QList; - -} // namespace data - -class Value { -public: - Value(); - Value(data::point value); - Value(data::size value); - Value(data::color value); - Value(data::margins value); - Value(data::font value); - Value(data::icon value); - Value(const FullName &type, data::fields value); - - // Can be only double. - Value(TypeTag type, double value); - - // Can be int / pixels. - Value(TypeTag type, int value); - - // Can be string / align. - Value(TypeTag type, std::string value); - - // Default constructed value (uninitialized). - Value(Type type, Qt::Initialization); - - Type type() const { return type_; } - int Int() const { return data_->Int(); } - double Double() const { return data_->Double(); } - std::string String() const { return data_->String(); } - data::point Point() const { return data_->Point(); } - data::size Size() const { return data_->Size(); }; - data::color Color() const { return data_->Color(); }; - data::margins Margins() const { return data_->Margins(); }; - data::font Font() const { return data_->Font(); }; - data::icon Icon() const { return data_->Icon(); }; - const data::fields *Fields() const { return data_->Fields(); }; - data::fields *Fields() { return data_->Fields(); }; - - explicit operator bool() const { - return type_.tag != TypeTag::Invalid; - } - - Value makeCopy(const FullName ©Of) const { - Value result(*this); - result.copyOf_ = copyOf; - return result; - } - - const FullName ©Of() const { - return copyOf_; - } - -private: - class DataBase { - public: - virtual int Int() const { return 0; } - virtual double Double() const { return 0.; } - virtual std::string String() const { return std::string(); } - virtual data::point Point() const { return {}; }; - virtual data::size Size() const { return {}; }; - virtual data::color Color() const { return {}; }; - virtual data::margins Margins() const { return {}; }; - virtual data::font Font() const { return {}; }; - virtual data::icon Icon() const { return {}; }; - virtual const data::fields *Fields() const { return nullptr; }; - virtual data::fields *Fields() { return nullptr; }; - virtual ~DataBase() { - } - }; - struct DataTypes; - - Value(TypeTag type, std::shared_ptr &&data); - - Type type_; - std::shared_ptr data_; - - FullName copyOf_; // for copies of existing named values - -}; - -struct Variable { - FullName name; - Value value; - QString description; - - explicit operator bool() const { - return !name.isEmpty(); - } -}; - -namespace data { -struct field { - enum class Status { - Uninitialized, - Implicit, - Explicit - }; - Variable variable; - Status status; -}; - -struct monoicon { - QString filename; - Value color; - Value offset; - - explicit operator bool() const { - return !filename.isEmpty(); - } -}; -} // namespace data - -struct StructField { - FullName name; - Type type; - - explicit operator bool() const { - return !name.isEmpty(); - } -}; - -struct Struct { - FullName name; - QList fields; - - explicit operator bool() const { - return !name.isEmpty(); - } -}; - -} // namespace structure -} // namespace style -} // namespace codegen diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index e1ca87a67..e7efbd9f9 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -183,7 +183,7 @@ constexpr auto ApiHash = "344583e45741c457fe1862106095a5eb"; #if (TDESKTOP_ALPHA_VERSION != 0) // Private key for downloading closed alphas. -#include "../../../TelegramPrivate/alpha_private.h" +#include "../../../DesktopPrivate/alpha_private.h" #else static const char *AlphaPrivateKey = ""; diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index 7216094be..118e46d65 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/local_url_handlers.h" #include "core/launcher.h" #include "core/kotato_settings.h" -#include "core/core_ui_integration.h" +#include "core/ui_integration.h" #include "chat_helpers/emoji_keywords.h" #include "storage/localstorage.h" #include "platform/platform_specific.h" diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index 8ee6961c3..6129e71bd 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -16,7 +16,6 @@ class MainWindow; class MainWidget; class FileUploader; class Translator; -class BoxContent; namespace Storage { class Databases; @@ -43,6 +42,7 @@ namespace Ui { namespace Animations { class Manager; } // namespace Animations +class BoxContent; } // namespace Ui namespace MTP { @@ -220,10 +220,6 @@ public: void call_handleDelayedPeerUpdates(); void call_handleObservables(); - void callDelayed(int duration, FnMut &&lambda) { - _callDelayedTimer.call(duration, std::move(lambda)); - } - protected: bool eventFilter(QObject *object, QEvent *event) override; @@ -273,7 +269,7 @@ private: const std::unique_ptr _emojiKeywords; std::unique_ptr _translator; base::Observable _passcodedChanged; - QPointer _badProxyDisableBox; + QPointer _badProxyDisableBox; const std::unique_ptr _audio; const QImage _logo; @@ -283,7 +279,6 @@ private: rpl::event_stream _termsLockChanges; std::unique_ptr _termsLock; - base::DelayedCallTimer _callDelayedTimer; base::Timer _saveSettingsTimer; struct LeaveSubscription { diff --git a/Telegram/SourceFiles/core/base_integration.cpp b/Telegram/SourceFiles/core/base_integration.cpp new file mode 100644 index 000000000..5228b988a --- /dev/null +++ b/Telegram/SourceFiles/core/base_integration.cpp @@ -0,0 +1,38 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "core/base_integration.h" + +#include "core/sandbox.h" +#include "core/crash_reports.h" + +namespace Core { + +BaseIntegration::BaseIntegration(int argc, char *argv[]) +: Integration(argc, argv) { +} + +void BaseIntegration::enterFromEventLoop(FnMut &&method) { + Core::Sandbox::Instance().customEnterFromEventLoop( + std::move(method)); +} + +void BaseIntegration::logMessage(const QString &message) { +#ifdef DEBUG_LOG + DEBUG_LOG((message)); +#endif // DEBUG_LOG +} + +void BaseIntegration::logAssertionViolation(const QString &info) { +#ifdef LOG + LOG(("Assertion Failed! ") + info); +#endif // LOG + + CrashReports::SetAnnotation("Assertion", info); +} + +} // namespace Core diff --git a/Telegram/SourceFiles/core/base_integration.h b/Telegram/SourceFiles/core/base_integration.h new file mode 100644 index 000000000..11652830e --- /dev/null +++ b/Telegram/SourceFiles/core/base_integration.h @@ -0,0 +1,24 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "base/integration.h" + +namespace Core { + +class BaseIntegration : public base::Integration { +public: + BaseIntegration(int argc, char *argv[]); + + void enterFromEventLoop(FnMut &&method) override; + void logMessage(const QString &message) override; + void logAssertionViolation(const QString &info) override; + +}; + +} // namespace Core diff --git a/Telegram/SourceFiles/core/changelogs.cpp b/Telegram/SourceFiles/core/changelogs.cpp index e38c56735..6ab48f095 100644 --- a/Telegram/SourceFiles/core/changelogs.cpp +++ b/Telegram/SourceFiles/core/changelogs.cpp @@ -60,6 +60,10 @@ std::map BetaLogs() { "\xE2\x80\xA2 Update your theme for all its users when you change something.\n" }, + { + 1009000, + "\xE2\x80\xA2 System spellchecker on Windows 8+ and macOS 10.12+.\n" + }, }; }; diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index 32828252a..e98d6a5e6 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -58,7 +58,7 @@ void HiddenUrlClickHandler::Open(QString url, QVariant context) { tr::lng_open_this_link(tr::now) + qsl("\n\n") + displayUrl, tr::lng_open_link(tr::now), [=] { Ui::hideLayer(); open(); }), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } else { open(); } diff --git a/Telegram/SourceFiles/core/crash_reports.cpp b/Telegram/SourceFiles/core/crash_reports.cpp index b0e722ae1..3d9f545d3 100644 --- a/Telegram/SourceFiles/core/crash_reports.cpp +++ b/Telegram/SourceFiles/core/crash_reports.cpp @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/crash_reports.h" #include "platform/platform_specific.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "core/launcher.h" #include @@ -328,8 +328,8 @@ QString PlatformString() { return qsl("Windows"); } else if (Platform::IsMacStoreBuild()) { return qsl("MacAppStore"); - } else if (Platform::IsMacOldBuild()) { - return qsl("MacOSold"); + } else if (Platform::IsOSXBuild()) { + return qsl("OSX"); } else if (Platform::IsMac()) { return qsl("MacOS"); } else if (Platform::IsLinux32Bit()) { diff --git a/Telegram/SourceFiles/core/crash_reports.h b/Telegram/SourceFiles/core/crash_reports.h index 5e60afd0e..665c431f9 100644 --- a/Telegram/SourceFiles/core/crash_reports.h +++ b/Telegram/SourceFiles/core/crash_reports.h @@ -57,24 +57,3 @@ void StartCatching(not_null launcher); void FinishCatching(); } // namespace CrashReports - -namespace base { -namespace assertion { - -inline void log(const char *message, const char *file, int line) { - const auto info = QStringLiteral("%1 %2:%3" - ).arg(message - ).arg(file - ).arg(line - ); - const auto entry = QStringLiteral("Assertion Failed! ") + info; - -#ifdef LOG - LOG((entry)); -#endif // LOG - - CrashReports::SetAnnotation("Assertion", info); -} - -} // namespace assertion -} // namespace base diff --git a/Telegram/SourceFiles/core/event_filter.cpp b/Telegram/SourceFiles/core/event_filter.cpp deleted file mode 100644 index 37e3e7cf3..000000000 --- a/Telegram/SourceFiles/core/event_filter.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "core/event_filter.h" - -namespace Core { - -EventFilter::EventFilter( - not_null parent, - not_null object, - Fn)> filter) -: QObject(parent) -, _filter(std::move(filter)) { - object->installEventFilter(this); -} - -bool EventFilter::eventFilter(QObject *watched, QEvent *event) { - return (_filter(event) == Result::Cancel); -} - -not_null InstallEventFilter( - not_null object, - Fn)> filter) { - return InstallEventFilter(object, object, std::move(filter)); -} - -not_null InstallEventFilter( - not_null context, - not_null object, - Fn)> filter) { - return new EventFilter(context, object, std::move(filter)); -} - -} // namespace Core diff --git a/Telegram/SourceFiles/core/event_filter.h b/Telegram/SourceFiles/core/event_filter.h deleted file mode 100644 index d6c847af2..000000000 --- a/Telegram/SourceFiles/core/event_filter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -namespace Core { - -class EventFilter : public QObject { -public: - enum Result { - Continue, - Cancel, - }; - - EventFilter( - not_null parent, - not_null object, - Fn)> filter); - -protected: - bool eventFilter(QObject *watched, QEvent *event); - -private: - Fn)> _filter; - -}; - -not_null InstallEventFilter( - not_null object, - Fn)> filter); - -not_null InstallEventFilter( - not_null context, - not_null object, - Fn)> filter); - -} // namespace Core diff --git a/Telegram/SourceFiles/core/file_utilities.cpp b/Telegram/SourceFiles/core/file_utilities.cpp index 3b0591df6..a90ee52b9 100644 --- a/Telegram/SourceFiles/core/file_utilities.cpp +++ b/Telegram/SourceFiles/core/file_utilities.cpp @@ -160,53 +160,6 @@ QString DefaultDownloadPath() { + '/'; } -QString NameFromUserString(QString name) { - static const auto Bad = { '/', '\\', '<', '>', ':', '"', '|', '?', '*' }; - for (auto &ch : name) { - if (ch < 32 || ranges::find(Bad, ch.unicode()) != end(Bad)) { - ch = '_'; - } - } - if (name.isEmpty() || name.endsWith(' ') || name.endsWith('.')) { - name.append('_'); - } -#ifdef Q_OS_WIN - static const auto BadNames = { - qstr("CON"), - qstr("PRN"), - qstr("AUX"), - qstr("NUL"), - qstr("COM1"), - qstr("COM2"), - qstr("COM3"), - qstr("COM4"), - qstr("COM5"), - qstr("COM6"), - qstr("COM7"), - qstr("COM8"), - qstr("COM9"), - qstr("LPT1"), - qstr("LPT2"), - qstr("LPT3"), - qstr("LPT4"), - qstr("LPT5"), - qstr("LPT6"), - qstr("LPT7"), - qstr("LPT8"), - qstr("LPT9") - }; - for (const auto bad : BadNames) { - if (name.startsWith(bad, Qt::CaseInsensitive)) { - if (name.size() == bad.size() || name[bad.size()] == '.') { - name = '_' + name; - break; - } - } - } -#endif // Q_OS_WIN - return name; -} - namespace internal { void UnsafeOpenEmailLinkDefault(const QString &email) { diff --git a/Telegram/SourceFiles/core/file_utilities.h b/Telegram/SourceFiles/core/file_utilities.h index 8d913f2a9..8e25f691e 100644 --- a/Telegram/SourceFiles/core/file_utilities.h +++ b/Telegram/SourceFiles/core/file_utilities.h @@ -37,8 +37,6 @@ void ShowInFolder(const QString &filepath); [[nodiscard]] QString DefaultDownloadPath(); -[[nodiscard]] QString NameFromUserString(QString name); - namespace internal { inline QString UrlToLocalDefault(const QUrl &url) { diff --git a/Telegram/SourceFiles/core/launcher.cpp b/Telegram/SourceFiles/core/launcher.cpp index 86742903f..7768510a0 100644 --- a/Telegram/SourceFiles/core/launcher.cpp +++ b/Telegram/SourceFiles/core/launcher.cpp @@ -9,8 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/platform_launcher.h" #include "platform/platform_specific.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "ui/main_queue_processor.h" +#include "ui/ui_utility.h" #include "core/crash_reports.h" #include "core/update_checker.h" #include "core/sandbox.h" @@ -234,8 +235,10 @@ Launcher::Launcher( const QString &systemVersion) : _argc(argc) , _argv(argv) +, _baseIntegration(_argc, _argv) , _deviceModel(deviceModel) , _systemVersion(systemVersion) { + base::Integration::Set(&_baseIntegration); } void Launcher::init() { @@ -268,9 +271,12 @@ int Launcher::exec() { return psCleanup(); } - // both are finished in Sandbox::closeApplication - Logs::start(this); // must be started before Platform is started - Platform::start(); // must be started before Sandbox is created + // Must be started before Platform is started. + Logs::start(this); + + // Must be started before Sandbox is created. + Platform::start(); + Ui::DisableCustomScaling(); auto result = executeApplication(); diff --git a/Telegram/SourceFiles/core/launcher.h b/Telegram/SourceFiles/core/launcher.h index 6060e96ff..05648bdb1 100644 --- a/Telegram/SourceFiles/core/launcher.h +++ b/Telegram/SourceFiles/core/launcher.h @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "core/base_integration.h" + namespace Core { class Launcher { @@ -63,6 +65,7 @@ private: int _argc; char **_argv; QStringList _arguments; + BaseIntegration _baseIntegration; const QString _deviceModel; const QString _systemVersion; diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 0799098dc..f19f54a24 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -341,7 +341,7 @@ bool HandleUnknown( Api::EntitiesFromMTP(result.ventities().value_or_empty()) }; if (result.is_update_app()) { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto callback = [=] { Core::UpdateApplication(); if (*box) (*box)->closeBox(); diff --git a/Telegram/SourceFiles/core/sandbox.cpp b/Telegram/SourceFiles/core/sandbox.cpp index 9da3cc41e..6f255a94c 100644 --- a/Telegram/SourceFiles/core/sandbox.cpp +++ b/Telegram/SourceFiles/core/sandbox.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "core/sandbox.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "mainwidget.h" #include "mainwindow.h" #include "storage/localstorage.h" diff --git a/Telegram/SourceFiles/core/shortcuts.cpp b/Telegram/SourceFiles/core/shortcuts.cpp index 05c0d4aa4..4886ddfc2 100644 --- a/Telegram/SourceFiles/core/shortcuts.cpp +++ b/Telegram/SourceFiles/core/shortcuts.cpp @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_controller.h" #include "core/application.h" #include "media/player/media_player_instance.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "base/parse_helper.h" #include "facades.h" diff --git a/Telegram/SourceFiles/core/core_ui_integration.cpp b/Telegram/SourceFiles/core/ui_integration.cpp similarity index 99% rename from Telegram/SourceFiles/core/core_ui_integration.cpp rename to Telegram/SourceFiles/core/ui_integration.cpp index a8011bd4a..a878b9075 100644 --- a/Telegram/SourceFiles/core/core_ui_integration.cpp +++ b/Telegram/SourceFiles/core/ui_integration.cpp @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "core/core_ui_integration.h" +#include "core/ui_integration.h" #include "core/local_url_handlers.h" #include "core/file_utilities.h" diff --git a/Telegram/SourceFiles/core/core_ui_integration.h b/Telegram/SourceFiles/core/ui_integration.h similarity index 98% rename from Telegram/SourceFiles/core/core_ui_integration.h rename to Telegram/SourceFiles/core/ui_integration.h index e52bbb2ed..b53c76aa7 100644 --- a/Telegram/SourceFiles/core/core_ui_integration.h +++ b/Telegram/SourceFiles/core/ui_integration.h @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "ui/ui_integration.h" +#include "ui/integration.h" namespace Core { diff --git a/Telegram/SourceFiles/core/update_checker.cpp b/Telegram/SourceFiles/core/update_checker.cpp index a680135be..e311600ff 100644 --- a/Telegram/SourceFiles/core/update_checker.cpp +++ b/Telegram/SourceFiles/core/update_checker.cpp @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "core/update_checker.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "base/timer.h" #include "base/bytes.h" #include "base/unixtime.h" @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/settings/info_settings_widget.h" #include "window/window_session_controller.h" #include "settings/settings_intro.h" +#include "ui/layers/box_content.h" #include "app.h" #include @@ -221,7 +222,7 @@ QString FindUpdateFile() { "^(" "tupdate|" "tmacupd|" - "tmac32upd|" + "tosxupd|" "tlinuxupd|" "tlinux32upd" ")\\d+(_[a-z\\d]+)?$", diff --git a/Telegram/SourceFiles/core/utils.cpp b/Telegram/SourceFiles/core/utils.cpp index 0daea75a1..54ded4de8 100644 --- a/Telegram/SourceFiles/core/utils.cpp +++ b/Telegram/SourceFiles/core/utils.cpp @@ -392,7 +392,6 @@ namespace ThirdParty { } else { LOG(("MTP Error: Could not init OpenSSL threads, CRYPTO_num_locks() returned zero!")); } - CRYPTO_THREADID_set_callback(_sslThreadId); } if (!CRYPTO_get_dynlock_create_callback()) { CRYPTO_set_dynlock_create_callback(_sslCreateFunction); @@ -419,9 +418,7 @@ namespace ThirdParty { #endif ENGINE_cleanup(); CONF_modules_unload(1); - ERR_remove_state(0); ERR_free_strings(); - ERR_remove_thread_state(nullptr); EVP_cleanup(); delete[] base::take(_sslLocks); diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index a80dd8a30..bac5c7f8c 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -15,9 +15,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #define TDESKTOP_ALPHA_VERSION (0ULL) #endif // TDESKTOP_OFFICIAL_TARGET -constexpr auto AppVersion = 1008015; -constexpr auto AppVersionStr = "1.8.15"; -constexpr auto AppBetaVersion = false; +constexpr auto AppVersion = 1009000; +constexpr auto AppVersionStr = "1.9"; +constexpr auto AppBetaVersion = true; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; constexpr auto AppKotatoVersion = 1001000; constexpr auto AppKotatoVersionStr = "1.1"; diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index a036b84b2..f23a484b0 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "ui/image/image_source.h" #include "ui/text/text_utilities.h" +#include "base/base_file_utilities.h" #include "mainwindow.h" #include "core/application.h" #include "lottie/lottie_animation.h" @@ -136,13 +137,7 @@ QString FileNameUnsafe( QString name, bool savingAs, const QDir &dir) { -#ifdef Q_OS_WIN - name = name.replace(QRegularExpression(qsl("[\\\\\\/\\:\\*\\?\\\"\\<\\>\\|]")), qsl("_")); -#elif defined Q_OS_MAC - name = name.replace(QRegularExpression(qsl("[\\:]")), qsl("_")); -#elif defined Q_OS_LINUX - name = name.replace(QRegularExpression(qsl("[\\/]")), qsl("_")); -#endif + name = base::FileNameFromUserString(name); if (Global::AskDownloadPath() || savingAs) { if (!name.isEmpty() && name.at(0) == QChar::fromLatin1('.')) { name = filedialogDefaultName(prefix, name); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 17ffef451..540979331 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -31,7 +31,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/streaming/media_streaming_loader.h" // unique_ptr #include "media/streaming/media_streaming_reader.h" // make_shared #include "boxes/abstract_box.h" -#include "platform/platform_info.h" #include "passport/passport_form_controller.h" #include "window/themes/window_theme.h" #include "lang/lang_keys.h" // tr::lng_deleted(tr::now) in user name @@ -48,7 +47,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_poll.h" #include "data/data_scheduled_messages.h" #include "data/data_cloud_themes.h" +#include "base/platform/base_platform_info.h" #include "base/unixtime.h" +#include "base/call_delayed.h" #include "facades.h" #include "app.h" #include "styles/style_boxes.h" // st::backgroundSize @@ -933,7 +934,7 @@ void Session::suggestStartExport() { ? 0 : (_exportAvailableAt - now); if (left) { - App::CallDelayed( + base::call_delayed( std::min(left + 5, 3600) * crl::time(1000), _session, [=] { suggestStartExport(); }); @@ -991,7 +992,7 @@ void Session::rememberPassportCredentials( _passportCredentials = std::make_unique( std::move(data), ++generation); - App::CallDelayed(rememberFor, _session, [=, check = generation] { + base::call_delayed(rememberFor, _session, [=, check = generation] { if (_passportCredentials && _passportCredentials->second == check) { forgetPassportCredentials(); } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 776af0db9..39d22c4fd 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -23,7 +23,6 @@ class Image; class HistoryItem; class HistoryMessage; class HistoryService; -class BoxContent; struct WebPageCollage; enum class WebPageType; enum class NewMessageType; @@ -54,6 +53,10 @@ class PanelController; } // namespace View } // namespace Export +namespace Ui { +class BoxContent; +} // namespace Ui + namespace Passport { struct SavedCredentials; } // namespace Passport @@ -840,7 +843,7 @@ private: std::unique_ptr _exportPanel; rpl::event_stream _exportViewChanges; TimeId _exportAvailableAt = 0; - QPointer _exportSuggestion; + QPointer _exportSuggestion; rpl::variable _contactsLoaded = false; rpl::event_stream _chatsListLoadedEvents; diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index dafa93579..9b67c3ee5 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -using "basic.style"; +using "ui/basic.style"; using "ui/widgets/widgets.style"; diff --git a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp index 9e11fa53e..7f0206ace 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp @@ -39,7 +39,7 @@ void ShowSearchFromBox( box->addButton(tr::lng_cancel(), [box, subscription] { box->closeBox(); }); - }), LayerOption::KeepOther); + }), Ui::LayerOption::KeepOther); box->boxClosing() | rpl::start_with_next( std::move(closedCallback), *subscription); diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 135cf452d..5c8952e24 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -23,8 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwidget.h" #include "main/main_session.h" #include "apiwrap.h" +#include "base/event_filter.h" #include "core/application.h" -#include "core/event_filter.h" #include "core/update_checker.h" #include "boxes/peer_list_box.h" #include "boxes/peers/edit_participants_box.h" @@ -314,13 +314,13 @@ void Widget::setupScrollUpButton() { } scrollToTop(); }); - Core::InstallEventFilter(_scrollToTop, [=](not_null event) { + base::install_event_filter(_scrollToTop, [=](not_null event) { if (event->type() != QEvent::Wheel) { - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; } return _scroll->viewportEvent(event) - ? Core::EventFilter::Result::Cancel - : Core::EventFilter::Result::Continue; + ? base::EventFilterResult::Cancel + : base::EventFilterResult::Continue; }); updateScrollUpVisibility(); } diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index aab49845e..1b006d2df 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "export/export_settings.h" #include "export/output/export_output_file.h" +#include "base/base_file_utilities.h" #include "core/mime_type.h" #include "core/utils.h" #include @@ -337,53 +338,6 @@ QString ComputeDocumentName( } } -QString CleanDocumentName(QString name) { - // We don't want LTR/RTL mark/embedding/override/isolate chars - // in filenames, because they introduce a security issue, when - // an executable "Fil[x]gepj.exe" may look like "Filexe.jpeg". - QChar controls[] = { - 0x200E, // LTR Mark - 0x200F, // RTL Mark - 0x202A, // LTR Embedding - 0x202B, // RTL Embedding - 0x202D, // LTR Override - 0x202E, // RTL Override - 0x2066, // LTR Isolate - 0x2067, // RTL Isolate -#ifdef Q_OS_WIN - '\\', - '/', - ':', - '*', - '?', - '"', - '<', - '>', - '|', -#elif defined Q_OS_MAC // Q_OS_WIN - ':', -#elif defined Q_OS_LINUX // Q_OS_WIN || Q_OS_MAC - '/', -#endif // Q_OS_WIN || Q_OS_MAC || Q_OS_LINUX - }; - for (const auto ch : controls) { - name = std::move(name).replace(ch, '_'); - } - -#ifdef Q_OS_WIN - const auto lower = name.trimmed().toLower(); - const auto kBadExtensions = { qstr(".lnk"), qstr(".scf") }; - const auto kMaskExtension = qsl(".download"); - for (const auto extension : kBadExtensions) { - if (lower.endsWith(extension)) { - return name + kMaskExtension; - } - } -#endif // Q_OS_WIN - - return name; -} - QString DocumentFolder(const Document &data) { if (data.isVideoFile) { return "video_files"; @@ -469,7 +423,8 @@ Document ParseDocument( MTP_string()); result.file.suggestedPath = suggestedFolder + DocumentFolder(result) + '/' - + CleanDocumentName(ComputeDocumentName(context, result, date)); + + base::FileNameFromUserString( + ComputeDocumentName(context, result, date)); result.thumb = ParseDocumentThumb( data, diff --git a/Telegram/SourceFiles/export/view/export.style b/Telegram/SourceFiles/export/view/export.style index 90c641750..4059cc3b1 100644 --- a/Telegram/SourceFiles/export/view/export.style +++ b/Telegram/SourceFiles/export/view/export.style @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -using "basic.style"; +using "ui/basic.style"; using "ui/widgets/widgets.style"; using "boxes/boxes.style"; diff --git a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp index f5b2103bf..dec220ed0 100644 --- a/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp +++ b/Telegram/SourceFiles/export/view/export_view_panel_controller.cpp @@ -16,13 +16,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "storage/localstorage.h" #include "core/file_utilities.h" -#include "platform/platform_info.h" #include "main/main_session.h" #include "data/data_session.h" +#include "base/platform/base_platform_info.h" #include "base/unixtime.h" #include "facades.h" #include "styles/style_export.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" namespace Export { namespace View { @@ -30,7 +30,7 @@ namespace { constexpr auto kSaveSettingsTimeout = crl::time(1000); -class SuggestBox : public BoxContent { +class SuggestBox : public Ui::BoxContent { public: SuggestBox(QWidget*); @@ -85,9 +85,9 @@ Environment PrepareEnvironment() { return result; } -QPointer SuggestStart() { +QPointer SuggestStart() { ClearSuggestStart(); - return Ui::show(Box(), LayerOption::KeepOther).data(); + return Ui::show(Box(), Ui::LayerOption::KeepOther).data(); } void ClearSuggestStart() { @@ -166,10 +166,10 @@ void PanelController::showSettings() { auto settings = base::make_unique_q( _panel, *_settings); - settings->setShowBoxCallback([=](object_ptr box) { + settings->setShowBoxCallback([=](object_ptr box) { _panel->showBox( std::move(box), - LayerOption::KeepOther, + Ui::LayerOption::KeepOther, anim::type::normal); }); @@ -256,7 +256,7 @@ void PanelController::showError(const QString &text) { const auto hidden = _panel->isHidden(); _panel->showBox( std::move(box), - LayerOption::CloseOther, + Ui::LayerOption::CloseOther, hidden ? anim::type::instant : anim::type::normal); weak->setCloseByEscape(false); weak->setCloseByOutsideClick(false); @@ -330,7 +330,7 @@ void PanelController::stopWithConfirmation(FnMut callback) { _confirmStopBox = box.data(); _panel->showBox( std::move(box), - LayerOption::CloseOther, + Ui::LayerOption::CloseOther, hidden ? anim::type::instant : anim::type::normal); if (hidden) { _panel->showAndActivate(); diff --git a/Telegram/SourceFiles/export/view/export_view_panel_controller.h b/Telegram/SourceFiles/export/view/export_view_panel_controller.h index 106fb1348..3bcebb513 100644 --- a/Telegram/SourceFiles/export/view/export_view_panel_controller.h +++ b/Telegram/SourceFiles/export/view/export_view_panel_controller.h @@ -12,10 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unique_qptr.h" #include "base/timer.h" -class BoxContent; - namespace Ui { class SeparatePanel; +class BoxContent; } // namespace Ui namespace Export { @@ -25,7 +24,7 @@ struct Environment; namespace View { Environment PrepareEnvironment(); -QPointer SuggestStart(); +QPointer SuggestStart(); void ClearSuggestStart(); bool IsDefaultPath(const QString &path); void ResolveSettings(Settings &settings); @@ -71,7 +70,7 @@ private: base::unique_qptr _panel; State _state; - QPointer _confirmStopBox; + QPointer _confirmStopBox; rpl::event_stream> _panelCloseEvents; bool _stopRequested = false; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp index 2ea4c2cdc..a6386df0c 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.cpp +++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp @@ -27,7 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "styles/style_widgets.h" #include "styles/style_export.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" namespace Export { namespace View { @@ -103,7 +103,7 @@ void SettingsWidget::changeData(Callback &&callback) { void SettingsWidget::setupContent() { const auto scroll = Ui::CreateChild( this, - st::boxLayerScroll); + st::boxScroll); const auto wrap = scroll->setOwnedWidget( object_ptr( scroll, @@ -406,7 +406,7 @@ not_null SettingsWidget::setupButtons( not_null wrap) { using namespace rpl::mappers; - const auto buttonsPadding = st::boxButtonPadding; + const auto buttonsPadding = st::defaultBox.buttonPadding; const auto buttonsHeight = buttonsPadding.top() + st::defaultBoxButton.height + buttonsPadding.bottom(); @@ -654,8 +654,8 @@ void SettingsWidget::refreshButtons( container->sizeValue( ) | rpl::start_with_next([=](QSize size) { - const auto right = st::boxButtonPadding.right(); - const auto top = st::boxButtonPadding.top(); + const auto right = st::defaultBox.buttonPadding.right(); + const auto top = st::defaultBox.buttonPadding.top(); start->moveToRight(right, top); }, start->lifetime()); } @@ -674,9 +674,9 @@ void SettingsWidget::refreshButtons( container->sizeValue(), start ? start->widthValue() : rpl::single(0) ) | rpl::start_with_next([=](QSize size, int width) { - const auto right = st::boxButtonPadding.right() - + (width ? width + st::boxButtonPadding.left() : 0); - const auto top = st::boxButtonPadding.top(); + const auto right = st::defaultBox.buttonPadding.right() + + (width ? width + st::defaultBox.buttonPadding.left() : 0); + const auto top = st::defaultBox.buttonPadding.top(); cancel->moveToRight(right, top); }, cancel->lifetime()); } diff --git a/Telegram/SourceFiles/export/view/export_view_settings.h b/Telegram/SourceFiles/export/view/export_view_settings.h index 68fae7695..facc3efe8 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.h +++ b/Telegram/SourceFiles/export/view/export_view_settings.h @@ -11,12 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" #include "base/object_ptr.h" -class BoxContent; - namespace Ui { class VerticalLayout; class Checkbox; class ScrollArea; +class BoxContent; } // namespace Ui namespace Export { @@ -34,7 +33,7 @@ public: rpl::producer<> startClicks() const; rpl::producer<> cancelClicks() const; - void setShowBoxCallback(Fn)> callback) { + void setShowBoxCallback(Fn)> callback) { _showBoxCallback = std::move(callback); } @@ -97,7 +96,7 @@ private: void changeData(Callback &&callback); PeerId _singlePeerId = 0; - Fn)> _showBoxCallback; + Fn)> _showBoxCallback; // Use through readData / changeData wrappers. Settings _internal_data; diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 42a756c5d..7f1a9505b 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/clip/media_clip_reader.h" #include "window/window_session_controller.h" #include "history/history_item_components.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "data/data_peer.h" #include "data/data_user.h" #include "observer_peer.h" @@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "boxes/confirm_box.h" #include "boxes/url_auth_box.h" -#include "window/layer_widget.h" +#include "ui/layers/layer_widget.h" #include "lang/lang_keys.h" #include "base/observer.h" #include "history/history.h" @@ -33,13 +33,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" namespace App { -namespace internal { - -void CallDelayed(int duration, FnMut &&lambda) { - Core::App().callDelayed(duration, std::move(lambda)); -} - -} // namespace internal void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) { if (auto m = App::main()) { diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 7d2838974..4c943d141 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/type_traits.h" #include "base/observer.h" +#include "base/call_delayed.h" #include "ui/effects/animation_value.h" class History; @@ -28,27 +29,6 @@ class ItemBase; } // namespace InlineBots namespace App { -namespace internal { - -void CallDelayed(int duration, FnMut &&lambda); - -} // namespace internal - -template -inline void CallDelayed( - int duration, - crl::guarded_wrap &&guarded) { - return internal::CallDelayed( - duration, - std::move(guarded)); -} - -template -inline void CallDelayed(int duration, Guard &&object, Lambda &&lambda) { - return internal::CallDelayed(duration, crl::guard( - std::forward(object), - std::forward(lambda))); -} template [[nodiscard]] inline auto LambdaDelayed(int duration, Guard &&object, Lambda &&lambda) { @@ -57,7 +37,7 @@ template std::forward(lambda)); return [saved = std::move(guarded), duration] { auto copy = saved; - internal::CallDelayed(duration, std::move(copy)); + base::call_delayed(duration, std::move(copy)); }; } diff --git a/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp b/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp index 3775f7503..4693f2e11 100644 --- a/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp +++ b/Telegram/SourceFiles/ffmpeg/ffmpeg_utility.cpp @@ -48,55 +48,37 @@ void AlignedImageBufferCleanupHandler(void* data) { } void UnPremultiplyLine(uchar *dst, const uchar *src, int intsCount) { -#ifdef TDESKTOP_OFFICIAL_TARGET - const auto layout = &qPixelLayouts[QImage::Format_ARGB32]; - const auto convert = layout->convertFromARGB32PM; -#else // TDESKTOP_OFFICIAL_TARGET - const auto layout = nullptr; - const auto convert = []( - uint *dst, - const uint *src, - int count, - std::nullptr_t, - std::nullptr_t) { - for (auto i = 0; i != count; ++i) { - dst[i] = qUnpremultiply(src[i]); - } - }; -#endif // TDESKTOP_OFFICIAL_TARGET + [[maybe_unused]] const auto udst = reinterpret_cast(dst); + const auto usrc = reinterpret_cast(src); - convert( - reinterpret_cast(dst), - reinterpret_cast(src), - intsCount, - layout, - nullptr); +#ifndef TDESKTOP_OFFICIAL_TARGET + for (auto i = 0; i != intsCount; ++i) { + udst[i] = qUnpremultiply(usrc[i]); + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 12, 0) + static const auto layout = &qPixelLayouts[QImage::Format_ARGB32]; + layout->convertFromARGB32PM(udst, usrc, intsCount, layout, nullptr); +#else // Qt >= 5.12 + static const auto layout = &qPixelLayouts[QImage::Format_ARGB32]; + layout->storeFromARGB32PM(dst, usrc, 0, intsCount, nullptr, nullptr); +#endif // Qt >= 5.12 } void PremultiplyLine(uchar *dst, const uchar *src, int intsCount) { -#ifdef TDESKTOP_OFFICIAL_TARGET - const auto layout = &qPixelLayouts[QImage::Format_ARGB32]; - const auto convert = layout->convertToARGB32PM; -#else // TDESKTOP_OFFICIAL_TARGET - const auto layout = nullptr; - const auto convert = []( - uint *dst, - const uint *src, - int count, - std::nullptr_t, - std::nullptr_t) { - for (auto i = 0; i != count; ++i) { - dst[i] = qPremultiply(src[i]); - } - }; -#endif // TDESKTOP_OFFICIAL_TARGET + const auto udst = reinterpret_cast(dst); + [[maybe_unused]] const auto usrc = reinterpret_cast(src); - convert( - reinterpret_cast(dst), - reinterpret_cast(src), - intsCount, - layout, - nullptr); +#ifndef TDESKTOP_OFFICIAL_TARGET + for (auto i = 0; i != intsCount; ++i) { + dst[i] = qPremultiply(src[i]); + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 12, 0) + static const auto layout = &qPixelLayouts[QImage::Format_ARGB32]; + layout->convertToARGB32PM(udst, usrc, intsCount, layout, nullptr); +#else // Qt >= 5.12 + static const auto layout = &qPixelLayouts[QImage::Format_ARGB32]; + layout->fetchToARGB32PM(udst, src, 0, intsCount, nullptr, nullptr); +#endif // Qt >= 5.12 } } // namespace diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp index 9354b05c5..5b7578ab5 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_user.h" #include "base/unixtime.h" +#include "styles/style_layers.h" #include "styles/style_boxes.h" namespace AdminLog { diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h index 0d21cc755..18741954e 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.h @@ -12,9 +12,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace AdminLog { -class FilterBox : public BoxContent { +class FilterBox : public Ui::BoxContent { public: - FilterBox(QWidget*, not_null channel, const std::vector> &admins, const FilterValue &filter, Fn saveCallback); + FilterBox( + QWidget*, + not_null channel, + const std::vector> &admins, + const FilterValue &filter, + Fn saveCallback); protected: void prepare() override; diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp index 36f8d7a71..555364637 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_inner.cpp @@ -21,7 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_cursor_state.h" #include "chat_helpers/message_field.h" #include "boxes/sticker_set_box.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "mainwindow.h" #include "mainwidget.h" #include "core/application.h" @@ -1212,7 +1212,7 @@ void InnerWidget::suggestRestrictUser(not_null user) { }); *weakBox = Ui::show( std::move(box), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); }; if (base::contains(_admins, user)) { editRestrictions(true, MTP_chatBannedRights(MTP_flags(0), MTP_int(0))); diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index d7050d4bb..6886d84e4 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -using "basic.style"; +using "ui/basic.style"; using "dialogs/dialogs.style"; using "ui/widgets/widgets.style"; @@ -47,6 +47,14 @@ historyToDownPosition: point(12px, 10px); historyToDownAbove: icon {{ "history_down_arrow", historyToDownFg, point(17px, 23px) }}; historyToDownAboveOver: icon {{ "history_down_arrow", historyToDownFgOver, point(17px, 23px) }}; historyToDownPaddingTop: 10px; +historyToDownBelow: icon { + { "history_down_shadow", historyToDownShadow }, + { "history_down_circle", historyToDownBg, point(4px, 4px) }, +}; +historyToDownBelowOver: icon { + { "history_down_shadow", historyToDownShadow }, + { "history_down_circle", historyToDownBgOver, point(4px, 4px) }, +}; historyToDown: TwoIconButton { width: 52px; height: 62px; @@ -636,3 +644,12 @@ scheduleTimeSeparator: FlatLabel(defaultFlatLabel) { } } scheduleTimeSeparatorPadding: margins(2px, 0px, 2px, 0px); + +youtubeIcon: icon { + { "media_youtube_play_bg", youtubePlayIconBg }, + { "media_youtube_play", youtubePlayIconFg, point(24px, 12px) }, +}; +videoIcon: icon { + { "media_video_play_bg", videoPlayIconBg }, + { "media_video_play", videoPlayIconFg, point(12px, 12px) }, +}; diff --git a/Telegram/SourceFiles/history/history_drag_area.cpp b/Telegram/SourceFiles/history/history_drag_area.cpp index 9b9b4069f..d786ad5c9 100644 --- a/Telegram/SourceFiles/history/history_drag_area.cpp +++ b/Telegram/SourceFiles/history/history_drag_area.cpp @@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwidget.h" #include "app.h" #include "styles/style_chat_helpers.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" DragArea::DragArea(QWidget *parent) : TWidget(parent) { setMouseTracking(true); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 305f9c71d..dc4812a5f 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/message_field.h" #include "chat_helpers/stickers.h" #include "history/history_widget.h" +#include "base/platform/base_platform_info.h" #include "base/unixtime.h" #include "mainwindow.h" #include "mainwidget.h" @@ -43,7 +44,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "core/application.h" #include "apiwrap.h" -#include "platform/platform_info.h" #include "lang/lang_keys.h" #include "data/data_session.h" #include "data/data_media_types.h" diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index e6f756616..077f7477a 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -260,7 +260,7 @@ void FastShareMessage(not_null item) { text.append(error.first); Ui::show( Box(text), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); return; } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index aaad3e63e..3059d87ba 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -14,7 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/share_box.h" #include "boxes/edit_caption_box.h" #include "core/file_utilities.h" -#include "core/event_filter.h" #include "ui/toast/toast.h" #include "ui/special_buttons.h" #include "ui/emoji_config.h" @@ -28,7 +27,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "ui/special_buttons.h" #include "inline_bots/inline_bot_result.h" +#include "base/event_filter.h" #include "base/unixtime.h" +#include "base/call_delayed.h" #include "data/data_drafts.h" #include "data/data_session.h" #include "data/data_web_page.h" @@ -123,6 +124,10 @@ constexpr auto kSaveDraftAnywayTimeout = 5000; constexpr auto kSaveCloudDraftIdleTimeout = 14000; constexpr auto kRecordingUpdateDelta = crl::time(100); constexpr auto kRefreshSlowmodeLabelTimeout = crl::time(200); +constexpr auto kCommonModifiers = 0 + | Qt::ShiftModifier + | Qt::MetaModifier + | Qt::ControlModifier; ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() { return [](ChannelData *channel, MsgId msgId) { @@ -396,6 +401,7 @@ HistoryWidget::HistoryWidget( _parsedLinks = std::move(parsed); checkPreview(); }, lifetime()); + _field->rawTextEdit()->installEventFilter(this); _field->rawTextEdit()->installEventFilter(_fieldAutocomplete); _field->setMimeDataHook([=]( not_null data, @@ -410,6 +416,7 @@ HistoryWidget::HistoryWidget( } Unexpected("action in MimeData hook."); }); + InitSpellchecker(&controller->session(), _field); const auto suggestions = Ui::Emoji::SuggestionsController::Init( this, @@ -694,11 +701,11 @@ void HistoryWidget::initTabbedSelector() { const auto selector = controller()->tabbedSelector(); - Core::InstallEventFilter(this, selector, [=](not_null e) { + base::install_event_filter(this, selector, [=](not_null e) { if (_tabbedPanel && e->type() == QEvent::ParentChange) { setTabbedPanel(nullptr); } - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; }); selector->emojiChosen( @@ -3050,7 +3057,7 @@ void HistoryWidget::sendScheduled() { const auto callback = [=](Api::SendOptions options) { send(options); }; Ui::show( HistoryView::PrepareScheduleBox(_list, sendMenuType(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } SendMenuType HistoryWidget::sendMenuType() const { @@ -3651,6 +3658,16 @@ bool HistoryWidget::insertBotCommand(const QString &cmd) { } bool HistoryWidget::eventFilter(QObject *obj, QEvent *e) { + if (e->type() == QEvent::KeyPress) { + const auto k = static_cast(e); + if ((k->modifiers() & kCommonModifiers) == Qt::ControlModifier) { + if (k->key() == Qt::Key_Up) { + return replyToPreviousMessage(); + } else if (k->key() == Qt::Key_Down) { + return replyToNextMessage(); + } + } + } if ((obj == _historyDown || obj == _unreadMentions) && e->type() == QEvent::Wheel) { return _scroll->viewportEvent(e); } @@ -3807,7 +3824,7 @@ void HistoryWidget::updateSendButtonType() { && (type == Type::Send || type == Type::Record)); if (delay != 0) { - App::CallDelayed( + base::call_delayed( kRefreshSlowmodeLabelTimeout, this, [=] { updateSendButtonType(); }); @@ -5469,6 +5486,7 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) { void HistoryWidget::keyPressEvent(QKeyEvent *e) { if (!_history) return; + const auto commonModifiers = e->modifiers() & kCommonModifiers; if (e->key() == Qt::Key_Escape) { e->ignore(); } else if (e->key() == Qt::Key_Back) { @@ -5478,29 +5496,21 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { _scroll->keyPressEvent(e); } else if (e->key() == Qt::Key_PageUp) { _scroll->keyPressEvent(e); - } else if (e->key() == Qt::Key_Down) { - if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) { - _scroll->keyPressEvent(e); - } else if ((e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier)) == Qt::ControlModifier) { - replyToNextMessage(); - } - } else if (e->key() == Qt::Key_Up) { - if (!(e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier))) { - const auto item = _history - ? _history->lastSentMessage() - : nullptr; - if (item - && item->allowsEdit(base::unixtime::now()) - && _field->empty() - && !_editMsgId - && !_replyToId) { - editMessage(item); - return; - } - _scroll->keyPressEvent(e); - } else if ((e->modifiers() & (Qt::ShiftModifier | Qt::MetaModifier | Qt::ControlModifier)) == Qt::ControlModifier) { - replyToPreviousMessage(); + } else if (e->key() == Qt::Key_Down && !commonModifiers) { + _scroll->keyPressEvent(e); + } else if (e->key() == Qt::Key_Up && !commonModifiers) { + const auto item = _history + ? _history->lastSentMessage() + : nullptr; + if (item + && item->allowsEdit(base::unixtime::now()) + && _field->empty() + && !_editMsgId + && !_replyToId) { + editMessage(item); + return; } + _scroll->keyPressEvent(e); } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { if (!_botStart->isHidden()) { sendBotStartCommand(); @@ -5549,9 +5559,9 @@ void HistoryWidget::handlePeerMigration() { } } -void HistoryWidget::replyToPreviousMessage() { +bool HistoryWidget::replyToPreviousMessage() { if (!_history || _editMsgId) { - return; + return false; } const auto fullId = FullMsgId( _history->channelId(), @@ -5562,17 +5572,20 @@ void HistoryWidget::replyToPreviousMessage() { const auto previous = previousView->data(); Ui::showPeerHistoryAtItem(previous); replyToMessage(previous); + return true; } } } else if (const auto previous = _history->lastMessage()) { Ui::showPeerHistoryAtItem(previous); replyToMessage(previous); + return true; } + return false; } -void HistoryWidget::replyToNextMessage() { +bool HistoryWidget::replyToNextMessage() { if (!_history || _editMsgId) { - return; + return false; } const auto fullId = FullMsgId( _history->channelId(), @@ -5587,8 +5600,10 @@ void HistoryWidget::replyToNextMessage() { clearHighlightMessages(); cancelReply(false); } + return true; } } + return false; } bool HistoryWidget::showSlowmodeError() { @@ -5811,7 +5826,7 @@ bool HistoryWidget::sendExistingDocument(not_null document) { ? Data::RestrictionError(_peer, ChatRestriction::f_send_stickers) : std::nullopt; if (error) { - Ui::show(Box(*error), LayerOption::KeepOther); + Ui::show(Box(*error), Ui::LayerOption::KeepOther); return false; } else if (!_peer || !_peer->canWrite()) { return false; @@ -5842,7 +5857,7 @@ bool HistoryWidget::sendExistingPhoto(not_null photo) { ? Data::RestrictionError(_peer, ChatRestriction::f_send_media) : std::nullopt; if (error) { - Ui::show(Box(*error), LayerOption::KeepOther); + Ui::show(Box(*error), Ui::LayerOption::KeepOther); return false; } else if (!_peer || !_peer->canWrite()) { return false; diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index f62bc9c56..873711258 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -513,8 +513,8 @@ private: void applyInlineBotQuery(UserData *bot, const QString &query); void cancelReplyAfterMediaSend(bool lastKeyboardUsed); - void replyToPreviousMessage(); - void replyToNextMessage(); + bool replyToPreviousMessage(); + bool replyToNextMessage(); [[nodiscard]] bool showSlowmodeError(); void hideSelectorControlsAnimated(); diff --git a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp index 41e8e143e..b6c27a34e 100644 --- a/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/history_view_compose_controls.cpp @@ -11,7 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/special_buttons.h" #include "ui/ui_utility.h" #include "lang/lang_keys.h" -#include "core/event_filter.h" +#include "base/event_filter.h" +#include "base/call_delayed.h" #include "base/qt_signal_producer.h" #include "history/history.h" #include "chat_helpers/tabbed_panel.h" @@ -228,11 +229,11 @@ void ComposeControls::initTabbedSelector() { const auto selector = _window->tabbedSelector(); const auto wrap = _wrap.get(); - Core::InstallEventFilter(wrap, selector, [=](not_null e) { + base::install_event_filter(wrap, selector, [=](not_null e) { if (_tabbedPanel && e->type() == QEvent::ParentChange) { setTabbedPanel(nullptr); } - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; }); selector->emojiChosen( @@ -281,7 +282,7 @@ void ComposeControls::updateSendButtonType() { // && (type == Type::Send || type == Type::Record)); //if (delay != 0) { - // App::CallDelayed( + // base::call_delayed( // kRefreshSlowmodeLabelTimeout, // this, // [=] { updateSendButtonType(); }); diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp index 6404bccd4..94b2113cd 100644 --- a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp +++ b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/labels.h" +#include "ui/layers/generic_box.h" #include "ui/toast/toast.h" #include "ui/text/text_utilities.h" #include "data/data_peer.h" @@ -23,11 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "main/main_session.h" #include "boxes/confirm_box.h" -#include "boxes/generic_box.h" // window->show(Box(InitMethod())) #include "boxes/peers/edit_contact_box.h" #include "app.h" #include "styles/style_history.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" namespace HistoryView { namespace { @@ -313,7 +313,7 @@ void ContactStatus::setupBlockHandler(not_null user) { void ContactStatus::setupShareHandler(not_null user) { _bar.entity()->shareClicks( ) | rpl::start_with_next([=] { - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto share = [=] { user->setSettings(0); user->session().api().request(MTPcontacts_AcceptContact( @@ -349,7 +349,7 @@ void ContactStatus::setupReportHandler(not_null peer) { ) | rpl::start_with_next([=] { Expects(!peer->isUser()); - const auto box = std::make_shared>(); + const auto box = std::make_shared>(); const auto callback = crl::guard(&_bar, [=] { if (*box) { (*box)->closeBox(); diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 76726733f..e00b3c9b8 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -30,7 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_file_origin.h" #include "core/file_utilities.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "window/window_peer_menu.h" #include "window/window_session_controller.h" #include "lang/lang_keys.h" diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp index 20b6dd9e5..64ef33a53 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.cpp @@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/wrap/padding_wrap.h" #include "chat_helpers/message_field.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" #include "styles/style_history.h" namespace HistoryView { @@ -542,7 +542,7 @@ TimeId DefaultScheduleTime() { } void ScheduleBox( - not_null box, + not_null box, SendMenuType type, FnMut done, TimeId time) { diff --git a/Telegram/SourceFiles/history/view/history_view_schedule_box.h b/Telegram/SourceFiles/history/view/history_view_schedule_box.h index a0269a5fc..387ee8c3c 100644 --- a/Telegram/SourceFiles/history/view/history_view_schedule_box.h +++ b/Telegram/SourceFiles/history/view/history_view_schedule_box.h @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "boxes/generic_box.h" +#include "ui/layers/generic_box.h" namespace Api { struct SendOptions; @@ -19,13 +19,13 @@ namespace HistoryView { [[nodiscard]] TimeId DefaultScheduleTime(); void ScheduleBox( - not_null box, + not_null box, SendMenuType type, FnMut done, TimeId time); template -[[nodiscard]] object_ptr PrepareScheduleBox( +[[nodiscard]] object_ptr PrepareScheduleBox( Guard &&guard, SendMenuType type, Submit &&submit) { diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index f2813348f..93e61fa71 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/message_field.h" // SendMenuType. #include "ui/widgets/scroll_area.h" #include "ui/widgets/shadow.h" +#include "ui/layers/generic_box.h" #include "ui/toast/toast.h" #include "ui/special_buttons.h" #include "ui/ui_utility.h" @@ -24,10 +25,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "boxes/confirm_box.h" #include "boxes/send_files_box.h" -#include "boxes/generic_box.h" #include "window/window_session_controller.h" #include "window/window_peer_menu.h" -#include "core/event_filter.h" +#include "base/event_filter.h" +#include "base/call_delayed.h" #include "core/file_utilities.h" #include "main/main_session.h" #include "data/data_session.h" @@ -143,7 +144,7 @@ void ScheduledWidget::setupComposeControls() { return !_choosingAttach; }) | rpl::start_with_next([=] { _choosingAttach = true; - App::CallDelayed( + base::call_delayed( st::historyAttach.ripple.hideDuration, this, [=] { _choosingAttach = false; chooseAttach(); }); @@ -344,7 +345,7 @@ void ScheduledWidget::uploadFile( }; Ui::show( PrepareScheduleBox(this, sendMenuType(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } bool ScheduledWidget::showSendingFilesError( @@ -387,7 +388,7 @@ void ScheduledWidget::send() { const auto callback = [=](Api::SendOptions options) { send(options); }; Ui::show( PrepareScheduleBox(this, sendMenuType(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void ScheduledWidget::send(Api::SendOptions options) { @@ -432,7 +433,7 @@ void ScheduledWidget::sendExistingDocument( }; Ui::show( PrepareScheduleBox(this, sendMenuType(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } bool ScheduledWidget::sendExistingDocument( @@ -442,7 +443,7 @@ bool ScheduledWidget::sendExistingDocument( _history->peer, ChatRestriction::f_send_stickers); if (error) { - Ui::show(Box(*error), LayerOption::KeepOther); + Ui::show(Box(*error), Ui::LayerOption::KeepOther); return false; } @@ -470,7 +471,7 @@ void ScheduledWidget::sendExistingPhoto(not_null photo) { }; Ui::show( PrepareScheduleBox(this, sendMenuType(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } bool ScheduledWidget::sendExistingPhoto( @@ -480,7 +481,7 @@ bool ScheduledWidget::sendExistingPhoto( _history->peer, ChatRestriction::f_send_media); if (error) { - Ui::show(Box(*error), LayerOption::KeepOther); + Ui::show(Box(*error), Ui::LayerOption::KeepOther); return false; } @@ -507,7 +508,7 @@ void ScheduledWidget::sendInlineResult( }; Ui::show( PrepareScheduleBox(this, sendMenuType(), callback), - LayerOption::KeepOther); + Ui::LayerOption::KeepOther); } void ScheduledWidget::sendInlineResult( @@ -551,13 +552,13 @@ void ScheduledWidget::setupScrollDownButton() { _scrollDown->setClickedCallback([=] { scrollDownClicked(); }); - Core::InstallEventFilter(_scrollDown, [=](not_null event) { + base::install_event_filter(_scrollDown, [=](not_null event) { if (event->type() != QEvent::Wheel) { - return Core::EventFilter::Result::Continue; + return base::EventFilterResult::Continue; } return _scroll->viewportEvent(event) - ? Core::EventFilter::Result::Cancel - : Core::EventFilter::Result::Continue; + ? base::EventFilterResult::Cancel + : base::EventFilterResult::Continue; }); updateScrollDownVisibility(); } diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index c5f289503..5bb793f21 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -using "basic.style"; +using "ui/basic.style"; using "boxes/boxes.style"; using "ui/widgets/widgets.style"; @@ -196,7 +196,7 @@ infoTopBarDuration: 150; infoLayerTopMinimal: 20px; infoLayerTopMaximal: 40px; -infoLayerTopBarHeight: boxLayerTitleHeight; +infoLayerTopBarHeight: boxTitleHeight; infoLayerTopBarBackIcon: icon {{ "info_back", boxTitleCloseFg }}; infoLayerTopBarBackIconOver: icon {{ "info_back", boxTitleCloseFgOver }}; infoLayerTopBarBack: IconButton(infoTopBarBack) { @@ -256,7 +256,7 @@ infoLayerTopBar: InfoTopBar(infoTopBar) { height: infoLayerTopBarHeight; back: infoLayerTopBarBack; title: boxTitle; - titlePosition: boxLayerTitlePosition; + titlePosition: boxTitlePosition; bg: boxBg; mediaCancel: infoLayerTopBarMediaCancel; mediaActionsSkip: 6px; @@ -402,7 +402,7 @@ infoProfileToggle: Toggle(defaultToggle) { infoProfileToggleOver: Toggle(infoProfileToggle) { untoggledFg: menuIconFgOver; } -infoProfileButton: InfoProfileButton { +infoProfileButton: SettingsButton { textFg: windowBoldFg; textFgOver: windowBoldFgOver; textBg: windowBg; @@ -419,10 +419,10 @@ infoProfileButton: InfoProfileButton { ripple: defaultRippleAnimation; } -infoNotificationsButton: InfoProfileButton(infoProfileButton) { +infoNotificationsButton: SettingsButton(infoProfileButton) { padding: margins(79px, 13px, 8px, 9px); } -infoMainButton: InfoProfileButton(infoProfileButton) { +infoMainButton: SettingsButton(infoProfileButton) { textFg: lightButtonFg; textFgOver: lightButtonFgOver; font: semiboldFont; @@ -431,14 +431,14 @@ infoSharedMediaCoverHeight: 62px; infoSharedMediaButton: infoProfileButton; infoSharedMediaBottomSkip: 12px; -infoBlockButton: InfoProfileButton(infoProfileButton) { +infoBlockButton: SettingsButton(infoProfileButton) { textFg: attentionButtonFg; textFgOver: attentionButtonFgOver; } -infoCreateLinkedChatButton: InfoProfileButton(infoMainButton) { +infoCreateLinkedChatButton: SettingsButton(infoMainButton) { padding: margins(74px, 10px, 8px, 8px); } -infoUnlinkChatButton: InfoProfileButton(infoCreateLinkedChatButton) { +infoUnlinkChatButton: SettingsButton(infoCreateLinkedChatButton) { textFg: attentionButtonFg; textFgOver: attentionButtonFgOver; } @@ -587,8 +587,8 @@ infoChannelsList: PeerList(infoCommonGroupsList) { } } -managePeerButton: InfoProfileCountButton { - button: InfoProfileButton(infoProfileButton) { +managePeerButton: SettingsCountButton { + button: SettingsButton(infoProfileButton) { padding: margins(76px, 12px, 76px, 10px); } iconPosition: point(20px, 5px); @@ -598,31 +598,31 @@ managePeerButton: InfoProfileCountButton { labelPosition: point(25px, 12px); } -peerPermissionsButton: InfoProfileCountButton(managePeerButton) { - button: InfoProfileButton(infoProfileButton) { +peerPermissionsButton: SettingsCountButton(managePeerButton) { + button: SettingsButton(infoProfileButton) { padding: margins(24px, 12px, 24px, 10px); } iconPosition: point(24px, 5px); } -manageGroupButton: InfoProfileCountButton(managePeerButton) { - button: InfoProfileButton(infoProfileButton) { +manageGroupButton: SettingsCountButton(managePeerButton) { + button: SettingsButton(infoProfileButton) { padding: margins(72px, 10px, 24px, 8px); } labelPosition: point(22px, 12px); iconPosition: point(20px, 4px); } -manageGroupTopButtonWithText: InfoProfileCountButton(manageGroupButton) { - button: InfoProfileButton(infoProfileButton) { +manageGroupTopButtonWithText: SettingsCountButton(manageGroupButton) { + button: SettingsButton(infoProfileButton) { padding: margins(22px, 10px, 24px, 8px); } labelPosition: point(22px, 10px); iconPosition: point(0px, 0px); } -manageDeleteGroupButton: InfoProfileCountButton(manageGroupTopButtonWithText) { - button: InfoProfileButton(infoProfileButton) { +manageDeleteGroupButton: SettingsCountButton(manageGroupTopButtonWithText) { + button: SettingsButton(infoProfileButton) { padding: margins(25px, 11px, 24px, 8px); textFg: attentionButtonFg; textFgOver: attentionButtonFg; @@ -634,7 +634,7 @@ manageDeleteGroupButton: InfoProfileCountButton(manageGroupTopButtonWithText) { editPeerSkip: 7px; editPeerHistoryVisibilityMargins: margins(15px, 0px, 20px, 16px); -terminateSessionsButton: InfoProfileButton(infoBlockButton) { +terminateSessionsButton: SettingsButton(infoBlockButton) { padding: margins(23px, 12px, 23px, 10px); } @@ -753,8 +753,8 @@ topBarCallSkip: -1px; topBarMenuToggle: IconButton(topBarSearch) { width: 44px; - icon: icon {{ "title_menu_dots", menuIconFg }}; - iconOver: icon {{ "title_menu_dots", menuIconFgOver }}; + icon: menuToggleIcon; + iconOver: menuToggleIconOver; iconPosition: point(16px, 17px); rippleAreaPosition: point(0px, 7px); diff --git a/Telegram/SourceFiles/info/info_layer_widget.cpp b/Telegram/SourceFiles/info/info_layer_widget.cpp index 2b745796c..ca4b0317f 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.cpp +++ b/Telegram/SourceFiles/info/info_layer_widget.cpp @@ -21,7 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "app.h" #include "styles/style_info.h" #include "styles/style_window.h" -#include "styles/style_boxes.h" +#include "styles/style_layers.h" namespace Info { diff --git a/Telegram/SourceFiles/info/info_layer_widget.h b/Telegram/SourceFiles/info/info_layer_widget.h index 13241cab7..db6edc1ac 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.h +++ b/Telegram/SourceFiles/info/info_layer_widget.h @@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "window/layer_widget.h" +#include "ui/layers/layer_widget.h" #include "media/player/media_player_float.h" namespace Window { @@ -22,7 +22,7 @@ class WrapWidget; class TopBar; class LayerWidget - : public Window::LayerWidget + : public Ui::LayerWidget , private ::Media::Player::FloatDelegate { public: LayerWidget( diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index e20f7b471..a4495b677 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -163,7 +163,7 @@ object_ptr Memento::createWidget( return std::move(result); } -object_ptr Memento::createLayer( +object_ptr Memento::createLayer( not_null controller, const QRect &geometry) { if (geometry.width() >= LayerWidget::MinimalSupportedWidth()) { @@ -201,7 +201,7 @@ object_ptr MoveMemento::createWidget( return std::move(result); } -object_ptr MoveMemento::createLayer( +object_ptr MoveMemento::createLayer( not_null controller, const QRect &geometry) { if (geometry.width() < LayerWidget::MinimalSupportedWidth()) { diff --git a/Telegram/SourceFiles/info/info_memento.h b/Telegram/SourceFiles/info/info_memento.h index 73ec0da59..45e41dff4 100644 --- a/Telegram/SourceFiles/info/info_memento.h +++ b/Telegram/SourceFiles/info/info_memento.h @@ -44,7 +44,7 @@ public: Window::Column column, const QRect &geometry) override; - object_ptr createLayer( + object_ptr createLayer( not_null controller, const QRect &geometry) override; @@ -98,7 +98,7 @@ public: Window::Column column, const QRect &geometry) override; - object_ptr createLayer( + object_ptr createLayer( not_null controller, const QRect &geometry) override; diff --git a/Telegram/SourceFiles/info/info_section_widget.cpp b/Telegram/SourceFiles/info/info_section_widget.cpp index 4050b0d40..cc0141ddf 100644 --- a/Telegram/SourceFiles/info/info_section_widget.cpp +++ b/Telegram/SourceFiles/info/info_section_widget.cpp @@ -93,7 +93,7 @@ std::unique_ptr SectionWidget::createMemento() { return _content->createMemento(); } -object_ptr SectionWidget::moveContentToLayer( +object_ptr SectionWidget::moveContentToLayer( QRect bodyGeometry) { if (_content->controller()->wrap() != Wrap::Narrow || width() < LayerWidget::MinimalSupportedWidth()) { diff --git a/Telegram/SourceFiles/info/info_section_widget.h b/Telegram/SourceFiles/info/info_section_widget.h index 7f26ca57e..1ca552569 100644 --- a/Telegram/SourceFiles/info/info_section_widget.h +++ b/Telegram/SourceFiles/info/info_section_widget.h @@ -50,7 +50,7 @@ public: const Window::SectionShow ¶ms) override; std::unique_ptr createMemento() override; - object_ptr moveContentToLayer( + object_ptr moveContentToLayer( QRect bodyGeometry) override; // Float player interface. diff --git a/Telegram/SourceFiles/info/media/info_media_buttons.h b/Telegram/SourceFiles/info/media/info_media_buttons.h index d70a594c5..e79cac60d 100644 --- a/Telegram/SourceFiles/info/media/info_media_buttons.h +++ b/Telegram/SourceFiles/info/media/info_media_buttons.h @@ -13,10 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_shared_media.h" #include "info/info_memento.h" #include "info/info_controller.h" -#include "info/profile/info_profile_button.h" #include "info/profile/info_profile_values.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" +#include "ui/widgets/buttons.h" #include "window/window_session_controller.h" #include "data/data_channel.h" #include "data/data_user.h" @@ -53,7 +53,7 @@ inline auto AddCountedButton( Ui::MultiSlideTracker &tracker) { using namespace rpl::mappers; - using Button = Profile::Button; + using Button = Ui::SettingsButton; auto forked = std::move(count) | start_spawning(parent->lifetime()); auto text = rpl::duplicate( diff --git a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp index 0ccd361aa..1f72ed406 100644 --- a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp @@ -12,11 +12,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/media/info_media_list_widget.h" #include "info/media/info_media_buttons.h" #include "info/media/info_media_empty_widget.h" -#include "info/profile/info_profile_button.h" #include "info/profile/info_profile_icon.h" #include "info/info_controller.h" #include "ui/widgets/discrete_sliders.h" #include "ui/widgets/shadow.h" +#include "ui/widgets/buttons.h" +#include "ui/widgets/box_content_divider.h" #include "ui/wrap/vertical_layout.h" #include "ui/search_field_controller.h" #include "styles/style_info.h" @@ -66,7 +67,7 @@ void InnerWidget::createOtherTypes() { _otherTypes->show(); createTypeButtons(); - _otherTypes->add(object_ptr(_otherTypes)); + _otherTypes->add(object_ptr(_otherTypes)); //createTabs(); _otherTypes->resizeToWidth(width()); diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index fdbd4f5fe..8e63a2869 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwindow.h" #include "styles/style_overview.h" #include "styles/style_info.h" -#include "platform/platform_info.h" +#include "base/platform/base_platform_info.h" #include "media/player/media_player_instance.h" #include "boxes/peer_list_controllers.h" #include "boxes/confirm_box.h" diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 6a85672fe..3d5c912db 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -17,6 +17,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/slide_wrap.h" #include "ui/widgets/shadow.h" #include "ui/widgets/labels.h" +#include "ui/widgets/buttons.h" +#include "ui/widgets/box_content_divider.h" +#include "ui/layers/generic_box.h" #include "ui/toast/toast.h" #include "ui/text/text_utilities.h" // Ui::Text::ToUpper #include "history/history_location_manager.h" // LocationClickHandler. @@ -26,14 +29,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peer_list_controllers.h" #include "boxes/add_contact_box.h" #include "boxes/report_box.h" -#include "boxes/generic_box.h" // window->show(Box(InitMethod())) #include "boxes/peers/edit_contact_box.h" #include "lang/lang_keys.h" #include "info/info_controller.h" #include "info/info_memento.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_values.h" -#include "info/profile/info_profile_button.h" #include "info/profile/info_profile_text.h" #include "support/support_helper.h" #include "window/window_session_controller.h" @@ -75,11 +76,11 @@ auto AddActionButton( Text &&text, ToggleOn &&toggleOn, Callback &&callback, - const style::InfoProfileButton &st + const style::SettingsButton &st = st::infoSharedMediaButton) { - auto result = parent->add(object_ptr>( + auto result = parent->add(object_ptr>( parent, - object_ptr