From 71f588a4fe7f4f51adace131ed54bc6df9d4aeb7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 10 Jan 2016 14:05:23 +0800 Subject: [PATCH] started signal handlers, shadow fixed in sticker-by-emoji, via @bot resize fixed --- Telegram/SourceFiles/_other/updater.cpp | 22 ++- Telegram/SourceFiles/_other/updater.h | 5 +- Telegram/SourceFiles/app.cpp | 2 +- Telegram/SourceFiles/application.cpp | 8 +- Telegram/SourceFiles/dropdown.cpp | 204 +++++++++++------------ Telegram/SourceFiles/facades.cpp | 2 +- Telegram/SourceFiles/history.cpp | 2 +- Telegram/SourceFiles/logs.cpp | 19 +-- Telegram/SourceFiles/logs.h | 2 +- Telegram/SourceFiles/main.cpp | 14 +- Telegram/SourceFiles/pspecific_linux.cpp | 14 +- Telegram/SourceFiles/pspecific_mac.cpp | 12 +- Telegram/SourceFiles/pspecific_wnd.cpp | 74 ++++---- Telegram/SourceFiles/pspecific_wnd.h | 3 +- Telegram/SourceFiles/settings.cpp | 8 +- Telegram/SourceFiles/stdafx.h | 6 - Telegram/SourceFiles/types.cpp | 43 +++++ Telegram/SourceFiles/types.h | 15 ++ 18 files changed, 253 insertions(+), 202 deletions(-) diff --git a/Telegram/SourceFiles/_other/updater.cpp b/Telegram/SourceFiles/_other/updater.cpp index 103803a88..a1dd35aa0 100644 --- a/Telegram/SourceFiles/_other/updater.cpp +++ b/Telegram/SourceFiles/_other/updater.cpp @@ -333,9 +333,8 @@ void updateRegistry() { int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) { openLog(); -#ifdef _NEED_WIN_GENERATE_DUMP _oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter); -#endif +// CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter); writeLog(L"Updaters started.."); @@ -465,7 +464,6 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara return 0; } -#ifdef _NEED_WIN_GENERATE_DUMP static const WCHAR *_programName = L"Telegram Desktop"; // folder in APPDATA, if current path is unavailable for writing static const WCHAR *_exeName = L"Updater.exe"; @@ -507,10 +505,10 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) { GetLocalTime(&stLocalTime); - wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", - szPath, szExeName, updaterVersionStr, - stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, - stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, + wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", + szPath, szExeName, updaterVersionStr, + stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, + stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, GetCurrentProcessId(), GetCurrentThreadId()); return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); } @@ -546,7 +544,7 @@ void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) { hDumpFile = _generateDumpFileAtPath(wstrPath); } } - + if (!hDumpFile || hDumpFile == INVALID_HANDLE_VALUE) { return; } @@ -564,4 +562,10 @@ LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) { return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH; } -#endif +// see http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li +LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) { + // When the CRT calls SetUnhandledExceptionFilter with NULL parameter + // our handler will not get removed. + _oldWndExceptionFilter = lpTopLevelExceptionFilter; + return 0; +} diff --git a/Telegram/SourceFiles/_other/updater.h b/Telegram/SourceFiles/_other/updater.h index 6afd341a3..b7f8fd8c0 100644 --- a/Telegram/SourceFiles/_other/updater.h +++ b/Telegram/SourceFiles/_other/updater.h @@ -32,12 +32,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org using std::deque; using std::wstring; -#define _NEED_WIN_GENERATE_DUMP - -#ifdef _NEED_WIN_GENERATE_DUMP extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter; LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers); -#endif _NEED_WIN_GENERATE_DUMP +LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); static int updaterVersion = 1000; static const WCHAR *updaterVersionStr = L"0.1.0"; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 5898cf1ac..c375fea47 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -935,7 +935,7 @@ namespace App { } void checkSavedGif(HistoryItem *item) { - if (!item->toHistoryForwarded() && item->out()) { + if (!item->toHistoryForwarded() && (item->out() || item->history()->peer == App::self())) { if (HistoryMedia *media = item->getMedia()) { if (DocumentData *doc = media->getDocument()) { if (doc->isGifv()) { diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index b455cb642..856174b53 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -208,7 +208,7 @@ void Application::updateGotCurrent() { if (!updateReply || updateThread) return; cSetLastUpdateCheck(unixtime()); - QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromUtf8(updateReply->readAll())); + QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromLatin1(updateReply->readAll())); if (m.hasMatch()) { uint64 currentVersion = m.captured(1).toULongLong(); QString url = m.captured(2); @@ -642,7 +642,7 @@ void Application::socketConnected() { } commands += qsl("CMD:show;"); DEBUG_LOG(("Application Info: writing commands %1").arg(commands)); - socket.write(commands.toLocal8Bit()); + socket.write(commands.toLatin1()); } void Application::socketWritten(qint64/* bytes*/) { @@ -799,13 +799,13 @@ void Application::readClients() { for (ClientSockets::iterator i = clients.begin(), e = clients.end(); i != e; ++i) { i->second.append(i->first->readAll()); if (i->second.size()) { - QString cmds(QString::fromLocal8Bit(i->second)); + QString cmds(QString::fromLatin1(i->second)); int32 from = 0, l = cmds.length(); for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) { QStringRef cmd(&cmds, from, to - from); if (cmd.startsWith(qsl("CMD:"))) { execExternal(cmds.mid(from + 4, to - from - 4)); - QByteArray response(qsl("RES:%1;").arg(QCoreApplication::applicationPid()).toUtf8()); + QByteArray response(qsl("RES:%1;").arg(QCoreApplication::applicationPid()).toLatin1()); i->first->write(response.data(), response.size()); } else if (cmd.startsWith(qsl("SEND:"))) { if (cSendPaths().isEmpty()) { diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index dc38319ad..0c706f7dc 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -3906,122 +3906,120 @@ void MentionsInner::paintEvent(QPaintEvent *e) { } } } - return; - } + } else { + int32 from = qFloor(e->rect().top() / st::mentionHeight), to = qFloor(e->rect().bottom() / st::mentionHeight) + 1; + int32 last = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size(); + bool hasUsername = _parent->filter().indexOf('@') > 1; + for (int32 i = from; i < to; ++i) { + if (i >= last) break; - int32 from = qFloor(e->rect().top() / st::mentionHeight), to = qFloor(e->rect().bottom() / st::mentionHeight) + 1; - int32 last = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size(); - bool hasUsername = _parent->filter().indexOf('@') > 1; - for (int32 i = from; i < to; ++i) { - if (i >= last) break; - - bool selected = (i == _sel); - if (selected) { - p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b); - int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2; - if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon); - } - p.setPen(st::black->p); - if (!_mrows->isEmpty()) { - UserData *user = _mrows->at(i); - QString first = (_parent->filter().size() < 2) ? QString() : ('@' + user->username.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('@' + user->username) : user->username.mid(_parent->filter().size() - 1); - int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth(); - if (mentionwidth < unamewidth + namewidth) { - namewidth = (mentionwidth * namewidth) / (namewidth + unamewidth); - unamewidth = mentionwidth - namewidth; - if (firstwidth < unamewidth + st::mentionFont->elidew) { - if (firstwidth < unamewidth) { - first = st::mentionFont->elided(first, unamewidth); - } else if (!second.isEmpty()) { - first = st::mentionFont->elided(first + second, unamewidth); - second = QString(); + bool selected = (i == _sel); + if (selected) { + p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b); + int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2; + if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon); + } + p.setPen(st::black->p); + if (!_mrows->isEmpty()) { + UserData *user = _mrows->at(i); + QString first = (_parent->filter().size() < 2) ? QString() : ('@' + user->username.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('@' + user->username) : user->username.mid(_parent->filter().size() - 1); + int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth(); + if (mentionwidth < unamewidth + namewidth) { + namewidth = (mentionwidth * namewidth) / (namewidth + unamewidth); + unamewidth = mentionwidth - namewidth; + if (firstwidth < unamewidth + st::mentionFont->elidew) { + if (firstwidth < unamewidth) { + first = st::mentionFont->elided(first, unamewidth); + } else if (!second.isEmpty()) { + first = st::mentionFont->elided(first + second, unamewidth); + second = QString(); + } + } else { + second = st::mentionFont->elided(second, unamewidth - firstwidth); } - } else { - second = st::mentionFont->elided(second, unamewidth - firstwidth); } - } - user->photo->load(); - p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize)); - user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth); - - p.setFont(st::mentionFont->f); - p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p); - p.drawText(mentionleft + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first); - if (!second.isEmpty()) { - p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); - p.drawText(mentionleft + namewidth + st::mentionPadding.right() + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second); - } - } else if (!_hrows->isEmpty()) { - QString hrow = _hrows->at(i); - QString first = (_parent->filter().size() < 2) ? QString() : ('#' + hrow.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('#' + hrow) : hrow.mid(_parent->filter().size() - 1); - int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second); - if (htagwidth < firstwidth + secondwidth) { - if (htagwidth < firstwidth + st::mentionFont->elidew) { - first = st::mentionFont->elided(first + second, htagwidth); - second = QString(); - } else { - second = st::mentionFont->elided(second, htagwidth - firstwidth); - } - } - - p.setFont(st::mentionFont->f); - if (!first.isEmpty()) { - p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p); - p.drawText(htagleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first); - } - if (!second.isEmpty()) { - p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); - p.drawText(htagleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second); - } - } else { - UserData *user = _brows->at(i).first; - - const BotCommand *command = _brows->at(i).second; - QString toHighlight = command->command; - int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1); - if (hasUsername || botStatus == 0 || botStatus == 2) { - toHighlight += '@' + user->username; - } - if (true || _parent->chat() || botStatus == 0 || botStatus == 2) { user->photo->load(); p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize)); - } + user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth); - int32 addleft = 0, widthleft = mentionwidth; - QString first = (_parent->filter().size() < 2) ? QString() : ('/' + toHighlight.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('/' + toHighlight) : toHighlight.mid(_parent->filter().size() - 1); - int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second); - if (widthleft < firstwidth + secondwidth) { - if (widthleft < firstwidth + st::mentionFont->elidew) { - first = st::mentionFont->elided(first + second, widthleft); - second = QString(); - } else { - second = st::mentionFont->elided(second, widthleft - firstwidth); + p.setFont(st::mentionFont->f); + p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p); + p.drawText(mentionleft + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first); + if (!second.isEmpty()) { + p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); + p.drawText(mentionleft + namewidth + st::mentionPadding.right() + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second); + } + } else if (!_hrows->isEmpty()) { + QString hrow = _hrows->at(i); + QString first = (_parent->filter().size() < 2) ? QString() : ('#' + hrow.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('#' + hrow) : hrow.mid(_parent->filter().size() - 1); + int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second); + if (htagwidth < firstwidth + secondwidth) { + if (htagwidth < firstwidth + st::mentionFont->elidew) { + first = st::mentionFont->elided(first + second, htagwidth); + second = QString(); + } else { + second = st::mentionFont->elided(second, htagwidth - firstwidth); + } + } + + p.setFont(st::mentionFont->f); + if (!first.isEmpty()) { + p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p); + p.drawText(htagleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first); + } + if (!second.isEmpty()) { + p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); + p.drawText(htagleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second); + } + } else { + UserData *user = _brows->at(i).first; + + const BotCommand *command = _brows->at(i).second; + QString toHighlight = command->command; + int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1); + if (hasUsername || botStatus == 0 || botStatus == 2) { + toHighlight += '@' + user->username; + } + if (true || _parent->chat() || botStatus == 0 || botStatus == 2) { + user->photo->load(); + p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize)); + } + + int32 addleft = 0, widthleft = mentionwidth; + QString first = (_parent->filter().size() < 2) ? QString() : ('/' + toHighlight.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('/' + toHighlight) : toHighlight.mid(_parent->filter().size() - 1); + int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second); + if (widthleft < firstwidth + secondwidth) { + if (widthleft < firstwidth + st::mentionFont->elidew) { + first = st::mentionFont->elided(first + second, widthleft); + second = QString(); + } else { + second = st::mentionFont->elided(second, widthleft - firstwidth); + } + } + p.setFont(st::mentionFont->f); + if (!first.isEmpty()) { + p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p); + p.drawText(mentionleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first); + } + if (!second.isEmpty()) { + p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); + p.drawText(mentionleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second); + } + addleft += firstwidth + secondwidth + st::mentionPadding.left(); + widthleft -= firstwidth + secondwidth + st::mentionPadding.left(); + if (widthleft > st::mentionFont->elidew && !command->descriptionText().isEmpty()) { + p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); + command->descriptionText().drawElided(p, mentionleft + addleft, i * st::mentionHeight + st::mentionTop, widthleft, 1, style::al_right); } } - p.setFont(st::mentionFont->f); - if (!first.isEmpty()) { - p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p); - p.drawText(mentionleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first); - } - if (!second.isEmpty()) { - p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); - p.drawText(mentionleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second); - } - addleft += firstwidth + secondwidth + st::mentionPadding.left(); - widthleft -= firstwidth + secondwidth + st::mentionPadding.left(); - if (widthleft > st::mentionFont->elidew && !command->descriptionText().isEmpty()) { - p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); - command->descriptionText().drawElided(p, mentionleft + addleft, i * st::mentionHeight + st::mentionTop, widthleft, 1, style::al_right); - } } + p.fillRect(cWideMode() ? st::lineWidth : 0, _parent->innerBottom() - st::lineWidth, width() - (cWideMode() ? st::lineWidth : 0), st::lineWidth, st::shadowColor->b); } - p.fillRect(cWideMode() ? st::lineWidth : 0, _parent->innerTop(), width() - (cWideMode() ? st::lineWidth : 0), st::lineWidth, st::shadowColor->b); - p.fillRect(cWideMode() ? st::lineWidth : 0, _parent->innerBottom() - st::lineWidth, width() - (cWideMode() ? st::lineWidth : 0), st::lineWidth, st::shadowColor->b); } void MentionsInner::resizeEvent(QResizeEvent *e) { - _stickersPerRow = int32(width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()); + _stickersPerRow = qMax(1, int32(width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width())); } void MentionsInner::mouseMoveEvent(QMouseEvent *e) { @@ -4514,7 +4512,7 @@ void MentionsDropdown::setBoundings(QRect boundings) { void MentionsDropdown::recount(bool resetScroll) { int32 h = 0, oldst = _scroll.scrollTop(), st = oldst, maxh = 4.5 * st::mentionHeight; if (!_srows.isEmpty()) { - int32 stickersPerRow = int32(_boundings.width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()); + int32 stickersPerRow = qMax(1, int32(_boundings.width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width())); int32 rows = rowscount(_srows.size(), stickersPerRow); h = st::stickerPanPadding + rows * st::stickerPanSize.height(); } else if (!_mrows.isEmpty()) { diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index b8befffe4..683b3cd27 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -178,7 +178,7 @@ namespace Notify { namespace Global { struct Data { - uint64 LaunchId; + uint64 LaunchId = 0; }; Data *_data = 0; diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index f76055744..8f49eed68 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -2499,6 +2499,7 @@ MsgId History::msgIdForRead() const { int32 History::geomResize(int32 newWidth, int32 *ytransform, const HistoryItem *resizedItem) { if (width != newWidth) resizedItem = 0; // recount all items if (width != newWidth || resizedItem) { + width = newWidth; int32 y = 0; for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) { HistoryBlock *block = *i; @@ -2513,7 +2514,6 @@ int32 History::geomResize(int32 newWidth, int32 *ytransform, const HistoryItem * ytransform = 0; } } - width = newWidth; height = y; } return height; diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index 41529c94a..9004d46ab 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -30,13 +30,6 @@ namespace { QMutex debugLogMutex, mainLogMutex; - class _StreamCreator { - public: - ~_StreamCreator() { - logsClose(); - } - }; - QString debugLogEntryStart() { static uint32 logEntry = 0; @@ -45,7 +38,7 @@ namespace { QThread *thread = QThread::currentThread(); MTPThread *mtpThread = qobject_cast(thread); uint32 threadId = mtpThread ? mtpThread->getThreadId() : 0; - + return QString("[%1 %2-%3]").arg(tm.toString("hh:mm:ss.zzz")).arg(QString("%1").arg(threadId, 2, 10, zero)).arg(++logEntry, 7, 10, zero); } } @@ -179,9 +172,8 @@ void moveOldDataFiles(const QString &wasDir) { } } -void logsInit() { - static _StreamCreator streamCreator; - if (mainLogStream) return; +bool logsInit() { + t_assert(mainLogStream == 0); QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta")); if (cBetaVersion()) { @@ -283,6 +275,7 @@ void logsInit() { } QDir().setCurrent(cWorkingDir()); + return true; } void logsInitDebug() { @@ -398,7 +391,7 @@ void logsClose() { } QString logVectorLong(const QVector &ids) { - if (!ids.size()) return "[void list]"; + if (!ids.size()) return "[]"; QString idsStr = QString("[%1").arg(ids.cbegin()->v); for (QVector::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) { idsStr += QString(", %2").arg(i->v); @@ -407,7 +400,7 @@ QString logVectorLong(const QVector &ids) { } QString logVectorLong(const QVector &ids) { - if (!ids.size()) return "[void list]"; + if (!ids.size()) return "[]"; QString idsStr = QString("[%1").arg(*ids.cbegin()); for (QVector::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) { idsStr += QString(", %2").arg(*i); diff --git a/Telegram/SourceFiles/logs.h b/Telegram/SourceFiles/logs.h index bb54a12d5..ff75a6f21 100644 --- a/Telegram/SourceFiles/logs.h +++ b/Telegram/SourceFiles/logs.h @@ -92,6 +92,6 @@ inline void t_assert_fail(const char *message, const char *file, int32 line) { #define t_assert_c(condition, comment) t_assert_full(condition, "\"" #condition "\" (" comment ")", __FILE__, __LINE__) #define t_assert(condition) t_assert_full(condition, "\"" #condition "\"", __FILE__, __LINE__) -void logsInit(); +bool logsInit(); void logsInitDebug(); void logsClose(); diff --git a/Telegram/SourceFiles/main.cpp b/Telegram/SourceFiles/main.cpp index a64c8641d..13e86c4d1 100644 --- a/Telegram/SourceFiles/main.cpp +++ b/Telegram/SourceFiles/main.cpp @@ -25,11 +25,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "localstorage.h" int main(int argc, char *argv[]) { -#ifdef _NEED_WIN_GENERATE_DUMP +#ifdef Q_OS_WIN _oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter); -#endif -#ifdef _NEED_LINUX_GENERATE_DUMP - //signal(SIGSEGV, _sigsegvHandler); +// CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter); #endif settingsParseArgs(argc, argv); @@ -40,7 +38,11 @@ int main(int argc, char *argv[]) { return psCleanup(); } } - logsInit(); + if (!logsInit()) { + return 0; + } + + installSignalHandlers(); Global::Initializer _init; @@ -58,7 +60,7 @@ int main(int argc, char *argv[]) { if (cDebug()) { LOG(("Application Info: Telegram started in debug mode")); for (int32 i = 0; i < argc; ++i) { - LOG(("Argument: %1").arg(QString::fromLocal8Bit(argv[i]))); + LOG(("Argument: %1").arg(fromUtf8Safe(argv[i]))); } QStringList logs = psInitLogs(); for (int32 i = 0, l = logs.size(); i < l; ++i) { diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp index b4efe2a77..35e208f8a 100644 --- a/Telegram/SourceFiles/pspecific_linux.cpp +++ b/Telegram/SourceFiles/pspecific_linux.cpp @@ -1,17 +1,17 @@ /* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org - + Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org */ @@ -667,7 +667,7 @@ void PsMainWindow::psUpdateCounter() { } else if (trayIcon) { int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; - + style::color bg = muted ? st::counterMuteBG : st::counterBG; QIcon iconSmall; iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(16, counter, bg, true), Qt::ColorOnly)); @@ -1072,7 +1072,7 @@ QString psCurrentLanguage() { namespace { QString _psHomeDir() { struct passwd *pw = getpwuid(getuid()); - return (pw && pw->pw_dir && strlen(pw->pw_dir)) ? (QString::fromLocal8Bit(pw->pw_dir) + '/') : QString(); + return (pw && pw->pw_dir && strlen(pw->pw_dir)) ? (fromUtf8Safe(pw->pw_dir) + '/') : QString(); } } @@ -1086,7 +1086,7 @@ QString psDownloadPath() { } QString psCurrentExeDirectory(int argc, char *argv[]) { - QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); + QString first = argc ? fromUtf8Safe(argv[0]) : QString(); if (!first.isEmpty()) { QFileInfo info(first); if (info.isSymLink()) { @@ -1100,7 +1100,7 @@ QString psCurrentExeDirectory(int argc, char *argv[]) { } QString psCurrentExeName(int argc, char *argv[]) { - QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); + QString first = argc ? fromUtf8Safe(argv[0]) : QString(); if (!first.isEmpty()) { QFileInfo info(first); if (info.isSymLink()) { diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp index 420ff8ad9..266da76f1 100644 --- a/Telegram/SourceFiles/pspecific_mac.cpp +++ b/Telegram/SourceFiles/pspecific_mac.cpp @@ -1,17 +1,17 @@ /* This file is part of Telegram Desktop, the official desktop version of Telegram messaging app, see https://telegram.org - + Telegram Desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org */ @@ -83,7 +83,7 @@ void MacPrivate::notifyClicked(unsigned long long peer, int msgid) { void MacPrivate::notifyReplied(unsigned long long peer, int msgid, const char *str) { History *history = App::history(PeerId(peer)); - + App::main()->sendMessage(history, QString::fromUtf8(str), (msgid > 0 && !history->peer->isUser()) ? msgid : 0, false); } @@ -592,7 +592,7 @@ QString psDownloadPath() { } QString psCurrentExeDirectory(int argc, char *argv[]) { - QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); + QString first = argc ? fromUtf8Safe(argv[0]) : QString(); if (!first.isEmpty()) { QFileInfo info(first); if (info.exists()) { @@ -603,7 +603,7 @@ QString psCurrentExeDirectory(int argc, char *argv[]) { } QString psCurrentExeName(int argc, char *argv[]) { - QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); + QString first = argc ? fromUtf8Safe(argv[0]) : QString(); if (!first.isEmpty()) { QFileInfo info(first); if (info.exists()) { diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp index 6f5c0794f..9db1afd29 100644 --- a/Telegram/SourceFiles/pspecific_wnd.cpp +++ b/Telegram/SourceFiles/pspecific_wnd.cpp @@ -106,7 +106,7 @@ namespace { bool sessionLoggedOff = false; UINT tbCreatedMsgId = 0; - + ComPtr taskbarList; ComPtr toastNotificationManager; @@ -132,7 +132,7 @@ namespace { HWND createTaskbarHider() { HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); HWND hWnd = 0; - + QString cn = QString("TelegramTaskbarHider"); LPCWSTR _cn = (LPCWSTR)cn.utf16(); WNDCLASSEX wc; @@ -153,7 +153,7 @@ namespace { DEBUG_LOG(("Application Error: could not register taskbar hider window class, error: %1").arg(GetLastError())); return hWnd; } - + hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0); if (!hWnd) { DEBUG_LOG(("Application Error: could not create taskbar hider window class, error: %1").arg(GetLastError())); @@ -186,12 +186,12 @@ namespace { hwnds[i] = 0; } } - + void setColor(QColor c) { r = c.red(); g = c.green(); b = c.blue(); - + if (!hwnds[0]) return; Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); for (int i = 0; i < 4; ++i) { @@ -251,7 +251,7 @@ namespace { Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; Gdiplus::Status gdiRes = Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); - + if (gdiRes != Gdiplus::Ok) { LOG(("Application Error: could not init GDI+, error: %1").arg((int)gdiRes)); return false; @@ -460,7 +460,7 @@ namespace { from = _fullsize - (_size - _shift); max_w *= 2; for (int i = 0; i < 4; i += 2) { - DeleteObject(bitmaps[i]); + DeleteObject(bitmaps[i]); bitmaps[i] = CreateCompatibleBitmap(screenDC, max_w, _size); SelectObject(dcs[i], bitmaps[i]); } @@ -549,7 +549,7 @@ namespace { _y = y; _w = w; _h = h; - + if (hidden && (changes & _PsShadowShown)) { for (int i = 0; i < 4; ++i) { SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE); @@ -680,7 +680,7 @@ namespace { typedef HRESULT (FAR STDAPICALLTYPE *f_shOpenWithDialog)(HWND hwndParent, const OPENASINFO *poainfo); f_shOpenWithDialog shOpenWithDialog = 0; - + typedef HRESULT (FAR STDAPICALLTYPE *f_shAssocEnumHandlers)(PCWSTR pszExtra, ASSOC_FILTER afFilter, IEnumAssocHandlers **ppEnumHandler); f_shAssocEnumHandlers shAssocEnumHandlers = 0; @@ -695,7 +695,7 @@ namespace { typedef HRESULT (FAR STDAPICALLTYPE *f_shQueryUserNotificationState)(QUERY_USER_NOTIFICATION_STATE *pquns); f_shQueryUserNotificationState shQueryUserNotificationState = 0; - + typedef HRESULT (FAR STDAPICALLTYPE *f_setCurrentProcessExplicitAppUserModelID)(__in PCWSTR AppID); f_setCurrentProcessExplicitAppUserModelID setCurrentProcessExplicitAppUserModelID = 0; @@ -849,7 +849,7 @@ namespace { QTimer::singleShot(0, Application::wnd(), SLOT(updateCounter())); Application::wnd()->update(); } return false; - + case WM_NCPAINT: if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; *result = 0; return true; case WM_NCCALCSIZE: { @@ -936,7 +936,7 @@ namespace { case HitTestBottomLeft: *result = HTBOTTOMLEFT; break; case HitTestLeft: *result = HTLEFT; break; case HitTestTopLeft: *result = HTTOPLEFT; break; - case HitTestNone: + case HitTestNone: default: *result = HTTRANSPARENT; break; }; } return true; @@ -951,7 +951,7 @@ namespace { GetWindowRect(hWnd, &r); HitTestType res = Application::wnd()->hitTest(QPoint(p.x - r.left + dleft, p.y - r.top + dtop)); switch (res) { - case HitTestIcon: + case HitTestIcon: if (menuHidden && getms() < menuHidden + 10) { menuHidden = 0; if (getms() < menuShown + GetDoubleClickTime()) { @@ -1229,7 +1229,7 @@ void PsMainWindow::psInitFrameless() { if (!ps_hWnd) return; if (useWtsapi) wtsRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION); - + if (frameless) { setWindowFlags(Qt::FramelessWindowHint); } @@ -1395,7 +1395,7 @@ void PsMainWindow::psUpdateMargins() { RECT w, m; GetWindowRect(ps_hWnd, &w); m = w; - + HMONITOR hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST); if (hMonitor) { MONITORINFO mi; @@ -1915,7 +1915,7 @@ void psDoFixPrevious() { LSTATUS newKeyRes2 = RegOpenKeyEx(HKEY_CURRENT_USER, newKeyStr2.toStdWString().c_str(), 0, KEY_READ, &newKey2); LSTATUS oldKeyRes1 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, oldKeyStr1.toStdWString().c_str(), 0, KEY_READ, &oldKey1); LSTATUS oldKeyRes2 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, oldKeyStr2.toStdWString().c_str(), 0, KEY_READ, &oldKey2); - + bool existNew1 = (newKeyRes1 == ERROR_SUCCESS) && (RegQueryValueEx(newKey1, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2; bool existNew2 = (newKeyRes2 == ERROR_SUCCESS) && (RegQueryValueEx(newKey2, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2; bool existOld1 = (oldKeyRes1 == ERROR_SUCCESS) && (RegQueryValueEx(oldKey1, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2; @@ -2048,7 +2048,7 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) { ULONG ulFetched = 0; hr = assocHandlers->Next(1, &handler, &ulFetched); if (FAILED(hr) || hr == S_FALSE || !ulFetched) break; - + LPWSTR name = 0; if (SUCCEEDED(handler->GetUIName(&name))) { LPWSTR icon = 0; @@ -2063,7 +2063,7 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) { } else { handler->Release(); } - } while (hr != S_FALSE); + } while (hr != S_FALSE); assocHandlers->Release(); } @@ -2201,7 +2201,7 @@ namespace { } return true; } - + bool _psSetKeyValue(HKEY rkey, LPCWSTR value, QString v) { static const int bufSize = 4096; DWORD defaultType, defaultSize = bufSize * 2; @@ -2352,7 +2352,6 @@ void psUpdateOverlayed(TWidget *widget) { if (!wv) widget->setAttribute(Qt::WA_WState_Visible, false); } -#ifdef _NEED_WIN_GENERATE_DUMP static const WCHAR *_programName = AppName; // folder in APPDATA, if current path is unavailable for writing static const WCHAR *_exeName = L"Telegram.exe"; @@ -2396,16 +2395,16 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) { GetLocalTime(&stLocalTime); if (cBetaVersion()) { - wsprintf(szFileName, L"%s%s-%ld-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", - szPath, szExeName, cBetaVersion(), - stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, - stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, + wsprintf(szFileName, L"%s%s-%ld-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", + szPath, szExeName, cBetaVersion(), + stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, + stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, GetCurrentProcessId(), GetCurrentThreadId()); } else { - wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", - szPath, szExeName, AppVersionStr, - stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, - stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, + wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", + szPath, szExeName, AppVersionStr, + stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, + stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, GetCurrentProcessId(), GetCurrentThreadId()); } return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); @@ -2455,9 +2454,16 @@ void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) { LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) { _generateDump(pExceptionPointers); - return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH; + return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH; +} + +// see http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li +LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) { + // When the CRT calls SetUnhandledExceptionFilter with NULL parameter + // our handler will not get removed. + _oldWndExceptionFilter = lpTopLevelExceptionFilter; + return 0; } -#endif class StringReferenceWrapper { public: @@ -2595,7 +2601,7 @@ public: ~ToastEventHandler() { } - // DesktopToastActivatedEventHandler + // DesktopToastActivatedEventHandler IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IInspectable* args) { ToastNotifications::iterator i = toastNotifications.find(_peerId); if (i != toastNotifications.cend()) { @@ -2867,7 +2873,7 @@ void CheckPinnedAppUserModelId() { QString path = pinnedPath(); std::wstring p = QDir::toNativeSeparators(path).toStdWString(); - + WCHAR src[MAX_PATH]; GetModuleFileName(GetModuleHandle(0), src, MAX_PATH); BY_HANDLE_FILE_INFORMATION srcinfo = { 0 }; @@ -2913,7 +2919,7 @@ void CheckPinnedAppUserModelId() { BOOL dstres = GetFileInformationByHandle(dstfile, &dstinfo); CloseHandle(dstfile); if (!dstres) continue; - + if (srcinfo.dwVolumeSerialNumber == dstinfo.dwVolumeSerialNumber && srcinfo.nFileIndexLow == dstinfo.nFileIndexLow && srcinfo.nFileIndexHigh == dstinfo.nFileIndexHigh) { ComPtr propertyStore; hr = shellLink.As(&propertyStore); @@ -3005,7 +3011,7 @@ void CleanupAppUserModelIdShortcut() { bool ValidateAppUserModelIdShortcutAt(const QString &path) { static const int maxFileLen = MAX_PATH * 10; - + std::wstring p = QDir::toNativeSeparators(path).toStdWString(); DWORD attributes = GetFileAttributes(p.c_str()); diff --git a/Telegram/SourceFiles/pspecific_wnd.h b/Telegram/SourceFiles/pspecific_wnd.h index 279de4c60..2d4232bf1 100644 --- a/Telegram/SourceFiles/pspecific_wnd.h +++ b/Telegram/SourceFiles/pspecific_wnd.h @@ -113,10 +113,9 @@ private: void psDestroyIcons(); }; -#ifdef _NEED_WIN_GENERATE_DUMP extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter; LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers); -#endif +LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); class PsApplication : public QApplication { Q_OBJECT diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index 6860e244a..0992e6a9f 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -199,7 +199,7 @@ void settingsParseArgs(int argc, char *argv[]) { } else if (string("-many") == argv[i]) { gManyInstance = true; } else if (string("-key") == argv[i] && i + 1 < argc) { - gKeyFile = QString::fromLocal8Bit(argv[++i]); + gKeyFile = fromUtf8Safe(argv[++i]); } else if (string("-autostart") == argv[i]) { gFromAutoStart = true; } else if (string("-noupdate") == argv[i]) { @@ -210,15 +210,15 @@ void settingsParseArgs(int argc, char *argv[]) { gStartInTray = true; } else if (string("-sendpath") == argv[i] && i + 1 < argc) { for (++i; i < argc; ++i) { - gSendPaths.push_back(QString::fromLocal8Bit(argv[i])); + gSendPaths.push_back(fromUtf8Safe(argv[i])); } } else if (string("-workdir") == argv[i] && i + 1 < argc) { - QString dir = QString::fromLocal8Bit(argv[++i]); + QString dir = fromUtf8Safe(argv[++i]); if (QDir().exists(dir)) { gWorkingDir = dir; } } else if (string("--") == argv[i] && i + 1 < argc) { - gStartUrl = QString::fromLocal8Bit(argv[++i]); + gStartUrl = fromUtf8Safe(argv[++i]); } } } diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index 104079dc6..bc67e1183 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -45,12 +45,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include #endif -#if defined Q_OS_WIN -#define _NEED_WIN_GENERATE_DUMP -#elif defined Q_OS_LINUX32 || defined Q_OS_LINUX64 -#define _NEED_LINUX_GENERATE_DUMP -#endif - extern "C" { #include diff --git a/Telegram/SourceFiles/types.cpp b/Telegram/SourceFiles/types.cpp index 0b3406426..ca7c917b4 100644 --- a/Telegram/SourceFiles/types.cpp +++ b/Telegram/SourceFiles/types.cpp @@ -22,6 +22,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org #include "application.h" +#include + uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 }; #ifdef Q_OS_WIN @@ -303,6 +305,47 @@ void deinitThirdParty() { _sslLocks = 0; } +namespace { + FILE *_crashDump = 0; + int _crashDumpNo = 0; +} + +void _signalHandler(int signum) { + const char* name = 0; + switch (signum) { + case SIGABRT: name = "SIGABRT"; break; + case SIGSEGV: name = "SIGSEGV"; break; + case SIGILL: name = "SIGILL"; break; + case SIGFPE: name = "SIGFPE"; break; +#ifndef Q_OS_WIN + case SIGBUS: name = "SIGBUS"; break; + case SIGSYS: name = "SIGSYS"; break; +#endif + } + LOG(("Caught signal %1").arg(name)); + if (name) + fprintf(stdout, "Caught signal %d (%s)\n", signum, name); + else + fprintf(stdout, "Caught signal %d\n", signum); + + + //printStackTrace(); +} + +void installSignalHandlers() { + _crashDump = fopen((cWorkingDir() + qsl("tdata/working")).toUtf8().constData(), "wb"); + if (_crashDump) _crashDumpNo = fileno(_crashDump); + + signal(SIGABRT, _signalHandler); + signal(SIGSEGV, _signalHandler); + signal(SIGILL, _signalHandler); + signal(SIGFPE, _signalHandler); +#ifndef Q_OS_WIN + signal(SIGBUS, _signalHandler); + signal(SIGSYS, _signalHandler); +#endif +} + bool checkms() { int64 unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime; int64 ms = int64(getms(true)); diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h index 264e4cfc1..3406ef1f0 100644 --- a/Telegram/SourceFiles/types.h +++ b/Telegram/SourceFiles/types.h @@ -133,6 +133,8 @@ inline void mylocaltime(struct tm * _Tm, const time_t * _Time) { #endif } +void installSignalHandlers(); + void initThirdParty(); // called by Global::Initializer void deinitThirdParty(); @@ -233,6 +235,19 @@ private: #define qsl(s) QStringLiteral(s) #define qstr(s) QLatin1String(s, sizeof(s) - 1) +inline QString fromUtf8Safe(const char *str, int32 size = -1) { + if (!str || !size) return QString(); + if (size < 0) size = int32(strlen(str)); + QString result(QString::fromUtf8(str, size)); + QByteArray back = result.toUtf8(); + if (back.size() != size || memcmp(back.constData(), str, size)) return QString::fromLocal8Bit(str, size); + return result; +} + +inline QString fromUtf8Safe(const QByteArray &str) { + return fromUtf8Safe(str.constData(), str.size()); +} + static const QRegularExpression::PatternOptions reMultiline(QRegularExpression::DotMatchesEverythingOption | QRegularExpression::MultilineOption); template