summaryrefslogtreecommitdiff
path: root/src/modules/srfile/ftmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/srfile/ftmanager.cpp')
-rw-r--r--src/modules/srfile/ftmanager.cpp592
1 files changed, 592 insertions, 0 deletions
diff --git a/src/modules/srfile/ftmanager.cpp b/src/modules/srfile/ftmanager.cpp
new file mode 100644
index 0000000000..a219d2188a
--- /dev/null
+++ b/src/modules/srfile/ftmanager.cpp
@@ -0,0 +1,592 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 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.
+*/
+#include "commonheaders.h"
+#include "file.h"
+
+static HWND hwndFtMgr = NULL;
+
+struct TFtMgrData
+{
+ HWND hwndIncoming;
+ HWND hwndOutgoing;
+
+ HANDLE hhkPreshutdown;
+ TBPFLAG errorState;
+};
+
+
+#define M_CALCPROGRESS (WM_USER + 200)
+struct TFtProgressData
+{
+ unsigned int init, run, scan;
+ unsigned __int64 totalBytes, totalProgress;
+};
+
+struct TLayoutWindowInfo
+{
+ HWND hwnd;
+ RECT rc;
+};
+
+struct TLayoutWindowList
+{
+ struct TLayoutWindowInfo **items;
+ int realCount, limit, increment;
+ FSortFunc sortFunc;
+};
+
+struct TFtPageData
+{
+ struct TLayoutWindowList *wnds;
+ int runningCount;
+ int height, dataHeight, scrollPos;
+};
+
+static void LayoutTransfers(HWND hwnd, struct TFtPageData *dat)
+{
+ int top = 0;
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+
+ dat->scrollPos = GetScrollPos(hwnd, SB_VERT);
+ dat->height = rc.bottom - rc.top;
+
+ if (dat->wnds->realCount)
+ {
+ int i;
+ HDWP hdwp;
+
+ hdwp = BeginDeferWindowPos(dat->wnds->realCount);
+ top -= dat->scrollPos;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ {
+ int height = dat->wnds->items[i]->rc.bottom - dat->wnds->items[i]->rc.top;
+ hdwp = DeferWindowPos(hdwp, dat->wnds->items[i]->hwnd, NULL, 0, top, rc.right, height, SWP_NOZORDER);
+ top += height;
+ }
+ top += dat->scrollPos;
+ EndDeferWindowPos(hdwp);
+ }
+
+ dat->dataHeight = top;
+
+ {
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_DISABLENOSCROLL|SIF_PAGE|SIF_RANGE;
+ si.nPage = dat->height;
+ si.nMin = 0;
+ si.nMax = dat->dataHeight;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ }
+}
+
+static INT_PTR CALLBACK FtMgrPageDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct TFtPageData *dat = (struct TFtPageData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ // Force scrollbar visibility
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_DISABLENOSCROLL;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+
+ dat = (struct TFtPageData *)mir_alloc(sizeof(struct TFtPageData));
+ dat->wnds = (struct TLayoutWindowList *)List_Create(0, 1);
+ dat->scrollPos = 0;
+ dat->runningCount = 0;
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat);
+ break;
+ }
+
+ case WM_FT_ADD:
+ {
+ struct TLayoutWindowInfo *wnd = (struct TLayoutWindowInfo *)mir_alloc(sizeof(struct TLayoutWindowInfo));
+ wnd->hwnd = (HWND)lParam;
+ GetWindowRect(wnd->hwnd, &wnd->rc);
+ List_Insert((SortedList *)dat->wnds, wnd, dat->wnds->realCount);
+ LayoutTransfers(hwnd, dat);
+ dat->runningCount++;
+ PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
+ break;
+ }
+
+ case WM_FT_RESIZE:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ if (dat->wnds->items[i]->hwnd == (HWND)lParam)
+ {
+ GetWindowRect(dat->wnds->items[i]->hwnd, &dat->wnds->items[i]->rc);
+ break;
+ }
+ LayoutTransfers(hwnd, dat);
+ break;
+ }
+
+ case WM_FT_REMOVE:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ if (dat->wnds->items[i]->hwnd == (HWND)lParam)
+ {
+ mir_free(dat->wnds->items[i]);
+ List_Remove((SortedList *)dat->wnds, i);
+ break;
+ }
+ LayoutTransfers(hwnd, dat);
+ break;
+ }
+
+ case WM_FT_COMPLETED:
+ { //wParam: { ACKRESULT_SUCCESS | ACKRESULT_FAILED | ACKRESULT_DENIED }
+ dat->runningCount--;
+ int i = 0;
+ while (i < dat->wnds->realCount)
+ {
+ // no error when canceling (WM_FT_REMOVE is send first, check if hwnd is still registered)
+ if (dat->wnds->items[i]->hwnd == (HWND)lParam)
+ {
+ SendMessage(GetParent(hwnd), WM_TIMER, 1, (LPARAM)wParam);
+ break;
+ }
+ ++i;
+ }
+ if (i == dat->wnds->realCount)
+ PostMessage(GetParent(hwnd), WM_TIMER, 1, NULL);
+
+ if(dat->runningCount == 0 && (int)wParam == ACKRESULT_SUCCESS && DBGetContactSettingByte(NULL,"SRFile","AutoClose",0))
+ ShowWindow(hwndFtMgr, SW_HIDE);
+ break;
+ }
+
+ case WM_FT_CLEANUP:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ SendMessage(dat->wnds->items[i]->hwnd, WM_FT_CLEANUP, wParam, lParam);
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ LayoutTransfers(hwnd, dat);
+ break;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
+ if (zDelta)
+ {
+ int i, nScrollLines = 0;
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, (void*)&nScrollLines, 0);
+ for (i = 0; i < (nScrollLines + 1) / 2; i++ )
+ SendMessage(hwnd, WM_VSCROLL, (zDelta < 0) ? SB_LINEDOWN : SB_LINEUP, 0);
+ }
+
+ SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 0);
+ return TRUE;
+ }
+
+ case WM_VSCROLL:
+ {
+ int pos = dat->scrollPos;
+ switch (LOWORD(wParam))
+ {
+ case SB_LINEDOWN:
+ pos += 15;
+ break;
+ case SB_LINEUP:
+ pos -= 15;
+ break;
+ case SB_PAGEDOWN:
+ pos += dat->height - 10;
+ break;
+ case SB_PAGEUP:
+ pos -= dat->height - 10;
+ break;
+ case SB_THUMBTRACK:
+ pos = HIWORD(wParam);
+ break;
+ }
+
+ if (pos > dat->dataHeight - dat->height) pos = dat->dataHeight - dat->height;
+ if (pos < 0) pos = 0;
+
+ if (dat->scrollPos != pos)
+ {
+ ScrollWindow(hwnd, 0, dat->scrollPos - pos, NULL, NULL);
+ SetScrollPos(hwnd, SB_VERT, pos, TRUE);
+ dat->scrollPos = pos;
+ }
+ break;
+ }
+
+ case M_PRESHUTDOWN:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ PostMessage(dat->wnds->items[i]->hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), 0);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ int i;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ mir_free(dat->wnds->items[i]);
+ List_Destroy((SortedList *)dat->wnds);
+ mir_free(dat->wnds);
+ mir_free(dat);
+ break;
+ }
+
+ case M_CALCPROGRESS:
+ {
+ int i;
+ TFtProgressData * prg = (TFtProgressData *)wParam;
+ for (i = 0; i < dat->wnds->realCount; ++i)
+ {
+ struct FileDlgData *trdat = (struct FileDlgData *)GetWindowLongPtr(dat->wnds->items[i]->hwnd, GWLP_USERDATA);
+ if (trdat->transferStatus.totalBytes && trdat->fs && !trdat->send && (trdat->transferStatus.totalBytes == trdat->transferStatus.totalProgress))
+ {
+ prg->scan++;
+ } else if (trdat->transferStatus.totalBytes && trdat->fs)
+ { // in progress
+ prg->run++;
+ prg->totalBytes += trdat->transferStatus.totalBytes;
+ prg->totalProgress += trdat->transferStatus.totalProgress;
+ } else if (trdat->fs)
+ { // starting
+ prg->init++;
+ }
+
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static INT_PTR CALLBACK FtMgrDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct TFtMgrData *dat = (struct TFtMgrData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TCITEM tci = {0};
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+
+ TranslateDialogDefault(hwnd);
+ Window_SetIcon_IcoLib(hwnd, SKINICON_EVENT_FILE);
+
+ dat = (struct TFtMgrData *)mir_calloc(sizeof(struct TFtMgrData));
+
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat);
+
+ dat->hhkPreshutdown = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwnd, M_PRESHUTDOWN);
+
+ dat->hwndIncoming = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
+ dat->hwndOutgoing = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTPAGE), hwnd, FtMgrPageDlgProc);
+ ShowWindow(dat->hwndIncoming, SW_SHOW);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.pszText = TranslateT("Incoming");
+ tci.lParam = (LPARAM)dat->hwndIncoming;
+ TabCtrl_InsertItem(hwndTab, 0, &tci);
+ tci.pszText = TranslateT("Outgoing");
+ tci.lParam = (LPARAM)dat->hwndOutgoing;
+ TabCtrl_InsertItem(hwndTab, 1, &tci);
+
+ // Utils_RestoreWindowPosition(hwnd, NULL, "SRFile", "FtMgrDlg_");
+ SAVEWINDOWPOS swp;
+ swp.hwnd=hwnd; swp.hContact=NULL; swp.szModule="SRFile"; swp.szNamePrefix="FtMgrDlg_";
+ CallService(MS_UTILS_RESTOREWINDOWPOSITION, RWPF_NOACTIVATE, (LPARAM)&swp);
+
+ // Fall through to setup initial placement
+ }
+ case WM_SIZE:
+ {
+ RECT rc, rcButton;
+ HDWP hdwp;
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+
+ GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rcButton);
+ OffsetRect(&rcButton, -rcButton.left, -rcButton.top);
+
+ GetClientRect(hwnd, &rc);
+ InflateRect(&rc, -6, -6);
+
+ hdwp = BeginDeferWindowPos(3);
+
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwnd, IDC_CLEAR), NULL, rc.left, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwnd, IDCANCEL), NULL, rc.right-rcButton.right, rc.bottom-rcButton.bottom, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
+
+ rc.bottom -= rcButton.bottom + 5;
+
+ hdwp = DeferWindowPos(hdwp, hwndTab, NULL, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER);
+
+ EndDeferWindowPos(hdwp);
+
+ GetWindowRect(hwndTab, &rc);
+ MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2);
+ TabCtrl_AdjustRect(hwndTab, FALSE, &rc);
+ InflateRect(&rc, -5, -5);
+
+ hdwp = BeginDeferWindowPos(2);
+
+ hdwp = DeferWindowPos(hdwp, dat->hwndIncoming, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0);
+ hdwp = DeferWindowPos(hdwp, dat->hwndOutgoing, HWND_TOP, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0);
+
+ EndDeferWindowPos(hdwp);
+
+ break;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ if (IsWindowVisible(dat->hwndIncoming)) SendMessage(dat->hwndIncoming, msg, wParam, lParam);
+ if (IsWindowVisible(dat->hwndOutgoing)) SendMessage(dat->hwndOutgoing, msg, wParam, lParam);
+ break;
+ }
+
+ case WM_FT_SELECTPAGE:
+ {
+ TCITEM tci = {0};
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+
+ if (TabCtrl_GetCurSel(hwndTab) == (int)wParam) break;
+
+ tci.mask = TCIF_PARAM;
+
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+
+ TabCtrl_SetCurSel(hwndTab, wParam);
+
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_SHOW);
+
+ break;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam;
+ lpmmi->ptMinTrackSize.x = 300;
+ lpmmi->ptMinTrackSize.y = 400;
+ return 0;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ PostMessage(hwnd, WM_CLOSE , 0, 0);
+ break;
+
+ case IDC_CLEAR:
+ PostMessage(dat->hwndIncoming, WM_FT_CLEANUP, 0, 0);
+ PostMessage(dat->hwndOutgoing, WM_FT_CLEANUP, 0, 0);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case IDC_TABS:
+ {
+ HWND hwndTab = GetDlgItem(hwnd, IDC_TABS);
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGING:
+ {
+ TCITEM tci = {0};
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_HIDE);
+ break;
+ }
+
+ case TCN_SELCHANGE:
+ {
+ TCITEM tci = {0};
+ tci.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, TabCtrl_GetCurSel(hwndTab), &tci);
+ ShowWindow((HWND)tci.lParam, SW_SHOW);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ case M_PRESHUTDOWN:
+ SendMessage(dat->hwndIncoming, M_PRESHUTDOWN, 0, 0);
+ SendMessage(dat->hwndOutgoing, M_PRESHUTDOWN, 0, 0);
+ DestroyWindow(hwnd);
+ break;
+
+ case WM_CLOSE:
+ ShowWindow(hwnd, SW_HIDE);
+ if (DBGetContactSettingByte(NULL, "SRFile", "AutoClear", 1)) {
+ PostMessage(dat->hwndIncoming, WM_FT_CLEANUP, 0, 0);
+ PostMessage(dat->hwndOutgoing, WM_FT_CLEANUP, 0, 0);
+ }
+ return TRUE; /* Disable default IDCANCEL notification */
+
+ case WM_DESTROY:
+ UnhookEvent(dat->hhkPreshutdown);
+ Window_FreeIcon_IcoLib(hwnd);
+ DestroyWindow(dat->hwndIncoming);
+ DestroyWindow(dat->hwndOutgoing);
+ mir_free(dat);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+ Utils_SaveWindowPosition(hwnd, NULL, "SRFile", "FtMgrDlg_");
+ break;
+
+ case WM_ACTIVATE:
+ {
+ dat->errorState = TBPF_NOPROGRESS;
+ wParam = 1;
+ } break;
+ case WM_SHOWWINDOW:
+ {
+ if (!wParam) // hiding
+ {
+ KillTimer(hwnd, 1);
+ break;
+ }
+ lParam = 0;
+ }
+ case WM_TIMER:
+ {
+ if (pTaskbarInterface)
+ {
+ SetTimer(hwnd, 1, 400, NULL);
+ if ((lParam == ACKRESULT_FAILED) || (lParam == ACKRESULT_DENIED))
+ dat->errorState = TBPF_ERROR;
+
+ TFtProgressData prg = {0};
+ SendMessage(dat->hwndIncoming, M_CALCPROGRESS, (WPARAM)&prg, 0);
+ SendMessage(dat->hwndOutgoing, M_CALCPROGRESS, (WPARAM)&prg, 0);
+ if (dat->errorState)
+ {
+ pTaskbarInterface->SetProgressState(hwnd, dat->errorState);
+ if (!prg.run)
+ pTaskbarInterface->SetProgressValue(hwnd, 1, 1);
+ } else if (prg.run)
+ {
+ pTaskbarInterface->SetProgressState(hwnd, TBPF_NORMAL);
+ } else if (prg.init || prg.scan)
+ {
+ pTaskbarInterface->SetProgressState(hwnd, TBPF_INDETERMINATE);
+ } else {
+ pTaskbarInterface->SetProgressState(hwnd, TBPF_NOPROGRESS);
+ KillTimer(hwnd, 1);
+ }
+
+ if (prg.run)
+ {
+ pTaskbarInterface->SetProgressValue(hwnd, prg.totalProgress, prg.totalBytes);
+ }
+
+ }
+ } break;
+
+ }
+
+ return FALSE;
+}
+
+HWND FtMgr_Show(bool bForceActivate, bool bFromMenu)
+{
+ bool bAutoMin = DBGetContactSettingByte(NULL,"SRFile","AutoMin",0) != 0; /* lqbe */
+
+ bool bJustCreated = (hwndFtMgr == NULL);
+ if (bJustCreated)
+ {
+ hwndFtMgr = CreateDialog(hMirandaInst, MAKEINTRESOURCE(IDD_FTMGR), NULL, FtMgrDlgProc);
+ }
+ if (bFromMenu) /* lqbe */
+ {
+ ShowWindow(hwndFtMgr, SW_RESTORE);
+ ShowWindow(hwndFtMgr, SW_SHOW);
+ SetForegroundWindow(hwndFtMgr);
+ return hwndFtMgr;
+ }
+ else if (bAutoMin && bJustCreated) /* lqbe */
+ {
+ ShowWindow(hwndFtMgr, SW_HIDE);
+ ShowWindow(hwndFtMgr, SW_MINIMIZE);
+ return hwndFtMgr;
+ }
+ else if (bForceActivate) /* lqbe */
+ {
+ ShowWindow(hwndFtMgr, SW_RESTORE);
+ ShowWindow(hwndFtMgr, SW_SHOWNOACTIVATE);
+ SetForegroundWindow(hwndFtMgr);
+ return hwndFtMgr;
+ }
+ if (!bJustCreated && IsWindowVisible(hwndFtMgr))
+ return hwndFtMgr;
+
+ ShowWindow(hwndFtMgr, bAutoMin ? SW_SHOWMINNOACTIVE : SW_SHOWNOACTIVATE);
+ return hwndFtMgr;
+ }
+
+void FtMgr_Destroy()
+{
+ if (hwndFtMgr)
+ DestroyWindow(hwndFtMgr);
+}
+
+void FtMgr_ShowPage(int page)
+{
+ if (hwndFtMgr)
+ SendMessage(hwndFtMgr, WM_FT_SELECTPAGE, page, 0);
+}
+
+HWND FtMgr_AddTransfer(FileDlgData *fdd)
+{
+ bool bForceActivate = fdd->send || !DBGetContactSettingByte(NULL, "SRFile", "AutoAccept", 0);
+ TFtMgrData *dat = (TFtMgrData*)GetWindowLongPtr(FtMgr_Show(bForceActivate, false), GWLP_USERDATA);
+ if (dat == NULL) return NULL;
+ HWND hwndBox = fdd->send ? dat->hwndOutgoing : dat->hwndIncoming;
+ HWND hwndFt = CreateDialogParam(hMirandaInst, MAKEINTRESOURCE(IDD_FILETRANSFERINFO), hwndBox, DlgProcFileTransfer, (LPARAM)fdd);
+ ShowWindow(hwndFt, SW_SHOWNA);
+ SendMessage(hwndBox, WM_FT_ADD, 0, (LPARAM)hwndFt);
+ FtMgr_ShowPage(fdd->send ? 1 : 0);
+ return hwndFt;
+} \ No newline at end of file