/* 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 "..\..\core\commonheaders.h" #include "profilemanager.h" #include #define WM_INPUTCHANGED (WM_USER + 0x3000) #define WM_FOCUSTEXTBOX (WM_USER + 0x3001) typedef BOOL (__cdecl *ENUMPROFILECALLBACK) (TCHAR * fullpath, TCHAR * profile, LPARAM lParam); struct DetailsPageInit { int pageCount; OPTIONSDIALOGPAGE *odp; }; struct DetailsPageData { DLGTEMPLATE *pTemplate; HINSTANCE hInst; DLGPROC dlgProc; HWND hwnd; int changed; }; struct DlgProfData { PROPSHEETHEADER * psh; HWND hwndOK; // handle to OK button PROFILEMANAGERDATA * pd; HANDLE hFileNotify; }; struct DetailsData { HINSTANCE hInstIcmp; HFONT hBoldFont; int pageCount; int currentPage; struct DetailsPageData *opd; RECT rcDisplay; struct DlgProfData * prof; }; struct ProfileEnumData { HWND hwnd; TCHAR* szProfile; }; extern TCHAR mirandabootini[MAX_PATH]; char **GetServiceModePluginsList(void); void SetServiceModePlugin( int idx ); static void ThemeDialogBackground(HWND hwnd) { if (enableThemeDialogTexture) enableThemeDialogTexture(hwnd, ETDT_ENABLETAB); } static int findProfiles(TCHAR * szProfileDir, ENUMPROFILECALLBACK callback, LPARAM lParam) { // find in Miranda IM profile subfolders HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; TCHAR searchspec[MAX_PATH]; mir_sntprintf(searchspec, SIZEOF(searchspec), _T("%s\\*.*"), szProfileDir); hFind = FindFirstFile(searchspec, &ffd); if ( hFind == INVALID_HANDLE_VALUE ) return 0; do { // find all subfolders except "." and ".." if ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && _tcscmp(ffd.cFileName, _T(".")) && _tcscmp(ffd.cFileName, _T("..")) ) { TCHAR buf[MAX_PATH], profile[MAX_PATH]; mir_sntprintf(buf, SIZEOF(buf), _T("%s\\%s\\%s.dat"), szProfileDir, ffd.cFileName, ffd.cFileName); if (_taccess(buf, 0) == 0) { mir_sntprintf(profile, SIZEOF(profile), _T("%s.dat"), ffd.cFileName); if ( !callback(buf, profile, lParam )) break; } } } while ( FindNextFile(hFind, &ffd) ); FindClose(hFind); return 1; } static LRESULT CALLBACK ProfileNameValidate(HWND edit, UINT msg, WPARAM wParam, LPARAM lParam) { if ( msg == WM_CHAR ) { if ( _tcschr( _T(".?/\\#' "), (TCHAR)wParam) != 0 ) return 0; PostMessage(GetParent(edit),WM_INPUTCHANGED,0,0); } return CallWindowProc((WNDPROC)GetWindowLongPtr(edit,GWLP_USERDATA),edit,msg,wParam,lParam); } static int FindDbProviders(const char*, DATABASELINK * dblink, LPARAM lParam) { HWND hwndDlg = (HWND)lParam; HWND hwndCombo = GetDlgItem(hwndDlg, IDC_PROFILEDRIVERS); char szName[64]; if ( dblink->getFriendlyName(szName,SIZEOF(szName),1) == 0 ) { // add to combo box TCHAR* p = LangPackPcharToTchar( szName ); LRESULT index = SendMessage( hwndCombo, CB_ADDSTRING, 0, (LPARAM)p ); mir_free( p ); SendMessage(hwndCombo, CB_SETITEMDATA, index, (LPARAM)dblink); } return DBPE_CONT; } static INT_PTR CALLBACK DlgProfileNew(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { struct DlgProfData * dat = (struct DlgProfData *)GetWindowLongPtr(hwndDlg,GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: TranslateDialogDefault( hwndDlg ); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); dat = (struct DlgProfData *)lParam; { // fill in the db plugins present PLUGIN_DB_ENUM dbe; dbe.cbSize = sizeof(dbe); dbe.pfnEnumCallback = (int(*)(const char*,void*,LPARAM))FindDbProviders; dbe.lParam = (LPARAM)hwndDlg; if ( CallService( MS_PLUGINS_ENUMDBPLUGINS, 0, ( LPARAM )&dbe ) == -1 ) { // no plugins?! EnableWindow( GetDlgItem(hwndDlg, IDC_PROFILEDRIVERS ), FALSE ); EnableWindow( GetDlgItem(hwndDlg, IDC_PROFILENAME ), FALSE ); ShowWindow( GetDlgItem(hwndDlg, IDC_NODBDRIVERS ), TRUE ); } // default item SendDlgItemMessage(hwndDlg, IDC_PROFILEDRIVERS, CB_SETCURSEL, 0, 0); } // subclass the profile name box { HWND hwndProfile = GetDlgItem(hwndDlg, IDC_PROFILENAME); WNDPROC proc = (WNDPROC)GetWindowLongPtr(hwndProfile, GWLP_WNDPROC); SetWindowLongPtr(hwndProfile,GWLP_USERDATA,(LONG_PTR)proc); SetWindowLongPtr(hwndProfile,GWLP_WNDPROC,(LONG_PTR)ProfileNameValidate); } // decide if there is a default profile name given in the INI and if it should be used if (dat->pd->noProfiles || (shouldAutoCreate(dat->pd->szProfile) && _taccess(dat->pd->szProfile, 0))) { TCHAR* profile = _tcsrchr(dat->pd->szProfile, '\\'); if (profile) ++profile; else profile = dat->pd->szProfile; TCHAR *p = _tcsrchr(profile, '.'); TCHAR c = 0; if (p) { c = *p; *p = 0; } SetDlgItemText(hwndDlg, IDC_PROFILENAME, profile); if (c) *p = c; } // focus on the textbox PostMessage( hwndDlg, WM_FOCUSTEXTBOX, 0, 0 ); return TRUE; case WM_FOCUSTEXTBOX: SetFocus( GetDlgItem( hwndDlg, IDC_PROFILENAME )); break; case WM_INPUTCHANGED: // when input in the edit box changes SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); EnableWindow( dat->hwndOK, GetWindowTextLength( GetDlgItem( hwndDlg, IDC_PROFILENAME )) > 0 ); break; case WM_SHOWWINDOW: if ( wParam ) { SetWindowText( dat->hwndOK, TranslateT("&Create")); SendMessage( hwndDlg, WM_INPUTCHANGED, 0, 0 ); } break; case WM_NOTIFY: { NMHDR* hdr = ( NMHDR* )lParam; if ( hdr && hdr->code == PSN_APPLY && dat && IsWindowVisible( hwndDlg )) { TCHAR szName[MAX_PATH]; LRESULT curSel = SendDlgItemMessage(hwndDlg,IDC_PROFILEDRIVERS,CB_GETCURSEL,0,0); if ( curSel == CB_ERR ) break; // should never happen GetDlgItemText(hwndDlg, IDC_PROFILENAME, szName, SIZEOF( szName )); if ( szName[0] == 0 ) break; // profile placed in "profile_name" subfolder mir_sntprintf( dat->pd->szProfile, MAX_PATH, _T("%s\\%s\\%s.dat"), dat->pd->szProfileDir, szName, szName ); dat->pd->newProfile = 1; dat->pd->dblink = (DATABASELINK *)SendDlgItemMessage( hwndDlg, IDC_PROFILEDRIVERS, CB_GETITEMDATA, ( WPARAM )curSel, 0 ); if ( makeDatabase( dat->pd->szProfile, dat->pd->dblink, hwndDlg ) == 0 ) { SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE ); } } } break; } return FALSE; } static int DetectDbProvider(const char*, DATABASELINK * dblink, LPARAM lParam) { int error; #ifdef _UNICODE char* fullpath = makeFileName(( TCHAR* )lParam ); #else char* fullpath = (char*)lParam; #endif int ret = dblink->grokHeader(fullpath, &error); #ifdef _UNICODE mir_free( fullpath ); #endif if ( ret == 0) { #ifdef _UNICODE char tmp[ MAX_PATH ]; dblink->getFriendlyName(tmp, SIZEOF(tmp), 1); MultiByteToWideChar(CP_ACP, 0, tmp, -1, (TCHAR*)lParam, MAX_PATH); #else dblink->getFriendlyName((TCHAR*)lParam, MAX_PATH, 1); #endif return DBPE_HALT; } return DBPE_CONT; } BOOL EnumProfilesForList(TCHAR * fullpath, TCHAR * profile, LPARAM lParam) { ProfileEnumData *ped = (ProfileEnumData*)lParam; HWND hwndList = GetDlgItem(ped->hwnd, IDC_PROFILELIST); TCHAR sizeBuf[64]; int iItem=0; struct _stat statbuf; bool bFileExists = false, bFileLocked = true; TCHAR* p = _tcsrchr(profile, '.'); _tcscpy(sizeBuf, _T("0 KB")); if ( p != NULL ) *p=0; LVITEM item = { 0 }; item.mask = LVIF_TEXT | LVIF_IMAGE; item.pszText = profile; item.iItem = 0; if ( _tstat(fullpath, &statbuf) == 0) { if ( statbuf.st_size > 1000000 ) { mir_sntprintf(sizeBuf,SIZEOF(sizeBuf), _T("%.3lf"), (double)statbuf.st_size / 1048576.0 ); _tcscpy(sizeBuf+5, _T(" MB")); } else { mir_sntprintf(sizeBuf,SIZEOF(sizeBuf), _T("%.3lf"), (double)statbuf.st_size / 1024.0 ); _tcscpy(sizeBuf+5, _T(" KB")); } bFileExists = TRUE; bFileLocked = !fileExist(fullpath); } item.iImage = bFileLocked; iItem = SendMessage( hwndList, LVM_INSERTITEM, 0, (LPARAM)&item ); if ( lstrcmpi(ped->szProfile, fullpath) == 0 ) ListView_SetItemState(hwndList, iItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); item.iItem = iItem; item.iSubItem = 2; item.pszText = sizeBuf; SendMessage( hwndList, LVM_SETITEMTEXT, iItem, (LPARAM)&item ); if ( bFileExists ) { PLUGIN_DB_ENUM dbe; TCHAR szPath[MAX_PATH]; LVITEM item2; item2.mask = LVIF_TEXT; item2.iItem = iItem; dbe.cbSize = sizeof(dbe); dbe.pfnEnumCallback = (int(*)(const char*,void*,LPARAM))DetectDbProvider; dbe.lParam = (LPARAM)szPath; _tcscpy(szPath, fullpath); if ( CallService( MS_PLUGINS_ENUMDBPLUGINS, 0, ( LPARAM )&dbe ) == 1 ) { if (bFileLocked) { // file locked item2.pszText = TranslateT( "" ); item2.iSubItem = 1; SendMessage( hwndList, LVM_SETITEMTEXT, iItem, ( LPARAM )&item2 ); } else { item.pszText = szPath; item.iSubItem = 1; SendMessage( hwndList, LVM_SETITEMTEXT, iItem, (LPARAM)&item ); } } item2.iSubItem = 3; item2.pszText = rtrim( _tctime( &statbuf.st_ctime )); SendMessage( hwndList, LVM_SETITEMTEXT, iItem, (LPARAM)&item2 ); item2.iSubItem = 4; item2.pszText = rtrim( _tctime( &statbuf.st_mtime )); SendMessage( hwndList, LVM_SETITEMTEXT, iItem, (LPARAM)&item2 ); } return TRUE; } void DeleteProfile(HWND hwndList, int iItem, DlgProfData* dat) { if (iItem < 0) return; TCHAR profile[MAX_PATH], profilef[MAX_PATH*2]; LVITEM item = {0}; item.mask = LVIF_TEXT; item.iItem = iItem; item.pszText = profile; item.cchTextMax = SIZEOF(profile); if (!ListView_GetItem(hwndList, &item)) return; mir_sntprintf(profilef, SIZEOF(profilef), TranslateT("Are you sure you want to remove profile \"%s\"?"), profile); if (IDYES != MessageBox(NULL, profilef, _T("Miranda IM"), MB_YESNO | MB_TASKMODAL | MB_ICONWARNING)) return; mir_sntprintf(profilef, SIZEOF(profilef), _T("%s\\%s%c"), dat->pd->szProfileDir, profile, 0); SHFILEOPSTRUCT sf = {0}; sf.wFunc = FO_DELETE; sf.pFrom = profilef; sf.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_ALLOWUNDO; SHFileOperation(&sf); ListView_DeleteItem(hwndList, item.iItem); } static INT_PTR CALLBACK DlgProfileSelect(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { DlgProfData* dat = (struct DlgProfData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); HWND hwndList = GetDlgItem(hwndDlg, IDC_PROFILELIST); switch (msg) { case WM_INITDIALOG: { HIMAGELIST hImgList; LVCOLUMN col; TranslateDialogDefault( hwndDlg ); dat = (DlgProfData*) lParam; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); // set columns col.mask = LVCF_TEXT | LVCF_WIDTH; col.pszText = TranslateT("Profile"); col.cx=122; ListView_InsertColumn( hwndList, 0, &col ); col.pszText = TranslateT("Driver"); col.cx=100; ListView_InsertColumn( hwndList, 1, &col ); col.pszText = TranslateT("Size"); col.cx=60; ListView_InsertColumn( hwndList, 2, &col ); col.pszText = TranslateT("Created"); col.cx=145; ListView_InsertColumn( hwndList, 3, &col ); col.pszText = TranslateT("Modified"); col.cx=145; ListView_InsertColumn( hwndList, 4, &col ); // icons hImgList = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 2, 1); ImageList_AddIcon_NotShared(hImgList, MAKEINTRESOURCE(IDI_USERDETAILS)); ImageList_AddIcon_NotShared(hImgList, MAKEINTRESOURCE(IDI_DELETE)); // LV will destroy the image list SetWindowLongPtr(hwndList, GWL_STYLE, GetWindowLongPtr(hwndList, GWL_STYLE) | LVS_SORTASCENDING); ListView_SetImageList(hwndList, hImgList, LVSIL_SMALL); ListView_SetExtendedListViewStyle(hwndList, ListView_GetExtendedListViewStyle(hwndList) | LVS_EX_DOUBLEBUFFER | LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT); // find all the profiles ProfileEnumData ped = { hwndDlg, dat->pd->szProfile }; findProfiles(dat->pd->szProfileDir, EnumProfilesForList, (LPARAM)&ped); PostMessage(hwndDlg, WM_FOCUSTEXTBOX, 0, 0); dat->hFileNotify = FindFirstChangeNotification(dat->pd->szProfileDir, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE); if (dat->hFileNotify != INVALID_HANDLE_VALUE) SetTimer(hwndDlg, 0, 1200, NULL); return TRUE; } case WM_DESTROY: KillTimer(hwndDlg, 0); FindCloseChangeNotification(dat->hFileNotify); break; case WM_TIMER: if (WaitForSingleObject(dat->hFileNotify, 0) == WAIT_OBJECT_0) { ListView_DeleteAllItems(hwndList); ProfileEnumData ped = { hwndDlg, dat->pd->szProfile }; findProfiles(dat->pd->szProfileDir, EnumProfilesForList, (LPARAM)&ped); FindNextChangeNotification(dat->hFileNotify); } break; case WM_FOCUSTEXTBOX: SetFocus(hwndList); if (dat->pd->szProfile[0] == 0 || ListView_GetSelectedCount(hwndList) == 0) ListView_SetItemState(hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); break; case WM_SHOWWINDOW: if ( wParam ) { SetWindowText(dat->hwndOK, TranslateT("&Run")); EnableWindow(dat->hwndOK, ListView_GetSelectedCount(hwndList) == 1); } break; case WM_CONTEXTMENU: { LVHITTESTINFO lvht = {0}; lvht.pt.x = GET_X_LPARAM(lParam); lvht.pt.y = GET_Y_LPARAM(lParam); ScreenToClient(hwndList, &lvht.pt); if (ListView_HitTest(hwndList, &lvht) < 0) break; lvht.pt.x = GET_X_LPARAM(lParam); lvht.pt.y = GET_Y_LPARAM(lParam); HMENU hMenu = CreatePopupMenu(); AppendMenu(hMenu, MF_STRING, 1, TranslateT("Run")); AppendMenu(hMenu, MF_SEPARATOR, 2, NULL); AppendMenu(hMenu, MF_STRING, 3, TranslateT("Delete")); int index = TrackPopupMenu(hMenu, TPM_RETURNCMD, lvht.pt.x, lvht.pt.y, 0, hwndDlg, NULL); switch (index) { case 1: SendMessage(GetParent(hwndDlg), WM_COMMAND, IDOK, 0); break; case 3: DeleteProfile(hwndList, lvht.iItem, dat); break; } DestroyMenu(hMenu); break; } case WM_NOTIFY: { LPNMHDR hdr = (LPNMHDR) lParam; if (hdr && hdr->code == PSN_INFOCHANGED) break; if (hdr && hdr->idFrom == IDC_PROFILELIST) { switch (hdr->code) { case LVN_ITEMCHANGED: EnableWindow(dat->hwndOK, ListView_GetSelectedCount(hwndList) == 1); case NM_DBLCLK: { LVITEM item = {0}; TCHAR profile[MAX_PATH]; if (dat == NULL) break; item.mask = LVIF_TEXT; item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED | LVNI_ALL); item.pszText = profile; item.cchTextMax = SIZEOF(profile); if (ListView_GetItem(hwndList, &item)) { // profile is placed in "profile_name" subfolder TCHAR tmpPath[MAX_PATH]; mir_sntprintf(tmpPath, SIZEOF(tmpPath), _T("%s\\%s.dat"), dat->pd->szProfileDir, profile); HANDLE hFile = CreateFile(tmpPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile == INVALID_HANDLE_VALUE) mir_sntprintf(dat->pd->szProfile, MAX_PATH, _T("%s\\%s\\%s.dat"), dat->pd->szProfileDir, profile, profile); else _tcscpy(dat->pd->szProfile, tmpPath); CloseHandle(hFile); if (hdr->code == NM_DBLCLK) EndDialog(GetParent(hwndDlg), 1); } return TRUE; } case LVN_KEYDOWN: { LPNMLVKEYDOWN hdrk = (LPNMLVKEYDOWN) lParam; if (hdrk->wVKey == VK_DELETE) DeleteProfile(hwndList, ListView_GetNextItem(hwndList, -1, LVNI_SELECTED | LVNI_ALL), dat); break; } } } break; } } return FALSE; } static INT_PTR CALLBACK DlgProfileManager(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { struct DetailsData* dat = ( struct DetailsData* )GetWindowLongPtr( hwndDlg, GWLP_USERDATA ); switch (msg) { case WM_INITDIALOG: { struct DlgProfData * prof = (struct DlgProfData *)lParam; PROPSHEETHEADER *psh = prof->psh; TranslateDialogDefault(hwndDlg); SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadImage(hMirandaInst, MAKEINTRESOURCE(IDI_USERDETAILS),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0)); SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadImage(hMirandaInst, MAKEINTRESOURCE(IDI_USERDETAILS),IMAGE_ICON,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),0)); dat = (struct DetailsData*)mir_alloc(sizeof(struct DetailsData)); dat->prof = prof; prof->hwndOK = GetDlgItem( hwndDlg, IDOK ); EnableWindow( prof->hwndOK, FALSE ); SetWindowLongPtr( hwndDlg, GWLP_USERDATA, (LONG_PTR)dat ); { TCHAR buf[512]; mir_sntprintf(buf, SIZEOF(buf), _T("%s: %s\n%s"), TranslateT("Miranda Profiles from"), prof->pd->szProfileDir, TranslateT("Select or create your Miranda IM user profile")); SetDlgItemText(hwndDlg, IDC_NAME, buf); } { OPTIONSDIALOGPAGE *odp; int i; TCITEM tci; dat->currentPage = 0; dat->pageCount = psh->nPages; dat->opd = ( struct DetailsPageData* )mir_calloc( sizeof( struct DetailsPageData )*dat->pageCount ); odp = ( OPTIONSDIALOGPAGE* )psh->ppsp; tci.mask = TCIF_TEXT; for ( i=0; i < dat->pageCount; i++ ) { dat->opd[i].pTemplate = (DLGTEMPLATE *)LockResource(LoadResource(odp[i].hInstance,FindResourceA(odp[i].hInstance,odp[i].pszTemplate,MAKEINTRESOURCEA(5)))); dat->opd[i].dlgProc = odp[i].pfnDlgProc; dat->opd[i].hInst = odp[i].hInstance; dat->opd[i].hwnd = NULL; dat->opd[i].changed = 0; tci.pszText = ( TCHAR* )odp[i].ptszTitle; if (dat->prof->pd->noProfiles || shouldAutoCreate(dat->prof->pd->szProfile)) dat->currentPage = 1; TabCtrl_InsertItem( GetDlgItem(hwndDlg,IDC_TABS), i, &tci ); } } GetWindowRect(GetDlgItem(hwndDlg,IDC_TABS),&dat->rcDisplay); TabCtrl_AdjustRect(GetDlgItem(hwndDlg,IDC_TABS),FALSE,&dat->rcDisplay); { POINT pt = {0,0}; ClientToScreen( hwndDlg, &pt ); OffsetRect( &dat->rcDisplay, -pt.x, -pt.y ); } TabCtrl_SetCurSel( GetDlgItem( hwndDlg, IDC_TABS ), dat->currentPage ); dat->opd[dat->currentPage].hwnd = CreateDialogIndirectParam(dat->opd[dat->currentPage].hInst,dat->opd[dat->currentPage].pTemplate,hwndDlg,dat->opd[dat->currentPage].dlgProc,(LPARAM)dat->prof); ThemeDialogBackground( dat->opd[dat->currentPage].hwnd ); SetWindowPos( dat->opd[dat->currentPage].hwnd, HWND_TOP, dat->rcDisplay.left, dat->rcDisplay.top, 0, 0, SWP_NOSIZE ); { PSHNOTIFY pshn; pshn.hdr.code = PSN_INFOCHANGED; pshn.hdr.hwndFrom = dat->opd[dat->currentPage].hwnd; pshn.hdr.idFrom = 0; pshn.lParam = ( LPARAM )0; SendMessage( dat->opd[dat->currentPage].hwnd, WM_NOTIFY, 0, ( LPARAM )&pshn ); } // service mode combobox { char **list = GetServiceModePluginsList(); if ( !list ) { ShowWindow( GetDlgItem(hwndDlg, IDC_SM_LABEL ), FALSE ); ShowWindow( GetDlgItem(hwndDlg, IDC_SM_COMBO ), FALSE ); } else { int i = 0; LRESULT index; HWND hwndCombo = GetDlgItem(hwndDlg, IDC_SM_COMBO ); index = SendMessage( hwndCombo, CB_ADDSTRING, 0, (LPARAM)_T("") ); SendMessage( hwndCombo, CB_SETITEMDATA, index, (LPARAM)-1 ); SendMessage( hwndCombo, CB_SETCURSEL, 0, 0); while ( list[i] ) { TCHAR *str = LangPackPcharToTchar( list[i] ); index = SendMessage( hwndCombo, CB_ADDSTRING, 0, (LPARAM)str ); mir_free(str); SendMessage( hwndCombo, CB_SETITEMDATA, index, (LPARAM)i ); i++; } mir_free(list); } } ShowWindow( dat->opd[dat->currentPage].hwnd, SW_SHOW ); return TRUE; } case WM_CTLCOLORSTATIC: switch ( GetDlgCtrlID(( HWND )lParam )) { case IDC_WHITERECT: SetBkColor(( HDC )wParam, GetSysColor( COLOR_WINDOW )); return ( INT_PTR )GetSysColorBrush( COLOR_WINDOW ); } break; case PSM_CHANGED: dat->opd[dat->currentPage].changed=1; return TRUE; case PSM_FORCECHANGED: { PSHNOTIFY pshn; int i; pshn.hdr.code = PSN_INFOCHANGED; pshn.hdr.idFrom = 0; pshn.lParam = (LPARAM)0; for ( i=0; i < dat->pageCount; i++ ) { pshn.hdr.hwndFrom = dat->opd[i].hwnd; if ( dat->opd[i].hwnd != NULL ) SendMessage(dat->opd[i].hwnd,WM_NOTIFY,0,(LPARAM)&pshn); } break; } case WM_NOTIFY: switch(wParam) { case IDC_TABS: switch(((LPNMHDR)lParam)->code) { case TCN_SELCHANGING: { PSHNOTIFY pshn; if ( dat->currentPage == -1 || dat->opd[dat->currentPage].hwnd == NULL ) break; pshn.hdr.code = PSN_KILLACTIVE; pshn.hdr.hwndFrom = dat->opd[dat->currentPage].hwnd; pshn.hdr.idFrom = 0; pshn.lParam = 0; if ( SendMessage( dat->opd[dat->currentPage].hwnd, WM_NOTIFY, 0, ( LPARAM )&pshn )) { SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, TRUE ); return TRUE; } break; } case TCN_SELCHANGE: if ( dat->currentPage != -1 && dat->opd[dat->currentPage].hwnd != NULL ) ShowWindow( dat->opd[ dat->currentPage ].hwnd, SW_HIDE ); dat->currentPage = TabCtrl_GetCurSel(GetDlgItem(hwndDlg,IDC_TABS)); if ( dat->currentPage != -1 ) { if ( dat->opd[dat->currentPage].hwnd == NULL ) { PSHNOTIFY pshn; dat->opd[dat->currentPage].hwnd=CreateDialogIndirectParam(dat->opd[dat->currentPage].hInst,dat->opd[dat->currentPage].pTemplate,hwndDlg,dat->opd[dat->currentPage].dlgProc,(LPARAM)dat->prof); ThemeDialogBackground(dat->opd[dat->currentPage].hwnd); SetWindowPos(dat->opd[dat->currentPage].hwnd,HWND_TOP,dat->rcDisplay.left,dat->rcDisplay.top,0,0,SWP_NOSIZE); pshn.hdr.code=PSN_INFOCHANGED; pshn.hdr.hwndFrom=dat->opd[dat->currentPage].hwnd; pshn.hdr.idFrom=0; pshn.lParam=(LPARAM)0; SendMessage(dat->opd[dat->currentPage].hwnd,WM_NOTIFY,0,(LPARAM)&pshn); } ShowWindow(dat->opd[dat->currentPage].hwnd,SW_SHOW); } break; } break; } break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDCANCEL: { int i; PSHNOTIFY pshn; pshn.hdr.idFrom=0; pshn.lParam=0; pshn.hdr.code=PSN_RESET; for (i=0;ipageCount;i++) { if (dat->opd[i].hwnd == NULL || !dat->opd[i].changed) continue; pshn.hdr.hwndFrom=dat->opd[i].hwnd; SendMessage(dat->opd[i].hwnd,WM_NOTIFY,0,(LPARAM)&pshn); } EndDialog(hwndDlg,0); } break; case IDC_REMOVE: if (!dat->prof->pd->noProfiles) { HWND hwndList = GetDlgItem(dat->opd[0].hwnd, IDC_PROFILELIST); DeleteProfile(hwndList, ListView_GetNextItem(hwndList, -1, LVNI_SELECTED | LVNI_ALL), dat->prof); } break; case IDOK: { int i; PSHNOTIFY pshn; pshn.hdr.idFrom=0; pshn.lParam=(LPARAM)0; if ( dat->currentPage != -1 ) { pshn.hdr.code = PSN_KILLACTIVE; pshn.hdr.hwndFrom = dat->opd[dat->currentPage].hwnd; if ( SendMessage(dat->opd[dat->currentPage].hwnd, WM_NOTIFY, 0, ( LPARAM )&pshn )) break; } pshn.hdr.code=PSN_APPLY; for ( i=0; i < dat->pageCount; i++ ) { if ( dat->opd[i].hwnd == NULL || !dat->opd[i].changed ) continue; pshn.hdr.hwndFrom = dat->opd[i].hwnd; SendMessage( dat->opd[i].hwnd, WM_NOTIFY, 0, ( LPARAM )&pshn ); if ( GetWindowLongPtr( dat->opd[i].hwnd, DWLP_MSGRESULT ) == PSNRET_INVALID_NOCHANGEPAGE) { TabCtrl_SetCurSel( GetDlgItem( hwndDlg, IDC_TABS ), i ); if ( dat->currentPage != -1 ) ShowWindow( dat->opd[ dat->currentPage ].hwnd, SW_HIDE ); dat->currentPage = i; ShowWindow( dat->opd[dat->currentPage].hwnd, SW_SHOW ); return 0; } } EndDialog(hwndDlg,1); break; } } break; case WM_DESTROY: { LRESULT curSel = SendDlgItemMessage(hwndDlg,IDC_SM_COMBO,CB_GETCURSEL,0,0); if ( curSel != CB_ERR ) { int idx = SendDlgItemMessage( hwndDlg, IDC_SM_COMBO, CB_GETITEMDATA, ( WPARAM )curSel, 0 ); SetServiceModePlugin(idx); } } DestroyIcon(( HICON )SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0)); DestroyIcon(( HICON )SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0)); DeleteObject( dat->hBoldFont ); { int i; for ( i=0; i < dat->pageCount; i++ ) if ( dat->opd[i].hwnd != NULL ) DestroyWindow( dat->opd[i].hwnd ); } mir_free( dat->opd ); mir_free( dat ); break; } return FALSE; } static int AddProfileManagerPage(struct DetailsPageInit * opi, OPTIONSDIALOGPAGE * odp) { if ( odp->cbSize != sizeof( OPTIONSDIALOGPAGE )) return 1; opi->odp = ( OPTIONSDIALOGPAGE* )mir_realloc( opi->odp, sizeof( OPTIONSDIALOGPAGE )*( opi->pageCount+1 )); { OPTIONSDIALOGPAGE* p = opi->odp + opi->pageCount++; p->cbSize = sizeof(OPTIONSDIALOGPAGE); p->hInstance = odp->hInstance; p->pfnDlgProc = odp->pfnDlgProc; p->position = odp->position; p->ptszTitle = LangPackPcharToTchar(odp->pszTitle); p->pszGroup = NULL; p->groupPosition = odp->groupPosition; p->hGroupIcon = odp->hGroupIcon; p->hIcon = odp->hIcon; if (( DWORD_PTR )odp->pszTemplate & 0xFFFF0000 ) p->pszTemplate = mir_strdup( odp->pszTemplate ); else p->pszTemplate = odp->pszTemplate; } return 0; } int getProfileManager(PROFILEMANAGERDATA * pd) { DetailsPageInit opi; opi.pageCount=0; opi.odp=NULL; { OPTIONSDIALOGPAGE odp = { 0 }; odp.cbSize = sizeof(odp); odp.pszTitle = LPGEN("My Profiles"); odp.pfnDlgProc = DlgProfileSelect; odp.pszTemplate = MAKEINTRESOURCEA(IDD_PROFILE_SELECTION); odp.hInstance = hMirandaInst; AddProfileManagerPage(&opi, &odp); odp.pszTitle = LPGEN("New Profile"); odp.pszTemplate = MAKEINTRESOURCEA(IDD_PROFILE_NEW); odp.pfnDlgProc = DlgProfileNew; AddProfileManagerPage(&opi, &odp); } PROPSHEETHEADER psh = { 0 }; psh.dwSize = sizeof(psh); psh.dwFlags = PSH_PROPSHEETPAGE|PSH_NOAPPLYNOW; psh.hwndParent = NULL; psh.nPages = opi.pageCount; psh.pStartPage = 0; psh.ppsp = (PROPSHEETPAGE*)opi.odp; DlgProfData prof; prof.pd = pd; prof.psh = &psh; int rc = DialogBoxParam(hMirandaInst,MAKEINTRESOURCE(IDD_PROFILEMANAGER),NULL,DlgProfileManager,(LPARAM)&prof); if ( rc != -1 ) for ( int i=0; i < opi.pageCount; i++ ) { mir_free(( char* )opi.odp[i].pszTitle ); mir_free( opi.odp[i].pszGroup ); if (( DWORD_PTR )opi.odp[i].pszTemplate & 0xFFFF0000 ) mir_free(( char* )opi.odp[i].pszTemplate ); } if ( opi.odp != NULL ) mir_free(opi.odp); return rc; }