From 1979fd80424d16b2e489f9b57d01d9c7811d25a2 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Mon, 2 Jan 2023 21:10:29 +0300 Subject: Update copyrights --- plugins/SendScreenshotPlus/src/CSend.cpp | 1226 +++++------ plugins/SendScreenshotPlus/src/CSend.h | 274 +-- plugins/SendScreenshotPlus/src/CSendCloduFile.h | 100 +- plugins/SendScreenshotPlus/src/CSendCloudFile.cpp | 156 +- plugins/SendScreenshotPlus/src/CSendEmail.cpp | 402 ++-- plugins/SendScreenshotPlus/src/CSendEmail.h | 106 +- plugins/SendScreenshotPlus/src/CSendFTPFile.cpp | 186 +- plugins/SendScreenshotPlus/src/CSendFTPFile.h | 96 +- plugins/SendScreenshotPlus/src/CSendFile.cpp | 100 +- plugins/SendScreenshotPlus/src/CSendFile.h | 86 +- plugins/SendScreenshotPlus/src/CSendHTTPServer.cpp | 234 +- plugins/SendScreenshotPlus/src/CSendHTTPServer.h | 110 +- .../src/CSendHost_ImageShack.cpp | 236 +- .../SendScreenshotPlus/src/CSendHost_ImageShack.h | 98 +- plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp | 172 +- plugins/SendScreenshotPlus/src/CSendHost_imgur.h | 60 +- .../SendScreenshotPlus/src/CSendHost_uploadpie.cpp | 210 +- .../SendScreenshotPlus/src/CSendHost_uploadpie.h | 60 +- plugins/SendScreenshotPlus/src/Main.cpp | 672 +++--- plugins/SendScreenshotPlus/src/UMainForm.cpp | 2248 ++++++++++---------- plugins/SendScreenshotPlus/src/UMainForm.h | 292 +-- plugins/SendScreenshotPlus/src/Utils.cpp | 824 +++---- plugins/SendScreenshotPlus/src/Utils.h | 146 +- plugins/SendScreenshotPlus/src/ctrl_button.h | 66 +- plugins/SendScreenshotPlus/src/dlg_msgbox.cpp | 1428 ++++++------- plugins/SendScreenshotPlus/src/dlg_msgbox.h | 2 +- plugins/SendScreenshotPlus/src/stdafx.cxx | 2 +- plugins/SendScreenshotPlus/src/stdafx.h | 372 ++-- 28 files changed, 4982 insertions(+), 4982 deletions(-) (limited to 'plugins/SendScreenshotPlus/src') diff --git a/plugins/SendScreenshotPlus/src/CSend.cpp b/plugins/SendScreenshotPlus/src/CSend.cpp index 5a5e72e03e..3e83d4b6c6 100644 --- a/plugins/SendScreenshotPlus/src/CSend.cpp +++ b/plugins/SendScreenshotPlus/src/CSend.cpp @@ -1,613 +1,613 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" -#define CSEND_DIALOG 8800 - -///////////////////////////////////////////////////////////////////////////////////////// - -CSend::CSend(HWND /*Owner*/, MCONTACT hContact, bool bAsync, bool bSilent) : - m_bDeleteAfterSend(false), - m_bAsync(bAsync), - m_bSilent(bSilent), - m_pszFile(nullptr), - m_pszFileDesc(nullptr), - m_pszSendTyp(nullptr), - m_pszProto(nullptr), - m_EnableItem(0), - m_ChatRoom(0), - m_cbEventMsg(0), - m_hSend(nullptr), - m_hOnSend(nullptr), - m_ErrorMsg(nullptr), - m_ErrorTitle(nullptr) -{ - SetContact(hContact); -} - -CSend::~CSend() -{ - mir_free(m_pszFile); - mir_free(m_pszFileDesc); - mir_free(m_ErrorMsg); - mir_free(m_ErrorTitle); - if (m_hOnSend) UnhookEvent(m_hOnSend); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void CSend::SetContact(MCONTACT hContact) -{ - m_hContact = hContact; - if (hContact) { - m_pszProto = Proto_GetBaseAccountName(hContact); - m_ChatRoom = Contact::IsGroupChat(hContact, m_pszProto); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -INT_PTR CALLBACK CSend::ResultDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - Window_SetIcon_IcoLib(hwndDlg, GetIconHandle(ICO_MAIN)); - { - CSend *self = (CSend*)lParam; - SetDlgItemText(hwndDlg, IDC_HEADERBAR, CMStringW(TranslateT("Resulting URL from\n")) + self->m_pszSendTyp); - - SendDlgItemMessage(hwndDlg, IDC_HEADERBAR, WM_SETICON, ICON_BIG, (LPARAM)GetIconBtn(ICO_BTN_ARROWR)); - SetDlgItemTextA(hwndDlg, ID_edtURL, self->m_URL); - if (self->m_URLthumb) { - SetDlgItemTextA(hwndDlg, ID_edtURLthumb, self->m_URLthumb); - } - else { - SetDlgItemTextA(hwndDlg, ID_edtURLthumb, "-"); - for (int i = ID_btnThumbCopy; i <= ID_edtURLthumb; ++i) { - EnableWindow(GetDlgItem(hwndDlg, i), FALSE); - } - } - if (!self->m_pszFileDesc) - SetDlgItemText(hwndDlg, ID_bvlDesc, self->m_ErrorTitle); - else - SetDlgItemText(hwndDlg, ID_bvlDesc, self->m_pszFileDesc); - SendDlgItemMessage(hwndDlg, IDOK, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_COPY)); - SendDlgItemMessage(hwndDlg, IDOK, BUTTONTRANSLATE, 0, 0); - SendDlgItemMessage(hwndDlg, IDCANCEL, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_CANCEL)); - SendDlgItemMessage(hwndDlg, IDCANCEL, BUTTONTRANSLATE, 0, 0); - for (int i = ID_btnCopy; i <= ID_btnThumbBBC2; ++i) { - SendDlgItemMessage(hwndDlg, i, BUTTONSETASTHEMEDBTN, 0, 0); - SendDlgItemMessage(hwndDlg, i, BUTTONSETASFLATBTN, 1, 0); - switch (i) { - case ID_btnCopy: - case ID_btnThumbCopy: - SendDlgItemMessage(hwndDlg, i, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_COPY)); - SendDlgItemMessage(hwndDlg, i, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Copy"), BATF_UNICODE); - break; - case ID_btnBBC: - case ID_btnThumbBBC: - SendDlgItemMessage(hwndDlg, i, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_BBC)); - SendDlgItemMessage(hwndDlg, i, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Copy BBCode"), BATF_UNICODE); - break; - default: - SendDlgItemMessage(hwndDlg, i, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_BBCLNK)); - SendDlgItemMessage(hwndDlg, i, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Copy BBCode w/ link"), BATF_UNICODE); - } - } - } - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDCANCEL: - DestroyWindow(hwndDlg); - return TRUE; - - case IDOK: - case ID_btnCopy: - case ID_btnThumbCopy: - case ID_btnBBC: - case ID_btnThumbBBC: - case ID_btnThumbBBC2: - wchar_t tmp[2048]; - int edtID = ID_edtURL; - int bbc = 0; - switch (LOWORD(wParam)) { - case ID_btnThumbBBC2: ++bbc; - case ID_btnThumbBBC: ++bbc; - case ID_btnThumbCopy: - edtID = ID_edtURLthumb; - break; - case ID_btnBBC: ++bbc; - break; - } - size_t len; - if (bbc) { - if (bbc == 1) { - memcpy(tmp, L"[img]", 5 * sizeof(wchar_t)); len = 5; - len += GetDlgItemText(hwndDlg, edtID, tmp + len, 2048 - 11); - memcpy(tmp + len, L"[/img]", 7 * sizeof(wchar_t)); len += 7; - } - else { - memcpy(tmp, L"[url=", 5 * sizeof(wchar_t)); len = 5; - len += GetDlgItemText(hwndDlg, ID_edtURL, tmp + len, 1024); - memcpy(tmp + len, L"][img]", 6 * sizeof(wchar_t)); len += 6; - len += GetDlgItemText(hwndDlg, edtID, tmp + len, 1024); - memcpy(tmp + len, L"[/img][/url]", 13 * sizeof(wchar_t)); len += 12; - } - } - else len = GetDlgItemText(hwndDlg, edtID, tmp, _countof(tmp)); - - Utils_ClipboardCopy(CMStringW(tmp, len + 1)); - - if (LOWORD(wParam) == IDOK) - DestroyWindow(hwndDlg); - return TRUE; - } - } - return FALSE; -} - -void CSend::svcSendMsgExit(const char* szMessage) -{ - if (m_bSilent) { - Exit(ACKRESULT_SUCCESS); return; - } - if (!m_hContact) { - if (!m_pszFileDesc) - m_pszFileDesc = mir_a2u(szMessage); - Exit(CSEND_DIALOG); return; - } - - if (m_ChatRoom) { - CMStringW tmp(szMessage); - if (m_pszFileDesc) { - tmp.Append(L"\r\n"); - tmp.Append(m_pszFileDesc); - } - - int res = GC_RESULT_NOSESSION; - int cnt = g_chatApi.SM_GetCount(m_pszProto); - - // loop on all gc session to get the right (save) ptszID for the chatroom from m_hContact - GC_INFO gci = { 0 }; - gci.pszModule = m_pszProto; - for (int i = 0; i < cnt; i++) { - gci.iItem = i; - gci.Flags = GCF_BYINDEX | GCF_HCONTACT | GCF_ID; - Chat_GetInfo(&gci); - if (gci.hContact == m_hContact) { - Chat_SendUserMessage(m_pszProto, gci.pszID, tmp); - res = 200; - break; - } - } - Exit(res); return; - } - else { - m_szEventMsg = szMessage; - if (m_pszFileDesc && m_pszFileDesc[0] != NULL) { - m_szEventMsg.Append("\r\n"); - m_szEventMsg.Append(_T2A(m_pszFileDesc)); - m_cbEventMsg = m_szEventMsg.GetLength() + 1; - } - - // create a HookEventObj on ME_PROTO_ACK - if (!m_hOnSend) - m_hOnSend = HookEventObj(ME_PROTO_ACK, OnSend, this); - - // start PSS_MESSAGE service - m_hSend = (HANDLE)ProtoChainSend(m_hContact, PSS_MESSAGE, NULL, ptrA(mir_utf8encode(m_szEventMsg))); - - // check we actually got an ft handle back from the protocol - if (!m_hSend) { - Unhook(); - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); return; - } - } -} - -void CSend::svcSendFileExit() -{ - // szMessage should be encoded as the File followed by the description, the - // separator being a single nul (\0). If there is no description, do not forget - // to end the File with two nuls. - if (m_bSilent) { - Exit(ACKRESULT_SUCCESS); return; - } - - if (!m_hContact) { - Error(LPGENW("%s requires a valid contact!"), m_pszSendTyp); - Exit(ACKRESULT_FAILED); return; - } - - m_szEventMsg = _T2A(m_pszFile); - - if (m_pszFileDesc && m_pszFileDesc[0] != NULL) { - m_szEventMsg.AppendChar(0); - m_szEventMsg.Append(_T2A(m_pszFileDesc)); - } - - m_cbEventMsg = m_szEventMsg.GetLength() + 1; - - // Сreate a HookEventObj on ME_PROTO_ACK - if (!m_hOnSend) { - m_hOnSend = HookEventObj(ME_PROTO_ACK, OnSend, this); - } - - // Start miranda PSS_FILE based on mir ver (T) - wchar_t* ppFile[2] = { nullptr, nullptr }; - wchar_t* pDesc = mir_wstrdup(m_pszFileDesc); - ppFile[0] = mir_wstrdup(m_pszFile); - ppFile[1] = nullptr; - m_hSend = (HANDLE)ProtoChainSend(m_hContact, PSS_FILE, (WPARAM)pDesc, (LPARAM)ppFile); - mir_free(pDesc); - mir_free(ppFile[0]); - - // check we actually got an ft handle back from the protocol - if (!m_hSend) { - Unhook(); - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); return; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSend::OnSend(void *obj, WPARAM, LPARAM lParam) -{ - CSend* self = (CSend*)obj; - ACKDATA *ack = (ACKDATA*)lParam; - if (ack->hProcess != self->m_hSend) - return 0; - - switch (ack->result) { - case ACKRESULT_INITIALISING: // SetFtStatus(hwndDlg, LPGENW("Initialising..."), FTS_TEXT); break; - case ACKRESULT_CONNECTING: // SetFtStatus(hwndDlg, LPGENW("Connecting..."), FTS_TEXT); break; - case ACKRESULT_CONNECTPROXY: // SetFtStatus(hwndDlg, LPGENW("Connecting to proxy..."), FTS_TEXT); break; - case ACKRESULT_LISTENING: // SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT); break; - case ACKRESULT_CONNECTED: // SetFtStatus(hwndDlg, LPGENW("Connected"), FTS_TEXT); break; - case ACKRESULT_SENTREQUEST: // SetFtStatus(hwndDlg, LPGENW("Decision sent"), FTS_TEXT); break; - case ACKRESULT_NEXTFILE: // SetFtStatus(hwndDlg, LPGENW("Moving to next file..."), FTS_TEXT); - case ACKRESULT_FILERESUME: - case ACKRESULT_DATA: // transfer is on progress - break; - case ACKRESULT_DENIED: - self->Unhook(); - self->Exit(ack->result); - break; - case ACKRESULT_FAILED: - self->Unhook(); - self->Exit(ack->result); - // type=ACKTYPE_MESSAGE, result=success/failure, (char*)lParam=error message or NULL. - // type=ACKTYPE_FILE, result=ACKRESULT_FAILED then lParam=(LPARAM)(const char*)szReason - break; - case ACKRESULT_SUCCESS: - self->Unhook(); - switch (ack->type) { - case ACKTYPE_CHAT: - break; - case ACKTYPE_MESSAGE: - self->DB_EventAdd((uint16_t)EVENTTYPE_MESSAGE); - break; - case ACKTYPE_FILE: - self->m_szEventMsg.Insert(0, "aaaa"); - self->m_cbEventMsg += sizeof(uint32_t); - self->DB_EventAdd((uint16_t)EVENTTYPE_FILE); - break; - } - self->Exit(ack->result); - break; - } - return 0; -} - -void CSend::DB_EventAdd(uint16_t EventType) -{ - DBEVENTINFO dbei = {}; - dbei.szModule = m_pszProto; - dbei.eventType = EventType; - dbei.flags = DBEF_SENT; - dbei.timestamp = time(0); - dbei.flags |= DBEF_UTF; - dbei.cbBlob = m_cbEventMsg; - dbei.pBlob = (uint8_t*)m_szEventMsg.GetString(); - db_event_add(m_hContact, &dbei); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void CSend::Error(LPCTSTR pszFormat, ...) -{ - wchar_t tszMsg[MAX_SECONDLINE]; - - mir_snwprintf(tszMsg, L"%s - %s", _A2W(MODULENAME), TranslateT("Error")); - mir_free(m_ErrorTitle), m_ErrorTitle = mir_wstrdup(tszMsg); - - va_list vl; - va_start(vl, pszFormat); - mir_vsnwprintf(tszMsg, _countof(tszMsg), TranslateW(pszFormat), vl); - va_end(vl); - mir_free(m_ErrorMsg), m_ErrorMsg = mir_wstrdup(tszMsg); - - memset(&m_box, 0, sizeof(MSGBOX)); - m_box.cbSize = sizeof(MSGBOX); - m_box.hParent = nullptr; - m_box.hiLogo = GetIcon(ICO_MAIN); - m_box.hiMsg = nullptr; - m_box.ptszTitle = m_ErrorTitle; - m_box.ptszMsg = m_ErrorMsg; - m_box.uType = MB_OK | MB_ICON_ERROR; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void CSend::Exit(unsigned int Result) -{ - if (!m_bSilent) { - bool err = true; - switch (Result) { - case CSEND_DIALOG: - Skin_PlaySound("FileDone"); - DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UResultForm), nullptr, ResultDialogProc, (LPARAM)this); - err = false; - break; - case ACKRESULT_SUCCESS: - case GC_RESULT_SUCCESS: - Skin_PlaySound("FileDone"); - err = false; - break; - case ACKRESULT_DENIED: - Skin_PlaySound("FileDenied"); - Error(L"%s (%i):\nFile transfer denied.", TranslateW(m_pszSendTyp), Result); - MsgBoxService(NULL, (LPARAM)&m_box); - err = false; - break; - case GC_RESULT_WRONGVER: // You appear to be using the wrong version of GC API. - Error(L"%s (%i):\nYou appear to be using the wrong version of GC API", TranslateT("GCHAT error"), Result); - break; - case GC_RESULT_ERROR: // An internal GC error occurred. - Error(L"%s (%i):\nAn internal GC error occurred.", TranslateT("GCHAT error"), Result); - break; - case GC_RESULT_NOSESSION: // contact has no open GC session - Error(L"%s (%i):\nContact has no open GC session.", TranslateT("GCHAT error"), Result); - break; - case ACKRESULT_FAILED: - default: - break; - } - if (err) { - Skin_PlaySound("FileFailed"); - if (m_ErrorMsg) MsgBoxService(NULL, (LPARAM)&m_box); - else MsgErr(nullptr, LPGENW("An unknown error has occurred.")); - } - } - if (m_pszFile && *m_pszFile && m_bDeleteAfterSend && m_EnableItem&SS_DLG_DELETEAFTERSSEND) { - DeleteFile(m_pszFile), m_pszFile = nullptr; - } - if (m_bAsync) - delete this; // deletes derived class since destructor is virtual (which also auto-calls base dtor) -} - -///////////////////////////////////////////////////////////////////////////////////////// -// helper functions used for HTTP uploads - -#define snprintf _snprintf - -const char* CSend::GetHTMLContent(char* str, const char* startTag, const char* endTag) -{ - char* begin = strstr(str, startTag); - if (!begin) return nullptr; - begin += mir_strlen(startTag) - 1; - for (; *begin != '>' && *begin; ++begin); - if (*begin) { - char* end = strstr(++begin, endTag); - if (end) *end = 0; - } - return begin; -} - -static void HTTPFormAppendData(NETLIBHTTPREQUEST* nlhr, size_t* dataMax, char** dataPos, const char* data, size_t len) -{ - nlhr->dataLength = (*dataPos - nlhr->pData); - if (nlhr->dataLength + len >= *dataMax) { - *dataPos = nlhr->pData; - *dataMax += 0x1000 + 0x1000 * (len >> 12); - nlhr->pData = (char*)mir_realloc(nlhr->pData, *dataMax); - if (!nlhr->pData) mir_free(*dataPos); - *dataPos = nlhr->pData; - if (!*dataPos) - return; - *dataPos += nlhr->dataLength; - } - if (data) { - memcpy(*dataPos, data, sizeof(char)*len); *dataPos += len; - nlhr->dataLength += (int)len; // not necessary - } -} - -void CSend::HTTPFormDestroy(NETLIBHTTPREQUEST* nlhr) -{ - mir_free(nlhr->headers[0].szValue), nlhr->headers[0].szValue = nullptr; - mir_free(nlhr->headers), nlhr->headers = nullptr; - mir_free(nlhr->pData), nlhr->pData = nullptr; -} - -int CSend::HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum) -{ - char boundary[16]; - memcpy(boundary, "--M461C/", 8); - { - union - { - uint32_t num; - unsigned char cr[4]; - }; num = GetTickCount() ^ 0x8000; - for (int i = 0; i < 4; ++i) { - unsigned char chcode = cr[i] >> 4; - boundary[8 + i * 2] = (chcode < 0x0a ? '0' : 'a' - 0x0a) + chcode; - chcode = cr[i] & 0x0f; - boundary[9 + i * 2] = (chcode < 0x0a ? '0' : 'a' - 0x0a) + chcode; - } - } - nlhr->cbSize = sizeof(NETLIBHTTPREQUEST); - nlhr->requestType = requestType; - nlhr->flags = NLHRF_HTTP11; - if (!strncmp(url, "https://", 8)) nlhr->flags |= NLHRF_SSL; - nlhr->szUrl = (char*)url; - nlhr->headersCount = 3; - for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { - if (!(iter->flags&HTTPFF_HEADER)) break; - ++nlhr->headersCount; - } - nlhr->headers = (NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr->headersCount); - { - char* contenttype = (char*)mir_alloc(sizeof(char)*(30 + 1 + sizeof(boundary))); - memcpy(contenttype, "multipart/form-data; boundary=", 30); - memcpy(contenttype + 30, boundary, sizeof(boundary)); - contenttype[30 + sizeof(boundary)] = '\0'; - nlhr->headers[0].szName = "Content-Type"; - nlhr->headers[0].szValue = contenttype; - nlhr->headers[1].szName = "User-Agent"; - nlhr->headers[1].szValue = __USER_AGENT_STRING; - nlhr->headers[2].szName = "Accept-Language"; - nlhr->headers[2].szValue = "en-us,en;q=0.8"; - int i = 3; - for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { - if (!(iter->flags&HTTPFF_HEADER)) break; - nlhr->headers[i].szName = (char*)iter->name; - nlhr->headers[i++].szValue = (char*)iter->value_str; - } - } - char* dataPos = nlhr->pData; - size_t dataMax = 0; - for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { - if (iter->flags&HTTPFF_HEADER) continue; - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, 2 + sizeof(boundary) + 40); - memset(dataPos, '-', 2); dataPos += 2; - memcpy(dataPos, boundary, sizeof(boundary)); dataPos += sizeof(boundary); - memcpy(dataPos, "\r\nContent-Disposition: form-data; name=\"", 40); dataPos += 40; - size_t namelen = mir_strlen(iter->name), valuelen = 0; - if (!(iter->flags&HTTPFF_INT)) - valuelen = mir_strlen(iter->value_str); - if (iter->flags&HTTPFF_FILE) { - const char* filename = strrchr(iter->value_str, '\\'); - if (!filename) filename = strrchr(iter->value_str, '/'); - if (!filename) filename = iter->value_str; - else ++filename; - valuelen = mir_strlen(filename); - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 13 + valuelen + 17); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"; filename=\"", 13); dataPos += 13; - memcpy(dataPos, filename, valuelen); dataPos += valuelen; - memcpy(dataPos, "\"\r\nContent-Type: ", 17); dataPos += 17; - /// add mime type - const char* mime = "application/octet-stream"; - const char* fileext = strrchr(filename, '.'); - if (fileext) { - if (!mir_strcmp(fileext, ".jpg") || !mir_strcmp(fileext, ".jpeg") || !mir_strcmp(fileext, ".jpe")) - mime = "image/jpeg"; - else if (!mir_strcmp(fileext, ".bmp")) - mime = "image/bmp"; - else if (!mir_strcmp(fileext, ".png")) - mime = "image/png"; - else if (!mir_strcmp(fileext, ".gif")) - mime = "image/gif"; - else if (!mir_strcmp(fileext, ".tif") || !mir_strcmp(fileext, ".tiff")) - mime = "image/tiff"; - } - HTTPFormAppendData(nlhr, &dataMax, &dataPos, mime, mir_strlen(mime)); - HTTPFormAppendData(nlhr, &dataMax, &dataPos, "\r\n\r\n", 4); - /// add file content - size_t filesize = 0; - FILE* fp = fopen(iter->value_str, "rb"); - if (fp) { - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); fseek(fp, 0, SEEK_SET); - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, filesize + 2); - if (fread(dataPos, 1, filesize, fp) != filesize) { - fclose(fp), fp = nullptr; - } - } - if (!fp) { - HTTPFormDestroy(nlhr); - Error(L"Error occurred when opening local file.\nAborting file upload..."); - Exit(ACKRESULT_FAILED); - return 1; - } - else - fclose(fp); - dataPos += filesize; - memcpy(dataPos, "\r\n", 2); dataPos += 2; - } - else if (iter->flags&HTTPFF_8BIT) { - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 38 + valuelen + 2); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"\r\nContent-Transfer-Encoding: 8bit\r\n\r\n", 38); dataPos += 38; - memcpy(dataPos, iter->value_str, valuelen); dataPos += valuelen; - memcpy(dataPos, "\r\n", 2); dataPos += 2; - } - else if (iter->flags&HTTPFF_INT) { - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 5 + 17/*max numbers*/ + 2); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"\r\n\r\n", 5); dataPos += 5; - int ret = snprintf(dataPos, 17, "%Id", iter->value_int); - if (ret < 17 && ret>0) dataPos += ret; - memcpy(dataPos, "\r\n", 2); dataPos += 2; - } - else { - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 5 + valuelen + 2); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"\r\n\r\n", 5); dataPos += 5; - memcpy(dataPos, iter->value_str, valuelen); dataPos += valuelen; - memcpy(dataPos, "\r\n", 2); dataPos += 2; - } - } - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, 2 + sizeof(boundary) + 4); - memset(dataPos, '-', 2); dataPos += 2; - memcpy(dataPos, boundary, sizeof(boundary)); dataPos += sizeof(boundary); - memcpy(dataPos, "--\r\n", 4); dataPos += 4; - nlhr->dataLength = dataPos - nlhr->pData; -#ifdef _DEBUG /// print request content to "_sendss_tmp" file for debugging - { - FILE* fp = fopen("_sendss_tmp", "wb"); - if (fp) { - fprintf(fp, "--Target-- %s\n", nlhr->szUrl); - for (int i = 0; i < nlhr->headersCount; ++i) { - fprintf(fp, "%s: %s\n", nlhr->headers[i].szName, nlhr->headers[i].szValue); - } - fprintf(fp, "\n\n"); - fwrite(nlhr->pData, 1, nlhr->dataLength, fp); - fclose(fp); - } - } -#endif // _DEBUG - return 0; -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#define CSEND_DIALOG 8800 + +///////////////////////////////////////////////////////////////////////////////////////// + +CSend::CSend(HWND /*Owner*/, MCONTACT hContact, bool bAsync, bool bSilent) : + m_bDeleteAfterSend(false), + m_bAsync(bAsync), + m_bSilent(bSilent), + m_pszFile(nullptr), + m_pszFileDesc(nullptr), + m_pszSendTyp(nullptr), + m_pszProto(nullptr), + m_EnableItem(0), + m_ChatRoom(0), + m_cbEventMsg(0), + m_hSend(nullptr), + m_hOnSend(nullptr), + m_ErrorMsg(nullptr), + m_ErrorTitle(nullptr) +{ + SetContact(hContact); +} + +CSend::~CSend() +{ + mir_free(m_pszFile); + mir_free(m_pszFileDesc); + mir_free(m_ErrorMsg); + mir_free(m_ErrorTitle); + if (m_hOnSend) UnhookEvent(m_hOnSend); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSend::SetContact(MCONTACT hContact) +{ + m_hContact = hContact; + if (hContact) { + m_pszProto = Proto_GetBaseAccountName(hContact); + m_ChatRoom = Contact::IsGroupChat(hContact, m_pszProto); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR CALLBACK CSend::ResultDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + Window_SetIcon_IcoLib(hwndDlg, GetIconHandle(ICO_MAIN)); + { + CSend *self = (CSend*)lParam; + SetDlgItemText(hwndDlg, IDC_HEADERBAR, CMStringW(TranslateT("Resulting URL from\n")) + self->m_pszSendTyp); + + SendDlgItemMessage(hwndDlg, IDC_HEADERBAR, WM_SETICON, ICON_BIG, (LPARAM)GetIconBtn(ICO_BTN_ARROWR)); + SetDlgItemTextA(hwndDlg, ID_edtURL, self->m_URL); + if (self->m_URLthumb) { + SetDlgItemTextA(hwndDlg, ID_edtURLthumb, self->m_URLthumb); + } + else { + SetDlgItemTextA(hwndDlg, ID_edtURLthumb, "-"); + for (int i = ID_btnThumbCopy; i <= ID_edtURLthumb; ++i) { + EnableWindow(GetDlgItem(hwndDlg, i), FALSE); + } + } + if (!self->m_pszFileDesc) + SetDlgItemText(hwndDlg, ID_bvlDesc, self->m_ErrorTitle); + else + SetDlgItemText(hwndDlg, ID_bvlDesc, self->m_pszFileDesc); + SendDlgItemMessage(hwndDlg, IDOK, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_COPY)); + SendDlgItemMessage(hwndDlg, IDOK, BUTTONTRANSLATE, 0, 0); + SendDlgItemMessage(hwndDlg, IDCANCEL, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_CANCEL)); + SendDlgItemMessage(hwndDlg, IDCANCEL, BUTTONTRANSLATE, 0, 0); + for (int i = ID_btnCopy; i <= ID_btnThumbBBC2; ++i) { + SendDlgItemMessage(hwndDlg, i, BUTTONSETASTHEMEDBTN, 0, 0); + SendDlgItemMessage(hwndDlg, i, BUTTONSETASFLATBTN, 1, 0); + switch (i) { + case ID_btnCopy: + case ID_btnThumbCopy: + SendDlgItemMessage(hwndDlg, i, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_COPY)); + SendDlgItemMessage(hwndDlg, i, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Copy"), BATF_UNICODE); + break; + case ID_btnBBC: + case ID_btnThumbBBC: + SendDlgItemMessage(hwndDlg, i, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_BBC)); + SendDlgItemMessage(hwndDlg, i, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Copy BBCode"), BATF_UNICODE); + break; + default: + SendDlgItemMessage(hwndDlg, i, BM_SETIMAGE, IMAGE_ICON, (LPARAM)GetIconBtn(ICO_BTN_BBCLNK)); + SendDlgItemMessage(hwndDlg, i, BUTTONADDTOOLTIP, (WPARAM)LPGENW("Copy BBCode w/ link"), BATF_UNICODE); + } + } + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDCANCEL: + DestroyWindow(hwndDlg); + return TRUE; + + case IDOK: + case ID_btnCopy: + case ID_btnThumbCopy: + case ID_btnBBC: + case ID_btnThumbBBC: + case ID_btnThumbBBC2: + wchar_t tmp[2048]; + int edtID = ID_edtURL; + int bbc = 0; + switch (LOWORD(wParam)) { + case ID_btnThumbBBC2: ++bbc; + case ID_btnThumbBBC: ++bbc; + case ID_btnThumbCopy: + edtID = ID_edtURLthumb; + break; + case ID_btnBBC: ++bbc; + break; + } + size_t len; + if (bbc) { + if (bbc == 1) { + memcpy(tmp, L"[img]", 5 * sizeof(wchar_t)); len = 5; + len += GetDlgItemText(hwndDlg, edtID, tmp + len, 2048 - 11); + memcpy(tmp + len, L"[/img]", 7 * sizeof(wchar_t)); len += 7; + } + else { + memcpy(tmp, L"[url=", 5 * sizeof(wchar_t)); len = 5; + len += GetDlgItemText(hwndDlg, ID_edtURL, tmp + len, 1024); + memcpy(tmp + len, L"][img]", 6 * sizeof(wchar_t)); len += 6; + len += GetDlgItemText(hwndDlg, edtID, tmp + len, 1024); + memcpy(tmp + len, L"[/img][/url]", 13 * sizeof(wchar_t)); len += 12; + } + } + else len = GetDlgItemText(hwndDlg, edtID, tmp, _countof(tmp)); + + Utils_ClipboardCopy(CMStringW(tmp, len + 1)); + + if (LOWORD(wParam) == IDOK) + DestroyWindow(hwndDlg); + return TRUE; + } + } + return FALSE; +} + +void CSend::svcSendMsgExit(const char* szMessage) +{ + if (m_bSilent) { + Exit(ACKRESULT_SUCCESS); return; + } + if (!m_hContact) { + if (!m_pszFileDesc) + m_pszFileDesc = mir_a2u(szMessage); + Exit(CSEND_DIALOG); return; + } + + if (m_ChatRoom) { + CMStringW tmp(szMessage); + if (m_pszFileDesc) { + tmp.Append(L"\r\n"); + tmp.Append(m_pszFileDesc); + } + + int res = GC_RESULT_NOSESSION; + int cnt = g_chatApi.SM_GetCount(m_pszProto); + + // loop on all gc session to get the right (save) ptszID for the chatroom from m_hContact + GC_INFO gci = { 0 }; + gci.pszModule = m_pszProto; + for (int i = 0; i < cnt; i++) { + gci.iItem = i; + gci.Flags = GCF_BYINDEX | GCF_HCONTACT | GCF_ID; + Chat_GetInfo(&gci); + if (gci.hContact == m_hContact) { + Chat_SendUserMessage(m_pszProto, gci.pszID, tmp); + res = 200; + break; + } + } + Exit(res); return; + } + else { + m_szEventMsg = szMessage; + if (m_pszFileDesc && m_pszFileDesc[0] != NULL) { + m_szEventMsg.Append("\r\n"); + m_szEventMsg.Append(_T2A(m_pszFileDesc)); + m_cbEventMsg = m_szEventMsg.GetLength() + 1; + } + + // create a HookEventObj on ME_PROTO_ACK + if (!m_hOnSend) + m_hOnSend = HookEventObj(ME_PROTO_ACK, OnSend, this); + + // start PSS_MESSAGE service + m_hSend = (HANDLE)ProtoChainSend(m_hContact, PSS_MESSAGE, NULL, ptrA(mir_utf8encode(m_szEventMsg))); + + // check we actually got an ft handle back from the protocol + if (!m_hSend) { + Unhook(); + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); return; + } + } +} + +void CSend::svcSendFileExit() +{ + // szMessage should be encoded as the File followed by the description, the + // separator being a single nul (\0). If there is no description, do not forget + // to end the File with two nuls. + if (m_bSilent) { + Exit(ACKRESULT_SUCCESS); return; + } + + if (!m_hContact) { + Error(LPGENW("%s requires a valid contact!"), m_pszSendTyp); + Exit(ACKRESULT_FAILED); return; + } + + m_szEventMsg = _T2A(m_pszFile); + + if (m_pszFileDesc && m_pszFileDesc[0] != NULL) { + m_szEventMsg.AppendChar(0); + m_szEventMsg.Append(_T2A(m_pszFileDesc)); + } + + m_cbEventMsg = m_szEventMsg.GetLength() + 1; + + // Сreate a HookEventObj on ME_PROTO_ACK + if (!m_hOnSend) { + m_hOnSend = HookEventObj(ME_PROTO_ACK, OnSend, this); + } + + // Start miranda PSS_FILE based on mir ver (T) + wchar_t* ppFile[2] = { nullptr, nullptr }; + wchar_t* pDesc = mir_wstrdup(m_pszFileDesc); + ppFile[0] = mir_wstrdup(m_pszFile); + ppFile[1] = nullptr; + m_hSend = (HANDLE)ProtoChainSend(m_hContact, PSS_FILE, (WPARAM)pDesc, (LPARAM)ppFile); + mir_free(pDesc); + mir_free(ppFile[0]); + + // check we actually got an ft handle back from the protocol + if (!m_hSend) { + Unhook(); + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); return; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSend::OnSend(void *obj, WPARAM, LPARAM lParam) +{ + CSend* self = (CSend*)obj; + ACKDATA *ack = (ACKDATA*)lParam; + if (ack->hProcess != self->m_hSend) + return 0; + + switch (ack->result) { + case ACKRESULT_INITIALISING: // SetFtStatus(hwndDlg, LPGENW("Initialising..."), FTS_TEXT); break; + case ACKRESULT_CONNECTING: // SetFtStatus(hwndDlg, LPGENW("Connecting..."), FTS_TEXT); break; + case ACKRESULT_CONNECTPROXY: // SetFtStatus(hwndDlg, LPGENW("Connecting to proxy..."), FTS_TEXT); break; + case ACKRESULT_LISTENING: // SetFtStatus(hwndDlg, LPGENW("Waiting for connection..."), FTS_TEXT); break; + case ACKRESULT_CONNECTED: // SetFtStatus(hwndDlg, LPGENW("Connected"), FTS_TEXT); break; + case ACKRESULT_SENTREQUEST: // SetFtStatus(hwndDlg, LPGENW("Decision sent"), FTS_TEXT); break; + case ACKRESULT_NEXTFILE: // SetFtStatus(hwndDlg, LPGENW("Moving to next file..."), FTS_TEXT); + case ACKRESULT_FILERESUME: + case ACKRESULT_DATA: // transfer is on progress + break; + case ACKRESULT_DENIED: + self->Unhook(); + self->Exit(ack->result); + break; + case ACKRESULT_FAILED: + self->Unhook(); + self->Exit(ack->result); + // type=ACKTYPE_MESSAGE, result=success/failure, (char*)lParam=error message or NULL. + // type=ACKTYPE_FILE, result=ACKRESULT_FAILED then lParam=(LPARAM)(const char*)szReason + break; + case ACKRESULT_SUCCESS: + self->Unhook(); + switch (ack->type) { + case ACKTYPE_CHAT: + break; + case ACKTYPE_MESSAGE: + self->DB_EventAdd((uint16_t)EVENTTYPE_MESSAGE); + break; + case ACKTYPE_FILE: + self->m_szEventMsg.Insert(0, "aaaa"); + self->m_cbEventMsg += sizeof(uint32_t); + self->DB_EventAdd((uint16_t)EVENTTYPE_FILE); + break; + } + self->Exit(ack->result); + break; + } + return 0; +} + +void CSend::DB_EventAdd(uint16_t EventType) +{ + DBEVENTINFO dbei = {}; + dbei.szModule = m_pszProto; + dbei.eventType = EventType; + dbei.flags = DBEF_SENT; + dbei.timestamp = time(0); + dbei.flags |= DBEF_UTF; + dbei.cbBlob = m_cbEventMsg; + dbei.pBlob = (uint8_t*)m_szEventMsg.GetString(); + db_event_add(m_hContact, &dbei); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSend::Error(LPCTSTR pszFormat, ...) +{ + wchar_t tszMsg[MAX_SECONDLINE]; + + mir_snwprintf(tszMsg, L"%s - %s", _A2W(MODULENAME), TranslateT("Error")); + mir_free(m_ErrorTitle), m_ErrorTitle = mir_wstrdup(tszMsg); + + va_list vl; + va_start(vl, pszFormat); + mir_vsnwprintf(tszMsg, _countof(tszMsg), TranslateW(pszFormat), vl); + va_end(vl); + mir_free(m_ErrorMsg), m_ErrorMsg = mir_wstrdup(tszMsg); + + memset(&m_box, 0, sizeof(MSGBOX)); + m_box.cbSize = sizeof(MSGBOX); + m_box.hParent = nullptr; + m_box.hiLogo = GetIcon(ICO_MAIN); + m_box.hiMsg = nullptr; + m_box.ptszTitle = m_ErrorTitle; + m_box.ptszMsg = m_ErrorMsg; + m_box.uType = MB_OK | MB_ICON_ERROR; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSend::Exit(unsigned int Result) +{ + if (!m_bSilent) { + bool err = true; + switch (Result) { + case CSEND_DIALOG: + Skin_PlaySound("FileDone"); + DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UResultForm), nullptr, ResultDialogProc, (LPARAM)this); + err = false; + break; + case ACKRESULT_SUCCESS: + case GC_RESULT_SUCCESS: + Skin_PlaySound("FileDone"); + err = false; + break; + case ACKRESULT_DENIED: + Skin_PlaySound("FileDenied"); + Error(L"%s (%i):\nFile transfer denied.", TranslateW(m_pszSendTyp), Result); + MsgBoxService(NULL, (LPARAM)&m_box); + err = false; + break; + case GC_RESULT_WRONGVER: // You appear to be using the wrong version of GC API. + Error(L"%s (%i):\nYou appear to be using the wrong version of GC API", TranslateT("GCHAT error"), Result); + break; + case GC_RESULT_ERROR: // An internal GC error occurred. + Error(L"%s (%i):\nAn internal GC error occurred.", TranslateT("GCHAT error"), Result); + break; + case GC_RESULT_NOSESSION: // contact has no open GC session + Error(L"%s (%i):\nContact has no open GC session.", TranslateT("GCHAT error"), Result); + break; + case ACKRESULT_FAILED: + default: + break; + } + if (err) { + Skin_PlaySound("FileFailed"); + if (m_ErrorMsg) MsgBoxService(NULL, (LPARAM)&m_box); + else MsgErr(nullptr, LPGENW("An unknown error has occurred.")); + } + } + if (m_pszFile && *m_pszFile && m_bDeleteAfterSend && m_EnableItem&SS_DLG_DELETEAFTERSSEND) { + DeleteFile(m_pszFile), m_pszFile = nullptr; + } + if (m_bAsync) + delete this; // deletes derived class since destructor is virtual (which also auto-calls base dtor) +} + +///////////////////////////////////////////////////////////////////////////////////////// +// helper functions used for HTTP uploads + +#define snprintf _snprintf + +const char* CSend::GetHTMLContent(char* str, const char* startTag, const char* endTag) +{ + char* begin = strstr(str, startTag); + if (!begin) return nullptr; + begin += mir_strlen(startTag) - 1; + for (; *begin != '>' && *begin; ++begin); + if (*begin) { + char* end = strstr(++begin, endTag); + if (end) *end = 0; + } + return begin; +} + +static void HTTPFormAppendData(NETLIBHTTPREQUEST* nlhr, size_t* dataMax, char** dataPos, const char* data, size_t len) +{ + nlhr->dataLength = (*dataPos - nlhr->pData); + if (nlhr->dataLength + len >= *dataMax) { + *dataPos = nlhr->pData; + *dataMax += 0x1000 + 0x1000 * (len >> 12); + nlhr->pData = (char*)mir_realloc(nlhr->pData, *dataMax); + if (!nlhr->pData) mir_free(*dataPos); + *dataPos = nlhr->pData; + if (!*dataPos) + return; + *dataPos += nlhr->dataLength; + } + if (data) { + memcpy(*dataPos, data, sizeof(char)*len); *dataPos += len; + nlhr->dataLength += (int)len; // not necessary + } +} + +void CSend::HTTPFormDestroy(NETLIBHTTPREQUEST* nlhr) +{ + mir_free(nlhr->headers[0].szValue), nlhr->headers[0].szValue = nullptr; + mir_free(nlhr->headers), nlhr->headers = nullptr; + mir_free(nlhr->pData), nlhr->pData = nullptr; +} + +int CSend::HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum) +{ + char boundary[16]; + memcpy(boundary, "--M461C/", 8); + { + union + { + uint32_t num; + unsigned char cr[4]; + }; num = GetTickCount() ^ 0x8000; + for (int i = 0; i < 4; ++i) { + unsigned char chcode = cr[i] >> 4; + boundary[8 + i * 2] = (chcode < 0x0a ? '0' : 'a' - 0x0a) + chcode; + chcode = cr[i] & 0x0f; + boundary[9 + i * 2] = (chcode < 0x0a ? '0' : 'a' - 0x0a) + chcode; + } + } + nlhr->cbSize = sizeof(NETLIBHTTPREQUEST); + nlhr->requestType = requestType; + nlhr->flags = NLHRF_HTTP11; + if (!strncmp(url, "https://", 8)) nlhr->flags |= NLHRF_SSL; + nlhr->szUrl = (char*)url; + nlhr->headersCount = 3; + for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { + if (!(iter->flags&HTTPFF_HEADER)) break; + ++nlhr->headersCount; + } + nlhr->headers = (NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr->headersCount); + { + char* contenttype = (char*)mir_alloc(sizeof(char)*(30 + 1 + sizeof(boundary))); + memcpy(contenttype, "multipart/form-data; boundary=", 30); + memcpy(contenttype + 30, boundary, sizeof(boundary)); + contenttype[30 + sizeof(boundary)] = '\0'; + nlhr->headers[0].szName = "Content-Type"; + nlhr->headers[0].szValue = contenttype; + nlhr->headers[1].szName = "User-Agent"; + nlhr->headers[1].szValue = __USER_AGENT_STRING; + nlhr->headers[2].szName = "Accept-Language"; + nlhr->headers[2].szValue = "en-us,en;q=0.8"; + int i = 3; + for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { + if (!(iter->flags&HTTPFF_HEADER)) break; + nlhr->headers[i].szName = (char*)iter->name; + nlhr->headers[i++].szValue = (char*)iter->value_str; + } + } + char* dataPos = nlhr->pData; + size_t dataMax = 0; + for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { + if (iter->flags&HTTPFF_HEADER) continue; + HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, 2 + sizeof(boundary) + 40); + memset(dataPos, '-', 2); dataPos += 2; + memcpy(dataPos, boundary, sizeof(boundary)); dataPos += sizeof(boundary); + memcpy(dataPos, "\r\nContent-Disposition: form-data; name=\"", 40); dataPos += 40; + size_t namelen = mir_strlen(iter->name), valuelen = 0; + if (!(iter->flags&HTTPFF_INT)) + valuelen = mir_strlen(iter->value_str); + if (iter->flags&HTTPFF_FILE) { + const char* filename = strrchr(iter->value_str, '\\'); + if (!filename) filename = strrchr(iter->value_str, '/'); + if (!filename) filename = iter->value_str; + else ++filename; + valuelen = mir_strlen(filename); + HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 13 + valuelen + 17); + memcpy(dataPos, iter->name, namelen); dataPos += namelen; + memcpy(dataPos, "\"; filename=\"", 13); dataPos += 13; + memcpy(dataPos, filename, valuelen); dataPos += valuelen; + memcpy(dataPos, "\"\r\nContent-Type: ", 17); dataPos += 17; + /// add mime type + const char* mime = "application/octet-stream"; + const char* fileext = strrchr(filename, '.'); + if (fileext) { + if (!mir_strcmp(fileext, ".jpg") || !mir_strcmp(fileext, ".jpeg") || !mir_strcmp(fileext, ".jpe")) + mime = "image/jpeg"; + else if (!mir_strcmp(fileext, ".bmp")) + mime = "image/bmp"; + else if (!mir_strcmp(fileext, ".png")) + mime = "image/png"; + else if (!mir_strcmp(fileext, ".gif")) + mime = "image/gif"; + else if (!mir_strcmp(fileext, ".tif") || !mir_strcmp(fileext, ".tiff")) + mime = "image/tiff"; + } + HTTPFormAppendData(nlhr, &dataMax, &dataPos, mime, mir_strlen(mime)); + HTTPFormAppendData(nlhr, &dataMax, &dataPos, "\r\n\r\n", 4); + /// add file content + size_t filesize = 0; + FILE* fp = fopen(iter->value_str, "rb"); + if (fp) { + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); fseek(fp, 0, SEEK_SET); + HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, filesize + 2); + if (fread(dataPos, 1, filesize, fp) != filesize) { + fclose(fp), fp = nullptr; + } + } + if (!fp) { + HTTPFormDestroy(nlhr); + Error(L"Error occurred when opening local file.\nAborting file upload..."); + Exit(ACKRESULT_FAILED); + return 1; + } + else + fclose(fp); + dataPos += filesize; + memcpy(dataPos, "\r\n", 2); dataPos += 2; + } + else if (iter->flags&HTTPFF_8BIT) { + HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 38 + valuelen + 2); + memcpy(dataPos, iter->name, namelen); dataPos += namelen; + memcpy(dataPos, "\"\r\nContent-Transfer-Encoding: 8bit\r\n\r\n", 38); dataPos += 38; + memcpy(dataPos, iter->value_str, valuelen); dataPos += valuelen; + memcpy(dataPos, "\r\n", 2); dataPos += 2; + } + else if (iter->flags&HTTPFF_INT) { + HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 5 + 17/*max numbers*/ + 2); + memcpy(dataPos, iter->name, namelen); dataPos += namelen; + memcpy(dataPos, "\"\r\n\r\n", 5); dataPos += 5; + int ret = snprintf(dataPos, 17, "%Id", iter->value_int); + if (ret < 17 && ret>0) dataPos += ret; + memcpy(dataPos, "\r\n", 2); dataPos += 2; + } + else { + HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 5 + valuelen + 2); + memcpy(dataPos, iter->name, namelen); dataPos += namelen; + memcpy(dataPos, "\"\r\n\r\n", 5); dataPos += 5; + memcpy(dataPos, iter->value_str, valuelen); dataPos += valuelen; + memcpy(dataPos, "\r\n", 2); dataPos += 2; + } + } + HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, 2 + sizeof(boundary) + 4); + memset(dataPos, '-', 2); dataPos += 2; + memcpy(dataPos, boundary, sizeof(boundary)); dataPos += sizeof(boundary); + memcpy(dataPos, "--\r\n", 4); dataPos += 4; + nlhr->dataLength = dataPos - nlhr->pData; +#ifdef _DEBUG /// print request content to "_sendss_tmp" file for debugging + { + FILE* fp = fopen("_sendss_tmp", "wb"); + if (fp) { + fprintf(fp, "--Target-- %s\n", nlhr->szUrl); + for (int i = 0; i < nlhr->headersCount; ++i) { + fprintf(fp, "%s: %s\n", nlhr->headers[i].szName, nlhr->headers[i].szValue); + } + fprintf(fp, "\n\n"); + fwrite(nlhr->pData, 1, nlhr->dataLength, fp); + fclose(fp); + } + } +#endif // _DEBUG + return 0; +} diff --git a/plugins/SendScreenshotPlus/src/CSend.h b/plugins/SendScreenshotPlus/src/CSend.h index 630222b69e..9301811f17 100644 --- a/plugins/SendScreenshotPlus/src/CSend.h +++ b/plugins/SendScreenshotPlus/src/CSend.h @@ -1,137 +1,137 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _CSEND_H -#define _CSEND_H - -///////////////////////////////////////////////////////////////////////////////////////// - -#define SS_AUTOSEND 1 -#define SS_DELETEAFTERSSEND 2 - -#define SS_DLG_AUTOSEND 1 // Button_Enable(GetDlgItem(Owner, ID_chkEmulateClick), TRUE); -#define SS_DLG_DELETEAFTERSSEND 2 // Button_Enable(GetDlgItem(Owner, ID_chkDeleteAfterSend), TRUE); -#define SS_DLG_DESCRIPTION 4 // Button_Enable(GetDlgItem(Owner, ID_chkDesc), TRUE); - -#define GC_RESULT_SUCCESS 200 -#define GC_RESULT_WRONGVER 201 -#define GC_RESULT_ERROR 202 -#define GC_RESULT_NOSESSION 209 - -const wchar_t SS_ERR_INIT[] = LPGENW("Unable to initiate %s."); -const wchar_t SS_ERR_MAPI[] = LPGENW("MAPI error (%i):\n%s."); -const wchar_t SS_ERR_RESPONSE[] = LPGENW("Unknown response from %s (%i)"); -const wchar_t SS_ERR_NORESPONSE[] = LPGENW("Got no response from %s (%i)"); - -///////////////////////////////////////////////////////////////////////////////////////// - -class CSend -{ -public: - CSend(HWND Owner, MCONTACT hContact, bool bAsync, bool bSilent=false); // oder (TfrmMain & Owner) - virtual ~CSend(); - - virtual int Send() = 0; // returns 1 if sent (you must delete class) and 0 when still sending (class deletes itself) - int SendSilent() { m_bAsync = m_bSilent = true; return Send(); } - - void SetFile(const wchar_t* file) { replaceStrW(m_pszFile, file); } - void SetFile(const char* file) { mir_free(m_pszFile), m_pszFile=mir_a2u(file); } - void SetDescription(const wchar_t* descr){ replaceStrW(m_pszFileDesc, descr); } - void SetContact(MCONTACT hContact); - const char* GetURL() { return m_URL; } - const char* GetURLthumbnail() {return m_URLthumb; } - uint8_t GetEnableItem() {return m_EnableItem;}; - wchar_t* GetErrorMsg() {return m_ErrorMsg;}; - - bool m_bDeleteAfterSend; - -protected: - bool m_bAsync; - bool m_bSilent; - wchar_t* m_pszFile; - wchar_t* m_pszFileDesc; - CMStringA m_URL; - CMStringA m_URLthumb; - static int OnSend(void *obj, WPARAM wParam, LPARAM lParam); - wchar_t* m_pszSendTyp; // hold string for error mess - char* m_pszProto; // Contact Proto Module - MCONTACT m_hContact; // Contact handle - uint8_t m_EnableItem; // hold flag for send type - uint8_t m_ChatRoom; // is Contact chatroom - - void Error(LPCTSTR pszFormat, ...); - void svcSendFileExit(); - void svcSendMsgExit(const char* szMessage); - void Exit(unsigned int Result); - - uint32_t m_cbEventMsg; // sizeof EventMsg(T) buffer - CMStringA m_szEventMsg; // EventMsg char* - HANDLE m_hSend; // protocol send handle - HANDLE m_hOnSend; // HookEventObj on ME_PROTO_ACK - - MSGBOX m_box; - wchar_t* m_ErrorMsg; - wchar_t* m_ErrorTitle; - - void Unhook(){if(m_hOnSend) {UnhookEvent(m_hOnSend);m_hOnSend = nullptr;}} - void DB_EventAdd(uint16_t EventType); - - static INT_PTR CALLBACK ResultDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam); - - /// HTTP upload helper stuff - enum HTTPFormFlags - { - HTTPFF_HEADER = 0x80, - HTTPFF_TEXT = 0x00, - HTTPFF_8BIT = 0x01, - HTTPFF_FILE = 0x02, - HTTPFF_INT = 0x04, - }; - - #define HTTPFORM_HEADER(str) str,HTTPFF_HEADER - #define HTTPFORM_TEXT(str) str,HTTPFF_TEXT - #define HTTPFORM_8BIT(str) str,HTTPFF_8BIT - #define HTTPFORM_FILE(str) str,HTTPFF_FILE - #define HTTPFORM_INT(int) (const char*)(int),HTTPFF_INT - - struct HTTPFormData - { - const char *name; - union{ - const char* value_str; - intptr_t value_int; - }; - int flags; - }; - - static const char* GetHTMLContent(char* str, const char* startTag, const char* endTag); // changes "str", can be successfully used only once - void HTTPFormDestroy(NETLIBHTTPREQUEST* nlhr); // use to free data inside "nlhr" created by HTTPFormCreate - int HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum); // returns "0" on success, Exit() will be called on failure (stop processing) -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CSEND_H +#define _CSEND_H + +///////////////////////////////////////////////////////////////////////////////////////// + +#define SS_AUTOSEND 1 +#define SS_DELETEAFTERSSEND 2 + +#define SS_DLG_AUTOSEND 1 // Button_Enable(GetDlgItem(Owner, ID_chkEmulateClick), TRUE); +#define SS_DLG_DELETEAFTERSSEND 2 // Button_Enable(GetDlgItem(Owner, ID_chkDeleteAfterSend), TRUE); +#define SS_DLG_DESCRIPTION 4 // Button_Enable(GetDlgItem(Owner, ID_chkDesc), TRUE); + +#define GC_RESULT_SUCCESS 200 +#define GC_RESULT_WRONGVER 201 +#define GC_RESULT_ERROR 202 +#define GC_RESULT_NOSESSION 209 + +const wchar_t SS_ERR_INIT[] = LPGENW("Unable to initiate %s."); +const wchar_t SS_ERR_MAPI[] = LPGENW("MAPI error (%i):\n%s."); +const wchar_t SS_ERR_RESPONSE[] = LPGENW("Unknown response from %s (%i)"); +const wchar_t SS_ERR_NORESPONSE[] = LPGENW("Got no response from %s (%i)"); + +///////////////////////////////////////////////////////////////////////////////////////// + +class CSend +{ +public: + CSend(HWND Owner, MCONTACT hContact, bool bAsync, bool bSilent=false); // oder (TfrmMain & Owner) + virtual ~CSend(); + + virtual int Send() = 0; // returns 1 if sent (you must delete class) and 0 when still sending (class deletes itself) + int SendSilent() { m_bAsync = m_bSilent = true; return Send(); } + + void SetFile(const wchar_t* file) { replaceStrW(m_pszFile, file); } + void SetFile(const char* file) { mir_free(m_pszFile), m_pszFile=mir_a2u(file); } + void SetDescription(const wchar_t* descr){ replaceStrW(m_pszFileDesc, descr); } + void SetContact(MCONTACT hContact); + const char* GetURL() { return m_URL; } + const char* GetURLthumbnail() {return m_URLthumb; } + uint8_t GetEnableItem() {return m_EnableItem;}; + wchar_t* GetErrorMsg() {return m_ErrorMsg;}; + + bool m_bDeleteAfterSend; + +protected: + bool m_bAsync; + bool m_bSilent; + wchar_t* m_pszFile; + wchar_t* m_pszFileDesc; + CMStringA m_URL; + CMStringA m_URLthumb; + static int OnSend(void *obj, WPARAM wParam, LPARAM lParam); + wchar_t* m_pszSendTyp; // hold string for error mess + char* m_pszProto; // Contact Proto Module + MCONTACT m_hContact; // Contact handle + uint8_t m_EnableItem; // hold flag for send type + uint8_t m_ChatRoom; // is Contact chatroom + + void Error(LPCTSTR pszFormat, ...); + void svcSendFileExit(); + void svcSendMsgExit(const char* szMessage); + void Exit(unsigned int Result); + + uint32_t m_cbEventMsg; // sizeof EventMsg(T) buffer + CMStringA m_szEventMsg; // EventMsg char* + HANDLE m_hSend; // protocol send handle + HANDLE m_hOnSend; // HookEventObj on ME_PROTO_ACK + + MSGBOX m_box; + wchar_t* m_ErrorMsg; + wchar_t* m_ErrorTitle; + + void Unhook(){if(m_hOnSend) {UnhookEvent(m_hOnSend);m_hOnSend = nullptr;}} + void DB_EventAdd(uint16_t EventType); + + static INT_PTR CALLBACK ResultDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam); + + /// HTTP upload helper stuff + enum HTTPFormFlags + { + HTTPFF_HEADER = 0x80, + HTTPFF_TEXT = 0x00, + HTTPFF_8BIT = 0x01, + HTTPFF_FILE = 0x02, + HTTPFF_INT = 0x04, + }; + + #define HTTPFORM_HEADER(str) str,HTTPFF_HEADER + #define HTTPFORM_TEXT(str) str,HTTPFF_TEXT + #define HTTPFORM_8BIT(str) str,HTTPFF_8BIT + #define HTTPFORM_FILE(str) str,HTTPFF_FILE + #define HTTPFORM_INT(int) (const char*)(int),HTTPFF_INT + + struct HTTPFormData + { + const char *name; + union{ + const char* value_str; + intptr_t value_int; + }; + int flags; + }; + + static const char* GetHTMLContent(char* str, const char* startTag, const char* endTag); // changes "str", can be successfully used only once + void HTTPFormDestroy(NETLIBHTTPREQUEST* nlhr); // use to free data inside "nlhr" created by HTTPFormCreate + int HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum); // returns "0" on success, Exit() will be called on failure (stop processing) +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendCloduFile.h b/plugins/SendScreenshotPlus/src/CSendCloduFile.h index 663bbf526c..f5f0c221db 100644 --- a/plugins/SendScreenshotPlus/src/CSendCloduFile.h +++ b/plugins/SendScreenshotPlus/src/CSendCloduFile.h @@ -1,50 +1,50 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _CSEND_CLOUD_FILE_H -#define _CSEND_CLOUD_FILE_H - -#include "Utils.h" - -class CSendCloudFile : public CSend -{ - -public: - CSendCloudFile(HWND Owner, MCONTACT hContact, bool bAsync, const char *service); - ~CSendCloudFile(); - - int Send() override; - -protected: - const char *m_service; - - void SendThread(); - static void SendThreadWrapper(void *Obj); -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CSEND_CLOUD_FILE_H +#define _CSEND_CLOUD_FILE_H + +#include "Utils.h" + +class CSendCloudFile : public CSend +{ + +public: + CSendCloudFile(HWND Owner, MCONTACT hContact, bool bAsync, const char *service); + ~CSendCloudFile(); + + int Send() override; + +protected: + const char *m_service; + + void SendThread(); + static void SendThreadWrapper(void *Obj); +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendCloudFile.cpp b/plugins/SendScreenshotPlus/src/CSendCloudFile.cpp index ddcdb3b0a5..88f5da4dac 100644 --- a/plugins/SendScreenshotPlus/src/CSendCloudFile.cpp +++ b/plugins/SendScreenshotPlus/src/CSendCloudFile.cpp @@ -1,78 +1,78 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -///////////////////////////////////////////////////////////////////////////////////////// - -CSendCloudFile::CSendCloudFile(HWND Owner, MCONTACT hContact, bool bAsync, const char *service) - : CSend(Owner, hContact, bAsync), m_service(service) -{ - // @todo : re-enable SS_DLG_DELETEAFTERSSEND with full implemention of Dropbox upload with progress, msg and sounds - m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; - m_pszSendTyp = TranslateT("CloudFile transfer"); -} - -CSendCloudFile::~CSendCloudFile() -{ -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSendCloudFile::Send() -{ - mir_forkthread(&CSendCloudFile::SendThreadWrapper, this); - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void CSendCloudFile::SendThread() -{ - // @todo : SS_DLG_DESCRIPTION and SS_DLG_DELETEAFTERSSEND are of no use as of now since we don't track upload progress - - CFUPLOADDATA ud = { m_service, m_pszFile, L"SendSS" }; - CFUPLOADRESULT ur = { }; - - if (CallService(MS_CLOUDFILE_UPLOAD, (WPARAM)&ud, (LPARAM)&ur)) { - Error(LPGENW("%s (%i):\nCould not add a share to the CloudFile plugin."), TranslateW(m_pszSendTyp), 0); - Exit(ACKRESULT_FAILED); - return; - } - - m_URL = ur.link; - if (m_URL) - svcSendMsgExit(m_URL); - else - Exit(ACKRESULT_FAILED); -} - -void CSendCloudFile::SendThreadWrapper(void * Obj) -{ - reinterpret_cast(Obj)->SendThread(); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +CSendCloudFile::CSendCloudFile(HWND Owner, MCONTACT hContact, bool bAsync, const char *service) + : CSend(Owner, hContact, bAsync), m_service(service) +{ + // @todo : re-enable SS_DLG_DELETEAFTERSSEND with full implemention of Dropbox upload with progress, msg and sounds + m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; + m_pszSendTyp = TranslateT("CloudFile transfer"); +} + +CSendCloudFile::~CSendCloudFile() +{ +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSendCloudFile::Send() +{ + mir_forkthread(&CSendCloudFile::SendThreadWrapper, this); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CSendCloudFile::SendThread() +{ + // @todo : SS_DLG_DESCRIPTION and SS_DLG_DELETEAFTERSSEND are of no use as of now since we don't track upload progress + + CFUPLOADDATA ud = { m_service, m_pszFile, L"SendSS" }; + CFUPLOADRESULT ur = { }; + + if (CallService(MS_CLOUDFILE_UPLOAD, (WPARAM)&ud, (LPARAM)&ur)) { + Error(LPGENW("%s (%i):\nCould not add a share to the CloudFile plugin."), TranslateW(m_pszSendTyp), 0); + Exit(ACKRESULT_FAILED); + return; + } + + m_URL = ur.link; + if (m_URL) + svcSendMsgExit(m_URL); + else + Exit(ACKRESULT_FAILED); +} + +void CSendCloudFile::SendThreadWrapper(void * Obj) +{ + reinterpret_cast(Obj)->SendThread(); +} diff --git a/plugins/SendScreenshotPlus/src/CSendEmail.cpp b/plugins/SendScreenshotPlus/src/CSendEmail.cpp index 8490004f21..2af6b0b174 100644 --- a/plugins/SendScreenshotPlus/src/CSendEmail.cpp +++ b/plugins/SendScreenshotPlus/src/CSendEmail.cpp @@ -1,201 +1,201 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -///////////////////////////////////////////////////////////////////////////////////////// - -CSendEmail::CSendEmail(HWND Owner, MCONTACT hContact, bool /*bAsync*/) - : CSend(Owner, hContact, true) -{ - m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_DELETEAFTERSSEND; // SS_DLG_AUTOSEND | ; - m_pszSendTyp = LPGENW("Email transfer"); - m_pszFileA = nullptr; - m_pszFileName = nullptr; - m_Email = nullptr; - m_FriendlyName = nullptr; - m_Subject = nullptr; -} - -CSendEmail::~CSendEmail() -{ - mir_free(m_pszFileA); - mir_free(m_pszFileName); - mir_free(m_Email); - mir_free(m_FriendlyName); - mir_free(m_Subject); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSendEmail::Send() -{ - if (!m_hContact) return 1; - mir_free(m_pszFileName); - m_pszFileName = GetFileNameA(m_pszFile); - - mir_free(m_pszFileA); - m_pszFileA = mir_u2a(m_pszFile); - - m_Email = mir_u2a(ptrW(Contact::GetInfo(CNF_EMAIL, m_hContact, m_pszProto))); - m_FriendlyName = mir_u2a(ptrW(Contact::GetInfo(CNF_DISPLAY, m_hContact, m_pszProto))); - m_Subject = mir_u2a(m_pszFileDesc); - - // SendByEmail(m_pszFileA, "", m_FriendlyName, m_Email, m_Subject); - - // start Send thread - mir_forkthread(&CSendEmail::SendThreadWrapper, this); - return 0; -} - -void CSendEmail::SendThread() -{ - // This code based on SentTo.exe application. - // The default mail client for Simple MAPI or MAPI calls is defined by the - // HKLM\Software\Clients\Mail::(default) registry value. - - MapiFileDesc arrfileDesc[1]; - - typedef ULONG(FAR PASCAL *MAPIFUNC)(LHANDLE, ULONG, lpMapiMessage, FLAGS, ULONG); - MapiMessage Msg; - MAPIFUNC lpMAPISendMail; - - HINSTANCE hMAPILib = ::LoadLibrary(L"MAPI32.DLL"); - if (hMAPILib == nullptr) { - // return -1; - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); return; - } - - lpMAPISendMail = (MAPIFUNC)GetProcAddress(hMAPILib, "MAPISendMail"); - if (lpMAPISendMail == nullptr) { - ::FreeLibrary(hMAPILib); - // return -2; - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); return; - } - - memset(&Msg, 0, sizeof(Msg)); - - arrfileDesc[0].ulReserved = 0; - arrfileDesc[0].flFlags = 0; - arrfileDesc[0].lpFileType = nullptr; - arrfileDesc[0].nPosition = -1; - arrfileDesc[0].lpszPathName = m_pszFileA; - arrfileDesc[0].lpszFileName = nullptr; - - Msg.nFileCount = 1; - Msg.lpFiles = arrfileDesc; - Msg.lpszNoteText = ""; // body - Msg.lpszSubject = m_Subject; // subject - - Msg.nRecipCount = 1; - MapiRecipDesc recip; - recip.ulReserved = 0; - recip.ulRecipClass = MAPI_TO; - - if (m_FriendlyName && m_FriendlyName[0] != NULL) { - recip.lpszName = m_FriendlyName; // friendly name set to contact's name - } - else { - recip.lpszName = m_Email; // friendly name set to contact's email - } - - recip.lpszAddress = m_Email; // email - recip.ulEIDSize = 0; - recip.lpEntryID = nullptr; - Msg.lpRecips = &recip; - - try { - int res = lpMAPISendMail(NULL, NULL, &Msg, MAPI_LOGON_UI | MAPI_DIALOG, 0); - ::FreeLibrary(hMAPILib); - - wchar_t* err; - switch (res) { - case SUCCESS_SUCCESS: - // The call succeeded and the message was sent. - Exit(ACKRESULT_SUCCESS); return; - // No message was sent - case MAPI_E_AMBIGUOUS_RECIPIENT: - err = LPGENW("A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set"); - break; - case MAPI_E_ATTACHMENT_NOT_FOUND: - err = LPGENW("The specified attachment was not found"); - break; - case MAPI_E_ATTACHMENT_OPEN_FAILURE: - err = LPGENW("The specified attachment could not be opened"); - break; - case MAPI_E_BAD_RECIPTYPE: - err = LPGENW("The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC"); - break; - case MAPI_E_FAILURE: - err = LPGENW("One or more unspecified errors occurred"); - break; - case MAPI_E_INSUFFICIENT_MEMORY: - err = LPGENW("There was insufficient memory to proceed"); - break; - case MAPI_E_INVALID_RECIPS: - err = LPGENW("One or more recipients were invalid or did not resolve to any address"); - break; - case MAPI_E_LOGIN_FAILURE: - err = LPGENW("There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed"); - break; - case MAPI_E_TEXT_TOO_LARGE: - err = LPGENW("The text in the message was too large"); - break; - case MAPI_E_TOO_MANY_FILES: - err = LPGENW("There were too many file attachments"); - break; - case MAPI_E_TOO_MANY_RECIPIENTS: - err = LPGENW("There were too many recipients"); - break; - case MAPI_E_UNKNOWN_RECIPIENT: - err = LPGENW("A recipient did not appear in the address list"); - break; - case MAPI_E_USER_ABORT: - err = LPGENW("The user canceled one of the dialog boxes"); - break; - default: - err = LPGENW("Unknown Error"); - break; - } - Error(SS_ERR_MAPI, res, err); - Exit(ACKRESULT_FAILED); - } - catch (...) { - ::FreeLibrary(hMAPILib); - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); - return; - } -} - -void CSendEmail::SendThreadWrapper(void * Obj) -{ - reinterpret_cast(Obj)->SendThread(); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +CSendEmail::CSendEmail(HWND Owner, MCONTACT hContact, bool /*bAsync*/) + : CSend(Owner, hContact, true) +{ + m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_DELETEAFTERSSEND; // SS_DLG_AUTOSEND | ; + m_pszSendTyp = LPGENW("Email transfer"); + m_pszFileA = nullptr; + m_pszFileName = nullptr; + m_Email = nullptr; + m_FriendlyName = nullptr; + m_Subject = nullptr; +} + +CSendEmail::~CSendEmail() +{ + mir_free(m_pszFileA); + mir_free(m_pszFileName); + mir_free(m_Email); + mir_free(m_FriendlyName); + mir_free(m_Subject); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSendEmail::Send() +{ + if (!m_hContact) return 1; + mir_free(m_pszFileName); + m_pszFileName = GetFileNameA(m_pszFile); + + mir_free(m_pszFileA); + m_pszFileA = mir_u2a(m_pszFile); + + m_Email = mir_u2a(ptrW(Contact::GetInfo(CNF_EMAIL, m_hContact, m_pszProto))); + m_FriendlyName = mir_u2a(ptrW(Contact::GetInfo(CNF_DISPLAY, m_hContact, m_pszProto))); + m_Subject = mir_u2a(m_pszFileDesc); + + // SendByEmail(m_pszFileA, "", m_FriendlyName, m_Email, m_Subject); + + // start Send thread + mir_forkthread(&CSendEmail::SendThreadWrapper, this); + return 0; +} + +void CSendEmail::SendThread() +{ + // This code based on SentTo.exe application. + // The default mail client for Simple MAPI or MAPI calls is defined by the + // HKLM\Software\Clients\Mail::(default) registry value. + + MapiFileDesc arrfileDesc[1]; + + typedef ULONG(FAR PASCAL *MAPIFUNC)(LHANDLE, ULONG, lpMapiMessage, FLAGS, ULONG); + MapiMessage Msg; + MAPIFUNC lpMAPISendMail; + + HINSTANCE hMAPILib = ::LoadLibrary(L"MAPI32.DLL"); + if (hMAPILib == nullptr) { + // return -1; + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); return; + } + + lpMAPISendMail = (MAPIFUNC)GetProcAddress(hMAPILib, "MAPISendMail"); + if (lpMAPISendMail == nullptr) { + ::FreeLibrary(hMAPILib); + // return -2; + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); return; + } + + memset(&Msg, 0, sizeof(Msg)); + + arrfileDesc[0].ulReserved = 0; + arrfileDesc[0].flFlags = 0; + arrfileDesc[0].lpFileType = nullptr; + arrfileDesc[0].nPosition = -1; + arrfileDesc[0].lpszPathName = m_pszFileA; + arrfileDesc[0].lpszFileName = nullptr; + + Msg.nFileCount = 1; + Msg.lpFiles = arrfileDesc; + Msg.lpszNoteText = ""; // body + Msg.lpszSubject = m_Subject; // subject + + Msg.nRecipCount = 1; + MapiRecipDesc recip; + recip.ulReserved = 0; + recip.ulRecipClass = MAPI_TO; + + if (m_FriendlyName && m_FriendlyName[0] != NULL) { + recip.lpszName = m_FriendlyName; // friendly name set to contact's name + } + else { + recip.lpszName = m_Email; // friendly name set to contact's email + } + + recip.lpszAddress = m_Email; // email + recip.ulEIDSize = 0; + recip.lpEntryID = nullptr; + Msg.lpRecips = &recip; + + try { + int res = lpMAPISendMail(NULL, NULL, &Msg, MAPI_LOGON_UI | MAPI_DIALOG, 0); + ::FreeLibrary(hMAPILib); + + wchar_t* err; + switch (res) { + case SUCCESS_SUCCESS: + // The call succeeded and the message was sent. + Exit(ACKRESULT_SUCCESS); return; + // No message was sent + case MAPI_E_AMBIGUOUS_RECIPIENT: + err = LPGENW("A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set"); + break; + case MAPI_E_ATTACHMENT_NOT_FOUND: + err = LPGENW("The specified attachment was not found"); + break; + case MAPI_E_ATTACHMENT_OPEN_FAILURE: + err = LPGENW("The specified attachment could not be opened"); + break; + case MAPI_E_BAD_RECIPTYPE: + err = LPGENW("The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC"); + break; + case MAPI_E_FAILURE: + err = LPGENW("One or more unspecified errors occurred"); + break; + case MAPI_E_INSUFFICIENT_MEMORY: + err = LPGENW("There was insufficient memory to proceed"); + break; + case MAPI_E_INVALID_RECIPS: + err = LPGENW("One or more recipients were invalid or did not resolve to any address"); + break; + case MAPI_E_LOGIN_FAILURE: + err = LPGENW("There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed"); + break; + case MAPI_E_TEXT_TOO_LARGE: + err = LPGENW("The text in the message was too large"); + break; + case MAPI_E_TOO_MANY_FILES: + err = LPGENW("There were too many file attachments"); + break; + case MAPI_E_TOO_MANY_RECIPIENTS: + err = LPGENW("There were too many recipients"); + break; + case MAPI_E_UNKNOWN_RECIPIENT: + err = LPGENW("A recipient did not appear in the address list"); + break; + case MAPI_E_USER_ABORT: + err = LPGENW("The user canceled one of the dialog boxes"); + break; + default: + err = LPGENW("Unknown Error"); + break; + } + Error(SS_ERR_MAPI, res, err); + Exit(ACKRESULT_FAILED); + } + catch (...) { + ::FreeLibrary(hMAPILib); + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); + return; + } +} + +void CSendEmail::SendThreadWrapper(void * Obj) +{ + reinterpret_cast(Obj)->SendThread(); +} diff --git a/plugins/SendScreenshotPlus/src/CSendEmail.h b/plugins/SendScreenshotPlus/src/CSendEmail.h index 7e765f747f..1bc852975e 100644 --- a/plugins/SendScreenshotPlus/src/CSendEmail.h +++ b/plugins/SendScreenshotPlus/src/CSendEmail.h @@ -1,53 +1,53 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _CSEND_EMAIL_H -#define _CSEND_EMAIL_H - -class CSendEmail : public CSend -{ - -public: - // Deklaration Standardkonstruktor/Standarddestructor - CSendEmail(HWND Owner, MCONTACT hContact, bool bAsync); - ~CSendEmail(); - - int Send() override; - -protected: - char* m_pszFileA; - char* m_pszFileName; - char* m_Email; - char* m_FriendlyName; - char* m_Subject; - - void SendThread(); - static void SendThreadWrapper(void * Obj); -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CSEND_EMAIL_H +#define _CSEND_EMAIL_H + +class CSendEmail : public CSend +{ + +public: + // Deklaration Standardkonstruktor/Standarddestructor + CSendEmail(HWND Owner, MCONTACT hContact, bool bAsync); + ~CSendEmail(); + + int Send() override; + +protected: + char* m_pszFileA; + char* m_pszFileName; + char* m_Email; + char* m_FriendlyName; + char* m_Subject; + + void SendThread(); + static void SendThreadWrapper(void * Obj); +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendFTPFile.cpp b/plugins/SendScreenshotPlus/src/CSendFTPFile.cpp index e4f5cc11d1..1e4ae57e2c 100644 --- a/plugins/SendScreenshotPlus/src/CSendFTPFile.cpp +++ b/plugins/SendScreenshotPlus/src/CSendFTPFile.cpp @@ -1,93 +1,93 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -///////////////////////////////////////////////////////////////////////////////////////// - -CSendFTPFile::CSendFTPFile(HWND Owner, MCONTACT hContact, bool /*bAsync*/) - : CSend(Owner, hContact, true) -{ - m_EnableItem = 0; //SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; - m_pszSendTyp = LPGENW("FTPFile transfer"); - m_pszFileName = nullptr; -} - -CSendFTPFile::~CSendFTPFile() -{ - mir_free(m_pszFileName); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSendFTPFile::Send() -{ - if (!m_hContact) return 1; - /********************************************************************************************* - * Send file (files) to the FTP server and copy file URL - * to message log or clipboard (according to plugin setting) - * wParam = (HANDLE)hContact - * lParam = (char *)filename - * Filename format is same as GetOpenFileName (OPENFILENAME.lpstrFile) returns, - * see http://msdn2.microsoft.com/en-us/library/ms646839.aspx - * Returns 0 on success or nonzero on failure - * if (!wParam || !lParam) return 1 - ********************************************************************************************/ - mir_free(m_pszFileName); - m_pszFileName = GetFileNameA(m_pszFile); - size_t size = sizeof(char)*(mir_strlen(m_pszFileName) + 2); - m_pszFileName = (char*)mir_realloc(m_pszFileName, size); - m_pszFileName[size - 1] = NULL; - - // start Send thread - mir_forkthread(&CSendFTPFile::SendThreadWrapper, this); - return 0; -} - -void CSendFTPFile::SendThread() -{ - - INT_PTR ret = FTPFileUploadA(m_hContact, FNUM_DEFAULT, FMODE_RAWFILE, &m_pszFileName, 1); - if (ret != 0) { - Error(LPGENW("%s (%i):\nCould not add a share to the FTP File plugin."), TranslateW(m_pszSendTyp), ret); - Exit(ret); return; - } - - // Can't delete the file since FTP File plugin will use it - m_bDeleteAfterSend = false; - - if (m_URL && *m_URL) {/// @fixme : m_URL never set - svcSendMsgExit(m_URL); return; - } - Exit(ACKRESULT_FAILED); -} - -void CSendFTPFile::SendThreadWrapper(void * Obj) -{ - reinterpret_cast(Obj)->SendThread(); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +CSendFTPFile::CSendFTPFile(HWND Owner, MCONTACT hContact, bool /*bAsync*/) + : CSend(Owner, hContact, true) +{ + m_EnableItem = 0; //SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; + m_pszSendTyp = LPGENW("FTPFile transfer"); + m_pszFileName = nullptr; +} + +CSendFTPFile::~CSendFTPFile() +{ + mir_free(m_pszFileName); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSendFTPFile::Send() +{ + if (!m_hContact) return 1; + /********************************************************************************************* + * Send file (files) to the FTP server and copy file URL + * to message log or clipboard (according to plugin setting) + * wParam = (HANDLE)hContact + * lParam = (char *)filename + * Filename format is same as GetOpenFileName (OPENFILENAME.lpstrFile) returns, + * see http://msdn2.microsoft.com/en-us/library/ms646839.aspx + * Returns 0 on success or nonzero on failure + * if (!wParam || !lParam) return 1 + ********************************************************************************************/ + mir_free(m_pszFileName); + m_pszFileName = GetFileNameA(m_pszFile); + size_t size = sizeof(char)*(mir_strlen(m_pszFileName) + 2); + m_pszFileName = (char*)mir_realloc(m_pszFileName, size); + m_pszFileName[size - 1] = NULL; + + // start Send thread + mir_forkthread(&CSendFTPFile::SendThreadWrapper, this); + return 0; +} + +void CSendFTPFile::SendThread() +{ + + INT_PTR ret = FTPFileUploadA(m_hContact, FNUM_DEFAULT, FMODE_RAWFILE, &m_pszFileName, 1); + if (ret != 0) { + Error(LPGENW("%s (%i):\nCould not add a share to the FTP File plugin."), TranslateW(m_pszSendTyp), ret); + Exit(ret); return; + } + + // Can't delete the file since FTP File plugin will use it + m_bDeleteAfterSend = false; + + if (m_URL && *m_URL) {/// @fixme : m_URL never set + svcSendMsgExit(m_URL); return; + } + Exit(ACKRESULT_FAILED); +} + +void CSendFTPFile::SendThreadWrapper(void * Obj) +{ + reinterpret_cast(Obj)->SendThread(); +} diff --git a/plugins/SendScreenshotPlus/src/CSendFTPFile.h b/plugins/SendScreenshotPlus/src/CSendFTPFile.h index 9094f3f4f7..b57f9243b2 100644 --- a/plugins/SendScreenshotPlus/src/CSendFTPFile.h +++ b/plugins/SendScreenshotPlus/src/CSendFTPFile.h @@ -1,48 +1,48 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _CSEND_FTP_FILE_H -#define _CSEND_FTP_FILE_H - -class CSendFTPFile : public CSend -{ - -public: - // Deklaration Standardkonstruktor/Standarddestructor - CSendFTPFile(HWND Owner, MCONTACT hContact, bool bAsync); - ~CSendFTPFile(); - - int Send() override; - -protected: - char* m_pszFileName; - void SendThread(); - static void SendThreadWrapper(void * Obj); -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CSEND_FTP_FILE_H +#define _CSEND_FTP_FILE_H + +class CSendFTPFile : public CSend +{ + +public: + // Deklaration Standardkonstruktor/Standarddestructor + CSendFTPFile(HWND Owner, MCONTACT hContact, bool bAsync); + ~CSendFTPFile(); + + int Send() override; + +protected: + char* m_pszFileName; + void SendThread(); + static void SendThreadWrapper(void * Obj); +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendFile.cpp b/plugins/SendScreenshotPlus/src/CSendFile.cpp index 550ad4bda4..ed1500a03f 100644 --- a/plugins/SendScreenshotPlus/src/CSendFile.cpp +++ b/plugins/SendScreenshotPlus/src/CSendFile.cpp @@ -1,50 +1,50 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -///////////////////////////////////////////////////////////////////////////////////////// - -CSendFile::CSendFile(HWND Owner, MCONTACT hContact, bool /*bAsync*/) - : CSend(Owner, hContact, true) -{ - m_EnableItem = SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND | SS_DLG_DESCRIPTION; - m_pszSendTyp = LPGENW("File transfer"); -} - -CSendFile::~CSendFile() -{ -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSendFile::Send() -{ - svcSendFileExit(); - return 0; -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +CSendFile::CSendFile(HWND Owner, MCONTACT hContact, bool /*bAsync*/) + : CSend(Owner, hContact, true) +{ + m_EnableItem = SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND | SS_DLG_DESCRIPTION; + m_pszSendTyp = LPGENW("File transfer"); +} + +CSendFile::~CSendFile() +{ +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSendFile::Send() +{ + svcSendFileExit(); + return 0; +} diff --git a/plugins/SendScreenshotPlus/src/CSendFile.h b/plugins/SendScreenshotPlus/src/CSendFile.h index b30a1ce6e3..e2b7462725 100644 --- a/plugins/SendScreenshotPlus/src/CSendFile.h +++ b/plugins/SendScreenshotPlus/src/CSendFile.h @@ -1,43 +1,43 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _CSEND_FILE_H -#define _CSEND_FILE_H - -class CSendFile : public CSend -{ - -public: - // Deklaration Standardkonstruktor/Standarddestructor - CSendFile(HWND Owner, MCONTACT hContact, bool bAsync); - ~CSendFile(); - - int Send() override; -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CSEND_FILE_H +#define _CSEND_FILE_H + +class CSendFile : public CSend +{ + +public: + // Deklaration Standardkonstruktor/Standarddestructor + CSendFile(HWND Owner, MCONTACT hContact, bool bAsync); + ~CSendFile(); + + int Send() override; +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendHTTPServer.cpp b/plugins/SendScreenshotPlus/src/CSendHTTPServer.cpp index 9075d70951..7815d49bfb 100644 --- a/plugins/SendScreenshotPlus/src/CSendHTTPServer.cpp +++ b/plugins/SendScreenshotPlus/src/CSendHTTPServer.cpp @@ -1,117 +1,117 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -INT_PTR(*g_MirCallService)(const char *, WPARAM, LPARAM) = nullptr; - -///////////////////////////////////////////////////////////////////////////////////////// - -CSendHTTPServer::CSendHTTPServer(HWND Owner, MCONTACT hContact, bool /*bAsync*/) - : CSend(Owner, hContact, true) -{ - m_EnableItem = SS_DLG_DESCRIPTION; //| SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; - m_pszSendTyp = LPGENW("HTTPServer transfer"); - m_pszFileName = nullptr; - m_fsi_pszRealPath = nullptr; -} - -CSendHTTPServer::~CSendHTTPServer() -{ - mir_free(m_pszFileName); - mir_free(m_fsi_pszRealPath); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSendHTTPServer::Send() -{ - if (!m_hContact) return 1; - if (CallService(MS_HTTP_ACCEPT_CONNECTIONS, TRUE, 0) != 0) { - Error(LPGENW("Could not start the HTTP Server plugin.")); - Exit(ACKRESULT_FAILED); - return !m_bAsync; - } - - if (!m_pszFileName) { - m_pszFileName = GetFileNameA(m_pszFile); - } - - m_fsi_pszSrvPath.Empty(); - m_fsi_pszSrvPath.AppendChar('/'); - m_fsi_pszSrvPath.Append(m_pszFileName); - - replaceStr(m_fsi_pszRealPath, _T2A(m_pszFile)); - - memset(&m_fsi, 0, sizeof(m_fsi)); - m_fsi.lStructSize = sizeof(STFileShareInfo); - m_fsi.nMaxDownloads = -1; // -1 = infinite - m_fsi.pszRealPath = m_fsi_pszRealPath; - - // start Send thread - mir_forkthread(&CSendHTTPServer::SendThreadWrapper, this); - return 0; -} - -void CSendHTTPServer::SendThread() -{ - INT_PTR ret; - - if (ServiceExists(MS_HTTP_GET_LINK)) { - // patched plugin version - ret = CallService(MS_HTTP_ADD_CHANGE_REMOVE, (WPARAM)m_hContact, (LPARAM)&m_fsi); - if (!ret) { - m_URL = ptrA((char*)CallService(MS_HTTP_GET_LINK, (WPARAM)m_fsi.pszSrvPath, 0)); - } - } - else { - // original plugin - m_fsi.dwOptions = OPT_SEND_LINK; - - // send DATA and wait for reply - ret = CallService(MS_HTTP_ADD_CHANGE_REMOVE, (WPARAM)m_hContact, (LPARAM)&m_fsi); - } - - if (ret != 0) { - Error(LPGENW("%s (%i):\nCould not add a share to the HTTP Server plugin."), TranslateW(m_pszSendTyp), ret); - Exit(ret); return; - } - - // Share the file by HTTP Server plugin, SendSS does not own the file anymore = auto-delete won't work - m_bDeleteAfterSend = false; - - if (m_URL && *m_URL) { - svcSendMsgExit(m_URL); return; - } - Exit(ACKRESULT_FAILED); -} - -void CSendHTTPServer::SendThreadWrapper(void * Obj) -{ - reinterpret_cast(Obj)->SendThread(); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +INT_PTR(*g_MirCallService)(const char *, WPARAM, LPARAM) = nullptr; + +///////////////////////////////////////////////////////////////////////////////////////// + +CSendHTTPServer::CSendHTTPServer(HWND Owner, MCONTACT hContact, bool /*bAsync*/) + : CSend(Owner, hContact, true) +{ + m_EnableItem = SS_DLG_DESCRIPTION; //| SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; + m_pszSendTyp = LPGENW("HTTPServer transfer"); + m_pszFileName = nullptr; + m_fsi_pszRealPath = nullptr; +} + +CSendHTTPServer::~CSendHTTPServer() +{ + mir_free(m_pszFileName); + mir_free(m_fsi_pszRealPath); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSendHTTPServer::Send() +{ + if (!m_hContact) return 1; + if (CallService(MS_HTTP_ACCEPT_CONNECTIONS, TRUE, 0) != 0) { + Error(LPGENW("Could not start the HTTP Server plugin.")); + Exit(ACKRESULT_FAILED); + return !m_bAsync; + } + + if (!m_pszFileName) { + m_pszFileName = GetFileNameA(m_pszFile); + } + + m_fsi_pszSrvPath.Empty(); + m_fsi_pszSrvPath.AppendChar('/'); + m_fsi_pszSrvPath.Append(m_pszFileName); + + replaceStr(m_fsi_pszRealPath, _T2A(m_pszFile)); + + memset(&m_fsi, 0, sizeof(m_fsi)); + m_fsi.lStructSize = sizeof(STFileShareInfo); + m_fsi.nMaxDownloads = -1; // -1 = infinite + m_fsi.pszRealPath = m_fsi_pszRealPath; + + // start Send thread + mir_forkthread(&CSendHTTPServer::SendThreadWrapper, this); + return 0; +} + +void CSendHTTPServer::SendThread() +{ + INT_PTR ret; + + if (ServiceExists(MS_HTTP_GET_LINK)) { + // patched plugin version + ret = CallService(MS_HTTP_ADD_CHANGE_REMOVE, (WPARAM)m_hContact, (LPARAM)&m_fsi); + if (!ret) { + m_URL = ptrA((char*)CallService(MS_HTTP_GET_LINK, (WPARAM)m_fsi.pszSrvPath, 0)); + } + } + else { + // original plugin + m_fsi.dwOptions = OPT_SEND_LINK; + + // send DATA and wait for reply + ret = CallService(MS_HTTP_ADD_CHANGE_REMOVE, (WPARAM)m_hContact, (LPARAM)&m_fsi); + } + + if (ret != 0) { + Error(LPGENW("%s (%i):\nCould not add a share to the HTTP Server plugin."), TranslateW(m_pszSendTyp), ret); + Exit(ret); return; + } + + // Share the file by HTTP Server plugin, SendSS does not own the file anymore = auto-delete won't work + m_bDeleteAfterSend = false; + + if (m_URL && *m_URL) { + svcSendMsgExit(m_URL); return; + } + Exit(ACKRESULT_FAILED); +} + +void CSendHTTPServer::SendThreadWrapper(void * Obj) +{ + reinterpret_cast(Obj)->SendThread(); +} diff --git a/plugins/SendScreenshotPlus/src/CSendHTTPServer.h b/plugins/SendScreenshotPlus/src/CSendHTTPServer.h index e11ac3fae0..aa5dec4030 100644 --- a/plugins/SendScreenshotPlus/src/CSendHTTPServer.h +++ b/plugins/SendScreenshotPlus/src/CSendHTTPServer.h @@ -1,55 +1,55 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _CSEND_HTTP_SERVER_H -#define _CSEND_HTTP_SERVER_H - -class CSendHTTPServer : public CSend -{ -public: - // Deklaration Standardkonstruktor/Standarddestructor - CSendHTTPServer(HWND Owner, MCONTACT hContact, bool bAsync); - ~CSendHTTPServer(); - - int Send() override; - -protected: - char* m_pszFileName; - CMStringA m_fsi_pszSrvPath; - char* m_fsi_pszRealPath; - - STFileShareInfo m_fsi; - - void SendThread(); - static void SendThreadWrapper(void * Obj); - - typedef std::map CContactMapping; - static CContactMapping _CContactMapping; -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CSEND_HTTP_SERVER_H +#define _CSEND_HTTP_SERVER_H + +class CSendHTTPServer : public CSend +{ +public: + // Deklaration Standardkonstruktor/Standarddestructor + CSendHTTPServer(HWND Owner, MCONTACT hContact, bool bAsync); + ~CSendHTTPServer(); + + int Send() override; + +protected: + char* m_pszFileName; + CMStringA m_fsi_pszSrvPath; + char* m_fsi_pszRealPath; + + STFileShareInfo m_fsi; + + void SendThread(); + static void SendThreadWrapper(void * Obj); + + typedef std::map CContactMapping; + static CContactMapping _CContactMapping; +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp index 7940487e88..5a2a4d8a34 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp +++ b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp @@ -1,118 +1,118 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -///////////////////////////////////////////////////////////////////////////////////////// - -CSendHost_ImageShack::CSendHost_ImageShack(HWND Owner, MCONTACT hContact, bool bAsync) - : CSend(Owner, hContact, bAsync) -{ - m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; - m_pszSendTyp = LPGENW("Image upload"); -} - -CSendHost_ImageShack::~CSendHost_ImageShack() -{ -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSendHost_ImageShack::Send() -{ - if (!g_hNetlibUser) { // check Netlib - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); - return !m_bAsync; - } - memset(&m_nlhr, 0, sizeof(m_nlhr)); - char* tmp; tmp = mir_u2a(m_pszFile); - HTTPFormData frm[] = { - // { "Referer", HTTPFORM_HEADER("http://www.imageshack.us/upload_api.php") }, - { "fileupload", HTTPFORM_FILE(tmp) }, - // { "rembar", "yes" },// no info bar on thumb - { "public", "no" }, - { "key", HTTPFORM_8BIT(DEVKEY_IMAGESHACK) }, - }; - int error = HTTPFormCreate(&m_nlhr, REQUEST_POST, "http://imageshack.us/upload_api.php", frm, sizeof(frm) / sizeof(HTTPFormData)); - mir_free(tmp); - if (error) - return !m_bAsync; - // start upload thread - if (m_bAsync) { - mir_forkthread(&CSendHost_ImageShack::SendThreadWrapper, this); - return 0; - } - SendThread(); - return 1; -} - -void CSendHost_ImageShack::SendThread() -{ - // send DATA and wait for m_nlreply - NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &m_nlhr)); - HTTPFormDestroy(&m_nlhr); - if (reply) { - if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->dataLength) { - reply->pData[reply->dataLength - 1] = '\0'; // make sure its null terminated - const char* url = nullptr; - url = GetHTMLContent(reply->pData, "", ""); - if (url && *url) { - m_URLthumb = m_URL = url; - - int idx = m_URLthumb.ReverseFind('.'); - if (idx != -1 && m_URLthumb.GetLength() - idx > 2) - m_URLthumb.Insert(idx + 1, "th"); - else - m_URLthumb.Empty(); - - svcSendMsgExit(url); - return; - } - - url = GetHTMLContent(reply->pData, ""); - wchar_t* err = nullptr; - if (url) err = mir_a2u(url); - if (!err || !*err) { // fallback to server response mess - mir_free(err); - err = mir_a2u(reply->pData); - } - Error(L"%s", err); - mir_free(err); - } - else Error(SS_ERR_RESPONSE, m_pszSendTyp, reply->resultCode); - } - else Error(SS_ERR_NORESPONSE, m_pszSendTyp, m_nlhr.resultCode); - - Exit(ACKRESULT_FAILED); -} - -void CSendHost_ImageShack::SendThreadWrapper(void * Obj) -{ - reinterpret_cast(Obj)->SendThread(); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +CSendHost_ImageShack::CSendHost_ImageShack(HWND Owner, MCONTACT hContact, bool bAsync) + : CSend(Owner, hContact, bAsync) +{ + m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; + m_pszSendTyp = LPGENW("Image upload"); +} + +CSendHost_ImageShack::~CSendHost_ImageShack() +{ +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSendHost_ImageShack::Send() +{ + if (!g_hNetlibUser) { // check Netlib + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); + return !m_bAsync; + } + memset(&m_nlhr, 0, sizeof(m_nlhr)); + char* tmp; tmp = mir_u2a(m_pszFile); + HTTPFormData frm[] = { + // { "Referer", HTTPFORM_HEADER("http://www.imageshack.us/upload_api.php") }, + { "fileupload", HTTPFORM_FILE(tmp) }, + // { "rembar", "yes" },// no info bar on thumb + { "public", "no" }, + { "key", HTTPFORM_8BIT(DEVKEY_IMAGESHACK) }, + }; + int error = HTTPFormCreate(&m_nlhr, REQUEST_POST, "http://imageshack.us/upload_api.php", frm, sizeof(frm) / sizeof(HTTPFormData)); + mir_free(tmp); + if (error) + return !m_bAsync; + // start upload thread + if (m_bAsync) { + mir_forkthread(&CSendHost_ImageShack::SendThreadWrapper, this); + return 0; + } + SendThread(); + return 1; +} + +void CSendHost_ImageShack::SendThread() +{ + // send DATA and wait for m_nlreply + NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &m_nlhr)); + HTTPFormDestroy(&m_nlhr); + if (reply) { + if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->dataLength) { + reply->pData[reply->dataLength - 1] = '\0'; // make sure its null terminated + const char* url = nullptr; + url = GetHTMLContent(reply->pData, "", ""); + if (url && *url) { + m_URLthumb = m_URL = url; + + int idx = m_URLthumb.ReverseFind('.'); + if (idx != -1 && m_URLthumb.GetLength() - idx > 2) + m_URLthumb.Insert(idx + 1, "th"); + else + m_URLthumb.Empty(); + + svcSendMsgExit(url); + return; + } + + url = GetHTMLContent(reply->pData, ""); + wchar_t* err = nullptr; + if (url) err = mir_a2u(url); + if (!err || !*err) { // fallback to server response mess + mir_free(err); + err = mir_a2u(reply->pData); + } + Error(L"%s", err); + mir_free(err); + } + else Error(SS_ERR_RESPONSE, m_pszSendTyp, reply->resultCode); + } + else Error(SS_ERR_NORESPONSE, m_pszSendTyp, m_nlhr.resultCode); + + Exit(ACKRESULT_FAILED); +} + +void CSendHost_ImageShack::SendThreadWrapper(void * Obj) +{ + reinterpret_cast(Obj)->SendThread(); +} diff --git a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h index a03647c063..7c58094aac 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h +++ b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h @@ -1,49 +1,49 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _CSEND_IMAGESHACK_H -#define _CSEND_IMAGESHACK_H - -class CSendHost_ImageShack : public CSend -{ - -public: - // Deklaration Standardkonstruktor/Standarddestructor - CSendHost_ImageShack(HWND Owner, MCONTACT hContact, bool bAsync); - ~CSendHost_ImageShack(); - - int Send() override; - -protected: - NETLIBHTTPREQUEST m_nlhr; - - void SendThread(); - static void SendThreadWrapper(void * Obj); -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _CSEND_IMAGESHACK_H +#define _CSEND_IMAGESHACK_H + +class CSendHost_ImageShack : public CSend +{ + +public: + // Deklaration Standardkonstruktor/Standarddestructor + CSendHost_ImageShack(HWND Owner, MCONTACT hContact, bool bAsync); + ~CSendHost_ImageShack(); + + int Send() override; + +protected: + NETLIBHTTPREQUEST m_nlhr; + + void SendThread(); + static void SendThreadWrapper(void * Obj); +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp b/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp index 4aa5ccc44f..bde9f158bb 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp +++ b/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp @@ -1,86 +1,86 @@ -/* - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2014-22 Miranda NG team (https://miranda-ng.org) - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. -*/ -#include "stdafx.h" - -CSendHost_Imgur::CSendHost_Imgur(HWND Owner, MCONTACT hContact, bool bAsync) - : CSend(Owner, hContact, bAsync) -{ - m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; - m_pszSendTyp = LPGENW("Image upload"); -} - -CSendHost_Imgur::~CSendHost_Imgur() -{ -} - -///////////////////////////////////////////////////////////////////////////////////////// - -int CSendHost_Imgur::Send() -{ - if (!g_hNetlibUser) { // check Netlib - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); - return !m_bAsync; - } - memset(&m_nlhr, 0, sizeof(m_nlhr)); - char* tmp; tmp = mir_u2a(m_pszFile); - HTTPFormData frm[] = { - { "Authorization", HTTPFORM_HEADER("Client-ID 2a7303d78abe041") }, - { "image", HTTPFORM_FILE(tmp) }, - }; - - int error = HTTPFormCreate(&m_nlhr, REQUEST_POST, "https://api.imgur.com/3/image", frm, _countof(frm)); - mir_free(tmp); - if (error) - return !m_bAsync; - // start upload thread - if (m_bAsync) { - mir_forkthread(&CSendHost_Imgur::SendThread, this); - return 0; - } - SendThread(this); - return 1; -} - -void CSendHost_Imgur::SendThread(void* obj) -{ - CSendHost_Imgur *self = (CSendHost_Imgur*)obj; - // send DATA and wait for m_nlreply - NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &self->m_nlhr)); - self->HTTPFormDestroy(&self->m_nlhr); - if (reply) { - if (reply->dataLength) { - JSONROOT root(reply->pData); - if (root) { - if ((*root)["success"].as_bool()) { - self->m_URL = (*root)["data"]["link"].as_mstring(); - int idx = self->m_URL.ReverseFind('.'); - if (idx != -1) { - self->m_URLthumb = self->m_URL; - self->m_URLthumb.Insert(idx, 'm'); - } - self->svcSendMsgExit(self->m_URL); return; - } - else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, (*root)["status"].as_int(), 0); - } - else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); - } - else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); - } - else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, self->m_nlhr.resultCode); - - self->Exit(ACKRESULT_FAILED); -} +/* + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2014-23 Miranda NG team (https://miranda-ng.org) + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. +*/ +#include "stdafx.h" + +CSendHost_Imgur::CSendHost_Imgur(HWND Owner, MCONTACT hContact, bool bAsync) + : CSend(Owner, hContact, bAsync) +{ + m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; + m_pszSendTyp = LPGENW("Image upload"); +} + +CSendHost_Imgur::~CSendHost_Imgur() +{ +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CSendHost_Imgur::Send() +{ + if (!g_hNetlibUser) { // check Netlib + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); + return !m_bAsync; + } + memset(&m_nlhr, 0, sizeof(m_nlhr)); + char* tmp; tmp = mir_u2a(m_pszFile); + HTTPFormData frm[] = { + { "Authorization", HTTPFORM_HEADER("Client-ID 2a7303d78abe041") }, + { "image", HTTPFORM_FILE(tmp) }, + }; + + int error = HTTPFormCreate(&m_nlhr, REQUEST_POST, "https://api.imgur.com/3/image", frm, _countof(frm)); + mir_free(tmp); + if (error) + return !m_bAsync; + // start upload thread + if (m_bAsync) { + mir_forkthread(&CSendHost_Imgur::SendThread, this); + return 0; + } + SendThread(this); + return 1; +} + +void CSendHost_Imgur::SendThread(void* obj) +{ + CSendHost_Imgur *self = (CSendHost_Imgur*)obj; + // send DATA and wait for m_nlreply + NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &self->m_nlhr)); + self->HTTPFormDestroy(&self->m_nlhr); + if (reply) { + if (reply->dataLength) { + JSONROOT root(reply->pData); + if (root) { + if ((*root)["success"].as_bool()) { + self->m_URL = (*root)["data"]["link"].as_mstring(); + int idx = self->m_URL.ReverseFind('.'); + if (idx != -1) { + self->m_URLthumb = self->m_URL; + self->m_URLthumb.Insert(idx, 'm'); + } + self->svcSendMsgExit(self->m_URL); return; + } + else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, (*root)["status"].as_int(), 0); + } + else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); + } + else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); + } + else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, self->m_nlhr.resultCode); + + self->Exit(ACKRESULT_FAILED); +} diff --git a/plugins/SendScreenshotPlus/src/CSendHost_imgur.h b/plugins/SendScreenshotPlus/src/CSendHost_imgur.h index b64b118391..544afecd53 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_imgur.h +++ b/plugins/SendScreenshotPlus/src/CSendHost_imgur.h @@ -1,30 +1,30 @@ -/* - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2014-22 Miranda NG team (https://miranda-ng.org) - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. -*/ -#ifndef _CSEND_HOST_IMGUR_H -#define _CSEND_HOST_IMGUR_H -class CSendHost_Imgur : public CSend { -// API: http://api.imgur.com/endpoints/image - public: - CSendHost_Imgur(HWND Owner, MCONTACT hContact, bool bAsync); - ~CSendHost_Imgur(); - - int Send() override; - - protected: - NETLIBHTTPREQUEST m_nlhr; - static void SendThread(void* obj); -}; -#endif +/* + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2014-23 Miranda NG team (https://miranda-ng.org) + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. +*/ +#ifndef _CSEND_HOST_IMGUR_H +#define _CSEND_HOST_IMGUR_H +class CSendHost_Imgur : public CSend { +// API: http://api.imgur.com/endpoints/image + public: + CSendHost_Imgur(HWND Owner, MCONTACT hContact, bool bAsync); + ~CSendHost_Imgur(); + + int Send() override; + + protected: + NETLIBHTTPREQUEST m_nlhr; + static void SendThread(void* obj); +}; +#endif diff --git a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp index 0b6c6c2311..58651ae85d 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp +++ b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp @@ -1,105 +1,105 @@ -/* - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2014-22 Miranda NG team (https://miranda-ng.org) - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. -*/ -#include "stdafx.h" - -CSendHost_UploadPie::CSendHost_UploadPie(HWND Owner, MCONTACT hContact, bool bAsync, int expire) - : m_expire(expire), CSend(Owner, hContact, bAsync) -{ - m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; - m_pszSendTyp = LPGENW("Image upload"); -} - -CSendHost_UploadPie::~CSendHost_UploadPie() -{ -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static const char kHostURL[] = "https://uploadpie.com/"; - -int CSendHost_UploadPie::Send() -{ - if (!g_hNetlibUser) { // check Netlib - Error(SS_ERR_INIT, m_pszSendTyp); - Exit(ACKRESULT_FAILED); - return !m_bAsync; - } - memset(&m_nlhr, 0, sizeof(m_nlhr)); - char* tmp; tmp = mir_u2a(m_pszFile); - HTTPFormData frm[] = { - { "MAX_FILE_SIZE", HTTPFORM_INT(3145728) }, - { "upload", HTTPFORM_INT(1) }, - { "uploadedfile", HTTPFORM_FILE(tmp) }, - { "expire", HTTPFORM_INT(m_expire) }, - }; - - int error = HTTPFormCreate(&m_nlhr, REQUEST_POST, kHostURL, frm, _countof(frm)); - mir_free(tmp); - if (error) - return !m_bAsync; - - // start upload thread - if (m_bAsync) { - mir_forkthread(&CSendHost_UploadPie::SendThread, this); - return 0; - } - SendThread(this); - return 1; -} - -void CSendHost_UploadPie::SendThread(void* obj) -{ - CSendHost_UploadPie* self = (CSendHost_UploadPie*)obj; - // send DATA and wait for m_nlreply - NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &self->m_nlhr)); - self->HTTPFormDestroy(&self->m_nlhr); - if (reply) { - if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->dataLength) { - reply->pData[reply->dataLength - 1] = '\0'; // make sure its null terminated - char* url = reply->pData; - do { - char* pos; - if ((url = strstr(url, kHostURL))) { - for (pos = url + _countof(kHostURL)-1; (*pos >= '0'&&*pos <= '9') || (*pos >= 'a'&&*pos <= 'z') || (*pos >= 'A'&&*pos <= 'Z') || *pos == '_' || *pos == '-' || *pos == '"' || *pos == '\''; ++pos) { - if (*pos == '"' || *pos == '\'') break; - } - if (url + _countof(kHostURL)-1 != pos && (*pos == '"' || *pos == '\'')) { - *pos = '\0'; - break; - } - ++url; - } - } while (url); - - if (url) { - self->m_URL = url; - self->svcSendMsgExit(url); return; - } - else { // check error mess from server - const char* err = GetHTMLContent(reply->pData, "

"); - wchar_t* werr; - if (err) werr = mir_a2u(err); - else werr = mir_a2u(reply->pData); - self->Error(L"%s", werr); - mir_free(werr); - } - } - else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); - } - else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, self->m_nlhr.resultCode); - - self->Exit(ACKRESULT_FAILED); -} +/* + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2014-23 Miranda NG team (https://miranda-ng.org) + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. +*/ +#include "stdafx.h" + +CSendHost_UploadPie::CSendHost_UploadPie(HWND Owner, MCONTACT hContact, bool bAsync, int expire) + : m_expire(expire), CSend(Owner, hContact, bAsync) +{ + m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; + m_pszSendTyp = LPGENW("Image upload"); +} + +CSendHost_UploadPie::~CSendHost_UploadPie() +{ +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static const char kHostURL[] = "https://uploadpie.com/"; + +int CSendHost_UploadPie::Send() +{ + if (!g_hNetlibUser) { // check Netlib + Error(SS_ERR_INIT, m_pszSendTyp); + Exit(ACKRESULT_FAILED); + return !m_bAsync; + } + memset(&m_nlhr, 0, sizeof(m_nlhr)); + char* tmp; tmp = mir_u2a(m_pszFile); + HTTPFormData frm[] = { + { "MAX_FILE_SIZE", HTTPFORM_INT(3145728) }, + { "upload", HTTPFORM_INT(1) }, + { "uploadedfile", HTTPFORM_FILE(tmp) }, + { "expire", HTTPFORM_INT(m_expire) }, + }; + + int error = HTTPFormCreate(&m_nlhr, REQUEST_POST, kHostURL, frm, _countof(frm)); + mir_free(tmp); + if (error) + return !m_bAsync; + + // start upload thread + if (m_bAsync) { + mir_forkthread(&CSendHost_UploadPie::SendThread, this); + return 0; + } + SendThread(this); + return 1; +} + +void CSendHost_UploadPie::SendThread(void* obj) +{ + CSendHost_UploadPie* self = (CSendHost_UploadPie*)obj; + // send DATA and wait for m_nlreply + NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &self->m_nlhr)); + self->HTTPFormDestroy(&self->m_nlhr); + if (reply) { + if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->dataLength) { + reply->pData[reply->dataLength - 1] = '\0'; // make sure its null terminated + char* url = reply->pData; + do { + char* pos; + if ((url = strstr(url, kHostURL))) { + for (pos = url + _countof(kHostURL)-1; (*pos >= '0'&&*pos <= '9') || (*pos >= 'a'&&*pos <= 'z') || (*pos >= 'A'&&*pos <= 'Z') || *pos == '_' || *pos == '-' || *pos == '"' || *pos == '\''; ++pos) { + if (*pos == '"' || *pos == '\'') break; + } + if (url + _countof(kHostURL)-1 != pos && (*pos == '"' || *pos == '\'')) { + *pos = '\0'; + break; + } + ++url; + } + } while (url); + + if (url) { + self->m_URL = url; + self->svcSendMsgExit(url); return; + } + else { // check error mess from server + const char* err = GetHTMLContent(reply->pData, "

"); + wchar_t* werr; + if (err) werr = mir_a2u(err); + else werr = mir_a2u(reply->pData); + self->Error(L"%s", werr); + mir_free(werr); + } + } + else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); + } + else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, self->m_nlhr.resultCode); + + self->Exit(ACKRESULT_FAILED); +} diff --git a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h index b1defe20c2..94cfdf1fbc 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h +++ b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h @@ -1,30 +1,30 @@ -/* - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2014-22 Miranda NG team (https://miranda-ng.org) - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. -*/ -#ifndef _CSEND_HOST_UPLOADPIE_H -#define _CSEND_HOST_UPLOADPIE_H -class CSendHost_UploadPie : public CSend { - public: - CSendHost_UploadPie(HWND Owner, MCONTACT hContact, bool bAsync, int expire); - ~CSendHost_UploadPie(); - - int Send() override; - - protected: - int m_expire; - NETLIBHTTPREQUEST m_nlhr; - static void SendThread(void* obj); -}; -#endif +/* + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2014-23 Miranda NG team (https://miranda-ng.org) + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. +*/ +#ifndef _CSEND_HOST_UPLOADPIE_H +#define _CSEND_HOST_UPLOADPIE_H +class CSendHost_UploadPie : public CSend { + public: + CSendHost_UploadPie(HWND Owner, MCONTACT hContact, bool bAsync, int expire); + ~CSendHost_UploadPie(); + + int Send() override; + + protected: + int m_expire; + NETLIBHTTPREQUEST m_nlhr; + static void SendThread(void* obj); +}; +#endif diff --git a/plugins/SendScreenshotPlus/src/Main.cpp b/plugins/SendScreenshotPlus/src/Main.cpp index e3223f43cc..f2455932b2 100644 --- a/plugins/SendScreenshotPlus/src/Main.cpp +++ b/plugins/SendScreenshotPlus/src/Main.cpp @@ -1,336 +1,336 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original source code -(c) 2004-2006 Sérgio Vieira Rolanski (ported from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -// Prototypes /////////////////////////////////////////////////////////////////////////// - -CMPlugin g_plugin; -HGENMENU g_hMenu1, g_hMenu2; - -ATOM g_clsTargetHighlighter = 0; -MGLOBAL g_myGlobals; -HNETLIBUSER g_hNetlibUser; - -IconItem ICONS[ICO_END_] = -{ - { LPGEN("Main Icon"), "main", IDI_MAIN, 32 }, - { LPGEN("Main Icon"), "mainxs", IDI_MAIN }, - { LPGEN("Target Cursor"), "target", IDI_TARGET, 32 }, - { LPGEN("Target Desktop"), "monitor", IDI_MONITOR, 32 }, -}; - -IconItem ICONS_BTN[ICO_BTN_END_] = -{ - { LPGEN("Help"), "help", IDI_HELP }, - { LPGEN("Open Folder"), "folder", IDI_FOLDER }, - { LPGEN("Description off"), "desc", IDI_DESC }, - { LPGEN("Description on"), "descon", IDI_DESCON }, - { LPGEN("Delete off"), "del", IDI_DEL }, - { LPGEN("Delete on"), "delon", IDI_DELON }, - { LPGEN("Prev"), "arrowl", IDI_ARROWL }, - { LPGEN("Next"), "arrowr", IDI_ARROWR }, - { LPGEN("Update"), "update", IDI_UPDATE }, - { LPGEN("OK"), "ok", IDI_OK }, - { LPGEN("Cancel"), "cancel", IDI_CANCEL }, - { LPGEN("Edit"), "edit", IDI_EDIT }, - { LPGEN("Edit on"), "editon", IDI_EDITON }, - { LPGEN("Copy"), "copy", IDI_COPY }, - { LPGEN("BBCode"), "bbc", IDI_BBC }, - { LPGEN("BBCode link"), "bbclnk", IDI_BBC2 }, - { LPGEN("Down arrow"), "downarrow", IDI_DOWNARROW }, -}; - -static HANDLE m_hFolderScreenshot = nullptr; -wchar_t* GetCustomPath() -{ - wchar_t *pszPath = Utils_ReplaceVarsW(L"%miranda_userdata%\\Screenshots"); - if (m_hFolderScreenshot) { - wchar_t szPath[1024] = { 0 }; - FoldersGetCustomPathW(m_hFolderScreenshot, szPath, 1024, pszPath); - mir_free(pszPath); - pszPath = mir_wstrdup(szPath); - } - if (!pszPath) { - MessageBox(nullptr, L"Can not retrieve screenshot path.", L"SendSS", MB_OK | MB_ICONERROR | MB_APPLMODAL); - return nullptr; - } - int result = CreateDirectoryTreeW(pszPath); - if (result) { - wchar_t szError[MAX_PATH]; - mir_snwprintf(szError, MAX_PATH, TranslateT("Could not create screenshot folder (error code: %d):\n%s\nDo you have write permissions?"), result, pszPath); - MessageBox(nullptr, szError, L"SendSS", MB_OK | MB_ICONERROR | MB_APPLMODAL); - mir_free(pszPath); - return nullptr; - } - return pszPath; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Callback function of service for contact menu and main menu -// wParam = contact handle -// lParam = 0 (or 0xFFFF to preselect window under cursor) - -INT_PTR service_OpenCaptureDialog(WPARAM wParam, LPARAM lParam) -{ - TfrmMain *frmMain = new TfrmMain(); - if (!frmMain) { - MessageBox(nullptr, TranslateT("Could not create main dialog."), TranslateT("Error"), MB_OK | MB_ICONERROR | MB_APPLMODAL); - return -1; - } - wchar_t *pszPath = GetCustomPath(); - if (!pszPath) { - delete frmMain; - return -1; - } - frmMain->Init(pszPath, wParam); - mir_free(pszPath); - if (lParam == 0xFFFF) { - frmMain->SetTargetWindow(nullptr); - } - frmMain->Show(); - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Callback function of service -// 1. Send a screenshot of the desktop to the selected contact -// wParam = contact handle -// lParam = 0 -// 2. Open the capture dialog in take screenshot only mode (it will not be sent) -// wParam = 0 -// lParam = anything but 0 - -INT_PTR service_SendDesktop(WPARAM wParam, LPARAM) -{ - TfrmMain *frmMain = new TfrmMain(); - if (!frmMain) { - MessageBox(nullptr, TranslateT("Could not create main dialog."), TranslateT("Error"), MB_OK | MB_ICONERROR | MB_APPLMODAL); - return -1; - } - wchar_t *pszPath = GetCustomPath(); - if (!pszPath) { - delete frmMain; - return -1; - } - - MCONTACT hContact = (MCONTACT)wParam; - frmMain->m_opt_chkTimed = false; - frmMain->m_opt_tabCapture = 1; - frmMain->m_opt_cboxDesktop = 0; - frmMain->m_opt_chkEditor = false; - frmMain->m_opt_cboxSendBy = Contact::IsGroupChat(hContact) ? SS_IMAGESHACK : SS_FILESEND; - frmMain->Init(pszPath, hContact); // this method create the window hidden. - mir_free(pszPath); - frmMain->btnCaptureClick(); // this method will call Close() - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Callback function of service for sending image to imageshack.us -// wParam = (char*)filename -// lParam = (HANDLE)contact (can be null) - -INT_PTR service_Send2ImageShack(WPARAM wParam, LPARAM lParam) -{ - char *result = nullptr; - CSendHost_ImageShack *cSend = new CSendHost_ImageShack(nullptr, lParam, false); - cSend->m_bDeleteAfterSend = false; - cSend->SetFile((char *)wParam); - if (lParam != NULL) { - if (cSend->Send()) delete cSend; - return NULL; - } - cSend->SendSilent(); - if (cSend->GetURL()) { - result = mir_strdup(cSend->GetURL()); - } - else { - result = mir_u2a(cSend->GetErrorMsg()); - } - delete cSend; - return (INT_PTR)result; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static PLUGININFOEX pluginInfoEx = -{ - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), - __DESCRIPTION, - __AUTHOR, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, - // {ED39AF7C-BECD-404E-9499-4D04F711B9CB} - { 0xed39af7c, 0xbecd, 0x404e, { 0x94, 0x99, 0x4d, 0x04, 0xf7, 0x11, 0xb9, 0xcb } } -}; - -CMPlugin::CMPlugin() : - PLUGIN(MODULENAME, pluginInfoEx) -{} - -///////////////////////////////////////////////////////////////////////////////////////// -// hooks - -int hook_ModulesLoaded(WPARAM, LPARAM) -{ - g_myGlobals.PluginHTTPExist = ServiceExists(MS_HTTP_ACCEPT_CONNECTIONS); - g_myGlobals.PluginFTPExist = ServiceExists(MS_FTPFILE_UPLOAD); - g_myGlobals.PluginCloudFileExist = ServiceExists(MS_CLOUDFILE_UPLOAD); - - // Netlib register - NETLIBUSER nlu = {}; - nlu.szSettingsModule = __PLUGIN_NAME; - nlu.szDescriptiveName.w = TranslateT("SendSS"); - nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE; //|NUF_NOHTTPSOPTION; - g_hNetlibUser = Netlib_RegisterUser(&nlu); - - // load my button class / or use UInfoEx - CtrlButtonLoadModule(); - - // Folders plugin support - m_hFolderScreenshot = FoldersRegisterCustomPathW(LPGEN("SendSS"), LPGEN("Screenshots"), - PROFILE_PATHW L"\\" CURRENT_PROFILEW L"\\Screenshots"); - return 0; -} - -int hook_SystemPreShutdown(WPARAM, LPARAM) -{ - TfrmMain::Unload(); - - // Netlib unregister - Netlib_CloseHandle(g_hNetlibUser); - - // uninitialize classes - CtrlButtonUnloadModule(); - return 0; -} - -int hook_PrebuildContactMenu(WPARAM hContact, LPARAM) -{ - INT_PTR flags = CallProtoService(Proto_GetBaseAccountName(hContact), PS_GETCAPS, PFLAGNUM_1, 0); - bool bEnabled = (flags != CALLSERVICE_NOTFOUND) && (flags & PF1_FILE) != 0; - Menu_ShowItem(g_hMenu1, bEnabled); - Menu_ShowItem(g_hMenu2, bEnabled); - return 0; -} - -static int TabsrmmButtonsInit(WPARAM, LPARAM) -{ - // SRMM toolbar button - BBButton bbd = {}; - bbd.pszModuleName = MODULENAME; - bbd.dwButtonID = 1; - bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON; - bbd.dwDefPos = 201; - bbd.hIcon = GetIconHandle(ICO_MAINXS); - Srmm_AddButton(&bbd, &g_plugin); - return 0; -} - -static int TabsrmmButtonPressed(WPARAM hContact, LPARAM lParam) -{ - CustomButtonClickData *cbcd = (CustomButtonClickData *)lParam; - if (!mir_strcmp(cbcd->pszModule, MODULENAME) && cbcd->dwButtonId == 1) - CallService(MS_SENDSS_OPENDIALOG, hContact, 0); - - return 0; -} - -int CMPlugin::Load() -{ - // hook events - HookEvent(ME_SYSTEM_MODULESLOADED, hook_ModulesLoaded); - HookEvent(ME_SYSTEM_PRESHUTDOWN, hook_SystemPreShutdown); - HookEvent(ME_CLIST_PREBUILDCONTACTMENU, hook_PrebuildContactMenu); - - HookEvent(ME_MSG_BUTTONPRESSED, TabsrmmButtonPressed); - HookTemporaryEvent(ME_MSG_TOOLBARLOADED, TabsrmmButtonsInit); - - // icons - g_plugin.registerIcon(MODULENAME, ICONS, MODULENAME); - g_plugin.registerIcon(MODULENAME "/" LPGEN("Buttons"), ICONS_BTN, MODULENAME); - - // services -#define srv_reg(name) CreateServiceFunction(MODULENAME "/" #name, service_##name); - srv_reg(OpenCaptureDialog); - srv_reg(SendDesktop); - srv_reg(Send2ImageShack); - - // menu items - CMenuItem mi(&g_plugin); - mi.flags = CMIF_UNICODE; - mi.hIcolibItem = GetIconHandle(ICO_MAINXS); - - SET_UID(mi, 0xa559a22e, 0xd0f9, 0x4553, 0x8e, 0x68, 0x55, 0xb3, 0xae, 0xc4, 0x5d, 0x93); - mi.name.w = LPGENW("Take a screenshot"); - mi.pszService = MS_SENDSS_OPENDIALOG; - mi.position = 1000001; - Menu_AddMainMenuItem(&mi); - - SET_UID(mi, 0xfea0a84, 0x1767, 0x4605, 0x99, 0xf0, 0xa9, 0x48, 0x1a, 0xa6, 0x6f, 0xce); - mi.name.w = LPGENW("Send screenshot"); - mi.pszService = MS_SENDSS_OPENDIALOG; - mi.position = 1000000; - g_hMenu1 = Menu_AddContactMenuItem(&mi); - - SET_UID(mi, 0x8d5b0d9a, 0x68d4, 0x4594, 0x9f, 0x41, 0x0, 0x64, 0x20, 0xe7, 0xf8, 0x9f); - mi.name.w = LPGENW("Send desktop screenshot"); - mi.pszService = MS_SENDSS_SENDDESKTOP; - mi.position = 1000001; - g_hMenu2 = Menu_AddContactMenuItem(&mi); - - // hotkey's - HOTKEYDESC hkd = {}; - hkd.pszName = "Open SendSS+"; - hkd.szDescription.w = LPGENW("Open SendSS+"); - hkd.szSection.w = L"SendSS+"; - hkd.pszService = MS_SENDSS_OPENDIALOG; - hkd.lParam = 0xFFFF; - hkd.dwFlags = HKD_UNICODE; - g_plugin.addHotkey(&hkd); - - // register highlighter window class - HBRUSH brush = CreateSolidBrush(0x0000FF00); // owned by class - WNDCLASS wndclass = { CS_HREDRAW | CS_VREDRAW, DefWindowProc, 0, 0, g_plugin.getInst(), nullptr, nullptr, brush, nullptr, L"SendSSHighlighter" }; - g_clsTargetHighlighter = RegisterClass(&wndclass); - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Prepare the plugin to stop - -int CMPlugin::Unload() -{ - if (g_clsTargetHighlighter) - UnregisterClass((wchar_t *)g_clsTargetHighlighter, g_plugin.getInst()), g_clsTargetHighlighter = 0; - return 0; -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original source code +(c) 2004-2006 Sérgio Vieira Rolanski (ported from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +// Prototypes /////////////////////////////////////////////////////////////////////////// + +CMPlugin g_plugin; +HGENMENU g_hMenu1, g_hMenu2; + +ATOM g_clsTargetHighlighter = 0; +MGLOBAL g_myGlobals; +HNETLIBUSER g_hNetlibUser; + +IconItem ICONS[ICO_END_] = +{ + { LPGEN("Main Icon"), "main", IDI_MAIN, 32 }, + { LPGEN("Main Icon"), "mainxs", IDI_MAIN }, + { LPGEN("Target Cursor"), "target", IDI_TARGET, 32 }, + { LPGEN("Target Desktop"), "monitor", IDI_MONITOR, 32 }, +}; + +IconItem ICONS_BTN[ICO_BTN_END_] = +{ + { LPGEN("Help"), "help", IDI_HELP }, + { LPGEN("Open Folder"), "folder", IDI_FOLDER }, + { LPGEN("Description off"), "desc", IDI_DESC }, + { LPGEN("Description on"), "descon", IDI_DESCON }, + { LPGEN("Delete off"), "del", IDI_DEL }, + { LPGEN("Delete on"), "delon", IDI_DELON }, + { LPGEN("Prev"), "arrowl", IDI_ARROWL }, + { LPGEN("Next"), "arrowr", IDI_ARROWR }, + { LPGEN("Update"), "update", IDI_UPDATE }, + { LPGEN("OK"), "ok", IDI_OK }, + { LPGEN("Cancel"), "cancel", IDI_CANCEL }, + { LPGEN("Edit"), "edit", IDI_EDIT }, + { LPGEN("Edit on"), "editon", IDI_EDITON }, + { LPGEN("Copy"), "copy", IDI_COPY }, + { LPGEN("BBCode"), "bbc", IDI_BBC }, + { LPGEN("BBCode link"), "bbclnk", IDI_BBC2 }, + { LPGEN("Down arrow"), "downarrow", IDI_DOWNARROW }, +}; + +static HANDLE m_hFolderScreenshot = nullptr; +wchar_t* GetCustomPath() +{ + wchar_t *pszPath = Utils_ReplaceVarsW(L"%miranda_userdata%\\Screenshots"); + if (m_hFolderScreenshot) { + wchar_t szPath[1024] = { 0 }; + FoldersGetCustomPathW(m_hFolderScreenshot, szPath, 1024, pszPath); + mir_free(pszPath); + pszPath = mir_wstrdup(szPath); + } + if (!pszPath) { + MessageBox(nullptr, L"Can not retrieve screenshot path.", L"SendSS", MB_OK | MB_ICONERROR | MB_APPLMODAL); + return nullptr; + } + int result = CreateDirectoryTreeW(pszPath); + if (result) { + wchar_t szError[MAX_PATH]; + mir_snwprintf(szError, MAX_PATH, TranslateT("Could not create screenshot folder (error code: %d):\n%s\nDo you have write permissions?"), result, pszPath); + MessageBox(nullptr, szError, L"SendSS", MB_OK | MB_ICONERROR | MB_APPLMODAL); + mir_free(pszPath); + return nullptr; + } + return pszPath; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Callback function of service for contact menu and main menu +// wParam = contact handle +// lParam = 0 (or 0xFFFF to preselect window under cursor) + +INT_PTR service_OpenCaptureDialog(WPARAM wParam, LPARAM lParam) +{ + TfrmMain *frmMain = new TfrmMain(); + if (!frmMain) { + MessageBox(nullptr, TranslateT("Could not create main dialog."), TranslateT("Error"), MB_OK | MB_ICONERROR | MB_APPLMODAL); + return -1; + } + wchar_t *pszPath = GetCustomPath(); + if (!pszPath) { + delete frmMain; + return -1; + } + frmMain->Init(pszPath, wParam); + mir_free(pszPath); + if (lParam == 0xFFFF) { + frmMain->SetTargetWindow(nullptr); + } + frmMain->Show(); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Callback function of service +// 1. Send a screenshot of the desktop to the selected contact +// wParam = contact handle +// lParam = 0 +// 2. Open the capture dialog in take screenshot only mode (it will not be sent) +// wParam = 0 +// lParam = anything but 0 + +INT_PTR service_SendDesktop(WPARAM wParam, LPARAM) +{ + TfrmMain *frmMain = new TfrmMain(); + if (!frmMain) { + MessageBox(nullptr, TranslateT("Could not create main dialog."), TranslateT("Error"), MB_OK | MB_ICONERROR | MB_APPLMODAL); + return -1; + } + wchar_t *pszPath = GetCustomPath(); + if (!pszPath) { + delete frmMain; + return -1; + } + + MCONTACT hContact = (MCONTACT)wParam; + frmMain->m_opt_chkTimed = false; + frmMain->m_opt_tabCapture = 1; + frmMain->m_opt_cboxDesktop = 0; + frmMain->m_opt_chkEditor = false; + frmMain->m_opt_cboxSendBy = Contact::IsGroupChat(hContact) ? SS_IMAGESHACK : SS_FILESEND; + frmMain->Init(pszPath, hContact); // this method create the window hidden. + mir_free(pszPath); + frmMain->btnCaptureClick(); // this method will call Close() + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Callback function of service for sending image to imageshack.us +// wParam = (char*)filename +// lParam = (HANDLE)contact (can be null) + +INT_PTR service_Send2ImageShack(WPARAM wParam, LPARAM lParam) +{ + char *result = nullptr; + CSendHost_ImageShack *cSend = new CSendHost_ImageShack(nullptr, lParam, false); + cSend->m_bDeleteAfterSend = false; + cSend->SetFile((char *)wParam); + if (lParam != NULL) { + if (cSend->Send()) delete cSend; + return NULL; + } + cSend->SendSilent(); + if (cSend->GetURL()) { + result = mir_strdup(cSend->GetURL()); + } + else { + result = mir_u2a(cSend->GetErrorMsg()); + } + delete cSend; + return (INT_PTR)result; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static PLUGININFOEX pluginInfoEx = +{ + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {ED39AF7C-BECD-404E-9499-4D04F711B9CB} + { 0xed39af7c, 0xbecd, 0x404e, { 0x94, 0x99, 0x4d, 0x04, 0xf7, 0x11, 0xb9, 0xcb } } +}; + +CMPlugin::CMPlugin() : + PLUGIN(MODULENAME, pluginInfoEx) +{} + +///////////////////////////////////////////////////////////////////////////////////////// +// hooks + +int hook_ModulesLoaded(WPARAM, LPARAM) +{ + g_myGlobals.PluginHTTPExist = ServiceExists(MS_HTTP_ACCEPT_CONNECTIONS); + g_myGlobals.PluginFTPExist = ServiceExists(MS_FTPFILE_UPLOAD); + g_myGlobals.PluginCloudFileExist = ServiceExists(MS_CLOUDFILE_UPLOAD); + + // Netlib register + NETLIBUSER nlu = {}; + nlu.szSettingsModule = __PLUGIN_NAME; + nlu.szDescriptiveName.w = TranslateT("SendSS"); + nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_UNICODE; //|NUF_NOHTTPSOPTION; + g_hNetlibUser = Netlib_RegisterUser(&nlu); + + // load my button class / or use UInfoEx + CtrlButtonLoadModule(); + + // Folders plugin support + m_hFolderScreenshot = FoldersRegisterCustomPathW(LPGEN("SendSS"), LPGEN("Screenshots"), + PROFILE_PATHW L"\\" CURRENT_PROFILEW L"\\Screenshots"); + return 0; +} + +int hook_SystemPreShutdown(WPARAM, LPARAM) +{ + TfrmMain::Unload(); + + // Netlib unregister + Netlib_CloseHandle(g_hNetlibUser); + + // uninitialize classes + CtrlButtonUnloadModule(); + return 0; +} + +int hook_PrebuildContactMenu(WPARAM hContact, LPARAM) +{ + INT_PTR flags = CallProtoService(Proto_GetBaseAccountName(hContact), PS_GETCAPS, PFLAGNUM_1, 0); + bool bEnabled = (flags != CALLSERVICE_NOTFOUND) && (flags & PF1_FILE) != 0; + Menu_ShowItem(g_hMenu1, bEnabled); + Menu_ShowItem(g_hMenu2, bEnabled); + return 0; +} + +static int TabsrmmButtonsInit(WPARAM, LPARAM) +{ + // SRMM toolbar button + BBButton bbd = {}; + bbd.pszModuleName = MODULENAME; + bbd.dwButtonID = 1; + bbd.bbbFlags = BBBF_ISIMBUTTON | BBBF_ISCHATBUTTON; + bbd.dwDefPos = 201; + bbd.hIcon = GetIconHandle(ICO_MAINXS); + Srmm_AddButton(&bbd, &g_plugin); + return 0; +} + +static int TabsrmmButtonPressed(WPARAM hContact, LPARAM lParam) +{ + CustomButtonClickData *cbcd = (CustomButtonClickData *)lParam; + if (!mir_strcmp(cbcd->pszModule, MODULENAME) && cbcd->dwButtonId == 1) + CallService(MS_SENDSS_OPENDIALOG, hContact, 0); + + return 0; +} + +int CMPlugin::Load() +{ + // hook events + HookEvent(ME_SYSTEM_MODULESLOADED, hook_ModulesLoaded); + HookEvent(ME_SYSTEM_PRESHUTDOWN, hook_SystemPreShutdown); + HookEvent(ME_CLIST_PREBUILDCONTACTMENU, hook_PrebuildContactMenu); + + HookEvent(ME_MSG_BUTTONPRESSED, TabsrmmButtonPressed); + HookTemporaryEvent(ME_MSG_TOOLBARLOADED, TabsrmmButtonsInit); + + // icons + g_plugin.registerIcon(MODULENAME, ICONS, MODULENAME); + g_plugin.registerIcon(MODULENAME "/" LPGEN("Buttons"), ICONS_BTN, MODULENAME); + + // services +#define srv_reg(name) CreateServiceFunction(MODULENAME "/" #name, service_##name); + srv_reg(OpenCaptureDialog); + srv_reg(SendDesktop); + srv_reg(Send2ImageShack); + + // menu items + CMenuItem mi(&g_plugin); + mi.flags = CMIF_UNICODE; + mi.hIcolibItem = GetIconHandle(ICO_MAINXS); + + SET_UID(mi, 0xa559a22e, 0xd0f9, 0x4553, 0x8e, 0x68, 0x55, 0xb3, 0xae, 0xc4, 0x5d, 0x93); + mi.name.w = LPGENW("Take a screenshot"); + mi.pszService = MS_SENDSS_OPENDIALOG; + mi.position = 1000001; + Menu_AddMainMenuItem(&mi); + + SET_UID(mi, 0xfea0a84, 0x1767, 0x4605, 0x99, 0xf0, 0xa9, 0x48, 0x1a, 0xa6, 0x6f, 0xce); + mi.name.w = LPGENW("Send screenshot"); + mi.pszService = MS_SENDSS_OPENDIALOG; + mi.position = 1000000; + g_hMenu1 = Menu_AddContactMenuItem(&mi); + + SET_UID(mi, 0x8d5b0d9a, 0x68d4, 0x4594, 0x9f, 0x41, 0x0, 0x64, 0x20, 0xe7, 0xf8, 0x9f); + mi.name.w = LPGENW("Send desktop screenshot"); + mi.pszService = MS_SENDSS_SENDDESKTOP; + mi.position = 1000001; + g_hMenu2 = Menu_AddContactMenuItem(&mi); + + // hotkey's + HOTKEYDESC hkd = {}; + hkd.pszName = "Open SendSS+"; + hkd.szDescription.w = LPGENW("Open SendSS+"); + hkd.szSection.w = L"SendSS+"; + hkd.pszService = MS_SENDSS_OPENDIALOG; + hkd.lParam = 0xFFFF; + hkd.dwFlags = HKD_UNICODE; + g_plugin.addHotkey(&hkd); + + // register highlighter window class + HBRUSH brush = CreateSolidBrush(0x0000FF00); // owned by class + WNDCLASS wndclass = { CS_HREDRAW | CS_VREDRAW, DefWindowProc, 0, 0, g_plugin.getInst(), nullptr, nullptr, brush, nullptr, L"SendSSHighlighter" }; + g_clsTargetHighlighter = RegisterClass(&wndclass); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Prepare the plugin to stop + +int CMPlugin::Unload() +{ + if (g_clsTargetHighlighter) + UnregisterClass((wchar_t *)g_clsTargetHighlighter, g_plugin.getInst()), g_clsTargetHighlighter = 0; + return 0; +} diff --git a/plugins/SendScreenshotPlus/src/UMainForm.cpp b/plugins/SendScreenshotPlus/src/UMainForm.cpp index 86b53ffef7..d67ebe3de0 100644 --- a/plugins/SendScreenshotPlus/src/UMainForm.cpp +++ b/plugins/SendScreenshotPlus/src/UMainForm.cpp @@ -1,1124 +1,1124 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -#include - -void TfrmMain::Unload() -{ - std::list lst; - for (auto &it : _HandleMapping) - lst.push_back(it.second); // we can't delete inside loop.. not MT compatible - - while (!lst.empty()) { - DestroyWindow(lst.front()->m_hWnd); // deletes class - lst.pop_front(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -INT_PTR CALLBACK TfrmMain::DlgProc_CaptureTabPage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - // main message handling is done inside TfrmMain::DlgTfrmMain - switch (uMsg) { - case WM_INITDIALOG: - switch (lParam) { - case IDD_UMain_CaptureWindow: - Static_SetIcon(GetDlgItem(hDlg, ID_imgTarget), GetIcon(ICO_TARGET)); - SetDlgItemText(hDlg, ID_edtCaption, TranslateT("Drag&Drop the target on the desired window.")); - break; - case IDD_UMain_CaptureDesktop: - Static_SetIcon(GetDlgItem(hDlg, ID_imgTarget), GetIcon(ICO_MONITOR)); - break; - case IDD_UMain_CaptureFile: - Static_SetIcon(GetDlgItem(hDlg, ID_imgTarget), GetIcon(ICO_MAIN)); - break; - } - SetFocus(GetDlgItem(hDlg, ID_imgTarget)); - return FALSE; - - case WM_CTLCOLORDLG: - case WM_CTLCOLOREDIT: - case WM_CTLCOLORSTATIC: - SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); - return (INT_PTR)GetStockObject(WHITE_BRUSH); - - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == ID_btnExplore) { // local file tab - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - wchar_t filename[MAX_PATH]; - GetDlgItemText(hDlg, ID_edtSize, filename, _countof(filename)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hDlg; - ofn.lpstrFilter = L"Images\0*.png;*.jpg;*.jpeg;*.bmp;*.gif;*.tif;*.tiff\0"; - ofn.nFilterIndex = 1; - ofn.lpstrFile = filename; - ofn.nMaxFile = MAX_PATH; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_READONLY; - if (GetOpenFileName(&ofn)) { - SetDlgItemText(hDlg, ID_edtSize, filename); - } - break; - } - SendMessage(GetParent(hDlg), uMsg, wParam, lParam); - break; - case WM_NOTIFY: - SendMessage(GetParent(hDlg), uMsg, wParam, lParam); - break; - case WM_DESTROY: - break; - } - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -TfrmMain::CHandleMapping TfrmMain::_HandleMapping; - -INT_PTR CALLBACK TfrmMain::DlgTfrmMain(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_CTLCOLOREDIT || msg == WM_CTLCOLORSTATIC) { - switch (GetWindowLongPtr((HWND)lParam, GWL_ID)) { - case IDC_HEADERBAR: - SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); - break; - default: - return 0; - } - SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); - return (INT_PTR)GetStockObject(WHITE_BRUSH); - } - - CHandleMapping::iterator wnd; - if (msg == WM_INITDIALOG) { - wnd = _HandleMapping.insert(CHandleMapping::value_type(hWnd, reinterpret_cast(lParam))).first; - wnd->second->m_hWnd = hWnd; - wnd->second->wmInitdialog(wParam, lParam); - return 0; - } - wnd = _HandleMapping.find(hWnd); - if (wnd == _HandleMapping.end()) - return 0; - - switch (msg) { - case WM_DROPFILES: - // Drag&Drop of local files - { - wchar_t filename[MAX_PATH]; - if (!DragQueryFile((HDROP)wParam, 0, filename, MAX_PATH)) - *filename = '\0'; - DragFinish((HDROP)wParam); - if (wnd->second->m_hwndTabPage) - ShowWindow(wnd->second->m_hwndTabPage, SW_HIDE); - - wnd->second->m_opt_tabCapture = 2; // activate file tab - TabCtrl_SetCurSel(wnd->second->m_hwndTab, wnd->second->m_opt_tabCapture); - - TAB_INFO itab = { TCIF_PARAM }; - TabCtrl_GetItem(wnd->second->m_hwndTab, wnd->second->m_opt_tabCapture, &itab); - wnd->second->m_hwndTabPage = itab.hwndTabPage; - - ShowWindow(wnd->second->m_hwndTabPage, SW_SHOW); - SetDlgItemText(wnd->second->m_hwndTabPage, ID_edtSize, filename); - } - break; - case WM_COMMAND: - wnd->second->wmCommand(wParam, lParam); - break; - case WM_CLOSE: - wnd->second->wmClose(wParam, lParam); - break; - case WM_DESTROY: - delete wnd->second; - break; - case WM_NOTIFY: - wnd->second->wmNotify(wParam, lParam); - break; - case WM_TIMER: - wnd->second->wmTimer(wParam, lParam); - break; - case UM_EVENT: - wnd->second->UMevent(wParam, lParam); - break; - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// WM_INITDIALOG: - -int EnumCloudFileServices(const CFSERVICEINFO *serviceInfo, void *param) -{ - HWND hCtrl = (HWND)param; - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, serviceInfo->userName), new UPLOAD_INFO(SS_CLOUDFILE, (void*)serviceInfo->accountName)); - return 0; -} - -void TfrmMain::wmInitdialog(WPARAM, LPARAM) -{ - HWND hCtrl; - // Taskbar and Window icon - Window_SetIcon_IcoLib(m_hWnd, GetIconHandle(ICO_MAIN)); - - wchar_t *pt = mir_wstrdup(Clist_GetContactDisplayName(m_hContact)); - if (pt && (m_hContact != 0)) { - CMStringW string; - string.AppendFormat(TranslateT("Send screenshot to %s"), pt); - SetWindowText(m_hWnd, string); - } - mir_free(pt); - - // Headerbar - SendDlgItemMessage(m_hWnd, IDC_HEADERBAR, WM_SETICON, ICON_BIG, (LPARAM)GetIcon(ICO_MAIN)); - - // Timed controls - CheckDlgButton(m_hWnd, ID_chkTimed, m_opt_chkTimed ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemInt(m_hWnd, ID_edtTimed, (UINT)m_opt_edtTimed, FALSE); - SendDlgItemMessage(m_hWnd, ID_upTimed, UDM_SETRANGE, 0, (LPARAM)MAKELONG(250, 1)); - chkTimedClick(); // enable disable Timed controls - - // create Image list for tab control - if (!m_himlTab) { - m_himlTab = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1); - ImageList_AddIcon(m_himlTab, GetIcon(ICO_TARGET)); - ImageList_AddIcon(m_himlTab, GetIcon(ICO_MONITOR)); - ImageList_AddIcon(m_himlTab, GetIconBtn(ICO_BTN_FOLDER)); - } - - // create the tab control. - { - m_hwndTab = GetDlgItem(m_hWnd, IDC_CAPTURETAB); - TabCtrl_SetImageList(m_hwndTab, m_himlTab); - TabCtrl_SetItemExtra(m_hwndTab, sizeof(TAB_INFO) - sizeof(TCITEMHEADER)); - RECT rcTab; - TAB_INFO itab; - itab.hwndMain = m_hWnd; - itab.hwndTab = m_hwndTab; - itab.tcih.mask = TCIF_PARAM | TCIF_TEXT | TCIF_IMAGE; - - // Add a tab for each of the three child dialog boxes. - itab.tcih.pszText = TranslateT("Window"); - itab.tcih.iImage = 0; - itab.hwndTabPage = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMain_CaptureWindow), m_hWnd, DlgProc_CaptureTabPage, IDD_UMain_CaptureWindow); - TabCtrl_InsertItem(m_hwndTab, 0, &itab); - - // get tab boundaries (required after 1st tab) - GetClientRect(m_hwndTab, &rcTab); - MapWindowPoints(m_hwndTab, m_hWnd, (POINT*)&rcTab, 2); - TabCtrl_AdjustRect(m_hwndTab, 0, &rcTab); - rcTab.bottom -= rcTab.top; rcTab.right -= rcTab.left; - - SetWindowPos(itab.hwndTabPage, HWND_TOP, rcTab.left, rcTab.top, rcTab.right, rcTab.bottom, 0); - CheckDlgButton(itab.hwndTabPage, ID_chkIndirectCapture, m_opt_chkIndirectCapture ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(itab.hwndTabPage, ID_chkClientArea, m_opt_chkClientArea ? BST_CHECKED : BST_UNCHECKED); - - itab.tcih.pszText = TranslateT("Desktop"); - itab.tcih.iImage = 1; - itab.hwndTabPage = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMain_CaptureDesktop), m_hWnd, DlgProc_CaptureTabPage, IDD_UMain_CaptureDesktop); - TabCtrl_InsertItem(m_hwndTab, 1, &itab); - SetWindowPos(itab.hwndTabPage, HWND_TOP, rcTab.left, rcTab.top, rcTab.right, rcTab.bottom, 0); - - hCtrl = GetDlgItem(itab.hwndTabPage, ID_edtCaption); - ComboBox_ResetContent(hCtrl); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("")), 0); - ComboBox_SetCurSel(hCtrl, 0); - if (m_MonitorCount > 1) { - wchar_t tszTemp[120]; - for (size_t mon = 0; mon < m_MonitorCount; ++mon) { // @todo : fix format for non MSVC compilers - mir_snwprintf(tszTemp, L"%Iu. %s%s", - mon + 1, TranslateT("Monitor"), - (m_Monitors[mon].dwFlags & MONITORINFOF_PRIMARY) ? TranslateT(" (primary)") : L"" - ); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, tszTemp), mon + 1); - } - ComboBox_SelectItem(hCtrl, m_opt_cboxDesktop); - } - PostMessage(m_hWnd, WM_COMMAND, MAKEWPARAM(ID_edtCaption, CBN_SELCHANGE), (LPARAM)hCtrl); - - itab.tcih.pszText = TranslateT("File"); - itab.tcih.iImage = 2; - itab.hwndTabPage = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMain_CaptureFile), m_hWnd, DlgProc_CaptureTabPage, IDD_UMain_CaptureFile); - TabCtrl_InsertItem(m_hwndTab, 2, &itab); - SetWindowPos(itab.hwndTabPage, HWND_TOP, rcTab.left, rcTab.top, rcTab.right, rcTab.bottom, 0); - - // select tab and set m_hwndTabPage - TabCtrl_SetCurSel(m_hwndTab, m_opt_tabCapture); - itab.tcih.mask = TCIF_PARAM; - TabCtrl_GetItem(m_hwndTab, m_opt_tabCapture, &itab); - m_hwndTabPage = itab.hwndTabPage; - ShowWindow(m_hwndTabPage, SW_SHOW); - - // enable Drag&Drop for local file pane - typedef BOOL(WINAPI *ChangeWindowMessageFilterEx_t)(HWND hwnd, UINT message, uint32_t action, PCHANGEFILTERSTRUCT pChangeFilterStruct); - ChangeWindowMessageFilterEx_t pChangeWindowMessageFilterEx; - pChangeWindowMessageFilterEx = (ChangeWindowMessageFilterEx_t)GetProcAddress(GetModuleHandleA("user32"), "ChangeWindowMessageFilterEx"); - if (pChangeWindowMessageFilterEx) { // Win7+, UAC fix - pChangeWindowMessageFilterEx(m_hWnd, WM_DROPFILES, MSGFLT_ALLOW, nullptr); - pChangeWindowMessageFilterEx(m_hWnd, WM_COPYDATA, MSGFLT_ALLOW, nullptr); - pChangeWindowMessageFilterEx(m_hWnd, 0x0049/*WM_COPYGLOBALDATA*/, MSGFLT_ALLOW, nullptr); - } - DragAcceptFiles(m_hWnd, 1); - } - - // init Format combo box - { - hCtrl = GetDlgItem(m_hWnd, ID_cboxFormat); - ComboBox_ResetContent(hCtrl); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"PNG"), 0); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"JPG"), 1); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"BMP"), 2); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"TIF"), 3); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"GIF"), 4); - ComboBox_SelectItem(hCtrl, m_opt_cboxFormat); - } - - // init SendBy combo box - UPLOAD_INFO *pDefault = nullptr; - { - hCtrl = GetDlgItem(m_hWnd, ID_cboxSendBy); - ComboBox_ResetContent(hCtrl); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("")), new UPLOAD_INFO(SS_JUSTSAVE)); - if (m_hContact) { - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("File Transfer")), new UPLOAD_INFO(SS_FILESEND)); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("E-mail")), new UPLOAD_INFO(SS_EMAIL)); - if (g_myGlobals.PluginHTTPExist) { - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"HTTP Server"), new UPLOAD_INFO(SS_HTTPSERVER)); - } - else if (m_opt_cboxSendBy == SS_HTTPSERVER) { - m_opt_cboxSendBy = SS_IMAGESHACK; - } - if (g_myGlobals.PluginFTPExist) { - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("FTP File")), new UPLOAD_INFO(SS_FTPFILE)); - } - else if (m_opt_cboxSendBy == SS_FTPFILE) { - m_opt_cboxSendBy = SS_IMAGESHACK; - } - } - else if (m_opt_cboxSendBy == SS_FILESEND || m_opt_cboxSendBy == SS_EMAIL || m_opt_cboxSendBy == SS_HTTPSERVER || m_opt_cboxSendBy == SS_FTPFILE) { - m_opt_cboxSendBy = SS_IMAGESHACK; - } - if (g_myGlobals.PluginCloudFileExist) { - CallService(MS_CLOUDFILE_ENUMSERVICES, (WPARAM)EnumCloudFileServices, (LPARAM)hCtrl); - } - else if (m_opt_cboxSendBy == SS_CLOUDFILE) { - m_opt_cboxSendBy = SS_IMAGESHACK; - } - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"ImageShack"), new UPLOAD_INFO(SS_IMAGESHACK)); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("Upload Pie (30m)")), new UPLOAD_INFO(SS_UPLOADPIE, (void*)1)); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("Upload Pie (1d)")), new UPLOAD_INFO(SS_UPLOADPIE, (void*)4)); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("Upload Pie (1w)")), new UPLOAD_INFO(SS_UPLOADPIE, (void*)5)); - ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"Imgur"), new UPLOAD_INFO(SS_IMGUR)); - - for (int i = 0; i < ComboBox_GetCount(hCtrl); i++) { - UPLOAD_INFO *p = (UPLOAD_INFO*)ComboBox_GetItemData(hCtrl, i); - if (p && p->sendBy == m_opt_cboxSendBy) { - pDefault = p; - ComboBox_SetCurSel(hCtrl, i); - break; - } - } - } - - // init footer options - CheckDlgButton(m_hWnd, ID_chkOpenAgain, m_opt_chkOpenAgain ? BST_CHECKED : BST_UNCHECKED); - - if (hCtrl = GetDlgItem(m_hWnd, ID_btnExplore)) { - SendDlgItemMessage(m_hWnd, ID_btnExplore, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Open Folder"), MBBF_TCHAR); - HICON hIcon = GetIconBtn(ICO_BTN_FOLDER); - SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - SetWindowText(hCtrl, hIcon ? L"" : L"..."); - } - - if (hCtrl = GetDlgItem(m_hWnd, ID_chkDesc)) { - SendDlgItemMessage(m_hWnd, ID_chkDesc, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Fill description textbox."), MBBF_TCHAR); - HICON hIcon = GetIconBtn(m_opt_btnDesc ? ICO_BTN_DESCON : ICO_BTN_DESC); - SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - SetWindowText(hCtrl, hIcon ? L"" : L"D"); - SendMessage(hCtrl, BM_SETCHECK, m_opt_btnDesc ? BST_CHECKED : BST_UNCHECKED, NULL); - } - - if (hCtrl = GetDlgItem(m_hWnd, ID_chkDeleteAfterSend)) { - SendDlgItemMessage(m_hWnd, ID_chkDeleteAfterSend, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Delete after send"), MBBF_TCHAR); - HICON hIcon = GetIconBtn(m_opt_btnDeleteAfterSend ? ICO_BTN_DELON : ICO_BTN_DEL); - SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - SetWindowText(hCtrl, hIcon ? L"" : L"X"); - SendMessage(hCtrl, BM_SETCHECK, m_opt_btnDeleteAfterSend ? BST_CHECKED : BST_UNCHECKED, NULL); - } - - if (hCtrl = GetDlgItem(m_hWnd, ID_chkEditor)) { - SendDlgItemMessage(m_hWnd, ID_chkEditor, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Open editor before sending"), MBBF_TCHAR); - HICON hIcon = GetIconBtn(m_opt_chkEditor ? ICO_BTN_EDITON : ICO_BTN_EDIT); - SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - SetWindowText(hCtrl, hIcon ? L"" : L"E"); - SendMessage(hCtrl, BM_SETCHECK, m_opt_chkEditor ? BST_CHECKED : BST_UNCHECKED, NULL); - } - - if (hCtrl = GetDlgItem(m_hWnd, ID_btnCapture)) { - SendMessage(hCtrl, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Capture"), MBBF_TCHAR); - HICON hIcon = GetIconBtn(ICO_BTN_OK); - SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - SetWindowText(hCtrl, TranslateT("&Capture")); - SendMessage(hCtrl, BUTTONSETDEFAULT, 1, NULL); - } - cboxSendByChange((pDefault) ? pDefault->param : nullptr); // enable disable controls - - TranslateDialogDefault(m_hWnd); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// WM_COMMAND: - -void TfrmMain::wmCommand(WPARAM wParam, LPARAM lParam) -{ - HICON hIcon; - - int IDControl = LOWORD(wParam); - switch (HIWORD(wParam)) { - case BN_CLICKED: // Button controls - switch (IDControl) { - case IDCANCEL: // ESC pressed - this->Close(); - break; - case ID_chkTimed: - m_opt_chkTimed = (uint8_t)Button_GetCheck((HWND)lParam); - TfrmMain::chkTimedClick(); - break; - case ID_chkIndirectCapture: - m_opt_chkIndirectCapture = (uint8_t)Button_GetCheck((HWND)lParam); - break; - case ID_chkClientArea: - m_opt_chkClientArea = (uint8_t)Button_GetCheck((HWND)lParam); - if (m_hTargetWindow) - edtSizeUpdate(m_hTargetWindow, m_opt_chkClientArea, GetParent((HWND)lParam), ID_edtSize); - break; - case ID_imgTarget: - if (m_opt_tabCapture != 0) break; - m_hLastWin = nullptr; - SetTimer(m_hWnd, ID_imgTarget, BUTTON_POLLDELAY, nullptr); - break; - case ID_btnExplore: - TfrmMain::btnExploreClick(); - break; - case ID_chkDesc: - m_opt_btnDesc = !m_opt_btnDesc; - hIcon = GetIconBtn(m_opt_btnDesc ? ICO_BTN_DESCON : ICO_BTN_DESC); - SendMessage((HWND)lParam, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - break; - case ID_chkDeleteAfterSend: - m_opt_btnDeleteAfterSend = !m_opt_btnDeleteAfterSend; - hIcon = GetIconBtn(m_opt_btnDeleteAfterSend ? ICO_BTN_DELON : ICO_BTN_DEL); - SendMessage((HWND)lParam, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - if (m_cSend) m_cSend->m_bDeleteAfterSend = m_opt_btnDeleteAfterSend; - break; - case ID_chkEditor: - m_opt_chkEditor = !m_opt_chkEditor; - hIcon = GetIconBtn(m_opt_chkEditor ? ICO_BTN_EDITON : ICO_BTN_EDIT); - SendMessage((HWND)lParam, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - break; - case ID_chkOpenAgain: - m_opt_chkOpenAgain = Button_GetCheck((HWND)lParam); - break; - case ID_btnCapture: - TfrmMain::btnCaptureClick(); - break; - } - break; - - case CBN_SELCHANGE: // ComboBox controls - switch (IDControl) { // lParam = Handle to the control - case ID_cboxFormat: // not finish - m_opt_cboxFormat = (uint8_t)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); - break; - case ID_cboxSendBy: - { - UPLOAD_INFO *upload = (UPLOAD_INFO*)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); - m_opt_cboxSendBy = upload->sendBy; - cboxSendByChange(upload->param); - } - break; - - case ID_edtCaption: // cboxDesktopChange - m_opt_cboxDesktop = (uint8_t)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); - m_hTargetWindow = nullptr; - if (m_opt_cboxDesktop > 0) { - edtSizeUpdate(m_Monitors[m_opt_cboxDesktop - 1].rcMonitor, GetParent((HWND)lParam), ID_edtSize); - } - else { - edtSizeUpdate(m_VirtualScreen, GetParent((HWND)lParam), ID_edtSize); - } - break; - } - break; - - case EN_CHANGE: // Edit controls - switch (IDControl) { // lParam = Handle to the control - case ID_edtQuality: - m_opt_edtQuality = (uint8_t)GetDlgItemInt(m_hWnd, ID_edtQuality, nullptr, FALSE); - break; - case ID_edtTimed: - m_opt_edtTimed = (uint8_t)GetDlgItemInt(m_hWnd, ID_edtTimed, nullptr, FALSE); - break; - } - break; - } -} - -// WM_CLOSE: -void TfrmMain::wmClose(WPARAM, LPARAM) -{ - HWND hCtrl = GetDlgItem(m_hWnd, ID_cboxSendBy); - size_t count = ComboBox_GetCount(hCtrl); - for (size_t i = 0; i < count; i++) { - UPLOAD_INFO *ui = (UPLOAD_INFO*)ComboBox_GetItemData(hCtrl, i); - delete ui; - } - DestroyWindow(m_hWnd); - return; -} - -// WM_TIMER: -const int g_iTargetBorder = 7; -void TfrmMain::SetTargetWindow(HWND hwnd) -{ - if (!hwnd) { - POINT point; GetCursorPos(&point); - hwnd = WindowFromPoint(point); - for (HWND hTMP; (hTMP = GetParent(hwnd)); hwnd = hTMP) - ; - } - m_hTargetWindow = hwnd; - int len = GetWindowTextLength(m_hTargetWindow) + 1; - wchar_t *lpTitle; - if (len > 1) { - lpTitle = (wchar_t*)mir_alloc(len*sizeof(wchar_t)); - GetWindowText(m_hTargetWindow, lpTitle, len); - } - else { // no WindowText present, use WindowClass - lpTitle = (wchar_t*)mir_alloc(64 * sizeof(wchar_t)); - RealGetWindowClass(m_hTargetWindow, lpTitle, 64); - } - SetDlgItemText(m_hwndTabPage, ID_edtCaption, lpTitle); - mir_free(lpTitle); - edtSizeUpdate(m_hTargetWindow, m_opt_chkClientArea, m_hwndTabPage, ID_edtSize); -} - -void TfrmMain::wmTimer(WPARAM wParam, LPARAM) -{ - if (wParam == ID_imgTarget) { // Timer for Target selector - static int primarymouse; - if (!m_hTargetHighlighter) { - primarymouse = GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON; - m_hTargetHighlighter = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, (wchar_t*)g_clsTargetHighlighter, nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, g_plugin.getInst(), nullptr); - if (!m_hTargetHighlighter) return; - SetLayeredWindowAttributes(m_hTargetHighlighter, 0, 123, LWA_ALPHA); - SetSystemCursor(CopyCursor(GetIcon(ICO_TARGET)), OCR_IBEAM); // text cursor - SetSystemCursor(CopyCursor(GetIcon(ICO_TARGET)), OCR_NORMAL); - SetActiveWindow(m_hTargetHighlighter); // activate highlighter to fix focus problems with UAC (unelevated GetAsyncKeyState() fails if an elevated app got focus) - Hide(); - } - if (!(GetAsyncKeyState(primarymouse) & 0x8000)) { - KillTimer(m_hWnd, ID_imgTarget); - SystemParametersInfo(SPI_SETCURSORS, 0, nullptr, 0); - DestroyWindow(m_hTargetHighlighter), m_hTargetHighlighter = nullptr; - SetTargetWindow(m_hLastWin); - Show(); - return; - } - POINT point; GetCursorPos(&point); - HWND hwnd = WindowFromPoint(point); - if (!((GetAsyncKeyState(VK_SHIFT) | GetAsyncKeyState(VK_MENU)) & 0x8000)) - for (HWND hTMP; (hTMP = GetAncestor(hwnd, GA_PARENT)) && IsChild(hTMP, hwnd); hwnd = hTMP); - else { - ScreenToClient(hwnd, &point); - HWND hTMP; if ((hTMP = RealChildWindowFromPoint(hwnd, point))) - hwnd = hTMP; - } - if (hwnd != m_hLastWin) { - m_hLastWin = hwnd; - RECT rect; - if (m_opt_chkClientArea) { - GetClientRect(hwnd, &rect); - ClientToScreen(hwnd, (POINT*)&rect); - rect.right = rect.left + rect.right; - rect.bottom = rect.top + rect.bottom; - } - else - GetWindowRect(hwnd, &rect); - int width = rect.right - rect.left; - int height = rect.bottom - rect.top; - if (g_iTargetBorder) { - SetWindowPos(m_hTargetHighlighter, nullptr, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE); - if (width > g_iTargetBorder * 2 && height > g_iTargetBorder * 2) { - HRGN hRegnNew = CreateRectRgn(0, 0, width, height); - HRGN hRgnHole = CreateRectRgn(g_iTargetBorder, g_iTargetBorder, width - g_iTargetBorder, height - g_iTargetBorder); - CombineRgn(hRegnNew, hRegnNew, hRgnHole, RGN_XOR); - DeleteObject(hRgnHole); - SetWindowRgn(m_hTargetHighlighter, hRegnNew, FALSE); // cleans up hRegnNew - } - else SetWindowRgn(m_hTargetHighlighter, nullptr, FALSE); - } - SetWindowPos(m_hTargetHighlighter, HWND_TOPMOST, rect.left, rect.top, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE); - } - return; - } - if (wParam == ID_chkTimed) { // Timer for Screenshot -#ifdef _DEBUG - OutputDebugStringA("SS Bitmap Timer Start\r\n"); -#endif - if (!m_bCapture) { // only start once - if (m_Screenshot) { - FreeImage_Unload(m_Screenshot); - m_Screenshot = nullptr; - } - m_bCapture = true; - switch (m_opt_tabCapture) { - case 0: - m_Screenshot = CaptureWindow(m_hTargetWindow, m_opt_chkClientArea, m_opt_chkIndirectCapture); - break; - case 1: - m_Screenshot = CaptureMonitor((m_opt_cboxDesktop > 0) ? m_Monitors[m_opt_cboxDesktop - 1].szDevice : nullptr); - break; - case 2: // edge case, existing local file - break; -#ifdef _DEBUG - default: - OutputDebugStringA("SS Bitmap Timer Stop (no tabCapture)\r\n"); -#endif - } - m_bCapture = false; - if (m_Screenshot || m_opt_tabCapture == 2) { // @note : test without "if" - KillTimer(m_hWnd, ID_chkTimed); -#ifdef _DEBUG - OutputDebugStringA("SS Bitmap Timer Stop (CaptureDone)\r\n"); -#endif - SendMessage(m_hWnd, UM_EVENT, 0, (LPARAM)EVT_CaptureDone); - } - } - } -} - -// WM_NOTIFY: -void TfrmMain::wmNotify(WPARAM, LPARAM lParam) -{ - switch (((LPNMHDR)lParam)->idFrom) { - case IDC_CAPTURETAB: - // HWND hwndFrom; = member is handle to the tab control - // UINT_PTR idFrom; = member is the child window identifier of the tab control. - // UINT code; = member is TCN_SELCHANGE - switch (((LPNMHDR)lParam)->code) { - case TCN_SELCHANGING: - if (m_hwndTabPage) { - ShowWindow(m_hwndTabPage, SW_HIDE); - m_hwndTabPage = nullptr; - } - break; - - case TCN_SELCHANGE: - { - TAB_INFO itab = { TCIF_PARAM }; - m_opt_tabCapture = TabCtrl_GetCurSel(m_hwndTab); - TabCtrl_GetItem(m_hwndTab, m_opt_tabCapture, &itab); - m_hwndTabPage = itab.hwndTabPage; - } - ShowWindow(m_hwndTabPage, SW_SHOW); - break; - } - break; - } -} - -// UM_EVENT: -void TfrmMain::UMevent(WPARAM, LPARAM lParam) -{ - // HWND hWnd = (HWND)wParam; - switch (lParam) { - case EVT_CaptureDone: - if (!m_Screenshot && m_opt_tabCapture != 2) { - wchar_t *err = TranslateT("Couldn't take a screenshot"); - MessageBox(nullptr, err, ERROR_TITLE, MB_OK | MB_ICONWARNING); - Show(); - return; - } - FormClose(); - break; - - case EVT_SendFileDone: - break; - - case EVT_CheckOpenAgain: - if (m_opt_chkOpenAgain) { - if (m_Screenshot) { - FreeImage_Unload(m_Screenshot); - m_Screenshot = nullptr; - } - Show(); - } - else {// Saving Options and close - SaveOptions(); - Close(); - } - break; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Standard konstruktor/destruktor - -TfrmMain::TfrmMain() -{ - /* m_opt_XXX */ - m_bOnExitSave = TRUE; - - m_hWnd = nullptr; - m_hContact = NULL; - m_hTargetWindow = m_hLastWin = nullptr; - m_hTargetHighlighter = nullptr; - m_FDestFolder = m_pszFile = nullptr; - m_Screenshot = nullptr; - /* m_AlphaColor */ - m_cSend = nullptr; - - m_Monitors = nullptr; - m_MonitorCount = MonitorInfoEnum(m_Monitors, m_VirtualScreen); - /* m_opt_XXX */ LoadOptions(); - m_bCapture = false; - /* m_hwndTab,m_hwndTabPage */ - m_himlTab = nullptr; -} - -TfrmMain::~TfrmMain() -{ - _HandleMapping.erase(m_hWnd); - mir_free(m_pszFile); - mir_free(m_FDestFolder); - mir_free(m_Monitors); - if (m_Screenshot) FreeImage_Unload(m_Screenshot); - if (m_cSend) delete m_cSend; - if (m_hTargetHighlighter) { - DestroyWindow(m_hTargetHighlighter), m_hTargetHighlighter = nullptr; - SystemParametersInfo(SPI_SETCURSORS, 0, nullptr, 0); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Load / Saving options from miranda's database - -void TfrmMain::LoadOptions(void) -{ - uint32_t rgb = g_plugin.getDword("AlphaColor", 16777215); - m_AlphaColor.rgbRed = GetRValue(rgb); - m_AlphaColor.rgbGreen = GetGValue(rgb); - m_AlphaColor.rgbBlue = GetBValue(rgb); - m_AlphaColor.rgbReserved = 0; - - m_opt_edtQuality = g_plugin.getByte("JpegQuality", 75); - - m_opt_tabCapture = g_plugin.getByte("Capture", 0); - m_opt_chkIndirectCapture = g_plugin.getByte("IndirectCapture", 0); - m_opt_chkClientArea = g_plugin.getByte("ClientArea", 0); - m_opt_cboxDesktop = g_plugin.getByte("Desktop", 0); - - m_opt_chkTimed = g_plugin.getByte("TimedCap", 0); - m_opt_edtTimed = g_plugin.getByte("CapTime", 3); - m_opt_cboxFormat = g_plugin.getByte("OutputFormat", 0); - m_opt_cboxSendBy = g_plugin.getByte("SendBy", 0); - - m_opt_btnDesc = g_plugin.getByte("AutoDescription", 1); - m_opt_btnDeleteAfterSend = g_plugin.getByte("DelAfterSend", 1) != 0; - m_opt_chkEditor = g_plugin.getByte("Preview", 0); - m_opt_chkOpenAgain = g_plugin.getByte("OpenAgain", 0); -} - -void TfrmMain::SaveOptions(void) -{ - if (m_bOnExitSave) { - g_plugin.setDword("AlphaColor", - (uint32_t)RGB(m_AlphaColor.rgbRed, m_AlphaColor.rgbGreen, m_AlphaColor.rgbBlue)); - - g_plugin.setByte("JpegQuality", m_opt_edtQuality); - - g_plugin.setByte("Capture", m_opt_tabCapture); - g_plugin.setByte("IndirectCapture", m_opt_chkIndirectCapture); - g_plugin.setByte("ClientArea", m_opt_chkClientArea); - g_plugin.setByte("Desktop", m_opt_cboxDesktop); - - g_plugin.setByte("TimedCap", m_opt_chkTimed); - g_plugin.setByte("CapTime", m_opt_edtTimed); - g_plugin.setByte("OutputFormat", m_opt_cboxFormat); - g_plugin.setByte("SendBy", m_opt_cboxSendBy); - - g_plugin.setByte("AutoDescription", m_opt_btnDesc); - g_plugin.setByte("DelAfterSend", m_opt_btnDeleteAfterSend); - g_plugin.setByte("Preview", m_opt_chkEditor); - g_plugin.setByte("OpenAgain", m_opt_chkOpenAgain); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void TfrmMain::Init(wchar_t *DestFolder, MCONTACT Contact) -{ - m_FDestFolder = mir_wstrdup(DestFolder); - m_hContact = Contact; - - // create window - m_hWnd = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMainForm), nullptr, DlgTfrmMain, (LPARAM)this); - - // register object - _HandleMapping.insert(CHandleMapping::value_type(m_hWnd, this)); - - // check Contact - if (m_cSend) - m_cSend->SetContact(Contact); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void TfrmMain::btnCaptureClick() -{ - if (m_opt_tabCapture == 1) m_hTargetWindow = GetDesktopWindow(); - else if (m_opt_tabCapture == 2) { - wchar_t filename[MAX_PATH]; - GetDlgItemText(m_hwndTabPage, ID_edtSize, filename, _countof(filename)); - FILE *fp = _wfopen(filename, L"rb"); - if (!fp) { - wchar_t *err = TranslateT("Select a file"); - MessageBox(m_hWnd, err, ERROR_TITLE, MB_OK | MB_ICONWARNING); - return; - } - fclose(fp); - mir_free(m_pszFile); m_pszFile = mir_wstrdup(filename); - } - else if (!m_hTargetWindow) { - wchar_t *err = TranslateT("Select a target window."); - MessageBox(m_hWnd, err, ERROR_TITLE, MB_OK | MB_ICONWARNING); - return; - } - TfrmMain::Hide(); - - if (m_opt_chkTimed) { - SetTimer(m_hWnd, ID_chkTimed, m_opt_edtTimed ? m_opt_edtTimed * 1000 : 500, nullptr); // calls EVT_CaptureDone - return; - } - if (m_opt_tabCapture == 1) { // desktop needs always time to update from TfrmMain::Hide() - SetTimer(m_hWnd, ID_chkTimed, 500, nullptr); // calls EVT_CaptureDone - return; - } - if (m_opt_tabCapture != 2) { - m_Screenshot = CaptureWindow(m_hTargetWindow, m_opt_chkClientArea, m_opt_chkIndirectCapture); - } - SendMessage(m_hWnd, UM_EVENT, 0, (LPARAM)EVT_CaptureDone); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void TfrmMain::chkTimedClick() -{ - Button_Enable(GetDlgItem(m_hWnd, ID_edtTimedLabel), (BOOL)m_opt_chkTimed); - Button_Enable(GetDlgItem(m_hWnd, ID_edtTimed), (BOOL)m_opt_chkTimed); - Button_Enable(GetDlgItem(m_hWnd, ID_upTimed), (BOOL)m_opt_chkTimed); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void TfrmMain::cboxSendByChange(void *param) -{ - BOOL bState; - HICON hIcon; - uint8_t itemFlag = SS_DLG_DESCRIPTION; - if (m_cSend) - delete m_cSend; - switch (m_opt_cboxSendBy) { - case SS_FILESEND: // "File Transfer" - m_cSend = new CSendFile(m_hWnd, m_hContact, true); - break; - case SS_EMAIL: // "E-mail" - m_cSend = new CSendEmail(m_hWnd, m_hContact, true); - break; - case SS_HTTPSERVER: // "HTTP Server" - m_cSend = new CSendHTTPServer(m_hWnd, m_hContact, true); - break; - case SS_FTPFILE: // "FTP File" - m_cSend = new CSendFTPFile(m_hWnd, m_hContact, true); - break; - case SS_CLOUDFILE: // "CloudFile" - m_cSend = new CSendCloudFile(m_hWnd, m_hContact, false, (char*)param); - break; - case SS_IMAGESHACK: // "ImageShack" - m_cSend = new CSendHost_ImageShack(m_hWnd, m_hContact, true); - break; - case SS_UPLOADPIE: // "Upload Pie" - m_cSend = new CSendHost_UploadPie(m_hWnd, m_hContact, true, (INT_PTR)param); - break; - case SS_IMGUR: - m_cSend = new CSendHost_Imgur(m_hWnd, m_hContact, true); - break; - default: - m_cSend = nullptr; - break; - } - if (m_cSend) { - itemFlag = m_cSend->GetEnableItem(); - m_cSend->m_bDeleteAfterSend = m_opt_btnDeleteAfterSend; - } - bState = (itemFlag & SS_DLG_DELETEAFTERSSEND); - hIcon = GetIconBtn(m_opt_btnDeleteAfterSend ? ICO_BTN_DELON : ICO_BTN_DEL); - SendDlgItemMessage(m_hWnd, ID_chkDeleteAfterSend, BM_SETIMAGE, IMAGE_ICON, (LPARAM)(bState ? hIcon : nullptr)); - Button_Enable(GetDlgItem(m_hWnd, ID_chkDeleteAfterSend), bState); - - bState = (itemFlag & SS_DLG_DESCRIPTION); - hIcon = GetIconBtn(m_opt_btnDesc ? ICO_BTN_DESCON : ICO_BTN_DESC); - SendDlgItemMessage(m_hWnd, ID_chkDesc, BM_SETIMAGE, IMAGE_ICON, (LPARAM)(bState ? hIcon : nullptr)); - Button_Enable(GetDlgItem(m_hWnd, ID_chkDesc), bState); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void TfrmMain::btnExploreClick() -{ - if (m_FDestFolder) - ShellExecute(nullptr, L"explore", m_FDestFolder, nullptr, nullptr, SW_SHOW); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void TfrmMain::edtSizeUpdate(HWND hWnd, BOOL ClientArea, HWND hTarget, UINT Ctrl) -{ - // get window dimensions - RECT rect = { 0 }; - RECT cliRect = { 0 }; - wchar_t B[33], H[16]; - GetWindowRect(hWnd, &rect); - if (ClientArea) { - POINT pt = { 0 }; - GetClientRect(hWnd, &cliRect); - pt.x = cliRect.left; - pt.y = cliRect.top; - ClientToScreen(hWnd, &pt); - pt.x = pt.x - rect.left; // offset x for client area - pt.y = pt.y - rect.top; // offset y for client area - rect = cliRect; - } - - _itow(rect.right - rect.left, B, 10); - _itow(rect.bottom - rect.top, H, 10); - mir_wstrncat(B, L"x", _countof(B) - mir_wstrlen(B)); - mir_wstrncat(B, H, _countof(B) - mir_wstrlen(B)); - SetDlgItemText(hTarget, Ctrl, B); -} - -void TfrmMain::edtSizeUpdate(RECT rect, HWND hTarget, UINT Ctrl) -{ - wchar_t B[33], H[16]; - _itow(ABS(rect.right - rect.left), B, 10); - _itow(ABS(rect.bottom - rect.top), H, 10); - mir_wstrncat(B, L"x", _countof(B) - mir_wstrlen(B)); - mir_wstrncat(B, H, _countof(B) - mir_wstrlen(B)); - SetDlgItemText(hTarget, Ctrl, B); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -INT_PTR TfrmMain::SaveScreenshot(FIBITMAP *dib) -{ - if (!dib) - return 1; - - // generate file name - unsigned FileNumber = g_plugin.getDword("FileNumber", 0) + 1; - if (FileNumber > 99999) - FileNumber = 1; - - CMStringW wszFileName(m_FDestFolder); - if (wszFileName.Right(1) != L"\\") - wszFileName.Append(L"\\"); - wszFileName.AppendFormat(L"shot%.5u", FileNumber); - - // generate a description according to the screenshot - wchar_t winText[1024]; - GetDlgItemText(m_hwndTabPage, ID_edtCaption, winText, _countof(winText)); - - CMStringW wszFileDesc; - if (m_opt_tabCapture) - wszFileDesc.Format(TranslateT("Screenshot of \"%s\""), winText); - else { - if (m_opt_chkClientArea) - wszFileDesc.Format(TranslateT("Screenshot for client area of \"%s\" window"), winText); - else - wszFileDesc.Format(TranslateT("Screenshot of \"%s\" window"), winText); - } - - // convert to 32Bits (make sure it is 32bit) - FIBITMAP *dib_new = FreeImage_ConvertTo32Bits(dib); - FreeImage_SetTransparent(dib_new, TRUE); - - BOOL ret = FALSE; - HWND hwndCombo = GetDlgItem(m_hWnd, ID_cboxFormat); - switch (ComboBox_GetItemData(hwndCombo, ComboBox_GetCurSel(hwndCombo))) { - case 0: // PNG - wszFileName.Append(L".png"); - ret = FreeImage_SaveU(FIF_PNG, dib_new, wszFileName, 0); - break; - - case 1: // JPG - wszFileName.Append(L".jpg"); - { - FIBITMAP *dib32 = FreeImage_Composite(dib_new, FALSE, &m_AlphaColor, nullptr); - FIBITMAP *dib24 = FreeImage_ConvertTo24Bits(dib32); - FreeImage_Unload(dib32); - ret = FreeImage_SaveU(FIF_JPEG, dib24, wszFileName, 0); - FreeImage_Unload(dib24); - } - break; - - case 2: // BMP - wszFileName.Append(L".bmp"); - { - FIBITMAP *dib32 = FreeImage_Composite(dib_new, FALSE, &m_AlphaColor, nullptr); - FIBITMAP *dib24 = FreeImage_ConvertTo24Bits(dib32); - FreeImage_Unload(dib32); - ret = FreeImage_SaveU(FIF_BMP, dib24, wszFileName, 0); - FreeImage_Unload(dib24); - } - break; - - case 3: // TIFF (miranda freeimage interface do not support save tiff, we udse GDI+) - wszFileName.Append(L".tif"); - { - FIBITMAP *dib32 = FreeImage_Composite(dib_new, FALSE, &m_AlphaColor, nullptr); - FIBITMAP *dib24 = FreeImage_ConvertTo24Bits(dib32); - FreeImage_Unload(dib32); - - HBITMAP hBmp = FreeImage_CreateHBITMAPFromDIB(dib24); - FreeImage_Unload(dib24); - SaveTIF(hBmp, wszFileName); - DeleteObject(hBmp); - } - ret = TRUE; - break; - - case 4: // GIF - wszFileName.Append(L".gif"); - { - HBITMAP hBmp = FreeImage_CreateHBITMAPFromDIB(dib_new); - SaveGIF(hBmp, wszFileName); - DeleteObject(hBmp); - } - ret = TRUE; - break; - } - - FreeImage_Unload(dib_new); - - if (!ret) - return 1; - - g_plugin.setDword("FileNumber", FileNumber); - replaceStrW(m_pszFile, wszFileName); - - if (!IsWindowEnabled(GetDlgItem(m_hWnd, ID_chkDesc)) || !m_opt_btnDesc) - wszFileDesc.Empty(); - - if (m_cSend) { - m_cSend->SetFile(m_pszFile); - m_cSend->SetDescription(wszFileDesc); - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void TfrmMain::FormClose() -{ - bool bCanDelete = m_opt_btnDeleteAfterSend; - if (m_opt_tabCapture == 2) { // existing file - wchar_t description[1024]; - GetDlgItemText(m_hwndTabPage, ID_edtCaption, description, _countof(description)); - if (!IsWindowEnabled(GetDlgItem(m_hWnd, ID_chkDesc)) || !m_opt_btnDesc) - *description = '\0'; - if (m_cSend) { - m_cSend->m_bDeleteAfterSend = false; // well... guess it's better to not delete existing files for now... - m_cSend->SetFile(m_pszFile); - m_cSend->SetDescription(description); - } - bCanDelete = false; - } - else if (SaveScreenshot(m_Screenshot)) { // Saving the screenshot - Show(); // Error from SaveScreenshot - return; - } - - bool send = true; - if (m_opt_chkEditor) { - SHELLEXECUTEINFO shex = { sizeof(SHELLEXECUTEINFO) }; - shex.fMask = SEE_MASK_NOCLOSEPROCESS; - shex.lpVerb = L"edit"; - shex.lpFile = m_pszFile; - shex.nShow = SW_SHOWNORMAL; - ShellExecuteEx(&shex); - if (shex.hProcess) { - uint32_t res; - MSG msg; - do { - // wait for editor exit or messages/input - res = MsgWaitForMultipleObjects(1, &shex.hProcess, 0, INFINITE, QS_ALLINPUT); - while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { - if (msg.message == WM_QUIT) { - res = WAIT_OBJECT_0; - PostMessage(nullptr, WM_QUIT, 0, 0); // forward for outer message loops - break; - } - - // process dialog messages (of unknown dialogs) - HWND hwndDlgModeless = GetActiveWindow(); - if (hwndDlgModeless != nullptr && IsDialogMessage(hwndDlgModeless, &msg)) /* Wine fix. */ - continue; - - // process messages - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } while (res == WAIT_OBJECT_0 + 1); - CloseHandle(shex.hProcess); - } - if (MessageBox(m_hWnd, TranslateT("Send screenshot?"), L"SendSS", MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL) != IDYES) - send = false; - } - - if (send && m_cSend && m_pszFile) { - if (!m_cSend->Send()) // not sent now, class deletes itself later - m_cSend = nullptr; - cboxSendByChange(nullptr); - } - else if (!send && bCanDelete) - DeleteFile(m_pszFile); - - SendMessage(m_hWnd, UM_EVENT, 0, (LPARAM)EVT_CheckOpenAgain); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +#include + +void TfrmMain::Unload() +{ + std::list lst; + for (auto &it : _HandleMapping) + lst.push_back(it.second); // we can't delete inside loop.. not MT compatible + + while (!lst.empty()) { + DestroyWindow(lst.front()->m_hWnd); // deletes class + lst.pop_front(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR CALLBACK TfrmMain::DlgProc_CaptureTabPage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + // main message handling is done inside TfrmMain::DlgTfrmMain + switch (uMsg) { + case WM_INITDIALOG: + switch (lParam) { + case IDD_UMain_CaptureWindow: + Static_SetIcon(GetDlgItem(hDlg, ID_imgTarget), GetIcon(ICO_TARGET)); + SetDlgItemText(hDlg, ID_edtCaption, TranslateT("Drag&Drop the target on the desired window.")); + break; + case IDD_UMain_CaptureDesktop: + Static_SetIcon(GetDlgItem(hDlg, ID_imgTarget), GetIcon(ICO_MONITOR)); + break; + case IDD_UMain_CaptureFile: + Static_SetIcon(GetDlgItem(hDlg, ID_imgTarget), GetIcon(ICO_MAIN)); + break; + } + SetFocus(GetDlgItem(hDlg, ID_imgTarget)); + return FALSE; + + case WM_CTLCOLORDLG: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); + return (INT_PTR)GetStockObject(WHITE_BRUSH); + + case WM_COMMAND: + if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == ID_btnExplore) { // local file tab + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + wchar_t filename[MAX_PATH]; + GetDlgItemText(hDlg, ID_edtSize, filename, _countof(filename)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hDlg; + ofn.lpstrFilter = L"Images\0*.png;*.jpg;*.jpeg;*.bmp;*.gif;*.tif;*.tiff\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_READONLY; + if (GetOpenFileName(&ofn)) { + SetDlgItemText(hDlg, ID_edtSize, filename); + } + break; + } + SendMessage(GetParent(hDlg), uMsg, wParam, lParam); + break; + case WM_NOTIFY: + SendMessage(GetParent(hDlg), uMsg, wParam, lParam); + break; + case WM_DESTROY: + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +TfrmMain::CHandleMapping TfrmMain::_HandleMapping; + +INT_PTR CALLBACK TfrmMain::DlgTfrmMain(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_CTLCOLOREDIT || msg == WM_CTLCOLORSTATIC) { + switch (GetWindowLongPtr((HWND)lParam, GWL_ID)) { + case IDC_HEADERBAR: + SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); + break; + default: + return 0; + } + SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); + return (INT_PTR)GetStockObject(WHITE_BRUSH); + } + + CHandleMapping::iterator wnd; + if (msg == WM_INITDIALOG) { + wnd = _HandleMapping.insert(CHandleMapping::value_type(hWnd, reinterpret_cast(lParam))).first; + wnd->second->m_hWnd = hWnd; + wnd->second->wmInitdialog(wParam, lParam); + return 0; + } + wnd = _HandleMapping.find(hWnd); + if (wnd == _HandleMapping.end()) + return 0; + + switch (msg) { + case WM_DROPFILES: + // Drag&Drop of local files + { + wchar_t filename[MAX_PATH]; + if (!DragQueryFile((HDROP)wParam, 0, filename, MAX_PATH)) + *filename = '\0'; + DragFinish((HDROP)wParam); + if (wnd->second->m_hwndTabPage) + ShowWindow(wnd->second->m_hwndTabPage, SW_HIDE); + + wnd->second->m_opt_tabCapture = 2; // activate file tab + TabCtrl_SetCurSel(wnd->second->m_hwndTab, wnd->second->m_opt_tabCapture); + + TAB_INFO itab = { TCIF_PARAM }; + TabCtrl_GetItem(wnd->second->m_hwndTab, wnd->second->m_opt_tabCapture, &itab); + wnd->second->m_hwndTabPage = itab.hwndTabPage; + + ShowWindow(wnd->second->m_hwndTabPage, SW_SHOW); + SetDlgItemText(wnd->second->m_hwndTabPage, ID_edtSize, filename); + } + break; + case WM_COMMAND: + wnd->second->wmCommand(wParam, lParam); + break; + case WM_CLOSE: + wnd->second->wmClose(wParam, lParam); + break; + case WM_DESTROY: + delete wnd->second; + break; + case WM_NOTIFY: + wnd->second->wmNotify(wParam, lParam); + break; + case WM_TIMER: + wnd->second->wmTimer(wParam, lParam); + break; + case UM_EVENT: + wnd->second->UMevent(wParam, lParam); + break; + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// WM_INITDIALOG: + +int EnumCloudFileServices(const CFSERVICEINFO *serviceInfo, void *param) +{ + HWND hCtrl = (HWND)param; + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, serviceInfo->userName), new UPLOAD_INFO(SS_CLOUDFILE, (void*)serviceInfo->accountName)); + return 0; +} + +void TfrmMain::wmInitdialog(WPARAM, LPARAM) +{ + HWND hCtrl; + // Taskbar and Window icon + Window_SetIcon_IcoLib(m_hWnd, GetIconHandle(ICO_MAIN)); + + wchar_t *pt = mir_wstrdup(Clist_GetContactDisplayName(m_hContact)); + if (pt && (m_hContact != 0)) { + CMStringW string; + string.AppendFormat(TranslateT("Send screenshot to %s"), pt); + SetWindowText(m_hWnd, string); + } + mir_free(pt); + + // Headerbar + SendDlgItemMessage(m_hWnd, IDC_HEADERBAR, WM_SETICON, ICON_BIG, (LPARAM)GetIcon(ICO_MAIN)); + + // Timed controls + CheckDlgButton(m_hWnd, ID_chkTimed, m_opt_chkTimed ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(m_hWnd, ID_edtTimed, (UINT)m_opt_edtTimed, FALSE); + SendDlgItemMessage(m_hWnd, ID_upTimed, UDM_SETRANGE, 0, (LPARAM)MAKELONG(250, 1)); + chkTimedClick(); // enable disable Timed controls + + // create Image list for tab control + if (!m_himlTab) { + m_himlTab = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 1); + ImageList_AddIcon(m_himlTab, GetIcon(ICO_TARGET)); + ImageList_AddIcon(m_himlTab, GetIcon(ICO_MONITOR)); + ImageList_AddIcon(m_himlTab, GetIconBtn(ICO_BTN_FOLDER)); + } + + // create the tab control. + { + m_hwndTab = GetDlgItem(m_hWnd, IDC_CAPTURETAB); + TabCtrl_SetImageList(m_hwndTab, m_himlTab); + TabCtrl_SetItemExtra(m_hwndTab, sizeof(TAB_INFO) - sizeof(TCITEMHEADER)); + RECT rcTab; + TAB_INFO itab; + itab.hwndMain = m_hWnd; + itab.hwndTab = m_hwndTab; + itab.tcih.mask = TCIF_PARAM | TCIF_TEXT | TCIF_IMAGE; + + // Add a tab for each of the three child dialog boxes. + itab.tcih.pszText = TranslateT("Window"); + itab.tcih.iImage = 0; + itab.hwndTabPage = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMain_CaptureWindow), m_hWnd, DlgProc_CaptureTabPage, IDD_UMain_CaptureWindow); + TabCtrl_InsertItem(m_hwndTab, 0, &itab); + + // get tab boundaries (required after 1st tab) + GetClientRect(m_hwndTab, &rcTab); + MapWindowPoints(m_hwndTab, m_hWnd, (POINT*)&rcTab, 2); + TabCtrl_AdjustRect(m_hwndTab, 0, &rcTab); + rcTab.bottom -= rcTab.top; rcTab.right -= rcTab.left; + + SetWindowPos(itab.hwndTabPage, HWND_TOP, rcTab.left, rcTab.top, rcTab.right, rcTab.bottom, 0); + CheckDlgButton(itab.hwndTabPage, ID_chkIndirectCapture, m_opt_chkIndirectCapture ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(itab.hwndTabPage, ID_chkClientArea, m_opt_chkClientArea ? BST_CHECKED : BST_UNCHECKED); + + itab.tcih.pszText = TranslateT("Desktop"); + itab.tcih.iImage = 1; + itab.hwndTabPage = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMain_CaptureDesktop), m_hWnd, DlgProc_CaptureTabPage, IDD_UMain_CaptureDesktop); + TabCtrl_InsertItem(m_hwndTab, 1, &itab); + SetWindowPos(itab.hwndTabPage, HWND_TOP, rcTab.left, rcTab.top, rcTab.right, rcTab.bottom, 0); + + hCtrl = GetDlgItem(itab.hwndTabPage, ID_edtCaption); + ComboBox_ResetContent(hCtrl); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("")), 0); + ComboBox_SetCurSel(hCtrl, 0); + if (m_MonitorCount > 1) { + wchar_t tszTemp[120]; + for (size_t mon = 0; mon < m_MonitorCount; ++mon) { // @todo : fix format for non MSVC compilers + mir_snwprintf(tszTemp, L"%Iu. %s%s", + mon + 1, TranslateT("Monitor"), + (m_Monitors[mon].dwFlags & MONITORINFOF_PRIMARY) ? TranslateT(" (primary)") : L"" + ); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, tszTemp), mon + 1); + } + ComboBox_SelectItem(hCtrl, m_opt_cboxDesktop); + } + PostMessage(m_hWnd, WM_COMMAND, MAKEWPARAM(ID_edtCaption, CBN_SELCHANGE), (LPARAM)hCtrl); + + itab.tcih.pszText = TranslateT("File"); + itab.tcih.iImage = 2; + itab.hwndTabPage = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMain_CaptureFile), m_hWnd, DlgProc_CaptureTabPage, IDD_UMain_CaptureFile); + TabCtrl_InsertItem(m_hwndTab, 2, &itab); + SetWindowPos(itab.hwndTabPage, HWND_TOP, rcTab.left, rcTab.top, rcTab.right, rcTab.bottom, 0); + + // select tab and set m_hwndTabPage + TabCtrl_SetCurSel(m_hwndTab, m_opt_tabCapture); + itab.tcih.mask = TCIF_PARAM; + TabCtrl_GetItem(m_hwndTab, m_opt_tabCapture, &itab); + m_hwndTabPage = itab.hwndTabPage; + ShowWindow(m_hwndTabPage, SW_SHOW); + + // enable Drag&Drop for local file pane + typedef BOOL(WINAPI *ChangeWindowMessageFilterEx_t)(HWND hwnd, UINT message, uint32_t action, PCHANGEFILTERSTRUCT pChangeFilterStruct); + ChangeWindowMessageFilterEx_t pChangeWindowMessageFilterEx; + pChangeWindowMessageFilterEx = (ChangeWindowMessageFilterEx_t)GetProcAddress(GetModuleHandleA("user32"), "ChangeWindowMessageFilterEx"); + if (pChangeWindowMessageFilterEx) { // Win7+, UAC fix + pChangeWindowMessageFilterEx(m_hWnd, WM_DROPFILES, MSGFLT_ALLOW, nullptr); + pChangeWindowMessageFilterEx(m_hWnd, WM_COPYDATA, MSGFLT_ALLOW, nullptr); + pChangeWindowMessageFilterEx(m_hWnd, 0x0049/*WM_COPYGLOBALDATA*/, MSGFLT_ALLOW, nullptr); + } + DragAcceptFiles(m_hWnd, 1); + } + + // init Format combo box + { + hCtrl = GetDlgItem(m_hWnd, ID_cboxFormat); + ComboBox_ResetContent(hCtrl); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"PNG"), 0); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"JPG"), 1); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"BMP"), 2); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"TIF"), 3); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"GIF"), 4); + ComboBox_SelectItem(hCtrl, m_opt_cboxFormat); + } + + // init SendBy combo box + UPLOAD_INFO *pDefault = nullptr; + { + hCtrl = GetDlgItem(m_hWnd, ID_cboxSendBy); + ComboBox_ResetContent(hCtrl); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("")), new UPLOAD_INFO(SS_JUSTSAVE)); + if (m_hContact) { + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("File Transfer")), new UPLOAD_INFO(SS_FILESEND)); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("E-mail")), new UPLOAD_INFO(SS_EMAIL)); + if (g_myGlobals.PluginHTTPExist) { + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"HTTP Server"), new UPLOAD_INFO(SS_HTTPSERVER)); + } + else if (m_opt_cboxSendBy == SS_HTTPSERVER) { + m_opt_cboxSendBy = SS_IMAGESHACK; + } + if (g_myGlobals.PluginFTPExist) { + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("FTP File")), new UPLOAD_INFO(SS_FTPFILE)); + } + else if (m_opt_cboxSendBy == SS_FTPFILE) { + m_opt_cboxSendBy = SS_IMAGESHACK; + } + } + else if (m_opt_cboxSendBy == SS_FILESEND || m_opt_cboxSendBy == SS_EMAIL || m_opt_cboxSendBy == SS_HTTPSERVER || m_opt_cboxSendBy == SS_FTPFILE) { + m_opt_cboxSendBy = SS_IMAGESHACK; + } + if (g_myGlobals.PluginCloudFileExist) { + CallService(MS_CLOUDFILE_ENUMSERVICES, (WPARAM)EnumCloudFileServices, (LPARAM)hCtrl); + } + else if (m_opt_cboxSendBy == SS_CLOUDFILE) { + m_opt_cboxSendBy = SS_IMAGESHACK; + } + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"ImageShack"), new UPLOAD_INFO(SS_IMAGESHACK)); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("Upload Pie (30m)")), new UPLOAD_INFO(SS_UPLOADPIE, (void*)1)); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("Upload Pie (1d)")), new UPLOAD_INFO(SS_UPLOADPIE, (void*)4)); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, TranslateT("Upload Pie (1w)")), new UPLOAD_INFO(SS_UPLOADPIE, (void*)5)); + ComboBox_SetItemData(hCtrl, ComboBox_AddString(hCtrl, L"Imgur"), new UPLOAD_INFO(SS_IMGUR)); + + for (int i = 0; i < ComboBox_GetCount(hCtrl); i++) { + UPLOAD_INFO *p = (UPLOAD_INFO*)ComboBox_GetItemData(hCtrl, i); + if (p && p->sendBy == m_opt_cboxSendBy) { + pDefault = p; + ComboBox_SetCurSel(hCtrl, i); + break; + } + } + } + + // init footer options + CheckDlgButton(m_hWnd, ID_chkOpenAgain, m_opt_chkOpenAgain ? BST_CHECKED : BST_UNCHECKED); + + if (hCtrl = GetDlgItem(m_hWnd, ID_btnExplore)) { + SendDlgItemMessage(m_hWnd, ID_btnExplore, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Open Folder"), MBBF_TCHAR); + HICON hIcon = GetIconBtn(ICO_BTN_FOLDER); + SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + SetWindowText(hCtrl, hIcon ? L"" : L"..."); + } + + if (hCtrl = GetDlgItem(m_hWnd, ID_chkDesc)) { + SendDlgItemMessage(m_hWnd, ID_chkDesc, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Fill description textbox."), MBBF_TCHAR); + HICON hIcon = GetIconBtn(m_opt_btnDesc ? ICO_BTN_DESCON : ICO_BTN_DESC); + SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + SetWindowText(hCtrl, hIcon ? L"" : L"D"); + SendMessage(hCtrl, BM_SETCHECK, m_opt_btnDesc ? BST_CHECKED : BST_UNCHECKED, NULL); + } + + if (hCtrl = GetDlgItem(m_hWnd, ID_chkDeleteAfterSend)) { + SendDlgItemMessage(m_hWnd, ID_chkDeleteAfterSend, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Delete after send"), MBBF_TCHAR); + HICON hIcon = GetIconBtn(m_opt_btnDeleteAfterSend ? ICO_BTN_DELON : ICO_BTN_DEL); + SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + SetWindowText(hCtrl, hIcon ? L"" : L"X"); + SendMessage(hCtrl, BM_SETCHECK, m_opt_btnDeleteAfterSend ? BST_CHECKED : BST_UNCHECKED, NULL); + } + + if (hCtrl = GetDlgItem(m_hWnd, ID_chkEditor)) { + SendDlgItemMessage(m_hWnd, ID_chkEditor, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Open editor before sending"), MBBF_TCHAR); + HICON hIcon = GetIconBtn(m_opt_chkEditor ? ICO_BTN_EDITON : ICO_BTN_EDIT); + SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + SetWindowText(hCtrl, hIcon ? L"" : L"E"); + SendMessage(hCtrl, BM_SETCHECK, m_opt_chkEditor ? BST_CHECKED : BST_UNCHECKED, NULL); + } + + if (hCtrl = GetDlgItem(m_hWnd, ID_btnCapture)) { + SendMessage(hCtrl, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Capture"), MBBF_TCHAR); + HICON hIcon = GetIconBtn(ICO_BTN_OK); + SendMessage(hCtrl, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + SetWindowText(hCtrl, TranslateT("&Capture")); + SendMessage(hCtrl, BUTTONSETDEFAULT, 1, NULL); + } + cboxSendByChange((pDefault) ? pDefault->param : nullptr); // enable disable controls + + TranslateDialogDefault(m_hWnd); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// WM_COMMAND: + +void TfrmMain::wmCommand(WPARAM wParam, LPARAM lParam) +{ + HICON hIcon; + + int IDControl = LOWORD(wParam); + switch (HIWORD(wParam)) { + case BN_CLICKED: // Button controls + switch (IDControl) { + case IDCANCEL: // ESC pressed + this->Close(); + break; + case ID_chkTimed: + m_opt_chkTimed = (uint8_t)Button_GetCheck((HWND)lParam); + TfrmMain::chkTimedClick(); + break; + case ID_chkIndirectCapture: + m_opt_chkIndirectCapture = (uint8_t)Button_GetCheck((HWND)lParam); + break; + case ID_chkClientArea: + m_opt_chkClientArea = (uint8_t)Button_GetCheck((HWND)lParam); + if (m_hTargetWindow) + edtSizeUpdate(m_hTargetWindow, m_opt_chkClientArea, GetParent((HWND)lParam), ID_edtSize); + break; + case ID_imgTarget: + if (m_opt_tabCapture != 0) break; + m_hLastWin = nullptr; + SetTimer(m_hWnd, ID_imgTarget, BUTTON_POLLDELAY, nullptr); + break; + case ID_btnExplore: + TfrmMain::btnExploreClick(); + break; + case ID_chkDesc: + m_opt_btnDesc = !m_opt_btnDesc; + hIcon = GetIconBtn(m_opt_btnDesc ? ICO_BTN_DESCON : ICO_BTN_DESC); + SendMessage((HWND)lParam, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + break; + case ID_chkDeleteAfterSend: + m_opt_btnDeleteAfterSend = !m_opt_btnDeleteAfterSend; + hIcon = GetIconBtn(m_opt_btnDeleteAfterSend ? ICO_BTN_DELON : ICO_BTN_DEL); + SendMessage((HWND)lParam, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + if (m_cSend) m_cSend->m_bDeleteAfterSend = m_opt_btnDeleteAfterSend; + break; + case ID_chkEditor: + m_opt_chkEditor = !m_opt_chkEditor; + hIcon = GetIconBtn(m_opt_chkEditor ? ICO_BTN_EDITON : ICO_BTN_EDIT); + SendMessage((HWND)lParam, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + break; + case ID_chkOpenAgain: + m_opt_chkOpenAgain = Button_GetCheck((HWND)lParam); + break; + case ID_btnCapture: + TfrmMain::btnCaptureClick(); + break; + } + break; + + case CBN_SELCHANGE: // ComboBox controls + switch (IDControl) { // lParam = Handle to the control + case ID_cboxFormat: // not finish + m_opt_cboxFormat = (uint8_t)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); + break; + case ID_cboxSendBy: + { + UPLOAD_INFO *upload = (UPLOAD_INFO*)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); + m_opt_cboxSendBy = upload->sendBy; + cboxSendByChange(upload->param); + } + break; + + case ID_edtCaption: // cboxDesktopChange + m_opt_cboxDesktop = (uint8_t)ComboBox_GetItemData((HWND)lParam, ComboBox_GetCurSel((HWND)lParam)); + m_hTargetWindow = nullptr; + if (m_opt_cboxDesktop > 0) { + edtSizeUpdate(m_Monitors[m_opt_cboxDesktop - 1].rcMonitor, GetParent((HWND)lParam), ID_edtSize); + } + else { + edtSizeUpdate(m_VirtualScreen, GetParent((HWND)lParam), ID_edtSize); + } + break; + } + break; + + case EN_CHANGE: // Edit controls + switch (IDControl) { // lParam = Handle to the control + case ID_edtQuality: + m_opt_edtQuality = (uint8_t)GetDlgItemInt(m_hWnd, ID_edtQuality, nullptr, FALSE); + break; + case ID_edtTimed: + m_opt_edtTimed = (uint8_t)GetDlgItemInt(m_hWnd, ID_edtTimed, nullptr, FALSE); + break; + } + break; + } +} + +// WM_CLOSE: +void TfrmMain::wmClose(WPARAM, LPARAM) +{ + HWND hCtrl = GetDlgItem(m_hWnd, ID_cboxSendBy); + size_t count = ComboBox_GetCount(hCtrl); + for (size_t i = 0; i < count; i++) { + UPLOAD_INFO *ui = (UPLOAD_INFO*)ComboBox_GetItemData(hCtrl, i); + delete ui; + } + DestroyWindow(m_hWnd); + return; +} + +// WM_TIMER: +const int g_iTargetBorder = 7; +void TfrmMain::SetTargetWindow(HWND hwnd) +{ + if (!hwnd) { + POINT point; GetCursorPos(&point); + hwnd = WindowFromPoint(point); + for (HWND hTMP; (hTMP = GetParent(hwnd)); hwnd = hTMP) + ; + } + m_hTargetWindow = hwnd; + int len = GetWindowTextLength(m_hTargetWindow) + 1; + wchar_t *lpTitle; + if (len > 1) { + lpTitle = (wchar_t*)mir_alloc(len*sizeof(wchar_t)); + GetWindowText(m_hTargetWindow, lpTitle, len); + } + else { // no WindowText present, use WindowClass + lpTitle = (wchar_t*)mir_alloc(64 * sizeof(wchar_t)); + RealGetWindowClass(m_hTargetWindow, lpTitle, 64); + } + SetDlgItemText(m_hwndTabPage, ID_edtCaption, lpTitle); + mir_free(lpTitle); + edtSizeUpdate(m_hTargetWindow, m_opt_chkClientArea, m_hwndTabPage, ID_edtSize); +} + +void TfrmMain::wmTimer(WPARAM wParam, LPARAM) +{ + if (wParam == ID_imgTarget) { // Timer for Target selector + static int primarymouse; + if (!m_hTargetHighlighter) { + primarymouse = GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON; + m_hTargetHighlighter = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, (wchar_t*)g_clsTargetHighlighter, nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, g_plugin.getInst(), nullptr); + if (!m_hTargetHighlighter) return; + SetLayeredWindowAttributes(m_hTargetHighlighter, 0, 123, LWA_ALPHA); + SetSystemCursor(CopyCursor(GetIcon(ICO_TARGET)), OCR_IBEAM); // text cursor + SetSystemCursor(CopyCursor(GetIcon(ICO_TARGET)), OCR_NORMAL); + SetActiveWindow(m_hTargetHighlighter); // activate highlighter to fix focus problems with UAC (unelevated GetAsyncKeyState() fails if an elevated app got focus) + Hide(); + } + if (!(GetAsyncKeyState(primarymouse) & 0x8000)) { + KillTimer(m_hWnd, ID_imgTarget); + SystemParametersInfo(SPI_SETCURSORS, 0, nullptr, 0); + DestroyWindow(m_hTargetHighlighter), m_hTargetHighlighter = nullptr; + SetTargetWindow(m_hLastWin); + Show(); + return; + } + POINT point; GetCursorPos(&point); + HWND hwnd = WindowFromPoint(point); + if (!((GetAsyncKeyState(VK_SHIFT) | GetAsyncKeyState(VK_MENU)) & 0x8000)) + for (HWND hTMP; (hTMP = GetAncestor(hwnd, GA_PARENT)) && IsChild(hTMP, hwnd); hwnd = hTMP); + else { + ScreenToClient(hwnd, &point); + HWND hTMP; if ((hTMP = RealChildWindowFromPoint(hwnd, point))) + hwnd = hTMP; + } + if (hwnd != m_hLastWin) { + m_hLastWin = hwnd; + RECT rect; + if (m_opt_chkClientArea) { + GetClientRect(hwnd, &rect); + ClientToScreen(hwnd, (POINT*)&rect); + rect.right = rect.left + rect.right; + rect.bottom = rect.top + rect.bottom; + } + else + GetWindowRect(hwnd, &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + if (g_iTargetBorder) { + SetWindowPos(m_hTargetHighlighter, nullptr, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE); + if (width > g_iTargetBorder * 2 && height > g_iTargetBorder * 2) { + HRGN hRegnNew = CreateRectRgn(0, 0, width, height); + HRGN hRgnHole = CreateRectRgn(g_iTargetBorder, g_iTargetBorder, width - g_iTargetBorder, height - g_iTargetBorder); + CombineRgn(hRegnNew, hRegnNew, hRgnHole, RGN_XOR); + DeleteObject(hRgnHole); + SetWindowRgn(m_hTargetHighlighter, hRegnNew, FALSE); // cleans up hRegnNew + } + else SetWindowRgn(m_hTargetHighlighter, nullptr, FALSE); + } + SetWindowPos(m_hTargetHighlighter, HWND_TOPMOST, rect.left, rect.top, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE); + } + return; + } + if (wParam == ID_chkTimed) { // Timer for Screenshot +#ifdef _DEBUG + OutputDebugStringA("SS Bitmap Timer Start\r\n"); +#endif + if (!m_bCapture) { // only start once + if (m_Screenshot) { + FreeImage_Unload(m_Screenshot); + m_Screenshot = nullptr; + } + m_bCapture = true; + switch (m_opt_tabCapture) { + case 0: + m_Screenshot = CaptureWindow(m_hTargetWindow, m_opt_chkClientArea, m_opt_chkIndirectCapture); + break; + case 1: + m_Screenshot = CaptureMonitor((m_opt_cboxDesktop > 0) ? m_Monitors[m_opt_cboxDesktop - 1].szDevice : nullptr); + break; + case 2: // edge case, existing local file + break; +#ifdef _DEBUG + default: + OutputDebugStringA("SS Bitmap Timer Stop (no tabCapture)\r\n"); +#endif + } + m_bCapture = false; + if (m_Screenshot || m_opt_tabCapture == 2) { // @note : test without "if" + KillTimer(m_hWnd, ID_chkTimed); +#ifdef _DEBUG + OutputDebugStringA("SS Bitmap Timer Stop (CaptureDone)\r\n"); +#endif + SendMessage(m_hWnd, UM_EVENT, 0, (LPARAM)EVT_CaptureDone); + } + } + } +} + +// WM_NOTIFY: +void TfrmMain::wmNotify(WPARAM, LPARAM lParam) +{ + switch (((LPNMHDR)lParam)->idFrom) { + case IDC_CAPTURETAB: + // HWND hwndFrom; = member is handle to the tab control + // UINT_PTR idFrom; = member is the child window identifier of the tab control. + // UINT code; = member is TCN_SELCHANGE + switch (((LPNMHDR)lParam)->code) { + case TCN_SELCHANGING: + if (m_hwndTabPage) { + ShowWindow(m_hwndTabPage, SW_HIDE); + m_hwndTabPage = nullptr; + } + break; + + case TCN_SELCHANGE: + { + TAB_INFO itab = { TCIF_PARAM }; + m_opt_tabCapture = TabCtrl_GetCurSel(m_hwndTab); + TabCtrl_GetItem(m_hwndTab, m_opt_tabCapture, &itab); + m_hwndTabPage = itab.hwndTabPage; + } + ShowWindow(m_hwndTabPage, SW_SHOW); + break; + } + break; + } +} + +// UM_EVENT: +void TfrmMain::UMevent(WPARAM, LPARAM lParam) +{ + // HWND hWnd = (HWND)wParam; + switch (lParam) { + case EVT_CaptureDone: + if (!m_Screenshot && m_opt_tabCapture != 2) { + wchar_t *err = TranslateT("Couldn't take a screenshot"); + MessageBox(nullptr, err, ERROR_TITLE, MB_OK | MB_ICONWARNING); + Show(); + return; + } + FormClose(); + break; + + case EVT_SendFileDone: + break; + + case EVT_CheckOpenAgain: + if (m_opt_chkOpenAgain) { + if (m_Screenshot) { + FreeImage_Unload(m_Screenshot); + m_Screenshot = nullptr; + } + Show(); + } + else {// Saving Options and close + SaveOptions(); + Close(); + } + break; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Standard konstruktor/destruktor + +TfrmMain::TfrmMain() +{ + /* m_opt_XXX */ + m_bOnExitSave = TRUE; + + m_hWnd = nullptr; + m_hContact = NULL; + m_hTargetWindow = m_hLastWin = nullptr; + m_hTargetHighlighter = nullptr; + m_FDestFolder = m_pszFile = nullptr; + m_Screenshot = nullptr; + /* m_AlphaColor */ + m_cSend = nullptr; + + m_Monitors = nullptr; + m_MonitorCount = MonitorInfoEnum(m_Monitors, m_VirtualScreen); + /* m_opt_XXX */ LoadOptions(); + m_bCapture = false; + /* m_hwndTab,m_hwndTabPage */ + m_himlTab = nullptr; +} + +TfrmMain::~TfrmMain() +{ + _HandleMapping.erase(m_hWnd); + mir_free(m_pszFile); + mir_free(m_FDestFolder); + mir_free(m_Monitors); + if (m_Screenshot) FreeImage_Unload(m_Screenshot); + if (m_cSend) delete m_cSend; + if (m_hTargetHighlighter) { + DestroyWindow(m_hTargetHighlighter), m_hTargetHighlighter = nullptr; + SystemParametersInfo(SPI_SETCURSORS, 0, nullptr, 0); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Load / Saving options from miranda's database + +void TfrmMain::LoadOptions(void) +{ + uint32_t rgb = g_plugin.getDword("AlphaColor", 16777215); + m_AlphaColor.rgbRed = GetRValue(rgb); + m_AlphaColor.rgbGreen = GetGValue(rgb); + m_AlphaColor.rgbBlue = GetBValue(rgb); + m_AlphaColor.rgbReserved = 0; + + m_opt_edtQuality = g_plugin.getByte("JpegQuality", 75); + + m_opt_tabCapture = g_plugin.getByte("Capture", 0); + m_opt_chkIndirectCapture = g_plugin.getByte("IndirectCapture", 0); + m_opt_chkClientArea = g_plugin.getByte("ClientArea", 0); + m_opt_cboxDesktop = g_plugin.getByte("Desktop", 0); + + m_opt_chkTimed = g_plugin.getByte("TimedCap", 0); + m_opt_edtTimed = g_plugin.getByte("CapTime", 3); + m_opt_cboxFormat = g_plugin.getByte("OutputFormat", 0); + m_opt_cboxSendBy = g_plugin.getByte("SendBy", 0); + + m_opt_btnDesc = g_plugin.getByte("AutoDescription", 1); + m_opt_btnDeleteAfterSend = g_plugin.getByte("DelAfterSend", 1) != 0; + m_opt_chkEditor = g_plugin.getByte("Preview", 0); + m_opt_chkOpenAgain = g_plugin.getByte("OpenAgain", 0); +} + +void TfrmMain::SaveOptions(void) +{ + if (m_bOnExitSave) { + g_plugin.setDword("AlphaColor", + (uint32_t)RGB(m_AlphaColor.rgbRed, m_AlphaColor.rgbGreen, m_AlphaColor.rgbBlue)); + + g_plugin.setByte("JpegQuality", m_opt_edtQuality); + + g_plugin.setByte("Capture", m_opt_tabCapture); + g_plugin.setByte("IndirectCapture", m_opt_chkIndirectCapture); + g_plugin.setByte("ClientArea", m_opt_chkClientArea); + g_plugin.setByte("Desktop", m_opt_cboxDesktop); + + g_plugin.setByte("TimedCap", m_opt_chkTimed); + g_plugin.setByte("CapTime", m_opt_edtTimed); + g_plugin.setByte("OutputFormat", m_opt_cboxFormat); + g_plugin.setByte("SendBy", m_opt_cboxSendBy); + + g_plugin.setByte("AutoDescription", m_opt_btnDesc); + g_plugin.setByte("DelAfterSend", m_opt_btnDeleteAfterSend); + g_plugin.setByte("Preview", m_opt_chkEditor); + g_plugin.setByte("OpenAgain", m_opt_chkOpenAgain); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void TfrmMain::Init(wchar_t *DestFolder, MCONTACT Contact) +{ + m_FDestFolder = mir_wstrdup(DestFolder); + m_hContact = Contact; + + // create window + m_hWnd = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_UMainForm), nullptr, DlgTfrmMain, (LPARAM)this); + + // register object + _HandleMapping.insert(CHandleMapping::value_type(m_hWnd, this)); + + // check Contact + if (m_cSend) + m_cSend->SetContact(Contact); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void TfrmMain::btnCaptureClick() +{ + if (m_opt_tabCapture == 1) m_hTargetWindow = GetDesktopWindow(); + else if (m_opt_tabCapture == 2) { + wchar_t filename[MAX_PATH]; + GetDlgItemText(m_hwndTabPage, ID_edtSize, filename, _countof(filename)); + FILE *fp = _wfopen(filename, L"rb"); + if (!fp) { + wchar_t *err = TranslateT("Select a file"); + MessageBox(m_hWnd, err, ERROR_TITLE, MB_OK | MB_ICONWARNING); + return; + } + fclose(fp); + mir_free(m_pszFile); m_pszFile = mir_wstrdup(filename); + } + else if (!m_hTargetWindow) { + wchar_t *err = TranslateT("Select a target window."); + MessageBox(m_hWnd, err, ERROR_TITLE, MB_OK | MB_ICONWARNING); + return; + } + TfrmMain::Hide(); + + if (m_opt_chkTimed) { + SetTimer(m_hWnd, ID_chkTimed, m_opt_edtTimed ? m_opt_edtTimed * 1000 : 500, nullptr); // calls EVT_CaptureDone + return; + } + if (m_opt_tabCapture == 1) { // desktop needs always time to update from TfrmMain::Hide() + SetTimer(m_hWnd, ID_chkTimed, 500, nullptr); // calls EVT_CaptureDone + return; + } + if (m_opt_tabCapture != 2) { + m_Screenshot = CaptureWindow(m_hTargetWindow, m_opt_chkClientArea, m_opt_chkIndirectCapture); + } + SendMessage(m_hWnd, UM_EVENT, 0, (LPARAM)EVT_CaptureDone); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void TfrmMain::chkTimedClick() +{ + Button_Enable(GetDlgItem(m_hWnd, ID_edtTimedLabel), (BOOL)m_opt_chkTimed); + Button_Enable(GetDlgItem(m_hWnd, ID_edtTimed), (BOOL)m_opt_chkTimed); + Button_Enable(GetDlgItem(m_hWnd, ID_upTimed), (BOOL)m_opt_chkTimed); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void TfrmMain::cboxSendByChange(void *param) +{ + BOOL bState; + HICON hIcon; + uint8_t itemFlag = SS_DLG_DESCRIPTION; + if (m_cSend) + delete m_cSend; + switch (m_opt_cboxSendBy) { + case SS_FILESEND: // "File Transfer" + m_cSend = new CSendFile(m_hWnd, m_hContact, true); + break; + case SS_EMAIL: // "E-mail" + m_cSend = new CSendEmail(m_hWnd, m_hContact, true); + break; + case SS_HTTPSERVER: // "HTTP Server" + m_cSend = new CSendHTTPServer(m_hWnd, m_hContact, true); + break; + case SS_FTPFILE: // "FTP File" + m_cSend = new CSendFTPFile(m_hWnd, m_hContact, true); + break; + case SS_CLOUDFILE: // "CloudFile" + m_cSend = new CSendCloudFile(m_hWnd, m_hContact, false, (char*)param); + break; + case SS_IMAGESHACK: // "ImageShack" + m_cSend = new CSendHost_ImageShack(m_hWnd, m_hContact, true); + break; + case SS_UPLOADPIE: // "Upload Pie" + m_cSend = new CSendHost_UploadPie(m_hWnd, m_hContact, true, (INT_PTR)param); + break; + case SS_IMGUR: + m_cSend = new CSendHost_Imgur(m_hWnd, m_hContact, true); + break; + default: + m_cSend = nullptr; + break; + } + if (m_cSend) { + itemFlag = m_cSend->GetEnableItem(); + m_cSend->m_bDeleteAfterSend = m_opt_btnDeleteAfterSend; + } + bState = (itemFlag & SS_DLG_DELETEAFTERSSEND); + hIcon = GetIconBtn(m_opt_btnDeleteAfterSend ? ICO_BTN_DELON : ICO_BTN_DEL); + SendDlgItemMessage(m_hWnd, ID_chkDeleteAfterSend, BM_SETIMAGE, IMAGE_ICON, (LPARAM)(bState ? hIcon : nullptr)); + Button_Enable(GetDlgItem(m_hWnd, ID_chkDeleteAfterSend), bState); + + bState = (itemFlag & SS_DLG_DESCRIPTION); + hIcon = GetIconBtn(m_opt_btnDesc ? ICO_BTN_DESCON : ICO_BTN_DESC); + SendDlgItemMessage(m_hWnd, ID_chkDesc, BM_SETIMAGE, IMAGE_ICON, (LPARAM)(bState ? hIcon : nullptr)); + Button_Enable(GetDlgItem(m_hWnd, ID_chkDesc), bState); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void TfrmMain::btnExploreClick() +{ + if (m_FDestFolder) + ShellExecute(nullptr, L"explore", m_FDestFolder, nullptr, nullptr, SW_SHOW); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void TfrmMain::edtSizeUpdate(HWND hWnd, BOOL ClientArea, HWND hTarget, UINT Ctrl) +{ + // get window dimensions + RECT rect = { 0 }; + RECT cliRect = { 0 }; + wchar_t B[33], H[16]; + GetWindowRect(hWnd, &rect); + if (ClientArea) { + POINT pt = { 0 }; + GetClientRect(hWnd, &cliRect); + pt.x = cliRect.left; + pt.y = cliRect.top; + ClientToScreen(hWnd, &pt); + pt.x = pt.x - rect.left; // offset x for client area + pt.y = pt.y - rect.top; // offset y for client area + rect = cliRect; + } + + _itow(rect.right - rect.left, B, 10); + _itow(rect.bottom - rect.top, H, 10); + mir_wstrncat(B, L"x", _countof(B) - mir_wstrlen(B)); + mir_wstrncat(B, H, _countof(B) - mir_wstrlen(B)); + SetDlgItemText(hTarget, Ctrl, B); +} + +void TfrmMain::edtSizeUpdate(RECT rect, HWND hTarget, UINT Ctrl) +{ + wchar_t B[33], H[16]; + _itow(ABS(rect.right - rect.left), B, 10); + _itow(ABS(rect.bottom - rect.top), H, 10); + mir_wstrncat(B, L"x", _countof(B) - mir_wstrlen(B)); + mir_wstrncat(B, H, _countof(B) - mir_wstrlen(B)); + SetDlgItemText(hTarget, Ctrl, B); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +INT_PTR TfrmMain::SaveScreenshot(FIBITMAP *dib) +{ + if (!dib) + return 1; + + // generate file name + unsigned FileNumber = g_plugin.getDword("FileNumber", 0) + 1; + if (FileNumber > 99999) + FileNumber = 1; + + CMStringW wszFileName(m_FDestFolder); + if (wszFileName.Right(1) != L"\\") + wszFileName.Append(L"\\"); + wszFileName.AppendFormat(L"shot%.5u", FileNumber); + + // generate a description according to the screenshot + wchar_t winText[1024]; + GetDlgItemText(m_hwndTabPage, ID_edtCaption, winText, _countof(winText)); + + CMStringW wszFileDesc; + if (m_opt_tabCapture) + wszFileDesc.Format(TranslateT("Screenshot of \"%s\""), winText); + else { + if (m_opt_chkClientArea) + wszFileDesc.Format(TranslateT("Screenshot for client area of \"%s\" window"), winText); + else + wszFileDesc.Format(TranslateT("Screenshot of \"%s\" window"), winText); + } + + // convert to 32Bits (make sure it is 32bit) + FIBITMAP *dib_new = FreeImage_ConvertTo32Bits(dib); + FreeImage_SetTransparent(dib_new, TRUE); + + BOOL ret = FALSE; + HWND hwndCombo = GetDlgItem(m_hWnd, ID_cboxFormat); + switch (ComboBox_GetItemData(hwndCombo, ComboBox_GetCurSel(hwndCombo))) { + case 0: // PNG + wszFileName.Append(L".png"); + ret = FreeImage_SaveU(FIF_PNG, dib_new, wszFileName, 0); + break; + + case 1: // JPG + wszFileName.Append(L".jpg"); + { + FIBITMAP *dib32 = FreeImage_Composite(dib_new, FALSE, &m_AlphaColor, nullptr); + FIBITMAP *dib24 = FreeImage_ConvertTo24Bits(dib32); + FreeImage_Unload(dib32); + ret = FreeImage_SaveU(FIF_JPEG, dib24, wszFileName, 0); + FreeImage_Unload(dib24); + } + break; + + case 2: // BMP + wszFileName.Append(L".bmp"); + { + FIBITMAP *dib32 = FreeImage_Composite(dib_new, FALSE, &m_AlphaColor, nullptr); + FIBITMAP *dib24 = FreeImage_ConvertTo24Bits(dib32); + FreeImage_Unload(dib32); + ret = FreeImage_SaveU(FIF_BMP, dib24, wszFileName, 0); + FreeImage_Unload(dib24); + } + break; + + case 3: // TIFF (miranda freeimage interface do not support save tiff, we udse GDI+) + wszFileName.Append(L".tif"); + { + FIBITMAP *dib32 = FreeImage_Composite(dib_new, FALSE, &m_AlphaColor, nullptr); + FIBITMAP *dib24 = FreeImage_ConvertTo24Bits(dib32); + FreeImage_Unload(dib32); + + HBITMAP hBmp = FreeImage_CreateHBITMAPFromDIB(dib24); + FreeImage_Unload(dib24); + SaveTIF(hBmp, wszFileName); + DeleteObject(hBmp); + } + ret = TRUE; + break; + + case 4: // GIF + wszFileName.Append(L".gif"); + { + HBITMAP hBmp = FreeImage_CreateHBITMAPFromDIB(dib_new); + SaveGIF(hBmp, wszFileName); + DeleteObject(hBmp); + } + ret = TRUE; + break; + } + + FreeImage_Unload(dib_new); + + if (!ret) + return 1; + + g_plugin.setDword("FileNumber", FileNumber); + replaceStrW(m_pszFile, wszFileName); + + if (!IsWindowEnabled(GetDlgItem(m_hWnd, ID_chkDesc)) || !m_opt_btnDesc) + wszFileDesc.Empty(); + + if (m_cSend) { + m_cSend->SetFile(m_pszFile); + m_cSend->SetDescription(wszFileDesc); + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void TfrmMain::FormClose() +{ + bool bCanDelete = m_opt_btnDeleteAfterSend; + if (m_opt_tabCapture == 2) { // existing file + wchar_t description[1024]; + GetDlgItemText(m_hwndTabPage, ID_edtCaption, description, _countof(description)); + if (!IsWindowEnabled(GetDlgItem(m_hWnd, ID_chkDesc)) || !m_opt_btnDesc) + *description = '\0'; + if (m_cSend) { + m_cSend->m_bDeleteAfterSend = false; // well... guess it's better to not delete existing files for now... + m_cSend->SetFile(m_pszFile); + m_cSend->SetDescription(description); + } + bCanDelete = false; + } + else if (SaveScreenshot(m_Screenshot)) { // Saving the screenshot + Show(); // Error from SaveScreenshot + return; + } + + bool send = true; + if (m_opt_chkEditor) { + SHELLEXECUTEINFO shex = { sizeof(SHELLEXECUTEINFO) }; + shex.fMask = SEE_MASK_NOCLOSEPROCESS; + shex.lpVerb = L"edit"; + shex.lpFile = m_pszFile; + shex.nShow = SW_SHOWNORMAL; + ShellExecuteEx(&shex); + if (shex.hProcess) { + uint32_t res; + MSG msg; + do { + // wait for editor exit or messages/input + res = MsgWaitForMultipleObjects(1, &shex.hProcess, 0, INFINITE, QS_ALLINPUT); + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + if (msg.message == WM_QUIT) { + res = WAIT_OBJECT_0; + PostMessage(nullptr, WM_QUIT, 0, 0); // forward for outer message loops + break; + } + + // process dialog messages (of unknown dialogs) + HWND hwndDlgModeless = GetActiveWindow(); + if (hwndDlgModeless != nullptr && IsDialogMessage(hwndDlgModeless, &msg)) /* Wine fix. */ + continue; + + // process messages + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } while (res == WAIT_OBJECT_0 + 1); + CloseHandle(shex.hProcess); + } + if (MessageBox(m_hWnd, TranslateT("Send screenshot?"), L"SendSS", MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL) != IDYES) + send = false; + } + + if (send && m_cSend && m_pszFile) { + if (!m_cSend->Send()) // not sent now, class deletes itself later + m_cSend = nullptr; + cboxSendByChange(nullptr); + } + else if (!send && bCanDelete) + DeleteFile(m_pszFile); + + SendMessage(m_hWnd, UM_EVENT, 0, (LPARAM)EVT_CheckOpenAgain); +} diff --git a/plugins/SendScreenshotPlus/src/UMainForm.h b/plugins/SendScreenshotPlus/src/UMainForm.h index 55b75e2373..fbe8a6a50b 100644 --- a/plugins/SendScreenshotPlus/src/UMainForm.h +++ b/plugins/SendScreenshotPlus/src/UMainForm.h @@ -1,146 +1,146 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef UMainFormH -#define UMainFormH - -#define SS_JUSTSAVE 0 -#define SS_FILESEND 1 -#define SS_EMAIL 2 -#define SS_HTTPSERVER 3 -#define SS_FTPFILE 4 -#define SS_CLOUDFILE 5 -#define SS_IMAGESHACK 6 -#define SS_UPLOADPIE 7 -#define SS_IMGUR 8 - -struct UPLOAD_INFO -{ - uint8_t sendBy; //SS_* - void *param; - - UPLOAD_INFO(uint8_t sb) : sendBy(sb), param(nullptr) { } - UPLOAD_INFO(uint8_t sb, void *p) : sendBy(sb), param(p) { } -}; - -// Used for our own cheap TrackMouseEvent -#define BUTTON_POLLDELAY 50 - -// User Events -#define EVT_CaptureDone 1 -#define EVT_SendFileDone 2 -#define EVT_CheckOpenAgain 3 - -struct TAB_INFO -{ - TCITEMHEADER tcih; - HWND hwndMain; // main window - HWND hwndTab; // tab control - HWND hwndTabPage; // current child dialog box -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -class TfrmMain -{ - -public: - // Deklaration Standardkonstruktor/Standarddestructor - TfrmMain(); - ~TfrmMain(); - - uint8_t m_opt_tabCapture; // capture tab page - uint8_t m_opt_cboxDesktop; // TRadioButton *rbtnDesktop; - uint8_t m_opt_chkTimed; // TCheckBox *chkTimed; - uint8_t m_opt_cboxSendBy; // TComboBox *cboxSendBy; - uint8_t m_opt_btnDesc; // TCheckBox *chkDesc; - uint8_t m_opt_chkEditor; // TCheckBox *chkEditor; - bool m_bOnExitSave; - - static void Unload(); - void Init(wchar_t* DestFolder, MCONTACT Contact); - void Close(){ SendMessage(m_hWnd, WM_CLOSE, 0, 0); } - void Show(){ ShowWindow(m_hWnd, SW_SHOW); } - void Hide(){ ShowWindow(m_hWnd, SW_HIDE); } - void SetTargetWindow(HWND hwnd = nullptr); - void btnCaptureClick(); - void cboxSendByChange(void *param); - -private: - HWND m_hWnd; - MCONTACT m_hContact; - HWND m_hTargetWindow, m_hLastWin; - HWND m_hTargetHighlighter; - wchar_t* m_FDestFolder; - wchar_t* m_pszFile; - FIBITMAP* m_Screenshot; - RGBQUAD m_AlphaColor; - CSend* m_cSend; - - void chkTimedClick(); - void btnExploreClick(); - void LoadOptions(void); - void SaveOptions(void); - INT_PTR SaveScreenshot(FIBITMAP* dib); - void FormClose(); - static void edtSizeUpdate(HWND hWnd, BOOL ClientArea, HWND hTarget, UINT Ctrl); - static void edtSizeUpdate(RECT rect, HWND hTarget, UINT Ctrl); - -protected: - MONITORINFOEX* m_Monitors; - size_t m_MonitorCount; - RECT m_VirtualScreen; - - uint8_t m_opt_chkOpenAgain; // TCheckBox *chkOpenAgain; - uint8_t m_opt_chkIndirectCapture; // TCheckBox *chkIndirectCapture; - uint8_t m_opt_chkClientArea; // TCheckBox *chkClientArea; - uint8_t m_opt_edtQuality; // TLabeledEdit *edtQuality; - bool m_opt_btnDeleteAfterSend; // TCheckBox *chkDeleteAfterSend; - uint8_t m_opt_cboxFormat; // TComboBox *cboxFormat; - uint8_t m_opt_edtTimed; // TLabeledEdit *edtTimed; - bool m_bCapture; // is capture active - HWND m_hwndTab; // TabControl handle - HWND m_hwndTabPage; // TabControl activ page handle - HIMAGELIST m_himlTab; // TabControl imagelist - - typedef std::map CHandleMapping; - static CHandleMapping _HandleMapping; - static INT_PTR CALLBACK DlgTfrmMain(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - - void wmInitdialog(WPARAM wParam, LPARAM lParam); - void wmCommand(WPARAM wParam, LPARAM lParam); - void wmClose(WPARAM wParam, LPARAM lParam); - void wmNotify(WPARAM wParam, LPARAM lParam); - void wmTimer(WPARAM wParam, LPARAM lParam); - - void UMevent(WPARAM wParam, LPARAM lParam); - - static INT_PTR CALLBACK DlgProc_CaptureTabPage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef UMainFormH +#define UMainFormH + +#define SS_JUSTSAVE 0 +#define SS_FILESEND 1 +#define SS_EMAIL 2 +#define SS_HTTPSERVER 3 +#define SS_FTPFILE 4 +#define SS_CLOUDFILE 5 +#define SS_IMAGESHACK 6 +#define SS_UPLOADPIE 7 +#define SS_IMGUR 8 + +struct UPLOAD_INFO +{ + uint8_t sendBy; //SS_* + void *param; + + UPLOAD_INFO(uint8_t sb) : sendBy(sb), param(nullptr) { } + UPLOAD_INFO(uint8_t sb, void *p) : sendBy(sb), param(p) { } +}; + +// Used for our own cheap TrackMouseEvent +#define BUTTON_POLLDELAY 50 + +// User Events +#define EVT_CaptureDone 1 +#define EVT_SendFileDone 2 +#define EVT_CheckOpenAgain 3 + +struct TAB_INFO +{ + TCITEMHEADER tcih; + HWND hwndMain; // main window + HWND hwndTab; // tab control + HWND hwndTabPage; // current child dialog box +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +class TfrmMain +{ + +public: + // Deklaration Standardkonstruktor/Standarddestructor + TfrmMain(); + ~TfrmMain(); + + uint8_t m_opt_tabCapture; // capture tab page + uint8_t m_opt_cboxDesktop; // TRadioButton *rbtnDesktop; + uint8_t m_opt_chkTimed; // TCheckBox *chkTimed; + uint8_t m_opt_cboxSendBy; // TComboBox *cboxSendBy; + uint8_t m_opt_btnDesc; // TCheckBox *chkDesc; + uint8_t m_opt_chkEditor; // TCheckBox *chkEditor; + bool m_bOnExitSave; + + static void Unload(); + void Init(wchar_t* DestFolder, MCONTACT Contact); + void Close(){ SendMessage(m_hWnd, WM_CLOSE, 0, 0); } + void Show(){ ShowWindow(m_hWnd, SW_SHOW); } + void Hide(){ ShowWindow(m_hWnd, SW_HIDE); } + void SetTargetWindow(HWND hwnd = nullptr); + void btnCaptureClick(); + void cboxSendByChange(void *param); + +private: + HWND m_hWnd; + MCONTACT m_hContact; + HWND m_hTargetWindow, m_hLastWin; + HWND m_hTargetHighlighter; + wchar_t* m_FDestFolder; + wchar_t* m_pszFile; + FIBITMAP* m_Screenshot; + RGBQUAD m_AlphaColor; + CSend* m_cSend; + + void chkTimedClick(); + void btnExploreClick(); + void LoadOptions(void); + void SaveOptions(void); + INT_PTR SaveScreenshot(FIBITMAP* dib); + void FormClose(); + static void edtSizeUpdate(HWND hWnd, BOOL ClientArea, HWND hTarget, UINT Ctrl); + static void edtSizeUpdate(RECT rect, HWND hTarget, UINT Ctrl); + +protected: + MONITORINFOEX* m_Monitors; + size_t m_MonitorCount; + RECT m_VirtualScreen; + + uint8_t m_opt_chkOpenAgain; // TCheckBox *chkOpenAgain; + uint8_t m_opt_chkIndirectCapture; // TCheckBox *chkIndirectCapture; + uint8_t m_opt_chkClientArea; // TCheckBox *chkClientArea; + uint8_t m_opt_edtQuality; // TLabeledEdit *edtQuality; + bool m_opt_btnDeleteAfterSend; // TCheckBox *chkDeleteAfterSend; + uint8_t m_opt_cboxFormat; // TComboBox *cboxFormat; + uint8_t m_opt_edtTimed; // TLabeledEdit *edtTimed; + bool m_bCapture; // is capture active + HWND m_hwndTab; // TabControl handle + HWND m_hwndTabPage; // TabControl activ page handle + HIMAGELIST m_himlTab; // TabControl imagelist + + typedef std::map CHandleMapping; + static CHandleMapping _HandleMapping; + static INT_PTR CALLBACK DlgTfrmMain(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + + void wmInitdialog(WPARAM wParam, LPARAM lParam); + void wmCommand(WPARAM wParam, LPARAM lParam); + void wmClose(WPARAM wParam, LPARAM lParam); + void wmNotify(WPARAM wParam, LPARAM lParam); + void wmTimer(WPARAM wParam, LPARAM lParam); + + void UMevent(WPARAM wParam, LPARAM lParam); + + static INT_PTR CALLBACK DlgProc_CaptureTabPage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/Utils.cpp b/plugins/SendScreenshotPlus/src/Utils.cpp index 1d0d92f5ea..bc543d1024 100644 --- a/plugins/SendScreenshotPlus/src/Utils.cpp +++ b/plugins/SendScreenshotPlus/src/Utils.cpp @@ -1,412 +1,412 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "stdafx.h" - -void ComboBox_SelectItem(HWND hCombo, LPARAM data) -{ - for (int i = 0;; i++) { - LPARAM itemData = ComboBox_GetItemData(hCombo, i); - if (itemData == data) { - ComboBox_SetCurSel(hCombo, i); - return; - } - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// MonitorInfoEnum - -static BOOL CALLBACK MonitorInfoEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) -{ - MONITORS* monitors = (MONITORS*)dwData; - ++monitors->count; - monitors->info = (MONITORINFOEX*)mir_realloc(monitors->info, sizeof(MONITORINFOEX)*monitors->count); - monitors->info[monitors->count - 1].cbSize = sizeof(MONITORINFOEX); - if (!GetMonitorInfo(hMonitor, (LPMONITORINFO)(monitors->info + monitors->count - 1))) - return FALSE; // stop enumeration if error - - return TRUE; -} - -size_t MonitorInfoEnum(MONITORINFOEX* &myMonitors, RECT &virtualScreen) -{ - MONITORS tmp = { 0, nullptr }; - if (EnumDisplayMonitors(nullptr, nullptr, MonitorInfoEnumProc, (LPARAM)&tmp)) { - myMonitors = tmp.info; - memset(&virtualScreen, 0, sizeof(virtualScreen)); - for (size_t i = 0; i < tmp.count; ++i) { - UnionRect(&virtualScreen, &virtualScreen, &tmp.info[i].rcMonitor); - } - return tmp.count; - } - - mir_free(tmp.info); - return 0; -} - -FIBITMAP* CreateDIBFromDC(HDC hDC, const RECT* rect, HWND hCapture = nullptr); - -///////////////////////////////////////////////////////////////////////////////////////// -// capture window as FIBITMAP - caller must FreeImage_Unload(dib) - -FIBITMAP* CaptureWindow(HWND hCapture, BOOL bClientArea, BOOL bIndirectCapture) -{ - FIBITMAP* dib; - HWND hForegroundWin; - RECT rect; // cropping rect - - if (!hCapture || !IsWindow(hCapture)) - return nullptr; - - hForegroundWin = GetForegroundWindow(); // old foreground window - SetForegroundWindow(hCapture); // force target foreground - BringWindowToTop(hCapture); // bring it to top as well - - // redraw window to prevent runtime artifacts in picture - UpdateWindow(hCapture); - - HWND hParent = GetAncestor(hCapture, GA_PARENT); - if (hParent && !IsChild(hParent, hCapture)) - hParent = nullptr; - if (bIndirectCapture) { - intptr_t wastopmost = GetWindowLongPtr(hCapture, GWL_EXSTYLE)&WS_EX_TOPMOST; - if (!wastopmost) - SetWindowPos(hCapture, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - if (bClientArea) { - GetClientRect(hCapture, &rect); - ClientToScreen(hCapture, (POINT*)&rect); - rect.right += rect.left; rect.bottom += rect.top; - } - else - GetWindowRect(hCapture, &rect); - dib = CaptureMonitor(nullptr, &rect); - if (!wastopmost) - SetWindowPos(hCapture, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - } - else { - HDC hDCsrc; - GetWindowRect(hCapture, &rect); - if (hParent) - hDCsrc = GetDC(hCapture); // hCapture is part of a window, capture that - else - hDCsrc = GetWindowDC(hCapture); // entire window w/ title bar - rect.right = ABS(rect.right - rect.left); - rect.bottom = ABS(rect.bottom - rect.top); - rect.left = rect.top = 0; - // capture window and get FIBITMAP - dib = CreateDIBFromDC(hDCsrc, &rect, hCapture); - ReleaseDC(hCapture, hDCsrc); - - // we could capture directly, but doing so breaks GetWindowRgn() and also includes artifacts... - if (bClientArea) { - GetWindowRect(hCapture, &rect); - RECT rectCA; GetClientRect(hCapture, &rectCA); - ClientToScreen(hCapture, (POINT*)&rectCA); - rectCA.left = ABS(rectCA.left - rect.left); - rectCA.top = ABS(rectCA.top - rect.top); - rectCA.right += rectCA.left; rectCA.bottom += rectCA.top; - - // crop the window to ClientArea - FIBITMAP* dibClient = FreeImage_Copy(dib, rectCA.left, rectCA.top, rectCA.right, rectCA.bottom); - FreeImage_Unload(dib); - dib = dibClient; - } - } - - // restore previous foreground window - if (hForegroundWin) { - SetForegroundWindow(hForegroundWin); - BringWindowToTop(hForegroundWin); - } - return dib; -} - -FIBITMAP* CaptureMonitor(const wchar_t* szDevice, const RECT* cropRect/*=NULL*/) -{ - HDC hScrDC; - RECT rect; - - // get screen resolution - if (!szDevice) { - hScrDC = CreateDC(L"DISPLAY", nullptr, nullptr, nullptr); - rect.left = GetSystemMetrics(SM_XVIRTUALSCREEN); - rect.top = GetSystemMetrics(SM_YVIRTUALSCREEN); - rect.right = GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN); - rect.bottom = GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN); - } - else { - hScrDC = CreateDC(szDevice, nullptr, nullptr, nullptr); - rect.left = rect.top = 0; - rect.right = GetDeviceCaps(hScrDC, HORZRES); - rect.bottom = GetDeviceCaps(hScrDC, VERTRES); - } - if (cropRect) { - if (cropRect->left > rect.left) rect.left = cropRect->left; - if (cropRect->top > rect.top) rect.top = cropRect->top; - if (cropRect->right < rect.right) rect.right = cropRect->right; - if (cropRect->bottom < rect.bottom) rect.bottom = cropRect->bottom; - } - - FIBITMAP *dib = CreateDIBFromDC(hScrDC, &rect); - ReleaseDC(nullptr, hScrDC); - return dib; -} - -FIBITMAP* CreateDIBFromDC(HDC hDC, const RECT* rect, HWND hCapture/*=NULL*/) -{ - long width = rect->right - rect->left; - long height = rect->bottom - rect->top; - - // create a DC for the screen and create - // a memory DC compatible to screen DC - HDC hScrDC = hDC; - if (!hScrDC) - hScrDC = GetDC(hCapture); - HDC hMemDC = CreateCompatibleDC(hScrDC); - // create a bitmap compatible with the screen DC - HBITMAP hBitmap = CreateCompatibleBitmap(hScrDC, width, height); - // select new bitmap into memory DC - SelectObject(hMemDC, hBitmap); - - if (hCapture && hDC) - PrintWindow(hCapture, hMemDC, 0); - else // bitblt screen DC to memory DC - BitBlt(hMemDC, 0, 0, width, height, hScrDC, rect->left, rect->top, CAPTUREBLT | SRCCOPY); - - FIBITMAP *dib = FreeImage_CreateDIBFromHBITMAP(hBitmap); - - // alpha channel from window is always wrong and sometimes even for desktop (Win7, no aero) - // coz GDI do not draw all in alpha mode. - // we have to create our own new alpha channel. - bool bFixAlpha = true; - bool bInvert = false; - HBRUSH hBr = CreateSolidBrush(RGB(255, 255, 255)); // Create a SolidBrush object for non transparent area - HBITMAP hMask = CreateBitmap(width, height, 1, 1, nullptr); // Create monochrome (1 bit) B+W mask bitmap. - HDC hMaskDC = CreateCompatibleDC(nullptr); - SelectBitmap(hMaskDC, hMask); - HRGN hRgn = CreateRectRgn(0, 0, 0, 0); - if (hCapture && GetWindowRgn(hCapture, hRgn) == ERROR) { - if ((GetWindowLongPtr(hCapture, GWL_EXSTYLE)&WS_EX_LAYERED)) { - uint8_t bAlpha = 0; - COLORREF crKey = 0x00000000; - DWORD dwFlags = 0; - if (GetLayeredWindowAttributes(hCapture, &crKey, &bAlpha, &dwFlags)) { - // per window transparency (like fading in a whole window) - if ((dwFlags&LWA_COLORKEY)) { - SetBkColor(hMemDC, crKey); - BitBlt(hMaskDC, 0, 0, width, height, hMemDC, rect->left, rect->top, SRCCOPY); - bInvert = true; - } - else if ((dwFlags&LWA_ALPHA)) { - bFixAlpha = false; - } - } - else { // per-pixel transparency (won't use the WM_PAINT) - bFixAlpha = false; - } - } - else { // not layered - fill the window region - SetRectRgn(hRgn, 0, 0, width, height); - FillRgn(hMaskDC, hRgn, hBr); - } - } - else { - if (!hCapture) SetRectRgn(hRgn, 0, 0, width, height); // client area only, no transparency - FillRgn(hMaskDC, hRgn, hBr); - } - DeleteObject(hRgn); - if (bFixAlpha) { - FIBITMAP* dibMask = FreeImage_CreateDIBFromHBITMAP(hMask); - if (bInvert) FreeImage_Invert(dibMask); - FIBITMAP* dib8 = FreeImage_ConvertTo8Bits(dibMask); - // copy the dib8 alpha mask to dib32 main bitmap - FreeImage_SetChannel(dib, dib8, FICC_ALPHA); - FreeImage_Unload(dibMask); - FreeImage_Unload(dib8); - } - DeleteDC(hMaskDC); - DeleteObject(hMask); - DeleteObject(hBr); - - // clean up - DeleteDC(hMemDC); - DeleteObject(hBitmap); - if (!hDC) - ReleaseDC(nullptr, hScrDC); - -#ifdef _DEBUG - switch (FreeImage_GetImageType(dib)) { - case FIT_UNKNOWN: - OutputDebugStringA("FIBITMAP Type: FIT_UNKNOWN\r\n"); - break; - case FIT_BITMAP: - OutputDebugStringA("FIBITMAP Type: FIT_BITMAP\r\n"); - break; - case FIT_UINT16: - OutputDebugStringA("FIBITMAP Type: FIT_UINT16\r\n"); - break; - case FIT_INT16: - OutputDebugStringA("FIBITMAP Type: FIT_INT16\r\n"); - break; - case FIT_UINT32: - OutputDebugStringA("FIBITMAP Type: FIT_UINT32\r\n"); - break; - case FIT_INT32: - OutputDebugStringA("FIBITMAP Type: FIT_INT32\r\n"); - break; - case FIT_FLOAT: - OutputDebugStringA("FIBITMAP Type: FIT_FLOAT\r\n"); - break; - case FIT_DOUBLE: - OutputDebugStringA("FIBITMAP Type: FIT_DOUBLE\r\n"); - break; - case FIT_COMPLEX: - OutputDebugStringA("FIBITMAP Type: FIT_COMPLEX\r\n"); - break; - case FIT_RGB16: - OutputDebugStringA("FIBITMAP Type: FIT_RGB16\r\n"); - break; - case FIT_RGBA16: - OutputDebugStringA("FIBITMAP Type: FIT_RGBA16\r\n"); - break; - case FIT_RGBF: - OutputDebugStringA("FIBITMAP Type: FIT_RGBF\r\n"); - break; - case FIT_RGBAF: - OutputDebugStringA("FIBITMAP Type: FIT_RGBAF\r\n"); - break; - default: - OutputDebugStringA("FIBITMAP Type: non detectable image type (error)\r\n"); - break; - } - BOOL inf = FreeImage_IsTransparent(dib); - OutputDebugStringA(inf ? "FIBITMAP Transparent: true\r\n" : "FIBITMAP Transparent: false\r\n"); -#endif - return dib; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -char* GetFileNameA(const wchar_t* pszPath) -{ - const wchar_t* slash = wcsrchr(pszPath, '\\'); - if (!slash) slash = wcsrchr(pszPath, '/'); - if (slash) - return mir_u2a(slash + 1); - else - return mir_u2a(pszPath); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -BOOL GetEncoderClsid(wchar_t *wchMimeType, CLSID &clsidEncoder) -{ - UINT uiNum = 0; - UINT uiSize = 0; - BOOL bOk = FALSE; - Gdiplus::GetImageEncodersSize(&uiNum, &uiSize); - if (uiSize > 0) { - Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::ImageCodecInfo*)mir_alloc(uiSize); - if (pImageCodecInfo) { - Gdiplus::GetImageEncoders(uiNum, uiSize, pImageCodecInfo); - for (UINT i = 0; i < uiNum; ++i) { - if (!mir_wstrcmp(pImageCodecInfo[i].MimeType, wchMimeType)) { - clsidEncoder = pImageCodecInfo[i].Clsid; - bOk = TRUE; - } - } - mir_free(pImageCodecInfo); - } - } - return bOk; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void SaveGIF(HBITMAP hBmp, const wchar_t *szFilename) -{ - Gdiplus::GdiplusStartupInput gdiplusStartupInput; - ULONG_PTR gdiplusToken; - Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); - - Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromHBITMAP(hBmp, (HPALETTE)GetStockObject(DEFAULT_PALETTE)); - if (pBitmap) { - // Get the CLSID of the GIF encoder. - CLSID clsidEncoder; - if (GetEncoderClsid(L"image/gif", clsidEncoder)) { - LPWSTR pswFile = mir_wstrdup(szFilename); - pBitmap->Save((const wchar_t*)pswFile, &clsidEncoder, nullptr); - mir_free(pswFile); - } - delete pBitmap; - } - Gdiplus::GdiplusShutdown(gdiplusToken); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void SaveTIF(HBITMAP hBmp, const wchar_t *szFilename) -{ - // http://www.codeproject.com/Messages/1406708/How-to-reduce-the-size-of-an-Image-using-GDIplus.aspx - ULONG_PTR gdiplusToken; - Gdiplus::GdiplusStartupInput gdiplusStartupInput; - Gdiplus::Status stat; - Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); - - Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromHBITMAP(hBmp, (HPALETTE)GetStockObject(DEFAULT_PALETTE)); - if (pBitmap) { - // Get the CLSID of the GIF encoder. - CLSID EncCLSID; - if (GetEncoderClsid(L"image/tiff", EncCLSID)) { - //--- Create a 2-parameter array, for Compression and for Color Bit depth - Gdiplus::EncoderParameters* EncParams = (Gdiplus::EncoderParameters*) malloc(sizeof(Gdiplus::EncoderParameters) + 1 * sizeof(Gdiplus::EncoderParameter)); - // Gdiplus::EncoderParameters pEncoderParameters; - //--- Use LZW Compression instead of Group 4, since it works for color and G4 doesn't - ULONG ulCompression = Gdiplus::EncoderValueCompressionLZW; - ULONG ulColorDepth = 24L; - - EncParams->Count = 2; - EncParams->Parameter[0].Guid = Gdiplus::EncoderCompression; - EncParams->Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong; - EncParams->Parameter[0].NumberOfValues = 1; - EncParams->Parameter[0].Value = &ulCompression; - EncParams->Parameter[1].Guid = Gdiplus::EncoderColorDepth; - EncParams->Parameter[1].Type = Gdiplus::EncoderParameterValueTypeLong; - EncParams->Parameter[1].NumberOfValues = 1; - EncParams->Parameter[1].Value = &ulColorDepth; - - LPWSTR pswFile = mir_wstrdup(szFilename); - stat = pBitmap->Save((const wchar_t*)pswFile, &EncCLSID, EncParams); - mir_free(pswFile); - free(EncParams); - } - delete pBitmap; - } - Gdiplus::GdiplusShutdown(gdiplusToken); -} +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" + +void ComboBox_SelectItem(HWND hCombo, LPARAM data) +{ + for (int i = 0;; i++) { + LPARAM itemData = ComboBox_GetItemData(hCombo, i); + if (itemData == data) { + ComboBox_SetCurSel(hCombo, i); + return; + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MonitorInfoEnum + +static BOOL CALLBACK MonitorInfoEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) +{ + MONITORS* monitors = (MONITORS*)dwData; + ++monitors->count; + monitors->info = (MONITORINFOEX*)mir_realloc(monitors->info, sizeof(MONITORINFOEX)*monitors->count); + monitors->info[monitors->count - 1].cbSize = sizeof(MONITORINFOEX); + if (!GetMonitorInfo(hMonitor, (LPMONITORINFO)(monitors->info + monitors->count - 1))) + return FALSE; // stop enumeration if error + + return TRUE; +} + +size_t MonitorInfoEnum(MONITORINFOEX* &myMonitors, RECT &virtualScreen) +{ + MONITORS tmp = { 0, nullptr }; + if (EnumDisplayMonitors(nullptr, nullptr, MonitorInfoEnumProc, (LPARAM)&tmp)) { + myMonitors = tmp.info; + memset(&virtualScreen, 0, sizeof(virtualScreen)); + for (size_t i = 0; i < tmp.count; ++i) { + UnionRect(&virtualScreen, &virtualScreen, &tmp.info[i].rcMonitor); + } + return tmp.count; + } + + mir_free(tmp.info); + return 0; +} + +FIBITMAP* CreateDIBFromDC(HDC hDC, const RECT* rect, HWND hCapture = nullptr); + +///////////////////////////////////////////////////////////////////////////////////////// +// capture window as FIBITMAP - caller must FreeImage_Unload(dib) + +FIBITMAP* CaptureWindow(HWND hCapture, BOOL bClientArea, BOOL bIndirectCapture) +{ + FIBITMAP* dib; + HWND hForegroundWin; + RECT rect; // cropping rect + + if (!hCapture || !IsWindow(hCapture)) + return nullptr; + + hForegroundWin = GetForegroundWindow(); // old foreground window + SetForegroundWindow(hCapture); // force target foreground + BringWindowToTop(hCapture); // bring it to top as well + + // redraw window to prevent runtime artifacts in picture + UpdateWindow(hCapture); + + HWND hParent = GetAncestor(hCapture, GA_PARENT); + if (hParent && !IsChild(hParent, hCapture)) + hParent = nullptr; + if (bIndirectCapture) { + intptr_t wastopmost = GetWindowLongPtr(hCapture, GWL_EXSTYLE)&WS_EX_TOPMOST; + if (!wastopmost) + SetWindowPos(hCapture, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + if (bClientArea) { + GetClientRect(hCapture, &rect); + ClientToScreen(hCapture, (POINT*)&rect); + rect.right += rect.left; rect.bottom += rect.top; + } + else + GetWindowRect(hCapture, &rect); + dib = CaptureMonitor(nullptr, &rect); + if (!wastopmost) + SetWindowPos(hCapture, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + else { + HDC hDCsrc; + GetWindowRect(hCapture, &rect); + if (hParent) + hDCsrc = GetDC(hCapture); // hCapture is part of a window, capture that + else + hDCsrc = GetWindowDC(hCapture); // entire window w/ title bar + rect.right = ABS(rect.right - rect.left); + rect.bottom = ABS(rect.bottom - rect.top); + rect.left = rect.top = 0; + // capture window and get FIBITMAP + dib = CreateDIBFromDC(hDCsrc, &rect, hCapture); + ReleaseDC(hCapture, hDCsrc); + + // we could capture directly, but doing so breaks GetWindowRgn() and also includes artifacts... + if (bClientArea) { + GetWindowRect(hCapture, &rect); + RECT rectCA; GetClientRect(hCapture, &rectCA); + ClientToScreen(hCapture, (POINT*)&rectCA); + rectCA.left = ABS(rectCA.left - rect.left); + rectCA.top = ABS(rectCA.top - rect.top); + rectCA.right += rectCA.left; rectCA.bottom += rectCA.top; + + // crop the window to ClientArea + FIBITMAP* dibClient = FreeImage_Copy(dib, rectCA.left, rectCA.top, rectCA.right, rectCA.bottom); + FreeImage_Unload(dib); + dib = dibClient; + } + } + + // restore previous foreground window + if (hForegroundWin) { + SetForegroundWindow(hForegroundWin); + BringWindowToTop(hForegroundWin); + } + return dib; +} + +FIBITMAP* CaptureMonitor(const wchar_t* szDevice, const RECT* cropRect/*=NULL*/) +{ + HDC hScrDC; + RECT rect; + + // get screen resolution + if (!szDevice) { + hScrDC = CreateDC(L"DISPLAY", nullptr, nullptr, nullptr); + rect.left = GetSystemMetrics(SM_XVIRTUALSCREEN); + rect.top = GetSystemMetrics(SM_YVIRTUALSCREEN); + rect.right = GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN); + rect.bottom = GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN); + } + else { + hScrDC = CreateDC(szDevice, nullptr, nullptr, nullptr); + rect.left = rect.top = 0; + rect.right = GetDeviceCaps(hScrDC, HORZRES); + rect.bottom = GetDeviceCaps(hScrDC, VERTRES); + } + if (cropRect) { + if (cropRect->left > rect.left) rect.left = cropRect->left; + if (cropRect->top > rect.top) rect.top = cropRect->top; + if (cropRect->right < rect.right) rect.right = cropRect->right; + if (cropRect->bottom < rect.bottom) rect.bottom = cropRect->bottom; + } + + FIBITMAP *dib = CreateDIBFromDC(hScrDC, &rect); + ReleaseDC(nullptr, hScrDC); + return dib; +} + +FIBITMAP* CreateDIBFromDC(HDC hDC, const RECT* rect, HWND hCapture/*=NULL*/) +{ + long width = rect->right - rect->left; + long height = rect->bottom - rect->top; + + // create a DC for the screen and create + // a memory DC compatible to screen DC + HDC hScrDC = hDC; + if (!hScrDC) + hScrDC = GetDC(hCapture); + HDC hMemDC = CreateCompatibleDC(hScrDC); + // create a bitmap compatible with the screen DC + HBITMAP hBitmap = CreateCompatibleBitmap(hScrDC, width, height); + // select new bitmap into memory DC + SelectObject(hMemDC, hBitmap); + + if (hCapture && hDC) + PrintWindow(hCapture, hMemDC, 0); + else // bitblt screen DC to memory DC + BitBlt(hMemDC, 0, 0, width, height, hScrDC, rect->left, rect->top, CAPTUREBLT | SRCCOPY); + + FIBITMAP *dib = FreeImage_CreateDIBFromHBITMAP(hBitmap); + + // alpha channel from window is always wrong and sometimes even for desktop (Win7, no aero) + // coz GDI do not draw all in alpha mode. + // we have to create our own new alpha channel. + bool bFixAlpha = true; + bool bInvert = false; + HBRUSH hBr = CreateSolidBrush(RGB(255, 255, 255)); // Create a SolidBrush object for non transparent area + HBITMAP hMask = CreateBitmap(width, height, 1, 1, nullptr); // Create monochrome (1 bit) B+W mask bitmap. + HDC hMaskDC = CreateCompatibleDC(nullptr); + SelectBitmap(hMaskDC, hMask); + HRGN hRgn = CreateRectRgn(0, 0, 0, 0); + if (hCapture && GetWindowRgn(hCapture, hRgn) == ERROR) { + if ((GetWindowLongPtr(hCapture, GWL_EXSTYLE)&WS_EX_LAYERED)) { + uint8_t bAlpha = 0; + COLORREF crKey = 0x00000000; + DWORD dwFlags = 0; + if (GetLayeredWindowAttributes(hCapture, &crKey, &bAlpha, &dwFlags)) { + // per window transparency (like fading in a whole window) + if ((dwFlags&LWA_COLORKEY)) { + SetBkColor(hMemDC, crKey); + BitBlt(hMaskDC, 0, 0, width, height, hMemDC, rect->left, rect->top, SRCCOPY); + bInvert = true; + } + else if ((dwFlags&LWA_ALPHA)) { + bFixAlpha = false; + } + } + else { // per-pixel transparency (won't use the WM_PAINT) + bFixAlpha = false; + } + } + else { // not layered - fill the window region + SetRectRgn(hRgn, 0, 0, width, height); + FillRgn(hMaskDC, hRgn, hBr); + } + } + else { + if (!hCapture) SetRectRgn(hRgn, 0, 0, width, height); // client area only, no transparency + FillRgn(hMaskDC, hRgn, hBr); + } + DeleteObject(hRgn); + if (bFixAlpha) { + FIBITMAP* dibMask = FreeImage_CreateDIBFromHBITMAP(hMask); + if (bInvert) FreeImage_Invert(dibMask); + FIBITMAP* dib8 = FreeImage_ConvertTo8Bits(dibMask); + // copy the dib8 alpha mask to dib32 main bitmap + FreeImage_SetChannel(dib, dib8, FICC_ALPHA); + FreeImage_Unload(dibMask); + FreeImage_Unload(dib8); + } + DeleteDC(hMaskDC); + DeleteObject(hMask); + DeleteObject(hBr); + + // clean up + DeleteDC(hMemDC); + DeleteObject(hBitmap); + if (!hDC) + ReleaseDC(nullptr, hScrDC); + +#ifdef _DEBUG + switch (FreeImage_GetImageType(dib)) { + case FIT_UNKNOWN: + OutputDebugStringA("FIBITMAP Type: FIT_UNKNOWN\r\n"); + break; + case FIT_BITMAP: + OutputDebugStringA("FIBITMAP Type: FIT_BITMAP\r\n"); + break; + case FIT_UINT16: + OutputDebugStringA("FIBITMAP Type: FIT_UINT16\r\n"); + break; + case FIT_INT16: + OutputDebugStringA("FIBITMAP Type: FIT_INT16\r\n"); + break; + case FIT_UINT32: + OutputDebugStringA("FIBITMAP Type: FIT_UINT32\r\n"); + break; + case FIT_INT32: + OutputDebugStringA("FIBITMAP Type: FIT_INT32\r\n"); + break; + case FIT_FLOAT: + OutputDebugStringA("FIBITMAP Type: FIT_FLOAT\r\n"); + break; + case FIT_DOUBLE: + OutputDebugStringA("FIBITMAP Type: FIT_DOUBLE\r\n"); + break; + case FIT_COMPLEX: + OutputDebugStringA("FIBITMAP Type: FIT_COMPLEX\r\n"); + break; + case FIT_RGB16: + OutputDebugStringA("FIBITMAP Type: FIT_RGB16\r\n"); + break; + case FIT_RGBA16: + OutputDebugStringA("FIBITMAP Type: FIT_RGBA16\r\n"); + break; + case FIT_RGBF: + OutputDebugStringA("FIBITMAP Type: FIT_RGBF\r\n"); + break; + case FIT_RGBAF: + OutputDebugStringA("FIBITMAP Type: FIT_RGBAF\r\n"); + break; + default: + OutputDebugStringA("FIBITMAP Type: non detectable image type (error)\r\n"); + break; + } + BOOL inf = FreeImage_IsTransparent(dib); + OutputDebugStringA(inf ? "FIBITMAP Transparent: true\r\n" : "FIBITMAP Transparent: false\r\n"); +#endif + return dib; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +char* GetFileNameA(const wchar_t* pszPath) +{ + const wchar_t* slash = wcsrchr(pszPath, '\\'); + if (!slash) slash = wcsrchr(pszPath, '/'); + if (slash) + return mir_u2a(slash + 1); + else + return mir_u2a(pszPath); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +BOOL GetEncoderClsid(wchar_t *wchMimeType, CLSID &clsidEncoder) +{ + UINT uiNum = 0; + UINT uiSize = 0; + BOOL bOk = FALSE; + Gdiplus::GetImageEncodersSize(&uiNum, &uiSize); + if (uiSize > 0) { + Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::ImageCodecInfo*)mir_alloc(uiSize); + if (pImageCodecInfo) { + Gdiplus::GetImageEncoders(uiNum, uiSize, pImageCodecInfo); + for (UINT i = 0; i < uiNum; ++i) { + if (!mir_wstrcmp(pImageCodecInfo[i].MimeType, wchMimeType)) { + clsidEncoder = pImageCodecInfo[i].Clsid; + bOk = TRUE; + } + } + mir_free(pImageCodecInfo); + } + } + return bOk; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void SaveGIF(HBITMAP hBmp, const wchar_t *szFilename) +{ + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); + + Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromHBITMAP(hBmp, (HPALETTE)GetStockObject(DEFAULT_PALETTE)); + if (pBitmap) { + // Get the CLSID of the GIF encoder. + CLSID clsidEncoder; + if (GetEncoderClsid(L"image/gif", clsidEncoder)) { + LPWSTR pswFile = mir_wstrdup(szFilename); + pBitmap->Save((const wchar_t*)pswFile, &clsidEncoder, nullptr); + mir_free(pswFile); + } + delete pBitmap; + } + Gdiplus::GdiplusShutdown(gdiplusToken); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void SaveTIF(HBITMAP hBmp, const wchar_t *szFilename) +{ + // http://www.codeproject.com/Messages/1406708/How-to-reduce-the-size-of-an-Image-using-GDIplus.aspx + ULONG_PTR gdiplusToken; + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + Gdiplus::Status stat; + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr); + + Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromHBITMAP(hBmp, (HPALETTE)GetStockObject(DEFAULT_PALETTE)); + if (pBitmap) { + // Get the CLSID of the GIF encoder. + CLSID EncCLSID; + if (GetEncoderClsid(L"image/tiff", EncCLSID)) { + //--- Create a 2-parameter array, for Compression and for Color Bit depth + Gdiplus::EncoderParameters* EncParams = (Gdiplus::EncoderParameters*) malloc(sizeof(Gdiplus::EncoderParameters) + 1 * sizeof(Gdiplus::EncoderParameter)); + // Gdiplus::EncoderParameters pEncoderParameters; + //--- Use LZW Compression instead of Group 4, since it works for color and G4 doesn't + ULONG ulCompression = Gdiplus::EncoderValueCompressionLZW; + ULONG ulColorDepth = 24L; + + EncParams->Count = 2; + EncParams->Parameter[0].Guid = Gdiplus::EncoderCompression; + EncParams->Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong; + EncParams->Parameter[0].NumberOfValues = 1; + EncParams->Parameter[0].Value = &ulCompression; + EncParams->Parameter[1].Guid = Gdiplus::EncoderColorDepth; + EncParams->Parameter[1].Type = Gdiplus::EncoderParameterValueTypeLong; + EncParams->Parameter[1].NumberOfValues = 1; + EncParams->Parameter[1].Value = &ulColorDepth; + + LPWSTR pswFile = mir_wstrdup(szFilename); + stat = pBitmap->Save((const wchar_t*)pswFile, &EncCLSID, EncParams); + mir_free(pswFile); + free(EncParams); + } + delete pBitmap; + } + Gdiplus::GdiplusShutdown(gdiplusToken); +} diff --git a/plugins/SendScreenshotPlus/src/Utils.h b/plugins/SendScreenshotPlus/src/Utils.h index 89dd2f614e..df736da08f 100644 --- a/plugins/SendScreenshotPlus/src/Utils.h +++ b/plugins/SendScreenshotPlus/src/Utils.h @@ -1,73 +1,73 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef UTILSH -#define UTILSH - -#define SPP_USERPANE 1 - -#define ABS(x) ((x)<0?-(x):(x)) - -struct MONITORS -{ - size_t count; - MONITORINFOEX* info; -}; - -extern HWND g_hCapture; -extern HBITMAP g_hBitmap, g_hbmMask; - -///////////////////////////////////////////////////////////////////////////////////////// - -size_t MonitorInfoEnum(MONITORINFOEX* &myMonitors, RECT &virtualScreen); - -FIBITMAP* CaptureWindow(HWND hCapture, BOOL bClientArea, BOOL bIndirectCapture); -FIBITMAP* CaptureMonitor(const wchar_t *pwszDevice, const RECT *cropRect = nullptr); - -char* GetFileNameA(const wchar_t *pwszPath); - -BOOL GetEncoderClsid(wchar_t *wchMimeType, CLSID &clsidEncoder); - -void SaveGIF(HBITMAP hBmp, const wchar_t *pwszFilename); -void SaveTIF(HBITMAP hBmp, const wchar_t *pwszFilename); - -///////////////////////////////////////////////////////////////////////////////////////// - -class EventHandle -{ - HANDLE _hEvent; -public: - inline EventHandle() { _hEvent = CreateEvent(nullptr, 0, 0, nullptr); } - inline ~EventHandle() { CloseHandle(_hEvent); } - inline void Set() { SetEvent(_hEvent); } - inline void Wait() { WaitForSingleObject(_hEvent, INFINITE); } - inline void Wait(uint32_t dwMilliseconds) { WaitForSingleObject(_hEvent, dwMilliseconds); } - inline operator HANDLE() { return _hEvent; } -}; - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef UTILSH +#define UTILSH + +#define SPP_USERPANE 1 + +#define ABS(x) ((x)<0?-(x):(x)) + +struct MONITORS +{ + size_t count; + MONITORINFOEX* info; +}; + +extern HWND g_hCapture; +extern HBITMAP g_hBitmap, g_hbmMask; + +///////////////////////////////////////////////////////////////////////////////////////// + +size_t MonitorInfoEnum(MONITORINFOEX* &myMonitors, RECT &virtualScreen); + +FIBITMAP* CaptureWindow(HWND hCapture, BOOL bClientArea, BOOL bIndirectCapture); +FIBITMAP* CaptureMonitor(const wchar_t *pwszDevice, const RECT *cropRect = nullptr); + +char* GetFileNameA(const wchar_t *pwszPath); + +BOOL GetEncoderClsid(wchar_t *wchMimeType, CLSID &clsidEncoder); + +void SaveGIF(HBITMAP hBmp, const wchar_t *pwszFilename); +void SaveTIF(HBITMAP hBmp, const wchar_t *pwszFilename); + +///////////////////////////////////////////////////////////////////////////////////////// + +class EventHandle +{ + HANDLE _hEvent; +public: + inline EventHandle() { _hEvent = CreateEvent(nullptr, 0, 0, nullptr); } + inline ~EventHandle() { CloseHandle(_hEvent); } + inline void Set() { SetEvent(_hEvent); } + inline void Wait() { WaitForSingleObject(_hEvent, INFINITE); } + inline void Wait(uint32_t dwMilliseconds) { WaitForSingleObject(_hEvent, dwMilliseconds); } + inline operator HANDLE() { return _hEvent; } +}; + +#endif diff --git a/plugins/SendScreenshotPlus/src/ctrl_button.h b/plugins/SendScreenshotPlus/src/ctrl_button.h index 42ac4762a7..d2672c79d7 100644 --- a/plugins/SendScreenshotPlus/src/ctrl_button.h +++ b/plugins/SendScreenshotPlus/src/ctrl_button.h @@ -1,34 +1,34 @@ -/* -imported from UserinfoEx plugin for Miranda NG -Copyright: -© 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _UINFOEX_BOTTONS_H_INCLUDED_ -#define _UINFOEX_BOTTONS_H_INCLUDED_ 1 - -void CtrlButtonLoadModule(); -void CtrlButtonUnloadModule(); - +/* +imported from UserinfoEx plugin for Miranda NG +Copyright: +© 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _UINFOEX_BOTTONS_H_INCLUDED_ +#define _UINFOEX_BOTTONS_H_INCLUDED_ 1 + +void CtrlButtonLoadModule(); +void CtrlButtonUnloadModule(); + #endif /* _UINFOEX_BOTTONS_H_INCLUDED_ */ \ No newline at end of file diff --git a/plugins/SendScreenshotPlus/src/dlg_msgbox.cpp b/plugins/SendScreenshotPlus/src/dlg_msgbox.cpp index e64e686215..b0aa0bc04d 100644 --- a/plugins/SendScreenshotPlus/src/dlg_msgbox.cpp +++ b/plugins/SendScreenshotPlus/src/dlg_msgbox.cpp @@ -1,714 +1,714 @@ -/* -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright: -© 2012-22 Miranda NG team (https://miranda-ng.org) -© 2006-10 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -// SendSS compatibility: -#include "stdafx.h" -#define ghInst g_plugin.getInst() -#define myGlobals g_myGlobals -#define MODNAME MODULENAME -#define ICO_COMMON_MAIN 0xFFFF -#define ICO_DLG_DETAILS 0xFFFF - -HICON Skin_GetIcon_SendSS(unsigned short id) -{ - if(id==0xFFFF) - return GetIcon(ICO_MAIN); - return GetIconBtn(id); -} -#define IcoLib_GetIcon Skin_GetIcon_SendSS -// original UserInfoEx codebase (almost): - -typedef struct _MSGPOPUPDATA -{ - POPUPACTION pa[3]; - HWND hDialog; -} MSGPOPUPDATA, *LPMSGPOPUPDATA; - -/** - * This helper function moves and resizes a dialog box's control element. - * - * @param hDlg - the dialog box's window handle - * @param idCtrl - the identication number of the control to move - * @param dx -´number of pixels to horizontal move the control - * @param dy - number of pixels to vertical move the control - * @param dw - number of pixels to horizontal resize the control - * @param dh - number of pixels to vertical resize the control - * - * @return nothing - **/ -static FORCEINLINE void MoveCtrl(HWND hDlg, int idCtrl, int dx, int dy, int dw, int dh) -{ - RECT ws; - HWND hCtrl = GetDlgItem(hDlg, idCtrl); - GetWindowRect(hCtrl, &ws); - OffsetRect(&ws, dx, dy); - MoveWindow(hCtrl, ws.left, ws.top, ws.right - ws.left + dw, ws.bottom - ws.top + dh, FALSE); -} - -/** -* This function loads the icon to display for the current message. -* -* @param pMsgBox - pointer to a MSGBOX structure, with information about the message to display. -* -* @retval HICON - The function returns an icon to display with the message. -* @retval NULL - There is no icon for the message. -**/ -static HICON MsgLoadIcon(LPMSGBOX pMsgBox) -{ - HICON hIcon; - - // load the desired status icon - switch (pMsgBox->uType & MB_ICONMASK) { - case MB_ICON_OTHER: // custom icon defined by caller function - hIcon = pMsgBox->hiMsg; - break; - - // default windows icons - case MB_ICON_ERROR: - case MB_ICON_QUESTION: - case MB_ICON_WARNING: - case MB_ICON_INFO: - { - LPCTSTR ico[] = { nullptr, IDI_ERROR, IDI_QUESTION, IDI_WARNING, IDI_INFORMATION }; - hIcon = LoadIcon(nullptr, ico[MB_ICON_INDEX(pMsgBox->uType)]); - } - break; - - // no icon - default: - hIcon = nullptr; - } - return hIcon; -} - -/** - * This function fills a given POPUPACTION structure with the data of a given message id, - * which is normally used by the message box. This is required to let the user interact - * with a popup in the same way as with a normal message dialog box. - * - * @param pa - reference to a POPUPACTION structure to fill - * @param id - the message id - * @param result - This parameter is passed to the POPUPACTION structure as is. - * - * @return nothing - **/ -static void MakePopupAction(POPUPACTION &pa, int id) -{ - pa.cbSize = sizeof(POPUPACTION); - pa.flags = PAF_ENABLED; - pa.wParam = MAKEWORD(id, BN_CLICKED); - pa.lParam = 0; - - switch (id) { - case IDOK: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); - mir_strcpy(pa.lpzTitle, MODNAME"/Ok"); - break; - - case IDCLOSE: - case IDCANCEL: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); - mir_strcpy(pa.lpzTitle, MODNAME"/Cancel"); - break; - - case IDABORT: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); - mir_strcpy(pa.lpzTitle, MODNAME"/Abort"); - break; - - case IDRETRY: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_UPDATE); - mir_strcpy(pa.lpzTitle, MODNAME"/Retry"); - break; - - case IDIGNORE: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); - mir_strcpy(pa.lpzTitle, MODNAME"/Ignore"); - break; - - case IDYES: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); - mir_strcpy(pa.lpzTitle, MODNAME"/Yes"); - break; - - case IDNO: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); - mir_strcpy(pa.lpzTitle, MODNAME"/No"); - break; - - case IDHELP: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); - mir_strcpy(pa.lpzTitle, MODNAME"/Help"); - break; - - case IDALL: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); - mir_strcpy(pa.lpzTitle, MODNAME"/All"); - break; - - case IDNONE: - pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); - mir_strcpy(pa.lpzTitle, MODNAME"/None"); - } -} - -/** - * This is the message procedure for my nice looking message box - * - * @param hDlg - window handle - * @param uMsg - message to handle - * @param wParam - message specific parameter - * @param lParam - message specific parameter - * - * @return TRUE, FALSE, IDOK, IDYES, IDALL, IDNO or IDCANCEL - **/ -static INT_PTR CALLBACK MsgBoxProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static int retOk = IDOK; - static int retAll = IDALL; - static int retNon = IDNONE; - static int retCancel = IDCANCEL; - - switch (uMsg) { - case WM_INITDIALOG: - { - LPMSGBOX pMsgBox = (LPMSGBOX)lParam; - if (PtrIsValid(pMsgBox)) { - int icoWidth = 0; - int InfoBarHeight = 0; - HFONT hNormalFont; - - hNormalFont = (HFONT)SendDlgItemMessage(hDlg, TXT_NAME, WM_GETFONT, 0, 0); - if (pMsgBox->uType & MB_INFOBAR) { - LOGFONT lf; - - // set bold font for name in description area - GetObject(hNormalFont, sizeof(lf), &lf); - lf.lfWeight = FW_BOLD; - hNormalFont = CreateFontIndirect(&lf); - - // set infobar's textfont - SendDlgItemMessage(hDlg, TXT_NAME, WM_SETFONT, (WPARAM)hNormalFont, 0); - - // set infobar's logo icon - SendDlgItemMessage(hDlg, ICO_DLGLOGO, STM_SETIMAGE, IMAGE_ICON, - (pMsgBox->hiLogo ? (LPARAM)pMsgBox->hiLogo : (LPARAM)IcoLib_GetIcon(ICO_DLG_DETAILS))); - - // enable headerbar - ShowWindow(GetDlgItem(hDlg, TXT_NAME), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, ICO_DLGLOGO), SW_SHOW); - } - else { - RECT rc; - GetClientRect(GetDlgItem(hDlg, TXT_NAME), &rc); - InfoBarHeight = rc.bottom; - - if (pMsgBox->hiLogo) - SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)pMsgBox->hiLogo); - } - - // draw the desired status icon - HICON hIcon = MsgLoadIcon(pMsgBox); - if (hIcon) - SendDlgItemMessage(hDlg, ICO_MSGDLG, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); - else { - RECT ws; - GetWindowRect(GetDlgItem(hDlg, ICO_MSGDLG), &ws); - icoWidth = ws.right - ws.left; - ShowWindow(GetDlgItem(hDlg, ICO_MSGDLG), SW_HIDE); - } - - // resize the messagebox and reorganize the buttons - if (HDC hDC = GetDC(hDlg)) { - POINT mpt = { 0, 0 }; - RECT ws = { 0, 0, 0, 0 }; - int txtWidth = 0, txtHeight = 0, needX, needY; - RECT rcDlg; - SIZE ts; - LPTSTR h, rs; - - SelectObject(hDC, hNormalFont); - // get message text width and height - if (pMsgBox->ptszMsg) for (rs = h = pMsgBox->ptszMsg;; ++h) { - if (*h == '\n' || !*h) { - GetTextExtentPoint32(hDC, rs, h - rs, &ts); - if (ts.cx > txtWidth) - txtWidth = ts.cx; - txtHeight += ts.cy; - if (!*h) - break; - rs = h + 1; - } - } - // increase width if info text requires more - if ((pMsgBox->uType&MB_INFOBAR) && pMsgBox->ptszInfoText && *pMsgBox->ptszInfoText) { - int multiline = 0; - RECT rcico; GetClientRect(GetDlgItem(hDlg, ICO_DLGLOGO), &rcico); - rcico.right = rcico.right * 100 / 66; // padding - for (rs = h = pMsgBox->ptszInfoText;; ++h) { - if (*h == '\n' || !*h) { - GetTextExtentPoint32(hDC, rs, h - rs, &ts); - ts.cx += rcico.right; - if (ts.cx > txtWidth) - txtWidth = ts.cx; - if (!*h) - break; - rs = h + 1; - ++multiline; - } - } - if (!multiline) - SetWindowLongPtr(GetDlgItem(hDlg, TXT_NAME), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hDlg, TXT_NAME), GWL_STYLE) | SS_CENTERIMAGE); - } - ReleaseDC(hDlg, hDC); - - // calc new dialog size - GetWindowRect(hDlg, &rcDlg); - GetWindowRect(GetDlgItem(hDlg, TXT_MESSAGE), &ws); - needX = txtWidth - (ws.right - ws.left) - icoWidth; - needY = max(0, txtHeight - (ws.bottom - ws.top) + 5); - rcDlg.left -= needX / 2; rcDlg.right += needX / 2; - rcDlg.top -= (needY - InfoBarHeight) / 2; rcDlg.bottom += (needY - InfoBarHeight) / 2; - - // resize dialog window - MoveWindow(hDlg, rcDlg.left, rcDlg.top, rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top, FALSE); - ClientToScreen(hDlg, &mpt); - - MoveCtrl(hDlg, STATIC_WHITERECT, -mpt.x, -mpt.y, needX, needY - InfoBarHeight); - MoveCtrl(hDlg, TXT_NAME, -mpt.x, -mpt.y, needX, 0); - MoveCtrl(hDlg, ICO_DLGLOGO, -mpt.x + needX, -mpt.y, 0, 0); - MoveCtrl(hDlg, ICO_MSGDLG, -mpt.x, -mpt.y - InfoBarHeight, 0, 0); - MoveCtrl(hDlg, TXT_MESSAGE, -mpt.x - icoWidth, -mpt.y - InfoBarHeight, needX, needY); - MoveCtrl(hDlg, STATIC_LINE2, -mpt.x, -mpt.y + needY - InfoBarHeight, needX, 0); - - // Do pushbutton positioning - RECT rcOk, rcAll, rcNone, rcCancel; - - // get button rectangles - GetWindowRect(GetDlgItem(hDlg, IDOK), &rcOk); - OffsetRect(&rcOk, -mpt.x, -mpt.y + needY - InfoBarHeight); - - GetWindowRect(GetDlgItem(hDlg, IDALL), &rcAll); - OffsetRect(&rcAll, -mpt.x, -mpt.y + needY - InfoBarHeight); - - GetWindowRect(GetDlgItem(hDlg, IDNONE), &rcNone); - OffsetRect(&rcNone, -mpt.x, -mpt.y + needY - InfoBarHeight); - - GetWindowRect(GetDlgItem(hDlg, IDCANCEL), &rcCancel); - OffsetRect(&rcCancel, -mpt.x, -mpt.y + needY - InfoBarHeight); - - LONG okWidth = rcOk.right - rcOk.left; - LONG allWidth = rcAll.right - rcAll.left; - LONG noneWidth = rcNone.right - rcNone.left; - LONG caWidth = rcCancel.right - rcCancel.left; - LONG dlgMid = (rcDlg.right - rcDlg.left) / 2; - - // load button configuration - switch (MB_TYPE(pMsgBox->uType)) { - case MB_OK: - rcOk.left = dlgMid - (okWidth / 2); - rcOk.right = rcOk.left + okWidth; - ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); - break; - - case MB_OKCANCEL: - retOk = IDRETRY; - SetDlgItemText(hDlg, IDOK, LPGENW("OK")); - retCancel = IDCANCEL; - SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); - rcOk.left = dlgMid - okWidth - 10; - rcOk.right = rcOk.left + okWidth; - rcCancel.left = dlgMid + 10; - rcCancel.right = rcCancel.left + caWidth; - ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); - break; - - case MB_RETRYCANCEL: - retOk = IDRETRY; - SetDlgItemText(hDlg, IDOK, LPGENW("Retry")); - retCancel = IDCANCEL; - SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); - rcOk.left = dlgMid - okWidth - 10; - rcOk.right = rcOk.left + okWidth; - rcCancel.left = dlgMid + 10; - rcCancel.right = rcCancel.left + caWidth; - ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); - break; - - case MB_YESNO: - retOk = IDYES; - SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); - retCancel = IDNO; - SetDlgItemText(hDlg, IDCANCEL, LPGENW("No")); - rcOk.left = dlgMid - okWidth - 10; - rcOk.right = rcOk.left + okWidth; - rcCancel.left = dlgMid + 10; - rcCancel.right = rcCancel.left + caWidth; - ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); - break; - - case MB_ABORTRETRYIGNORE: - retOk = IDABORT; - SetDlgItemText(hDlg, IDOK, LPGENW("Abort")); - retAll = IDABORT; - SetDlgItemText(hDlg, IDALL, LPGENW("Retry")); - retCancel = IDCANCEL; - SetDlgItemText(hDlg, IDCANCEL, LPGENW("Ignore")); - rcAll.left = dlgMid - (allWidth / 2); - rcAll.right = rcAll.left + allWidth; - rcOk.left = rcAll.left - okWidth - 5; - rcOk.right = rcOk.left + okWidth; - rcCancel.left = rcAll.right + 5; - rcCancel.right = rcCancel.left + caWidth; - ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); - break; - - case MB_YESNOCANCEL: - retOk = IDYES; - SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); - retAll = IDNO; - SetDlgItemText(hDlg, IDALL, LPGENW("No")); - retCancel = IDCANCEL; - SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); - rcAll.left = dlgMid - (allWidth / 2); - rcAll.right = rcAll.left + allWidth; - rcOk.left = rcAll.left - okWidth - 5; - rcOk.right = rcOk.left + okWidth; - rcCancel.left = rcAll.right + 5; - rcCancel.right = rcCancel.left + caWidth; - ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); - break; - - case MB_YESALLNO: - retOk = IDYES; - SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); - retAll = IDALL; - SetDlgItemText(hDlg, IDALL, LPGENW("All")); - SetDlgItemText(hDlg, IDNONE, LPGENW("None")); - retCancel = IDNO; - SetDlgItemText(hDlg, IDCANCEL, LPGENW("No")); - rcCancel.right = rcDlg.right - rcDlg.left - 10; - rcCancel.left = rcCancel.right - caWidth; - rcNone.right = rcCancel.left - 5; - rcNone.left = rcNone.right - noneWidth; - rcAll.right = rcNone.left - 5; - rcAll.left = rcAll.right - allWidth; - rcOk.right = rcAll.left - 5; - rcOk.left = rcOk.right - okWidth; - // show buttons - ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDNONE), SW_SHOW); - ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); - break; - - default: - rcOk.left = dlgMid - (okWidth / 2); - rcOk.right = rcOk.left + okWidth; - } - - MoveWindow(GetDlgItem(hDlg, IDOK), rcOk.left, rcOk.top, rcOk.right - rcOk.left, rcOk.bottom - rcOk.top, FALSE); - MoveWindow(GetDlgItem(hDlg, IDALL), rcAll.left, rcAll.top, rcAll.right - rcAll.left, rcAll.bottom - rcAll.top, FALSE); - MoveWindow(GetDlgItem(hDlg, IDNONE), rcNone.left, rcNone.top, rcNone.right - rcNone.left, rcNone.bottom - rcNone.top, FALSE); - MoveWindow(GetDlgItem(hDlg, IDCANCEL), rcCancel.left, rcCancel.top, rcCancel.right - rcCancel.left, rcCancel.bottom - rcCancel.top, FALSE); - } - - // set text's - SetWindowText(hDlg, pMsgBox->ptszTitle); - SetDlgItemText(hDlg, TXT_NAME, pMsgBox->ptszInfoText); - SetDlgItemText(hDlg, TXT_MESSAGE, pMsgBox->ptszMsg); - - TranslateDialogDefault(hDlg); - return TRUE; - } - } - break; - - case WM_CTLCOLORSTATIC: - switch (GetWindowLongPtr((HWND)lParam, GWLP_ID)) { - case STATIC_WHITERECT: - case ICO_DLGLOGO: - case ICO_MSGDLG: - case TXT_MESSAGE: - case TXT_NAME: - SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); - return GetSysColor(COLOR_WINDOW); - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - EndDialog(hDlg, retOk); - break; - case IDCANCEL: - EndDialog(hDlg, retCancel); - break; - case IDALL: - EndDialog(hDlg, retAll); - break; - case IDNONE: - EndDialog(hDlg, retNon); - } - break; - - case WM_DESTROY: - DeleteObject((HFONT)SendDlgItemMessage(hDlg, TXT_NAME, WM_GETFONT, 0, 0)); - break; - } - return FALSE; -} - -/** -* Dummi modal MsgBox for popup, -* this set call function in wait stait and do not freece miranda main thread -* the window is outside the desktop -*/ -static INT_PTR CALLBACK MsgBoxPop(HWND hDlg, UINT uMsg, WPARAM, LPARAM lParam) -{ - switch (uMsg) { - case WM_INITDIALOG: - LPMSGBOX pMsgBox = (LPMSGBOX)lParam; - - MoveWindow(hDlg, -10, -10, 0, 0, FALSE); - LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)mir_alloc(sizeof(MSGPOPUPDATA)); - if (pmpd) { - POPUPDATAW ppd; - ppd.lchContact = NULL; // (HANDLE)wParam; - // icon - ppd.lchIcon = MsgLoadIcon(pMsgBox); - mir_wstrncpy(ppd.lpwzContactName, pMsgBox->ptszTitle, _countof(ppd.lpwzContactName)); - mir_wstrncpy(ppd.lpwzText, pMsgBox->ptszMsg, _countof(ppd.lpwzText)); - - // CALLBAC Proc - ppd.PluginWindowProc = PopupProc; - ppd.PluginData = pmpd; - ppd.iSeconds = -1; - ppd.lpActions = pmpd->pa; - - // set color of popup - switch (pMsgBox->uType & MB_ICONMASK) { - case MB_ICON_ERROR: - ppd.colorBack = RGB(200, 10, 0); - ppd.colorText = RGB(255, 255, 255); - break; - - case MB_ICON_WARNING: - ppd.colorBack = RGB(200, 100, 0); - ppd.colorText = RGB(255, 255, 255); - break; - - default: - if (pMsgBox->uType & MB_CUSTOMCOLOR) { - ppd.colorBack = pMsgBox->colorBack; - ppd.colorText = pMsgBox->colorText; - } - } - - // handle for MakePopupAction - pmpd->hDialog = hDlg; - - // active buttons - switch (MB_TYPE(pMsgBox->uType)) { - case MB_OK: - MakePopupAction(pmpd->pa[ppd.actionCount++], IDOK); - break; - - case MB_OKCANCEL: - MakePopupAction(pmpd->pa[ppd.actionCount++], IDOK); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); - break; - - case MB_RETRYCANCEL: - MakePopupAction(pmpd->pa[ppd.actionCount++], IDRETRY); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); - break; - - case MB_YESNO: - MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); - break; - - case MB_ABORTRETRYIGNORE: - MakePopupAction(pmpd->pa[ppd.actionCount++], IDABORT); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDRETRY); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDIGNORE); - break; - - case MB_YESNOCANCEL: - MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); - break; - - case MB_YESALLNO: - MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDALL); - MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); - break; - } - - // create popup - PUAddPopupW(&ppd); - if (MB_TYPE(pMsgBox->uType) == MB_OK) - EndDialog(hDlg, IDOK); - } - break; - } - return FALSE; -} - -/** -* This is the message procedure for popup -* -* @param hDlg - window handle -* @param uMsg - message to handle -* @param wParam - message specific parameter -* @param lParam - message specific parameter -* -* @return TRUE, FALSE, IDOK, IDYES, IDALL, IDNO or IDCANCEL -**/ - -LRESULT CALLBACK PopupProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case UM_POPUPACTION: - if (HIWORD(wParam) == BN_CLICKED) { - LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); - if (pmpd) { - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - case IDABORT: - case IDRETRY: - case IDIGNORE: - case IDYES: - case IDNO: - case IDALL: - case IDNONE: - if (IsWindow(pmpd->hDialog)) - EndDialog(pmpd->hDialog, LOWORD(wParam)); - break; - - default: - if (IsWindow(pmpd->hDialog)) - EndDialog(pmpd->hDialog, IDCANCEL); - } - } - PUDeletePopup(hDlg); - } - break; - - case UM_FREEPLUGINDATA: - LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); - if (pmpd > 0) - MIR_FREE(pmpd); - return TRUE; - } - return DefWindowProc(hDlg, uMsg, wParam, lParam); -} - -/** -* This is the service function for external plugins to use the nice messagebox -* -* @param wParam - MCONTACT hContact which can display an avatar for popups -* @param lParam - MSGBOX structure holding parameters -* -* @return The function returns the ID of the clicked button (IDOK, IDCANCEL, ...) -* or -1 on error. -**/ -INT_PTR MsgBoxService(WPARAM, LPARAM lParam) -{ - LPMSGBOX pMsgBox = (LPMSGBOX)lParam; - - // check input - if (PtrIsValid(pMsgBox) && pMsgBox->cbSize == sizeof(MSGBOX)) { - // Shall the MessageBox displayed as popup? - if (!(pMsgBox->uType & (MB_INFOBAR | MB_NOPOPUP)) // message box can be a popup? - && myGlobals.PopupActionsExist == 1 // popup support ext stuct? - && (db_get_dw(0, "Popup", "Actions", 0) & 1) // popup++ actions on? - && db_get_b(0, MODNAME, SET_POPUPMSGBOX, DEFVAL_POPUPMSGBOX)) // user likes popups? - return DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_MSGBOXDUMMI), pMsgBox->hParent, MsgBoxPop, lParam); - - return DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_MSGBOX), pMsgBox->hParent, MsgBoxProc, lParam); - } - return -1; -} - -/** -* name: MsgBox -* desc: calls a messagebox -* param: -**/ -INT_PTR CALLBACK MsgBox(HWND hParent, UINT uType, LPCTSTR pszTitle, LPCTSTR pszInfo, LPCTSTR pszFormat, ...) -{ - wchar_t tszMsg[MAX_SECONDLINE]; - - va_list vl; - va_start(vl, pszFormat); - mir_vsnwprintf(tszMsg, _countof(tszMsg), TranslateW(pszFormat), vl); - va_end(vl); - - MSGBOX mb = { 0 }; - mb.cbSize = sizeof(MSGBOX); - mb.hParent = hParent; - mb.hiLogo = IcoLib_GetIcon(ICO_COMMON_MAIN); - mb.hiMsg = nullptr; - mb.ptszTitle = TranslateW(pszTitle); - mb.ptszInfoText = TranslateW(pszInfo); - mb.ptszMsg = tszMsg; - mb.uType = uType; - return MsgBoxService(NULL, (LPARAM)&mb); -} - -/** -* name: MsgErr -* desc: calls a messagebox -* param: -**/ -INT_PTR CALLBACK MsgErr(HWND hParent, LPCTSTR pszFormat, ...) -{ - wchar_t tszTitle[MAX_SECONDLINE], tszMsg[MAX_SECONDLINE]; - mir_snwprintf(tszTitle, L"%s - %s", _A2W(MODNAME), TranslateT("Error")); - - va_list vl; - va_start(vl, pszFormat); - mir_vsnwprintf(tszMsg, TranslateW(pszFormat), vl); - va_end(vl); - - MSGBOX mb = { 0 }; - mb.cbSize = sizeof(MSGBOX); - mb.hParent = hParent; - mb.hiLogo = IcoLib_GetIcon(ICO_COMMON_MAIN); - mb.hiMsg = nullptr; - mb.ptszTitle = tszTitle; - mb.ptszMsg = tszMsg; - mb.uType = MB_OK | MB_ICON_ERROR; - return MsgBoxService(NULL, (LPARAM)&mb); -} +/* +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright: +© 2012-23 Miranda NG team (https://miranda-ng.org) +© 2006-10 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +// SendSS compatibility: +#include "stdafx.h" +#define ghInst g_plugin.getInst() +#define myGlobals g_myGlobals +#define MODNAME MODULENAME +#define ICO_COMMON_MAIN 0xFFFF +#define ICO_DLG_DETAILS 0xFFFF + +HICON Skin_GetIcon_SendSS(unsigned short id) +{ + if(id==0xFFFF) + return GetIcon(ICO_MAIN); + return GetIconBtn(id); +} +#define IcoLib_GetIcon Skin_GetIcon_SendSS +// original UserInfoEx codebase (almost): + +typedef struct _MSGPOPUPDATA +{ + POPUPACTION pa[3]; + HWND hDialog; +} MSGPOPUPDATA, *LPMSGPOPUPDATA; + +/** + * This helper function moves and resizes a dialog box's control element. + * + * @param hDlg - the dialog box's window handle + * @param idCtrl - the identication number of the control to move + * @param dx -´number of pixels to horizontal move the control + * @param dy - number of pixels to vertical move the control + * @param dw - number of pixels to horizontal resize the control + * @param dh - number of pixels to vertical resize the control + * + * @return nothing + **/ +static FORCEINLINE void MoveCtrl(HWND hDlg, int idCtrl, int dx, int dy, int dw, int dh) +{ + RECT ws; + HWND hCtrl = GetDlgItem(hDlg, idCtrl); + GetWindowRect(hCtrl, &ws); + OffsetRect(&ws, dx, dy); + MoveWindow(hCtrl, ws.left, ws.top, ws.right - ws.left + dw, ws.bottom - ws.top + dh, FALSE); +} + +/** +* This function loads the icon to display for the current message. +* +* @param pMsgBox - pointer to a MSGBOX structure, with information about the message to display. +* +* @retval HICON - The function returns an icon to display with the message. +* @retval NULL - There is no icon for the message. +**/ +static HICON MsgLoadIcon(LPMSGBOX pMsgBox) +{ + HICON hIcon; + + // load the desired status icon + switch (pMsgBox->uType & MB_ICONMASK) { + case MB_ICON_OTHER: // custom icon defined by caller function + hIcon = pMsgBox->hiMsg; + break; + + // default windows icons + case MB_ICON_ERROR: + case MB_ICON_QUESTION: + case MB_ICON_WARNING: + case MB_ICON_INFO: + { + LPCTSTR ico[] = { nullptr, IDI_ERROR, IDI_QUESTION, IDI_WARNING, IDI_INFORMATION }; + hIcon = LoadIcon(nullptr, ico[MB_ICON_INDEX(pMsgBox->uType)]); + } + break; + + // no icon + default: + hIcon = nullptr; + } + return hIcon; +} + +/** + * This function fills a given POPUPACTION structure with the data of a given message id, + * which is normally used by the message box. This is required to let the user interact + * with a popup in the same way as with a normal message dialog box. + * + * @param pa - reference to a POPUPACTION structure to fill + * @param id - the message id + * @param result - This parameter is passed to the POPUPACTION structure as is. + * + * @return nothing + **/ +static void MakePopupAction(POPUPACTION &pa, int id) +{ + pa.cbSize = sizeof(POPUPACTION); + pa.flags = PAF_ENABLED; + pa.wParam = MAKEWORD(id, BN_CLICKED); + pa.lParam = 0; + + switch (id) { + case IDOK: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); + mir_strcpy(pa.lpzTitle, MODNAME"/Ok"); + break; + + case IDCLOSE: + case IDCANCEL: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); + mir_strcpy(pa.lpzTitle, MODNAME"/Cancel"); + break; + + case IDABORT: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); + mir_strcpy(pa.lpzTitle, MODNAME"/Abort"); + break; + + case IDRETRY: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_UPDATE); + mir_strcpy(pa.lpzTitle, MODNAME"/Retry"); + break; + + case IDIGNORE: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); + mir_strcpy(pa.lpzTitle, MODNAME"/Ignore"); + break; + + case IDYES: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); + mir_strcpy(pa.lpzTitle, MODNAME"/Yes"); + break; + + case IDNO: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); + mir_strcpy(pa.lpzTitle, MODNAME"/No"); + break; + + case IDHELP: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); + mir_strcpy(pa.lpzTitle, MODNAME"/Help"); + break; + + case IDALL: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_OK); + mir_strcpy(pa.lpzTitle, MODNAME"/All"); + break; + + case IDNONE: + pa.lchIcon = IcoLib_GetIcon(ICO_BTN_CANCEL); + mir_strcpy(pa.lpzTitle, MODNAME"/None"); + } +} + +/** + * This is the message procedure for my nice looking message box + * + * @param hDlg - window handle + * @param uMsg - message to handle + * @param wParam - message specific parameter + * @param lParam - message specific parameter + * + * @return TRUE, FALSE, IDOK, IDYES, IDALL, IDNO or IDCANCEL + **/ +static INT_PTR CALLBACK MsgBoxProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static int retOk = IDOK; + static int retAll = IDALL; + static int retNon = IDNONE; + static int retCancel = IDCANCEL; + + switch (uMsg) { + case WM_INITDIALOG: + { + LPMSGBOX pMsgBox = (LPMSGBOX)lParam; + if (PtrIsValid(pMsgBox)) { + int icoWidth = 0; + int InfoBarHeight = 0; + HFONT hNormalFont; + + hNormalFont = (HFONT)SendDlgItemMessage(hDlg, TXT_NAME, WM_GETFONT, 0, 0); + if (pMsgBox->uType & MB_INFOBAR) { + LOGFONT lf; + + // set bold font for name in description area + GetObject(hNormalFont, sizeof(lf), &lf); + lf.lfWeight = FW_BOLD; + hNormalFont = CreateFontIndirect(&lf); + + // set infobar's textfont + SendDlgItemMessage(hDlg, TXT_NAME, WM_SETFONT, (WPARAM)hNormalFont, 0); + + // set infobar's logo icon + SendDlgItemMessage(hDlg, ICO_DLGLOGO, STM_SETIMAGE, IMAGE_ICON, + (pMsgBox->hiLogo ? (LPARAM)pMsgBox->hiLogo : (LPARAM)IcoLib_GetIcon(ICO_DLG_DETAILS))); + + // enable headerbar + ShowWindow(GetDlgItem(hDlg, TXT_NAME), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, ICO_DLGLOGO), SW_SHOW); + } + else { + RECT rc; + GetClientRect(GetDlgItem(hDlg, TXT_NAME), &rc); + InfoBarHeight = rc.bottom; + + if (pMsgBox->hiLogo) + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)pMsgBox->hiLogo); + } + + // draw the desired status icon + HICON hIcon = MsgLoadIcon(pMsgBox); + if (hIcon) + SendDlgItemMessage(hDlg, ICO_MSGDLG, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon); + else { + RECT ws; + GetWindowRect(GetDlgItem(hDlg, ICO_MSGDLG), &ws); + icoWidth = ws.right - ws.left; + ShowWindow(GetDlgItem(hDlg, ICO_MSGDLG), SW_HIDE); + } + + // resize the messagebox and reorganize the buttons + if (HDC hDC = GetDC(hDlg)) { + POINT mpt = { 0, 0 }; + RECT ws = { 0, 0, 0, 0 }; + int txtWidth = 0, txtHeight = 0, needX, needY; + RECT rcDlg; + SIZE ts; + LPTSTR h, rs; + + SelectObject(hDC, hNormalFont); + // get message text width and height + if (pMsgBox->ptszMsg) for (rs = h = pMsgBox->ptszMsg;; ++h) { + if (*h == '\n' || !*h) { + GetTextExtentPoint32(hDC, rs, h - rs, &ts); + if (ts.cx > txtWidth) + txtWidth = ts.cx; + txtHeight += ts.cy; + if (!*h) + break; + rs = h + 1; + } + } + // increase width if info text requires more + if ((pMsgBox->uType&MB_INFOBAR) && pMsgBox->ptszInfoText && *pMsgBox->ptszInfoText) { + int multiline = 0; + RECT rcico; GetClientRect(GetDlgItem(hDlg, ICO_DLGLOGO), &rcico); + rcico.right = rcico.right * 100 / 66; // padding + for (rs = h = pMsgBox->ptszInfoText;; ++h) { + if (*h == '\n' || !*h) { + GetTextExtentPoint32(hDC, rs, h - rs, &ts); + ts.cx += rcico.right; + if (ts.cx > txtWidth) + txtWidth = ts.cx; + if (!*h) + break; + rs = h + 1; + ++multiline; + } + } + if (!multiline) + SetWindowLongPtr(GetDlgItem(hDlg, TXT_NAME), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hDlg, TXT_NAME), GWL_STYLE) | SS_CENTERIMAGE); + } + ReleaseDC(hDlg, hDC); + + // calc new dialog size + GetWindowRect(hDlg, &rcDlg); + GetWindowRect(GetDlgItem(hDlg, TXT_MESSAGE), &ws); + needX = txtWidth - (ws.right - ws.left) - icoWidth; + needY = max(0, txtHeight - (ws.bottom - ws.top) + 5); + rcDlg.left -= needX / 2; rcDlg.right += needX / 2; + rcDlg.top -= (needY - InfoBarHeight) / 2; rcDlg.bottom += (needY - InfoBarHeight) / 2; + + // resize dialog window + MoveWindow(hDlg, rcDlg.left, rcDlg.top, rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top, FALSE); + ClientToScreen(hDlg, &mpt); + + MoveCtrl(hDlg, STATIC_WHITERECT, -mpt.x, -mpt.y, needX, needY - InfoBarHeight); + MoveCtrl(hDlg, TXT_NAME, -mpt.x, -mpt.y, needX, 0); + MoveCtrl(hDlg, ICO_DLGLOGO, -mpt.x + needX, -mpt.y, 0, 0); + MoveCtrl(hDlg, ICO_MSGDLG, -mpt.x, -mpt.y - InfoBarHeight, 0, 0); + MoveCtrl(hDlg, TXT_MESSAGE, -mpt.x - icoWidth, -mpt.y - InfoBarHeight, needX, needY); + MoveCtrl(hDlg, STATIC_LINE2, -mpt.x, -mpt.y + needY - InfoBarHeight, needX, 0); + + // Do pushbutton positioning + RECT rcOk, rcAll, rcNone, rcCancel; + + // get button rectangles + GetWindowRect(GetDlgItem(hDlg, IDOK), &rcOk); + OffsetRect(&rcOk, -mpt.x, -mpt.y + needY - InfoBarHeight); + + GetWindowRect(GetDlgItem(hDlg, IDALL), &rcAll); + OffsetRect(&rcAll, -mpt.x, -mpt.y + needY - InfoBarHeight); + + GetWindowRect(GetDlgItem(hDlg, IDNONE), &rcNone); + OffsetRect(&rcNone, -mpt.x, -mpt.y + needY - InfoBarHeight); + + GetWindowRect(GetDlgItem(hDlg, IDCANCEL), &rcCancel); + OffsetRect(&rcCancel, -mpt.x, -mpt.y + needY - InfoBarHeight); + + LONG okWidth = rcOk.right - rcOk.left; + LONG allWidth = rcAll.right - rcAll.left; + LONG noneWidth = rcNone.right - rcNone.left; + LONG caWidth = rcCancel.right - rcCancel.left; + LONG dlgMid = (rcDlg.right - rcDlg.left) / 2; + + // load button configuration + switch (MB_TYPE(pMsgBox->uType)) { + case MB_OK: + rcOk.left = dlgMid - (okWidth / 2); + rcOk.right = rcOk.left + okWidth; + ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); + break; + + case MB_OKCANCEL: + retOk = IDRETRY; + SetDlgItemText(hDlg, IDOK, LPGENW("OK")); + retCancel = IDCANCEL; + SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); + rcOk.left = dlgMid - okWidth - 10; + rcOk.right = rcOk.left + okWidth; + rcCancel.left = dlgMid + 10; + rcCancel.right = rcCancel.left + caWidth; + ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); + break; + + case MB_RETRYCANCEL: + retOk = IDRETRY; + SetDlgItemText(hDlg, IDOK, LPGENW("Retry")); + retCancel = IDCANCEL; + SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); + rcOk.left = dlgMid - okWidth - 10; + rcOk.right = rcOk.left + okWidth; + rcCancel.left = dlgMid + 10; + rcCancel.right = rcCancel.left + caWidth; + ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); + break; + + case MB_YESNO: + retOk = IDYES; + SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); + retCancel = IDNO; + SetDlgItemText(hDlg, IDCANCEL, LPGENW("No")); + rcOk.left = dlgMid - okWidth - 10; + rcOk.right = rcOk.left + okWidth; + rcCancel.left = dlgMid + 10; + rcCancel.right = rcCancel.left + caWidth; + ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); + break; + + case MB_ABORTRETRYIGNORE: + retOk = IDABORT; + SetDlgItemText(hDlg, IDOK, LPGENW("Abort")); + retAll = IDABORT; + SetDlgItemText(hDlg, IDALL, LPGENW("Retry")); + retCancel = IDCANCEL; + SetDlgItemText(hDlg, IDCANCEL, LPGENW("Ignore")); + rcAll.left = dlgMid - (allWidth / 2); + rcAll.right = rcAll.left + allWidth; + rcOk.left = rcAll.left - okWidth - 5; + rcOk.right = rcOk.left + okWidth; + rcCancel.left = rcAll.right + 5; + rcCancel.right = rcCancel.left + caWidth; + ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); + break; + + case MB_YESNOCANCEL: + retOk = IDYES; + SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); + retAll = IDNO; + SetDlgItemText(hDlg, IDALL, LPGENW("No")); + retCancel = IDCANCEL; + SetDlgItemText(hDlg, IDCANCEL, LPGENW("Cancel")); + rcAll.left = dlgMid - (allWidth / 2); + rcAll.right = rcAll.left + allWidth; + rcOk.left = rcAll.left - okWidth - 5; + rcOk.right = rcOk.left + okWidth; + rcCancel.left = rcAll.right + 5; + rcCancel.right = rcCancel.left + caWidth; + ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); + break; + + case MB_YESALLNO: + retOk = IDYES; + SetDlgItemText(hDlg, IDOK, LPGENW("Yes")); + retAll = IDALL; + SetDlgItemText(hDlg, IDALL, LPGENW("All")); + SetDlgItemText(hDlg, IDNONE, LPGENW("None")); + retCancel = IDNO; + SetDlgItemText(hDlg, IDCANCEL, LPGENW("No")); + rcCancel.right = rcDlg.right - rcDlg.left - 10; + rcCancel.left = rcCancel.right - caWidth; + rcNone.right = rcCancel.left - 5; + rcNone.left = rcNone.right - noneWidth; + rcAll.right = rcNone.left - 5; + rcAll.left = rcAll.right - allWidth; + rcOk.right = rcAll.left - 5; + rcOk.left = rcOk.right - okWidth; + // show buttons + ShowWindow(GetDlgItem(hDlg, IDOK), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDALL), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDNONE), SW_SHOW); + ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_SHOW); + break; + + default: + rcOk.left = dlgMid - (okWidth / 2); + rcOk.right = rcOk.left + okWidth; + } + + MoveWindow(GetDlgItem(hDlg, IDOK), rcOk.left, rcOk.top, rcOk.right - rcOk.left, rcOk.bottom - rcOk.top, FALSE); + MoveWindow(GetDlgItem(hDlg, IDALL), rcAll.left, rcAll.top, rcAll.right - rcAll.left, rcAll.bottom - rcAll.top, FALSE); + MoveWindow(GetDlgItem(hDlg, IDNONE), rcNone.left, rcNone.top, rcNone.right - rcNone.left, rcNone.bottom - rcNone.top, FALSE); + MoveWindow(GetDlgItem(hDlg, IDCANCEL), rcCancel.left, rcCancel.top, rcCancel.right - rcCancel.left, rcCancel.bottom - rcCancel.top, FALSE); + } + + // set text's + SetWindowText(hDlg, pMsgBox->ptszTitle); + SetDlgItemText(hDlg, TXT_NAME, pMsgBox->ptszInfoText); + SetDlgItemText(hDlg, TXT_MESSAGE, pMsgBox->ptszMsg); + + TranslateDialogDefault(hDlg); + return TRUE; + } + } + break; + + case WM_CTLCOLORSTATIC: + switch (GetWindowLongPtr((HWND)lParam, GWLP_ID)) { + case STATIC_WHITERECT: + case ICO_DLGLOGO: + case ICO_MSGDLG: + case TXT_MESSAGE: + case TXT_NAME: + SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); + return GetSysColor(COLOR_WINDOW); + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + EndDialog(hDlg, retOk); + break; + case IDCANCEL: + EndDialog(hDlg, retCancel); + break; + case IDALL: + EndDialog(hDlg, retAll); + break; + case IDNONE: + EndDialog(hDlg, retNon); + } + break; + + case WM_DESTROY: + DeleteObject((HFONT)SendDlgItemMessage(hDlg, TXT_NAME, WM_GETFONT, 0, 0)); + break; + } + return FALSE; +} + +/** +* Dummi modal MsgBox for popup, +* this set call function in wait stait and do not freece miranda main thread +* the window is outside the desktop +*/ +static INT_PTR CALLBACK MsgBoxPop(HWND hDlg, UINT uMsg, WPARAM, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + LPMSGBOX pMsgBox = (LPMSGBOX)lParam; + + MoveWindow(hDlg, -10, -10, 0, 0, FALSE); + LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)mir_alloc(sizeof(MSGPOPUPDATA)); + if (pmpd) { + POPUPDATAW ppd; + ppd.lchContact = NULL; // (HANDLE)wParam; + // icon + ppd.lchIcon = MsgLoadIcon(pMsgBox); + mir_wstrncpy(ppd.lpwzContactName, pMsgBox->ptszTitle, _countof(ppd.lpwzContactName)); + mir_wstrncpy(ppd.lpwzText, pMsgBox->ptszMsg, _countof(ppd.lpwzText)); + + // CALLBAC Proc + ppd.PluginWindowProc = PopupProc; + ppd.PluginData = pmpd; + ppd.iSeconds = -1; + ppd.lpActions = pmpd->pa; + + // set color of popup + switch (pMsgBox->uType & MB_ICONMASK) { + case MB_ICON_ERROR: + ppd.colorBack = RGB(200, 10, 0); + ppd.colorText = RGB(255, 255, 255); + break; + + case MB_ICON_WARNING: + ppd.colorBack = RGB(200, 100, 0); + ppd.colorText = RGB(255, 255, 255); + break; + + default: + if (pMsgBox->uType & MB_CUSTOMCOLOR) { + ppd.colorBack = pMsgBox->colorBack; + ppd.colorText = pMsgBox->colorText; + } + } + + // handle for MakePopupAction + pmpd->hDialog = hDlg; + + // active buttons + switch (MB_TYPE(pMsgBox->uType)) { + case MB_OK: + MakePopupAction(pmpd->pa[ppd.actionCount++], IDOK); + break; + + case MB_OKCANCEL: + MakePopupAction(pmpd->pa[ppd.actionCount++], IDOK); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); + break; + + case MB_RETRYCANCEL: + MakePopupAction(pmpd->pa[ppd.actionCount++], IDRETRY); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); + break; + + case MB_YESNO: + MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); + break; + + case MB_ABORTRETRYIGNORE: + MakePopupAction(pmpd->pa[ppd.actionCount++], IDABORT); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDRETRY); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDIGNORE); + break; + + case MB_YESNOCANCEL: + MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDCANCEL); + break; + + case MB_YESALLNO: + MakePopupAction(pmpd->pa[ppd.actionCount++], IDYES); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDALL); + MakePopupAction(pmpd->pa[ppd.actionCount++], IDNO); + break; + } + + // create popup + PUAddPopupW(&ppd); + if (MB_TYPE(pMsgBox->uType) == MB_OK) + EndDialog(hDlg, IDOK); + } + break; + } + return FALSE; +} + +/** +* This is the message procedure for popup +* +* @param hDlg - window handle +* @param uMsg - message to handle +* @param wParam - message specific parameter +* @param lParam - message specific parameter +* +* @return TRUE, FALSE, IDOK, IDYES, IDALL, IDNO or IDCANCEL +**/ + +LRESULT CALLBACK PopupProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case UM_POPUPACTION: + if (HIWORD(wParam) == BN_CLICKED) { + LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); + if (pmpd) { + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + case IDABORT: + case IDRETRY: + case IDIGNORE: + case IDYES: + case IDNO: + case IDALL: + case IDNONE: + if (IsWindow(pmpd->hDialog)) + EndDialog(pmpd->hDialog, LOWORD(wParam)); + break; + + default: + if (IsWindow(pmpd->hDialog)) + EndDialog(pmpd->hDialog, IDCANCEL); + } + } + PUDeletePopup(hDlg); + } + break; + + case UM_FREEPLUGINDATA: + LPMSGPOPUPDATA pmpd = (LPMSGPOPUPDATA)PUGetPluginData(hDlg); + if (pmpd > 0) + MIR_FREE(pmpd); + return TRUE; + } + return DefWindowProc(hDlg, uMsg, wParam, lParam); +} + +/** +* This is the service function for external plugins to use the nice messagebox +* +* @param wParam - MCONTACT hContact which can display an avatar for popups +* @param lParam - MSGBOX structure holding parameters +* +* @return The function returns the ID of the clicked button (IDOK, IDCANCEL, ...) +* or -1 on error. +**/ +INT_PTR MsgBoxService(WPARAM, LPARAM lParam) +{ + LPMSGBOX pMsgBox = (LPMSGBOX)lParam; + + // check input + if (PtrIsValid(pMsgBox) && pMsgBox->cbSize == sizeof(MSGBOX)) { + // Shall the MessageBox displayed as popup? + if (!(pMsgBox->uType & (MB_INFOBAR | MB_NOPOPUP)) // message box can be a popup? + && myGlobals.PopupActionsExist == 1 // popup support ext stuct? + && (db_get_dw(0, "Popup", "Actions", 0) & 1) // popup++ actions on? + && db_get_b(0, MODNAME, SET_POPUPMSGBOX, DEFVAL_POPUPMSGBOX)) // user likes popups? + return DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_MSGBOXDUMMI), pMsgBox->hParent, MsgBoxPop, lParam); + + return DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_MSGBOX), pMsgBox->hParent, MsgBoxProc, lParam); + } + return -1; +} + +/** +* name: MsgBox +* desc: calls a messagebox +* param: +**/ +INT_PTR CALLBACK MsgBox(HWND hParent, UINT uType, LPCTSTR pszTitle, LPCTSTR pszInfo, LPCTSTR pszFormat, ...) +{ + wchar_t tszMsg[MAX_SECONDLINE]; + + va_list vl; + va_start(vl, pszFormat); + mir_vsnwprintf(tszMsg, _countof(tszMsg), TranslateW(pszFormat), vl); + va_end(vl); + + MSGBOX mb = { 0 }; + mb.cbSize = sizeof(MSGBOX); + mb.hParent = hParent; + mb.hiLogo = IcoLib_GetIcon(ICO_COMMON_MAIN); + mb.hiMsg = nullptr; + mb.ptszTitle = TranslateW(pszTitle); + mb.ptszInfoText = TranslateW(pszInfo); + mb.ptszMsg = tszMsg; + mb.uType = uType; + return MsgBoxService(NULL, (LPARAM)&mb); +} + +/** +* name: MsgErr +* desc: calls a messagebox +* param: +**/ +INT_PTR CALLBACK MsgErr(HWND hParent, LPCTSTR pszFormat, ...) +{ + wchar_t tszTitle[MAX_SECONDLINE], tszMsg[MAX_SECONDLINE]; + mir_snwprintf(tszTitle, L"%s - %s", _A2W(MODNAME), TranslateT("Error")); + + va_list vl; + va_start(vl, pszFormat); + mir_vsnwprintf(tszMsg, TranslateW(pszFormat), vl); + va_end(vl); + + MSGBOX mb = { 0 }; + mb.cbSize = sizeof(MSGBOX); + mb.hParent = hParent; + mb.hiLogo = IcoLib_GetIcon(ICO_COMMON_MAIN); + mb.hiMsg = nullptr; + mb.ptszTitle = tszTitle; + mb.ptszMsg = tszMsg; + mb.uType = MB_OK | MB_ICON_ERROR; + return MsgBoxService(NULL, (LPARAM)&mb); +} diff --git a/plugins/SendScreenshotPlus/src/dlg_msgbox.h b/plugins/SendScreenshotPlus/src/dlg_msgbox.h index 68f40ea6b3..d1b31e6538 100644 --- a/plugins/SendScreenshotPlus/src/dlg_msgbox.h +++ b/plugins/SendScreenshotPlus/src/dlg_msgbox.h @@ -2,7 +2,7 @@ Miranda NG: the free IM client for Microsoft* Windows* Copyright: -© 2012-22 Miranda NG team (https://miranda-ng.org) +© 2012-23 Miranda NG team (https://miranda-ng.org) © 2006-10 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol This program is free software; you can redistribute it and/or diff --git a/plugins/SendScreenshotPlus/src/stdafx.cxx b/plugins/SendScreenshotPlus/src/stdafx.cxx index f64d25234b..ebbde0ade1 100644 --- a/plugins/SendScreenshotPlus/src/stdafx.cxx +++ b/plugins/SendScreenshotPlus/src/stdafx.cxx @@ -1,5 +1,5 @@ /* -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org) +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/plugins/SendScreenshotPlus/src/stdafx.h b/plugins/SendScreenshotPlus/src/stdafx.h index bdf13cef1f..ecad2333c8 100644 --- a/plugins/SendScreenshotPlus/src/stdafx.h +++ b/plugins/SendScreenshotPlus/src/stdafx.h @@ -1,186 +1,186 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (C) 2012-22 Miranda NG team (https://miranda-ng.org), -Copyright (c) 2000-09 Miranda ICQ/IM project, - -This file is part of Send Screenshot Plus, a Miranda IM plugin. -Copyright (c) 2010 Ing.U.Horn - -Parts of this file based on original sorce code -(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#ifndef _GLOBAL_H_ -#define _GLOBAL_H_ - -#define OEMRESOURCE - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -using namespace std; - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ctrl_button.h" -#include "dlg_msgbox.h" -#include "resource.h" -#include "version.h" -#include "CSend.h" -#include "CSendEmail.h" -#include "CSendFile.h" -#include "CSendFTPFile.h" -#include "CSendHTTPServer.h" -#include "CSendCloduFile.h" -#include "CSendHost_ImageShack.h" -#include "CSendHost_uploadpie.h" -#include "CSendHost_imgur.h" -#include "DevKey.h" -#include "UMainForm.h" -#include "Utils.h" - -#define UM_CLOSING WM_USER+1 -#define UM_EVENT WM_USER+2 - -// Generic Message Box for Errors -#define MSGERROR(text) MessageBox(NULL, text, L"SendSS", MB_OK | MB_ICONERROR) -#define MSGINFO (text) MessageBox(NULL, text, L"SendSS", MB_OK | MB_ICONINFORMATION) - -typedef struct _MGLOBAL { - uint32_t mirandaVersion; // mirandaVersion - BOOLEAN PopupActionsExist : 1; // Popup+ or MS_POPUP_REGISTERACTIONS exist - BOOLEAN PluginHTTPExist : 1; // HTTPServer or MS_HTTP_ACCEPT_CONNECTIONS exist - BOOLEAN PluginFTPExist : 1; // FTPFile or MS_FTPFILE_UPLOAD exist - BOOLEAN PluginCloudFileExist: 1; // CloudFile or MS_CLOUDFILE_UPLOAD exists - -} MGLOBAL, *LPMGLOBAL; - -///////////////////////////////////////////////////////////////////////////////////////// - -#define ERROR_TITLE TranslateT("SendScreenshot - Error") - -// Miranda Database Key -#define MODULENAME "SendSS" - -struct CMPlugin : public PLUGIN -{ - CMPlugin(); - - int Load() override; - int Unload() override; -}; - -extern ATOM g_clsTargetHighlighter; -extern MGLOBAL g_myGlobals; -extern HNETLIBUSER g_hNetlibUser; - -enum -{ - ICO_MAIN = 0, - ICO_MAINXS, - ICO_TARGET, - ICO_MONITOR, - ICO_END_, - ICO_BTN_HELP = 0, - ICO_BTN_FOLDER, - ICO_BTN_DESC, - ICO_BTN_DESCON, - ICO_BTN_DEL, - ICO_BTN_DELON, - ICO_BTN_ARROWL, - ICO_BTN_ARROWR, - ICO_BTN_UPDATE, - ICO_BTN_OK, - ICO_BTN_CANCEL, - ICO_BTN_EDIT, - ICO_BTN_EDITON, - ICO_BTN_COPY, - ICO_BTN_BBC, - ICO_BTN_BBCLNK, - ICO_BTN_DOWNARROW, - ICO_BTN_END_, -}; -#define GetIconHandle(ico) ICONS[ico].hIcolib -#define GetIcon(ico) IcoLib_GetIconByHandle(GetIconHandle(ico)) -extern IconItem ICONS[ICO_END_]; -#define GetIconBtnHandle(ico) ICONS_BTN[ico].hIcolib -#define GetIconBtn(ico) IcoLib_GetIconByHandle(GetIconBtnHandle(ico)) -extern IconItem ICONS_BTN[ICO_BTN_END_]; - -#define PtrIsValid(p) (((p)!=0)&&(((HANDLE)(p))!=INVALID_HANDLE_VALUE)) -#define MIR_FREE(p) {if (PtrIsValid(p)){mir_free((void*)p);(p)=NULL;}} -#ifdef _DEBUG -# define DBGMSG(str,...) do{char tmp[1024];sprintf(tmp,str,##__VA_ARGS__);OutputDebugStringA(tmp);}while(0) -#else -# define DBGMSG(str,...) -#endif - -void ComboBox_SelectItem(HWND hCombo, LPARAM data); - -template -std::basic_string<_Elem> replace(const std::basic_string<_Elem> & Origninal, const std::basic_string<_Elem> & What, const std::basic_string<_Elem> & With) -{ - std::basic_string<_Elem> res; - size_t l = 0; - for (size_t p = Origninal.find(What.c_str(), 0); p != std::basic_string<_Elem>::npos; p = Origninal.find(What.c_str(), l)) - { - if (l != p) - res.append(Origninal.c_str() + l, p - l); - res.append(With); - l = p + What.length(); - } - if (l < Origninal.length()) - res.append(Origninal.c_str() + l); - - return res; -} - -#endif +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org), +Copyright (c) 2000-09 Miranda ICQ/IM project, + +This file is part of Send Screenshot Plus, a Miranda IM plugin. +Copyright (c) 2010 Ing.U.Horn + +Parts of this file based on original sorce code +(c) 2004-2006 Sérgio Vieira Rolanski (portet from Borland C++) + +This program 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 2 +of the License, or (at your option) any later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#ifndef _GLOBAL_H_ +#define _GLOBAL_H_ + +#define OEMRESOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +using namespace std; + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ctrl_button.h" +#include "dlg_msgbox.h" +#include "resource.h" +#include "version.h" +#include "CSend.h" +#include "CSendEmail.h" +#include "CSendFile.h" +#include "CSendFTPFile.h" +#include "CSendHTTPServer.h" +#include "CSendCloduFile.h" +#include "CSendHost_ImageShack.h" +#include "CSendHost_uploadpie.h" +#include "CSendHost_imgur.h" +#include "DevKey.h" +#include "UMainForm.h" +#include "Utils.h" + +#define UM_CLOSING WM_USER+1 +#define UM_EVENT WM_USER+2 + +// Generic Message Box for Errors +#define MSGERROR(text) MessageBox(NULL, text, L"SendSS", MB_OK | MB_ICONERROR) +#define MSGINFO (text) MessageBox(NULL, text, L"SendSS", MB_OK | MB_ICONINFORMATION) + +typedef struct _MGLOBAL { + uint32_t mirandaVersion; // mirandaVersion + BOOLEAN PopupActionsExist : 1; // Popup+ or MS_POPUP_REGISTERACTIONS exist + BOOLEAN PluginHTTPExist : 1; // HTTPServer or MS_HTTP_ACCEPT_CONNECTIONS exist + BOOLEAN PluginFTPExist : 1; // FTPFile or MS_FTPFILE_UPLOAD exist + BOOLEAN PluginCloudFileExist: 1; // CloudFile or MS_CLOUDFILE_UPLOAD exists + +} MGLOBAL, *LPMGLOBAL; + +///////////////////////////////////////////////////////////////////////////////////////// + +#define ERROR_TITLE TranslateT("SendScreenshot - Error") + +// Miranda Database Key +#define MODULENAME "SendSS" + +struct CMPlugin : public PLUGIN +{ + CMPlugin(); + + int Load() override; + int Unload() override; +}; + +extern ATOM g_clsTargetHighlighter; +extern MGLOBAL g_myGlobals; +extern HNETLIBUSER g_hNetlibUser; + +enum +{ + ICO_MAIN = 0, + ICO_MAINXS, + ICO_TARGET, + ICO_MONITOR, + ICO_END_, + ICO_BTN_HELP = 0, + ICO_BTN_FOLDER, + ICO_BTN_DESC, + ICO_BTN_DESCON, + ICO_BTN_DEL, + ICO_BTN_DELON, + ICO_BTN_ARROWL, + ICO_BTN_ARROWR, + ICO_BTN_UPDATE, + ICO_BTN_OK, + ICO_BTN_CANCEL, + ICO_BTN_EDIT, + ICO_BTN_EDITON, + ICO_BTN_COPY, + ICO_BTN_BBC, + ICO_BTN_BBCLNK, + ICO_BTN_DOWNARROW, + ICO_BTN_END_, +}; +#define GetIconHandle(ico) ICONS[ico].hIcolib +#define GetIcon(ico) IcoLib_GetIconByHandle(GetIconHandle(ico)) +extern IconItem ICONS[ICO_END_]; +#define GetIconBtnHandle(ico) ICONS_BTN[ico].hIcolib +#define GetIconBtn(ico) IcoLib_GetIconByHandle(GetIconBtnHandle(ico)) +extern IconItem ICONS_BTN[ICO_BTN_END_]; + +#define PtrIsValid(p) (((p)!=0)&&(((HANDLE)(p))!=INVALID_HANDLE_VALUE)) +#define MIR_FREE(p) {if (PtrIsValid(p)){mir_free((void*)p);(p)=NULL;}} +#ifdef _DEBUG +# define DBGMSG(str,...) do{char tmp[1024];sprintf(tmp,str,##__VA_ARGS__);OutputDebugStringA(tmp);}while(0) +#else +# define DBGMSG(str,...) +#endif + +void ComboBox_SelectItem(HWND hCombo, LPARAM data); + +template +std::basic_string<_Elem> replace(const std::basic_string<_Elem> & Origninal, const std::basic_string<_Elem> & What, const std::basic_string<_Elem> & With) +{ + std::basic_string<_Elem> res; + size_t l = 0; + for (size_t p = Origninal.find(What.c_str(), 0); p != std::basic_string<_Elem>::npos; p = Origninal.find(What.c_str(), l)) + { + if (l != p) + res.append(Origninal.c_str() + l, p - l); + res.append(With); + l = p + What.length(); + } + if (l < Origninal.length()) + res.append(Origninal.c_str() + l); + + return res; +} + +#endif -- cgit v1.2.3