summaryrefslogtreecommitdiff
path: root/plugins/SeenPlugin
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/SeenPlugin')
-rw-r--r--plugins/SeenPlugin/file.c119
-rw-r--r--plugins/SeenPlugin/history.c347
-rw-r--r--plugins/SeenPlugin/main.c189
-rw-r--r--plugins/SeenPlugin/menu.c114
-rw-r--r--plugins/SeenPlugin/missed.c301
-rw-r--r--plugins/SeenPlugin/options.c506
-rw-r--r--plugins/SeenPlugin/readme_src.txt23
-rw-r--r--plugins/SeenPlugin/resource.h97
-rw-r--r--plugins/SeenPlugin/resource.rc293
-rw-r--r--plugins/SeenPlugin/seen.h128
-rw-r--r--plugins/SeenPlugin/seen_info.txt216
-rw-r--r--plugins/SeenPlugin/seen_langpack.txt172
-rw-r--r--plugins/SeenPlugin/seenplugin.dsp225
-rw-r--r--plugins/SeenPlugin/seenplugin.dsw29
-rw-r--r--plugins/SeenPlugin/seenplugin_10.sln25
-rw-r--r--plugins/SeenPlugin/seenplugin_10.vcxproj361
-rw-r--r--plugins/SeenPlugin/seenplugin_10.vcxproj.filters60
-rw-r--r--plugins/SeenPlugin/userinfo.c95
-rw-r--r--plugins/SeenPlugin/utils.c967
19 files changed, 4267 insertions, 0 deletions
diff --git a/plugins/SeenPlugin/file.c b/plugins/SeenPlugin/file.c
new file mode 100644
index 0000000000..97cd2d9c3f
--- /dev/null
+++ b/plugins/SeenPlugin/file.c
@@ -0,0 +1,119 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/file.c $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+
+#include "seen.h"
+/*
+Prepares the log file:
+- calculates the absolute path (and store it in the db)
+- creates the directory
+
+*/
+int InitFileOutput(void)
+{
+ char szfpath[256]="",szmpath[256]="",*str;
+ DBVARIANT dbv;
+
+ GetModuleFileName(NULL,szmpath,MAX_PATH);
+ strcpy(szfpath,!DBGetContactSetting(NULL,S_MOD,"FileName",&dbv)?dbv.pszVal:DEFAULT_FILENAME);
+
+ DBFreeVariant(&dbv);
+
+ if(szfpath[0]=='\\')
+ strcpy(szfpath,szfpath+1);
+
+ str=strrchr(szmpath,'\\');
+ if(str!=NULL)
+ *++str=0;
+
+ strcat(szmpath,szfpath);
+
+ strcpy(szfpath,szmpath);
+
+ str=strrchr(szmpath,'\\');
+ if(str!=NULL)
+ *++str=0;
+/*
+//we dont need this anylonger. the directory is created in filewrite
+ if(!CreateDirectory(szmpath,NULL))
+ {
+ if(!(GetFileAttributes(szmpath) & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ MessageBox(NULL,"Directory could not be created\nPlease choose another!","Last seen plugin",MB_OK|MB_ICONERROR);
+ DBWriteContactSettingByte(NULL,S_MOD,"FileOutput",0);
+ return 0;
+ }
+ }
+*/
+ DBWriteContactSettingString(NULL,S_MOD,"PathToFile",szfpath);
+
+ return 0;
+}
+
+//borrowed from netliblog.c
+static void CreateDirectoryTree(char *szDir)
+{
+ DWORD dwAttributes;
+ char *pszLastBackslash,szTestDir[MAX_PATH];
+
+ lstrcpynA(szTestDir,szDir,sizeof(szTestDir));
+ if((dwAttributes=GetFileAttributesA(szTestDir))!=0xffffffff && dwAttributes&FILE_ATTRIBUTE_DIRECTORY) return;
+ pszLastBackslash=strrchr(szTestDir,'\\');
+ if(pszLastBackslash==NULL) return;
+ *pszLastBackslash='\0';
+ CreateDirectoryTree(szTestDir);
+ CreateDirectoryA(szTestDir,NULL);
+}
+
+/*
+Writes a line into the log.
+*/
+void FileWrite(HANDLE hcontact)
+{
+ HANDLE fhout;
+ DWORD byteswritten;
+ char szout[1024],sznl[3]="\r\n";
+ DBVARIANT dbv;
+
+ DBGetContactSetting(NULL,S_MOD,"PathToFile",&dbv);
+ strcpy(szout,ParseString(dbv.pszVal,hcontact,1));
+ fhout=CreateFile(szout,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,NULL);
+ if (fhout==INVALID_HANDLE_VALUE){
+ CreateDirectoryTree(szout);
+ fhout=CreateFile(szout,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,NULL);
+ if (fhout==INVALID_HANDLE_VALUE) return;
+ }
+ DBFreeVariant(&dbv);
+ SetFilePointer(fhout,0,0,FILE_END);
+
+ strcpy(szout,ParseString(!DBGetContactSetting(NULL,S_MOD,"FileStamp",&dbv)?dbv.pszVal:DEFAULT_FILESTAMP,hcontact,1));
+ DBFreeVariant(&dbv);
+
+ WriteFile(fhout,szout, (DWORD)_tcslen(szout),&byteswritten,NULL);
+ WriteFile(fhout,sznl, (DWORD)_tcslen(sznl),&byteswritten,NULL);
+
+ CloseHandle(fhout);
+
+
+}
diff --git a/plugins/SeenPlugin/history.c b/plugins/SeenPlugin/history.c
new file mode 100644
index 0000000000..724cfd5612
--- /dev/null
+++ b/plugins/SeenPlugin/history.c
@@ -0,0 +1,347 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-06 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/history.c $
+Revision : $Rev: 1056 $
+Last change on : $Date: 2006-10-30 06:22:07 +0300 (Пн, 30 окт 2006) $
+Last change by : $Author: y_b $
+*/
+#include "seen.h"
+
+
+extern HINSTANCE hInstance;
+
+static HANDLE hWindowList;
+
+char* BuildSetting(int historyLast) {
+ static char setting[15];
+ static char sztemp[15];
+ *setting = '\0';
+ strcat(setting, "History_");
+ strcat(setting, itoa(historyLast, sztemp, 10));
+ return setting;
+}
+
+void HistoryWrite(HANDLE hContact)
+{
+ short historyFirst, historyLast, historyMax;
+ DBVARIANT dbv;
+
+ historyMax = DBGetContactSettingWord(NULL,S_MOD,"HistoryMax",10);
+ if (historyMax < 0) historyMax=0; else if (historyMax > 99) historyMax = 99;
+ if (historyMax == 0) return;
+ historyFirst = DBGetContactSettingWord(hContact,S_MOD,"HistoryFirst",0);
+ if (historyFirst >= historyMax) historyFirst = 0;
+ historyLast = DBGetContactSettingWord(hContact,S_MOD,"HistoryLast",0);
+ if (historyLast >= historyMax) historyLast = historyMax-1;
+
+ DBWriteContactSettingString(hContact,S_MOD,BuildSetting(historyLast),
+ ParseString(!DBGetContactSetting(NULL,S_MOD,"HistoryStamp",&dbv)?dbv.pszVal:DEFAULT_HISTORYSTAMP,hContact,0));
+ DBFreeVariant(&dbv);
+
+ historyLast = (historyLast+1) % historyMax;
+ DBWriteContactSettingWord(hContact,S_MOD,"HistoryLast",historyLast);
+ if (historyLast == historyFirst) {
+ DBWriteContactSettingWord(hContact,S_MOD,"HistoryFirst",(short) ((historyFirst+1) % historyMax));
+ }
+
+}
+
+void LoadHistoryList(HANDLE hContact, HWND hwnd, int nList) {
+ short historyFirst, historyLast, historyMax;
+ short i;
+ DBVARIANT dbv;
+
+
+ SendDlgItemMessage(hwnd, nList, LB_RESETCONTENT, 0, 0);
+ historyMax = DBGetContactSettingWord(NULL,S_MOD,"HistoryMax",10);
+ if (historyMax < 0) historyMax = 0; else if (historyMax > 99) historyMax = 99;
+ if (historyMax == 0) return;
+ historyFirst = DBGetContactSettingWord(hContact,S_MOD,"HistoryFirst",0);
+ if (historyFirst >= historyMax) historyFirst = 0;
+ historyLast = DBGetContactSettingWord(hContact,S_MOD,"HistoryLast",0);
+ if (historyLast >= historyMax) historyLast = historyMax-1;
+
+ i = historyLast;
+ while (i != historyFirst) {
+ i = (i-1+historyMax) % historyMax;
+ SendDlgItemMessage(hwnd, nList, LB_ADDSTRING, 0,
+ (LPARAM)(!DBGetContactSetting(hContact,S_MOD,BuildSetting(i),&dbv)?dbv.pszVal:""));
+ DBFreeVariant(&dbv);
+ }
+
+}
+
+
+HDWP MyResizeWindow (HDWP hDwp, HWND hwndDlg, HWND hwndControl,
+ int nHorizontalOffset, int nVerticalOffset,
+ int nWidthOffset, int nHeightOffset)
+{
+ POINT pt;
+ RECT rcinit;
+
+ // get current bounding rectangle
+ GetWindowRect(hwndControl, &rcinit);
+
+ // get current top left point
+ pt.x = rcinit.left;
+ pt.y = rcinit.top;
+ ScreenToClient(hwndDlg, &pt);
+
+ // resize control
+/* MoveWindow(hwndControl,
+ pt.x + nHorizontalOffset,
+ pt.y + nVerticalOffset,
+ rcinit.right - rcinit.left + nWidthOffset,
+ rcinit.bottom - rcinit.top + nHeightOffset,
+ FALSE);
+*/
+ return DeferWindowPos(hDwp, hwndControl, NULL,
+ pt.x + nHorizontalOffset,
+ pt.y + nVerticalOffset,
+ rcinit.right - rcinit.left + nWidthOffset,
+ rcinit.bottom - rcinit.top + nHeightOffset,
+ SWP_NOZORDER);
+
+
+}
+
+HDWP MyHorizCenterWindow (HDWP hDwp, HWND hwndDlg, HWND hwndControl,
+ int nClientWidth, int nVerticalOffset,
+ int nHeightOffset)
+{
+ POINT pt;
+ RECT rcinit;
+
+ // get current bounding rectangle
+ GetWindowRect(hwndControl, &rcinit);
+
+ // get current top left point
+ pt.x = rcinit.left;
+ pt.y = rcinit.top;
+ ScreenToClient(hwndDlg, &pt);
+
+ // resize control
+/* MoveWindow(hwndControl,
+ (int) ((nClientWidth - (rcinit.right - rcinit.left))/2),
+ pt.y + nVerticalOffset,
+ rcinit.right - rcinit.left,
+ rcinit.bottom - rcinit.top + nHeightOffset,
+ TRUE);
+*/
+ return DeferWindowPos(hDwp, hwndControl, NULL,
+ (int) ((nClientWidth - (rcinit.right - rcinit.left))/2),
+ pt.y + nVerticalOffset,
+ rcinit.right - rcinit.left,
+ rcinit.bottom - rcinit.top + nHeightOffset,
+ SWP_NOZORDER);
+
+}
+void MyResizeGetOffset (HWND hwndDlg, HWND hwndControl,
+ int nWidth, int nHeight,
+ int* nDx, int* nDy)
+{
+ RECT rcinit;
+
+ // get current bounding rectangle
+ GetWindowRect(hwndControl, &rcinit);
+
+ // calculate offsets
+ *nDx = nWidth - (rcinit.right - rcinit.left);
+ *nDy = nHeight - (rcinit.bottom - rcinit.top);
+}
+
+INT_PTR CALLBACK HistoryDlgProc(HWND hwndDlg, UINT Message, WPARAM wparam, LPARAM lparam)
+{
+ HANDLE hContact;
+ char sztemp[1024]="";
+ static HIMAGELIST hIml=NULL;
+
+ switch(Message)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ hContact = (HANDLE)lparam;
+ SetWindowLongPtr(hwndDlg,GWLP_USERDATA,lparam);
+ strcpy(sztemp,(char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0));
+ strcat(sztemp, ": ");
+ strcat(sztemp, Translate("last seen history"));
+ SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)sztemp);
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_BIG, (LPARAM) LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+ SendMessage(hwndDlg, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+
+// LoadHistoryList(hContact, hwndDlg, IDC_HISTORYLIST);
+
+ if (DBGetContactSettingByte(hContact,S_MOD,"OnlineAlert",0))
+ SendDlgItemMessage(hwndDlg, IDC_STATUSCHANGE, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
+ {
+ hIml=ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,3,3);
+ ImageList_AddIcon(hIml,LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_USERDETAILS)));
+ ImageList_AddIcon(hIml,LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_DOWNARROW)));
+ ImageList_AddIcon(hIml,LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ SendDlgItemMessage(hwndDlg,IDC_DETAILS,BM_SETIMAGE,IMAGE_ICON,(WPARAM)ImageList_GetIcon(hIml,0,ILD_NORMAL));
+ SendDlgItemMessage(hwndDlg,IDC_USERMENU,BM_SETIMAGE,IMAGE_ICON,(WPARAM)ImageList_GetIcon(hIml,1,ILD_NORMAL));
+ SendDlgItemMessage(hwndDlg,IDC_SENDMSG,BM_SETIMAGE,IMAGE_ICON,(WPARAM)ImageList_GetIcon(hIml,2,ILD_NORMAL));
+ }
+
+ //set-up tooltips
+ {
+ HWND hwndDlgToolTips;
+ TOOLINFO ti;
+
+ hwndDlgToolTips = CreateWindowEx(WS_EX_TOPMOST,TOOLTIPS_CLASS,"",WS_POPUP,0,0,0,0,NULL,NULL,GetModuleHandle(NULL),NULL);
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize=sizeof(ti);
+ ti.uFlags=TTF_IDISHWND|TTF_SUBCLASS;
+ ti.uId=(UINT)GetDlgItem(hwndDlg,IDC_USERMENU);
+ ti.lpszText=Translate("User Menu");
+ SendMessage(hwndDlgToolTips,TTM_ADDTOOL,0,(LPARAM)&ti);
+ ti.uId=(UINT)GetDlgItem(hwndDlg,IDC_DETAILS);
+ ti.lpszText=Translate("View User's Details");
+ SendMessage(hwndDlgToolTips,TTM_ADDTOOL,0,(LPARAM)&ti);
+ ti.uId=(UINT)GetDlgItem(hwndDlg,IDC_SENDMSG);
+ ti.lpszText=Translate("Send Instant Message");
+ SendMessage(hwndDlgToolTips,TTM_ADDTOOL,0,(LPARAM)&ti);
+ }
+
+
+ Utils_RestoreWindowPositionNoMove(hwndDlg,NULL,S_MOD,"History_");
+ ShowWindow(hwndDlg, SW_SHOW);
+ break;
+
+ case WM_MEASUREITEM:
+ return CallService(MS_CLIST_MENUMEASUREITEM,wparam,lparam);
+ case WM_DRAWITEM:
+ return CallService(MS_CLIST_MENUDRAWITEM,wparam,lparam);
+ case WM_COMMAND:
+ hContact=(HANDLE)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+ if(CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wparam),MPCF_CONTACTMENU),(LPARAM)hContact))
+ break;
+ switch(LOWORD(wparam))
+ {
+ case IDCANCEL:
+ SendMessage(hwndDlg, WM_CLOSE, 0, 0);
+ break;
+ case IDOK:
+ if (SendDlgItemMessage(hwndDlg, IDC_STATUSCHANGE, BM_GETCHECK, 0, 0) == BST_CHECKED)
+ DBWriteContactSettingByte(hContact,S_MOD,"OnlineAlert",1);
+ else
+ DBWriteContactSettingByte(hContact,S_MOD,"OnlineAlert",0);
+ SendMessage(hwndDlg, WM_CLOSE, 0, 0);
+ break;
+ case IDC_USERMENU:
+ {
+ RECT rc;
+ HMENU hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,(WPARAM)hContact,0);
+ GetWindowRect(GetDlgItem(hwndDlg,IDC_USERMENU),&rc);
+ TrackPopupMenu(hMenu,0,rc.left,rc.bottom,0,hwndDlg,NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+ case IDC_DETAILS:
+ CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)hContact,0);
+ break;
+ case IDC_SENDMSG:
+ CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,0);
+ break;
+ case IDC_TEST:
+ debug(ParseString("Date: %d.%m.%y(%Y) \n Date desc: %W - %w - %E - %e \n Time: %H:%M:%S (%h-%p) \n user: %n - %u \n Status: %s \n IP: %i - %r",hContact,0));
+ break;
+ }
+ break;
+ case WM_SIZE:
+ {
+ int dx, dy;
+ HDWP hDwp;
+
+ hDwp = BeginDeferWindowPos(6);
+ MyResizeGetOffset(hwndDlg, GetDlgItem(hwndDlg, IDC_HISTORYLIST),
+ LOWORD(lparam)-15, HIWORD(lparam)-99, &dx, &dy);
+ hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_USERMENU),
+ dx, 0, 0, 0);
+ hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_DETAILS),
+ dx, 0, 0, 0);
+ hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_SENDMSG),
+ dx, 0, 0, 0);
+ hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_HISTORYLIST),
+ 0, 0, dx, dy);
+ hDwp = MyResizeWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDC_STATUSCHANGE),
+ 0, dy, dx, 0);
+ hDwp = MyHorizCenterWindow(hDwp, hwndDlg, GetDlgItem(hwndDlg, IDOK),
+ LOWORD(lparam), dy, 0);
+ EndDeferWindowPos(hDwp);
+ }
+ break;
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO mmi;
+ CopyMemory (&mmi, (LPMINMAXINFO) lparam, sizeof (MINMAXINFO));
+
+ /* The minimum width in points*/
+ mmi.ptMinTrackSize.x = 200;
+ /* The minimum height in points*/
+ mmi.ptMinTrackSize.y = 190;
+
+ CopyMemory ((LPMINMAXINFO) lparam, &mmi, sizeof (MINMAXINFO));
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ WindowList_Remove(hWindowList,hwndDlg);
+ break;
+ case WM_DESTROY:
+ Utils_SaveWindowPosition(hwndDlg,NULL,S_MOD,"History_");
+ ImageList_Destroy(hIml);
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void ShowHistory(HANDLE hContact, BYTE isAlert)
+{
+ HWND hHistoryDlg;
+
+ hHistoryDlg = WindowList_Find(hWindowList,hContact);
+ if (hHistoryDlg == NULL)
+ {
+ hHistoryDlg = CreateDialogParam(hInstance,MAKEINTRESOURCE(IDD_HISTORY),NULL,HistoryDlgProc,(LPARAM)hContact);
+ LoadHistoryList(hContact, hHistoryDlg, IDC_HISTORYLIST);
+ WindowList_Add(hWindowList,hHistoryDlg,hContact);
+ }
+ else
+ {
+ SetForegroundWindow(hHistoryDlg);
+ LoadHistoryList(hContact, hHistoryDlg, IDC_HISTORYLIST);
+ SetFocus(hHistoryDlg);
+ }
+
+ if (isAlert)
+ {
+ SkinPlaySound("LastSeenTrackedStatusChange");
+ }
+}
+
+
+void InitHistoryDialog(void)
+{
+ hWindowList=(HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
+}
diff --git a/plugins/SeenPlugin/main.c b/plugins/SeenPlugin/main.c
new file mode 100644
index 0000000000..6e60405058
--- /dev/null
+++ b/plugins/SeenPlugin/main.c
@@ -0,0 +1,189 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/main.c $
+Revision : $Rev: 1571 $
+Last change on : $Date: 2007-12-30 04:55:51 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+#include "seen.h"
+
+
+HINSTANCE hInstance;
+HANDLE ehdb = NULL, ehproto = NULL, ehmissed = NULL, ehuserinfo = NULL, ehmissed_proto = NULL, hOptInit = NULL, hMainInit = NULL;
+PLUGINLINK *pluginLink;
+struct MM_INTERFACE mmi;
+int hLangpack;
+char authemail[] = "fscking@spammer.oip.info";//the correct e-mail shall be constructed in DllMain
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+#ifndef PERMITNSN
+ "Last seen",
+#else
+ "Last seen",
+#endif
+ PLUGIN_MAKE_VERSION(5,0,4,7),
+ "Log when a user was last seen online and which users were online while you were away.",
+ "Heiko Schillinger, YB",
+ authemail,
+ " 2001-2002 Heiko Schillinger, 2003 modified by Bruno Rino, 2005-7 Modified by YB",
+ "http://forums.miranda-im.org/showthread.php?t=2822",
+ 0,
+#ifndef PERMITNSN
+ DEFMOD_RNDUSERONLINE,
+ { 0x0beac488,0x578d,0x458d,{0xbb, 0x93, 0x8f, 0x2f, 0x53, 0x9b, 0x2a, 0xe4}}/* 0beac488-578d-458d-bb93-8f2f539b2ae4 */
+#else
+ 0,
+ { 0x2d506d46,0xc94e,0x4ef8,{0x85, 0x37, 0xf1, 0x12, 0x33, 0xa8, 0x03, 0x81}}/* 2d506d46-c94e-4ef8-8537-f11233a80381 */
+#endif
+};
+
+#define TRANSNUMBER 2
+DBVTranslation idleTr[TRANSNUMBER]={
+ {(TranslateFunc*)any_to_IdleNotidleUnknown, _T("Any to Idle/Not Idle/Unknown"),0},
+ {(TranslateFunc*)any_to_Idle, _T("Any to /Idle or empty"),0}
+};
+
+
+
+int OptionsInit(WPARAM,LPARAM);
+int UserinfoInit(WPARAM,LPARAM);
+int InitFileOutput(void);
+void InitMenuitem(void);
+int UpdateValues(WPARAM,LPARAM);
+int ModeChange(WPARAM,LPARAM);
+//int GetInfoAck(WPARAM,LPARAM);
+void SetOffline(void);
+int ModeChange_mo(WPARAM,LPARAM);
+int CheckIfOnline(void);
+
+BOOL includeIdle;
+logthread_info **contactQueue = NULL;
+int contactQueueSize = 0;
+
+
+int MainInit(WPARAM wparam,LPARAM lparam)
+{
+ contactQueueSize = 16*sizeof(logthread_info *);
+ contactQueue = (logthread_info **)malloc(contactQueueSize);
+ memset(&contactQueue[0], 0, contactQueueSize);
+ contactQueueSize = 16;
+ includeIdle = (BOOL )DBGetContactSettingByte(NULL,S_MOD,"IdleSupport",1);
+ hOptInit = HookEvent(ME_OPT_INITIALISE, OptionsInit);
+
+ if(DBGetContactSettingByte(NULL,S_MOD,"MenuItem",1)) {
+ InitMenuitem();
+ }
+
+ if(DBGetContactSettingByte(NULL,S_MOD,"UserinfoTab",1))
+ ehuserinfo = HookEvent(ME_USERINFO_INITIALISE,UserinfoInit);
+
+ if(DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0))
+ InitFileOutput();
+
+ if(DBGetContactSettingByte(NULL,S_MOD,"MissedOnes",0))
+ ehmissed_proto=HookEvent(ME_PROTO_ACK,ModeChange_mo);
+
+// SetOffline();
+
+ ehdb=HookEvent(ME_DB_CONTACT_SETTINGCHANGED,UpdateValues);
+ ehproto=HookEvent(ME_PROTO_ACK,ModeChange);
+
+ SkinAddNewSoundEx("LastSeenTrackedStatusChange",Translate("LastSeen"),Translate("User status change"));
+ SkinAddNewSoundEx("LastSeenTrackedStatusOnline",Translate("LastSeen"),Translate("Changed to Online"));
+ SkinAddNewSoundEx("LastSeenTrackedStatusOffline",Translate("LastSeen"),Translate("User Logged Off"));
+ SkinAddNewSoundEx("LastSeenTrackedStatusFromOffline",Translate("LastSeen"),Translate("User Logged In"));
+ // known modules list
+ if (ServiceExists("DBEditorpp/RegisterSingleModule"))
+ CallService("DBEditorpp/RegisterSingleModule", (WPARAM)S_MOD, 0);
+ DBWriteContactSettingString(NULL,"Uninstall",Translate("Last seen"),S_MOD);
+
+#ifndef PERMITNSN
+ SkinAddNewSoundEx("UserOnline",Translate("Alerts"),Translate("Online"));
+#endif
+ if (ServiceExists(MS_TIPPER_ADDTRANSLATION)){
+ int i=0;
+ for (i=0;i<TRANSNUMBER;i++){
+ CallService(MS_TIPPER_ADDTRANSLATION,0,(LPARAM)&idleTr[i]);
+ }
+ }
+
+ return 0;
+}
+
+__declspec(dllexport) PLUGININFOEX * MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof( PLUGININFOEX );
+ return &pluginInfo;
+}
+
+#define MIID_LASTSEEN {0x0df23e71, 0x7950, 0x43d5, {0xb9, 0x86, 0x7a, 0xbf, 0xf5, 0xa5, 0x40, 0x18}}
+static const MUUID interfaces[] = {MIID_LASTSEEN,
+#ifndef PERMITNSN
+MIID_USERONLINE,
+#endif
+MIID_LAST};
+__declspec(dllexport) const MUUID * MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+__declspec(dllexport)int Unload(void)
+{
+ UnhookEvent(ehdb);
+ if(ehmissed) UnhookEvent(ehmissed);
+ UnhookEvent(ehproto);
+ if(ehmissed_proto) UnhookEvent(ehmissed_proto);
+ UnhookEvent(hOptInit);
+ UnhookEvent(hMainInit);
+ if (ehuserinfo) UnhookEvent(ehuserinfo);
+ UninitMenuitem();
+// free(contactQueue);
+ return 0;
+}
+
+
+
+BOOL WINAPI DllMain(HINSTANCE hinst,DWORD fdwReason,LPVOID lpvReserved)
+{
+ memcpy(pluginInfo.authorEmail,"y_b@saaplugin.no-",17);
+ hInstance=hinst;
+ return 1;
+}
+
+
+
+int __declspec(dllexport)Load(PLUGINLINK *link)
+{
+ pluginLink=link;
+ mir_getMMI(&mmi);
+ mir_getLP(&pluginInfo);
+ // this isn't required for most events
+ // but the ME_USERINFO_INITIALISE
+ // I decided to hook all events after
+ // everything is loaded because it seems
+ // to be safer in my opinion
+ hMainInit = HookEvent(ME_SYSTEM_MODULESLOADED,MainInit);
+ return 0;
+}
+
+
+
+
+
diff --git a/plugins/SeenPlugin/menu.c b/plugins/SeenPlugin/menu.c
new file mode 100644
index 0000000000..e6b972fec4
--- /dev/null
+++ b/plugins/SeenPlugin/menu.c
@@ -0,0 +1,114 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/menu.c $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+#include "seen.h"
+
+HANDLE hmenuitem=NULL, hLSUserDet = NULL, hBuildMenu = NULL;
+
+void ShowHistory(HANDLE hContact, BYTE isAlert);
+void InitHistoryDialog(void);
+
+/*
+Handles the messages sent by clicking the contact's menu item
+*/
+INT_PTR MenuitemClicked(WPARAM wparam,LPARAM lparam)
+{
+ ShowHistory((HANDLE)wparam, 0);
+ return 0;
+}
+
+int BuildContactMenu(WPARAM wparam,LPARAM lparam)
+{
+ CLISTMENUITEM cmi;
+ DBVARIANT dbv;
+ int id=-1,isetting;
+ HANDLE hContact;
+ char *szProto;
+
+ hContact = (HANDLE)wparam;
+ szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+
+ ZeroMemory(&cmi,sizeof(cmi));
+ cmi.cbSize=sizeof(cmi);
+ if(!IsWatchedProtocol(szProto) || !DBGetContactSettingByte(NULL,S_MOD,"MenuItem",1))
+ {
+ cmi.flags=CMIM_FLAGS|CMIF_HIDDEN;
+ }
+ else
+ {
+ cmi.flags=CMIM_NAME|CMIM_FLAGS|CMIM_ICON;
+ cmi.hIcon=NULL;
+ cmi.pszName=ParseString(!DBGetContactSetting(NULL,S_MOD,"MenuStamp",&dbv)?dbv.pszVal:DEFAULT_MENUSTAMP,(HANDLE)wparam,0);
+
+ if(!strcmp(cmi.pszName,Translate("<unknown>")))
+ {
+ if (IsWatchedProtocol(szProto))
+ cmi.flags|=CMIF_GRAYED;
+ else
+ cmi.flags|=CMIF_HIDDEN;
+ }
+ else if(DBGetContactSettingByte(NULL,S_MOD,"ShowIcon",1))
+ {
+ isetting=DBGetContactSettingWord((HANDLE)hContact,S_MOD,"StatusTriger",-1);
+ cmi.hIcon=LoadSkinnedProtoIcon(szProto,isetting|0x8000);
+
+ }
+ }
+
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hmenuitem,(LPARAM)&cmi);
+ DBFreeVariant(&dbv);
+
+ return 0;
+}
+
+
+
+void InitMenuitem()
+{
+ CLISTMENUITEM cmi;
+
+ hLSUserDet = CreateServiceFunction("LastSeenUserDetails", MenuitemClicked);
+
+ ZeroMemory(&cmi,sizeof(cmi));
+ cmi.cbSize=sizeof(cmi);
+ cmi.flags=0;
+ cmi.hIcon=NULL;
+ cmi.hotKey=0;
+ cmi.position=-0x7FFFFFFF;
+ cmi.pszContactOwner=NULL;
+ cmi.pszName="<none>";
+ cmi.pszService="LastSeenUserDetails";
+
+ hmenuitem=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&cmi);
+
+ hBuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,BuildContactMenu);
+
+ InitHistoryDialog();
+}
+
+void UninitMenuitem()
+{
+ DestroyServiceFunction(hLSUserDet);
+ UnhookEvent(hBuildMenu);
+} \ No newline at end of file
diff --git a/plugins/SeenPlugin/missed.c b/plugins/SeenPlugin/missed.c
new file mode 100644
index 0000000000..f6ed40035c
--- /dev/null
+++ b/plugins/SeenPlugin/missed.c
@@ -0,0 +1,301 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/missed.c $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+#include "seen.h"
+
+#include <m_ignore.h>
+
+
+
+MISSEDCONTACTS mcs;
+extern HANDLE ehmissed;
+extern HINSTANCE hInstance;
+
+
+
+WPARAM IsUserMissed(WPARAM contact)
+{
+ int loop=0;
+
+ for(;loop<mcs.count;loop++)
+ {
+ if(mcs.wpcontact[loop]==contact)
+ return MAKEWPARAM(1,loop);
+ }
+
+ return 0;
+}
+
+
+
+int RemoveUser(int pos)
+{
+ int loop;
+
+ for(loop=pos;loop<mcs.count-1;loop++)
+ mcs.wpcontact[loop]=mcs.wpcontact[loop+1];
+
+ mcs.count--;
+
+ return 0;
+}
+
+
+
+int ResetMissed(void)
+{
+ HANDLE hcontact=NULL;
+
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hcontact!=NULL)
+ {
+ DBWriteContactSettingByte(hcontact,S_MOD,"Missed",0);
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hcontact,0);
+ }
+
+ ZeroMemory(&mcs,sizeof(mcs));
+
+ return 0;
+}
+
+
+int CheckIfOnline(void)
+{
+ HANDLE hcontact;
+// char *szProto;
+// WORD status;
+
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hcontact!=NULL)
+ {
+/* szProto=(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hcontact,0);
+ status=(szProto==NULL)?ID_STATUS_OFFLINE:DBGetContactSettingWord(hcontact,szProto,"Status",ID_STATUS_OFFLINE);
+ if(status!=ID_STATUS_OFFLINE)
+*/
+ if(CallService(MS_CLIST_GETCONTACTICON,(WPARAM)hcontact,0)!=ICON_OFFLINE)
+ DBWriteContactSettingByte(hcontact,S_MOD,"Missed",2);
+
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hcontact,0);
+ }
+
+ return 0;
+}
+
+
+
+INT_PTR CALLBACK MissedDlgProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
+{
+ POINT pt;
+ RECT rcinit,rcresized,rcb,rcd;
+ HWND htemp;
+
+ switch(msg){
+
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hdlg);
+
+ htemp=GetDlgItem(hdlg,IDC_CONTACTS);
+ GetWindowRect(htemp,&rcinit);
+ SetWindowPos(htemp,NULL,0,0,rcinit.right-rcinit.left,mcs.count*(rcinit.bottom-rcinit.top)/2,SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
+ GetWindowRect(htemp,&rcresized);
+
+ htemp=GetDlgItem(hdlg,IDOK);
+ GetWindowRect(htemp,&rcb);
+ pt.x=rcb.left;
+ pt.y=rcb.top;
+
+ ScreenToClient(hdlg,&pt);
+ MoveWindow(htemp,pt.x,pt.y+(rcresized.bottom-rcinit.bottom),(rcb.right-rcb.left),(rcb.bottom-rcb.top),FALSE);
+ GetWindowRect(hdlg,&rcd);
+ SetWindowPos(hdlg,NULL,0,0,rcd.right-rcd.left,rcd.bottom-rcd.top+(rcresized.bottom-rcinit.bottom),SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
+
+ SetDlgItemText(hdlg,IDC_CONTACTS,(LPCSTR)lparam);
+ ShowWindow(hdlg,SW_SHOWNOACTIVATE);
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hdlg,0);
+ break;
+
+ case WM_COMMAND:
+ if(LOWORD(wparam)==IDOK)
+ SendMessage(hdlg,WM_CLOSE,0,0);
+ break;
+ }
+
+ return 0;
+}
+
+
+
+
+int ShowMissed(void)
+{
+ int loop=0;
+ char sztemp[1024]="",szcount[7];
+
+ if(!mcs.count) return 0;
+
+ for(;loop<mcs.count;loop++)
+ {
+ strcat(sztemp,(const char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,mcs.wpcontact[loop],0));
+ if(DBGetContactSettingByte(NULL,S_MOD,"MissedOnes_Count",0))
+ {
+ wsprintf(szcount," [%i]",mcs.times[loop]);
+ strcat(sztemp,szcount);
+ }
+
+ strcat(sztemp,"\n");
+ }
+
+ CreateDialogParam(hInstance,MAKEINTRESOURCE(IDD_MISSED),NULL,MissedDlgProc,(LPARAM)&sztemp[0]);
+
+ return 0;
+}
+
+/*
+
+int LogStatus(WPARAM wparam,LPARAM lparam)
+{
+ DBCONTACTWRITESETTING *cws;
+ WPARAM wpvar;
+
+ cws=(DBCONTACTWRITESETTING *)lparam;
+
+ if(strcmp(cws->szSetting,"Status") || (strcmp(cws->szModule,"ICQ") && strcmp(cws->szModule,"MSN")) || (HANDLE)wparam==NULL) return 0;
+
+ if(CallService(MS_IGNORE_ISIGNORED,wparam,IGNOREEVENT_USERONLINE))
+ return 0;
+
+ if(cws->value.wVal==ID_STATUS_OFFLINE)
+ {
+ if(DBGetContactSettingByte((HANDLE)wparam,S_MOD,"Missed",0)==1)
+ {
+ mcs.times[mcs.count]++;
+ mcs.wpcontact[mcs.count++]=wparam;
+ DBWriteContactSettingByte((HANDLE)wparam,S_MOD,"Missed",0);
+ }
+
+ else if(DBGetContactSettingByte((HANDLE)wparam,S_MOD,"Missed",0)==3)
+ mcs.times[HIWORD(IsUserMissed(wparam))]++;
+
+ return 0;
+ }
+
+ wpvar=IsUserMissed(wparam);
+ if(LOWORD(wpvar))
+ DBWriteContactSettingByte((HANDLE)wparam,S_MOD,"Missed",3);
+
+ else
+ DBWriteContactSettingByte((HANDLE)wparam,S_MOD,"Missed",1);
+
+ return 0;
+}
+
+*/
+
+int Test(WPARAM wparam,LPARAM lparam)
+{
+ if(lparam<ICON_OFFLINE || lparam>ICON_INVIS)
+ return 0;
+
+ if(CallService(MS_IGNORE_ISIGNORED,wparam,IGNOREEVENT_USERONLINE))
+ return 0;
+
+ if(DBGetContactSettingByte((HANDLE)wparam,S_MOD,"Missed",0)==2)
+ return 0;
+
+ switch(lparam){
+
+ case ICON_OFFLINE:
+ if(DBGetContactSettingByte((HANDLE)wparam,S_MOD,"Missed",0)==1)
+ {
+ WORD missed=IsUserMissed(wparam);
+
+ if(!LOWORD(missed))
+ {
+ mcs.times[mcs.count]=1;
+ mcs.wpcontact[mcs.count++]=wparam;
+ }
+ else
+ mcs.times[HIWORD(missed)]++;
+
+ DBWriteContactSettingByte((HANDLE)wparam,S_MOD,"Missed",0);
+ }
+ break;
+
+ case ICON_ONLINE:
+ case ICON_AWAY:
+ case ICON_NA:
+ case ICON_OCC:
+ case ICON_DND:
+ case ICON_FREE:
+ case ICON_INVIS:
+ DBWriteContactSettingByte((HANDLE)wparam,S_MOD,"Missed",1);
+ break;
+ }
+
+ return 0;
+}
+
+
+
+int ModeChange_mo(WPARAM wparam,LPARAM lparam)
+{
+ ACKDATA *ack;
+ int isetting=0;
+
+ ack=(ACKDATA *)lparam;
+
+ if(ack->type!=ACKTYPE_STATUS || ack->result!=ACKRESULT_SUCCESS || ack->hContact!=NULL) return 0;
+
+ isetting=CallProtoService(ack->szModule,PS_GETSTATUS,0,0);
+
+ switch(isetting){
+
+ case ID_STATUS_AWAY:
+ case ID_STATUS_DND:
+ case ID_STATUS_NA:
+ if(ehmissed==NULL)
+ {
+ ZeroMemory(&mcs,sizeof(mcs));
+ CheckIfOnline();
+ //ehmissed=HookEvent(ME_DB_CONTACT_SETTINGCHANGED,LogStatus);
+ ehmissed=HookEvent(ME_CLIST_CONTACTICONCHANGED,Test);
+ }
+ break;
+
+ default:
+ if(ehmissed!=NULL)
+ {
+ UnhookEvent(ehmissed);
+ ehmissed=NULL;
+ ShowMissed();
+ ResetMissed();
+ }
+ break;
+ }
+
+ return 0;
+}
diff --git a/plugins/SeenPlugin/options.c b/plugins/SeenPlugin/options.c
new file mode 100644
index 0000000000..cf5ab019ba
--- /dev/null
+++ b/plugins/SeenPlugin/options.c
@@ -0,0 +1,506 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/options.c $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+#include "seen.h"
+
+
+
+extern HINSTANCE hInstance;
+extern HANDLE ehuserinfo,hmenuitem,ehmissed_proto;
+void BuildInfo(char *,char *,char *);
+int BuildContactMenu(WPARAM,LPARAM);
+int UserinfoInit(WPARAM,LPARAM);
+int InitFileOutput(void);
+void ShutdownFileOutput(void);
+void InitMenuitem(void);
+int ModeChange_mo(WPARAM,LPARAM);
+int CheckIfOnline(void);
+int ResetMissed(void);
+static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
+
+INT_PTR CALLBACK OptsPopUpsDlgProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
+{
+ DBVARIANT dbv;
+ int i;
+ char szstamp[256];
+ BOOL hasPopups;
+ switch(msg)
+ {
+ case WM_INITDIALOG:{
+ if (hasPopups = (ServiceExists(MS_POPUP_QUERY) != 0))
+ hasPopups = CallService(MS_POPUP_QUERY,PUQS_GETSTATUS,0);
+ TranslateDialogDefault(hdlg);
+ ShowWindow(GetDlgItem(hdlg,IDC_MISSPOPUP),hasPopups?SW_HIDE:SW_SHOW);
+ ShowWindow(GetDlgItem(hdlg,IDC_POPUPS),hasPopups?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hdlg,IDC_POPUPSTAMP),hasPopups?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hdlg,IDC_LABTEXT),hasPopups?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hdlg,IDC_LABTTITLE),hasPopups?SW_SHOW:SW_HIDE);
+ ShowWindow(GetDlgItem(hdlg,IDC_POPUPSTAMPTEXT),hasPopups?SW_SHOW:SW_HIDE);
+ CheckDlgButton(hdlg,IDC_POPUPS,DBGetContactSettingByte(NULL,S_MOD,"UsePopups",0)&hasPopups);
+ EnableWindow(GetDlgItem(hdlg,IDC_POPUPS),hasPopups);
+ hasPopups = IsDlgButtonChecked(hdlg,IDC_POPUPS);
+ EnableWindow(GetDlgItem(hdlg,IDC_POPUPSTAMP),hasPopups);
+ EnableWindow(GetDlgItem(hdlg,IDC_POPUPSTAMPTEXT),hasPopups);
+ for (i=ID_STATUS_OFFLINE;i<=ID_STATUS_OUTTOLUNCH;i++){
+ DWORD sett;
+ COLORREF back, text;
+ sprintf(szstamp, "Col_%d",i-ID_STATUS_OFFLINE);
+ sett = DBGetContactSettingDword(NULL,S_MOD,szstamp,StatusColors15bits[i-ID_STATUS_OFFLINE]);
+ GetColorsFromDWord(&back, &text, sett);
+ SendDlgItemMessage(hdlg,i,CPM_SETCOLOUR,0,back);
+ SendDlgItemMessage(hdlg,i+20,CPM_SETCOLOUR,0,text);
+ EnableWindow(GetDlgItem(hdlg,i),hasPopups);
+ EnableWindow(GetDlgItem(hdlg,i+20),hasPopups);
+ }
+
+ SetDlgItemText(hdlg,IDC_POPUPSTAMP,!DBGetContactSetting(NULL,S_MOD,"PopupStamp",&dbv)?dbv.pszVal:DEFAULT_POPUPSTAMP);
+ DBFreeVariant(&dbv);
+ SetDlgItemText(hdlg,IDC_POPUPSTAMPTEXT,!DBGetContactSetting(NULL,S_MOD,"PopupStampText",&dbv)?dbv.pszVal:DEFAULT_POPUPSTAMPTEXT);
+ DBFreeVariant(&dbv);
+#ifndef PERMITNSN
+ i = DBGetContactSettingByte(NULL,S_MOD,"SuppCListOnline",3);
+ CheckDlgButton(hdlg,IDC_DISWATCHED,i&1);
+ CheckDlgButton(hdlg,IDC_DISNONWATCHED,i&2);
+#endif
+ }
+ break; //case WM_INITDIALOG
+ case WM_COMMAND:
+ if((HIWORD(wparam)==BN_CLICKED || HIWORD(wparam)==EN_CHANGE) && GetFocus()==(HWND)lparam)
+ SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+ else if (HIWORD(wparam)==CPN_COLOURCHANGED){
+ WORD idText, idBack;
+ POPUPDATAEX ppd = {0};
+ DBVARIANT dbv = {0};
+ DWORD temp;
+ if (LOWORD(wparam)>ID_STATUS_OUTTOLUNCH){ // we have clicked a text color
+ idText = wparam; idBack = wparam-20;
+ } else {idText = wparam+20; idBack = wparam;}
+ ppd.colorBack = SendDlgItemMessage(hdlg,idBack,CPM_GETCOLOUR,0,0);
+ ppd.colorText = SendDlgItemMessage(hdlg,idText,CPM_GETCOLOUR,0,0);
+ temp = GetDWordFromColors(ppd.colorBack,ppd.colorText);
+ GetColorsFromDWord(&ppd.colorBack,&ppd.colorText,temp);
+ SendDlgItemMessage(hdlg,idBack,CPM_SETCOLOUR,0,ppd.colorBack);
+ SendDlgItemMessage(hdlg,idText,CPM_SETCOLOUR,0,ppd.colorText);
+ ppd.lchIcon = LoadSkinnedProtoIcon(NULL, idBack);
+ GetDlgItemText(hdlg,IDC_POPUPSTAMP,szstamp,255);
+ strncpy(ppd.lpzContactName,ParseString(szstamp,NULL,0),MAX_CONTACTNAME);
+ GetDlgItemText(hdlg,IDC_POPUPSTAMPTEXT,szstamp,255);
+ strncpy(ppd.lpzText,ParseString(szstamp,NULL,0),MAX_SECONDLINE);
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+
+ SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+ }
+ if(HIWORD(wparam)==BN_CLICKED)
+ {
+ switch(LOWORD(wparam)){
+ case IDC_POPUPS:
+ hasPopups = IsDlgButtonChecked(hdlg,IDC_POPUPS);
+ EnableWindow(GetDlgItem(hdlg,IDC_POPUPSTAMP),hasPopups);
+ EnableWindow(GetDlgItem(hdlg,IDC_POPUPSTAMPTEXT),hasPopups);
+ for (i=ID_STATUS_OFFLINE;i<=ID_STATUS_OUTTOLUNCH;i++){
+ EnableWindow(GetDlgItem(hdlg,i),hasPopups);
+ EnableWindow(GetDlgItem(hdlg,i+20),hasPopups);
+ }
+ break;
+ case IDC_DEFAULTCOL:
+ for (i=ID_STATUS_OFFLINE;i<=ID_STATUS_OUTTOLUNCH;i++){
+ DWORD sett;
+ COLORREF back, text;
+ sprintf(szstamp, "Col_%d",i-ID_STATUS_OFFLINE);
+ sett = StatusColors15bits[i-ID_STATUS_OFFLINE];
+ GetColorsFromDWord(&back, &text, sett);
+ SendDlgItemMessage(hdlg,i,CPM_SETCOLOUR,0,back);
+ SendDlgItemMessage(hdlg,i+20,CPM_SETCOLOUR,0,text);
+ }
+ break;
+ }
+ }
+ break; //case WM_COMMAND
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lparam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lparam)->code)
+ {
+ BYTE checkValue;
+
+ case PSN_APPLY:
+ GetDlgItemText(hdlg,IDC_POPUPSTAMP,szstamp,256);
+ DBWriteContactSettingString(NULL,S_MOD,"PopupStamp",szstamp);
+ GetDlgItemText(hdlg,IDC_POPUPSTAMPTEXT,szstamp,256);
+ DBWriteContactSettingString(NULL,S_MOD,"PopupStampText",szstamp);
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_POPUPS);
+ if (DBGetContactSettingByte(NULL,S_MOD,"UsePopups",0) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"UsePopups",checkValue);
+ }
+ for (i=ID_STATUS_OFFLINE;i<=ID_STATUS_OUTTOLUNCH;i++){
+ DWORD sett;
+ COLORREF back=0, text=0;
+ sprintf(szstamp, "Col_%d",i-ID_STATUS_OFFLINE);
+ back = SendDlgItemMessage(hdlg,i,CPM_GETCOLOUR,0,0);
+ text = SendDlgItemMessage(hdlg,i+20,CPM_GETCOLOUR,0,0);
+ sett=GetDWordFromColors(back,text);
+ if (sett!=StatusColors15bits[i-ID_STATUS_OFFLINE])
+ DBWriteContactSettingDword(NULL,S_MOD,szstamp,sett);
+ else DBDeleteContactSetting(NULL,S_MOD,szstamp);
+ }
+#ifndef PERMITNSN
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_DISNONWATCHED)<<1;
+ checkValue |= (BYTE)IsDlgButtonChecked(hdlg,IDC_DISWATCHED);
+ if (3 == checkValue) DBDeleteContactSetting(NULL,S_MOD,"SuppCListOnline");
+ else DBWriteContactSettingByte(NULL,S_MOD,"SuppCListOnline",checkValue);
+#endif
+ break; //case PSN_APPLY
+ }
+ break; //case 0
+ }
+ break;//case WM_NOTIFY
+
+ }
+
+ return 0;
+}
+
+INT_PTR CALLBACK OptsSettingsDlgProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
+{
+ DBVARIANT dbv;
+ char szstamp[256];
+ BYTE bchecked=0;
+ WPARAM wpsend=0;
+
+ switch(msg)
+ {
+ case WM_INITDIALOG:{
+ TranslateDialogDefault(hdlg);
+
+ CheckDlgButton(hdlg,IDC_MENUITEM,DBGetContactSettingByte(NULL,S_MOD,"MenuItem",1));
+ CheckDlgButton(hdlg,IDC_USERINFO,DBGetContactSettingByte(NULL,S_MOD,"UserinfoTab",1));
+ CheckDlgButton(hdlg,IDC_FILE,DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0));
+ CheckDlgButton(hdlg,IDC_HISTORY,DBGetContactSettingByte(NULL,S_MOD,"KeepHistory",0));
+ CheckDlgButton(hdlg,IDC_IGNOREOFFLINE,DBGetContactSettingByte(NULL,S_MOD,"IgnoreOffline",1));
+ CheckDlgButton(hdlg,IDC_MISSEDONES,DBGetContactSettingByte(NULL,S_MOD,"MissedOnes",0));
+ CheckDlgButton(hdlg,IDC_SHOWICON,DBGetContactSettingByte(NULL,S_MOD,"ShowIcon",1));
+ CheckDlgButton(hdlg,IDC_COUNT,DBGetContactSettingByte(NULL,S_MOD,"MissedOnes_Count",0));
+ CheckDlgButton(hdlg,IDC_IDLESUPPORT,DBGetContactSettingByte(NULL,S_MOD,"IdleSupport",1));
+
+ EnableWindow(GetDlgItem(hdlg,IDC_MENUSTAMP),IsDlgButtonChecked(hdlg,IDC_MENUITEM));
+ EnableWindow(GetDlgItem(hdlg,IDC_SHOWICON),IsDlgButtonChecked(hdlg,IDC_MENUITEM));
+ EnableWindow(GetDlgItem(hdlg,IDC_USERSTAMP),IsDlgButtonChecked(hdlg,IDC_USERINFO));
+ EnableWindow(GetDlgItem(hdlg,IDC_FILESTAMP),IsDlgButtonChecked(hdlg,IDC_FILE));
+ EnableWindow(GetDlgItem(hdlg,IDC_FILENAME),IsDlgButtonChecked(hdlg,IDC_FILE));
+ EnableWindow(GetDlgItem(hdlg,IDC_HISTORYSIZE),IsDlgButtonChecked(hdlg,IDC_HISTORY));
+ EnableWindow(GetDlgItem(hdlg,IDC_HISTORYSTAMP),IsDlgButtonChecked(hdlg,IDC_HISTORY));
+ EnableWindow(GetDlgItem(hdlg,IDC_COUNT),IsDlgButtonChecked(hdlg,IDC_MISSEDONES));
+
+ SetDlgItemText(hdlg,IDC_MENUSTAMP,!DBGetContactSetting(NULL,S_MOD,"MenuStamp",&dbv)?dbv.pszVal:DEFAULT_MENUSTAMP);
+ DBFreeVariant(&dbv);
+ SetDlgItemText(hdlg,IDC_USERSTAMP,!DBGetContactSetting(NULL,S_MOD,"UserStamp",&dbv)?dbv.pszVal:DEFAULT_USERSTAMP);
+ DBFreeVariant(&dbv);
+ SetDlgItemText(hdlg,IDC_FILESTAMP,!DBGetContactSetting(NULL,S_MOD,"FileStamp",&dbv)?dbv.pszVal:DEFAULT_FILESTAMP);
+ DBFreeVariant(&dbv);
+ SetDlgItemText(hdlg,IDC_FILENAME,!DBGetContactSetting(NULL,S_MOD,"FileName",&dbv)?dbv.pszVal:DEFAULT_FILENAME);
+ DBFreeVariant(&dbv);
+ SetDlgItemInt(hdlg,IDC_HISTORYSIZE,DBGetContactSettingWord(NULL,S_MOD,"HistoryMax",10-1)-1,FALSE);
+ SetDlgItemText(hdlg,IDC_HISTORYSTAMP,!DBGetContactSetting(NULL,S_MOD,"HistoryStamp",&dbv)?dbv.pszVal:DEFAULT_HISTORYSTAMP);
+ DBFreeVariant(&dbv);
+
+ // load protocol list
+ SetWindowLong(GetDlgItem(hdlg,IDC_PROTOCOLLIST),GWL_STYLE,GetWindowLong(GetDlgItem(hdlg,IDC_PROTOCOLLIST),GWL_STYLE)|TVS_CHECKBOXES);
+ {
+ TVINSERTSTRUCT tvis;
+ int numberOfProtocols,i;
+ PROTOCOLDESCRIPTOR** protos;
+ char *protoName;
+ char *protoLabel;
+
+ tvis.hParent=NULL;
+ tvis.hInsertAfter=TVI_LAST;
+ tvis.item.mask=TVIF_TEXT | TVIF_HANDLE | TVIF_STATE | TVIF_PARAM;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+
+ CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&numberOfProtocols,(LPARAM)&protos);
+ for (i=0; i<numberOfProtocols; i++) {
+ if(protos[i]->type!=PROTOTYPE_PROTOCOL || CallProtoService(protos[i]->szName,PS_GETCAPS,PFLAGNUM_2,0)==0) continue;
+ protoName = (char *)malloc(strlen(protos[i]->szName)+1);
+ strcpy(protoName,protos[i]->szName);
+//debug(protoName);
+ protoLabel = (char *)malloc(MAXMODULELABELLENGTH+1);
+ CallProtoService(protoName,PS_GETNAME,MAXMODULELABELLENGTH,(LPARAM)protoLabel);
+//debug(protoLabel);
+ tvis.item.pszText = protoLabel;
+ tvis.item.lParam = (LPARAM)protoName;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK(IsWatchedProtocol(protoName)+1);
+ TreeView_InsertItem(GetDlgItem(hdlg,IDC_PROTOCOLLIST),&tvis);
+ free(protoLabel);
+
+ }
+ }
+ }
+ break; //case WM_INITDIALOG
+
+ case WM_COMMAND:
+ if((HIWORD(wparam)==BN_CLICKED || HIWORD(wparam)==EN_CHANGE) && GetFocus()==(HWND)lparam)
+ if (LOWORD(wparam)!=IDC_VARIABLES)SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+
+ if(HIWORD(wparam)==BN_CLICKED)
+ {
+ switch(LOWORD(wparam)){
+ case IDC_MENUITEM:
+ EnableWindow(GetDlgItem(hdlg,IDC_MENUSTAMP),IsDlgButtonChecked(hdlg,IDC_MENUITEM));
+ EnableWindow(GetDlgItem(hdlg,IDC_SHOWICON),IsDlgButtonChecked(hdlg,IDC_MENUITEM));
+ break;
+ case IDC_USERINFO:
+ EnableWindow(GetDlgItem(hdlg,IDC_USERSTAMP),IsDlgButtonChecked(hdlg,IDC_USERINFO));
+ break;
+ case IDC_FILE:
+ EnableWindow(GetDlgItem(hdlg,IDC_FILESTAMP),IsDlgButtonChecked(hdlg,IDC_FILE));
+ EnableWindow(GetDlgItem(hdlg,IDC_FILENAME),IsDlgButtonChecked(hdlg,IDC_FILE));
+ break;
+ case IDC_HISTORY:
+ EnableWindow(GetDlgItem(hdlg,IDC_HISTORYSTAMP),IsDlgButtonChecked(hdlg,IDC_HISTORY));
+ EnableWindow(GetDlgItem(hdlg,IDC_HISTORYSIZE),IsDlgButtonChecked(hdlg,IDC_HISTORY));
+ break;
+ case IDC_MISSEDONES:
+ EnableWindow(GetDlgItem(hdlg,IDC_COUNT),IsDlgButtonChecked(hdlg,IDC_MISSEDONES));
+ break;
+ }
+ }
+
+ if (LOWORD(wparam)==IDC_VARIABLES)
+ {
+ char szout[2048]="";
+ wsprintf(szout,VARIABLE_LIST);
+ MessageBox(NULL,szout,Translate("Last Seen Variables"),MB_OK|MB_TOPMOST);
+ }
+
+ break; //case WM_COMMAND
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lparam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lparam)->code)
+ {
+ BYTE checkValue;
+
+ case PSN_APPLY:
+
+ GetDlgItemText(hdlg,IDC_MENUSTAMP,szstamp,256);
+ DBWriteContactSettingString(NULL,S_MOD,"MenuStamp",szstamp);
+
+ GetDlgItemText(hdlg,IDC_USERSTAMP,szstamp,256);
+ DBWriteContactSettingString(NULL,S_MOD,"UserStamp",szstamp);
+
+ GetDlgItemText(hdlg,IDC_FILESTAMP,szstamp,256);
+ DBWriteContactSettingString(NULL,S_MOD,"FileStamp",szstamp);
+
+ GetDlgItemText(hdlg,IDC_FILENAME,szstamp,256);
+ DBWriteContactSettingString(NULL,S_MOD,"FileName",szstamp);
+
+ GetDlgItemText(hdlg,IDC_HISTORYSTAMP,szstamp,256);
+ DBWriteContactSettingString(NULL,S_MOD,"HistoryStamp",szstamp);
+
+ DBWriteContactSettingWord(NULL,S_MOD,"HistoryMax",(WORD)(GetDlgItemInt(hdlg,IDC_HISTORYSIZE,NULL,FALSE)+1));
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_MENUITEM);
+ if (DBGetContactSettingByte(NULL,S_MOD,"MenuItem",1) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"MenuItem",checkValue);
+ if(hmenuitem==NULL && checkValue) {
+ InitMenuitem();
+ }
+ }
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_USERINFO);
+ if (DBGetContactSettingByte(NULL,S_MOD,"UserinfoTab",1) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"UserinfoTab",checkValue);
+ if(checkValue) {
+ ehuserinfo=HookEvent(ME_USERINFO_INITIALISE,UserinfoInit);
+ } else {
+ UnhookEvent(ehuserinfo);
+ }
+ }
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_FILE);
+ if (DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"FileOutput",checkValue);
+ if(checkValue) {
+ InitFileOutput();
+ }
+ }
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_HISTORY);
+ if (DBGetContactSettingByte(NULL,S_MOD,"KeepHistory",0) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"KeepHistory",checkValue);
+ }
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_IGNOREOFFLINE);
+ if (DBGetContactSettingByte(NULL,S_MOD,"IgnoreOffline",1) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"IgnoreOffline",checkValue);
+ }
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_MISSEDONES);
+ if (DBGetContactSettingByte(NULL,S_MOD,"MissedOnes",0) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"MissedOnes",checkValue);
+ if(checkValue) {
+ ehmissed_proto=HookEvent(ME_PROTO_ACK,ModeChange_mo);
+ } else {
+ UnhookEvent(ehmissed_proto);
+ }
+ }
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_SHOWICON);
+ if (DBGetContactSettingByte(NULL,S_MOD,"ShowIcon",1) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"ShowIcon",checkValue);
+ }
+
+ checkValue = (BYTE)IsDlgButtonChecked(hdlg,IDC_COUNT);
+ if (DBGetContactSettingByte(NULL,S_MOD,"MissedOnes_Count",0) != checkValue) {
+ DBWriteContactSettingByte(NULL,S_MOD,"MissedOnes_Count",checkValue);
+ }
+
+ includeIdle = (BYTE)IsDlgButtonChecked(hdlg,IDC_IDLESUPPORT);
+ if (DBGetContactSettingByte(NULL,S_MOD,"IdleSupport",1) != includeIdle) {
+ DBWriteContactSettingByte(NULL,S_MOD,"IdleSupport",(BYTE)includeIdle);
+ }
+
+ // save protocol list
+ {
+ HWND hwndTreeView = GetDlgItem(hdlg,IDC_PROTOCOLLIST);
+ HTREEITEM hItem;
+ TVITEM tvItem;
+ char *watchedProtocols;
+ char *protocol;
+ int size=1;
+
+ watchedProtocols = (char *)malloc(sizeof(char));
+ *watchedProtocols = '\0';
+ hItem = TreeView_GetRoot(hwndTreeView);
+ tvItem.mask = TVIF_HANDLE | TVIF_STATE | TVIF_PARAM;
+ tvItem.stateMask = TVIS_STATEIMAGEMASK;
+
+ while (hItem != NULL) {
+ tvItem.hItem = hItem;
+ TreeView_GetItem(hwndTreeView, &tvItem);
+ protocol = (char*)tvItem.lParam;
+ if ((BOOL)(tvItem.state >> 12) -1) {
+ size = (size + (int)_tcslen(protocol)+2) * sizeof(char);
+ watchedProtocols = (char *)realloc(watchedProtocols, size);
+ strcat(watchedProtocols, protocol);
+ strcat(watchedProtocols, " ");
+ }
+ hItem = TreeView_GetNextSibling(hwndTreeView, hItem);
+ }
+ DBWriteContactSettingString(NULL,S_MOD,"WatchedProtocols",watchedProtocols);
+ free(watchedProtocols);
+ }
+
+ break; //case PSN_APPLY
+ }
+ break; //case 0
+
+ case IDC_PROTOCOLLIST:
+ switch (((LPNMHDR)lparam)->code)
+ {
+ case NM_CLICK:
+ {
+ HWND hTree=((LPNMHDR)lparam)->hwndFrom;
+ TVHITTESTINFO hti;
+ HTREEITEM hItem;
+
+ hti.pt.x=(short)LOWORD(GetMessagePos());
+ hti.pt.y=(short)HIWORD(GetMessagePos());
+ ScreenToClient(hTree,&hti.pt);
+ if(hItem=TreeView_HitTest(hTree,&hti))
+ {
+ if (hti.flags & TVHT_ONITEM)
+ TreeView_SelectItem(hTree,hItem);
+ if (hti.flags & TVHT_ONITEMSTATEICON)
+ SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0);
+
+ }
+ }
+ break;
+ }
+ break; //case IDC_PROTOCOLLIST
+ }
+ break;//case WM_NOTIFY
+
+ case WM_DESTROY:
+ // free protocol list
+ {
+ HWND hwndTreeView = GetDlgItem(hdlg,IDC_PROTOCOLLIST);
+ HTREEITEM hItem;
+ TVITEM tvItem;
+
+ hItem = TreeView_GetRoot(hwndTreeView);
+ tvItem.mask = TVIF_HANDLE | TVIF_PARAM;
+
+ while (hItem != NULL) {
+ tvItem.hItem = hItem;
+ TreeView_GetItem(hwndTreeView, &tvItem);
+ free((void *)tvItem.lParam);
+ hItem = TreeView_GetNextSibling(hwndTreeView, hItem);
+ }
+ }
+ break;
+
+ }
+
+ return 0;
+}
+
+int OptionsInit(WPARAM wparam,LPARAM lparam)
+{
+ OPTIONSDIALOGPAGE odp;
+ HMODULE hUxTheme = 0;
+
+ if(IsWinVerXPPlus()) {
+ hUxTheme = GetModuleHandle(_T("uxtheme.dll"));
+
+ if(hUxTheme)
+ pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
+ }
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize=sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance=hInstance;
+ odp.flags=ODPF_BOLDGROUPS;
+ odp.pszTemplate=MAKEINTRESOURCE(IDD_SETTINGS);
+ odp.pszGroup="Services";
+ odp.pszTitle="Last seen";
+ odp.pfnDlgProc= OptsSettingsDlgProc;
+ CallService(MS_OPT_ADDPAGE,wparam,(LPARAM)&odp);
+ if (ServiceExists(MS_POPUP_ADDPOPUP))
+ {
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_POPUPS);
+ odp.pszGroup = "PopUps";
+ odp.pszTitle = "Last seen";
+ odp.pfnDlgProc = OptsPopUpsDlgProc;
+ CallService(MS_OPT_ADDPAGE,wparam,(LPARAM)&odp);
+ }
+ return 0;
+}
diff --git a/plugins/SeenPlugin/readme_src.txt b/plugins/SeenPlugin/readme_src.txt
new file mode 100644
index 0000000000..0769b49b03
--- /dev/null
+++ b/plugins/SeenPlugin/readme_src.txt
@@ -0,0 +1,23 @@
+This source code is licensed under the GPL (http://www.gnu.org/copyleft/gpl.html)
+
+Please notify me of any changes that improve the plugin or add
+new features.
+
+If you have any questions on the code, feel free to contact me at
+UIN: 46955367 or
+eMail: micron@nexgo.de
+Visit http://home.nexgo.de/micron/miranda for the latest source files
+
+micron-x
+
+
+
+Rebase information
+******************
+enotify.dll 0x67700000
+dbviewer.dll 0x67600000
+hotkey.dll 0x67500000
+pluginsweeper.dll 0x67400000
+seenplugin.dll 0x67300000
+tipinfo.dll 0x67200000
+visibility.dll 0x67100000 \ No newline at end of file
diff --git a/plugins/SeenPlugin/resource.h b/plugins/SeenPlugin/resource.h
new file mode 100644
index 0000000000..913ed4c8b4
--- /dev/null
+++ b/plugins/SeenPlugin/resource.h
@@ -0,0 +1,97 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+
+#ifndef TVS_NOTOOLTIPS
+#define TVS_NOTOOLTIPS 0x0080
+#endif
+
+#define ID_STATUS_OFFLINE 40071
+#define ID_STATUS_ONLINE 40072
+#define ID_STATUS_AWAY 40073
+#define ID_STATUS_DND 40074
+#define ID_STATUS_NA 40075
+#define ID_STATUS_OCCUPIED 40076
+#define ID_STATUS_FREECHAT 40077
+#define ID_STATUS_INVISIBLE 40078
+#define ID_STATUS_ONTHEPHONE 40079
+#define ID_STATUS_OUTTOLUNCH 40080
+#define ID_STATUS_IDLE 40081 /* do not use as a status */
+
+
+#define IDD_SETTINGS 101
+#define IDD_USERINFO 102
+#define IDD_MISSED 103
+#define IDD_USERDETAILS 104
+#define IDD_HISTORY 105
+#define IDD_POPUPS 106
+#define IDC_SEENMENUITEM 1000
+#define IDC_MENUITEM 1001
+#define IDC_UINFOTAB 1002
+#define IDC_USERINFO 1003
+#define IDC_USERTIME 1004
+#define IDC_HISTORY 1005
+#define IDC_FILE 1006
+#define IDC_FILEGROUP 1007
+#define IDC_POPUPS 1008
+#define IDC_TIME 1009
+#define IDC_OWNSTATUS 1010
+#define IDC_TIMESTAMPGROUP 1011
+#define IDC_EDIT1 1012
+#define IDC_TIMESTAMP 1013
+#define IDC_FILESTAMP 1014
+#define IDC_CONTACTS 1015
+#define IDC_INFOTEXT 1016
+#define IDC_TIMESTAMPHELP 1017
+#define IDC_USERSTAMP 1018
+#define IDC_DELCHAR 1019
+#define IDC_HISTORYSTAMP 1020
+#define IDC_DELCHARHELP 1021
+#define IDC_POPUPSTAMP 1022
+#define IDC_MENUGROUP 1023
+#define IDC_POPUPSTAMPTEXT 1023
+#define IDC_MENUTIME 1024
+#define IDC_MENUSTATUS 1025
+#define IDC_MENUSTAMP 1026
+#define IDC_LABTEXT 1027
+#define IDC_MISSPOPUP 1028
+#define IDC_DEFAULTCOL 1029
+#define IDC_FILENAME 1030
+#define IDC_IGNOREOFFLINE 1031
+#define IDC_MISSEDONES 1032
+#define IDC_SHOWICON 1033
+#define IDC_COUNT 1034
+#define IDC_FILENAME2 1035
+#define IDC_HISTORYSIZE 1036
+#define IDC_LASTSEENLIST 1037
+#define IDC_HISTORYLIST 1038
+#define IDC_STATUSCHANGE 1039
+#define IDC_VARIABLES 1040
+#define IDC_PROTOCOLLIST 1041
+#define IDC_USERMENU 1042
+#define IDC_TEST 1043
+#define IDC_DETAILS 1044
+#define IDC_SENDMSG 1045
+#define IDC_LABTTITLE 1046
+#define IDC_OPTIONSTAB 1047
+#ifndef PERMITNSN
+#define IDC_DISWATCHED 1048
+#define IDC_DISNONWATCHED 1049
+#endif
+#define IDC_IDLESUPPORT 1050
+#define IDC_MAINGROUP -1
+#define IDC_INFO -1
+#define IDC_TEXT -1
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1051
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/SeenPlugin/resource.rc b/plugins/SeenPlugin/resource.rc
new file mode 100644
index 0000000000..90733f0fd1
--- /dev/null
+++ b/plugins/SeenPlugin/resource.rc
@@ -0,0 +1,293 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include <windows.h>\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_SETTINGS DIALOGEX 0, 0, 300, 228
+STYLE DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Last seen options",IDC_MAINGROUP,0,0,299,226,WS_GROUP
+ CONTROL "Last seen menuitem",IDC_MENUITEM,"Button",
+ BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,6,12,132,10
+ CONTROL "Show icon",IDC_SHOWICON,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,141,12,69,10
+ EDITTEXT IDC_MENUSTAMP,18,23,120,12,ES_AUTOHSCROLL | WS_GROUP
+ CONTROL "Userinfo tab",IDC_USERINFO,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,6,42,140,10
+ EDITTEXT IDC_USERSTAMP,18,52,275,12,ES_AUTOHSCROLL | WS_GROUP
+ CONTROL "Log to file",IDC_FILE,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,6,72,132,10
+ EDITTEXT IDC_FILENAME,149,69,144,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_FILESTAMP,18,83,275,12,ES_AUTOHSCROLL | WS_GROUP
+ CONTROL "Log to history",IDC_HISTORY,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,7,104,131,10
+ LTEXT "Maximum size",IDC_STATIC,183,102,51,9
+ EDITTEXT IDC_HISTORYSIZE,149,100,30,12,ES_AUTOHSCROLL | ES_NUMBER
+ EDITTEXT IDC_HISTORYSTAMP,18,114,275,12,ES_AUTOHSCROLL | WS_GROUP
+ PUSHBUTTON "Variable list",IDC_VARIABLES,47,137,50,13
+ CONTROL "Enable Idle support",IDC_IDLESUPPORT,"Button",
+ BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,158,135,10
+ CONTROL "Ignore contacts going offline",IDC_IGNOREOFFLINE,"Button",
+ BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,174,135,10
+ CONTROL "Enable 'Missed Ones' feature",IDC_MISSEDONES,"Button",
+ BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,7,190,135,10
+ CONTROL "Count times",IDC_COUNT,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,18,202,100,10
+ LTEXT "Protocols to watch:",IDC_MAINGROUP,149,130,114,9
+ CONTROL "Tree1",IDC_PROTOCOLLIST,"SysTreeView32",TVS_NOTOOLTIPS |
+ WS_BORDER | WS_TABSTOP,149,140,144,81
+END
+
+IDD_POPUPS DIALOGEX 0, 0, 280, 208
+STYLE DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "",IDC_STATIC,0,0,280,26,WS_GROUP
+ CTEXT "Popup interoperability missing or disabled. You need Popups plugin",IDC_MISSPOPUP,1,11,280,10,NOT WS_VISIBLE
+ CONTROL "Use popups",IDC_POPUPS,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,3,10,50,10
+ RTEXT "Title",IDC_LABTEXT,57,11,40,10
+ EDITTEXT IDC_POPUPSTAMP,100,9,50,12,ES_AUTOHSCROLL | WS_GROUP
+ RTEXT "Text",IDC_LABTTITLE,155,11,25,10
+ EDITTEXT IDC_POPUPSTAMPTEXT,185,9,88,12,ES_AUTOHSCROLL |
+ WS_GROUP
+ GROUPBOX "PopUp Colors",IDC_STATIC,0,30,280,136,WS_GROUP
+ RTEXT "Online",IDC_STATIC,10,43,60,10
+ CONTROL "",ID_STATUS_ONLINE,"ColourPicker",WS_TABSTOP,80,40,20,14
+ CONTROL "",ID_STATUS_ONLINE+20,"ColourPicker",WS_TABSTOP,105,40,20,14
+ RTEXT "Away",IDC_STATIC,10,63,60,10
+ CONTROL "",ID_STATUS_AWAY,"ColourPicker",WS_TABSTOP,80,60,20,14
+ CONTROL "",ID_STATUS_AWAY+20,"ColourPicker",WS_TABSTOP,105,60,20,14
+ RTEXT "N/A",IDC_STATIC,10,83,60,10
+ CONTROL "",ID_STATUS_NA,"ColourPicker",WS_TABSTOP,80,80,20,14
+ CONTROL "",ID_STATUS_NA+20,"ColourPicker",WS_TABSTOP,105,80,20,14
+ RTEXT "Occupied",IDC_STATIC,10,103,60,10
+ CONTROL "",ID_STATUS_OCCUPIED,"ColourPicker",WS_TABSTOP,80,100,20,14
+ CONTROL "",ID_STATUS_OCCUPIED+20,"ColourPicker",WS_TABSTOP,105,100,20,14
+ RTEXT "DND",IDC_STATIC,10,123,60,10
+ CONTROL "",ID_STATUS_DND,"ColourPicker",WS_TABSTOP,80,120,20,14
+ CONTROL "",ID_STATUS_DND+20,"ColourPicker",WS_TABSTOP,105,120,20,14
+
+ RTEXT "On the phone",IDC_STATIC,140,43,60,10
+ CONTROL "",ID_STATUS_ONTHEPHONE,"ColourPicker",WS_TABSTOP,210,40,20,14
+ CONTROL "",ID_STATUS_ONTHEPHONE+20,"ColourPicker",WS_TABSTOP,235,40,20,14
+ RTEXT "Out to lunch",IDC_STATIC,140,63,60,10
+ CONTROL "",ID_STATUS_OUTTOLUNCH,"ColourPicker",WS_TABSTOP,210,60,20,14
+ CONTROL "",ID_STATUS_OUTTOLUNCH+20,"ColourPicker",WS_TABSTOP,235,60,20,14
+ RTEXT "Free for chat",IDC_STATIC,140,83,60,10
+ CONTROL "",ID_STATUS_FREECHAT,"ColourPicker",WS_TABSTOP,210,80,20,14
+ CONTROL "",ID_STATUS_FREECHAT+20,"ColourPicker",WS_TABSTOP,235,80,20,14
+ RTEXT "Invisible",IDC_STATIC,140,103,60,10
+ CONTROL "",ID_STATUS_INVISIBLE,"ColourPicker",WS_TABSTOP,210,100,20,14
+ CONTROL "",ID_STATUS_INVISIBLE+20,"ColourPicker",WS_TABSTOP,235,100,20,14
+ RTEXT "Offline",IDC_STATIC,140,123,60,10
+ CONTROL "",ID_STATUS_OFFLINE,"ColourPicker",WS_TABSTOP,210,120,20,14
+ CONTROL "",ID_STATUS_OFFLINE+20,"ColourPicker",WS_TABSTOP,235,120,20,14
+ PUSHBUTTON "Reset colors",IDC_DEFAULTCOL,115,145,50,13
+#ifndef PERMITNSN
+ GROUPBOX "Disable CList Notifications",IDC_STATIC,0,170,280,38,WS_GROUP
+ CONTROL "For watched protocols",IDC_DISWATCHED,"Button", BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,10,180,100,10
+ CONTROL "For non-watched protocols",IDC_DISNONWATCHED,"Button", BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,10,193,100,10
+#endif
+END
+
+IDD_USERINFO DIALOGEX 0, 0, 222, 132
+STYLE DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_INFOTEXT,6,6,210,122,ES_MULTILINE | ES_NOHIDESEL |
+ ES_READONLY | NOT WS_BORDER
+END
+
+IDD_MISSED DIALOGEX 0, 0, 160, 71
+STYLE DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Last seen plugin"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,55,48,50,14
+ LTEXT "You missed following contacts:",IDC_TEXT,6,6,148,10
+ CTEXT "Test\nTest",IDC_CONTACTS,6,22,148,16
+END
+
+IDD_HISTORY DIALOGEX 0, 0, 200, 120
+STYLE DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+// PUSHBUTTON "Variablestest",IDC_TEST,5,5,52,13,NOT WS_VISIBLE
+ DEFPUSHBUTTON "OK",IDOK,75,101,50,14
+ PUSHBUTTON "",IDC_USERMENU,146,5,15,13,BS_ICON | WS_TABSTOP
+ PUSHBUTTON "",IDC_DETAILS,163,5,15,13,BS_ICON | WS_TABSTOP
+ PUSHBUTTON "",IDC_SENDMSG,180,5,15,13,BS_ICON | WS_TABSTOP
+ LISTBOX IDC_HISTORYLIST,5,20,190,59,LBS_NOINTEGRALHEIGHT |
+ WS_VSCROLL | WS_TABSTOP
+ CONTROL "Alert when user status changes",IDC_STATUSCHANGE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,5,86,190,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 293
+ VERTGUIDE, 18
+ VERTGUIDE, 149
+ VERTGUIDE, 161
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 225
+ HORZGUIDE, 22
+ END
+
+ IDD_USERINFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 215
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 125
+ END
+
+ IDD_MISSED, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 153
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 64
+ END
+
+ IDD_HISTORY, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 195
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 115
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 5,0,4,7
+ PRODUCTVERSION 5,0,4,7
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "Last Seen Mod Plugin for Miranda IM\0"
+ VALUE "CompanyName", "Heiko Schillinger, YB\0"
+#ifdef PERMITNSN
+ VALUE "FileDescription", "Last Seen Plugin\0"
+#else
+ VALUE "FileDescription", "Last Seen Plugin (NSN Compatible)\0"
+#endif
+ VALUE "FileVersion", "5.0.4.7\0"
+ VALUE "InternalName", "Last Seen\0"
+ VALUE "LegalCopyright", " 2001-2002 by Heiko Schillinger, 2003 by Bruno Rino, 2006 by YB\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "seenplugin.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", " Last Seen Plugin Mod\0"
+ VALUE "ProductVersion", "5.0.4.7\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // !_MAC
+
+#endif // German (Germany) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/SeenPlugin/seen.h b/plugins/SeenPlugin/seen.h
new file mode 100644
index 0000000000..4e38c29c57
--- /dev/null
+++ b/plugins/SeenPlugin/seen.h
@@ -0,0 +1,128 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/seen.h $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0300
+#endif
+#define ETDT_ENABLE 0x00000002
+#define ETDT_USETABTEXTURE 0x00000004
+#define ETDT_ENABLETAB (ETDT_ENABLE | ETDT_USETABTEXTURE)
+#define MIRANDA_VER 0x0900
+#define MIRANDA_CUSTOM_LP
+
+#include <windows.h>
+#include <win2k.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "resource.h"
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_langpack.h>
+
+#include <m_system.h>
+#include <m_skin.h>
+#include <m_utils.h>
+#include <m_options.h>
+#include <m_userinfo.h>
+#include <m_clist.h>
+#include <m_userinfo.h>
+#include <m_contacts.h>
+#include <m_message.h>
+#include <m_protosvc.h>
+#include <m_protocols.h>
+#include <m_popup.h>
+#include <m_system.h>
+
+#include "m_tipper.h"
+WCHAR *any_to_IdleNotidleUnknown(HANDLE hContact, const char *module_name, const char *setting_name, WCHAR *buff, int bufflen);
+WCHAR *any_to_Idle(HANDLE hContact, const char *module_name, const char *setting_name, WCHAR *buff, int bufflen);
+
+#ifdef __GNUC__
+#define NUM100NANOSEC 116444736000000000ULL
+#else
+#define NUM100NANOSEC 116444736000000000
+#endif
+
+#define S_MOD "SeenModule"
+
+//#define UM_CHECKHOOKS (WM_USER+1)
+
+#define debug(a) MessageBox(NULL,a,"Debug",MB_OK)
+
+#define IDI_USERDETAILS 160
+#define IDI_DOWNARROW 264
+#define IDI_RECVMSG 136
+
+#define ICON_OFFLINE 13
+#define ICON_ONLINE 14
+#define ICON_AWAY 15
+#define ICON_NA 16
+#define ICON_OCC 17
+#define ICON_DND 18
+#define ICON_FREE 19
+#define ICON_INVIS 20
+
+#define DEFAULT_MENUSTAMP "%d.%m.%Y - %H:%M [%s]"
+#define DEFAULT_POPUPSTAMP Translate("%n is %s (%u)")
+#define DEFAULT_POPUPSTAMPTEXT Translate("%i(%r)%bWas %o")
+#define DEFAULT_USERSTAMP Translate("Name:%t%N%bStatus:%t%s%bDay:%t%d.%m.%Y%bTime:%t%H:%M:%S%bPrevious Status:%t%o%b%b%P ID:%t%u%bExternal IP:%t%i%bInternal IP:%t%r%bClientID: %t%C%b%bStatus Message:%t%T")
+#define DEFAULT_FILESTAMP "%d.%m.%Y %H:%M:%S%t%n%t%s%t%u%t%r | %i%t%N"
+#define DEFAULT_FILENAME "logs\\%P.txt"
+#define DEFAULT_HISTORYSTAMP "%d.%m.%Y - %H:%M [%s]"
+#define DEFAULT_WATCHEDPROTOCOLS ""
+
+#define VARIABLE_LIST "%s \n%%Y: \t %s \n%%y: \t %s \n%%m: \t %s \n%%E: \t %s \n%%e: \t %s \n%%d: \t %s \n%%W: \t %s \n%%w: \t %s \n\n%s \n%%H: \t %s \n%%h: \t %s \n%%p: \t %s \n%%M: \t %s \n%%S: \t %s \n\n%s \n%%n: \t %s \n%%N: \t %s \n%%u: \t %s \n%%G: \t %s \n%%s: \t %s \n%%T: \t %s \n%%o: \t %s \n%%i: \t %s \n%%r: \t %s \n%%C: \t %s \n%%P: \t %s \n\n%s \n%%t: \t %s \n%%b: \t %s\n\n%s\t%s \"#\" %s\n\t%s %s", Translate("-- Date --"), Translate("year (4 digits)"), Translate("year (2 digits)"), Translate("month"), Translate("name of month"), Translate("short name of month"), Translate("day"), Translate("weekday (full)"), Translate("weekday (abbreviated)"), Translate("-- Time --"), Translate("hours (24)"), Translate("hours (12)"), Translate("AM/PM"), Translate("minutes"), Translate("seconds"), Translate("-- User --"), Translate("username"), Translate("nick"), Translate("UIN/handle"), Translate("Group"), Translate("Status"), Translate("Status message"), Translate("Old status"), Translate("external IP"), Translate("internal IP"),Translate("Client info"),Translate("Protocol"), Translate("-- Format --"), Translate("tabulator"), Translate("line break"), Translate("Note:"),Translate("Use"),Translate("for empty string"),Translate("instead of"),Translate("<unknown>")
+
+#ifndef LPCOLORREF
+typedef DWORD *LPCOLORREF;
+#endif
+
+typedef struct{
+ int count;
+ WPARAM wpcontact[1024];
+ BYTE times[1024];
+} MISSEDCONTACTS;
+
+/* utils.c */
+int IsWatchedProtocol(const char* szProto);
+char *ParseString(char *,HANDLE,BYTE);
+extern DWORD StatusColors15bits[];
+void GetColorsFromDWord(LPCOLORREF First, LPCOLORREF Second, DWORD colDword);
+DWORD GetDWordFromColors(COLORREF First, COLORREF Second);
+
+void UninitMenuitem();
+
+BOOL includeIdle;
+typedef struct logthread_info {
+ char sProtoName[MAXMODULELABELLENGTH];
+ HANDLE hContact;
+ WORD courStatus;
+ int queueIndex;
+} logthread_info;
+
+extern logthread_info **contactQueue;
+extern int contactQueueSize;
+
diff --git a/plugins/SeenPlugin/seen_info.txt b/plugins/SeenPlugin/seen_info.txt
new file mode 100644
index 0000000000..5ba87f079a
--- /dev/null
+++ b/plugins/SeenPlugin/seen_info.txt
@@ -0,0 +1,216 @@
+Last Seen plugin
+****************
+This plugin logs when a contact was last seen online.
+You can choose between contactmenu item, userinfo page and file output.
+Second feature is to show which users were online while you were away.
+
+micron-x
+
+Questions and comments to:
+micron@nexgo.de
+
+Last Seen Mod
+*************
+I did some (quick'n'dirty) modifications to LastSeen plugin to fit better to my taste:
+
+ 1. ICQ IPs are logged correctly;
+ 2. Variables can be used in the log filename. You could have separate files for different protocols/contacts or create new file each month;
+ 3. Rewritten "Protocols to watch". Now selecting/deselecting protocols is easy ;)
+ 4. Solved enable/disable file logging bug
+ 5. Introduced 6 new variables:
+ * %P - protocol name (ICQ, ICQ1, MSN...);
+ * %N - nick on the server;
+ * %C - Client Info;
+ * %G - Group;
+ * %o - Old status;
+ * %T - Status message
+ 6. Option to use # instead of % to get empty strings instead of <unknown>
+ 7. extended support of multiple yahoo protocols(not tested);
+ 8. extended support for jabber/s.
+ 9. popup support
+ 10. delayed logging to wait for the protocols to update all the settings
+ 11. option to track idle statuses
+
+Y.B.
+http://saaplugin.no-ip.info/
+http://forums.miranda-im.org/showthread.php?t=2822
+
+
+Langpack strings
+****************
+
+see seen_langpack.txt
+
+
+
+Version history
+***************
+
+Last Seen Mod
+*************
+ * v. 5.0.4.7
+ o Added special sound for "Uses Logged In"
+ o Used the core service MS_SYSTEM_FORK_THREAD_EX
+
+ * v. 5.0.4.3
+ o Included seenTS DB setting
+ o "suppress online notification" affects only sounds and popups
+ o Sounds are working now. Two new are added.
+ * v. 5.0.4.2
+ o Implemented Idle support (Will include "/Idle" to the status if contact is idle)
+ * v. 5.0.4.1
+ o Enabled 32bit icons in lastseen history dialog (fixes the "transperancy bug")
+ o New variable: %T: Status Message
+ o Parser rewritten to be safer
+ o Click on popup will open message window
+ * v. 5.0.4.0
+ o Small memory leak in user info dialog fixed (thanks Tio Duke)
+ o Increased the delay to check offline contacts 2->10 seconds
+ o If the contact's status changer while we have been offline the time we went offline will be logged (not the current time)
+ o Fixed visual glitch in the "last seen history" dialog
+ o Suppress the DEFMOD_RNDUSERONLINE core functionality - LastSeenMod is not compatible with NewStatusNotify anylonger
+ o Option to enable clist online notify
+ * v. 5.0.3.2
+ o Better protocol type guessing (based on PFLAG_UNIQUEIDSETTING)
+ o Popups colors are configurable
+ o Tabbed interface of the option page
+ * v. 5.0.3.1 (never released)
+ o Avoid multiple popups on login - only those for contacts with different status before logoff
+ o implemented delayed logging of the status changes using thread
+ o Doesn't show popups is the contact is "hidden"
+ o Better tracking if the contact went offline while we were offline
+ o %i and %r are replaced by "resource" and "system" for Jabber/JGmail
+ * v. 5.0.3.0
+ o Enhanced PopUp support:
+ + separated fields for PopUp title and text
+ + Correct icon is chosen according to the protocol and status
+ o New Variable %o - "Old Status"
+ o JGmail is recognised as Jabber
+ * v. 5.0.2.6
+ o Basic PopUp support
+ * v. 5.0.2.5
+ o Added %G standing for "Group"
+ o Using variables in the path of the log file(s) is possible now
+ * v. 5.0.2.4
+ o Updated MSN capability bits according to this post
+ * v. 5.0.2.3
+ o Solved enable/disable file logging bug (hopefully)
+ o Option to use # instead of % to get empty strings instead of <unknown>
+ * v. 5.0.2.2
+ o Added %C (Client/version for ICQ; ClientID flags for MSN);
+ o Better support for multiple instances of same protocol;
+ o Logging contacts of protocol logon/off is back;
+ * v. 5.0.2.1
+ o Updated plugin info
+
+Last Seen plugin
+****************
+5.0.1.1:
+ - FIX: The protocol list now uses more uuser friendly names
+ - FIX: The "Missed Ones" feature options weren't saved correctly
+ - FIX: The "Offline" setting was added even to contacts whose protocol wasn't "watched"
+ - FIX: Minor cosmetics (icons and tooltips)
+ - UPDATE: seen_langpack.txt
+5.0.1.0:
+ - FIX: Some protocols added an offline entry for every contact when the user logoff the network
+ - FIX: An extra character (0 or 1) was added to each line of the file log.
+ - UPDATE: seen_langpack.txt now contains the strings added on version 5.0.0.0
+5.0.0.1:
+ - FIX: Removed some code that flooded the network with requests (see http://miranda-icq.sourceforge.net/forums/viewtopic.php?t=11579)
+ - CHANGE: History now defaults to a "pretier" format.
+5.0.0.0:
+ - FIX: Last statusmode icon displayed according to the contact's protocol
+ - NEW: Support for all protocols (user selectable)
+ - NEW: Added dialog showing the recent "seen history" of an user
+ - NEW: Added option to display an alert when a specified user changes its status
+
+4.1.6.2: - prevent plugin not loading & new base address
+
+4.1.6.1: - Silly bug with 4.1.6.0 fixed
+
+4.1.6.0: - Directory access fix
+
+4.1.5.0: - fixed 0AM/PM bug
+ - 'Missed Ones' window doesn't steal focus anymore
+ - 'Missed Ones' bugfixes
+
+4.1.4.0: - removed Miranda 0.1.2.0 support
+
+4.1.3.0: - 'Missed Ones' dismisses ignored contacts (online notification)
+ - reduced file size
+
+4.1.2.0: - Added support for Plugin sweeper
+
+4.1.1.0: - New option: count times a user was online while you were away
+ - Bug crashing Miranda on open userdetails fixed
+
+4.1.0.0: - 'Missed Ones' should finally work now
+
+4.0.9.0: - works now with Miranda v0.1.2.0
+ - unknown values grayed out
+
+4.0.8.0: - fixed bug crashing miranda on status change
+
+4.0.7.0: - two new variables: %E - name of month and %e abrreviated name of month
+ - empty userinfo page fixed
+
+4.0.6.0: - attempted fix for bad userinfo page
+ - two new variables: %W - weekday and %w - abbr. weekday
+
+4.0.5.0: - Two new variables: %h - 12 hour time and %p - AM/PM
+ - New 'Missed Ones' popup (Dialog instead of MessageBox)
+
+4.0.4.0: - Option to show last statusmode icon
+
+4.0.3.0: - 'Missed Ones' feature reimplemented
+ - Miranda crashing on close fixed
+
+4.0.2.0: - Option to keep track of contacts going offline
+ - fixed crashing when %u was used
+ - file output implemented
+ - one new langpack string
+
+4.0.1.0: - IP/RealIP variables working now
+
+4.0.0.0: - Initial release of the totally rewritten version
+ Please mail me any bug reports
+
+
+
+Rebase information
+******************
+seenplugin.dll 0x67300000
+
+enotify.dll 0x67700000
+dbviewer.dll 0x67600000
+hotkey.dll 0x67500000
+pluginsweeper.dll 0x67400000
+tipinfo.dll 0x67200000
+visibility.dll 0x67100000
+
+
+
+======================================
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-06 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/seen_info.txt $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+
diff --git a/plugins/SeenPlugin/seen_langpack.txt b/plugins/SeenPlugin/seen_langpack.txt
new file mode 100644
index 0000000000..a46cb433d3
--- /dev/null
+++ b/plugins/SeenPlugin/seen_langpack.txt
@@ -0,0 +1,172 @@
+[Last seen]
+
+[Last seen options]
+
+[Last seen menuitem]
+
+[Userinfo tab]
+
+[Log to file]
+
+[year (4 digits)]
+
+[year (2 digits)]
+
+[month]
+
+[day]
+
+[minutes]
+
+[seconds]
+
+[username]
+
+[UIN/handle]
+
+[status]
+
+[external IP]
+
+[internal IP]
+
+[line break]
+
+[tabulator]
+
+[<unknown>]
+
+;New 4.0.2
+;--------------------
+[Ignore contacts going offline]
+
+;New 4.0.3
+;--------------------
+[Enable 'Missed Ones' feature]
+
+[You missed following contacts:]
+
+;New 4.0.4
+;--------------------
+[Show icon]
+
+;Modified 4.0.5
+;--------------------
+;[hours]
+[hours (24)]
+
+;New 4.0.5
+;--------------------
+[hours (12)]
+
+[AM/PM]
+
+;New 4.0.6
+;--------------------
+[weekday (full)]
+
+[weekday (abbreviated)]
+
+[Monday]
+
+[Tuesday]
+
+[Wednesday]
+
+[Thursday]
+
+[Friday]
+
+[Saturday]
+
+[Sunday]
+
+[Mon.]
+
+[Tue.]
+
+[Wed.]
+
+[Thu.]
+
+[Fri.]
+
+[Sat.]
+
+[Sun.]
+
+;New 4.0.7
+;--------------------
+[name of month]
+
+[short name of month]
+
+[January]
+
+[February]
+
+[March]
+
+[April]
+
+[May]
+
+[June]
+
+[July]
+
+[August]
+
+[September]
+
+[October]
+
+[November]
+
+[December]
+
+[Jan.]
+
+[Feb.]
+
+[Mar.]
+
+[Apr.]
+
+[May]
+
+[Jun.]
+
+[Jul.]
+
+[Aug.]
+
+[Sep.]
+
+[Oct.]
+
+[Nov.]
+
+[Dec.]
+
+;New 4.1.1
+;--------------------
+[Count times]
+
+;New 5.0.0.0
+;--------------------
+[last seen history]
+
+[Log to history]
+
+[Maximum size]
+
+[Variable list]
+
+[Protocols to watch:]
+
+[Alert when user status changes]
+
+;New 5.0.1.1
+;--------------------
+[Send Instant Message]
diff --git a/plugins/SeenPlugin/seenplugin.dsp b/plugins/SeenPlugin/seenplugin.dsp
new file mode 100644
index 0000000000..b1a406ce5a
--- /dev/null
+++ b/plugins/SeenPlugin/seenplugin.dsp
@@ -0,0 +1,225 @@
+# Microsoft Developer Studio Project File - Name="seenplugin" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=seenplugin - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "seenplugin.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "seenplugin.mak" CFG="seenplugin - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "seenplugin - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "seenplugin - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "seenplugin - Win32 PermNSN Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "seenplugin - Win32 PermNSN Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "seenplugin - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "release"
+# PROP Intermediate_Dir "release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MP_SEEN_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /Gi /GX /O1 /I "..\..\include\\" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+# SUBTRACT MTL /mktyplib203
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib winmm.lib version.lib /nologo /base:"0x67400000" /dll /machine:I386 /out:"../../bin/upload/seen/seenplugin.dll" /filealign:0x200
+# SUBTRACT LINK32 /pdb:none /map
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=cd ../../bin/upload/ md5 -s -t -oseen/seenplugin.dll.md5 seen/seenplugin.dll
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "seenplugin - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MP_SEEN_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MP_SEEN_EXPORTS" /FAcs /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib winmm.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib winmm.lib /nologo /base:"0x67400000" /dll /debug /machine:I386 /out:"../../bin/debug/Plugins/seenplugin.dll"
+# SUBTRACT LINK32 /profile /pdb:none /incremental:no /map
+
+!ELSEIF "$(CFG)" == "seenplugin - Win32 PermNSN Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleasePermNSN"
+# PROP BASE Intermediate_Dir "ReleasePermNSN"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "releasePermNSN"
+# PROP Intermediate_Dir "releasePermNSN"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "PERMITNSN" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MP_SEEN_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /Gi /GX /O1 /I "..\..\include\\" /D "PERMITNSN" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+# SUBTRACT MTL /mktyplib203
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib winmm.lib /nologo /dll /machine:I386
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib winmm.lib /nologo /base:"0x67400000" /dll /machine:I386 /out:"../../bin/upload/seen/NSNCompat/seenplugin.dll" /filealign:0x200
+# SUBTRACT LINK32 /pdb:none /map
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=cd ../../bin/upload/ md5 -s -t -oseen/NSNCompat/seenplugin.dll.md5 seen/NSNCompat/seenplugin.dll
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "seenplugin - Win32 PermNSN Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugPermNSN"
+# PROP BASE Intermediate_Dir "DebugPermNSN"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugPermNSN"
+# PROP Intermediate_Dir "DebugPermNSN"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MP_SEEN_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../../include" /D "PERMITNSN" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MP_SEEN_EXPORTS" /FAcs /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib winmm.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib winmm.lib /nologo /base:"0x67400000" /dll /debug /machine:I386 /out:"../../bin/debug/Plugins/NSNCompat/seenplugin.dll"
+# SUBTRACT LINK32 /profile /pdb:none /incremental:no /map
+
+!ENDIF
+
+# Begin Target
+
+# Name "seenplugin - Win32 Release"
+# Name "seenplugin - Win32 Debug"
+# Name "seenplugin - Win32 PermNSN Release"
+# Name "seenplugin - Win32 PermNSN Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\history.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\menu.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\missed.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\userinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\utils.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\seen.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\seen_info.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\seen_langpack.txt
+# End Source File
+# End Target
+# End Project
diff --git a/plugins/SeenPlugin/seenplugin.dsw b/plugins/SeenPlugin/seenplugin.dsw
new file mode 100644
index 0000000000..bfadb79ded
--- /dev/null
+++ b/plugins/SeenPlugin/seenplugin.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "seenplugin"=".\seenplugin.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/plugins/SeenPlugin/seenplugin_10.sln b/plugins/SeenPlugin/seenplugin_10.sln
new file mode 100644
index 0000000000..0c6cc2a79e
--- /dev/null
+++ b/plugins/SeenPlugin/seenplugin_10.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SeenPlugin", "seenplugin_10.vcxproj", "{EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Debug|Win32.Build.0 = Debug|Win32
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Debug|x64.ActiveCfg = Debug|x64
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Debug|x64.Build.0 = Debug|x64
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Release|Win32.ActiveCfg = Release|Win32
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Release|Win32.Build.0 = Release|Win32
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Release|x64.ActiveCfg = Release|x64
+ {EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/SeenPlugin/seenplugin_10.vcxproj b/plugins/SeenPlugin/seenplugin_10.vcxproj
new file mode 100644
index 0000000000..e90f9f4701
--- /dev/null
+++ b/plugins/SeenPlugin/seenplugin_10.vcxproj
@@ -0,0 +1,361 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>SeenPlugin</ProjectName>
+ <ProjectGuid>{EFD45F48-63D5-48AE-96CD-8ADB3545A4EE}</ProjectGuid>
+ <RootNamespace>Seenplugin</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\releasePermNSN/seenplugin.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>PERMITNSN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/filealign:0x200 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>ws2_32.lib;comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ProgramDatabaseFile>
+ </ProgramDatabaseFile>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <BaseAddress>0x67400000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\releasePermNSN/seenplugin.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>PERMITNSN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
+ <BrowseInformationFile>
+ </BrowseInformationFile>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/filealign:0x200 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>ws2_32.lib;comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ProgramDatabaseFile>
+ </ProgramDatabaseFile>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <BaseAddress>0x67400000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\DebugPermNSN/seenplugin.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>PERMITNSN;WIN32;_DEBUG;_WINDOWS;_USRDLL;MP_SEEN_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
+ <AssemblerOutput>All</AssemblerOutput>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <BaseAddress>0x67400000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\DebugPermNSN/seenplugin.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>PERMITNSN;WIN32;_DEBUG;_WINDOWS;_USRDLL;MP_SEEN_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
+ <AssemblerOutput>All</AssemblerOutput>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;comctl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <BaseAddress>0x67400000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="file.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="history.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="main.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="menu.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="missed.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="options.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="userinfo.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="utils.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="seen.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="seen_info.txt" />
+ <None Include="seen_langpack.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/SeenPlugin/seenplugin_10.vcxproj.filters b/plugins/SeenPlugin/seenplugin_10.vcxproj.filters
new file mode 100644
index 0000000000..99de7b53e9
--- /dev/null
+++ b/plugins/SeenPlugin/seenplugin_10.vcxproj.filters
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{89af4e67-032f-4900-b14d-1d956b6c376d}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{1f155b67-4f4e-4b49-a10e-6a0588c62a69}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{a800d3aa-15e0-4d7d-8b9f-99dfd4112d8e}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="file.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="history.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="menu.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="missed.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="options.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="userinfo.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="utils.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="seen.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="seen_info.txt" />
+ <None Include="seen_langpack.txt" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/SeenPlugin/userinfo.c b/plugins/SeenPlugin/userinfo.c
new file mode 100644
index 0000000000..02f050ea0f
--- /dev/null
+++ b/plugins/SeenPlugin/userinfo.c
@@ -0,0 +1,95 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/userinfo.c $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+#include "seen.h"
+
+
+
+WNDPROC MainProc;
+
+
+
+extern HINSTANCE hInstance;
+extern DWORD dwmirver;
+
+
+
+BOOL CALLBACK EditProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
+{
+ switch(msg){
+ case WM_SETCURSOR:
+ SetCursor(LoadCursor(NULL,IDC_ARROW));
+ return 1;
+
+ default:
+ break;
+ }
+ return CallWindowProc(MainProc,hdlg,msg,wparam,lparam);
+}
+
+
+
+INT_PTR CALLBACK UserinfoDlgProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
+{
+ char *szout;
+ DBVARIANT dbv;
+
+ switch(msg){
+
+ case WM_INITDIALOG:
+ MainProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hdlg,IDC_INFOTEXT),GWLP_WNDPROC,(LONG)EditProc);
+ szout=strdup(ParseString((!DBGetContactSetting(NULL,S_MOD,"UserStamp",&dbv)?dbv.pszVal:DEFAULT_USERSTAMP),(HANDLE)lparam,0));
+ SetDlgItemText(hdlg,IDC_INFOTEXT,szout);
+ if(!strcmp(szout,Translate("<unknown>")))
+ EnableWindow(GetDlgItem(hdlg,IDC_INFOTEXT),FALSE);
+ free(szout);
+ DBFreeVariant(&dbv);
+ break;
+
+ case WM_COMMAND:
+ if(HIWORD(wparam)==EN_SETFOCUS)
+ SetFocus(GetParent(hdlg));
+ break;
+ }
+
+ return 0;
+}
+
+
+
+int UserinfoInit(WPARAM wparam,LPARAM lparam)
+{
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,lparam,0);
+ if (IsWatchedProtocol(proto)){
+ OPTIONSDIALOGPAGE uip;
+ ZeroMemory(&uip,sizeof(uip));
+ uip.cbSize=sizeof(uip);
+ uip.hInstance=hInstance;
+ uip.pszTemplate=MAKEINTRESOURCE(IDD_USERINFO);
+ uip.pszTitle="Last seen";
+ uip.pfnDlgProc=UserinfoDlgProc;
+ CallService(MS_USERINFO_ADDPAGE,wparam,(LPARAM)&uip);
+ }
+ return 0;
+}
diff --git a/plugins/SeenPlugin/utils.c b/plugins/SeenPlugin/utils.c
new file mode 100644
index 0000000000..5fc880ec75
--- /dev/null
+++ b/plugins/SeenPlugin/utils.c
@@ -0,0 +1,967 @@
+/*
+"Last Seen mod" plugin for Miranda IM
+Copyright ( C ) 2002-03 micron-x
+Copyright ( C ) 2005-07 Y.B.
+
+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.
+
+File name : $URL: http://svn.berlios.de/svnroot/repos/mgoodies/trunk/lastseen-mod/utils.c $
+Revision : $Rev: 1570 $
+Last change on : $Date: 2007-12-30 01:30:07 +0300 (Вс, 30 дек 2007) $
+Last change by : $Author: y_b $
+*/
+#include "seen.h"
+#include <m_ignore.h>
+#include <time.h>
+
+
+void FileWrite(HANDLE);
+void HistoryWrite(HANDLE hcontact);
+//void SetOffline(void);
+void ShowHistory(HANDLE hContact, BYTE isAlert);
+
+char * courProtoName = 0;
+
+//copied from ..\..\miranda32\protocols\protocols\protocols.c
+PROTOCOLDESCRIPTOR* Proto_IsProtocolLoaded(const char* szProto)
+{
+ return (PROTOCOLDESCRIPTOR*) CallService(MS_PROTO_ISPROTOCOLLOADED, 0, (LPARAM)szProto);
+}
+
+
+/*
+Returns true if the protocols is to be monitored
+*/
+int IsWatchedProtocol(const char* szProto)
+{
+ DBVARIANT dbv;
+ char *szProtoPointer, *szWatched;
+ int iProtoLen, iWatchedLen;
+ int retval = 0;
+ PROTOCOLDESCRIPTOR *pd;
+
+ if (szProto == NULL)
+ return 0;
+
+ pd=Proto_IsProtocolLoaded(szProto);
+ if (pd==NULL || pd->type!=PROTOTYPE_PROTOCOL || CallProtoService(pd->szName,PS_GETCAPS,PFLAGNUM_2,0)==0)
+ return 0;
+
+ iProtoLen = (int)_tcslen(szProto);
+ if(DBGetContactSetting(NULL, S_MOD, "WatchedProtocols", &dbv))
+ szWatched = DEFAULT_WATCHEDPROTOCOLS;
+ else
+ szWatched = dbv.pszVal;
+ iWatchedLen = (int)_tcslen(szWatched);
+
+ if (*szWatched == '\0')
+ {
+ retval=1; //empty string: all protocols are watched
+ }
+ else
+ {
+ char sTemp [MAXMODULELABELLENGTH+1]="";
+ strcat(sTemp,szProto);
+ strcat(sTemp," ");
+ szProtoPointer = strstr(szWatched, sTemp);
+ if (szProtoPointer == NULL)
+ retval=0;
+ else
+ retval=1;
+ }
+
+ DBFreeVariant(&dbv);
+ return retval;
+}
+
+BOOL isYahoo(char * protoname){
+ if (protoname) {
+ char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ if (pszUniqueSetting){
+ return (!strcmp(pszUniqueSetting,"yahoo_id"));
+ } }
+ return FALSE;
+}
+BOOL isJabber(char * protoname){
+ if (protoname) {
+ char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ if (pszUniqueSetting){
+ return (!strcmp(pszUniqueSetting,"jid"));
+ } }
+ return FALSE;
+}
+BOOL isICQ(char * protoname){
+ if (protoname) {
+ char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ if (pszUniqueSetting){
+ return (!strcmp(pszUniqueSetting,"UIN"));
+ } }
+ return FALSE;
+}
+BOOL isMSN(char * protoname){
+ if (protoname) {
+ char *pszUniqueSetting = (char*)CallProtoService(protoname, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+ if (pszUniqueSetting){
+ return (!strcmp(pszUniqueSetting,"e-mail"));
+ } }
+ return FALSE;
+}
+
+DWORD isSeen(HANDLE hcontact, SYSTEMTIME *st){
+ DWORD res = 0;
+ FILETIME ft;
+ ULONGLONG ll;
+ res = DBGetContactSettingDword(hcontact,S_MOD,"seenTS",0);
+ if (res){
+ if (st) {
+ ll = UInt32x32To64(CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,res,0), 10000000) + NUM100NANOSEC;
+ ft.dwLowDateTime = (DWORD)ll;
+ ft.dwHighDateTime = (DWORD)(ll >> 32);
+ FileTimeToSystemTime(&ft, st);
+ }
+ return res;
+ } else {
+ SYSTEMTIME lst;
+ ZeroMemory(&lst,sizeof(lst));
+ if (lst.wYear = DBGetContactSettingWord(hcontact,S_MOD,"Year",0)) {
+ if (lst.wMonth = DBGetContactSettingWord(hcontact,S_MOD,"Month",0)) {
+ if (lst.wDay = DBGetContactSettingWord(hcontact,S_MOD,"Day",0)) {
+ lst.wDayOfWeek = DBGetContactSettingWord(hcontact,S_MOD,"WeekDay",0);
+ lst.wHour = DBGetContactSettingWord(hcontact,S_MOD,"Hours",0);
+ lst.wMinute = DBGetContactSettingWord(hcontact,S_MOD,"Minutes",0);
+ lst.wSecond = DBGetContactSettingWord(hcontact,S_MOD,"Seconds",0);
+ if (SystemTimeToFileTime(&lst,&ft)){
+ ll = ((LONGLONG)ft.dwHighDateTime<<32)|((LONGLONG)ft.dwLowDateTime);
+ ll -= NUM100NANOSEC;
+ ll /= 10000000;
+ //perform LOCALTOTIMESTAMP
+ res = (DWORD)ll - CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,0,0);
+ //nevel look for Year/Month/Day/Hour/Minute/Second again
+ DBWriteContactSettingDword(hcontact,S_MOD,"seenTS",res);
+ }
+ } } }
+ if (st) CopyMemory (st, &lst, sizeof (SYSTEMTIME));
+ }
+ return res;
+}
+
+char *ParseString(char *szstring,HANDLE hcontact,BYTE isfile)
+{
+#define MAXSIZE 1024
+ static char sztemp[MAXSIZE+1];
+ int sztemplen = 0;
+ char szdbsetting[128]="";
+ char *charPtr;
+ UINT loop=0;
+ int isetting=0;
+ DWORD dwsetting=0;
+ struct in_addr ia;
+ char *weekdays[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
+ char *wdays_short[]={"Sun.","Mon.","Tue.","Wed.","Thu.","Fri.","Sat."};
+ char *monthnames[]={"January","February","March","April","May","June","July","August","September","October","November","December"};
+ char *mnames_short[]={"Jan.","Feb.","Mar.","Apr.","May","Jun.","Jul.","Aug.","Sep.","Oct.","Nov.","Dec."};
+ CONTACTINFO ci;
+ BOOL wantempty;
+ SYSTEMTIME st;
+
+ sztemp[0] = '\0';
+ if (!isSeen(hcontact,&st)){
+ strcat(sztemp,Translate("<never seen>"));
+ return sztemp;
+ }
+
+ ci.cbSize=sizeof(CONTACTINFO);
+ ci.hContact=hcontact;
+ ci.szProto=hcontact?(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hcontact,0):courProtoName;
+ for(;loop<strlen(szstring);loop++)
+ {
+ if (sztemplen == MAXSIZE) break;
+ if((szstring[loop]!='%')&(szstring[loop]!='#'))
+ {
+ strncat(sztemp,szstring+loop,1);
+ sztemplen++;
+ continue;
+ }
+
+ else
+ {
+ wantempty = (szstring[loop]=='#');
+ switch(szstring[++loop]){
+ case 'Y':
+ if (!st.wYear) goto LBL_noData;
+ sztemplen += mir_snprintf(sztemp+sztemplen,MAXSIZE-sztemplen,"%04i",st.wYear);
+ break;
+
+ case 'y':
+ if (!st.wYear) goto LBL_noData;
+ wsprintf(szdbsetting,"%04i",st.wYear);
+ sztemplen += mir_snprintf(sztemp+sztemplen,MAXSIZE-sztemplen,"%s",szdbsetting+2);
+ break;
+
+ case 'm':
+ if (!(isetting=st.wMonth)) goto LBL_noData;
+LBL_2DigNum:
+ sztemplen += mir_snprintf(sztemp+sztemplen,MAXSIZE-sztemplen,"%02i",isetting);
+ break;
+
+ case 'd':
+ if (isetting=st.wDay) goto LBL_2DigNum;
+ else goto LBL_noData;
+
+ case 'W':
+ isetting=st.wDayOfWeek;
+ if(isetting==-1){
+LBL_noData:
+ charPtr = wantempty?"":Translate("<unknown>");
+ goto LBL_charPtr;
+ }
+ charPtr = Translate(weekdays[isetting]);
+LBL_charPtr:
+ sztemplen += mir_snprintf(sztemp+sztemplen,MAXSIZE-sztemplen,"%s",charPtr);
+ break;
+
+ case 'w':
+ isetting=st.wDayOfWeek;
+ if(isetting==-1)goto LBL_noData;
+ charPtr = Translate(wdays_short[isetting]);
+ goto LBL_charPtr;
+
+ case 'E':
+ if(!(isetting=st.wMonth))goto LBL_noData;
+ charPtr = Translate(monthnames[isetting-1]);
+ goto LBL_charPtr;
+
+ case 'e':
+ if(!(isetting=st.wMonth))goto LBL_noData;
+ charPtr = Translate(mnames_short[isetting-1]);
+ goto LBL_charPtr;
+
+ case 'H':
+ if((isetting=st.wHour)==-1)goto LBL_noData;
+ goto LBL_2DigNum;
+
+ case 'h':
+ if((isetting=st.wHour)==-1)goto LBL_noData;
+ if(!isetting) isetting=12;
+ isetting = isetting-((isetting>12)?12:0);
+ goto LBL_2DigNum;
+
+ case 'p':
+ if((isetting=st.wHour)==-1)goto LBL_noData;
+ charPtr = (isetting>=12)?"PM":"AM";
+ goto LBL_charPtr;
+
+ case 'M':
+ if((isetting=st.wMinute)==-1)goto LBL_noData;
+ goto LBL_2DigNum;
+
+ case 'S':
+ if((isetting=st.wHour)==-1)goto LBL_noData;
+ goto LBL_2DigNum;
+
+ case 'n':
+ charPtr = hcontact?(char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hcontact,0):(wantempty?"":"---");
+ goto LBL_charPtr;
+ case 'N':
+ ci.dwFlag=CNF_NICK;
+ if(!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci)){
+ charPtr = ci.pszVal;
+ } else goto LBL_noData;
+ goto LBL_charPtr;
+ case 'G':
+ {
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hcontact,"CList","Group",&dbv)){
+ strcpy(szdbsetting,dbv.pszVal);
+ DBFreeVariant(&dbv);
+ charPtr = szdbsetting;
+ goto LBL_charPtr;
+ } else; //do nothing
+ }
+ break;
+
+ case 'u':
+ ci.dwFlag=CNF_UNIQUEID;
+ if(!CallService(MS_CONTACT_GETCONTACTINFO,(WPARAM)0,(LPARAM)&ci))
+ {
+ switch(ci.type)
+ {
+ case CNFT_BYTE:
+ ltoa(ci.bVal,szdbsetting,10);
+ break;
+ case CNFT_WORD:
+ ltoa(ci.wVal,szdbsetting,10);
+ break;
+ case CNFT_DWORD:
+ ltoa(ci.dVal,szdbsetting,10);
+ break;
+ case CNFT_ASCIIZ:
+ strcpy(szdbsetting,ci.pszVal);
+ break;
+ }
+
+ }
+ else if (ci.szProto != NULL)
+ {
+ if (isYahoo(ci.szProto)) // YAHOO support
+ {
+ DBVARIANT dbv;
+ DBGetContactSetting(hcontact,ci.szProto,"id",&dbv);
+ strcpy(szdbsetting,dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ else if (isJabber(ci.szProto)) // JABBER support
+ {
+ DBVARIANT dbv;
+ if (DBGetContactSetting(hcontact,ci.szProto,"LoginName",&dbv)) goto LBL_noData;
+ strcpy(szdbsetting,dbv.pszVal);
+ DBFreeVariant(&dbv);
+ DBGetContactSetting(hcontact,ci.szProto,"LoginServer",&dbv);
+ strcat(szdbsetting,"@");
+ strcat(szdbsetting,dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else goto LBL_noData;
+ }
+ else goto LBL_noData;
+ charPtr = szdbsetting;
+ goto LBL_charPtr;
+
+ case 's':
+ if (isetting=DBGetContactSettingWord(hcontact,S_MOD,hcontact?"StatusTriger":courProtoName,0)){
+ strcpy(szdbsetting,Translate((const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)(isetting|0x8000),0)));
+ if (!(isetting&0x8000)){
+ strcat(szdbsetting,"/");
+ strcat(szdbsetting,Translate("Idle"));
+ }
+ charPtr = szdbsetting;
+ } else goto LBL_noData;
+ goto LBL_charPtr;
+ case 'T':
+ {
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hcontact,"CList","StatusMsg",&dbv)){
+ sztemplen += mir_snprintf(sztemp+sztemplen,MAXSIZE-sztemplen,"%s",dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else goto LBL_noData;
+ }
+ break;
+ case 'o':
+ if (isetting=DBGetContactSettingWord(hcontact,S_MOD,hcontact?"OldStatus":courProtoName,0)){
+ strcpy(szdbsetting,Translate((const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)isetting,0)));
+ if (includeIdle) if (hcontact) if (DBGetContactSettingByte(hcontact,S_MOD,"OldIdle",0)){
+ strcat(szdbsetting,"/");
+ strcat(szdbsetting,Translate("Idle"));
+ }
+ charPtr = szdbsetting;
+ } else goto LBL_noData;
+ goto LBL_charPtr;
+
+ case 'i':
+ case 'r': if (isJabber(ci.szProto)){
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hcontact,ci.szProto,szstring[loop]=='i'?"Resource":"System",&dbv)){
+ strcpy(szdbsetting,dbv.pszVal);
+ DBFreeVariant(&dbv);
+ charPtr = szdbsetting;
+ } else goto LBL_noData;
+ } else {
+ dwsetting=DBGetContactSettingDword(hcontact,ci.szProto,szstring[loop]=='i'?"IP":"RealIP",0);
+ if(dwsetting){
+ ia.S_un.S_addr=htonl(dwsetting);
+ charPtr = inet_ntoa(ia);
+ } else goto LBL_noData;
+ }
+ goto LBL_charPtr;
+ case 'P':if (ci.szProto) charPtr = ci.szProto; else charPtr = wantempty?"":"ProtoUnknown";
+ goto LBL_charPtr;
+ case 'b':
+ charPtr = /*"\n"*/"\x0D\x0A";
+ goto LBL_charPtr;
+ case 'C': // Get Client Info
+ if (isMSN(ci.szProto)) {
+ if (hcontact) {
+ dwsetting = (int)DBGetContactSettingDword(hcontact,ci.szProto,"FlagBits",0);
+ wsprintf(szdbsetting,"MSNC%i",(dwsetting&0x70000000)>>28);
+ if (dwsetting & 0x00000001) strcat(szdbsetting," MobD"); //Mobile Device
+ if (dwsetting & 0x00000004) strcat(szdbsetting," InkG"); //GIF Ink Send/Receive
+ if (dwsetting & 0x00000008) strcat(szdbsetting," InkI"); //ISF Ink Send/Receive
+ if (dwsetting & 0x00000010) strcat(szdbsetting," WCam"); //Webcam
+ if (dwsetting & 0x00000020) strcat(szdbsetting," MPkt"); //Multi packet messages
+ if (dwsetting & 0x00000040) strcat(szdbsetting," SMSr"); //Paging
+ if (dwsetting & 0x00000080) strcat(szdbsetting," DSMS"); //Using MSN Direct
+ if (dwsetting & 0x00000200) strcat(szdbsetting," WebM"); //WebMessenger
+ if (dwsetting & 0x00001000) strcat(szdbsetting," MS7+"); //Unknown (Msgr 7 always[?] sets it)
+ if (dwsetting & 0x00004000) strcat(szdbsetting," DirM"); //DirectIM
+ if (dwsetting & 0x00008000) strcat(szdbsetting," Wink"); //Send/Receive Winks
+ if (dwsetting & 0x00010000) strcat(szdbsetting," MSrc"); //MSN Search ??
+ if (dwsetting & 0x00040000) strcat(szdbsetting," VoiC"); //Voice Clips
+ } else strcpy(szdbsetting,"Miranda");
+ } else {
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(hcontact,ci.szProto,"MirVer",&dbv)){
+ strcpy(szdbsetting,dbv.pszVal);
+ DBFreeVariant(&dbv);
+ } else goto LBL_noData;
+ }
+ charPtr = szdbsetting;
+ goto LBL_charPtr;
+ case 't':
+ charPtr = "\t";
+ goto LBL_charPtr;
+
+ default:
+ strncpy(szdbsetting,szstring+loop-1,2);
+ goto LBL_charPtr;
+ }
+ }
+ }
+
+ return sztemp;
+}
+
+
+
+void _DBWriteTime(SYSTEMTIME *st,HANDLE hcontact)
+{
+ DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Day",st->wDay);
+ DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Month",st->wMonth);
+ DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Year",st->wYear);
+ DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Hours",st->wHour);
+ DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Minutes",st->wMinute);
+ DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"Seconds",st->wSecond);
+ DBWriteContactSettingWord((HANDLE)hcontact,S_MOD,"WeekDay",st->wDayOfWeek);
+
+}
+
+void DBWriteTimeTS(DWORD t, HANDLE hcontact){
+ SYSTEMTIME st;
+ FILETIME ft;
+ ULONGLONG ll = UInt32x32To64(CallService(MS_DB_TIME_TIMESTAMPTOLOCAL,t,0), 10000000) + NUM100NANOSEC;
+ ft.dwLowDateTime = (DWORD)ll;
+ ft.dwHighDateTime = (DWORD)(ll >> 32);
+ FileTimeToSystemTime(&ft, &st);
+ DBWriteContactSettingDword(hcontact,S_MOD,"seenTS",t);
+ _DBWriteTime(&st, hcontact);
+}
+void GetColorsFromDWord(LPCOLORREF First, LPCOLORREF Second, DWORD colDword){
+ WORD temp;
+ COLORREF res=0;
+ temp = (WORD)(colDword>>16);
+ res |= ((temp & 0x1F) <<3);
+ res |= ((temp & 0x3E0) <<6);
+ res |= ((temp & 0x7C00) <<9);
+ if (First) *First = res;
+ res = 0;
+ temp = (WORD)colDword;
+ res |= ((temp & 0x1F) <<3);
+ res |= ((temp & 0x3E0) <<6);
+ res |= ((temp & 0x7C00) <<9);
+ if (Second) *Second = res;
+}
+
+DWORD StatusColors15bits[] = {
+ 0x63180000, // 0x00C0C0C0, 0x00000000, Offline - LightGray
+ 0x7B350000, // 0x00F0C8A8, 0x00000000, Online - LightBlue
+ 0x33fe0000, // 0x0070E0E0, 0x00000000, Away -LightOrange
+ 0x295C0000, // 0x005050E0, 0x00000000, DND -DarkRed
+ 0x5EFD0000, // 0x00B8B8E8, 0x00000000, NA -LightRed
+ 0x295C0000, // 0x005050E0, 0x00000000, Occupied
+ 0x43900000, // 0x0080E080, 0x00000000, Free for chat - LightGreen
+ 0x76AF0000, // 0x00E8A878, 0x00000000, Invisible
+ 0x431C0000, // 0x0080C0E0, 0x00000000, On the phone
+ 0x5EFD0000, // 0x00B8B8E8, 0x00000000, Out to lunch
+};
+
+DWORD GetDWordFromColors(COLORREF First, COLORREF Second){
+ DWORD res = 0;
+ res |= (First&0xF8)>>3;
+ res |= (First&0xF800)>>6;
+ res |= (First&0xF80000)>>9;
+ res <<= 16;
+ res |= (Second&0xF8)>>3;
+ res |= (Second&0xF800)>>6;
+ res |= (Second&0xF80000)>>9;
+ return res;
+}
+
+LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+
+ switch(message) {
+ case WM_COMMAND:
+ if (HIWORD(wParam) == STN_CLICKED){
+ HANDLE hContact = PUGetContact(hwnd);
+ if (hContact > 0) CallService(MS_MSG_SENDMESSAGE,(WPARAM)hContact,0);
+ }
+ case WM_CONTEXTMENU:
+ PUDeletePopUp(hwnd);
+ break;
+ case UM_INITPOPUP: return 0;
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+};
+
+void ShowPopup(HANDLE hcontact, const char * lpzProto, int newStatus){
+ if(CallService(MS_IGNORE_ISIGNORED,(WPARAM)hcontact,IGNOREEVENT_USERONLINE)) return;
+ if (ServiceExists(MS_POPUP_QUERY)){
+ if (DBGetContactSettingByte(NULL,S_MOD,"UsePopups",0)){
+ if (!DBGetContactSettingByte(hcontact,"CList","Hidden",0)){
+ POPUPDATAEX ppd = {0};
+ DBVARIANT dbv = {0};
+ char szstamp[10];
+ DWORD sett;
+ sprintf(szstamp, "Col_%d",newStatus-ID_STATUS_OFFLINE);
+ sett = DBGetContactSettingDword(NULL,S_MOD,szstamp,StatusColors15bits[newStatus-ID_STATUS_OFFLINE]);
+ GetColorsFromDWord(&ppd.colorBack,&ppd.colorText,sett);
+ ppd.lchContact = hcontact;
+ ppd.lchIcon = LoadSkinnedProtoIcon(lpzProto, newStatus);
+ strncpy(ppd.lpzContactName,ParseString(!DBGetContactSetting(NULL,S_MOD,"PopupStamp",&dbv)?dbv.pszVal:DEFAULT_POPUPSTAMP,hcontact,0),MAX_CONTACTNAME);
+ DBFreeVariant(&dbv);
+ strncpy(ppd.lpzText,ParseString(!DBGetContactSetting(NULL,S_MOD,"PopupStampText",&dbv)?dbv.pszVal:DEFAULT_POPUPSTAMPTEXT,hcontact,0),MAX_SECONDLINE);
+ DBFreeVariant(&dbv);
+ ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+ }
+ }
+ }
+}
+
+void myPlaySound(HANDLE hcontact, WORD newStatus, WORD oldStatus){
+ if(CallService(MS_IGNORE_ISIGNORED,(WPARAM)hcontact,IGNOREEVENT_USERONLINE)) return;
+ //oldStatus and hcontact are not used yet
+ if (DBGetContactSettingByte(NULL,"Skin","UseSound",1)){
+ char * soundname=0;
+ if ((newStatus==ID_STATUS_ONLINE) || (newStatus==ID_STATUS_FREECHAT)) soundname = "LastSeenTrackedStatusOnline";
+ else if (newStatus==ID_STATUS_OFFLINE) soundname = "LastSeenTrackedStatusOffline";
+ else if (oldStatus==ID_STATUS_OFFLINE) soundname = "LastSeenTrackedStatusFromOffline";
+ else soundname = "LastSeenTrackedStatusChange";
+ if (!DBGetContactSettingByte(NULL,"SkinSoundsOff",soundname,0)){
+ DBVARIANT dbv;
+ if (!DBGetContactSetting(NULL,"SkinSounds",soundname,&dbv)){
+ PlaySoundA(dbv.pszVal, NULL, SND_ASYNC | SND_FILENAME | SND_NOWAIT);
+ DBFreeVariant(&dbv);
+} } } }
+
+//will give hContact position or zero
+int isContactQueueActive(HANDLE hContact){
+ int i = 0;
+ if (!hContact) {
+// MessageBox(0,"Is myself in the queue: never","LastSeen-Mod",0);
+ return 0;
+ }
+ for (i=1;i<contactQueueSize;i++){
+ if (contactQueue[i])
+ if (contactQueue[i]->hContact==hContact) return i;
+ }
+ return 0;
+}
+
+//will add hContact to queue and will return position;
+int addContactToQueue(HANDLE hContact){
+ int i = 0;
+ if (!hContact) {
+// MessageBox(0,"Adding myself to queue","LastSeen-Mod",0);
+ return 0;
+ }
+ for (i=1;i<contactQueueSize;i++){
+ if (!contactQueue[i]) {
+ contactQueue[i] = malloc(sizeof(logthread_info));
+ contactQueue[i]->queueIndex = i;
+ contactQueue[i]->hContact = hContact;
+ return i;
+ }
+ }
+ //no free space. Create some
+ //MessageBox(0,"Creating more space","LastSeen-Mod",0);
+ contactQueue = (logthread_info **)realloc(contactQueue,(contactQueueSize+16)*sizeof(logthread_info *));
+ memset(&contactQueue[contactQueueSize],0, 16*sizeof(logthread_info *));
+ i = contactQueueSize;
+ contactQueue[i] = malloc(sizeof(logthread_info));
+ contactQueue[i]->queueIndex = i;
+ contactQueue[i]->hContact = hContact;
+ contactQueueSize += 16;
+ return i;
+}
+
+static DWORD __stdcall waitThread(logthread_info* infoParam)
+{
+// char str[MAXMODULELABELLENGTH];
+// sprintf(str,"In Thread: %s; %s; %s\n",
+// infoParam->sProtoName,
+// (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)infoParam->hContact,0),
+// (const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)infoParam->courStatus,0)
+// );
+// OutputDebugStringA(str);
+ WORD prevStatus = DBGetContactSettingWord(infoParam->hContact,S_MOD,"StatusTriger",ID_STATUS_OFFLINE);
+ Sleep(1500); // I hope in 1.5 second all the needed info will be set
+ if (includeIdle){
+ if (DBGetContactSettingDword(infoParam->hContact,infoParam->sProtoName,"IdleTS",0)) {
+ infoParam->courStatus &=0x7FFF;
+ }
+ }
+ if (infoParam->courStatus != prevStatus){
+ DBWriteContactSettingWord(infoParam->hContact,S_MOD,"OldStatus",(WORD)(prevStatus|0x8000));
+ if (includeIdle){
+ DBWriteContactSettingByte(infoParam->hContact,S_MOD,"OldIdle",(BYTE)((prevStatus&0x8000)==0));
+ }
+ DBWriteContactSettingWord(infoParam->hContact,S_MOD,"StatusTriger",infoParam->courStatus);
+ }
+// sprintf(str,"OutThread: %s; %s; %s\n",
+// infoParam->sProtoName,
+// (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)infoParam->hContact,0),
+// (const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)infoParam->courStatus,0)
+// );
+// infoParam->hContact = 0; //declare the slot as empty
+ contactQueue[infoParam->queueIndex] = 0;
+ free(infoParam);
+// OutputDebugStringA(str);
+ return 0;
+}
+
+#ifndef PERMITNSN
+static int uniqueEventId=0;
+#endif
+
+int UpdateValues(HANDLE hContact,LPARAM lparam)
+{
+ FORK_THREADEX_PARAMS params;
+ DWORD dwThreadId;
+ DBCONTACTWRITESETTING *cws;
+ BOOL isIdleEvent;
+ // to make this code faster
+ if (!hContact) return 0;
+ cws=(DBCONTACTWRITESETTING *)lparam;
+ //if(CallService(MS_IGNORE_ISIGNORED,(WPARAM)hContact,IGNOREEVENT_USERONLINE)) return 0;
+ isIdleEvent = includeIdle?(strcmp(cws->szSetting,"IdleTS")==0):0;
+ if (strcmp(cws->szSetting,"Status") && strcmp(cws->szSetting,"StatusTriger") && (isIdleEvent==0)) return 0;
+ if (!strcmp(cws->szModule,S_MOD)){
+ //here we will come when Settings/SeenModule/StatusTriger is changed
+ WORD prevStatus=DBGetContactSettingWord(hContact,S_MOD,"OldStatus",ID_STATUS_OFFLINE);
+ if (includeIdle){
+ if (DBGetContactSettingByte(hContact,S_MOD,"OldIdle",0)) prevStatus &= 0x7FFF;
+ else prevStatus |= 0x8000;
+ }
+ if((cws->value.wVal|0x8000)<=ID_STATUS_OFFLINE)
+ {
+ char * proto;
+ // avoid repeating the offline status
+ if ((prevStatus|0x8000)<=ID_STATUS_OFFLINE)
+ return 0;
+ proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+ DBWriteContactSettingByte(hContact,S_MOD,"Offline",1);
+ {
+ DWORD t;
+ char *str = malloc(MAXMODULELABELLENGTH+9);
+ mir_snprintf(str,MAXMODULELABELLENGTH+8,"OffTime-%s",proto);
+ t = DBGetContactSettingDword(NULL,S_MOD,str,0);
+ if (!t) t = time(NULL);
+ free(str);
+ DBWriteTimeTS(t,hContact);
+ }
+
+ if(!DBGetContactSettingByte(NULL,S_MOD,"IgnoreOffline",1))
+ {
+ char * sProto;
+ if(DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0))
+ FileWrite(hContact);
+
+ if (CallProtoService(sProto =
+ (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0),
+ PS_GETSTATUS,0,0
+ )>ID_STATUS_OFFLINE) {
+ myPlaySound(hContact,ID_STATUS_OFFLINE,prevStatus);
+ if(DBGetContactSettingByte(NULL,S_MOD,"UsePopups",0)){
+ ShowPopup(hContact,sProto,ID_STATUS_OFFLINE);
+ } }
+
+ if(DBGetContactSettingByte(NULL,S_MOD,"KeepHistory",0))
+ HistoryWrite(hContact);
+
+ if(DBGetContactSettingByte(hContact,S_MOD,"OnlineAlert",0))
+ ShowHistory(hContact, 1);
+ }
+
+ } else {
+
+ if(cws->value.wVal==prevStatus && !DBGetContactSettingByte(hContact,S_MOD,"Offline",0))
+ return 0;
+
+ DBWriteTimeTS(time(NULL),hContact);
+
+ //DBWriteContactSettingWord(hContact,S_MOD,"StatusTriger",(WORD)cws->value.wVal);
+
+ if(DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0)) FileWrite(hContact);
+ if (prevStatus != cws->value.wVal) myPlaySound(hContact,cws->value.wVal,prevStatus);
+ if(DBGetContactSettingByte(NULL,S_MOD,"UsePopups",0))
+ if (prevStatus != cws->value.wVal) ShowPopup(hContact,(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0),cws->value.wVal|0x8000);
+
+ if(DBGetContactSettingByte(NULL,S_MOD,"KeepHistory",0)) HistoryWrite(hContact);
+ if(DBGetContactSettingByte(hContact,S_MOD,"OnlineAlert",0)) ShowHistory(hContact, 1);
+ DBWriteContactSettingByte(hContact,S_MOD,"Offline",0);
+ }
+ } else if (IsWatchedProtocol(cws->szModule)){
+ //here we will come when <User>/<module>/Status is changed or it is idle event and if <module> is watched
+ if (CallProtoService(cws->szModule,PS_GETSTATUS,0,0)>ID_STATUS_OFFLINE){
+ int index;
+ if (!(index = isContactQueueActive(hContact))){
+ index = addContactToQueue(hContact);
+ strncpy(contactQueue[index]->sProtoName,cws->szModule,MAXMODULELABELLENGTH);
+ //forkthreadex(NULL, 0, waitThread, contactQueue[index], 0, 0);
+ params.pFunc = waitThread;
+ params.arg = contactQueue[index];
+ params.iStackSize = 0;
+ params.threadID = &dwThreadId;
+ CallService(MS_SYSTEM_FORK_THREAD_EX, 0, (LPARAM)&params);
+
+
+// } else {
+// MessageBox(0,"Already in contact queue",cws->szModule,0);
+ }
+ contactQueue[index]->courStatus = isIdleEvent?DBGetContactSettingWord(hContact,cws->szModule,"Status",ID_STATUS_OFFLINE):cws->value.wVal;
+ } }
+#ifndef PERMITNSN
+ //Some useronline.c functionality
+ {
+ int newStatus,oldStatus;
+ newStatus=(cws->value.wVal|0x8000);
+ oldStatus=DBGetContactSettingWord(hContact,"UserOnline","OldStatus",ID_STATUS_OFFLINE);
+ DBWriteContactSettingWord(hContact,"UserOnline","OldStatus",(WORD)newStatus);
+ if(DBGetContactSettingByte(hContact,"CList","Hidden",0)) return 0;
+ if((newStatus==ID_STATUS_ONLINE || newStatus==ID_STATUS_FREECHAT) &&
+ oldStatus!=ID_STATUS_ONLINE && oldStatus!=ID_STATUS_FREECHAT) {
+ BYTE supp = db_byte_get(NULL, S_MOD, "SuppCListOnline", 3); //By default no online allert :P
+ BOOL willAlert = FALSE;
+ switch (supp) {
+ case 3: willAlert = FALSE; break;
+ case 2: willAlert = !IsWatchedProtocol(cws->szModule); break;
+ case 1: willAlert = IsWatchedProtocol(cws->szModule); break;
+ case 0: willAlert = TRUE; break;
+ }
+ if (willAlert) {
+ DWORD ticked = db_dword_get(NULL, "UserOnline", cws->szModule, GetTickCount());
+ // only play the sound (or show event) if this event happens at least 10 secs after the proto went from offline
+ if ( GetTickCount() - ticked > (1000*10) ) {
+ CLISTEVENT cle;
+ char tooltip[256];
+
+ ZeroMemory(&cle,sizeof(cle));
+ cle.cbSize=sizeof(cle);
+ cle.flags=CLEF_ONLYAFEW;
+ cle.hContact=hContact;
+ cle.hDbEvent=(HANDLE)(uniqueEventId++);
+ cle.hIcon=LoadSkinnedIcon(SKINICON_OTHER_USERONLINE);
+ cle.pszService="UserOnline/Description";
+ mir_snprintf(tooltip,256,Translate("%s is Online"),(char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0));
+ cle.pszTooltip=tooltip;
+ CallService(MS_CLIST_ADDEVENT,0,(LPARAM)&cle);
+
+ SkinPlaySound("UserOnline");
+ }
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+static DWORD __stdcall cleanThread(logthread_info* infoParam)
+{
+ HANDLE hcontact=NULL;
+// char str[MAXMODULELABELLENGTH];
+// sprintf(str,"In Clean: %s; %s; %s\n",
+// infoParam->sProtoName,
+// (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)infoParam->hContact,0),
+// (const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)infoParam->courStatus,0)
+// );
+// OutputDebugStringA(str);
+ Sleep(10000); // I hope in 10 secons all logged-in contacts will be listed
+ //Searching for contact marked as online but now are offline
+
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hcontact!=NULL)
+ {
+ char * contactProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hcontact,0);
+ if (contactProto) {
+ if (!strncmp(infoParam->sProtoName,contactProto,MAXMODULELABELLENGTH)){
+ WORD oldStatus;
+ if ( (oldStatus = (DBGetContactSettingWord(hcontact,S_MOD,"StatusTriger",ID_STATUS_OFFLINE))|0x8000)>ID_STATUS_OFFLINE){
+ if (DBGetContactSettingWord(hcontact,contactProto,"Status",ID_STATUS_OFFLINE)==ID_STATUS_OFFLINE){
+ DBWriteContactSettingWord(hcontact,S_MOD,"OldStatus",(WORD)(oldStatus|0x8000));
+ if (includeIdle)DBWriteContactSettingByte(hcontact,S_MOD,"OldIdle",(BYTE)((oldStatus&0x8000)?0:1));
+ DBWriteContactSettingWord(hcontact,S_MOD,"StatusTriger",ID_STATUS_OFFLINE);
+ }
+ }
+ }
+ }
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hcontact,0);
+ }
+
+// sprintf(str,"OutClean: %s; %s; %s\n",
+// infoParam->sProtoName,
+// (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)infoParam->hContact,0),
+// (const char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)infoParam->courStatus,0)
+// );
+ {
+ char *str = malloc(MAXMODULELABELLENGTH+9);
+ mir_snprintf(str,MAXMODULELABELLENGTH+8,"OffTime-%s",infoParam->sProtoName);
+ DBDeleteContactSetting(NULL,S_MOD,str);
+ free(str);
+ }
+ free(infoParam);
+// OutputDebugStringA(str);
+ return 0;
+}
+
+
+int ModeChange(WPARAM wparam,LPARAM lparam)
+{
+ ACKDATA *ack;
+ WORD isetting=0;
+ FORK_THREADEX_PARAMS params;
+ DWORD dwThreadId;
+
+ ack=(ACKDATA *)lparam;
+
+ if(ack->type!=ACKTYPE_STATUS || ack->result!=ACKRESULT_SUCCESS || ack->hContact!=NULL) return 0;
+ courProtoName = (char *)ack->szModule;
+ if (!IsWatchedProtocol(courProtoName) && strncmp(courProtoName,"MetaContacts",12))
+ {
+ //MessageBox(NULL,"Protocol not watched",courProtoName,0);
+ return 0;
+ }
+
+ DBWriteTimeTS(time(NULL),NULL);
+
+// isetting=CallProtoService(ack->szModule,PS_GETSTATUS,0,0);
+ isetting=(WORD)ack->lParam;
+ if (isetting<ID_STATUS_OFFLINE) isetting = ID_STATUS_OFFLINE;
+ if ((isetting>ID_STATUS_OFFLINE)&&((WORD)ack->hProcess<=ID_STATUS_OFFLINE)){
+ //we have just loged-in
+ db_dword_set(NULL, "UserOnline", ack->szModule, GetTickCount());
+ if (IsWatchedProtocol(ack->szModule)){
+ logthread_info *info;
+ info = (logthread_info *)malloc(sizeof(logthread_info));
+ strncpy(info->sProtoName,courProtoName,MAXMODULELABELLENGTH);
+ info->hContact = 0;
+ info->courStatus = 0;
+ //forkthreadex(NULL, 0, cleanThread, info, 0, 0);
+ params.pFunc = cleanThread;
+ params.arg = info;
+ params.iStackSize = 0;
+ params.threadID = &dwThreadId;
+ CallService(MS_SYSTEM_FORK_THREAD_EX, 0, (LPARAM)&params);
+
+ }
+ } else if ((isetting==ID_STATUS_OFFLINE)&&((WORD)ack->hProcess>ID_STATUS_OFFLINE)){
+ //we have just loged-off
+ if (IsWatchedProtocol(ack->szModule)){
+ char *str = malloc(MAXMODULELABELLENGTH+9);
+ time_t t;
+ time(&t);
+ mir_snprintf(str,MAXMODULELABELLENGTH+8,"OffTime-%s",ack->szModule);
+ DBWriteContactSettingDword(NULL,S_MOD,str,t);
+ free(str);
+ } }
+ if (isetting==DBGetContactSettingWord(NULL,S_MOD,courProtoName,ID_STATUS_OFFLINE)) return 0;
+ DBWriteContactSettingWord(NULL,S_MOD,courProtoName,isetting);
+
+ // log "myself"
+ if(DBGetContactSettingByte(NULL,S_MOD,"FileOutput",0))
+ FileWrite(NULL);
+
+// if(isetting==ID_STATUS_OFFLINE) //this is removed 'cause I want other contacts to be logged only if the status changed while I was offline
+// SetOffline();
+
+ courProtoName = NULL;
+
+ return 0;
+}
+
+short int isDbZero(HANDLE hContact, const char *module_name, const char *setting_name){
+ DBVARIANT dbv;
+ if(!DBGetContactSetting(hContact, module_name, setting_name, &dbv)) {
+ short int res = 0;
+ switch (dbv.type) {
+ case DBVT_BYTE: res=dbv.bVal==0; break;
+ case DBVT_WORD: res=dbv.wVal==0; break;
+ case DBVT_DWORD: res=dbv.dVal==0; break;
+ case DBVT_BLOB: res=dbv.cpbVal==0; break;
+ default: res=dbv.pszVal[0]==0; break;
+ }
+ DBFreeVariant(&dbv);
+ return res;
+ } else return -1;
+}
+
+WCHAR *any_to_IdleNotidleUnknown(HANDLE hContact, const char *module_name, const char *setting_name, WCHAR *buff, int bufflen) {
+ short int r = isDbZero(hContact, module_name, setting_name);
+ if (r==-1){
+ wcsncpy(buff, TranslateW(L"Unknown"), bufflen);
+ } else {
+ wcsncpy(buff, TranslateW(r?L"Not Idle":L"Idle"), bufflen);
+ };
+ buff[bufflen - 1] = 0;
+ return buff;
+}
+WCHAR *any_to_Idle(HANDLE hContact, const char *module_name, const char *setting_name, WCHAR *buff, int bufflen) {
+ if(isDbZero(hContact, module_name, setting_name)==0) { //DB setting is NOT zero and exists
+ buff[0] = L'/';
+ wcsncpy((WCHAR *)&buff[1], TranslateW(L"Idle"), bufflen-1);
+ } else buff[0] = 0;
+ buff[bufflen - 1] = 0;
+ return buff;
+}
+
+
+/*int GetInfoAck(WPARAM wparam,LPARAM lparam)
+{
+ ACKDATA *ack;
+ DWORD dwsetting=0;
+
+ ack=(ACKDATA *)lparam;
+
+ if(ack->type!=ACKTYPE_GETINFO || ack->hContact==NULL) return 0;
+ if(((int)ack->hProcess-1)!=(int)ack->lParam) return 0;
+
+ dwsetting=DBGetContactSettingDword(ack->hContact,ack->szModule,"IP",0);
+ if(dwsetting)
+ DBWriteContactSettingDword(ack->hContact,S_MOD,"IP",dwsetting);
+
+ dwsetting=DBGetContactSettingDword(ack->hContact,ack->szModule,"RealIP",0);
+ if(dwsetting)
+ DBWriteContactSettingDword(ack->hContact,S_MOD,"RealIP",dwsetting);
+
+ return 0;
+}*/
+
+
+
+/*void SetOffline(void)
+{
+ HANDLE hcontact=NULL;
+ char * szProto;
+
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hcontact!=NULL)
+ {
+ szProto=(char *)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hcontact,0);
+ if (szProto != NULL && IsWatchedProtocol(szProto)) {
+ DBWriteContactSettingByte(hcontact,S_MOD,"Offline",1);
+ }
+ hcontact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hcontact,0);
+ }
+}*/
+
+
+