/* X-Tray * Copyright (C) 2005 Michael Hotaling <Mike.Hotaling@SinisterDevelopments.com> * * X-Tray 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. * * X-Tray 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 X-Tray; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <windows.h> #include <stdio.h> #include <commctrl.h> #include <tchar.h> #include "xchat-plugin.h" #include "utility.h" #include "xtray.h" #include "callbacks.h" #include "resource.h" TCHAR BACKUP_INI_FILE[] = _T(".\\plugins\\config\\xtray.conf"); struct HOTKEY g_hHotKey; /* we need to convert ALT and SHIFT modifiers // from <winuser.h> #define MOD_ALT 0x0001 #define MOD_CONTROL 0x0002 #define MOD_SHIFT 0x0004 // from <commctrl.h> #define HOTKEYF_SHIFT 0x01 #define HOTKEYF_CONTROL 0x02 #define HOTKEYF_ALT 0x04 */ WORD HotkeyfToMod(WORD modifiers) { WORD newmods = 0; if (modifiers & HOTKEYF_SHIFT) newmods |= MOD_SHIFT; if (modifiers & HOTKEYF_CONTROL) newmods |= MOD_CONTROL; if (modifiers & HOTKEYF_ALT) newmods |= MOD_ALT; return newmods; } WORD ModToHotkeyf(WORD modifiers) { WORD newmods = 0; if (modifiers & MOD_SHIFT) newmods |= HOTKEYF_SHIFT; if (modifiers & MOD_CONTROL) newmods |= HOTKEYF_CONTROL; if (modifiers & MOD_ALT) newmods |= HOTKEYF_ALT; return newmods; } void SavePrefs(int iDlg) { /**************************************************************************************************/ /********** allocate space for our string, and then set it to the currently logged on user ********/ /**************************************************************************************************/ DWORD dBuff = 257; TCHAR szUser[257]; GetUserName(szUser, &dBuff); /**************************************************************************************************/ /*********************** Test if the file exists, If it doesn't, Create It ************************/ /**************************************************************************************************/ TCHAR XTRAY_INI_FILE[1024]; #ifdef UNICODE char temp[1024]; TCHAR TEMP_INI_FILE[1024]; _snprintf(temp, 1024, "%s\\xtray.conf", xchat_get_info(ph, "xchatdir")); ConvertString(temp, TEMP_INI_FILE, 1024); // ok this one is really ugly // it checks to see if the file exists in two locations // X-Chat default config dir, if that fails it trys xchat\plugins\config // if neither one exists it tries to create it in // X-Chat default config dir, if that fails it trys xchat\plugins\config // In either case it writes \xFF\xFE to the file ( on creation ) // so that we can save unicode away messages WritePrivateProfile doesn't // do this for us, though I think it really should if(FileExists(TEMP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE); } else { if(FileExists(BACKUP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE); } else { HANDLE xTemp; DWORD dwBytesTemp; if(xTemp = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) { if(GetLastError() != ERROR_ALREADY_EXISTS) { WriteFile(xTemp, _T("\xFF\xFE"), 4, &dwBytesTemp, NULL); } CloseHandle(xTemp); } if(FileExists(TEMP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE); } else { HANDLE xBackup; DWORD dwBytesBackup; if(xBackup = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) { if(GetLastError() != ERROR_ALREADY_EXISTS) { WriteFile(xBackup, _T("\xFF\xFE"), 4, &dwBytesBackup, NULL); } CloseHandle(xBackup); } if(FileExists(BACKUP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE); } } } } #else _tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE); #endif WritePrivateProfileInt(szUser, _T("SETTINGS"), g_dwPrefs, XTRAY_INI_FILE); WritePrivateProfileInt(szUser, _T("AOT"), g_iTime, XTRAY_INI_FILE); WritePrivateProfileInt(szUser, _T("KEY"), g_hHotKey.key, XTRAY_INI_FILE); WritePrivateProfileInt(szUser, _T("MOD"), g_hHotKey.mod, XTRAY_INI_FILE); WritePrivateProfileString(szUser, _T("AWAY"), g_szAway, XTRAY_INI_FILE); } void LoadPrefs() { /**************************************************************************************************/ /*********************** Our Settings Section *****************************************************/ /**************************************************************************************************/ DWORD dBuff = 257; TCHAR szUser[257]; GetUserName(szUser, &dBuff); /**************************************************************************************************/ /*********************** Test if the file exists, If it doesn't, Create It ************************/ /**************************************************************************************************/ TCHAR XTRAY_INI_FILE[1024]; #ifdef UNICODE char temp[1024]; TCHAR TEMP_INI_FILE[1024]; _snprintf(temp, 1024, "%s\\xtray.conf", xchat_get_info(ph, "xchatdir")); ConvertString(temp, TEMP_INI_FILE, 1024); if(FileExists(TEMP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE); } else { if(FileExists(BACKUP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE); } else { HANDLE xTemp; DWORD dwBytesTemp; if(xTemp = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) { if(GetLastError() != ERROR_ALREADY_EXISTS) { WriteFile(xTemp, _T("\xFF\xFE"), 4, &dwBytesTemp, NULL); } CloseHandle(xTemp); } if(FileExists(TEMP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE); } else { HANDLE xBackup; DWORD dwBytesBackup; if(xBackup = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) { if(GetLastError() != ERROR_ALREADY_EXISTS) { WriteFile(xBackup, _T("\xFF\xFE"), 4, &dwBytesBackup, NULL); } CloseHandle(xBackup); } if(FileExists(BACKUP_INI_FILE)) { _tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE); } } } } #else _tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE); #endif /**************************************************************************************************/ /*************************** Get the value for each of our preferances ****************************/ /**************************************************************************************************/ g_dwPrefs = GetPrivateProfileInt(szUser, _T("SETTINGS"), 0, XTRAY_INI_FILE); // backwards compatability // also allows us to set defaults if its a new installation // disable topic change, channel message and server notice by default if(g_dwPrefs == 0) { g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("HILIGHT"), 1, XTRAY_INI_FILE)<<1); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("INVITE"), 1, XTRAY_INI_FILE)<<2); /* g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("TOPIC"), 1, XTRAY_INI_FILE)<<3); */ g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("BANNED"), 1, XTRAY_INI_FILE)<<4); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("KICKED"), 1, XTRAY_INI_FILE)<<5); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("CTCP"), 1, XTRAY_INI_FILE)<<6); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("PMSG"), 1, XTRAY_INI_FILE)<<7); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("KILLED"), 1, XTRAY_INI_FILE)<<8); /* g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("NOTICE"), 1, XTRAY_INI_FILE)<<9); */ g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("DISCONNECT"), 1, XTRAY_INI_FILE)<<10); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("AOM"), 0, XTRAY_INI_FILE)<<11); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("TOT"), 1, XTRAY_INI_FILE)<<12); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("AMAE"), 1, XTRAY_INI_FILE)<<13); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("OSBWM"), 0, XTRAY_INI_FILE)<<14); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("UWIOB"), 0, XTRAY_INI_FILE)<<15); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("KAOI"), 0, XTRAY_INI_FILE)<<16); g_dwPrefs |= (GetPrivateProfileInt(szUser, _T("MIOC"), 0, XTRAY_INI_FILE)<<17); } g_hHotKey.key = GetPrivateProfileInt(szUser, _T("KEY"), 84, XTRAY_INI_FILE); g_hHotKey.mod = GetPrivateProfileInt(szUser, _T("MOD"), (MOD_CONTROL | MOD_SHIFT), XTRAY_INI_FILE); g_iTime = GetPrivateProfileInt(szUser, _T("AOT"), 5, XTRAY_INI_FILE); GetPrivateProfileString(szUser, _T("AWAY"), _T(""), g_szAway, 1024, XTRAY_INI_FILE); /**************************************************************************************************/ /******************************** Register our hotkey with windows ********************************/ /**************************************************************************************************/ if(g_dwPrefs & (1<<PREF_UWIOB)) { RegisterHotKey(g_hHotkeyWnd, 1, g_hHotKey.mod, g_hHotKey.key); } } void CheckPrefs(HWND hwnd, int iDlg) { /**************************************************************************************************/ /**************** save the preferances based on the checkmarks/options ****************************/ /**************************************************************************************************/ switch(iDlg) { case IDD_EVENTS: { SetOption(hwnd, CHAN_HILIGHT, CHAN_HILIGHT); SetOption(hwnd, CHAN_INVITE, CHAN_INVITE); SetOption(hwnd, CHAN_TOPIC_CHANGE, CHAN_TOPIC_CHANGE); SetOption(hwnd, CHAN_BANNED, CHAN_BANNED); SetOption(hwnd, CHAN_KICKED, CHAN_KICKED); SetOption(hwnd, CTCP_GENERIC, CTCP_GENERIC); SetOption(hwnd, PMSG_RECEIVE, PMSG_RECEIVE); SetOption(hwnd, SERV_KILLED, SERV_KILLED); SetOption(hwnd, SERV_NOTICE, SERV_NOTICE); SetOption(hwnd, SERV_DISCONNECT, SERV_DISCONNECT); SetOption(hwnd, CHAN_MESSAGE, CHAN_MESSAGE); } break; case IDD_ALERTS: { SetOption(hwnd, PREF_AMAE, PREF_AMAE); SetOption(hwnd, PREF_OSBWM, PREF_OSBWM); SetOption(hwnd, PREF_UWIOB, PREF_UWIOB); SetOption(hwnd, PREF_KAOI, PREF_KAOI); SetOption(hwnd, PREF_BLINK, PREF_BLINK); /**************************************************************************/ /**************************************************************************/ /**************************************************************************/ TCHAR tTime[512]; GetWindowText(GetDlgItem(hwnd, IDC_ALERT_TIME), tTime, 511); g_iTime = _tstoi(tTime); /**************************************************************************/ /**************** Get our Hotkey and save it **********/ /**************** then remove the old hotkey and add the new one **********/ /**************************************************************************/ DWORD hHotkey; hHotkey = SendDlgItemMessage(hwnd, IDC_ALERT_HOTKEY, HKM_GETHOTKEY, 0, 0); g_hHotKey.key = LOBYTE(hHotkey); g_hHotKey.mod = HotkeyfToMod(HIBYTE(hHotkey)); if(IsDlgButtonChecked(hwnd, PREF_UWIOB) == BST_CHECKED) { UnregisterHotKey(g_hHotkeyWnd, 1); RegisterHotKey(g_hHotkeyWnd, 1, g_hHotKey.mod, g_hHotKey.key); } else { UnregisterHotKey(g_hHotkeyWnd, 1); } /*************************************************************************/ /*********** Get and save the away msg and alert time ********************/ /*************************************************************************/ } break; case IDD_SETTINGS: { SetOption(hwnd, PREF_AOM, PREF_AOM); SetOption(hwnd, PREF_TOT, PREF_TOT); SetOption(hwnd, PREF_MIOC, PREF_MIOC); SetOption(hwnd, PREF_DNSIT, PREF_DNSIT); GetDlgItemText(hwnd, IDC_AWAY_MSG, g_szAway, 511); if(g_dwPrefs & (1<<PREF_DNSIT)) { DWORD dwStyle; dwStyle = GetWindowLong(g_hXchatWnd, GWL_STYLE); dwStyle |= (1<<WS_CHILD); SetWindowLongPtr(g_hXchatWnd, GWL_STYLE, (LONG_PTR)dwStyle); SetWindowLongPtr(g_hXchatWnd, GWL_HWNDPARENT, (LONG_PTR)g_hHotkeyWnd); } else { DWORD dwStyle; dwStyle = GetWindowLong(g_hXchatWnd, GWL_STYLE); dwStyle &= ~(1<<WS_CHILD); SetWindowLongPtr(g_hXchatWnd, GWL_STYLE, (LONG_PTR)dwStyle); SetWindowLongPtr(g_hXchatWnd, GWL_HWNDPARENT, NULL); } } break; } } void SetDialog(HWND hwnd, int iDlg) { switch(iDlg) { case IDD_EVENTS: { SetCheck(hwnd, CHAN_HILIGHT, CHAN_HILIGHT); SetCheck(hwnd, CHAN_INVITE, CHAN_INVITE); SetCheck(hwnd, CHAN_TOPIC_CHANGE, CHAN_TOPIC_CHANGE); SetCheck(hwnd, CHAN_BANNED, CHAN_BANNED); SetCheck(hwnd, CHAN_KICKED, CHAN_KICKED); SetCheck(hwnd, CTCP_GENERIC, CTCP_GENERIC); SetCheck(hwnd, PMSG_RECEIVE, PMSG_RECEIVE); SetCheck(hwnd, SERV_KILLED, SERV_KILLED); SetCheck(hwnd, SERV_NOTICE, SERV_NOTICE); SetCheck(hwnd, SERV_DISCONNECT, SERV_DISCONNECT); SetCheck(hwnd, CHAN_MESSAGE, CHAN_MESSAGE); } break; case IDD_SETTINGS: { SetCheck(hwnd, PREF_TOT, PREF_TOT); SetCheck(hwnd, PREF_MIOC, PREF_MIOC); SetCheck(hwnd, PREF_AOM, PREF_AOM); SetCheck(hwnd, PREF_DNSIT, PREF_DNSIT); SetDlgItemText(hwnd, IDC_AWAY_MSG, g_szAway); } break; case IDD_ALERTS: { SetCheck(hwnd, PREF_BLINK, PREF_BLINK); SetCheck(hwnd, PREF_OSBWM, PREF_OSBWM); SetCheck(hwnd, PREF_UWIOB, PREF_UWIOB); SetCheck(hwnd, PREF_KAOI, PREF_KAOI); /**********************************************************/ /**********************************************************/ /**********************************************************/ if(SetCheck(hwnd, PREF_AMAE, PREF_AMAE) == false) { SetToggle(hwnd, PREF_OSBWM, PREF_AMAE, TRUE); SetToggle(hwnd, PREF_UWIOB, PREF_AMAE, TRUE); SetToggle(hwnd, PREF_KAOI, PREF_AMAE, TRUE); SetToggle(hwnd, IDC_ALERT_TIME, PREF_AMAE, TRUE); SetToggle(hwnd, IDC_ALERT_TIME_TEXT, PREF_AMAE, TRUE); SetToggle(hwnd, IDC_ALERT_HOTKEY, PREF_AMAE, TRUE); SetToggle(hwnd, IDC_ALERT_HOTKEY_TEXT, PREF_AMAE, TRUE); } else { SetToggle(hwnd, IDC_ALERT_HOTKEY, PREF_UWIOB, TRUE); SetToggle(hwnd, IDC_ALERT_HOTKEY_TEXT, PREF_UWIOB, TRUE); SetToggle(hwnd, IDC_ALERT_TIME, PREF_KAOI, FALSE); SetToggle(hwnd, IDC_ALERT_TIME_TEXT, PREF_KAOI, FALSE); } /**********************************************************/ /**********************************************************/ /**********************************************************/ TCHAR tTime[255]; SendDlgItemMessage(hwnd, IDC_ALERT_TIME, WM_SETTEXT, 0, (LPARAM)_itot(g_iTime, tTime, 10)); SendDlgItemMessage(hwnd, IDC_ALERT_HOTKEY, HKM_SETHOTKEY, MAKEWORD(g_hHotKey.key, ModToHotkeyf(g_hHotKey.mod)), 0); } break; } } int SetCheck(HWND hDialog, unsigned int uiCheckBox, unsigned int uiPref) { if((g_dwPrefs & (1<<uiPref))) { CheckDlgButton(hDialog, uiCheckBox, BST_CHECKED); return 1; } else { CheckDlgButton(hDialog, uiCheckBox, BST_UNCHECKED); return 0; } return 0; } int SetToggle(HWND hDialog, unsigned int uiCheckBox, unsigned int uiTestbox, bool offeqoff) { /**************************************************************************************************/ /*********************** if(true) then if option is off turn toggle off ***************************/ /*********************** if(false) then if option is off turn toggle on ***************************/ /**************************************************************************************************/ if(offeqoff) { if(IsDlgButtonChecked(hDialog, uiTestbox) == BST_CHECKED) { EnableWindow(GetDlgItem(hDialog, uiCheckBox), TRUE); return 1; } else { EnableWindow(GetDlgItem(hDialog, uiCheckBox), FALSE); return 0; } } else { if(IsDlgButtonChecked(hDialog, uiTestbox) == BST_CHECKED) { EnableWindow(GetDlgItem(hDialog, uiCheckBox), FALSE); return 1; } else { EnableWindow(GetDlgItem(hDialog, uiCheckBox), TRUE); return 0; } } return 0; } int SetOption(HWND hDialog, unsigned int uiCheckBox, unsigned int uiPref) { if(IsDlgButtonChecked(hDialog, uiCheckBox) == BST_CHECKED) { g_dwPrefs |= (1<<uiPref); } else { g_dwPrefs &= ~(1<<uiPref); } return (g_dwPrefs & (1<<uiPref)); } int WritePrivateProfileIntA(char *szSection, char *szItem, int iData, char *szPath) { char szData[33]; itoa(iData, szData, 10); return WritePrivateProfileStringA(szSection, szItem, szData, szPath); } int WritePrivateProfileIntW(wchar_t *wszSection, wchar_t *wszItem, int iData, wchar_t *wszPath) { wchar_t wszData[33]; _itow(iData, wszData, 10); return WritePrivateProfileStringW(wszSection, wszItem, wszData, wszPath); } // For cleanup ( Closing windows and the such ) void HoldClose() { HANDLE hcThread; DWORD dwThreadID; hcThread = CreateThread(NULL, 0, HoldCloseThread, 0, 0, &dwThreadID); } DWORD WINAPI HoldCloseThread(LPVOID lpParam) { Sleep(1000); PostMessage(g_hXchatWnd, WM_CLOSE, 0, 0); return 0; } bool FileExists(TCHAR *file) { HANDLE hTemp = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); int nRet = GetLastError(); CloseHandle(hTemp); if(nRet == 0) { return true; } else { return false; } return false; } void ConvertString(const char *in, wchar_t *out, int size) { MultiByteToWideChar(CP_UTF8, 0, in, -1, out, size); } void ConvertString(const wchar_t *in, char *out, int size) { WideCharToMultiByte(CP_UTF8, 0, in, (size - 1), out, size, NULL, NULL); } void ConvertString(const char *in, char *out, int size) { strncpy(out, in, size); } void ErrorDebug(LPTSTR lpszFunction) { TCHAR szBuf[80]; LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); _stprintf(szBuf, _T("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, szBuf, _T("Error"), MB_OK); LocalFree(lpMsgBuf); }