summaryrefslogtreecommitdiff
path: root/worldtime_protocol/worldtimeproto.cpp
diff options
context:
space:
mode:
authorsje <sje@4f64403b-2f21-0410-a795-97e2b3489a10>2006-11-01 14:57:42 +0000
committersje <sje@4f64403b-2f21-0410-a795-97e2b3489a10>2006-11-01 14:57:42 +0000
commitd513db102812c5dd83f94084e979bb7e24345498 (patch)
tree29f599f98d2d5fb01d0e1dcb58077459ea609961 /worldtime_protocol/worldtimeproto.cpp
parent610f48f080c6ae8c298a032cd92bb2ca9948aded (diff)
git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@24 4f64403b-2f21-0410-a795-97e2b3489a10
Diffstat (limited to 'worldtime_protocol/worldtimeproto.cpp')
-rw-r--r--worldtime_protocol/worldtimeproto.cpp456
1 files changed, 456 insertions, 0 deletions
diff --git a/worldtime_protocol/worldtimeproto.cpp b/worldtime_protocol/worldtimeproto.cpp
new file mode 100644
index 0000000..657c6ea
--- /dev/null
+++ b/worldtime_protocol/worldtimeproto.cpp
@@ -0,0 +1,456 @@
+#include "common.h"
+#include "worldtimeproto.h"
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+
+HANDLE hContactDblClick = 0;
+HANDLE hMenuEdit;
+
+int previousMode,
+ mcStatus = ID_STATUS_OFFLINE;
+
+UINT id_timer = 0;
+
+// protocol related services
+int GetCaps(WPARAM wParam,LPARAM lParam)
+{
+ int ret = 0;
+ switch (wParam) {
+ case PFLAGNUM_1:
+ break;
+ case PFLAGNUM_2:
+ if(!hide_proto)
+ ret = PF2_ONLINE | PF2_LONGAWAY;
+ break;
+ case PFLAGNUM_3:
+ if(!hide_proto)
+ ret = PF2_ONLINE | PF2_LONGAWAY;
+ break;
+ case PFLAGNUM_4:
+ break;
+ case PFLAG_UNIQUEIDTEXT:
+ ret = (int) Translate(PROTO);
+ break;
+ case PFLAG_MAXLENOFMESSAGE:
+ ret = 2000;
+ break;
+ case PFLAG_UNIQUEIDSETTING:
+ ret = (int) "Nick";
+ break;
+ }
+ return ret;
+}
+
+/** Copy the name of the protocole into lParam
+* @param wParam : max size of the name
+* @param lParam : reference to a char *, which will hold the name
+*/
+int GetName(WPARAM wParam,LPARAM lParam)
+{
+ char *name = (char *)Translate(PROTO);
+ size_t size = min(strlen(name),wParam-1); // copy only the first size bytes.
+ if(strncpy((char *)lParam,name,size)==NULL)
+ return 1;
+ ((char *)lParam)[size]='\0';
+ return 0;
+}
+
+/** Loads the icon corresponding to the status
+* Called by the CList when the status changes.
+* @param wParam : one of the following values : \n
+ <tt>PLI_PROTOCOL | PLI_ONLINE | PLI_OFFLINE</tt>
+* @return an \c HICON in which the icon has been loaded.
+*/
+int LoadIcon(WPARAM wParam,LPARAM lParam)
+{
+
+ UINT id;
+ switch (wParam & 0xFFFF)
+ {
+ case PLI_PROTOCOL:
+ id = IDI_ICON_PROTO;
+ break;
+ case PLI_ONLINE:
+ id = IDI_ICON_PROTO;
+ break;
+ case PLI_OFFLINE:
+ id = IDI_ICON_PROTO;
+ break;
+ default:
+ return (int) (HICON) NULL;
+ }
+
+ return (int) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON,
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON),
+ GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0);
+ return 0;
+}
+
+
+/** Changes the status and notifies everybody
+* @param wParam : The new mode
+* @param lParam : Allways set to 0.
+*/
+int SetStatus(WPARAM wParam,LPARAM lParam)
+{
+ previousMode = mcStatus;
+ mcStatus = (int)wParam;
+ ProtoBroadcastAck(PROTO,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS, (HANDLE)previousMode, mcStatus);
+
+ return 0;
+}
+
+/** Returns the current status
+*/
+int GetStatus(WPARAM wParam,LPARAM lParam)
+{
+ return mcStatus;
+}
+
+// plugin stuff
+PLUGININFO pluginInfo={
+ sizeof(PLUGININFO),
+ "World Time Protocol",
+ PLUGIN_MAKE_VERSION(0, 0, 6, 0),
+ "Adds 'contacts' showing the time at specified locations around the world.",
+ "Scott Ellis",
+ "mail@scottellis.com.au",
+ "© 2005 Scott Ellis",
+ "http://www.scottellis.com.au/",
+ 0, //not transient
+ 0 //doesn't replace anything built-in
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst=hinstDLL;
+ return TRUE;
+}
+
+extern "C" WORLDTIMEPROTO_API PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+
+int ContactDblClick(WPARAM wParam, LPARAM lParam) {
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if(proto && strcmp(proto, PROTO) == 0)
+ show_time((HANDLE)wParam);
+ return 0;
+}
+
+//////////////////////////////////////////////////////////
+/// Copied from MSN plugin - sent acks need to be from different thread :(
+//////////////////////////////////////////////////////////
+typedef struct tag_TFakeAckParams
+{
+ HANDLE hEvent;
+ HANDLE hContact;
+} TFakeAckParams;
+
+
+static DWORD CALLBACK sttFakeAckInfoSuccess( LPVOID param )
+{
+ TFakeAckParams *tParam = ( TFakeAckParams* )param;
+ WaitForSingleObject( tParam->hEvent, INFINITE );
+
+ Sleep( 100 );
+ ProtoBroadcastAck(PROTO, tParam->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, ( HANDLE )1, 0 );
+
+ CloseHandle( tParam->hEvent );
+ free(tParam);
+ return 0;
+}
+
+int GetInfo(WPARAM wParam, LPARAM lParam) {
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ DWORD dwThreadId;
+ HANDLE hEvent;
+ TFakeAckParams *tfap;
+
+ hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+
+ tfap = (TFakeAckParams *)malloc(sizeof(TFakeAckParams));
+ tfap->hContact = ccs->hContact;
+ tfap->hEvent = hEvent;
+
+ CloseHandle( CreateThread( NULL, 0, sttFakeAckInfoSuccess, tfap, 0, &dwThreadId ));
+ SetEvent( hEvent );
+
+ return 0;
+}
+
+int EditContact(WPARAM wParam, LPARAM lParam) {
+ LISTITEM pa;
+ HWND hwndList = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+ DBVARIANT dbv;
+
+ pa.hContact = (HANDLE)wParam;
+ pa.timezone_list_index = DBGetContactSettingDword(pa.hContact, PROTO, "TimezoneListIndex", -1);
+ if(!DBGetContactSetting(pa.hContact, PROTO, "Nick", &dbv)) {
+ strncpy(pa.pszText, dbv.pszVal, MAX_NAME_LENGTH);
+ DBFreeVariant(&dbv);
+ }
+ add_edit_item = pa;
+ if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG2), hwndList, DlgProcOptsEdit) == IDOK) {
+ pa = add_edit_item;
+
+ DBWriteContactSettingString(pa.hContact, PROTO, "Nick", pa.pszText);
+ DBWriteContactSettingDword(pa.hContact, PROTO, "TimezoneListIndex", pa.timezone_list_index);
+ DBWriteContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_ONLINE);
+ return 0;
+ }
+ return 1;
+}
+
+HANDLE hServices[7];
+
+void CreatePluginServices() {
+ // protocol
+ hServices[0] = CreateProtoServiceFunction(PROTO,PS_GETCAPS, GetCaps);
+ hServices[1] = CreateProtoServiceFunction(PROTO,PS_GETNAME, GetName);
+ hServices[2] = CreateProtoServiceFunction(PROTO,PS_SETSTATUS, SetStatus);
+ hServices[3] = CreateProtoServiceFunction(PROTO,PS_GETSTATUS, GetStatus);
+ hServices[4] = CreateProtoServiceFunction(PROTO,PS_LOADICON,LoadIcon);
+ hServices[5] = CreateProtoServiceFunction(PROTO,PSS_GETINFO,GetInfo);
+
+ // menu
+ hServices[6] = CreateServiceFunction(PROTO "/Edit", EditContact);
+}
+
+void DestroyServiceFunctions() {
+ for(int i = 0; i < 7; i++)
+ DestroyServiceFunction(hServices[i]);
+}
+
+VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
+ SYSTEMTIME st, other_st;
+ TCHAR date_buf[512], time_buf[512];
+ std::string buf;
+
+ MyGetSystemTime(&st);
+
+ TIME_ZONE_INFORMATION here_tzi, tzi;
+ LISTITEM pa;
+ DBVARIANT dbv;
+ WORD status;
+ char *proto;
+
+
+ BOOL daylight_here = (GetTimeZoneInformation(&here_tzi) == TIME_ZONE_ID_DAYLIGHT);
+
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL ) {
+ proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 );
+ if ( proto && !lstrcmp( PROTO, proto)) {
+ pa.hContact = hContact;
+ pa.timezone_list_index = DBGetContactSettingDword(pa.hContact, PROTO, "TimezoneListIndex", -1);
+ if(!DBGetContactSetting(pa.hContact, PROTO, "Nick", &dbv)) {
+ strncpy(pa.pszText, dbv.pszVal, MAX_NAME_LENGTH);
+ DBFreeVariant(&dbv);
+ }
+ status = DBGetContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_ONLINE);
+
+ tzi.Bias = timezone_list[pa.timezone_list_index].TZI.Bias;
+ tzi.DaylightBias = timezone_list[pa.timezone_list_index].TZI.DaylightBias;
+ tzi.DaylightDate = timezone_list[pa.timezone_list_index].TZI.DaylightDate;
+ tzi.StandardBias = timezone_list[pa.timezone_list_index].TZI.StandardBias;
+ tzi.StandardDate = timezone_list[pa.timezone_list_index].TZI.StandardDate;
+
+ MySystemTimeToTzSpecificLocalTime(&tzi, &st, &other_st);
+
+ if(set_format) {
+ GetTimeFormat(LOCALE_USER_DEFAULT, 0, &other_st, format_string, time_buf, 512);
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, &other_st, date_format_string, date_buf, 512);
+ } else {
+ GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &other_st, 0, time_buf, 512);
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, &other_st, 0, date_buf, 512);
+ }
+
+ std::string::size_type pos;
+ buf = clist_format_string;
+ pos = buf.find ("%n");
+ if(pos != std::string::npos)
+ buf.replace(pos, 2, pa.pszText);
+ pos = buf.find ("%t");
+ if(pos != std::string::npos)
+ buf.replace(pos, 2, time_buf);
+ pos = buf.find ("%d");
+ if(pos != std::string::npos)
+ buf.replace(pos, 2, date_buf);
+
+ pos = buf.find ("%o");
+ if(pos != std::string::npos) {
+ int other_offset, offset;
+
+ if(tzi.StandardDate.wMonth) {
+ if(tzi.DaylightDate.wMonth < tzi.StandardDate.wMonth) {
+ if(LocalGreaterThanTransition(&other_st, &tzi.DaylightDate)
+ && !LocalGreaterThanTransition(&other_st, &tzi.StandardDate))
+ {
+ other_offset = tzi.Bias + tzi.DaylightBias;
+ } else
+ other_offset = tzi.Bias;
+
+ } else {
+ if(!LocalGreaterThanTransition(&other_st, &tzi.StandardDate)
+ || LocalGreaterThanTransition(&other_st, &tzi.DaylightDate))
+ {
+ other_offset = tzi.Bias + tzi.DaylightBias;
+ } else
+ other_offset = tzi.Bias;
+ }
+ } else
+ other_offset = tzi.Bias;
+
+ char temp_buf[8];
+
+ unsigned char icq_offset = (unsigned char)((other_offset / 60) * 2) + (other_offset % 60) / 30;
+
+ if(DBGetContactSettingByte(pa.hContact, PROTO, "Timezone", 256) != icq_offset)
+ DBWriteContactSettingByte(pa.hContact, PROTO, "Timezone", icq_offset);
+
+ offset = here_tzi.Bias + (daylight_here ? here_tzi.DaylightBias : 0) - other_offset;
+ //if(offset > 12 * 60) offset -= 24 * 60;
+ //if(offset < -12 * 60) offset += 24 * 60;
+
+ mir_snprintf(temp_buf, sizeof(temp_buf), "%+g", offset/60.0);
+ buf.replace(pos, 2, temp_buf);
+ }
+
+ if(!DBGetContactSetting(pa.hContact, "CList", "MyHandle", &dbv)) {
+ // only write if times are different
+ if(strcmp(dbv.pszVal, buf.c_str()))
+ DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", buf.c_str());
+ DBFreeVariant(&dbv);
+ } else
+ DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", buf.c_str());
+
+ if(!DBGetContactSetting(pa.hContact, PROTO, "FirstName", &dbv)) {
+ // only write if times are different
+ if(strcmp(dbv.pszVal, time_buf))
+ DBWriteContactSettingString(pa.hContact, PROTO, "FirstName", time_buf);
+ DBFreeVariant(&dbv);
+ } else
+ DBWriteContactSettingString(pa.hContact, PROTO, "FirstName", time_buf);
+
+ if(set_format) {
+ if(!DBGetContactSetting(pa.hContact, PROTO, "LastName", &dbv)) {
+ // only write if times are different
+ if(strcmp(dbv.pszVal, date_buf))
+ DBWriteContactSettingString(pa.hContact, PROTO, "LastName", date_buf);
+ DBFreeVariant(&dbv);
+ } else
+ DBWriteContactSettingString(pa.hContact, PROTO, "LastName", date_buf);
+ } else
+ DBDeleteContactSetting(pa.hContact, PROTO, "LastName");
+
+ if(other_st.wHour >= 6 && other_st.wHour < 18) {
+ if(status != ID_STATUS_ONLINE)
+ DBWriteContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_ONLINE);
+ } else {
+ if(status != ID_STATUS_NA)
+ DBWriteContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_NA);
+ }
+ }
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+}
+
+int OnShutdown(WPARAM wParam, LPARAM lParam) {
+ time_windows_cleanup();
+ return 0;
+}
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam) {
+
+ // for database editor++ ver 3+
+ if(ServiceExists("DBEditorpp/RegisterSingleModule"))
+ CallService("DBEditorpp/RegisterSingleModule",(WPARAM)PROTO,0);
+
+ //ignore status for all WORLD TIME contacts
+ {
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ char *proto;
+ while ( hContact != NULL )
+ {
+ proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 );
+ if ( proto && !lstrcmp( PROTO, proto)) {
+ CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE);
+ DBDeleteContactSetting(hContact, PROTO, "WindowHandle");
+ }
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+ }
+
+
+ hContactDblClick = HookEvent(ME_CLIST_DOUBLECLICKED, ContactDblClick);
+
+
+ {
+ CLISTMENUITEM menu;
+
+ ZeroMemory(&menu,sizeof(menu));
+ menu.cbSize=sizeof(menu);
+ menu.flags = CMIM_ALL;
+
+ menu.hIcon=LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_PROTO));
+
+ menu.position = -200000;
+ menu.pszName = (char *)Translate("Edit...");
+ menu.pszService=PROTO "/Edit";
+ menu.pszContactOwner = PROTO;
+ hMenuEdit = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&menu);
+
+ }
+
+ build_timezone_list();
+ time_windows_init();
+
+ id_timer = SetTimer(0, 0, 950, TimerProc);
+
+ return 0;
+}
+
+HANDLE hEventModulesLoaded, hEventOptInit, hEventPreShutdown;
+extern "C" WORLDTIMEPROTO_API int Load(PLUGINLINK *link)
+{
+ pluginLink=link;
+
+ previousMode = mcStatus = ID_STATUS_OFFLINE;
+
+ PROTOCOLDESCRIPTOR pd = {0};
+ pd.cbSize=sizeof(pd);
+ pd.szName=PROTO;
+ pd.type = PROTOTYPE_PROTOCOL;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+
+ CreatePluginServices();
+
+ LoadOptions();
+
+ hEventModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+
+ hEventOptInit = HookEvent(ME_OPT_INITIALISE, OptInit);
+
+ hEventPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, OnShutdown);
+
+ return 0;
+}
+
+extern "C" WORLDTIMEPROTO_API int Unload(void)
+{
+ UnhookEvent(hEventModulesLoaded);
+ UnhookEvent(hEventOptInit);
+ UnhookEvent(hEventPreShutdown);
+
+ KillTimer(0, id_timer);
+
+ DestroyServiceFunctions();
+
+ UnhookEvent(hContactDblClick);
+ return 0;
+}