diff --git a/win-linux/extras/update-daemon/UpdateDaemon.pro b/win-linux/extras/update-daemon/UpdateDaemon.pro
index a9eead74f..8bf868242 100644
--- a/win-linux/extras/update-daemon/UpdateDaemon.pro
+++ b/win-linux/extras/update-daemon/UpdateDaemon.pro
@@ -4,7 +4,7 @@ include(common.pri)
DEFINES += COPYRIGHT_YEAR=$${CURRENT_YEAR}
DEFINES += APP_ICON_PATH=\"./icons/desktopeditors.ico\"
-DEFINES += APP_LANG_PATH=\"./langs/langs.iss\"
+DEFINES += APP_LANG_PATH=\"./langs/langs.bin\"
ENV_URL_APPCAST_MAIN = $$(DESKTOP_URL_UPDATES_MAIN_CHANNEL)
!isEmpty(ENV_URL_APPCAST_MAIN) {
@@ -30,4 +30,4 @@ core_linux {
QMAKE_EXTRA_COMPILERS += glib_resources
}
-OTHER_FILES += $$PWD/res/langs/langs.iss
+OTHER_FILES += $$PWD/res/langs/langs.isl
diff --git a/win-linux/extras/update-daemon/res/gresource.xml b/win-linux/extras/update-daemon/res/gresource.xml
index 2d420e866..fa84b6574 100644
--- a/win-linux/extras/update-daemon/res/gresource.xml
+++ b/win-linux/extras/update-daemon/res/gresource.xml
@@ -1,7 +1,7 @@
- langs/langs.iss
+ langs/langs.bin
diff --git a/win-linux/extras/update-daemon/res/langs/langs.bin b/win-linux/extras/update-daemon/res/langs/langs.bin
new file mode 100644
index 000000000..7a741e5c4
Binary files /dev/null and b/win-linux/extras/update-daemon/res/langs/langs.bin differ
diff --git a/win-linux/extras/update-daemon/res/langs/langs.iss b/win-linux/extras/update-daemon/res/langs/langs.isl
similarity index 100%
rename from win-linux/extras/update-daemon/res/langs/langs.iss
rename to win-linux/extras/update-daemon/res/langs/langs.isl
diff --git a/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp b/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp
index ec42a4132..7c276daea 100644
--- a/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp
+++ b/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp
@@ -385,7 +385,7 @@ void CSvcManager::init()
break;
case MSG_SetLanguage:
- Translator::setLanguage(params[1]);
+ Translator::instance().setLanguage(params[1]);
break;
default:
diff --git a/win-linux/extras/update-daemon/src/classes/translator.cpp b/win-linux/extras/update-daemon/src/classes/translator.cpp
index 83bafcdbc..3f0c4ef3b 100644
--- a/win-linux/extras/update-daemon/src/classes/translator.cpp
+++ b/win-linux/extras/update-daemon/src/classes/translator.cpp
@@ -1,39 +1,22 @@
#include "translator.h"
#include
+#include
#ifdef _WIN32
# include "platform_win/resource.h"
# include "platform_win/utils.h"
# include
+# include
# include
-# include
-# define istalnum(c) std::iswalnum(c)
-# define istalpha(c) std::iswalpha(c)
# define tistringstream std::wistringstream
#else
# include "platform_linux/utils.h"
# include "res/gresource.c"
-# include
-# define istalnum(c) std::isalnum(c)
-# define istalpha(c) std::isalpha(c)
+# include
# define tistringstream std::istringstream
+ typedef uint16_t WORD;
#endif
-bool isSeparator(tchar c)
-{
- return c == _T(' ') || c == _T('\t') || c == _T('\r') || c == _T('\n');
-}
-
-bool isValidStringIdCharacter(tchar c)
-{
- return istalnum(c) || istalpha(c) || c == _T('_');
-}
-
-bool isValidLocaleCharacter(tchar c)
-{
- return istalpha(c) || c == _T('_');
-}
-
tstring getPrimaryLang(const tstring &lang, bool withScript = false)
{
if (lang.empty()) {
@@ -54,69 +37,223 @@ tstring getPrimaryLang(const tstring &lang, bool withScript = false)
}
#ifdef _WIN32
+static IStream* LoadResourceToStream(int resourceId)
+{
+ IStream *pStream = nullptr;
+ HMODULE hInst = GetModuleHandle(nullptr);
+ if (HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(resourceId), RT_RCDATA)) {
+ DWORD dataSize = SizeofResource(hInst, hRes);
+ if (dataSize > 0) {
+ if (HGLOBAL hResData = LoadResource(hInst, hRes)) {
+ if (LPVOID pData = LockResource(hResData)) {
+ if (HGLOBAL hGlobal = GlobalAlloc(GHND, dataSize)) {
+ if (LPVOID pBuffer = GlobalLock(hGlobal)) {
+ memcpy(pBuffer, pData, dataSize);
+ GlobalUnlock(hGlobal);
+ HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
+ if (FAILED(hr)) {
+ GlobalFree(hGlobal);
+ pStream = nullptr;
+ }
+ } else {
+ GlobalFree(hGlobal);
+ }
+ }
+ }
+ FreeResource(hResData);
+ }
+ }
+ }
+ return pStream;
+}
+
wstring StrToWStr(const string &str)
{
std::wstring_convert> converter;
return converter.from_bytes(str);
}
-#endif
-
-TranslationsMap Translator::translMap = TranslationsMap();
-tstring Translator::langName = _T("en");
-bool Translator::is_translations_valid = false;
-
-#ifdef _WIN32
-Translator::Translator(const tstring &lang, int resourceId)
#else
-Translator::Translator(const tstring &lang, const char *resourcePath)
-#endif
+static GInputStream* LoadResourceToStream(const char *resourcePath)
{
- langName = lang;
- NS_Logger::WriteLog(_T("Current locale: ") + langName);
-
-#ifdef _WIN32
- HMODULE hInst = GetModuleHandle(NULL);
- if (HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(resourceId), RT_RCDATA)) {
- if (HGLOBAL hResData = LoadResource(hInst, hRes)) {
- if (LPVOID pData = LockResource(hResData)) {
- DWORD dataSize = SizeofResource(hInst, hRes);
- if (dataSize > 0) {
- string text((const char*)pData, dataSize);
- translations = StrToWStr(text);
- } else
- NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
- } else
- NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
- FreeResource(hResData);
- } else
- NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
- } else
- NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
-#else
+ GInputStream *pStream = nullptr;
if (GResource *res = gresource_get_resource()) {
g_resources_register(res);
if (GBytes *bytes = g_resource_lookup_data(res, resourcePath, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL)) {
gsize dataSize = 0;
const char *pData = (const char*)g_bytes_get_data(bytes, &dataSize);
if (dataSize > 0) {
- string text(pData, dataSize);
- translations = text;
- } else
- NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
+ pStream = g_memory_input_stream_new_from_data(pData, dataSize, NULL);
+ }
g_bytes_unref(bytes);
- } else
- NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
+ }
g_resource_unref(res);
- } else
- NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
+ }
+ return pStream;
+}
#endif
- if (!translations.empty()) {
- parseTranslations();
- if (!is_translations_valid)
- NS_Logger::WriteLog(_T("Cannot parse translations, error in string: ") + error_substr + _T(" <---"));
- } else
- NS_Logger::WriteLog(_T("Error: translations is empty."));
+Translator::Translator() :
+ langName(_T("en")),
+ is_translations_valid(false)
+{
+
+}
+
+Translator& Translator::instance()
+{
+ static Translator inst;
+ return inst;
+}
+
+#ifdef _WIN32
+void Translator::init(const tstring &lang, int resourceId)
+#else
+void Translator::init(const tstring &lang, const char *resourcePath)
+#endif
+{
+ langName = lang;
+ std::replace(langName.begin(), langName.end(), '-', '_');
+ NS_Logger::WriteLog(_T("Current locale: ") + langName);
+
+ is_translations_valid = false;
+ const char ISL_MAGIC[] = "ISL";
+#ifdef _WIN32
+ if (IStream *pStream = LoadResourceToStream(resourceId)) {
+ ULONG bytesRead = 0;
+ HRESULT hr = S_OK;
+ char magic[sizeof(ISL_MAGIC)] = { 0 };
+ hr = pStream->Read(magic, sizeof(magic), &bytesRead);
+ if (FAILED(hr) || bytesRead != sizeof(magic) || strncmp(magic, ISL_MAGIC, sizeof(magic) - 1) != 0) {
+ pStream->Release();
+ return;
+ }
+ WORD stringsMapSize = 0;
+ hr = pStream->Read(&stringsMapSize, sizeof(stringsMapSize), &bytesRead);
+ if (FAILED(hr) || bytesRead != sizeof(stringsMapSize)) {
+ pStream->Release();
+ return;
+ }
+ for (WORD i = 0; i < stringsMapSize; i++) {
+ uint8_t stringIdLen = 0;
+ hr = pStream->Read(&stringIdLen, sizeof(stringIdLen), &bytesRead);
+ if (FAILED(hr) || bytesRead != sizeof(stringIdLen)) {
+ pStream->Release();
+ return;
+ }
+ std::string stringId(stringIdLen, '\0');
+ hr = pStream->Read(&stringId[0], stringIdLen, &bytesRead);
+ if (FAILED(hr) || bytesRead != stringIdLen) {
+ pStream->Release();
+ return;
+ }
+ WORD localeMapSize = 0;
+ hr = pStream->Read(&localeMapSize, sizeof(localeMapSize), &bytesRead);
+ if (FAILED(hr) || bytesRead != sizeof(localeMapSize)) {
+ pStream->Release();
+ return;
+ }
+ LocaleMap localeMap;
+ for (WORD j = 0; j < localeMapSize; j++) {
+ uint8_t localeLen = 0;
+ hr = pStream->Read(&localeLen, sizeof(localeLen), &bytesRead);
+ if (FAILED(hr) || bytesRead != sizeof(localeLen)) {
+ pStream->Release();
+ return;
+ }
+ std::string localeName(localeLen, '\0');
+ hr = pStream->Read(&localeName[0], localeLen, &bytesRead);
+ if (FAILED(hr) || bytesRead != localeLen) {
+ pStream->Release();
+ return;
+ }
+ WORD translationLen = 0;
+ hr = pStream->Read(&translationLen, sizeof(translationLen), &bytesRead);
+ if (FAILED(hr) || bytesRead != sizeof(translationLen)) {
+ pStream->Release();
+ return;
+ }
+ std::string translationString(translationLen, '\0');
+ hr = pStream->Read(&translationString[0], translationLen, &bytesRead);
+ if (FAILED(hr) || bytesRead != translationLen) {
+ pStream->Release();
+ return;
+ }
+ localeMap[StrToWStr(localeName)] = StrToWStr(translationString);
+ }
+ translMap[StrToWStr(stringId)] = localeMap;
+ }
+ pStream->Release();
+ is_translations_valid = true;
+ }
+#else
+ if (GInputStream *pStream = LoadResourceToStream(resourcePath)) {
+ gsize bytesRead = 0;
+ gboolean hr = true;
+ char magic[sizeof(ISL_MAGIC)] = { 0 };
+ hr = g_input_stream_read_all(pStream, magic, sizeof(magic), &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != sizeof(magic) || strncmp(magic, ISL_MAGIC, sizeof(magic) - 1) != 0) {
+ g_object_unref(pStream);
+ return;
+ }
+ WORD stringsMapSize = 0;
+ hr = g_input_stream_read_all(pStream, &stringsMapSize, sizeof(stringsMapSize), &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != sizeof(stringsMapSize)) {
+ g_object_unref(pStream);
+ return;
+ }
+ for (WORD i = 0; i < stringsMapSize; i++) {
+ uint8_t stringIdLen = 0;
+ hr = g_input_stream_read_all(pStream, &stringIdLen, sizeof(stringIdLen), &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != sizeof(stringIdLen)) {
+ g_object_unref(pStream);
+ return;
+ }
+ std::string stringId(stringIdLen, '\0');
+ hr = g_input_stream_read_all(pStream, &stringId[0], stringIdLen, &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != stringIdLen) {
+ g_object_unref(pStream);
+ return;
+ }
+ WORD localeMapSize = 0;
+ hr = g_input_stream_read_all(pStream, &localeMapSize, sizeof(localeMapSize), &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != sizeof(localeMapSize)) {
+ g_object_unref(pStream);
+ return;
+ }
+ LocaleMap localeMap;
+ for (WORD j = 0; j < localeMapSize; j++) {
+ uint8_t localeLen = 0;
+ hr = g_input_stream_read_all(pStream, &localeLen, sizeof(localeLen), &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != sizeof(localeLen)) {
+ g_object_unref(pStream);
+ return;
+ }
+ std::string localeName(localeLen, '\0');
+ hr = g_input_stream_read_all(pStream, &localeName[0], localeLen, &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != localeLen) {
+ g_object_unref(pStream);
+ return;
+ }
+ WORD translationLen = 0;
+ hr = g_input_stream_read_all(pStream, &translationLen, sizeof(translationLen), &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != sizeof(translationLen)) {
+ g_object_unref(pStream);
+ return;
+ }
+ std::string translationString(translationLen, '\0');
+ hr = g_input_stream_read_all(pStream, &translationString[0], translationLen, &bytesRead, NULL, NULL);
+ if (!hr || bytesRead != translationLen) {
+ g_object_unref(pStream);
+ return;
+ }
+ localeMap[localeName] = translationString;
+ }
+ translMap[stringId] = localeMap;
+ }
+ g_object_unref(pStream);
+ is_translations_valid = true;
+ }
+#endif
}
Translator::~Translator()
@@ -124,185 +261,32 @@ Translator::~Translator()
}
-tstring Translator::tr(const char *str)
+tstring Translator::tr(const tchar *str) const
{
-#ifdef _WIN32
- tstring translatedStr = StrToWStr(str);
-#else
- tstring translatedStr = str;
-#endif
if (is_translations_valid) {
- for (auto &strIdPair : translMap) {
- //LocaleMap locMap = strIdPair.second;
- // for (LocaleMap::const_iterator it = strIdPair.second.begin(); it != strIdPair.second.end(); ++it) {
- //wcout << L"\n\n" << translatedStr << L"\n" << it->second;
- if (strIdPair.first == translatedStr) {
- if (strIdPair.second.find(langName) != strIdPair.second.end())
- return strIdPair.second[langName];
- else {
- tstring primaryLangAndScript = getPrimaryLang(langName, true);
- if (strIdPair.second.find(primaryLangAndScript) != strIdPair.second.end())
- return strIdPair.second[primaryLangAndScript];
- else {
- tstring primaryLang = getPrimaryLang(langName);
- if (strIdPair.second.find(primaryLang) != strIdPair.second.end())
- return strIdPair.second[primaryLang];
- }
+ auto it = translMap.find(str);
+ if (it != translMap.end()) {
+ const LocaleMap &lcmap = it->second;
+ auto lc_it = lcmap.find(langName);
+ if (lc_it == lcmap.end()) {
+ tstring primaryLangAndScript = getPrimaryLang(langName, true);
+ if ((lc_it = lcmap.find(primaryLangAndScript)) == lcmap.end()) {
+ tstring primaryLang = getPrimaryLang(langName);
+ if ((lc_it = lcmap.find(primaryLang)) == lcmap.end()) {
+ lc_it = lcmap.find(_T("en"));
}
- if (strIdPair.second.find(_T("en")) != strIdPair.second.end())
- return strIdPair.second[_T("en")];
- break;
}
- // }
+ }
+ if (lc_it != lcmap.end())
+ return lc_it->second;
}
}
- return translatedStr;
+ return str;
}
void Translator::setLanguage(const tstring &lang)
{
langName = lang;
+ std::replace(langName.begin(), langName.end(), '-', '_');
NS_Logger::WriteLog(_T("Current locale: ") + langName);
}
-
-void Translator::parseTranslations()
-{
- int token = TOKEN_BEGIN_DOCUMENT;
- tstring stringId, currentLocale;
- size_t pos = 0, len = translations.length();
- while (pos < len) {
- size_t incr = 1;
- tchar ch = translations.at(pos);
-
- switch (token) {
- case TOKEN_BEGIN_DOCUMENT:
- case TOKEN_END_VALUE:
- if (!isSeparator(ch)) {
- if (ch == _T(';')) {
- // string is comment
- size_t end = translations.find_first_of(_T('\n'), pos);
- incr = (end == tstring::npos) ? len - pos : end - pos + 1;
- } else {
- size_t end;
- for (end = pos; end < len; end++) {
- tchar c = translations.at(end);
- if (!isValidLocaleCharacter(c))
- break;
- }
- size_t locale_len = end - pos;
- if (locale_len < 12 && locale_len != 0 && locale_len != 1 && locale_len != 4 && locale_len != 9) {
- token = TOKEN_BEGIN_LOCALE;
- continue;
- } else {
- // TOKEN_ERROR
- error_substr = translations.substr(0, pos + 1);
- return;
- }
- }
- }
- break;
-
- case TOKEN_BEGIN_STRING_ID:
- if (!isSeparator(ch)) {
- size_t end;
- tchar c;
- for (end = pos; end < len; end++) {
- c = translations.at(end);
- if (!isValidStringIdCharacter(c))
- break;
- }
- c = translations.at(end);
- if (end < len && !isSeparator(c) && c != _T('=')) {
- // TOKEN_ERROR
- error_substr = translations.substr(0, end + 1);
- return;
- }
- stringId = translations.substr(pos, end - pos);
- if (!stringId.empty() && translMap.find(stringId) == translMap.end())
- translMap[stringId] = LocaleMap();
-
- token = TOKEN_END_STRING_ID;
- incr = end - pos;
- }
- break;
-
- case TOKEN_END_STRING_ID:
- if (!isSeparator(ch)) {
- if (ch == _T('=')) {
- token = TOKEN_BEGIN_VALUE;
- } else {
- // TOKEN_ERROR
- error_substr = translations.substr(0, pos + 1);
- return;
- }
- }
- break;
-
- case TOKEN_BEGIN_LOCALE: {
- size_t end;
- for (end = pos; end < len; end++) {
- tchar c = translations.at(end);
- if (!isValidLocaleCharacter(c))
- break;
- }
- size_t locale_len = end - pos;
- currentLocale = translations.substr(pos, locale_len);
- if (pos + locale_len == len) {
- error_substr = translations.substr(0, pos + locale_len);
- return;
- }
- token = TOKEN_END_LOCALE;
- incr = locale_len;
- break;
- }
-
- case TOKEN_END_LOCALE:
- if (!isSeparator(ch)) {
- if (ch == _T('.')) {
- token = TOKEN_BEGIN_STRING_ID;
- } else {
- // TOKEN_ERROR
- error_substr = translations.substr(0, pos + 1);
- return;
- }
- }
- break;
-
- case TOKEN_BEGIN_VALUE: {
- size_t end = translations.find_first_of(_T('\n'), pos);
- tstring val;
- if (end == tstring::npos) {
- val = translations.substr(pos);
- incr = len - pos;
- } else {
- val = translations.substr(pos, end - pos);
- incr = end - pos;
- }
-
- if (!val.empty() && val.back() == _T('\r'))
- val.pop_back();
-
- size_t p = val.find(_T("\\n"));
- while (p != std::string::npos) {
- val.replace(p, 2, _T("\\"));
- val[p] = _T('\n');
- p = val.find(_T("\\n"), p + 1);
- }
- if (!currentLocale.empty() && translMap.find(stringId) != translMap.end())
- translMap[stringId][currentLocale] = val;
-
- token = TOKEN_END_VALUE;
- break;
- }
-
- default:
- break;
- }
- pos += incr;
- if (pos == len)
- token = TOKEN_END_DOCUMENT;
- }
-
- if (token == TOKEN_END_DOCUMENT)
- is_translations_valid = true;
-}
diff --git a/win-linux/extras/update-daemon/src/classes/translator.h b/win-linux/extras/update-daemon/src/classes/translator.h
index 28bb5f680..0d8a99564 100644
--- a/win-linux/extras/update-daemon/src/classes/translator.h
+++ b/win-linux/extras/update-daemon/src/classes/translator.h
@@ -13,7 +13,7 @@
# define tstring std::string
#endif
-#define _TR(str) Translator::tr(#str)
+#define _TR(str) Translator::instance().tr(_T(#str))
using std::unordered_map;
@@ -24,24 +24,25 @@ typedef unordered_map TranslationsMap;
class Translator
{
public:
-#ifdef _WIN32
- Translator(const tstring &lang, int resourceId);
-#else
- Translator(const tstring &lang, const char *resourcePath);
-#endif
- ~Translator();
+ Translator(const Translator&) = delete;
+ Translator& operator=(const Translator&) = delete;
+ static Translator& instance();
- static tstring tr(const char*);
- static void setLanguage(const tstring &lang);
+#ifdef _WIN32
+ void init(const tstring &lang, int resourceId);
+#else
+ void init(const tstring &lang, const char *resourcePath);
+#endif
+ tstring tr(const tchar*) const;
+ void setLanguage(const tstring &lang);
private:
- void parseTranslations();
+ Translator();
+ ~Translator();
- static TranslationsMap translMap;
- tstring translations,
- error_substr;
- static tstring langName;
- static bool is_translations_valid;
+ TranslationsMap translMap;
+ tstring langName;
+ bool is_translations_valid;
enum TokenType {
TOKEN_BEGIN_DOCUMENT = 0,
diff --git a/win-linux/extras/update-daemon/src/platform_linux/main.cpp b/win-linux/extras/update-daemon/src/platform_linux/main.cpp
index f6eeaeacb..b3bdab154 100644
--- a/win-linux/extras/update-daemon/src/platform_linux/main.cpp
+++ b/win-linux/extras/update-daemon/src/platform_linux/main.cpp
@@ -65,7 +65,7 @@ int main(int argc, char *argv[])
NS_Logger::WriteLog(gSvcVersion);
}
std::locale::global(std::locale(""));
- Translator lang(NS_Utils::GetAppLanguage(), "/langs/langs.iss");
+ Translator::instance().init(NS_Utils::GetAppLanguage(), "/langs/langs.bin");
CSocket socket(0, INSTANCE_SVC_PORT);
if (!socket.isPrimaryInstance())
return 0;
diff --git a/win-linux/extras/update-daemon/src/platform_win/main.cpp b/win-linux/extras/update-daemon/src/platform_win/main.cpp
index 1a86236e0..87035e43f 100644
--- a/win-linux/extras/update-daemon/src/platform_win/main.cpp
+++ b/win-linux/extras/update-daemon/src/platform_win/main.cpp
@@ -105,7 +105,7 @@ int __cdecl _tmain (int argc, TCHAR *argv[])
NS_Logger::WriteLog(gSvcVersion);
}
std::locale::global(std::locale(""));
- Translator lang(NS_Utils::GetAppLanguage().c_str(), IDT_TRANSLATIONS);
+ Translator::instance().init(NS_Utils::GetAppLanguage().c_str(), IDT_TRANSLATIONS);
CSocket socket(0, INSTANCE_SVC_PORT);
if (!socket.isPrimaryInstance())
return 0;
@@ -147,7 +147,7 @@ int __cdecl _tmain (int argc, TCHAR *argv[])
}
std::locale::global(std::locale(""));
- Translator lang(NS_Utils::GetAppLanguage().c_str(), IDT_TRANSLATIONS);
+ Translator::instance().init(NS_Utils::GetAppLanguage().c_str(), IDT_TRANSLATIONS);
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{(LPTSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)SvcMain},
diff --git a/win-linux/src/cprintdata.cpp b/win-linux/src/cprintdata.cpp
index f4600a6ea..6267a2532 100644
--- a/win-linux/src/cprintdata.cpp
+++ b/win-linux/src/cprintdata.cpp
@@ -188,10 +188,12 @@ public:
PRINTER_INFO_4 *printers = reinterpret_cast(buf.data());
for (DWORD i = 0; i < ret; ++i) {
bool duplex_supported = (DeviceCapabilities(printers[i].pPrinterName, NULL, DC_DUPLEX, NULL, NULL) == 1);
+ bool color_supported = (DeviceCapabilities(printers[i].pPrinterName, NULL, DC_COLORDEVICE, NULL, NULL) == 1);
QJsonObject printerObject;
printerObject["name"] = QString::fromWCharArray(printers[i].pPrinterName);
printerObject["duplex_supported"] = duplex_supported;
+ printerObject["color_supported"] = color_supported;
constexpr int PAPER_NAME_LENGTH = 64;
bool paperNamesSuccess = false, paperSizeSuccess = false;
@@ -243,9 +245,18 @@ public:
QJsonObject printerObject;
printerObject["name"] = QString::fromUtf8(dest->name);
printerObject["duplex_supported"] = duplex_supported;
+ printerObject["color_supported"] = false;
ppd_option_t *option = ppdFirstOption(ppdF);
while (option) {
+ if (strcmp(option->keyword, "ColorModel") == 0) {
+ for (int j = 0; j < option->num_choices; j++) {
+ if (strcmp(option->choices[j].choice, "Gray") != 0) {
+ printerObject["color_supported"] = true;
+ break;
+ }
+ }
+ } else
if (strcmp(option->keyword, "PageSize") == 0) {
QJsonArray paperArray;
for (int j = 0; j < option->num_choices; j++) {