From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/src/modules/srawaymsg/sendmsg.c | 414 +++++++++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 miranda-wine/src/modules/srawaymsg/sendmsg.c (limited to 'miranda-wine/src/modules/srawaymsg/sendmsg.c') diff --git a/miranda-wine/src/modules/srawaymsg/sendmsg.c b/miranda-wine/src/modules/srawaymsg/sendmsg.c new file mode 100644 index 0000000..83d8aa1 --- /dev/null +++ b/miranda-wine/src/modules/srawaymsg/sendmsg.c @@ -0,0 +1,414 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" + +static DWORD protoModeMsgFlags; + +static char *GetDefaultMessage(int status) +{ + switch(status) { + case ID_STATUS_AWAY: return Translate("I've been away since %time%."); + case ID_STATUS_NA: return Translate("Give it up, I'm not in!"); + case ID_STATUS_OCCUPIED: return Translate("Not right now."); + case ID_STATUS_DND: return Translate("Give a guy some peace, would ya?"); + case ID_STATUS_FREECHAT: return Translate("I'm a chatbot!"); + case ID_STATUS_ONLINE: return Translate("Yep, I'm here."); + case ID_STATUS_OFFLINE: return Translate("Nope, not here."); + case ID_STATUS_INVISIBLE: return Translate("I'm hiding from the mafia."); + case ID_STATUS_ONTHEPHONE: return Translate("That'll be the phone."); + case ID_STATUS_OUTTOLUNCH: return Translate("Mmm...food."); + case ID_STATUS_IDLE: return Translate("idleeeeeeee"); + } + return NULL; +} + +static char *StatusModeToDbSetting(int status,const char *suffix) +{ + char *prefix; + static char str[64]; + + switch(status) { + case ID_STATUS_AWAY: prefix="Away"; break; + case ID_STATUS_NA: prefix="Na"; break; + case ID_STATUS_DND: prefix="Dnd"; break; + case ID_STATUS_OCCUPIED: prefix="Occupied"; break; + case ID_STATUS_FREECHAT: prefix="FreeChat"; break; + case ID_STATUS_ONLINE: prefix="On"; break; + case ID_STATUS_OFFLINE: prefix="Off"; break; + case ID_STATUS_INVISIBLE: prefix="Inv"; break; + case ID_STATUS_ONTHEPHONE: prefix="Otp"; break; + case ID_STATUS_OUTTOLUNCH: prefix="Otl"; break; + case ID_STATUS_IDLE: prefix="Idl"; break; + default: return NULL; + } + lstrcpyA(str,prefix); lstrcatA(str,suffix); + return str; +} + +//remember to mir_free() the return value +static int GetAwayMessage(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + int statusMode = (int)wParam; + + if(DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(wParam,"Ignore"),0)) { + return (int)NULL; + } + if(DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(statusMode,"UsePrev"),0)) { + if(DBGetContactSetting(NULL,"SRAway",StatusModeToDbSetting(statusMode,"Msg"),&dbv)) + dbv.pszVal=mir_strdup(GetDefaultMessage(statusMode)); + } + else { + int i; + char substituteStr[128]; + if(DBGetContactSetting(NULL,"SRAway",StatusModeToDbSetting(statusMode,"Default"),&dbv)) + dbv.pszVal=mir_strdup(GetDefaultMessage(statusMode)); + for(i=0;dbv.pszVal[i];i++) { + if(dbv.pszVal[i]!='%') continue; + if(!_strnicmp(dbv.pszVal+i,"%time%",6)) + GetTimeFormatA(LOCALE_USER_DEFAULT,TIME_NOSECONDS,NULL,NULL,substituteStr,SIZEOF(substituteStr)); + else if(!_strnicmp(dbv.pszVal+i,"%date%",6)) + GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,NULL,NULL,substituteStr,SIZEOF(substituteStr)); + else continue; + if(lstrlenA(substituteStr)>6) dbv.pszVal=(char*)mir_realloc(dbv.pszVal,lstrlenA(dbv.pszVal)+1+lstrlenA(substituteStr)-6); + MoveMemory(dbv.pszVal+i+lstrlenA(substituteStr),dbv.pszVal+i+6,lstrlenA(dbv.pszVal)-i-5); + CopyMemory(dbv.pszVal+i,substituteStr,lstrlenA(substituteStr)); + } + } + return (int)dbv.pszVal; +} + +static WNDPROC OldMessageEditProc; + +static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) +{ + switch(msg) { + case WM_CHAR: + if(wParam=='\n' && GetKeyState(VK_CONTROL)&0x8000) { + PostMessage(GetParent(hwnd),WM_COMMAND,IDOK,0); + return 0; + } + if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-a + SendMessage(hwnd, EM_SETSEL, 0, -1); + return 0; + } + if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w + SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return 0; + } + if (wParam == 127 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-backspace + DWORD start, end; + TCHAR *text; + int textLen; + SendMessage(hwnd, EM_GETSEL, (WPARAM) & end, (LPARAM) (PDWORD) NULL); + SendMessage(hwnd, WM_KEYDOWN, VK_LEFT, 0); + SendMessage(hwnd, EM_GETSEL, (WPARAM) & start, (LPARAM) (PDWORD) NULL); + textLen = GetWindowTextLength(hwnd); + text = (TCHAR *) mir_alloc(sizeof(TCHAR) * (textLen + 1)); + GetWindowText(hwnd, text, textLen + 1); + MoveMemory(text + start, text + end, sizeof(TCHAR) * (textLen + 1 - end)); + SetWindowText(hwnd, text); + mir_free(text); + SendMessage(hwnd, EM_SETSEL, start, start); + SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd); + return 0; + } + break; + } + return CallWindowProc(OldMessageEditProc,hwnd,msg,wParam,lParam); +} + +void ChangeAllProtoMessages(char *szProto, int statusMode,char *msg) +{ + int protoCount,i; + PROTOCOLDESCRIPTOR **proto; + + CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&protoCount,(LPARAM)&proto); + if (szProto) CallProtoService(szProto,PS_SETAWAYMSG,statusMode,(LPARAM)msg); + else { + for(i=0;iszName,PS_GETCAPS,PFLAGNUM_1,0)&PF1_MODEMSGSEND) + CallProtoService(proto[i]->szName,PS_SETAWAYMSG,statusMode,(LPARAM)msg); + } + } +} + +struct SetAwayMsgData { + int statusMode; + int countdown; + char okButtonFormat[64]; + char *szProto; + HANDLE hPreshutdown; +}; +struct SetAwasMsgNewData { + char *szProto; + int statusMode; +}; + +#define DM_SRAWAY_SHUTDOWN WM_USER+10 + +static BOOL CALLBACK SetAwayMsgDlgProc(HWND hwndDlg,UINT message,WPARAM wParam,LPARAM lParam) +{ + struct SetAwayMsgData *dat; + + dat=(struct SetAwayMsgData*)GetWindowLong(hwndDlg,GWL_USERDATA); + switch(message) { + case WM_INITDIALOG: + { + struct SetAwasMsgNewData *newdat = (struct SetAwasMsgNewData*)lParam; + TranslateDialogDefault(hwndDlg); + dat=(struct SetAwayMsgData*)mir_alloc(sizeof(struct SetAwayMsgData)); + SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat); + dat->statusMode=newdat->statusMode; + dat->szProto=newdat->szProto; + mir_free(newdat); + SendDlgItemMessage(hwndDlg,IDC_MSG,EM_LIMITTEXT,1024,0); + OldMessageEditProc=(WNDPROC)SetWindowLong(GetDlgItem(hwndDlg,IDC_MSG),GWL_WNDPROC,(LONG)MessageEditSubclassProc); + { char str[256],format[128]; + GetWindowTextA(hwndDlg,format,SIZEOF(format)); + mir_snprintf(str,SIZEOF(str),format,(char*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,dat->statusMode,0)); + SetWindowTextA(hwndDlg,str); + } + GetDlgItemTextA(hwndDlg,IDOK,dat->okButtonFormat,SIZEOF(dat->okButtonFormat)); + { char *msg=(char*)GetAwayMessage((WPARAM)dat->statusMode,0); + SetDlgItemTextA(hwndDlg,IDC_MSG,msg); + mir_free(msg); + } + dat->countdown=5; + SendMessage(hwndDlg,WM_TIMER,0,0); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedProtoIcon(dat->szProto, dat->statusMode)); + SetTimer(hwndDlg,1,1000,0); + dat->hPreshutdown=HookEventMessage(ME_SYSTEM_PRESHUTDOWN,hwndDlg,DM_SRAWAY_SHUTDOWN); + return TRUE; + } + case WM_TIMER: + if(dat->countdown==-1) {DestroyWindow(hwndDlg); break;} + { char str[64]; + mir_snprintf(str,SIZEOF(str),dat->okButtonFormat,dat->countdown); + SetDlgItemTextA(hwndDlg,IDOK,str); + } + dat->countdown--; + break; + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + case IDC_MSG: + KillTimer(hwndDlg,1); + SetDlgItemText(hwndDlg,IDOK,TranslateT("OK")); + break; + } + break; + case DM_SRAWAY_SHUTDOWN: + DestroyWindow(hwndDlg); + break; + case WM_DESTROY: + { char str[1024]; + GetDlgItemTextA(hwndDlg,IDC_MSG,str,SIZEOF(str)); + ChangeAllProtoMessages(dat->szProto,dat->statusMode,str); + DBWriteContactSettingString(NULL,"SRAway",StatusModeToDbSetting(dat->statusMode,"Msg"),str); + } + SetWindowLong(GetDlgItem(hwndDlg,IDC_MSG),GWL_WNDPROC,(LONG)OldMessageEditProc); + mir_free(dat); + break; + } + return FALSE; +} + +static int StatusModeChange(WPARAM wParam,LPARAM lParam) +{ + BOOL bScreenSaverRunning=FALSE; + char *szProto = (char*)lParam; + + // If its a global change check the complete PFLAGNUM_3 flags to see if a popup might be needed + if(!szProto) { + if(!(protoModeMsgFlags&Proto_Status2Flag(wParam))) + return 0; + } + // If its a single protocol check the PFLAGNUM_3 for the single protocol + else if (!(CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_1,0)&PF1_MODEMSGSEND)||!(CallProtoService(szProto,PS_GETCAPS,PFLAGNUM_3,0)&Proto_Status2Flag(wParam))) + return 0; + SystemParametersInfo(SPI_GETSCREENSAVERRUNNING,0,&bScreenSaverRunning,FALSE); + if(DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(wParam,"Ignore"),0)) { + ChangeAllProtoMessages((char*)lParam,wParam,NULL); + } + else if(bScreenSaverRunning || DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(wParam,"NoDlg"),0)) { + char *msg=(char*)GetAwayMessage(wParam, 0); + ChangeAllProtoMessages((char*)lParam,wParam,msg); + mir_free(msg); + } + else { + struct SetAwasMsgNewData *newdat = (struct SetAwasMsgNewData*)mir_alloc(sizeof(struct SetAwasMsgNewData)); + newdat->szProto = (char*)lParam; + newdat->statusMode = (int)wParam; + CreateDialogParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_SETAWAYMSG),NULL,SetAwayMsgDlgProc,(LPARAM)newdat); + } + return 0; +} + +static int statusModes[]={ID_STATUS_OFFLINE,ID_STATUS_ONLINE,ID_STATUS_AWAY,ID_STATUS_NA,ID_STATUS_OCCUPIED,ID_STATUS_DND,ID_STATUS_FREECHAT,ID_STATUS_INVISIBLE,ID_STATUS_OUTTOLUNCH,ID_STATUS_ONTHEPHONE, ID_STATUS_IDLE}; + +struct AwayMsgInfo { + int ignore; + int noDialog; + int usePrevious; + char msg[1024]; +}; +struct AwayMsgDlgData { + struct AwayMsgInfo info[ SIZEOF(statusModes) ]; + int oldPage; +}; +static BOOL CALLBACK DlgProcAwayMsgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct AwayMsgDlgData *dat; + + dat=(struct AwayMsgDlgData*)GetWindowLong(hwndDlg,GWL_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { int i,j; + DBVARIANT dbv; + TranslateDialogDefault(hwndDlg); + dat=(struct AwayMsgDlgData*)mir_alloc(sizeof(struct AwayMsgDlgData)); + SetWindowLong(hwndDlg,GWL_USERDATA,(LONG)dat); + dat->oldPage=-1; + for( i=0; i < SIZEOF(statusModes); i++ ) { + if(!(protoModeMsgFlags&Proto_Status2Flag(statusModes[i]))) continue; + { TCHAR* ptszDescr = LangPackPcharToTchar(( LPCSTR )CallService( MS_CLIST_GETSTATUSMODEDESCRIPTION, statusModes[i], 0 )); + j = SendDlgItemMessage( hwndDlg, IDC_STATUS, CB_ADDSTRING, 0, (LPARAM)ptszDescr ); + mir_free( ptszDescr ); + } + SendDlgItemMessage(hwndDlg,IDC_STATUS,CB_SETITEMDATA,j,statusModes[i]); + dat->info[j].ignore=DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(statusModes[i],"Ignore"),0); + dat->info[j].noDialog=DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(statusModes[i],"NoDlg"),0); + dat->info[j].usePrevious=DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(statusModes[i],"UsePrev"),0); + if(DBGetContactSetting(NULL,"SRAway",StatusModeToDbSetting(statusModes[i],"Default"),&dbv)) + if(DBGetContactSetting(NULL,"SRAway",StatusModeToDbSetting(statusModes[i],"Msg"),&dbv)) + dbv.pszVal=mir_strdup(GetDefaultMessage(statusModes[i])); + lstrcpyA(dat->info[j].msg,dbv.pszVal); + mir_free(dbv.pszVal); + } + SendDlgItemMessage(hwndDlg,IDC_STATUS,CB_SETCURSEL,0,0); + SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_STATUS,CBN_SELCHANGE),0); + return TRUE; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_STATUS: + if(HIWORD(wParam)==CBN_SELCHANGE) { + int i=SendDlgItemMessage(hwndDlg,IDC_STATUS,CB_GETCURSEL,0,0); + if(dat->oldPage!=-1) { + dat->info[dat->oldPage].ignore=IsDlgButtonChecked(hwndDlg,IDC_DONTREPLY); + dat->info[dat->oldPage].noDialog=IsDlgButtonChecked(hwndDlg,IDC_NODIALOG); + dat->info[dat->oldPage].usePrevious=IsDlgButtonChecked(hwndDlg,IDC_USEPREVIOUS); + GetDlgItemTextA(hwndDlg,IDC_MSG,dat->info[dat->oldPage].msg,SIZEOF(dat->info[dat->oldPage].msg)); + } + CheckDlgButton(hwndDlg,IDC_DONTREPLY,i<0?0:dat->info[i].ignore); + CheckDlgButton(hwndDlg,IDC_NODIALOG,i<0?0:dat->info[i].noDialog); + CheckDlgButton(hwndDlg,IDC_USEPREVIOUS,i<0?0:dat->info[i].usePrevious); + CheckDlgButton(hwndDlg,IDC_USESPECIFIC,i<0?0:!dat->info[i].usePrevious); + SetDlgItemTextA(hwndDlg,IDC_MSG,i<0?"":dat->info[i].msg); + EnableWindow(GetDlgItem(hwndDlg,IDC_NODIALOG),i<0?0:!dat->info[i].ignore); + EnableWindow(GetDlgItem(hwndDlg,IDC_USEPREVIOUS),i<0?0:!dat->info[i].ignore); + EnableWindow(GetDlgItem(hwndDlg,IDC_USESPECIFIC),i<0?0:!dat->info[i].ignore); + EnableWindow(GetDlgItem(hwndDlg,IDC_MSG),i<0?0:!(dat->info[i].ignore || dat->info[i].usePrevious)); + dat->oldPage=i; + } + return 0; + case IDC_DONTREPLY: + case IDC_USEPREVIOUS: + case IDC_USESPECIFIC: + SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_STATUS,CBN_SELCHANGE),0); + break; + case IDC_MSG: + if(HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()) return 0; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch(((LPNMHDR)lParam)->code) { + case PSN_APPLY: + { int i,status; + SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_STATUS,CBN_SELCHANGE),0); + for(i=SendDlgItemMessage(hwndDlg,IDC_STATUS,CB_GETCOUNT,0,0)-1;i>=0;i--) { + status=SendDlgItemMessage(hwndDlg,IDC_STATUS,CB_GETITEMDATA,i,0); + DBWriteContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(status,"Ignore"),(BYTE)dat->info[i].ignore); + DBWriteContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(status,"NoDlg"),(BYTE)dat->info[i].noDialog); + DBWriteContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(status,"UsePrev"),(BYTE)dat->info[i].usePrevious); + DBWriteContactSettingString(NULL,"SRAway",StatusModeToDbSetting(status,"Default"),dat->info[i].msg); + } + return TRUE; + } + } + break; + } + break; + case WM_DESTROY: + mir_free(dat); + break; + } + return FALSE; +} + +static int AwayMsgOptInitialise(WPARAM wParam,LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = 870000000; + odp.hInstance = GetModuleHandle(NULL); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AWAYMSG); + odp.pszTitle = "Status Messages"; + odp.pszGroup = "Status"; + odp.pfnDlgProc = DlgProcAwayMsgOpts; + odp.flags = ODPF_BOLDGROUPS; + CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp ); + return 0; +} + +static int AwayMsgSendModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + int i,protoCount; + PROTOCOLDESCRIPTOR **proto; + + protoModeMsgFlags=0; + CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&protoCount,(LPARAM)&proto); + for(i=0;iszName,PS_GETCAPS,PFLAGNUM_3,0); + if(protoModeMsgFlags) { + HookEvent(ME_CLIST_STATUSMODECHANGE,StatusModeChange); + HookEvent(ME_OPT_INITIALISE,AwayMsgOptInitialise); + } + return 0; +} + +int LoadAwayMessageSending(void) +{ + HookEvent(ME_SYSTEM_MODULESLOADED,AwayMsgSendModulesLoaded); + CreateServiceFunction(MS_AWAYMSG_GETSTATUSMSG, GetAwayMessage); + return 0; +} -- cgit v1.2.3