From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/src/modules/database/database.c | 377 +++++++++++ miranda-wine/src/modules/database/dbini.c | 495 +++++++++++++++ miranda-wine/src/modules/database/dblists.c | 149 +++++ miranda-wine/src/modules/database/dblists.h | 36 ++ miranda-wine/src/modules/database/dbtime.c | 239 +++++++ miranda-wine/src/modules/database/profilemanager.c | 696 +++++++++++++++++++++ miranda-wine/src/modules/database/profilemanager.h | 37 ++ 7 files changed, 2029 insertions(+) create mode 100644 miranda-wine/src/modules/database/database.c create mode 100644 miranda-wine/src/modules/database/dbini.c create mode 100644 miranda-wine/src/modules/database/dblists.c create mode 100644 miranda-wine/src/modules/database/dblists.h create mode 100644 miranda-wine/src/modules/database/dbtime.c create mode 100644 miranda-wine/src/modules/database/profilemanager.c create mode 100644 miranda-wine/src/modules/database/profilemanager.h (limited to 'miranda-wine/src/modules/database') diff --git a/miranda-wine/src/modules/database/database.c b/miranda-wine/src/modules/database/database.c new file mode 100644 index 0000000..ead8acd --- /dev/null +++ b/miranda-wine/src/modules/database/database.c @@ -0,0 +1,377 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 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 "profilemanager.h" + + +// from the plugin loader, hate extern but the db frontend is pretty much tied +extern PLUGINLINK pluginCoreLink; +// contains the location of mirandaboot.ini +extern char mirandabootini[MAX_PATH]; + +// returns 1 if the profile path was returned, without trailing slash +int getProfilePath(char * buf, size_t cch) +{ + char profiledir[MAX_PATH]; + char exprofiledir[MAX_PATH]; + char * p = 0; + // grab the base location now + GetModuleFileNameA(NULL, buf, cch); + p = strrchr(buf, '\\'); + if ( p != 0 ) *p=0; + // change to this location, or "." wont expand properly + _chdir(buf); + GetPrivateProfileStringA("Database", "ProfileDir", ".", profiledir, SIZEOF(profiledir), mirandabootini); + // get the string containing envars and maybe relative paths + // get rid of the vars + ExpandEnvironmentStringsA(profiledir, exprofiledir, SIZEOF(exprofiledir)); + if ( _fullpath(profiledir, exprofiledir, SIZEOF(profiledir)) != 0 ) { + /* XXX: really use CreateDirectory()? it only creates the last dir given a\b\c, SHCreateDirectory() + does what we want however thats 2000+ only */ + DWORD dw = INVALID_FILE_ATTRIBUTES; + CreateDirectoryA(profiledir, NULL); + dw=GetFileAttributesA(profiledir); + if ( dw != INVALID_FILE_ATTRIBUTES && dw&FILE_ATTRIBUTE_DIRECTORY ) { + strncpy(buf, profiledir, cch); + p = strrchr(buf, '\\'); + // if the char after '\' is null then change '\' to null + if ( p != 0 && *(++p)==0 ) *(--p)=0; + return 1; + } + } + // this never happens, usually C:\ is always returned + return 0; +} + +// returns 1 if *.dat spec is matched +int isValidProfileName(char * name) +{ + char * p = strrchr(name, '.'); + if ( p ) { + p++; + if ( lstrcmpiA( p, "dat" ) == 0 ) { + if ( p[3] == 0 ) return 1; + } + } + return 0; +} + +// returns 1 if a single profile (full path) is found within the profile dir +static int getProfile1(char * szProfile, size_t cch, char * profiledir, BOOL * noProfiles) +{ + int rc = 1; + char searchspec[MAX_PATH]; + WIN32_FIND_DATAA ffd; + HANDLE hFind = INVALID_HANDLE_VALUE; + unsigned int found=0; + mir_snprintf(searchspec,SIZEOF(searchspec),"%s\\*.dat", profiledir); + hFind = FindFirstFileA(searchspec, &ffd); + if ( hFind != INVALID_HANDLE_VALUE ) + { + // make sure the first hit is actually a *.dat file + if ( !(ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && isValidProfileName(ffd.cFileName) ) + { + // copy the profile name early cos it might be the only one + mir_snprintf(szProfile, cch, "%s\\%s", profiledir, ffd.cFileName); + found++; + // this might be the only dat but there might be a few wrong things returned before another *.dat + while ( FindNextFileA(hFind,&ffd) ) { + // found another *.dat, but valid? + if ( !(ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && isValidProfileName(ffd.cFileName) ) { + rc=0; + found++; + break; + } //if + } // while + } //if + FindClose(hFind); + } + if ( found == 0 && noProfiles != 0 ) { + *noProfiles=TRUE; + rc=0; + } + return rc; +} + +// returns 1 if something that looks like a profile is there +static int getProfileCmdLineArgs(char * szProfile, size_t cch) +{ + char *szCmdLine=GetCommandLineA(); + char *szEndOfParam; + char szThisParam[1024]; + int firstParam=1; + + while(szCmdLine[0]) { + if(szCmdLine[0]=='"') { + szEndOfParam=strchr(szCmdLine+1,'"'); + if(szEndOfParam==NULL) break; + lstrcpynA(szThisParam,szCmdLine+1,min( SIZEOF(szThisParam),szEndOfParam-szCmdLine)); + szCmdLine=szEndOfParam+1; + } + else { + szEndOfParam=szCmdLine+strcspn(szCmdLine," \t"); + lstrcpynA(szThisParam,szCmdLine,min( SIZEOF(szThisParam),szEndOfParam-szCmdLine+1)); + szCmdLine=szEndOfParam; + } + while(*szCmdLine && *szCmdLine<=' ') szCmdLine++; + if(firstParam) {firstParam=0; continue;} //first param is executable name + if(szThisParam[0]=='/' || szThisParam[0]=='-') continue; //no switches supported + ExpandEnvironmentStringsA(szThisParam,szProfile,cch); + return 1; + } + return 0; +} + +// returns 1 if a valid filename (incl. dat) is found, includes fully qualified path +static int getProfileCmdLine(char * szProfile, size_t cch, char * profiledir) +{ + char buf[MAX_PATH]; + HANDLE hFile; + int rc; + if ( getProfileCmdLineArgs(buf, SIZEOF(buf)) ) { + // have something that looks like a .dat, with or without .dat in the filename + if ( !isValidProfileName(buf) ) mir_snprintf(buf, SIZEOF(buf)-5,"%s.dat",buf); + // expand the relative to a full path , which might fail + if ( _fullpath(szProfile, buf, cch) != 0 ) { + hFile=CreateFileA(szProfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + rc=hFile != INVALID_HANDLE_VALUE; + CloseHandle(hFile); + return rc; + } + return 0; + } + return 0; +} + +// returns 1 if the profile manager should be shown +static int showProfileManager(void) +{ + char Mgr[32]; + // is control pressed? + if (GetAsyncKeyState(VK_CONTROL)&0x8000) return 1; + // wanna show it? + GetPrivateProfileStringA("Database", "ShowProfileMgr", "never", Mgr, SIZEOF(Mgr), mirandabootini); + if ( _strcmpi(Mgr,"yes") == 0 ) return 1; + return 0; +} + +// returns 1 if a default profile should be selected instead of showing the manager. +static int getProfileAutoRun(char * szProfile, size_t cch, char * profiledir) +{ + char Mgr[32]; + char env_profile[MAX_PATH]; + char exp_profile[MAX_PATH]; + GetPrivateProfileStringA("Database", "ShowProfileMgr", "", Mgr, SIZEOF(Mgr), mirandabootini); + if ( lstrcmpiA(Mgr,"never") ) return 0; + GetPrivateProfileStringA("Database", "DefaultProfile", "", env_profile, SIZEOF(env_profile), mirandabootini); + if ( lstrlenA(env_profile) == 0 ) return 0; + ExpandEnvironmentStringsA(env_profile, exp_profile, SIZEOF(exp_profile)); + mir_snprintf(szProfile, cch, "%s\\%s.dat", profiledir, exp_profile); + return 1; +} + + + +// returns 1 if a profile was selected +static int getProfile(char * szProfile, size_t cch) +{ + char profiledir[MAX_PATH]; + PROFILEMANAGERDATA pd; + ZeroMemory(&pd,sizeof(pd)); + getProfilePath(profiledir,SIZEOF(profiledir)); + if ( getProfileCmdLine(szProfile, cch, profiledir) ) return 1; + if ( getProfileAutoRun(szProfile, cch, profiledir) ) return 1; + if ( !showProfileManager() && getProfile1(szProfile, cch, profiledir, &pd.noProfiles) ) return 1; + else { + pd.szProfile=szProfile; + pd.szProfileDir=profiledir; + return getProfileManager(&pd); + } +} + +// called by the UI, return 1 on success, use link to create profile, set error if any +int makeDatabase(char * profile, DATABASELINK * link, HWND hwndDlg) +{ + char buf[256]; + int err=0; + // check if the file already exists + HANDLE hFile=CreateFileA(profile, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + char * file = strrchr(profile,'\\'); + file++; + if ( hFile != INVALID_HANDLE_VALUE ) { + CloseHandle(hFile); + mir_snprintf(buf, SIZEOF(buf), Translate("The profile '%s' already exists. Do you want to move it to the " + "Recycle Bin? \n\nWARNING: The profile will be deleted if Recycle Bin is disabled.\nWARNING: A profile may contain confidential information and should be properly deleted."),file); + // file already exists! + if ( MessageBoxA(hwndDlg, buf, Translate("The profile already exists"), MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2) != IDYES ) return 0; + // move the file + { + char szName[MAX_PATH]; // SHFileOperation needs a "double null" + SHFILEOPSTRUCTA sf; + ZeroMemory(&sf,sizeof(sf)); + sf.wFunc=FO_DELETE; + sf.pFrom=szName; + sf.fFlags=FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT; + mir_snprintf(szName, SIZEOF(szName),"%s\0",profile); + if ( SHFileOperationA(&sf) != 0 ) { + mir_snprintf(buf, SIZEOF(buf),Translate("Couldn't move '%s' to the Recycle Bin, Please select another profile name."),file); + MessageBoxA(0,buf,Translate("Problem moving profile"),MB_ICONINFORMATION|MB_OK); + return 0; + } + } + // now the file should be gone! + } + // ask the database to create the profile + if ( link->makeDatabase(profile,&err) ) { + mir_snprintf(buf, SIZEOF(buf),Translate("Unable to create the profile '%s', the error was %x"),file, err); + MessageBoxA(hwndDlg,buf,Translate("Problem creating profile"),MB_ICONERROR|MB_OK); + return 0; + } + // the profile has been created! woot + return 1; +} + +// enumerate all plugins that had valid DatabasePluginInfo() +static int FindDbPluginForProfile(char * pluginname, DATABASELINK * dblink, LPARAM lParam) +{ + char * szProfile = (char *) lParam; + if ( dblink && dblink->cbSize == sizeof(DATABASELINK) ) { + int err=0; + int rc=0; + // liked the profile? + rc=dblink->grokHeader(szProfile,&err); + if ( rc == 0 ) { + // added APIs? + if ( dblink->Load(szProfile, &pluginCoreLink) == 0 ) return DBPE_DONE; + return DBPE_HALT; + } else { + switch ( err ) { + case EGROKPRF_CANTREAD: + case EGROKPRF_UNKHEADER: + { + // just not supported. + return DBPE_CONT; + } + case EGROKPRF_VERNEWER: + case EGROKPRF_DAMAGED: + { + break; + } + } + return DBPE_HALT; + } //if + } + return DBPE_CONT; +} + +typedef struct { + char * profile; + UINT msg; + ATOM aPath; + int found; +} ENUMMIRANDAWINDOW; + +static BOOL CALLBACK EnumMirandaWindows(HWND hwnd, LPARAM lParam) +{ + TCHAR classname[256]; + ENUMMIRANDAWINDOW * x = (ENUMMIRANDAWINDOW *)lParam; + DWORD res=0; + if ( GetClassName(hwnd,classname,SIZEOF(classname)) && lstrcmp( _T("Miranda"),classname)==0 ) { + if ( SendMessageTimeout(hwnd, x->msg, (WPARAM)x->aPath, 0, SMTO_ABORTIFHUNG, 100, &res) && res ) { + x->found++; + return FALSE; + } + } + return TRUE; +} + +static int FindMirandaForProfile(char * szProfile) +{ + ENUMMIRANDAWINDOW x={0}; + x.profile=szProfile; + x.msg=RegisterWindowMessage( _T( "Miranda::ProcessProfile" )); + x.aPath=GlobalAddAtomA(szProfile); + EnumWindows(EnumMirandaWindows, (LPARAM)&x); + GlobalDeleteAtom(x.aPath); + return x.found; +} + +int LoadDatabaseModule(void) +{ + int iReturn = 0; + char szProfile[MAX_PATH]; + szProfile[0]=0; + + // load the older basic services of the db + InitTime(); + + // find out which profile to load + if ( getProfile(szProfile, SIZEOF(szProfile)) ) + { + int rc; + PLUGIN_DB_ENUM dbe; + + dbe.cbSize=sizeof(PLUGIN_DB_ENUM); + dbe.pfnEnumCallback=( int(*) (char*,void*,LPARAM) )FindDbPluginForProfile; + dbe.lParam=(LPARAM)szProfile; + + // find a driver to support the given profile + rc=CallService(MS_PLUGINS_ENUMDBPLUGINS, 0, (LPARAM)&dbe); + switch ( rc ) { + case -1: { + // no plugins at all + char buf[256]; + char * p = strrchr(szProfile,'\\'); + mir_snprintf(buf,SIZEOF(buf),Translate("Miranda is unable to open '%s' because you do not have any profile plugins installed.\nYou need to install dbx_3x.dll or equivalent."), p ? ++p : szProfile ); + MessageBoxA(0,buf,Translate("No profile support installed!"),MB_OK | MB_ICONERROR); + break; + } + case 1: { + // if there were drivers but they all failed cos the file is locked, try and find the miranda which locked it + HANDLE hFile; + hFile=CreateFileA(szProfile,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); + if ( hFile == INVALID_HANDLE_VALUE ) { + if ( !FindMirandaForProfile(szProfile) ) { + // file is locked, tried to find miranda window, but that failed too. + } + } else { + // file isn't locked, just no driver could open it. + char buf[256]; + char * p = strrchr(szProfile,'\\'); + mir_snprintf(buf,SIZEOF(buf),Translate("Miranda was unable to open '%s', its in an unknown format.\nThis profile might also be damaged, please run DB-tool which should be installed."), p ? ++p : szProfile); + MessageBoxA(0,buf,Translate("Miranda can't understand that profile"),MB_OK | MB_ICONERROR); + CloseHandle(hFile); + } + break; + } + } + iReturn = (rc != 0); + } + else + { + iReturn = 1; + } + + return iReturn; +} + diff --git a/miranda-wine/src/modules/database/dbini.c b/miranda-wine/src/modules/database/dbini.c new file mode 100644 index 0000000..0717080 --- /dev/null +++ b/miranda-wine/src/modules/database/dbini.c @@ -0,0 +1,495 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 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 "database.h" + +static HANDLE hIniChangeNotification; +extern char mirandabootini[MAX_PATH]; + +int GetCommandLineDbName(char *szName,int cbName) +{ + char *szCmdLine=GetCommandLineA(); + char *szEndOfParam; + char szThisParam[1024]; + int firstParam=1; + + while(szCmdLine[0]) { + if(szCmdLine[0]=='"') { + szEndOfParam=strchr(szCmdLine+1,'"'); + if(szEndOfParam==NULL) break; + lstrcpynA(szThisParam,szCmdLine+1,min(sizeof(szThisParam),szEndOfParam-szCmdLine)); + szCmdLine=szEndOfParam+1; + } + else { + szEndOfParam=szCmdLine+strcspn(szCmdLine," \t"); + lstrcpynA(szThisParam,szCmdLine,min(sizeof(szThisParam),szEndOfParam-szCmdLine+1)); + szCmdLine=szEndOfParam; + } + while(*szCmdLine && *szCmdLine<=' ') szCmdLine++; + if(firstParam) {firstParam=0; continue;} //first param is executable name + if(szThisParam[0]=='/' || szThisParam[0]=='-') continue; //no switches supported + lstrcpynA(szName,szThisParam,cbName); + return 0; + } + return 1; +} + +void GetProfileDirectory(char *szPath,int cbPath) +{ + char *str2; + char szMirandaDir[MAX_PATH],szProfileDir[MAX_PATH],szExpandedProfileDir[MAX_PATH]; + DWORD dwAttributes; + + GetModuleFileNameA(GetModuleHandle(NULL),szMirandaDir,sizeof(szMirandaDir)); + str2=strrchr(szMirandaDir,'\\'); + if(str2!=NULL) *str2=0; + GetPrivateProfileStringA("Database","ProfileDir",".",szProfileDir,sizeof(szProfileDir),mirandabootini); + ExpandEnvironmentStringsA(szProfileDir,szExpandedProfileDir,sizeof(szExpandedProfileDir)); + _chdir(szMirandaDir); + if(!_fullpath(szPath,szExpandedProfileDir,cbPath)) + lstrcpynA(szPath,szMirandaDir,cbPath); + if(szPath[lstrlenA(szPath)-1]=='\\') szPath[lstrlenA(szPath)-1]='\0'; + if((dwAttributes=GetFileAttributesA(szPath))!=0xffffffff&&dwAttributes&FILE_ATTRIBUTE_DIRECTORY) return; + CreateDirectoryA(szPath,NULL); +} + +int ShouldAutoCreate(void) +{ + char szAutoCreate[4]; + GetPrivateProfileStringA("Database","AutoCreate","no",szAutoCreate,sizeof(szAutoCreate),mirandabootini); + return !lstrcmpiA(szAutoCreate,"yes"); +} + +int GetDefaultProfilePath(char *szPath,int cbPath,int *specified) +{ + char szProfileDir[MAX_PATH],szDefaultName[MAX_PATH],szExpandedDefaultName[MAX_PATH]; + HANDLE hFind; + char szSearchPath[MAX_PATH],szSingleExistingPath[MAX_PATH]; + WIN32_FIND_DATAA fd; + + if(specified) *specified=1; + GetProfileDirectory(szProfileDir,sizeof(szProfileDir)); + if(GetCommandLineDbName(szDefaultName,sizeof(szDefaultName))) { + if(specified) *specified=0; + GetPrivateProfileStringA("Database","DefaultProfile","",szDefaultName,sizeof(szDefaultName),mirandabootini); + } + ExpandEnvironmentStringsA(szDefaultName,szExpandedDefaultName,sizeof(szExpandedDefaultName)); + + _chdir(szProfileDir); + + szSingleExistingPath[0]='\0'; + lstrcpyA(szSearchPath,szProfileDir); + lstrcatA(szSearchPath,"\\*.dat"); + hFind=FindFirstFileA(szSearchPath,&fd); + if(hFind!=INVALID_HANDLE_VALUE) { + if(FindNextFileA(hFind,&fd)==0) + if(_fullpath(szSingleExistingPath,fd.cFileName,cbPath)==NULL) + szSingleExistingPath[0]='\0'; + FindClose(hFind); + } + + if(szExpandedDefaultName[0]) { + lstrcatA(szExpandedDefaultName,".dat"); + if(_fullpath(szPath,szExpandedDefaultName,cbPath)!=NULL) { + if(specified && !lstrcmpiA(szSingleExistingPath,szPath)) *specified=1; + if(!_access(szPath,0)) return 0; + if(ShouldAutoCreate()) { + HANDLE hFile; + if(specified && szSingleExistingPath[0]=='\0') *specified=1; + hFile=CreateFileA(szPath,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,0,NULL); + CloseHandle(hFile); + return 0; + } + } + } + + if(szSingleExistingPath[0]) { + if(specified && szExpandedDefaultName[0]=='\0') *specified=1; + lstrcpynA(szPath,szSingleExistingPath,cbPath); + return 0; + } + return 1; +} + +int ShouldShowProfileManager(void) +{ + char szShowValue[7]; + char szDefaultProfile[MAX_PATH]; + int defaultProfileSpecified; + + if(GetAsyncKeyState(VK_CONTROL)&0x8000) return 1; + GetPrivateProfileStringA("Database","ShowProfileMgr","smart",szShowValue,sizeof(szShowValue),mirandabootini); + if(!lstrcmpiA(szShowValue,"always")) return 1; + if(!lstrcmpiA(szShowValue,"never")) { + return GetDefaultProfilePath(szDefaultProfile,sizeof(szDefaultProfile),NULL); + } + return GetDefaultProfilePath(szDefaultProfile,sizeof(szDefaultProfile),&defaultProfileSpecified) + || !defaultProfileSpecified; +} + +static BOOL CALLBACK InstallIniDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetDlgItemTextA(hwndDlg,IDC_ININAME,(char*)lParam); + { char szSecurity[11],*pszSecurityInfo; + GetPrivateProfileStringA("AutoExec","Warn","notsafe",szSecurity,sizeof(szSecurity),mirandabootini); + if(!lstrcmpiA(szSecurity,"all")) + pszSecurityInfo="Security systems to prevent malicious changes are in place and you will be warned before every change that is made."; + else if(!lstrcmpiA(szSecurity,"onlyunsafe")) + pszSecurityInfo="Security systems to prevent malicious changes are in place and you will be warned before changes that are known to be unsafe."; + else if(!lstrcmpiA(szSecurity,"none")) + pszSecurityInfo="Security systems to prevent malicious changes have been disabled. You will receive no further warnings."; + else pszSecurityInfo=NULL; + if(pszSecurityInfo) SetDlgItemTextA(hwndDlg,IDC_SECURITYINFO,ServiceExists(MS_LANGPACK_TRANSLATESTRING)?Translate(pszSecurityInfo):pszSecurityInfo); + } + return TRUE; + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_VIEWINI: + { char szPath[MAX_PATH]; + GetDlgItemTextA(hwndDlg,IDC_ININAME,szPath,sizeof(szPath)); + ShellExecuteA(hwndDlg,"open",szPath,NULL,NULL,SW_SHOW); + break; + } + case IDOK: + case IDCANCEL: + case IDC_NOTOALL: + EndDialog(hwndDlg,LOWORD(wParam)); + break; + } + break; + } + return FALSE; +} + +static int IsInSpaceSeparatedList(const char *szWord,const char *szList) +{ + char *szItem,*szEnd; + int wordLen=lstrlenA(szWord); + + for(szItem=(char*)szList;;) { + szEnd=strchr(szItem,' '); + if(szEnd==NULL) return !lstrcmpA(szItem,szWord); + if(szEnd-szItem==wordLen) { + if(!strncmp(szItem,szWord,wordLen)) return 1; + } + szItem=szEnd+1; + } + return 0; +} + +struct warnSettingChangeInfo_t { + char *szIniPath; + char *szSection; + char *szSafeSections; + char *szUnsafeSections; + char *szName; + char *szValue; + int warnNoMore,cancel; +}; + +static BOOL CALLBACK WarnIniChangeDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + static struct warnSettingChangeInfo_t *warnInfo; + + switch(message) { + case WM_INITDIALOG: + { char szSettingName[256]; + char *pszSecurityInfo; + warnInfo=(struct warnSettingChangeInfo_t*)lParam; + TranslateDialogDefault(hwndDlg); + SetDlgItemTextA(hwndDlg,IDC_ININAME,warnInfo->szIniPath); + lstrcpyA(szSettingName,warnInfo->szSection); + lstrcatA(szSettingName," / "); + lstrcatA(szSettingName,warnInfo->szName); + SetDlgItemTextA(hwndDlg,IDC_SETTINGNAME,szSettingName); + SetDlgItemTextA(hwndDlg,IDC_NEWVALUE,warnInfo->szValue); + if(IsInSpaceSeparatedList(warnInfo->szSection,warnInfo->szSafeSections)) + pszSecurityInfo="This change is known to be safe."; + else if(IsInSpaceSeparatedList(warnInfo->szSection,warnInfo->szUnsafeSections)) + pszSecurityInfo="This change is known to be potentially hazardous."; + else + pszSecurityInfo="This change is not known to be safe."; + SetDlgItemTextA(hwndDlg,IDC_SECURITYINFO,ServiceExists(MS_LANGPACK_TRANSLATESTRING)?Translate(pszSecurityInfo):pszSecurityInfo); + return TRUE; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + warnInfo->cancel=1; + case IDYES: + case IDNO: + warnInfo->warnNoMore=IsDlgButtonChecked(hwndDlg,IDC_WARNNOMORE); + EndDialog(hwndDlg,LOWORD(wParam)); + break; + } + break; + } + return FALSE; +} + +static BOOL CALLBACK IniImportDoneDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + switch(message) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SetDlgItemTextA(hwndDlg,IDC_ININAME,(char*)lParam); + SetDlgItemTextA(hwndDlg,IDC_NEWNAME,(char*)lParam); + return TRUE; + case WM_COMMAND: + { char szIniPath[MAX_PATH]; + GetDlgItemTextA(hwndDlg,IDC_ININAME,szIniPath,sizeof(szIniPath)); + switch(LOWORD(wParam)) { + case IDC_DELETE: + DeleteFileA(szIniPath); + case IDC_LEAVE: + EndDialog(hwndDlg,LOWORD(wParam)); + break; + case IDC_RECYCLE: + { SHFILEOPSTRUCTA shfo={0}; + shfo.wFunc=FO_DELETE; + shfo.pFrom=szIniPath; + szIniPath[lstrlenA(szIniPath)+1]='\0'; + shfo.fFlags=FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT; + SHFileOperationA(&shfo); + } + EndDialog(hwndDlg,LOWORD(wParam)); + break; + case IDC_MOVE: + { char szNewPath[MAX_PATH]; + GetDlgItemTextA(hwndDlg,IDC_NEWNAME,szNewPath,sizeof(szNewPath)); + MoveFileA(szIniPath,szNewPath); + } + EndDialog(hwndDlg,LOWORD(wParam)); + break; + } + break; + } + } + return FALSE; +} + +static void DoAutoExec(void) +{ + HANDLE hFind; + char szMirandaDir[MAX_PATH],szUse[7],szIniPath[MAX_PATH],szFindPath[MAX_PATH],szExpandedFindPath[MAX_PATH]; + char szLine[2048]; + char *str2; + WIN32_FIND_DATAA fd; + FILE *fp; + char szSection[128]; + int lineLength; + char szSafeSections[2048],szUnsafeSections[2048],szSecurity[11],szOverrideSecurityFilename[MAX_PATH]; + int warnThisSection=0; + + GetPrivateProfileStringA("AutoExec","Use","prompt",szUse,sizeof(szUse),mirandabootini); + if(!lstrcmpiA(szUse,"no")) return; + GetPrivateProfileStringA("AutoExec","Safe","CLC Icons CLUI CList SkinSounds",szSafeSections,sizeof(szSafeSections),mirandabootini); + GetPrivateProfileStringA("AutoExec","Unsafe","ICQ MSN",szUnsafeSections,sizeof(szUnsafeSections),mirandabootini); + GetPrivateProfileStringA("AutoExec","Warn","notsafe",szSecurity,sizeof(szSecurity),mirandabootini); + GetPrivateProfileStringA("AutoExec","OverrideSecurityFilename","",szOverrideSecurityFilename,sizeof(szOverrideSecurityFilename),mirandabootini); + GetModuleFileNameA(GetModuleHandle(NULL),szMirandaDir,sizeof(szMirandaDir)); + str2=strrchr(szMirandaDir,'\\'); + if(str2!=NULL) *str2=0; + _chdir(szMirandaDir); + GetPrivateProfileStringA("AutoExec","Glob","autoexec_*.ini",szFindPath,sizeof(szFindPath),mirandabootini); + ExpandEnvironmentStringsA(szFindPath,szExpandedFindPath,sizeof(szExpandedFindPath)); + hFind=FindFirstFileA(szExpandedFindPath,&fd); + if(hFind==INVALID_HANDLE_VALUE) return; + str2=strrchr(szExpandedFindPath,'\\'); + if(str2==NULL) str2=szExpandedFindPath; + else str2++; + *str2='\0'; + szSection[0]='\0'; + do { + lstrcpyA(szIniPath,szExpandedFindPath); + lstrcatA(szIniPath,fd.cFileName); + if(!lstrcmpiA(szUse,"prompt") && lstrcmpiA(fd.cFileName,szOverrideSecurityFilename)) { + int result=DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_INSTALLINI),NULL,InstallIniDlgProc,(LPARAM)szIniPath); + if(result==IDC_NOTOALL) break; + if(result==IDCANCEL) continue; + } + fp=fopen(szIniPath,"rt"); + while(!feof(fp)) { + if(fgets(szLine,sizeof(szLine),fp)==NULL) break; + lineLength=lstrlenA(szLine); + while(lineLength && (BYTE)(szLine[lineLength-1])<=' ') szLine[--lineLength]='\0'; + if(szLine[0]==';' || szLine[0]<=' ') continue; + if(szLine[0]=='[') { + char *szEnd=strchr(szLine+1,']'); + if(szEnd==NULL) continue; + if(szLine[1]=='!') + szSection[0]='\0'; + else { + lstrcpynA(szSection,szLine+1,min(sizeof(szSection),szEnd-szLine)); + if(!lstrcmpiA(szSecurity,"none")) warnThisSection=0; + else if(!lstrcmpiA(szSecurity,"notsafe")) + warnThisSection=!IsInSpaceSeparatedList(szSection,szSafeSections); + else if(!lstrcmpiA(szSecurity,"onlyunsafe")) + warnThisSection=IsInSpaceSeparatedList(szSection,szUnsafeSections); + else warnThisSection=1; + if(!lstrcmpiA(fd.cFileName,szOverrideSecurityFilename)) warnThisSection=0; + } + } + else { + char *szValue; + char szName[128]; + struct warnSettingChangeInfo_t warnInfo; + + if(szSection[0]=='\0') continue; + szValue=strchr(szLine,'='); + if(szValue==NULL) continue; + lstrcpynA(szName,szLine,min(sizeof(szName),szValue-szLine+1)); + szValue++; + warnInfo.szIniPath=szIniPath; + warnInfo.szName=szName; + warnInfo.szSafeSections=szSafeSections; + warnInfo.szSection=szSection; + warnInfo.szUnsafeSections=szUnsafeSections; + warnInfo.szValue=szValue; + warnInfo.warnNoMore=0; + warnInfo.cancel=0; + if(!warnThisSection || IDNO!=DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_WARNINICHANGE),NULL,WarnIniChangeDlgProc,(LPARAM)&warnInfo)) { + if(warnInfo.cancel) break; + if(warnInfo.warnNoMore) warnThisSection=0; + switch(szValue[0]) { + case 'b': + case 'B': + DBWriteContactSettingByte(NULL,szSection,szName,(BYTE)strtol(szValue+1,NULL,0)); + break; + case 'w': + case 'W': + DBWriteContactSettingWord(NULL,szSection,szName,(WORD)strtol(szValue+1,NULL,0)); + break; + case 'd': + case 'D': + DBWriteContactSettingDword(NULL,szSection,szName,(DWORD)strtoul(szValue+1,NULL,0)); + break; + case 'l': + case 'L': + DBDeleteContactSetting(NULL,szSection,szName); + break; + case 's': + case 'S': + DBWriteContactSettingString(NULL,szSection,szName,szValue+1); + break; + case 'u': + case 'U': + DBWriteContactSettingStringUtf(NULL,szSection,szName,szValue+1); + break; + case 'n': + case 'N': + { PBYTE buf; + int len; + char *pszValue,*pszEnd; + DBCONTACTWRITESETTING cws; + + buf=(PBYTE)mir_alloc(lstrlenA(szValue+1)); + for(len=0,pszValue=szValue+1;;len++) { + buf[len]=(BYTE)strtol(pszValue,&pszEnd,0x10); + if(pszValue==pszEnd) break; + pszValue=pszEnd; + } + cws.szModule=szSection; + cws.szSetting=szName; + cws.value.type=DBVT_BLOB; + cws.value.pbVal=buf; + cws.value.cpbVal=len; + CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)(HANDLE)NULL,(LPARAM)&cws); + mir_free(buf); + } + break; + default: + if(ServiceExists(MS_LANGPACK_TRANSLATESTRING)) + MessageBox(NULL,TranslateT("Invalid setting type. The first character of every value must be b, w, d, l, s or n."),TranslateT("Install Database Settings"),MB_OK); + else + MessageBoxA(NULL,"Invalid setting type. The first character of every value must be b, w, d, l, s or n.","Install Database Settings",MB_OK); + break; + } + } + } + } + fclose(fp); + if(!lstrcmpiA(fd.cFileName,szOverrideSecurityFilename)) + DeleteFileA(szIniPath); + else { + char szOnCompletion[8]; + GetPrivateProfileStringA("AutoExec","OnCompletion","recycle",szOnCompletion,sizeof(szOnCompletion),mirandabootini); + if(!lstrcmpiA(szOnCompletion,"delete")) + DeleteFileA(szIniPath); + else if(!lstrcmpiA(szOnCompletion,"recycle")) { + SHFILEOPSTRUCTA shfo={0}; + shfo.wFunc=FO_DELETE; + shfo.pFrom=szIniPath; + szIniPath[lstrlenA(szIniPath)+1]='\0'; + shfo.fFlags=FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT; + SHFileOperationA(&shfo); + } + else if(!lstrcmpiA(szOnCompletion,"rename")) { + char szRenamePrefix[MAX_PATH]; + char szNewPath[MAX_PATH]; + GetPrivateProfileStringA("AutoExec","RenamePrefix","done_",szRenamePrefix,sizeof(szRenamePrefix),mirandabootini); + lstrcpyA(szNewPath,szExpandedFindPath); + lstrcatA(szNewPath,szRenamePrefix); + lstrcatA(szNewPath,fd.cFileName); + MoveFileA(szIniPath,szNewPath); + } + else if(!lstrcmpiA(szOnCompletion,"ask")) + DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_INIIMPORTDONE),NULL,IniImportDoneDlgProc,(LPARAM)szIniPath); + } + } while(FindNextFileA(hFind,&fd)); + FindClose(hFind); +} + +static int CheckIniImportNow(WPARAM wParam,LPARAM lParam) +{ + DoAutoExec(); + FindNextChangeNotification(hIniChangeNotification); + return 0; +} + +int InitIni(void) +{ + char szMirandaDir[MAX_PATH]; + char *str2; + + DoAutoExec(); + GetModuleFileNameA(GetModuleHandle(NULL),szMirandaDir,sizeof(szMirandaDir)); + str2=strrchr(szMirandaDir,'\\'); + if(str2!=NULL) *str2=0; + hIniChangeNotification=FindFirstChangeNotificationA(szMirandaDir,0,FILE_NOTIFY_CHANGE_FILE_NAME); + if(hIniChangeNotification!=INVALID_HANDLE_VALUE) { + CreateServiceFunction("DB/Ini/CheckImportNow",CheckIniImportNow); + CallService(MS_SYSTEM_WAITONHANDLE,(WPARAM)hIniChangeNotification,(LPARAM)"DB/Ini/CheckImportNow"); + } + return 0; +} + +void UninitIni(void) +{ + CallService(MS_SYSTEM_REMOVEWAIT,(WPARAM)hIniChangeNotification,0); + FindCloseChangeNotification(hIniChangeNotification); +} \ No newline at end of file diff --git a/miranda-wine/src/modules/database/dblists.c b/miranda-wine/src/modules/database/dblists.c new file mode 100644 index 0000000..ab656ff --- /dev/null +++ b/miranda-wine/src/modules/database/dblists.c @@ -0,0 +1,149 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 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 "dblists.h" + +/* a simple sorted list implementation */ + +SortedList* List_Create( int p_limit, int p_increment ) +{ + SortedList* result = ( SortedList* )mir_calloc( sizeof( SortedList )); + if ( result == NULL ) + return(NULL); + + result->increment = p_increment; + result->limit = p_limit; + return(result); +} + +void List_Destroy( SortedList* p_list ) +{ + if ( p_list == NULL ) + return; + + if ( p_list->items != NULL ) { + mir_free( p_list->items ); + p_list->items = NULL; + } + + p_list->realCount = p_list->limit = 0; +} + +void* List_Find( SortedList* p_list, void* p_value ) +{ + int index; + + if ( !List_GetIndex( p_list, p_value, &index )) + return(NULL); + + return(p_list->items[ index ]); +} + +int List_GetIndex( SortedList* p_list, void* p_value, int* p_index ) +{ + if ( p_list->sortFunc != NULL ) + { + int low = 0; + int high = p_list->realCount-1; + + while( low <= high ) + { + int i = ( low+high )/2; + int result = p_list->sortFunc( p_list->items[ i ], p_value ); + if ( result == 0 ) + { *p_index = i; + return 1; + } + + if ( result < 0 ) + low = i+1; + else + high = i-1; + } + + *p_index = low; + } + return 0; +} + +int List_IndexOf( SortedList* p_list, void* p_value ) +{ + int i; + for ( i=0; i < p_list->realCount; i++ ) + if ( p_list->items[i] == p_value ) + return i; + + return -1; +} + +int List_Insert( SortedList* p_list, void* p_value, int p_index) +{ + if ( p_value == NULL || p_index > p_list->realCount ) + return 0; + + if ( p_list->realCount == p_list->limit ) + { + p_list->items = ( void** )mir_realloc( p_list->items, sizeof( void* )*(p_list->realCount + p_list->increment)); + p_list->limit += p_list->increment; + } + + if ( p_index < p_list->realCount ) + memmove( p_list->items+p_index+1, p_list->items+p_index, sizeof( void* )*( p_list->realCount-p_index )); + + p_list->realCount++; + + p_list->items[ p_index ] = p_value; + return 1; +} + +int List_InsertPtr( SortedList* list, void* p ) +{ + int idx; + List_GetIndex( list, p, &idx ); + return List_Insert( list, p, idx ); +} + +int List_Remove( SortedList* p_list, int index ) +{ + if ( index < 0 || index > p_list->realCount ) + return(0); + + p_list->realCount--; + if ( p_list->realCount > index ) + { + memmove( p_list->items+index, p_list->items+index+1, sizeof( void* )*( p_list->realCount-index )); + p_list->items[ p_list->realCount ] = NULL; + } + + return 1; +} + +int List_RemovePtr( SortedList* list, void* p ) +{ + int idx = -1; + if ( List_GetIndex( list, p, &idx )) + List_Remove( list, idx ); + + return idx; +} diff --git a/miranda-wine/src/modules/database/dblists.h b/miranda-wine/src/modules/database/dblists.h new file mode 100644 index 0000000..c3397ab --- /dev/null +++ b/miranda-wine/src/modules/database/dblists.h @@ -0,0 +1,36 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 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. +*/ + +/* a simple sorted list implementation */ + +SortedList* List_Create( int, int ); +void List_Destroy( SortedList* ); + +void* List_Find( SortedList*, void* ); +int List_GetIndex( SortedList*, void*, int* ); +int List_Insert( SortedList*, void*, int ); +int List_Remove( SortedList*, int ); +int List_IndexOf( SortedList*, void* ); + +int List_InsertPtr( SortedList* list, void* p ); +int List_RemovePtr( SortedList* list, void* p ); diff --git a/miranda-wine/src/modules/database/dbtime.c b/miranda-wine/src/modules/database/dbtime.c new file mode 100644 index 0000000..b2c9eb1 --- /dev/null +++ b/miranda-wine/src/modules/database/dbtime.c @@ -0,0 +1,239 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 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 "database.h" + +static int daysInMonth[12]={31,28,31,30,31,30,31,31,30,31,30,31}; +static int IsLeapYear(int year) +{ + if(year&3) return 0; + if(year%100) return 1; + if(year%400) return 0; + return 1; +} + +static int CompareSystemTimes(SYSTEMTIME *st,SYSTEMTIME *switchDate) +{ + FILETIME ft1,ft2; + + if(switchDate->wYear==0) { //strange day-in-month thing + SYSTEMTIME tempst; + + //short-circuit if the months aren't the same + if(st->wMonthwMonth) return -1; + if(st->wMonth>switchDate->wMonth) return 1; + + tempst=*switchDate; + tempst.wYear=st->wYear; + tempst.wDay=1; + SystemTimeToFileTime(&tempst,&ft1); + FileTimeToSystemTime(&ft1,&tempst); //gets the day of week of the first of the month + tempst.wDay=1+(7+switchDate->wDayOfWeek-tempst.wDayOfWeek)%7; + if(switchDate->wDay==5) { //last wDayOfWeek in month + if(tempst.wMonth==2) { + if(IsLeapYear(tempst.wYear)) daysInMonth[1]=29; + else daysInMonth[1]=28; + } + tempst.wDay+=7*3; //can't be less than 4 of that day in the month + if(tempst.wDay+7<=daysInMonth[switchDate->wMonth-1]) tempst.wDay+=7; + } + else tempst.wDay+=7*(switchDate->wDay-1); //nth of month + SystemTimeToFileTime(&tempst,&ft2); + } + else { + switchDate->wYear=st->wYear; + SystemTimeToFileTime(switchDate,&ft2); + } + SystemTimeToFileTime(st,&ft1); + return CompareFileTime(&ft1,&ft2); +} + +static int TimestampToLocal(WPARAM wParam,LPARAM lParam) +{ + TIME_ZONE_INFORMATION tzInfo; + LARGE_INTEGER liFiletime; + FILETIME filetime; + SYSTEMTIME st; + int iReturn = 0; + + GetTimeZoneInformation(&tzInfo); + if(tzInfo.StandardDate.wMonth==0) + { + //no daylight savings time + iReturn = (int)(wParam-tzInfo.Bias*60); + } + else + { + //this huge number is the difference between 1970 and 1601 in seconds + liFiletime.QuadPart=((__int64)11644473600+(__int64)wParam)*10000000; + filetime.dwHighDateTime=liFiletime.HighPart; + filetime.dwLowDateTime=liFiletime.LowPart; + FileTimeToSystemTime(&filetime,&st); + + if(tzInfo.DaylightDate.wMonth0) + { + iReturn = (int)(wParam-(tzInfo.Bias+tzInfo.StandardBias)*60); + } + else + { + iReturn = (int)(wParam-(tzInfo.Bias+tzInfo.DaylightBias)*60); + } + } + else + { + //southern hemisphere + if(CompareSystemTimes(&st,&tzInfo.StandardDate)<0 || + CompareSystemTimes(&st,&tzInfo.DaylightDate)>0) + { + iReturn = (int)(wParam-(tzInfo.Bias+tzInfo.DaylightBias)*60); + } + else + { + iReturn = (int)(wParam-(tzInfo.Bias+tzInfo.StandardBias)*60); + } + } + } + + return iReturn; +} + +static int TimestampToString(WPARAM wParam,LPARAM lParam) +{ + DBTIMETOSTRING *tts=(DBTIMETOSTRING*)lParam; + LARGE_INTEGER liFiletime; + FILETIME filetime; + SYSTEMTIME st; + char dateTimeStr[64]; + char *pDest,*pFormat; + int destCharsLeft,dateTimeStrLen; + + //this huge number is the difference between 1970 and 1601 in seconds + liFiletime.QuadPart=((__int64)11644473600+(__int64)(DWORD)TimestampToLocal(wParam,0))*10000000; + filetime.dwHighDateTime=liFiletime.HighPart; + filetime.dwLowDateTime=liFiletime.LowPart; + FileTimeToSystemTime(&filetime,&st); + destCharsLeft=tts->cbDest; + for(pFormat=tts->szFormat,pDest=tts->szDest;*pFormat;pFormat++) { + switch(*pFormat) { + case 't': + GetTimeFormatA(LOCALE_USER_DEFAULT,TIME_NOSECONDS,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 's': + GetTimeFormatA(LOCALE_USER_DEFAULT,0,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 'm': + GetTimeFormatA(LOCALE_USER_DEFAULT,TIME_NOMINUTESORSECONDS,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 'd': + GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 'D': + GetDateFormatA(LOCALE_USER_DEFAULT,DATE_LONGDATE,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + default: + if(destCharsLeft) { + *pDest++=*pFormat; + destCharsLeft--; + } + continue; + } + dateTimeStrLen=strlen(dateTimeStr); + if(destCharsLeftszDest[tts->cbDest-1]=0; + return 0; +} + +#if defined( _UNICODE ) +static int TimestampToStringW(WPARAM wParam,LPARAM lParam) +{ + DBTIMETOSTRINGT *tts = ( DBTIMETOSTRINGT* )lParam; + LARGE_INTEGER liFiletime; + FILETIME filetime; + SYSTEMTIME st; + TCHAR dateTimeStr[64]; + TCHAR *pDest,*pFormat; + int destCharsLeft, dateTimeStrLen; + + //this huge number is the difference between 1970 and 1601 in seconds + liFiletime.QuadPart = (11644473600i64+(__int64)(DWORD)TimestampToLocal(wParam,0))*10000000; + filetime.dwHighDateTime = liFiletime.HighPart; + filetime.dwLowDateTime = liFiletime.LowPart; + FileTimeToSystemTime(&filetime,&st); + destCharsLeft = tts->cbDest; + for ( pFormat = tts->szFormat, pDest=tts->szDest; *pFormat; pFormat++ ) { + switch(*pFormat) { + case 't': + GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOSECONDS,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 's': + GetTimeFormat(LOCALE_USER_DEFAULT,0,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 'm': + GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOMINUTESORSECONDS,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 'd': + GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + case 'D': + GetDateFormat(LOCALE_USER_DEFAULT,DATE_LONGDATE,&st,NULL,dateTimeStr,SIZEOF(dateTimeStr)); + break; + default: + if ( destCharsLeft ) { + *pDest++ = *pFormat; + destCharsLeft--; + } + continue; + } + dateTimeStrLen = _tcslen(dateTimeStr); + if (destCharsLeft < dateTimeStrLen) dateTimeStrLen = destCharsLeft; + CopyMemory(pDest, dateTimeStr, dateTimeStrLen*sizeof(TCHAR)); + destCharsLeft -= dateTimeStrLen; + pDest += dateTimeStrLen; + } + if ( destCharsLeft ) *pDest=0; + else tts->szDest[ tts->cbDest-1 ] = 0; + return 0; +} +#endif + +int InitTime(void) +{ + CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOLOCAL, TimestampToLocal); + CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOSTRING, TimestampToString); + #if defined( _UNICODE ) + CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOSTRINGT, TimestampToStringW); + #else + CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOSTRINGT, TimestampToString); + #endif + return 0; +} diff --git a/miranda-wine/src/modules/database/profilemanager.c b/miranda-wine/src/modules/database/profilemanager.c new file mode 100644 index 0000000..8eeaa09 --- /dev/null +++ b/miranda-wine/src/modules/database/profilemanager.c @@ -0,0 +1,696 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 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 "profilemanager.h" +#include + +#define WM_INPUTCHANGED (WM_USER + 0x3000) +#define WM_FOCUSTEXTBOX (WM_USER + 0x3001) + +typedef BOOL (__cdecl *ENUMPROFILECALLBACK) (char * fullpath, char * 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; +}; + +struct DetailsData { + HINSTANCE hInstIcmp; + HFONT hBoldFont; + int pageCount; + int currentPage; + struct DetailsPageData *opd; + RECT rcDisplay; + struct DlgProfData * prof; +}; + +extern char mirandabootini[MAX_PATH]; // bad bad bad bad! +static char szDefaultMirandaProfile[MAX_PATH]; + +static void ThemeDialogBackground(HWND hwnd) { + if (IsWinVerXPPlus()) { + static HMODULE hThemeAPI = NULL; + if (!hThemeAPI) hThemeAPI = GetModuleHandleA("uxtheme"); + if (hThemeAPI) { + HRESULT (STDAPICALLTYPE *MyEnableThemeDialogTexture)(HWND,DWORD) = (HRESULT (STDAPICALLTYPE*)(HWND,DWORD))GetProcAddress(hThemeAPI,"EnableThemeDialogTexture"); + if (MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture(hwnd,0x00000002|0x00000004); //0x00000002|0x00000004=ETDT_ENABLETAB + } + } +} + +static int findProfiles(char * szProfileDir, ENUMPROFILECALLBACK callback, LPARAM lParam) +{ + HANDLE hFind = INVALID_HANDLE_VALUE; + WIN32_FIND_DATAA ffd; + char searchspec[MAX_PATH]; + mir_snprintf(searchspec, SIZEOF(searchspec), "%s\\*.dat", szProfileDir); + hFind = FindFirstFileA(searchspec, &ffd); + if ( hFind != INVALID_HANDLE_VALUE ) { + do { + if ( !(ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && isValidProfileName(ffd.cFileName) ) + { + char buf[MAX_PATH]; + mir_snprintf(buf,SIZEOF(buf),"%s\\%s",szProfileDir, ffd.cFileName); + if ( !callback(buf, ffd.cFileName, lParam) ) break; + } + } while ( FindNextFileA(hFind, &ffd) ); + FindClose(hFind); + return 1; + } + return 0; +} + +static LRESULT CALLBACK ProfileNameValidate(HWND edit, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if ( msg==WM_CHAR ) { + if ( strchr(".?/\\#' ",(char)wParam&0xFF) != 0 ) return 0; + PostMessage(GetParent(edit),WM_INPUTCHANGED,0,0); + } + return CallWindowProc((WNDPROC)GetWindowLong(edit,GWL_USERDATA),edit,msg,wParam,lParam); +} + +static int FindDbProviders(char * pluginname, 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 + LRESULT index = SendMessageA(hwndCombo, CB_ADDSTRING, 0, (LPARAM)Translate(szName)); + SendMessage(hwndCombo, CB_SETITEMDATA, index, (LPARAM)dblink); + } + return DBPE_CONT; +} + +// returns 1 if autocreation of the profile is setup, profile has to be at least MAX_PATH! +static int checkAutoCreateProfile(char * profile) +{ + char ac[MAX_PATH]; + char env_profile[MAX_PATH]; + GetPrivateProfileStringA("Database", "AutoCreate", "no", ac, SIZEOF(ac), mirandabootini); + if ( lstrcmpiA(ac,"yes") != 0 ) return 0; + GetPrivateProfileStringA("Database", "DefaultProfile", "", ac, SIZEOF(ac), mirandabootini); + ExpandEnvironmentStringsA(ac, env_profile, SIZEOF(env_profile)); + if ( profile != NULL ) strcpy(profile, env_profile); + return lstrlenA(env_profile) > 0; +} + +static BOOL CALLBACK DlgProfileNew(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct DlgProfData * dat = (struct DlgProfData *)GetWindowLong(hwndDlg,GWL_USERDATA); + switch (msg) { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + // lParam = (struct DlgProfData *) + SetWindowLong(hwndDlg, GWL_USERDATA, lParam); + dat=(struct DlgProfData *)lParam; + { + // fill in the db plugins present + PLUGIN_DB_ENUM dbe; + dbe.cbSize=sizeof(dbe); + dbe.pfnEnumCallback=(int(*)(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); + } //if + // default item + SendDlgItemMessage(hwndDlg, IDC_PROFILEDRIVERS, CB_SETCURSEL, 0, 0); + } + // subclass the profile name box + { + HWND hwndProfile=GetDlgItem(hwndDlg, IDC_PROFILENAME); + WNDPROC proc = (WNDPROC)GetWindowLong(hwndProfile, GWL_WNDPROC); + SetWindowLong(hwndProfile,GWL_USERDATA,(LONG)proc); + SetWindowLong(hwndProfile,GWL_WNDPROC,(LONG)ProfileNameValidate); + } + // decide if there is a default profile name given in the INI and if it should be used + { + char profile[MAX_PATH]; + if ( checkAutoCreateProfile((char*)&profile) ) SetDlgItemTextA(hwndDlg, IDC_PROFILENAME, profile); + } + // 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) ) { + char szName[MAX_PATH]; + LRESULT curSel = SendDlgItemMessage(hwndDlg,IDC_PROFILEDRIVERS,CB_GETCURSEL,0,0); + if ( curSel == CB_ERR ) break; // should never happen + GetWindowTextA(GetDlgItem(hwndDlg,IDC_PROFILENAME),szName,SIZEOF(szName)); + if ( lstrlenA(szName) == 0 ) break; + mir_snprintf(dat->pd->szProfile,MAX_PATH,"%s\\%s.dat",dat->pd->szProfileDir,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 ) { + SetWindowLong(hwndDlg,DWL_MSGRESULT,PSNRET_INVALID_NOCHANGEPAGE); + return FALSE; + } + } + break; + } + } + return FALSE; +} + +TCHAR* rtrim( TCHAR *string ) +{ + TCHAR* p = string + _tcslen( string ) - 1; + + while ( p >= string ) + { if ( *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r' ) + break; + + *p-- = 0; + } + return string; +} + +static int DetectDbProvider(char * pluginname, DATABASELINK * dblink, LPARAM lParam) +{ + char* fullPath = (char*)lParam; + int error; + + if ( dblink->grokHeader( fullPath, &error ) == 0 ) { + dblink->getFriendlyName( fullPath, MAX_PATH, 1 ); + //strncpy( fullPath, pluginname, MAX_PATH ); + return DBPE_HALT; + } + + return DBPE_CONT; +} + +BOOL EnumProfilesForList(char * fullpath, char * profile, LPARAM lParam) +{ + HWND hwndDlg = (HWND) lParam; + HWND hwndList = GetDlgItem(hwndDlg, IDC_PROFILELIST); + char sizeBuf[64]; + LVITEMA item; + int iItem=0; + struct stat statbuf; + int bFileExists = FALSE; + char * p = strrchr(profile, '.'); + strcpy(sizeBuf, "0 KB"); + if ( p != NULL ) *p=0; + ZeroMemory(&item,sizeof(item)); + item.mask = LVIF_TEXT | LVIF_IMAGE; + item.pszText = profile; + item.iItem=0; + item.iImage=0; + { + FILE * fp = fopen(fullpath, "r+"); + item.iImage = fp != NULL ? 0 : 1; + if ( stat(fullpath, &statbuf) == 0) { + mir_snprintf(sizeBuf,SIZEOF(sizeBuf),"%u KB", statbuf.st_size / 1024); + bFileExists = TRUE; + } + if ( fp ) fclose(fp); + } + iItem=SendMessageA( hwndList, LVM_INSERTITEMA, 0, (LPARAM)&item); + if ( lstrcmpiA(szDefaultMirandaProfile, profile) == 0 ) + ListView_SetItemState(hwndList, iItem, LVIS_SELECTED, LVIS_SELECTED); + + item.iItem = iItem; + item.iSubItem = 2; + item.pszText = sizeBuf; + SendMessageA( hwndList, LVM_SETITEMTEXTA, iItem, (LPARAM)&item ); + + if ( bFileExists ) { + PLUGIN_DB_ENUM dbe; + char szPath[ MAX_PATH ]; + + LVITEM item2; + item2.mask = LVIF_TEXT; + item2.iItem = iItem; + + dbe.cbSize=sizeof(dbe); + dbe.pfnEnumCallback=(int(*)(char*,void*,LPARAM))DetectDbProvider; + dbe.lParam=(LPARAM)szPath; + strncpy( szPath, fullpath, sizeof(szPath)); + if (CallService(MS_PLUGINS_ENUMDBPLUGINS,0,(LPARAM)&dbe)==1) { + HANDLE hFile; + + hFile=CreateFileA(fullpath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); + if (hFile == INVALID_HANDLE_VALUE) { + // file locked + item.pszText = Translate(""); + } + else { + CloseHandle(hFile); + item.pszText = szPath; + } + item.iSubItem = 1; + SendMessageA( hwndList, LVM_SETITEMTEXTA, 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; +} + +static BOOL CALLBACK DlgProfileSelect(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct DlgProfData * dat = (struct DlgProfData *)GetWindowLong(hwndDlg, GWL_USERDATA); + switch (msg) { + case WM_INITDIALOG: + { + HWND hwndList = GetDlgItem(hwndDlg, IDC_PROFILELIST); + HIMAGELIST hImgList=0; + LVCOLUMN col; + + TranslateDialogDefault(hwndDlg); + + dat = (struct DlgProfData *) lParam; + SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)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("Accessed"); + col.cx=145; + ListView_InsertColumn( hwndList, 4, &col ); + + // icons + hImgList=ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 1, 1); + ImageList_AddIcon(hImgList, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_USERDETAILS)) ); + ImageList_AddIcon(hImgList, LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_DELETE)) ); + // LV will destroy the image list + ListView_SetImageList(hwndList, hImgList, LVSIL_SMALL); + // find all the profiles + findProfiles(dat->pd->szProfileDir, EnumProfilesForList, (LPARAM)hwndDlg); + PostMessage(hwndDlg,WM_FOCUSTEXTBOX,0,0); + return TRUE; + } + case WM_FOCUSTEXTBOX: + { + HWND hwndList=GetDlgItem(hwndDlg,IDC_PROFILELIST); + SetFocus(hwndList); + if ( lstrlenA(szDefaultMirandaProfile) == 0 || ListView_GetSelectedCount(GetDlgItem(hwndDlg,IDC_PROFILELIST)) == 0 ) + ListView_SetItemState(hwndList, 0, LVIS_SELECTED, LVIS_SELECTED); + break; + } + case WM_SHOWWINDOW: + { + if ( wParam ) { + SetWindowText(dat->hwndOK,TranslateT("&Run")); + EnableWindow(dat->hwndOK, ListView_GetSelectedCount(GetDlgItem(hwndDlg,IDC_PROFILELIST))==1); + } + 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(hdr->hwndFrom)==1); + } + case NM_DBLCLK: + { + HWND hwndList = GetDlgItem(hwndDlg, IDC_PROFILELIST); + LVITEMA item; + char profile[MAX_PATH]; + + if ( dat == NULL ) break; + ZeroMemory(&item,sizeof(item)); + item.mask = LVIF_TEXT; + item.iItem = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED | LVNI_ALL); + item.pszText = profile; + item.cchTextMax = SIZEOF(profile); + if ( SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item) && dat ) { + mir_snprintf(dat->pd->szProfile, MAX_PATH, "%s\\%s.dat", dat->pd->szProfileDir, profile); + if ( hdr->code == NM_DBLCLK ) EndDialog(GetParent(hwndDlg), 1); + } + return TRUE; + } + } + } + break; + } + } //switch + return FALSE; +} + +static BOOL CALLBACK DlgProfileManager(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct DetailsData *dat; + + dat=(struct DetailsData*)GetWindowLong(hwndDlg,GWL_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { + struct DlgProfData * prof = (struct DlgProfData *)lParam; + PROPSHEETHEADER *psh = prof->psh; + TranslateDialogDefault(hwndDlg); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_USERDETAILS))); + dat=(struct DetailsData*)mir_alloc(sizeof(struct DetailsData)); + dat->prof = prof; + prof->hwndOK=GetDlgItem(hwndDlg,IDOK); + EnableWindow(prof->hwndOK, FALSE); + SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)dat); + SetDlgItemTextA(hwndDlg,IDC_NAME,"Miranda IM Profile Manager"); + { LOGFONT lf; + HFONT hNormalFont=(HFONT)SendDlgItemMessage(hwndDlg,IDC_NAME,WM_GETFONT,0,0); + GetObject(hNormalFont,sizeof(lf),&lf); + lf.lfWeight=FW_BOLD; + dat->hBoldFont=CreateFontIndirect(&lf); + SendDlgItemMessage(hwndDlg,IDC_NAME,WM_SETFONT,(WPARAM)dat->hBoldFont,0); + } + { OPTIONSDIALOGPAGE *odp; + int i; + TCITEM tci; + + dat->currentPage=0; + dat->pageCount=psh->nPages; + dat->opd=(struct DetailsPageData*)mir_alloc(sizeof(struct DetailsPageData)*dat->pageCount); + odp=(OPTIONSDIALOGPAGE*)psh->ppsp; + + tci.mask=TCIF_TEXT; + for(i=0;ipageCount;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 || checkAutoCreateProfile(NULL) ) 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); + } + ShowWindow(dat->opd[dat->currentPage].hwnd,SW_SHOW); + return TRUE; + } + case WM_CTLCOLORSTATIC: + switch (GetDlgCtrlID((HWND)lParam)) { + case IDC_WHITERECT: + case IDC_LOGO: + case IDC_NAME: + case IDC_DESCRIPTION: + SetBkColor((HDC)wParam,RGB(255,255,255)); + return (BOOL)GetStockObject(WHITE_BRUSH); + } + 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;ipageCount;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=(LPARAM)0; + if(SendMessage(dat->opd[dat->currentPage].hwnd,WM_NOTIFY,0,(LPARAM)&pshn)) { + SetWindowLong(hwndDlg,DWL_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 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;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); + if ( GetWindowLong(dat->opd[i].hwnd,DWL_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: + SendDlgItemMessage(hwndDlg,IDC_NAME,WM_SETFONT,SendDlgItemMessage(hwndDlg,IDC_WHITERECT,WM_GETFONT,0,0),0); + DeleteObject(dat->hBoldFont); + { int i; + for(i=0;ipageCount;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(opi==NULL||odp==NULL); + if(odp->cbSize!=sizeof(OPTIONSDIALOGPAGE)) return 1; + opi->odp=(OPTIONSDIALOGPAGE*)mir_realloc(opi->odp,sizeof(OPTIONSDIALOGPAGE)*(opi->pageCount+1)); + opi->odp[opi->pageCount].cbSize=sizeof(OPTIONSDIALOGPAGE); + opi->odp[opi->pageCount].hInstance=odp->hInstance; + opi->odp[opi->pageCount].pfnDlgProc=odp->pfnDlgProc; + opi->odp[opi->pageCount].position=odp->position; + opi->odp[opi->pageCount].ptszTitle=LangPackPcharToTchar(odp->pszTitle); + if((DWORD)odp->pszTemplate&0xFFFF0000) opi->odp[opi->pageCount].pszTemplate=mir_strdup(odp->pszTemplate); + else opi->odp[opi->pageCount].pszTemplate=odp->pszTemplate; + opi->odp[opi->pageCount].pszGroup=NULL; + opi->odp[opi->pageCount].groupPosition=odp->groupPosition; + opi->odp[opi->pageCount].hGroupIcon=odp->hGroupIcon; + opi->odp[opi->pageCount].hIcon=odp->hIcon; + opi->pageCount++; + return 0; +} + + +int getProfileManager(PROFILEMANAGERDATA * pd) +{ + PROPSHEETHEADER psh; + struct DlgProfData prof; + struct DetailsPageInit opi; + int rc=0; + int i; + + opi.pageCount=0; + opi.odp=NULL; + + { // remember what the default profile is, if any. + char defaultProfile[MAX_PATH]; + GetPrivateProfileStringA("Database", "DefaultProfile", "", defaultProfile, SIZEOF(defaultProfile), mirandabootini); + ExpandEnvironmentStringsA(defaultProfile, szDefaultMirandaProfile, SIZEOF(szDefaultMirandaProfile)); + } + + { + OPTIONSDIALOGPAGE odp; + ZeroMemory(&odp,sizeof(odp)); + odp.cbSize=sizeof(odp); + odp.pszTitle=Translate("My Profiles"); + odp.pfnDlgProc=DlgProfileSelect; + odp.pszTemplate=MAKEINTRESOURCEA(IDD_PROFILE_SELECTION); + odp.hInstance=GetModuleHandle(NULL); + AddProfileManagerPage(&opi, &odp); + + odp.pszTitle=Translate("New Profile"); + odp.pszTemplate=MAKEINTRESOURCEA(IDD_PROFILE_NEW); + odp.pfnDlgProc=DlgProfileNew; + AddProfileManagerPage(&opi, &odp); + } + + ZeroMemory(&psh,sizeof(psh)); + 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; + prof.pd=pd; + prof.psh=&psh; + rc=DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_PROFILEMANAGER),NULL,DlgProfileManager,(LPARAM)&prof); + + if (rc != -1) + { + for(i=0;i