started signal handlers, shadow fixed in sticker-by-emoji, via @bot resize fixed

This commit is contained in:
John Preston 2016-01-10 14:05:23 +08:00
parent 5531f49c3e
commit 71f588a4fe
18 changed files with 253 additions and 202 deletions

View File

@ -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;
}

View File

@ -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";

View File

@ -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()) {

View File

@ -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()) {

View File

@ -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()) {

View File

@ -178,7 +178,7 @@ namespace Notify {
namespace Global {
struct Data {
uint64 LaunchId;
uint64 LaunchId = 0;
};
Data *_data = 0;

View File

@ -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;

View File

@ -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<MTPThread*>(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<MTPlong> &ids) {
if (!ids.size()) return "[void list]";
if (!ids.size()) return "[]";
QString idsStr = QString("[%1").arg(ids.cbegin()->v);
for (QVector<MTPlong>::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<MTPlong> &ids) {
}
QString logVectorLong(const QVector<uint64> &ids) {
if (!ids.size()) return "[void list]";
if (!ids.size()) return "[]";
QString idsStr = QString("[%1").arg(*ids.cbegin());
for (QVector<uint64>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) {
idsStr += QString(", %2").arg(*i);

View File

@ -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();

View File

@ -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) {

View File

@ -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()) {

View File

@ -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()) {

View File

@ -106,7 +106,7 @@ namespace {
bool sessionLoggedOff = false;
UINT tbCreatedMsgId = 0;
ComPtr<ITaskbarList3> taskbarList;
ComPtr<IToastNotificationManagerStatics> 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<IPropertyStore> 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());

View File

@ -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

View File

@ -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]);
}
}
}

View File

@ -45,12 +45,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include <lzma.h>
#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 <libavcodec/avcodec.h>

View File

@ -22,6 +22,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "application.h"
#include <signal.h>
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));

View File

@ -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 <typename T>