From 7a6399d054da0e2e21d00b110b885e15b278d3b7 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sun, 24 Jun 2012 12:33:14 +0000 Subject: Chat: renamed to .cpp git-svn-id: http://svn.miranda-ng.org/main/trunk@601 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Chat/tools.cpp | 918 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 918 insertions(+) create mode 100644 plugins/Chat/tools.cpp (limited to 'plugins/Chat/tools.cpp') diff --git a/plugins/Chat/tools.cpp b/plugins/Chat/tools.cpp new file mode 100644 index 0000000000..ef24f40a13 --- /dev/null +++ b/plugins/Chat/tools.cpp @@ -0,0 +1,918 @@ +/* +Chat module plugin for Miranda IM + +Copyright 2000-2010 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 "chat.h" + +extern HICON hIcons[30]; +extern BOOL PopUpInstalled; +extern HINSTANCE g_hInst; +extern FONTINFO aFonts[OPTIONS_FONTCOUNT]; +extern HMENU g_hMenu; +extern HANDLE hBuildMenuEvent ; +extern HANDLE hSendEvent; +extern SESSION_INFO g_TabSession; + +int GetRichTextLength(HWND hwnd) +{ + GETTEXTLENGTHEX gtl; + + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP ; + return (int) SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); +} + +TCHAR* RemoveFormatting(const TCHAR* pszWord) +{ + static TCHAR szTemp[10000]; + int i = 0; + int j = 0; + + if ( pszWord == 0 || lstrlen(pszWord) == 0 ) + return NULL; + + while(j < 9999 && i <= lstrlen( pszWord )) { + if (pszWord[i] == '%') { + switch ( pszWord[i+1] ) { + case '%': + szTemp[j] = '%'; + j++; + i++; i++; + break; + case 'b': + case 'u': + case 'i': + case 'B': + case 'U': + case 'I': + case 'r': + case 'C': + case 'F': + i++; i++; + break; + + case 'c': + case 'f': + i += 4; + break; + + default: + szTemp[j] = pszWord[i]; + j++; + i++; + break; + } } + else { + szTemp[j] = pszWord[i]; + j++; + i++; + } } + + return (TCHAR*) &szTemp; +} + +static void __stdcall ShowRoomFromPopup(void * pi) +{ + SESSION_INFO* si = (SESSION_INFO*) pi; + ShowRoom(si, WINDOW_VISIBLE, TRUE); +} + +static INT_PTR CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) { + case WM_COMMAND: + if (HIWORD(wParam) == STN_CLICKED) { + SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)0);; + + CallFunctionAsync(ShowRoomFromPopup, si); + + PUDeletePopUp(hWnd); + return TRUE; + } + break; + case WM_CONTEXTMENU: + { + SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)0); + if (si->hContact) + if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0)) + CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)"chaticon"); + + if (si->hWnd && KillTimer(si->hWnd, TIMERID_FLASHWND)) + FlashWindow(si->hWnd, FALSE); + + PUDeletePopUp( hWnd ); + } + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +static int ShowPopup (HANDLE hContact, SESSION_INFO* si, HICON hIcon, char* pszProtoName, TCHAR* pszRoomName, COLORREF crBkg, const TCHAR* fmt, ...) +{ + POPUPDATAT pd = {0}; + va_list marker; + static TCHAR szBuf[4*1024]; + + if (!fmt || lstrlen(fmt) == 0 || lstrlen(fmt) > 2000) + return 0; + + va_start(marker, fmt); + _vsntprintf(szBuf, 4096, fmt, marker); + va_end(marker); + + pd.lchContact = hContact; + + if ( hIcon ) + pd.lchIcon = hIcon ; + else + pd.lchIcon = LoadIconEx( "window", FALSE ); + + mir_sntprintf(pd.lptzContactName, MAX_CONTACTNAME-1, _T(TCHAR_STR_PARAM) _T(" - %s"), + pszProtoName, CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR )); + lstrcpyn( pd.lptzText, TranslateTS(szBuf), MAX_SECONDLINE-1); + pd.iSeconds = g_Settings.iPopupTimeout; + + if (g_Settings.iPopupStyle == 2) { + pd.colorBack = 0; + pd.colorText = 0; + } + else if (g_Settings.iPopupStyle == 3) { + pd.colorBack = g_Settings.crPUBkgColour; + pd.colorText = g_Settings.crPUTextColour; + } + else { + pd.colorBack = g_Settings.crLogBackground; + pd.colorText = crBkg; + } + + pd.PluginWindowProc = PopupDlgProc; + pd.PluginData = si; + return PUAddPopUpT(&pd); +} + +static BOOL DoTrayIcon(SESSION_INFO* si, GCEVENT * gce) +{ + int iEvent = gce->pDest->iType; + + if ( iEvent&g_Settings.dwTrayIconFlags ) { + switch ( iEvent ) { + case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT : + case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT : + CList_AddEvent(si->hContact, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), "chaticon", 0, TranslateT("%s wants your attention in %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_MESSAGE : + CList_AddEvent(si->hContact, hIcons[ICON_MESSAGE], "chaticon", CLEF_ONLYAFEW, TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_ACTION: + CList_AddEvent(si->hContact, hIcons[ICON_ACTION], "chaticon", CLEF_ONLYAFEW, TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_JOIN: + CList_AddEvent(si->hContact, hIcons[ICON_JOIN], "chaticon", CLEF_ONLYAFEW, TranslateT("%s has joined %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_PART: + CList_AddEvent(si->hContact, hIcons[ICON_PART], "chaticon", CLEF_ONLYAFEW, TranslateT("%s has left %s"), gce->ptszNick, si->ptszName); + break; + case GC_EVENT_QUIT: + CList_AddEvent(si->hContact, hIcons[ICON_QUIT], "chaticon", CLEF_ONLYAFEW, TranslateT("%s has disconnected"), gce->ptszNick); + break; + case GC_EVENT_NICK: + CList_AddEvent(si->hContact, hIcons[ICON_NICK], "chaticon", CLEF_ONLYAFEW, TranslateT("%s is now known as %s"), gce->ptszNick, gce->pszText); + break; + case GC_EVENT_KICK: + CList_AddEvent(si->hContact, hIcons[ICON_KICK], "chaticon", CLEF_ONLYAFEW, TranslateT("%s kicked %s from %s"), gce->pszStatus, gce->ptszNick, si->ptszName); + break; + case GC_EVENT_NOTICE: + CList_AddEvent(si->hContact, hIcons[ICON_NOTICE], "chaticon", CLEF_ONLYAFEW, TranslateT("Notice from %s"), gce->ptszNick); + break; + case GC_EVENT_TOPIC: + CList_AddEvent(si->hContact, hIcons[ICON_TOPIC], "chaticon", CLEF_ONLYAFEW, TranslateT("Topic change in %s"), si->ptszName); + break; + case GC_EVENT_INFORMATION: + CList_AddEvent(si->hContact, hIcons[ICON_INFO], "chaticon", CLEF_ONLYAFEW, TranslateT("Information in %s"), si->ptszName); + break; + case GC_EVENT_ADDSTATUS: + CList_AddEvent(si->hContact, hIcons[ICON_ADDSTATUS], "chaticon", CLEF_ONLYAFEW, TranslateT("%s enables \'%s\' status for %s in %s"), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName); + break; + case GC_EVENT_REMOVESTATUS: + CList_AddEvent(si->hContact, hIcons[ICON_REMSTATUS], "chaticon", CLEF_ONLYAFEW, TranslateT("%s disables \'%s\' status for %s in %s"), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName); + break; + } } + + return TRUE; +} + +static BOOL DoPopup(SESSION_INFO* si, GCEVENT * gce) +{ + int iEvent = gce->pDest->iType; + + if ( iEvent & g_Settings.dwPopupFlags ) { + switch (iEvent) { + case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT : + ShowPopup(si->hContact, si, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), si->pszModule, si->ptszName, aFonts[16].color, TranslateT("%s says: %s"), gce->ptszNick, RemoveFormatting( gce->ptszText )); + break; + case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT : + ShowPopup(si->hContact, si, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), si->pszModule, si->ptszName, aFonts[16].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_MESSAGE : + ShowPopup(si->hContact, si, hIcons[ICON_MESSAGE], si->pszModule, si->ptszName, aFonts[9].color, TranslateT("%s says: %s"), gce->ptszNick, RemoveFormatting( gce->ptszText)); + break; + case GC_EVENT_ACTION: + ShowPopup(si->hContact, si, hIcons[ICON_ACTION], si->pszModule, si->ptszName, aFonts[15].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_JOIN: + ShowPopup(si->hContact, si, hIcons[ICON_JOIN], si->pszModule, si->ptszName, aFonts[3].color, TranslateT("%s has joined"), gce->ptszNick); + break; + case GC_EVENT_PART: + if (!gce->pszText) + ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, aFonts[4].color, TranslateT("%s has left"), gce->ptszNick); + else + ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, aFonts[4].color, TranslateT("%s has left (%s)"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_QUIT: + if (!gce->pszText) + ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, aFonts[5].color, TranslateT("%s has disconnected"), gce->ptszNick); + else + ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, aFonts[5].color, TranslateT("%s has disconnected (%s)"), gce->ptszNick,RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NICK: + ShowPopup(si->hContact, si, hIcons[ICON_NICK], si->pszModule, si->ptszName, aFonts[7].color, TranslateT("%s is now known as %s"), gce->ptszNick, gce->ptszText); + break; + case GC_EVENT_KICK: + if (!gce->pszText) + ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, aFonts[6].color, TranslateT("%s kicked %s"), (char *)gce->pszStatus, gce->ptszNick); + else + ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, aFonts[6].color, TranslateT("%s kicked %s (%s)"), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NOTICE: + ShowPopup(si->hContact, si, hIcons[ICON_NOTICE], si->pszModule, si->ptszName, aFonts[8].color, TranslateT("Notice from %s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_TOPIC: + if (!gce->ptszNick) + ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, aFonts[11].color, TranslateT("The topic is \'%s\'"), RemoveFormatting(gce->ptszText)); + else + ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, aFonts[11].color, TranslateT("The topic is \'%s\' (set by %s)"), RemoveFormatting(gce->ptszText), gce->ptszNick); + break; + case GC_EVENT_INFORMATION: + ShowPopup(si->hContact, si, hIcons[ICON_INFO], si->pszModule, si->ptszName, aFonts[12].color, _T("%s"), RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_ADDSTATUS: + ShowPopup(si->hContact, si, hIcons[ICON_ADDSTATUS], si->pszModule, si->ptszName, aFonts[13].color, TranslateT("%s enables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + case GC_EVENT_REMOVESTATUS: + ShowPopup(si->hContact, si, hIcons[ICON_REMSTATUS], si->pszModule, si->ptszName, aFonts[14].color, TranslateT("%s disables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + } } + + return TRUE; +} + +BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix) +{ + BOOL bInactive; + int iEvent; + + if (!gce || !si || gce->bIsMe || si->iType == GCW_SERVER) + return FALSE; + + bInactive = si->hWnd == NULL || GetForegroundWindow() != si->hWnd; + // bInactive |= GetActiveWindow() != si->hWnd; // Removed this, because it seemed to be FALSE, even when window was focused, causing incorrect notifications + + iEvent = gce->pDest->iType; + + if ( bHighlight ) { + gce->pDest->iType |= GC_EVENT_HIGHLIGHT; + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatHighlight"); + if (!g_Settings.TabsEnable && bInactive && si->hWnd && DBGetContactSettingByte(NULL, "Chat", "FlashWindowHighlight", 0) != 0) + SetTimer(si->hWnd, TIMERID_FLASHWND, 900, NULL); + if (DBGetContactSettingByte(si->hContact, "CList", "Hidden", 0) != 0) + DBDeleteContactSetting(si->hContact, "CList", "Hidden"); + if (bInactive) + DoTrayIcon(si, gce); + if (bInactive || !g_Settings.PopUpInactiveOnly) + DoPopup(si, gce); + if (g_Settings.TabsEnable && bInactive && g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM) si); + return TRUE; + } + + // do blinking icons in tray + if (bInactive || !g_Settings.TrayIconInactiveOnly) + DoTrayIcon(si, gce); + + // stupid thing to not create multiple popups for a QUIT event for instance + if (bManyFix == 0) { + // do popups + if (bInactive || !g_Settings.PopUpInactiveOnly) + DoPopup(si, gce); + + // do sounds and flashing + switch (iEvent) { + case GC_EVENT_JOIN: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatJoin"); + break; + case GC_EVENT_PART: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatPart"); + break; + case GC_EVENT_QUIT: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatQuit"); + break; + case GC_EVENT_ADDSTATUS: + case GC_EVENT_REMOVESTATUS: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatMode"); + break; + case GC_EVENT_KICK: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatKick"); + break; + case GC_EVENT_MESSAGE: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatMessage"); + if (!g_Settings.TabsEnable && bInactive && g_Settings.FlashWindow && si->hWnd) + SetTimer(si->hWnd, TIMERID_FLASHWND, 900, NULL); + + if (bInactive && !( si->wState & STATE_TALK )) { + si->wState |= STATE_TALK; + DBWriteContactSettingWord(si->hContact, si->pszModule,"ApparentMode",(LPARAM)(WORD) 40071); + } + if (g_Settings.TabsEnable && bInactive && g_TabSession.hWnd) + SendMessage(g_TabSession.hWnd, GC_SETTABHIGHLIGHT, 0, (LPARAM) si); + break; + case GC_EVENT_ACTION: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatAction"); + break; + case GC_EVENT_NICK: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatNick"); + break; + case GC_EVENT_NOTICE: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatNotice"); + break; + case GC_EVENT_TOPIC: + if (bInactive || !g_Settings.SoundsFocus) + SkinPlaySound("ChatTopic"); + break; + } } + + return TRUE; +} + +int GetColorIndex(const char* pszModule, COLORREF cr) +{ + MODULEINFO * pMod = MM_FindModule(pszModule); + int i = 0; + + if (!pMod || pMod->nColorCount == 0) + return -1; + + for (i = 0; i < pMod->nColorCount; i++) + if (pMod->crColors[i] == cr) + return i; + + return -1; +} + +// obscure function that is used to make sure that any of the colors +// passed by the protocol is used as fore- or background color +// in the messagebox. THis is to vvercome limitations in the richedit +// that I do not know currently how to fix + +void CheckColorsInModule(const char* pszModule) +{ + MODULEINFO * pMod = MM_FindModule( pszModule ); + int i = 0; + COLORREF crFG; + COLORREF crBG = (COLORREF)DBGetContactSettingDword(NULL, "Chat", "ColorMessageBG", GetSysColor(COLOR_WINDOW)); + + LoadMsgDlgFont(17, NULL, &crFG); + + if ( !pMod ) + return; + + for (i = 0; i < pMod->nColorCount; i++) { + if (pMod->crColors[i] == crFG || pMod->crColors[i] == crBG) { + if (pMod->crColors[i] == RGB(255,255,255)) + pMod->crColors[i]--; + else + pMod->crColors[i]++; +} } } + +const TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2) +{ + int i,j,k; + for(i=0; s1[i]; i++) + for(j=i, k=0; _totlower(s1[j]) == _totlower(s2[k]); j++, k++) + if (!s2[k+1]) + return s1 + i; + + return NULL; +} + +BOOL IsHighlighted(SESSION_INFO* si, const TCHAR* pszText) +{ + if ( g_Settings.HighlightEnabled && g_Settings.pszHighlightWords && pszText && si->pMe ) { + TCHAR* p1 = g_Settings.pszHighlightWords; + TCHAR* p2 = NULL; + const TCHAR* p3 = pszText; + static TCHAR szWord1[1000]; + static TCHAR szWord2[1000]; + static TCHAR szTrimString[] = _T(":,.!?;\'>)"); + + // compare word for word + while (*p1 != '\0') { + // find the next/first word in the highlight word string + // skip 'spaces' be4 the word + while(*p1 == ' ' && *p1 != '\0') + p1 += 1; + + //find the end of the word + p2 = _tcschr(p1, ' '); + if (!p2) + p2 = _tcschr(p1, '\0'); + if (p1 == p2) + return FALSE; + + // copy the word into szWord1 + lstrcpyn(szWord1, p1, p2 - p1 > 998 ? 999 : p2 - p1 + 1); + p1 = p2; + + // replace %m with the users nickname + p2 = _tcschr(szWord1, '%'); + if (p2 && p2[1] == 'm') { + TCHAR szTemp[50]; + + p2[1] = 's'; + lstrcpyn(szTemp, szWord1, 999); + mir_sntprintf(szWord1, SIZEOF(szWord1), szTemp, si->pMe->pszNick); + } + + // time to get the next/first word in the incoming text string + while(*p3 != '\0') + { + // skip 'spaces' be4 the word + while(*p3 == ' ' && *p3 != '\0') + p3 += 1; + + //find the end of the word + p2 = _tcschr(p3, ' '); + if (!p2) + p2 = _tcschr(p3, '\0'); + + + if (p3 != p2) { + // eliminate ending character if needed + if (p2-p3 > 1 && _tcschr(szTrimString, p2[-1])) + p2 -= 1; + + // copy the word into szWord2 and remove formatting + lstrcpyn(szWord2, p3, p2-p3>998?999:p2-p3+1); + + // reset the pointer if it was touched because of an ending character + if (*p2 != '\0' && *p2 != ' ') + p2 += 1; + p3 = p2; + + CharLower(szWord1); + CharLower(szWord2); + + // compare the words, using wildcards + if (WCCmp(szWord1, RemoveFormatting(szWord2))) + return TRUE; + } } + + p3 = pszText; + } } + + return FALSE; +} + +BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce) +{ + MODULEINFO * mi = NULL; + TCHAR szBuffer[4096]; + TCHAR szLine[4096]; + TCHAR szTime[100]; + FILE *hFile = NULL; + TCHAR szFile[MAX_PATH]; + TCHAR szName[MAX_PATH]; + TCHAR szFolder[MAX_PATH]; + char p = '\0'; + TCHAR *szModName = NULL; + szBuffer[0] = '\0'; + + if (!si || !gce) + return FALSE; + + mi = MM_FindModule(si->pszModule); + if ( !mi ) + return FALSE; + + szModName = mir_a2t(si->pszModule); + mir_sntprintf(szName, MAX_PATH, _T("%s"), mi->ptszModDispName ? mi->ptszModDispName : (szModName = mir_a2t(si->pszModule))); + mir_free(szModName); + ValidateFilename(szName); + mir_sntprintf(szFolder, MAX_PATH, _T("%s\\%s"), g_Settings.pszLogDir, szName ); + + CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)szFolder); + + mir_sntprintf( szName, MAX_PATH, _T("%s.log"), si->ptszID ); + ValidateFilename(szName); + + mir_sntprintf(szFile, MAX_PATH, _T("%s\\%s"), szFolder, szName ); + lstrcpyn(szTime, MakeTimeStamp(g_Settings.pszTimeStampLog, gce->time), 99); + + hFile = _tfopen(szFile, _T("at+")); + if (hFile) + { + TCHAR szTemp[512], szTemp2[512]; + TCHAR* pszNick = NULL; + if ( gce->ptszNick ) { + if ( g_Settings.LogLimitNames && lstrlen(gce->ptszNick) > 20 ) { + lstrcpyn(szTemp2, gce->ptszNick, 20); + lstrcpyn(szTemp2+20, _T("..."), 4); + } + else lstrcpyn(szTemp2, gce->ptszNick, 511); + + if (gce->pszUserInfo) + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, gce->pszUserInfo); + else + mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), szTemp2); + pszNick = szTemp; + } + switch (gce->pDest->iType) { + case GC_EVENT_MESSAGE: + case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT: + p = '*'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s * %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_ACTION: + case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT: + p = '*'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_JOIN: + p = '>'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has joined"), (char *)pszNick); + break; + case GC_EVENT_PART: + p = '<'; + if (!gce->pszText) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has left"), (char *)pszNick); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has left (%s)"), (char *)pszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_QUIT: + p = '<'; + if (!gce->pszText) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has disconnected"), (char *)pszNick); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has disconnected (%s)"), (char *)pszNick,RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NICK: + p = '^'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s is now known as %s"), gce->ptszNick, gce->ptszText); + break; + case GC_EVENT_KICK: + p = '~'; + if (!gce->pszText) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s kicked %s"), (char *)gce->pszStatus, gce->ptszNick); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s kicked %s (%s)"), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_NOTICE: + p = '¤'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("Notice from %s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_TOPIC: + p = '#'; + if (!gce->pszNick) + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The topic is \'%s\'"), RemoveFormatting(gce->ptszText)); + else + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The topic is \'%s\' (set by %s)"), RemoveFormatting(gce->ptszText), gce->ptszNick); + break; + case GC_EVENT_INFORMATION: + p = '!'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s"), RemoveFormatting(gce->ptszText)); + break; + case GC_EVENT_ADDSTATUS: + p = '+'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s enables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + case GC_EVENT_REMOVESTATUS: + p = '-'; + mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s disables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick); + break; + } + if (p) + mir_sntprintf(szLine, SIZEOF(szLine), TranslateT("%s %c %s\n"), szTime, p, szBuffer); + else + mir_sntprintf(szLine, SIZEOF(szLine), TranslateT("%s %s\n"), szTime, szBuffer); + + if ( szLine[0] ) { + char* p = mir_t2a( szLine ); + fputs(p, hFile); + mir_free( p ); + + if ( g_Settings.LoggingLimit > 0 ) { + DWORD dwSize; + DWORD trimlimit; + + fseek(hFile,0,SEEK_END); + dwSize = ftell(hFile); + rewind (hFile); + trimlimit = g_Settings.LoggingLimit*1024+ 1024*10; + if (dwSize > trimlimit) { + BYTE * pBuffer = 0; + BYTE * pBufferTemp = 0; + int read = 0; + + pBuffer = (BYTE *)mir_alloc(g_Settings.LoggingLimit*1024+1); + pBuffer[g_Settings.LoggingLimit*1024] = '\0'; + fseek(hFile,-g_Settings.LoggingLimit*1024,SEEK_END); + read = (int)fread(pBuffer, 1, g_Settings.LoggingLimit*1024, hFile); + fclose(hFile); + hFile = NULL; + + // trim to whole lines, should help with broken log files I hope. + pBufferTemp = strchr(pBuffer, '\n'); + if ( pBufferTemp ) { + pBufferTemp++; + read -= pBufferTemp - pBuffer; + } + else pBufferTemp = pBuffer; + + if (read > 0) { + hFile = _tfopen(szFile, _T("wt")); + if (hFile ) { + fwrite(pBufferTemp, 1, read, hFile); + fclose(hFile); hFile = NULL; + } } + + mir_free(pBuffer); + } } } + + if (hFile) + fclose(hFile); hFile = NULL; + return TRUE; + } + + return FALSE; +} + +UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText) +{ + GCMENUITEMS gcmi = {0}; + int i; + HMENU hSubMenu = 0; + + *hMenu = GetSubMenu(g_hMenu, iIndex); + TranslateMenu(*hMenu); + gcmi.pszID = si->ptszID; + gcmi.pszModule = si->pszModule; + gcmi.pszUID = pszUID; + + if (iIndex == 1) { + int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_LOG)); + + EnableMenuItem(*hMenu, ID_CLEARLOG, MF_ENABLED); + EnableMenuItem(*hMenu, ID_COPYALL, MF_ENABLED); + ModifyMenu(*hMenu, 4, MF_GRAYED|MF_BYPOSITION, 4, NULL); + if (!i) { + EnableMenuItem(*hMenu, ID_COPYALL, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(*hMenu, ID_CLEARLOG, MF_BYCOMMAND | MF_GRAYED); + if (pszWordText && pszWordText[0]) + ModifyMenu(*hMenu, 4, MF_ENABLED|MF_BYPOSITION, 4, NULL); + } + + if ( pszWordText && pszWordText[0] ) { + TCHAR szMenuText[4096]; + mir_sntprintf( szMenuText, 4096, TranslateT("Look up \'%s\':"), pszWordText ); + ModifyMenu( *hMenu, 4, MF_STRING|MF_BYPOSITION, 4, szMenuText ); + } + else ModifyMenu( *hMenu, 4, MF_STRING|MF_GRAYED|MF_BYPOSITION, 4, TranslateT( "No word to look up" )); + gcmi.Type = MENU_ON_LOG; + } + else if (iIndex == 0) + { + TCHAR szTemp[30], szTemp2[30]; + lstrcpyn(szTemp, TranslateT("&Message"), 24); + if ( pszUID ) + mir_sntprintf( szTemp2, SIZEOF(szTemp2), _T("%s %s"), szTemp, pszUID); + else + lstrcpyn(szTemp2, szTemp, 24); + + if ( lstrlen(szTemp2) > 22 ) + lstrcpyn( szTemp2+22, _T("..."), 4 ); + ModifyMenu( *hMenu, ID_MESS, MF_STRING|MF_BYCOMMAND, ID_MESS, szTemp2 ); + gcmi.Type = MENU_ON_NICKLIST; + } + + NotifyEventHooks(hBuildMenuEvent, 0, (WPARAM)&gcmi); + + if (gcmi.nItems > 0) + AppendMenu(*hMenu, MF_SEPARATOR, 0, 0); + + for (i = 0; i < gcmi.nItems; i++) { + TCHAR* ptszDescr = a2tf(gcmi.Item[i].pszDesc, si->dwFlags); + TCHAR* ptszText = TranslateTS(ptszDescr); + DWORD dwState = gcmi.Item[i].bDisabled ? MF_GRAYED : 0; + + if (gcmi.Item[i].uType == MENU_NEWPOPUP) { + hSubMenu = CreateMenu(); + AppendMenu(*hMenu, dwState | MF_POPUP, (UINT_PTR)hSubMenu, ptszText); + } + else if (gcmi.Item[i].uType == MENU_POPUPHMENU) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPITEM) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPCHECK) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_SEPARATOR) + AppendMenu(*hMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_HMENU) + AppendMenu(*hMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_ITEM) + AppendMenu(*hMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_CHECK) + AppendMenu(*hMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + + mir_free( ptszDescr ); + } + return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); +} + +void DestroyGCMenu(HMENU *hMenu, int iIndex) +{ + MENUITEMINFO mi; + mi.cbSize = sizeof(mi); + mi.fMask = MIIM_SUBMENU; + while(GetMenuItemInfo(*hMenu, iIndex, TRUE, &mi)) + { + if (mi.hSubMenu != NULL) + DestroyMenu(mi.hSubMenu); + RemoveMenu(*hMenu, iIndex, MF_BYPOSITION); + } +} + +BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem) +{ + GCHOOK* gch = (GCHOOK*)mir_calloc( sizeof( GCHOOK )); + GCDEST* gcd = (GCDEST*)mir_calloc( sizeof( GCDEST )); + + gcd->pszModule = mir_strdup( pszModule ); + + { + SESSION_INFO* si; + if (( si = SM_FindSession(pszID, pszModule)) == NULL ) + return FALSE; + + if ( !( si->dwFlags & GC_UNICODE )) { + gcd->pszID = mir_t2a( pszID ); + gch->pszUID = mir_t2a( pszUID ); + gch->pszText = mir_t2a( pszText ); + } + else { + gcd->ptszID = mir_tstrdup( pszID ); + gch->ptszUID = mir_tstrdup( pszUID ); + gch->ptszText = mir_tstrdup( pszText ); + } + } + + gcd->iType = iType; + gch->dwData = dwItem; + gch->pDest = gcd; + PostMessage(hwnd, GC_FIREHOOK, 0, (LPARAM) gch); + return TRUE; +} + +BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem) +{ + GCHOOK gch = {0}; + GCDEST gcd = {0}; + + gcd.pszModule = (char*)pszModule; + + { + SESSION_INFO* si; + if (( si = SM_FindSession(pszID, pszModule)) == NULL ) + return FALSE; + + if ( !( si->dwFlags & GC_UNICODE )) { + gcd.pszID = mir_t2a( pszID ); + gch.pszUID = mir_t2a( pszUID ); + gch.pszText = mir_t2a( pszText ); + } + else { + gcd.ptszID = mir_tstrdup( pszID ); + gch.ptszUID = mir_tstrdup( pszUID ); + gch.ptszText = mir_tstrdup( pszText ); + } + } + + gcd.iType = iType; + gch.dwData = dwItem; + gch.pDest = &gcd; + NotifyEventHooks(hSendEvent,0,(WPARAM)&gch); + + mir_free( gcd.pszID ); + mir_free( gch.ptszUID ); + mir_free( gch.ptszText ); + + return TRUE; +} + +BOOL IsEventSupported(int eventType) +{ + switch (eventType) + { + // Supported events + case GC_EVENT_JOIN: + case GC_EVENT_PART: + case GC_EVENT_QUIT: + case GC_EVENT_KICK: + case GC_EVENT_NICK: + case GC_EVENT_NOTICE: + case GC_EVENT_MESSAGE: + case GC_EVENT_TOPIC: + case GC_EVENT_INFORMATION: + case GC_EVENT_ACTION: + case GC_EVENT_ADDSTATUS: + case GC_EVENT_REMOVESTATUS: + case GC_EVENT_CHUID: + case GC_EVENT_CHANGESESSIONAME: + case GC_EVENT_ADDGROUP: + case GC_EVENT_SETITEMDATA: + case GC_EVENT_GETITEMDATA: + case GC_EVENT_SETSBTEXT: + case GC_EVENT_ACK: + case GC_EVENT_SENDMESSAGE: + case GC_EVENT_SETSTATUSEX: + case GC_EVENT_CONTROL: + case GC_EVENT_SETCONTACTSTATUS: + return TRUE; + } + + // Other events + return FALSE; +} + +void ValidateFilename (TCHAR * filename) +{ + TCHAR *p1 = filename; + TCHAR szForbidden[] = _T("\\/:*?\"<>|"); + while(*p1 != '\0') + { + if (_tcschr(szForbidden, *p1)) + *p1 = '_'; + p1 +=1; +} } + +TCHAR* a2tf( const TCHAR* str, int flags ) +{ + if ( str == NULL ) + return NULL; + + if ( flags & GC_UNICODE ) + return mir_tstrdup( str ); + else + return mir_a2u((char*)str); +} + +TCHAR* replaceStr( TCHAR** dest, const TCHAR* src ) +{ + mir_free( *dest ); + *dest = mir_tstrdup( src ); + return *dest; +} + +char* replaceStrA( char** dest, const char* src ) +{ + mir_free( *dest ); + *dest = mir_strdup( src ); + return *dest; +} -- cgit v1.2.3