Telegram: bump version

This commit is contained in:
Gerasim Troeglazov
2020-04-17 13:08:36 +10:00
parent c9373a3a67
commit 06bbe2da09
2 changed files with 39 additions and 759 deletions

View File

@@ -1,6 +1,6 @@
From b2d99a06c3859641d53c0919c6fc921ceaee1677 Mon Sep 17 00:00:00 2001
From c82adbfa1c3296cfedfde1c78dca1ad4aa831040 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sun, 15 Mar 2020 19:54:39 +1000
Date: Fri, 17 Apr 2020 12:23:15 +1000
Subject: Add Haiku support
@@ -40,10 +40,10 @@ index 645d886..3a0a0e9 100644
add_subdirectory(cmake)
add_subdirectory(Telegram)
diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt
index b7be40f..30e289b 100644
index 5c50088..367a607 100644
--- a/Telegram/CMakeLists.txt
+++ b/Telegram/CMakeLists.txt
@@ -97,7 +97,7 @@ PRIVATE
@@ -98,7 +98,7 @@ PRIVATE
desktop-app::external_minizip
desktop-app::external_qt
desktop-app::external_qr_code_generator
@@ -52,7 +52,7 @@ index b7be40f..30e289b 100644
desktop-app::external_auto_updates
tdesktop::lib_tgvoip
desktop-app::external_openssl
@@ -800,6 +800,18 @@ PRIVATE
@@ -813,6 +813,18 @@ PRIVATE
platform/win/windows_event_filter.cpp
platform/win/windows_event_filter.h
platform/win/wrapper_wrl_implements_h.h
@@ -71,7 +71,7 @@ index b7be40f..30e289b 100644
platform/platform_audio.h
platform/platform_file_utilities.h
platform/platform_launcher.h
@@ -1166,7 +1178,7 @@ endif()
@@ -1187,7 +1199,7 @@ endif()
set_target_properties(Telegram PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${output_folder})
@@ -81,7 +81,7 @@ index b7be40f..30e289b 100644
init_target(Updater)
diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp
index bf57bdc..ae79d2f 100644
index 732c516..822dcaf 100644
--- a/Telegram/SourceFiles/calls/calls_call.cpp
+++ b/Telegram/SourceFiles/calls/calls_call.cpp
@@ -5,6 +5,7 @@ the official desktop application for the Telegram messaging service.
@@ -121,10 +121,10 @@ index 160571e..842ac9b 100644
if (!updater.exists()) {
QFileInfo current(curUpdater);
diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp
index 7fa9f0a..59b9bde 100644
index b3cf552..96eda72 100644
--- a/Telegram/SourceFiles/data/data_session.cpp
+++ b/Telegram/SourceFiles/data/data_session.cpp
@@ -200,7 +200,7 @@ Session::Session(not_null<Main::Session*> session)
@@ -202,7 +202,7 @@ Session::Session(not_null<Main::Session*> session)
_cache->open(Local::cacheKey());
_bigFileCache->open(Local::cacheBigFileKey());
@@ -134,7 +134,7 @@ index 7fa9f0a..59b9bde 100644
if (wasVersion >= 1007011 && wasVersion < 1007015) {
_bigFileCache->clear();
diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp
index 6df70cd..6c9727c 100644
index 592d4db..83b71d9 100644
--- a/Telegram/SourceFiles/mainwindow.cpp
+++ b/Telegram/SourceFiles/mainwindow.cpp
@@ -142,7 +142,7 @@ void MainWindow::createTrayIconMenu() {
@@ -165,7 +165,7 @@ index 6df70cd..6c9727c 100644
? tr::lng_disable_notifications_from_tray(tr::now)
: tr::lng_enable_notifications_from_tray(tr::now);
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
index df5e243..f825716 100644
index 89a0df8..508952d 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
@@ -363,7 +363,7 @@ OverlayWidget::OverlayWidget()
@@ -1600,10 +1600,10 @@ index 0000000..06f4d28
+}
diff --git a/Telegram/SourceFiles/platform/haiku/specific_haiku.h b/Telegram/SourceFiles/platform/haiku/specific_haiku.h
new file mode 100644
index 0000000..d79f6e4
index 0000000..ef5d0f2
--- /dev/null
+++ b/Telegram/SourceFiles/platform/haiku/specific_haiku.h
@@ -0,0 +1,116 @@
@@ -0,0 +1,122 @@
+/*
+This file is part of Telegram Desktop for Haiku,
+
@@ -1648,6 +1648,12 @@ index 0000000..d79f6e4
+ return std::nullopt;
+}
+
+inline void FallbackFontConfigCheckBegin() {
+}
+
+inline void FallbackFontConfigCheckEnd() {
+}
+
+} // namespace Platform
+
+inline QString psServerPrefix() {
@@ -1882,7 +1888,7 @@ index 9ec30eb..53152ee 100644
}
return QString();
diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp
index a220b03..92830f6 100644
index 88ffe6e..7e26c59 100644
--- a/Telegram/SourceFiles/window/main_window.cpp
+++ b/Telegram/SourceFiles/window/main_window.cpp
@@ -117,7 +117,7 @@ QIcon CreateOfficialIcon(Main::Account *account) {
@@ -2867,10 +2873,10 @@ index 963a720..d67d6c3 100644
#ifdef USE_BREAKPAD
diff --git a/Telegram/lib_base/base/platform/base_platform_file_utilities.h b/Telegram/lib_base/base/platform/base_platform_file_utilities.h
index d9ec560..e5076b5 100644
index c30eba8..ad7fc36 100644
--- a/Telegram/lib_base/base/platform/base_platform_file_utilities.h
+++ b/Telegram/lib_base/base/platform/base_platform_file_utilities.h
@@ -22,8 +22,10 @@ void RemoveQuarantine(const QString &path);
@@ -24,8 +24,10 @@ bool RenameWithOverwrite(const QString &from, const QString &to);
#ifdef Q_OS_MAC
#include "base/platform/mac/base_file_utilities_mac.h"
@@ -2996,10 +3002,10 @@ index 0000000..2e18272
+} // namespace base::Platform
diff --git a/Telegram/lib_base/base/platform/haiku/base_file_utilities_haiku.h b/Telegram/lib_base/base/platform/haiku/base_file_utilities_haiku.h
new file mode 100644
index 0000000..3b2d42b
index 0000000..6700d58
--- /dev/null
+++ b/Telegram/lib_base/base/platform/haiku/base_file_utilities_haiku.h
@@ -0,0 +1,20 @@
@@ -0,0 +1,27 @@
+/*
+This file is part of Telegram Desktop for Haiku,
+
@@ -3011,6 +3017,7 @@ index 0000000..3b2d42b
+
+#pragma once
+
+#include <QtCore/QFile>
+#include <QtCore/QString>
+
+namespace base::Platform {
@@ -3019,6 +3026,12 @@ index 0000000..3b2d42b
+ return name;
+}
+
+inline bool RenameWithOverwrite(const QString &from, const QString &to) {
+ const auto fromPath = QFile::encodeName(from);
+ const auto toPath = QFile::encodeName(to);
+ return (rename(fromPath.constData(), toPath.constData()) == 0);
+}
+
+} // namespace base::Platform
diff --git a/Telegram/lib_base/base/platform/haiku/base_info_haiku.cpp b/Telegram/lib_base/base/platform/haiku/base_info_haiku.cpp
new file mode 100644
@@ -3437,740 +3450,8 @@ index 0000000..f682740
+} // namespace crl::details
+
+#endif // CRL_USE_LINUX_TIME
diff --git a/Telegram/lib_spellcheck/CMakeLists.txt b/Telegram/lib_spellcheck/CMakeLists.txt
index 4568692..36df305 100644
--- a/Telegram/lib_spellcheck/CMakeLists.txt
+++ b/Telegram/lib_spellcheck/CMakeLists.txt
@@ -46,6 +46,10 @@ if (system_spellchecker)
spellcheck/platform/mac/spellcheck_mac.mm
spellcheck/platform/win/spellcheck_win.cpp
spellcheck/platform/win/spellcheck_win.h
+ spellcheck/platform/haiku/haiku_enchant.cpp
+ spellcheck/platform/haiku/haiku_enchant.h
+ spellcheck/platform/haiku/spellcheck_haiku.cpp
+ spellcheck/platform/haiku/spellcheck_haiku.h
)
else()
nice_target_sources(lib_spellcheck ${src_loc}
@@ -75,7 +79,7 @@ PUBLIC
desktop-app::lib_ui
)
-if (LINUX AND use_enchant)
+if ((LINUX OR HAIKU) AND use_enchant)
find_package(PkgConfig REQUIRED)
pkg_search_module(ENCHANT REQUIRED enchant-2 enchant)
diff --git a/Telegram/lib_spellcheck/spellcheck/platform/haiku/haiku_enchant.cpp b/Telegram/lib_spellcheck/spellcheck/platform/haiku/haiku_enchant.cpp
new file mode 100644
index 0000000..cc3db6a
--- /dev/null
+++ b/Telegram/lib_spellcheck/spellcheck/platform/haiku/haiku_enchant.cpp
@@ -0,0 +1,229 @@
+/* enchant
+ * Copyright (C) 2003 Dom Lachowicz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+#include <enchant-2/enchant.h>
+#include <dlfcn.h>
+#include "spellcheck/platform/haiku/haiku_enchant.h"
+
+namespace {
+
+struct {
+ //decltype (enchant_broker_describe) * broker_describe;
+ //decltype (enchant_broker_dict_exists) * broker_dict_exists;
+ decltype (enchant_broker_free) * broker_free;
+ decltype (enchant_broker_free_dict) * broker_free_dict;
+ decltype (enchant_broker_get_error) * broker_get_error;
+ decltype (enchant_broker_init) * broker_init;
+ decltype (enchant_broker_list_dicts) * broker_list_dicts;
+ decltype (enchant_broker_request_dict) * broker_request_dict;
+ //decltype (enchant_broker_request_pwl_dict) * broker_request_pwl_dict;
+ decltype (enchant_broker_set_ordering) * broker_set_ordering;
+ decltype (enchant_dict_add) * dict_add;
+ decltype (enchant_dict_add_to_session) * dict_add_to_session;
+ decltype (enchant_dict_check) * dict_check;
+ decltype (enchant_dict_describe) * dict_describe;
+ decltype (enchant_dict_free_string_list) * dict_free_string_list;
+ decltype (enchant_dict_get_error) * dict_get_error;
+ decltype (enchant_dict_is_added) * dict_is_added;
+ //decltype (enchant_dict_is_removed) * dict_is_removed;
+ decltype (enchant_dict_remove) * dict_remove;
+ decltype (enchant_dict_remove_from_session) * dict_remove_from_session;
+ //decltype (enchant_dict_store_replacement) * dict_store_replacement;
+ decltype (enchant_dict_suggest) * dict_suggest;
+} f_enchant;
+
+} // anonymous namespace
+
+enchant::Exception::Exception (const char * ex)
+ : std::exception (), m_ex ("") {
+ if (ex)
+ m_ex = ex;
+}
+
+enchant::Exception::~Exception () = default;
+
+const char * enchant::Exception::what () const noexcept {
+ return m_ex.c_str();
+}
+
+enchant::Dict::Dict (EnchantDict * dict, EnchantBroker * broker)
+ : m_dict (dict), m_broker (broker) {
+ f_enchant.dict_describe (m_dict, s_describe_fn, this);
+}
+
+enchant::Dict::~Dict () {
+ f_enchant.broker_free_dict (m_broker, m_dict);
+}
+
+bool enchant::Dict::check (const std::string & utf8word) {
+ int val;
+
+ val = f_enchant.dict_check (m_dict, utf8word.c_str(), utf8word.size());
+ if (val == 0)
+ return true;
+ else if (val > 0)
+ return false;
+ else {
+ throw enchant::Exception (f_enchant.dict_get_error (m_dict));
+ }
+
+ return false; // never reached
+}
+
+void enchant::Dict::suggest (const std::string & utf8word,
+ std::vector<std::string> & out_suggestions) {
+ size_t n_suggs;
+ char ** suggs;
+
+ out_suggestions.clear ();
+
+ suggs = f_enchant.dict_suggest (m_dict, utf8word.c_str(),
+ utf8word.size(), &n_suggs);
+
+ if (suggs && n_suggs) {
+ out_suggestions.reserve(n_suggs);
+
+ for (size_t i = 0; i < n_suggs; i++) {
+ out_suggestions.push_back (suggs[i]);
+ }
+
+ f_enchant.dict_free_string_list (m_dict, suggs);
+ }
+}
+
+void enchant::Dict::add (const std::string & utf8word) {
+ f_enchant.dict_add (m_dict, utf8word.c_str(), utf8word.size());
+}
+
+void enchant::Dict::add_to_session (const std::string & utf8word) {
+ f_enchant.dict_add_to_session (m_dict, utf8word.c_str(), utf8word.size());
+}
+
+bool enchant::Dict::is_added (const std::string & utf8word) {
+ return f_enchant.dict_is_added (m_dict, utf8word.c_str(),
+ utf8word.size());
+}
+
+void enchant::Dict::remove (const std::string & utf8word) {
+ f_enchant.dict_remove (m_dict, utf8word.c_str(), utf8word.size());
+}
+
+void enchant::Dict::remove_from_session (const std::string & utf8word) {
+ f_enchant.dict_remove_from_session (m_dict, utf8word.c_str(),
+ utf8word.size());
+}
+
+//bool enchant::Dict::is_removed (const std::string & utf8word) {
+// return f_enchant.dict_is_removed (m_dict, utf8word.c_str(),
+// utf8word.size());
+//}
+
+//void enchant::Dict::store_replacement (const std::string & utf8bad,
+// const std::string & utf8good) {
+// f_enchant.dict_store_replacement (m_dict,
+// utf8bad.c_str(), utf8bad.size(),
+// utf8good.c_str(), utf8good.size());
+//}
+
+enchant::Broker::Broker ()
+ : m_broker (f_enchant.broker_init ())
+ {
+ }
+
+enchant::Broker::~Broker () {
+ f_enchant.broker_free (m_broker);
+}
+
+enchant::Dict * enchant::Broker::request_dict (const std::string & lang) {
+ EnchantDict * dict = f_enchant.broker_request_dict (m_broker, lang.c_str());
+
+ if (!dict) {
+ throw enchant::Exception (f_enchant.broker_get_error (m_broker));
+ return 0; // never reached
+ }
+
+ return new Dict (dict, m_broker);
+}
+
+//enchant::Dict * enchant::Broker::request_pwl_dict (const std::string & pwl) {
+// EnchantDict * dict = f_enchant.broker_request_pwl_dict (m_broker, pwl.c_str());
+//
+// if (!dict) {
+// throw enchant::Exception (f_enchant.broker_get_error (m_broker));
+// return 0; // never reached
+// }
+//
+// return new Dict (dict, m_broker);
+//}
+
+//bool enchant::Broker::dict_exists (const std::string & lang) {
+// if (f_enchant.broker_dict_exists (m_broker, lang.c_str()))
+// return true;
+// return false;
+//}
+
+void enchant::Broker::set_ordering (const std::string & tag, const std::string & ordering) {
+ f_enchant.broker_set_ordering (m_broker, tag.c_str(), ordering.c_str());
+}
+
+//void enchant::Broker::describe (EnchantBrokerDescribeFn fn, void * user_data) {
+// f_enchant.broker_describe (m_broker, fn, user_data);
+//}
+
+void enchant::Broker::list_dicts (EnchantDictDescribeFn fn, void * user_data) {
+ f_enchant.broker_list_dicts (m_broker, fn, user_data);
+}
+
+#define GET_SYMBOL_enchant(func_name) do { \
+ typedef decltype (enchant_ ## func_name) * Fp; \
+ f_enchant.func_name = reinterpret_cast<Fp> ( dlsym (handle, "enchant_" # func_name)); \
+ if (!f_enchant.func_name) { \
+ return false; \
+ } \
+} while(0)
+
+bool enchant::loader::do_explicit_linking () {
+ static enum { NotLoadedYet, LoadSuccessful, LoadFailed = -1 } load_status;
+ if (load_status == NotLoadedYet) {
+ load_status = LoadFailed;
+ void * handle = dlopen ("libenchant.so.1", RTLD_NOW)
+ ?: dlopen ("libenchant-2.so.2", RTLD_NOW)
+ ?: dlopen ("libenchant.so.2", RTLD_NOW);
+ if (!handle) {
+ // logs ?
+ return false;
+ }
+ //GET_SYMBOL_enchant (broker_describe);
+ //GET_SYMBOL_enchant (broker_dict_exists);
+ GET_SYMBOL_enchant (broker_free);
+ GET_SYMBOL_enchant (broker_free_dict);
+ GET_SYMBOL_enchant (broker_get_error);
+ GET_SYMBOL_enchant (broker_init);
+ GET_SYMBOL_enchant (broker_list_dicts);
+ GET_SYMBOL_enchant (broker_request_dict);
+ //GET_SYMBOL_enchant (broker_request_pwl_dict);
+ GET_SYMBOL_enchant (broker_set_ordering);
+ GET_SYMBOL_enchant (dict_add);
+ GET_SYMBOL_enchant (dict_add_to_session);
+ GET_SYMBOL_enchant (dict_check);
+ GET_SYMBOL_enchant (dict_describe);
+ GET_SYMBOL_enchant (dict_free_string_list);
+ GET_SYMBOL_enchant (dict_get_error);
+ GET_SYMBOL_enchant (dict_is_added);
+ //GET_SYMBOL_enchant (dict_is_removed);
+ GET_SYMBOL_enchant (dict_remove);
+ GET_SYMBOL_enchant (dict_remove_from_session);
+ //GET_SYMBOL_enchant (dict_store_replacement);
+ GET_SYMBOL_enchant (dict_suggest);
+ load_status = LoadSuccessful;
+ }
+ return load_status == LoadSuccessful;
+}
+
+// vi: ts=8 sw=8
diff --git a/Telegram/lib_spellcheck/spellcheck/platform/haiku/haiku_enchant.h b/Telegram/lib_spellcheck/spellcheck/platform/haiku/haiku_enchant.h
new file mode 100644
index 0000000..f73f860
--- /dev/null
+++ b/Telegram/lib_spellcheck/spellcheck/platform/haiku/haiku_enchant.h
@@ -0,0 +1,151 @@
+/* enchant
+ * Copyright (C) 2003 Dom Lachowicz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <exception>
+
+#ifndef ENCHANT_H
+typedef struct str_enchant_broker EnchantBroker;
+typedef struct str_enchant_dict EnchantDict;
+
+typedef void (*EnchantBrokerDescribeFn) (const char * const provider_name,
+ const char * const provider_desc,
+ const char * const provider_dll_file,
+ void * user_data);
+
+typedef void (*EnchantDictDescribeFn) (const char * const lang_tag,
+ const char * const provider_name,
+ const char * const provider_desc,
+ const char * const provider_file,
+ void * user_data);
+#endif // !ENCHANT_H
+
+namespace enchant
+{
+ class Broker;
+
+ class Exception : public std::exception
+ {
+ public:
+ explicit Exception (const char * ex);
+ virtual ~Exception () noexcept;
+ virtual const char * what () const noexcept;
+
+ private:
+ std::string m_ex;
+ };
+
+ class Dict
+ {
+ friend class enchant::Broker;
+
+ public:
+
+ ~Dict ();
+
+ bool check (const std::string & utf8word);
+ void suggest (const std::string & utf8word,
+ std::vector<std::string> & out_suggestions);
+
+ std::vector<std::string> suggest (const std::string & utf8word) {
+ std::vector<std::string> result;
+ suggest (utf8word, result);
+ return result;
+ }
+
+ void add (const std::string & utf8word);
+ void add_to_session (const std::string & utf8word);
+ bool is_added (const std::string & utf8word);
+ void remove (const std::string & utf8word);
+ void remove_from_session (const std::string & utf8word);
+ bool is_removed (const std::string & utf8word);
+ void store_replacement (const std::string & utf8bad,
+ const std::string & utf8good);
+
+ const std::string & get_lang () const {
+ return m_lang;
+ }
+
+ const std::string & get_provider_name () const {
+ return m_provider_name;
+ }
+
+ const std::string & get_provider_desc () const {
+ return m_provider_desc;
+ }
+
+ const std::string & get_provider_file () const {
+ return m_provider_file;
+ }
+
+ private:
+
+ void * _private[5];
+
+ static void s_describe_fn (const char * const lang,
+ const char * const provider_name,
+ const char * const provider_desc,
+ const char * const provider_file,
+ void * user_data) {
+ enchant::Dict * dict = static_cast<enchant::Dict *> (user_data);
+
+ dict->m_lang = lang;
+ dict->m_provider_name = provider_name;
+ dict->m_provider_desc = provider_desc;
+ dict->m_provider_file = provider_file;
+ }
+
+ Dict (EnchantDict * dict, EnchantBroker * broker);
+
+ Dict () = delete;
+ Dict (const Dict & rhs) = delete;
+ Dict& operator=(const Dict & rhs) = delete;
+
+ EnchantDict * m_dict;
+ EnchantBroker * m_broker;
+
+ std::string m_lang;
+ std::string m_provider_name;
+ std::string m_provider_desc;
+ std::string m_provider_file;
+ };
+
+ class Broker
+ {
+
+ public:
+
+ Broker ();
+ ~Broker ();
+
+ Dict * request_dict (const std::string & lang);
+ Dict * request_pwl_dict (const std::string & pwl);
+ bool dict_exists (const std::string & lang);
+ void set_ordering (const std::string & tag, const std::string & ordering);
+ void describe (EnchantBrokerDescribeFn fn, void * user_data = nullptr);
+ void list_dicts (EnchantDictDescribeFn fn, void * user_data = nullptr);
+
+ private:
+
+ void * _private[5];
+
+ Broker (const Broker & rhs) = delete;
+ Broker& operator=(const Broker & rhs) = delete;
+
+ EnchantBroker * m_broker;
+ };
+
+ namespace loader {
+ bool do_explicit_linking ();
+ }
+
+}
diff --git a/Telegram/lib_spellcheck/spellcheck/platform/haiku/spellcheck_haiku.cpp b/Telegram/lib_spellcheck/spellcheck/platform/haiku/spellcheck_haiku.cpp
new file mode 100644
index 0000000..d73aadc
--- /dev/null
+++ b/Telegram/lib_spellcheck/spellcheck/platform/haiku/spellcheck_haiku.cpp
@@ -0,0 +1,276 @@
+// This file is part of Desktop App Toolkit,
+// a set of libraries for developing nice desktop applications.
+//
+// Author: Nicholas Guriev <guriev-ns@ya.ru>, public domain, 2019
+// License: CC0, https://creativecommons.org/publicdomain/zero/1.0/legalcode
+
+#include <set>
+#include <QLocale>
+
+#include "spellcheck/spellcheck_utils.h"
+#include "spellcheck/platform/haiku/haiku_enchant.h"
+
+#include "spellcheck/platform/haiku/spellcheck_haiku.h"
+#include "base/integration.h"
+
+namespace Platform::Spellchecker {
+namespace {
+
+constexpr auto kHspell = "hspell";
+constexpr auto kMySpell = "myspell";
+constexpr auto kHunspell = "hunspell";
+constexpr auto kOrdering = "hspell,aspell,hunspell,myspell";
+constexpr auto kMaxValidators = 10;
+constexpr auto kMaxMySpellCount = 3;
+constexpr auto kMaxWordLength = 15;
+
+using DictPtr = std::unique_ptr<enchant::Dict>;
+
+auto CheckProvider(DictPtr &validator, const std::string &provider) {
+ auto p = validator->get_provider_name();
+ std::transform(begin(p), end(p), begin(p), ::tolower);
+ return (p.find(provider) == 0); // startsWith.
+}
+
+auto IsHebrew(const QString &word) {
+ // Words with mixed scripts will be automatically ignored,
+ // so this check should be fine.
+ return ::Spellchecker::WordScript(&word) == QChar::Script_Hebrew;
+}
+
+class EnchantSpellChecker {
+public:
+ auto knownLanguages();
+ bool checkSpelling(const QString &word);
+ auto findSuggestions(const QString &word);
+ void addWord(const QString &wordToAdd);
+ void ignoreWord(const QString &word);
+ void removeWord(const QString &word);
+ bool isWordInDictionary(const QString &word);
+ static EnchantSpellChecker *instance();
+
+private:
+ EnchantSpellChecker();
+ EnchantSpellChecker(const EnchantSpellChecker&) = delete;
+ EnchantSpellChecker& operator =(const EnchantSpellChecker&) = delete;
+
+ std::unique_ptr<enchant::Broker> _brokerHandle;
+ std::vector<DictPtr> _validators;
+
+ std::vector<not_null<enchant::Dict*>> _hspells;
+};
+
+EnchantSpellChecker::EnchantSpellChecker() {
+ std::set<std::string> langs;
+ _brokerHandle = std::make_unique<enchant::Broker>();
+ _brokerHandle->list_dicts([](
+ const char *language,
+ const char *provider,
+ const char *description,
+ const char *filename,
+ void *our_payload) {
+ static_cast<decltype(langs)*>(our_payload)->insert(language);
+ }, &langs);
+ _validators.reserve(langs.size());
+ try {
+ std::string langTag = QLocale::system().name().toStdString();
+ _brokerHandle->set_ordering(langTag, kOrdering);
+ _validators.push_back(DictPtr(_brokerHandle->request_dict(langTag)));
+ langs.erase(langTag);
+ } catch (const enchant::Exception &e) {
+ // no first dictionary found
+ }
+ auto mySpellCount = 0;
+ for (const std::string &language : langs) {
+ try {
+ _brokerHandle->set_ordering(language, kOrdering);
+ auto validator = DictPtr(_brokerHandle->request_dict(language));
+ if (!validator) {
+ continue;
+ }
+ if (CheckProvider(validator, kHspell)) {
+ _hspells.push_back(validator.get());
+ }
+ if (CheckProvider(validator, kMySpell)
+ || CheckProvider(validator, kHunspell)) {
+ if (mySpellCount > kMaxMySpellCount) {
+ continue;
+ } else {
+ mySpellCount++;
+ }
+ }
+ _validators.push_back(std::move(validator));
+ if (_validators.size() > kMaxValidators) {
+ break;
+ }
+ } catch (const enchant::Exception &e) {
+ base::Integration::Instance().logMessage(QString("Catch after request_dict: ") + e.what());
+ }
+ }
+}
+
+EnchantSpellChecker *EnchantSpellChecker::instance() {
+ static EnchantSpellChecker capsule;
+ return &capsule;
+}
+
+auto EnchantSpellChecker::knownLanguages() {
+ return _validators | ranges::views::transform([](const auto &validator) {
+ return QString(validator->get_lang().c_str());
+ }) | ranges::to_vector;
+}
+
+bool EnchantSpellChecker::checkSpelling(const QString &word) {
+ auto w = word.toStdString();
+
+ if (IsHebrew(word) && _hspells.size()) {
+ return ranges::any_of(_hspells, [&](const auto &validator) {
+ return validator->check(w);
+ });
+ }
+ return ranges::any_of(_validators, [&](const auto &validator) {
+ // Hspell is the spell checker that only checks words in Hebrew.
+ // It returns 'true' for any non-Hebrew word,
+ // so we should skip Hspell if a word is not in Hebrew.
+ if (ranges::find_if(_hspells, [&](auto &v) {
+ return v == validator.get();
+ }) != _hspells.end()) {
+ return false;
+ }
+ if (validator->get_lang().find("uk") == 0) {
+ return false;
+ }
+ try {
+ return validator->check(w);
+ } catch (const enchant::Exception &e) {
+ base::Integration::Instance().logMessage(QString("Catch after check '") + word + "': " + e.what());
+ return true;
+ }
+ }) || _validators.empty();
+}
+
+auto EnchantSpellChecker::findSuggestions(const QString &word) {
+ const auto wordScript = ::Spellchecker::WordScript(&word);
+ auto w = word.toStdString();
+ std::vector<QString> result;
+ if (!_validators.size()) {
+ return result;
+ }
+
+ const auto convertSuggestions = [&](auto suggestions) {
+ for (const auto &replacement : suggestions) {
+ if (result.size() >= kMaxSuggestions) {
+ break;
+ }
+ if (!replacement.empty()) {
+ result.push_back(replacement.c_str());
+ }
+ }
+ };
+
+ if (word.size() >= kMaxWordLength) {
+ // The first element is the validator of the system language.
+ auto *v = _validators[0].get();
+ const auto lang = QString::fromStdString(v->get_lang());
+ if (wordScript == ::Spellchecker::LocaleToScriptCode(lang)) {
+ convertSuggestions(v->suggest(w));
+ }
+ return result;
+ }
+
+ if (IsHebrew(word) && _hspells.size()) {
+ for (const auto &h : _hspells) {
+ convertSuggestions(h->suggest(w));
+ if (result.size()) {
+ return result;
+ }
+ }
+ }
+ for (const auto &validator : _validators) {
+ const auto lang = QString::fromStdString(validator->get_lang());
+ if (wordScript != ::Spellchecker::LocaleToScriptCode(lang)) {
+ continue;
+ }
+ convertSuggestions(validator->suggest(w));
+ if (!result.empty()) {
+ break;
+ }
+ }
+ return result;
+}
+
+void EnchantSpellChecker::addWord(const QString &wordToAdd) {
+ auto word = wordToAdd.toStdString();
+ auto &&first = _validators.at(0);
+ first->add(word);
+ first->add_to_session(word);
+}
+
+void EnchantSpellChecker::ignoreWord(const QString &word) {
+ _validators.at(0)->add_to_session(word.toStdString());
+}
+
+void EnchantSpellChecker::removeWord(const QString &word) {
+ auto w = word.toStdString();
+ for (const auto &validator : _validators) {
+ validator->remove_from_session(w);
+ validator->remove(w);
+ }
+}
+
+bool EnchantSpellChecker::isWordInDictionary(const QString &word) {
+ auto w = word.toStdString();
+ return ranges::any_of(_validators, [&w](const auto &validator) {
+ return validator->is_added(w);
+ });
+}
+
+} // namespace
+
+void Init() {
+}
+
+bool IsAvailable() {
+ static auto Available = enchant::loader::do_explicit_linking();
+ return Available;
+}
+
+void KnownLanguages(std::vector<QString> *langCodes) {
+ *langCodes = EnchantSpellChecker::instance()->knownLanguages();
+}
+
+bool CheckSpelling(const QString &wordToCheck) {
+ return EnchantSpellChecker::instance()->checkSpelling(wordToCheck);
+}
+
+void FillSuggestionList(
+ const QString &wrongWord,
+ std::vector<QString> *variants) {
+ *variants = EnchantSpellChecker::instance()->findSuggestions(wrongWord);
+}
+
+void AddWord(const QString &word) {
+ EnchantSpellChecker::instance()->addWord(word);
+}
+
+void RemoveWord(const QString &word) {
+ EnchantSpellChecker::instance()->removeWord(word);
+}
+
+void IgnoreWord(const QString &word) {
+ EnchantSpellChecker::instance()->ignoreWord(word);
+}
+
+bool IsWordInDictionary(const QString &wordToCheck) {
+ return EnchantSpellChecker::instance()->isWordInDictionary(wordToCheck);
+}
+
+void CheckSpellingText(
+ const QString &text,
+ MisspelledWords *misspelledWords) {
+ *misspelledWords = ::Spellchecker::RangesFromText(
+ text,
+ ::Spellchecker::CheckSkipAndSpell);
+}
+
+} // namespace Platform::Spellchecker
diff --git a/Telegram/lib_spellcheck/spellcheck/platform/haiku/spellcheck_haiku.h b/Telegram/lib_spellcheck/spellcheck/platform/haiku/spellcheck_haiku.h
new file mode 100644
index 0000000..49d672c
--- /dev/null
+++ b/Telegram/lib_spellcheck/spellcheck/platform/haiku/spellcheck_haiku.h
@@ -0,0 +1,13 @@
+// This file is part of Desktop App Toolkit,
+// a set of libraries for developing nice desktop applications.
+//
+// For license and copyright information please follow this link:
+// https://github.com/desktop-app/legal/blob/master/LEGAL
+//
+#pragma once
+
+#include "spellcheck/platform/platform_spellcheck.h"
+
+namespace Platform::Spellchecker {
+
+} // namespace Platform::Spellchecker
diff --git a/Telegram/lib_spellcheck/spellcheck/platform/platform_spellcheck.h b/Telegram/lib_spellcheck/spellcheck/platform/platform_spellcheck.h
index c3b8199..fdccb8e 100644
--- a/Telegram/lib_spellcheck/spellcheck/platform/platform_spellcheck.h
+++ b/Telegram/lib_spellcheck/spellcheck/platform/platform_spellcheck.h
@@ -40,6 +40,8 @@ void UpdateLanguages(std::vector<int> languages);
#include "spellcheck/platform/mac/spellcheck_mac.h"
#elif defined Q_OS_WIN // Q_OS_MAC
#include "spellcheck/platform/win/spellcheck_win.h"
-#elif defined Q_OS_WINRT || defined Q_OS_LINUX // Q_OS_MAC || Q_OS_WIN
+#elif defined Q_OS_HAIKU // Q_OS_MAC || Q_OS_WIN
+#include "spellcheck/platform/haiku/spellcheck_haiku.h"
+#elif defined Q_OS_WINRT || defined Q_OS_LINUX // Q_OS_MAC || Q_OS_WIN || Q_OS_HAIKU
#include "spellcheck/platform/linux/spellcheck_linux.h"
-#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_WINRT || Q_OS_LINUX
+#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_WINRT || Q_OS_LINUX || defined Q_OS_HAIKU
diff --git a/Telegram/lib_ui/CMakeLists.txt b/Telegram/lib_ui/CMakeLists.txt
index 88c28e6..53599c6 100644
index 6188df5..b3df3a9 100644
--- a/Telegram/lib_ui/CMakeLists.txt
+++ b/Telegram/lib_ui/CMakeLists.txt
@@ -84,6 +84,10 @@ PRIVATE
@@ -4186,7 +3467,7 @@ index 88c28e6..53599c6 100644
ui/style/style_core.cpp
diff --git a/Telegram/lib_ui/ui/platform/haiku/ui_utility_haiku.cpp b/Telegram/lib_ui/ui/platform/haiku/ui_utility_haiku.cpp
new file mode 100644
index 0000000..fef675e
index 0000000..d9723c2
--- /dev/null
+++ b/Telegram/lib_ui/ui/platform/haiku/ui_utility_haiku.cpp
@@ -0,0 +1,35 @@
@@ -4199,7 +3480,7 @@ index 0000000..fef675e
+Copyright (c) 2019-2020 Gerasim Troeglazov, 3dEyes@gmail.com
+*/
+
+#include "ui/platform/linux/ui_utility_linux.h"
+#include "ui/platform/haiku/ui_utility_haiku.h"
+
+#include "base/flat_set.h"
+#include "ui/ui_log.h"
@@ -4615,5 +3896,5 @@ index cb3303a..1dc7d45 100644
get_filename_component(libs_loc "../Libraries/macos" REALPATH)
endif()
--
2.24.1
2.26.0

View File

@@ -3,10 +3,10 @@ DESCRIPTION="Unofficial build of the original Telegram client for Haiku."
HOMEPAGE="https://www.telegram.org/"
COPYRIGHT="2013-2020 Telegram"
LICENSE="GNU GPL v3"
REVISION="2"
REVISION="1"
SOURCE_URI="https://github.com/telegramdesktop/tdesktop/releases/download/v$portVersion/tdesktop-$portVersion-full.tar.gz"
CHECKSUM_SHA256="e1f9b58c1475a5044bc4d7a7ed5f89777e717ea5e6126707105e2c2d3032ffac"
CHECKSUM_SHA256="ced19f5bc15e26d7bf76e47841422425f664110f1aada111b9f525ab18e1723c"
SOURCE_FILENAME="tdesktop-$portVersion-full.tar.gz"
SOURCE_DIR="tdesktop-$portVersion-full"
srcGitRev_2="0663103551379b958b2e79c51d51d163ec484300"
@@ -33,7 +33,6 @@ REQUIRES="
lib:libavformat$secondaryArchSuffix
lib:libavutil$secondaryArchSuffix
lib:libcrypto$secondaryArchSuffix
lib:libenchant_2$secondaryArchSuffix
lib:libglib_2.0$secondaryArchSuffix
lib:libgthread_2.0$secondaryArchSuffix
lib:libhunspell_1.7$secondaryArchSuffix
@@ -58,7 +57,6 @@ BUILD_REQUIRES="
devel:libavformat$secondaryArchSuffix
devel:libavutil$secondaryArchSuffix
devel:libcrypto$secondaryArchSuffix
devel:libenchant_2$secondaryArchSuffix
devel:libglib_2.0$secondaryArchSuffix
devel:libgthread_2.0$secondaryArchSuffix
devel:libhunspell_1.7$secondaryArchSuffix
@@ -125,13 +123,14 @@ BUILD()
-DDESKTOP_APP_USE_PACKAGED_GSL=OFF \
-DDESKTOP_APP_USE_PACKAGED_VARIANT=OFF \
-DDESKTOP_APP_USE_PACKAGED_EXPECTED=OFF \
-DDESKTOP_APP_USE_HUNSPELL_ONLY=ON \
-DTDESKTOP_USE_PACKAGED_TGVOIP=OFF \
-DTDESKTOP_API_ID=$TELEGRAM_API_ID \
-DTDESKTOP_API_HASH=$TELEGRAM_API_HASH
export DISABLE_ASLR=1
# multi-job takes too much memory
make -j4
make
#build notify gate tool
gcc -o tg-notify-gate $sourceDir/Telegram/SourceFiles/platform/haiku/notifications_haiku_gate.cpp -lbe