summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/delphi/m_protocols.inc25
-rw-r--r--include/m_protocols.h265
-rw-r--r--src/core/miranda.h8
-rw-r--r--src/modules/protocols/protocols.cpp15
-rw-r--r--src/modules/protocols/protoopts.cpp292
5 files changed, 331 insertions, 274 deletions
diff --git a/include/delphi/m_protocols.inc b/include/delphi/m_protocols.inc
index 9cf6007b4f..ef17ae9dff 100644
--- a/include/delphi/m_protocols.inc
+++ b/include/delphi/m_protocols.inc
@@ -273,20 +273,29 @@ type
end;
tagACCOUNT = TPROTOACCOUNT;
-const
//account enumeration service
//wParam=(WPARAM)(int)piNumAccounts
//lParam=(LPARAM)(PROTOACCOUNT**)paAccounts
+const
MS_PROTO_ENUMACCOUNTS:PAnsiChar = 'Proto/EnumAccounts';
- MS_PROTO_ENUMPROTOS :PAnsiChar = 'Proto/EnumProtos'; // MIRANDA_VER >= $800
-// MS_PROTO_ENUMPROTOCOLS:PAnsiChar = 'Proto/EnumProtocols';// MIRANDA_VER < $800
+ MS_PROTO_ENUMPROTOS:PAnsiChar = 'Proto/EnumProtos'; // MIRANDA_VER >= $800
+
+type
+ PACC_CREATE = ^ACC_CREATE;
+ ACC_CREATE = record
+ pszBaseProto :PAnsiChar;
+ pszInternal :PAnsiChar;
+ ptszAccountName:PWideChar;
+ end;
+
+const
+// creates new account
+// wParam = 0
+// lParam = (LPARAM)(ACC_CREATE*) account definition
+// return value = PROTOACCOUNT* or NULL
+ MS_PROTO_CREATEACCOUNT:PAnsiChar = 'Proto/CreateAccount';
-(*
-__inline int ProtoEnumAccounts( int* accNumber, PROTOACCOUNT*** accArray )
-{ return CallService( MS_PROTO_ENUMACCOUNTS, ( WPARAM )accNumber, (LPARAM)accArray );
-}
-*)
//retrieves an account's interface by its physical name (database module)
//wParam=0
//lParam=(LPARAM)(AnsiChar*)szAccountName
diff --git a/include/m_protocols.h b/include/m_protocols.h
index 54533cee57..fc21f8d9a4 100644
--- a/include/m_protocols.h
+++ b/include/m_protocols.h
@@ -2,7 +2,7 @@
Miranda NG: the free IM client for Microsoft* Windows*
-Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org)
+Copyright (c) 2012-14 Miranda NG project (http:// miranda-ng.org)
Copyright (c) 2000-08 Miranda ICQ/IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.
@@ -22,7 +22,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-//this module was created in v0.1.1.0
+// this module was created in v0.1.1.0
#ifndef M_PROTOCOLS_H__
#define M_PROTOCOLS_H__ 1
@@ -31,34 +31,34 @@ struct PROTO_INTERFACE;
#include "statusmodes.h"
-//send a general request through the protocol chain for a contact
-//wParam = 0
-//lParam = (LPARAM)(CCSDATA*)&ccs
-//returns the value as documented in the PS_ definition (m_protosvc.h)
+// send a general request through the protocol chain for a contact
+// wParam = 0
+// lParam = (LPARAM)(CCSDATA*)&ccs
+// returns the value as documented in the PS_ definition (m_protosvc.h)
typedef struct {
MCONTACT hContact;
- const char *szProtoService; //a PS_ constant
+ const char *szProtoService; // a PS_ constant
WPARAM wParam;
LPARAM lParam;
} CCSDATA;
#define MS_PROTO_CALLCONTACTSERVICE "Proto/CallContactService"
-//a general network 'ack'
-//wParam = 0
-//lParam = (LPARAM)(ACKDATA*)&ack
-//Note that just because definitions are here doesn't mean they will be sent.
-//Read the documentation for the function you are calling to see what replies
-//you will receive.
+// a general network 'ack'
+// wParam = 0
+// lParam = (LPARAM)(ACKDATA*)&ack
+// Note that just because definitions are here doesn't mean they will be sent.
+// Read the documentation for the function you are calling to see what replies
+// you will receive.
typedef struct {
int cbSize;
- const char *szModule; //the name of the protocol module which initiated this ack
+ const char *szModule; // the name of the protocol module which initiated this ack
MCONTACT hContact;
- int type; //an ACKTYPE_ constant
- int result; //an ACKRESULT_ constant
- HANDLE hProcess; //a caller-defined process code
- LPARAM lParam; //caller-defined extra info
+ int type; // an ACKTYPE_ constant
+ int result; // an ACKRESULT_ constant
+ HANDLE hProcess; // a caller-defined process code
+ LPARAM lParam; // caller-defined extra info
} ACKDATA;
#define ACKTYPE_MESSAGE 0
#define ACKTYPE_URL 1
@@ -73,26 +73,26 @@ typedef struct {
#define ACKTYPE_SEARCH 10
#define ACKTYPE_NEWUSER 11
#define ACKTYPE_STATUS 12
-#define ACKTYPE_CONTACTS 13 //send/recv of contacts
-#define ACKTYPE_AVATAR 14 //send/recv of avatars from a protocol
-#define ACKTYPE_EMAIL 15 //notify if the unread emails changed
+#define ACKTYPE_CONTACTS 13 // send/recv of contacts
+#define ACKTYPE_AVATAR 14 // send/recv of avatars from a protocol
+#define ACKTYPE_EMAIL 15 // notify if the unread emails changed
#define ACKRESULT_SUCCESS 0
#define ACKRESULT_FAILED 1
-//'in progress' result codes:
+// 'in progress' result codes:
#define ACKRESULT_CONNECTING 100
#define ACKRESULT_CONNECTED 101
#define ACKRESULT_INITIALISING 102
-#define ACKRESULT_SENTREQUEST 103 //waiting for reply...
-#define ACKRESULT_DATA 104 //blob of file data sent/recved, or search result
-#define ACKRESULT_NEXTFILE 105 //file transfer went to next file
-#define ACKRESULT_FILERESUME 106 //a file is about to be received, see PS_FILERESUME
-#define ACKRESULT_DENIED 107 //a file send has been denied
-#define ACKRESULT_STATUS 108 //an ack or a series of acks to do with a task have a status change
-#define ACKRESULT_LISTENING 109 //waiting for connection
-#define ACKRESULT_CONNECTPROXY 110 //connecting to file proxy
-#define ACKRESULT_SEARCHRESULT 111 //result of extended search
+#define ACKRESULT_SENTREQUEST 103 // waiting for reply...
+#define ACKRESULT_DATA 104 // blob of file data sent/recved, or search result
+#define ACKRESULT_NEXTFILE 105 // file transfer went to next file
+#define ACKRESULT_FILERESUME 106 // a file is about to be received, see PS_FILERESUME
+#define ACKRESULT_DENIED 107 // a file send has been denied
+#define ACKRESULT_STATUS 108 // an ack or a series of acks to do with a task have a status change
+#define ACKRESULT_LISTENING 109 // waiting for connection
+#define ACKRESULT_CONNECTPROXY 110 // connecting to file proxy
+#define ACKRESULT_SEARCHRESULT 111 // result of extended search
#define ME_PROTO_ACK "Proto/Ack"
@@ -101,8 +101,8 @@ typedef struct {
// long to be delivered". If no error message is specified, lParam must be NULL.
// Right now only explanations from ACKTYPE_MESSAGE is shown.
-//when type == ACKTYPE_FILE && (result == ACKRESULT_DATA || result == ACKRESULT_FILERESUME),
-//lParam points to this
+// when type == ACKTYPE_FILE && (result == ACKRESULT_DATA || result == ACKRESULT_FILERESUME),
+// lParam points to this
#define FNAMECHAR TCHAR
@@ -148,30 +148,30 @@ typedef struct tagPROTOFILETRANSFERSTATUS
unsigned __int64 currentFileSize;
unsigned __int64 currentFileProgress;
- unsigned __int64 currentFileTime; //as seconds since 1970
+ unsigned __int64 currentFileTime; // as seconds since 1970
}
PROTOFILETRANSFERSTATUS;
-//Enumerate the currently running protocols
-//wParam = (WPARAM)(int*)&numberOfProtocols
-//lParam = (LPARAM)(PROTOCOLDESCRIPTOR***)&ppProtocolDescriptors
-//Returns 0 on success, nonzero on failure
-//Neither wParam nor lParam may be NULL
-//The list returned by this service is the protocol modules currently installed
-//and running. It is not the complete list of all protocols that have ever been
-//installed.
-//IMPORTANT NOTE #1: the list returned is not static, it may be changed in the
-//program's lifetime. Do not use this list in the global context, copy protocols
-//names otherwise.
-//IMPORTANT NOTE #2: in version 0.8 this service is mapped to the MS_PROTO_ENUMACCOUNTS
-//service to provide the compatibility with old plugins (first three members of
-//PROTOACCOUNT are equal to the old PROTOCOLDESCRIPTOR format). If you declare the
-//MIRANDA_VER macro with value greater or equal to 0x800, use MS_PROTO_ENUMPROTOS
-//service instead to obtain the list of running protocols instead of accounts.
-//Note that a protocol module need not be an interface to an Internet server,
-//they can be encryption and loads of other things, too.
-//And yes, before you ask, that is triple indirection. Deal with it.
-//Access members using ppProtocolDescriptors[index]->element
+// Enumerate the currently running protocols
+// wParam = (WPARAM)(int*)&numberOfProtocols
+// lParam = (LPARAM)(PROTOCOLDESCRIPTOR***)&ppProtocolDescriptors
+// Returns 0 on success, nonzero on failure
+// Neither wParam nor lParam may be NULL
+// The list returned by this service is the protocol modules currently installed
+// and running. It is not the complete list of all protocols that have ever been
+// installed.
+// IMPORTANT NOTE #1: the list returned is not static, it may be changed in the
+// program's lifetime. Do not use this list in the global context, copy protocols
+// names otherwise.
+// IMPORTANT NOTE #2: in version 0.8 this service is mapped to the MS_PROTO_ENUMACCOUNTS
+// service to provide the compatibility with old plugins (first three members of
+// PROTOACCOUNT are equal to the old PROTOCOLDESCRIPTOR format). If you declare the
+// MIRANDA_VER macro with value greater or equal to 0x800, use MS_PROTO_ENUMPROTOS
+// service instead to obtain the list of running protocols instead of accounts.
+// Note that a protocol module need not be an interface to an Internet server,
+// they can be encryption and loads of other things, too.
+// And yes, before you ask, that is triple indirection. Deal with it.
+// Access members using ppProtocolDescriptors[index]->element
#define PROTOCOLDESCRIPTOR_V3_SIZE (sizeof(size_t)+sizeof(INT_PTR)+sizeof(char*))
@@ -197,12 +197,12 @@ typedef struct {
PROTOCOLDESCRIPTOR;
// v0.3.3+:
-//
+//
// For recv, it will go from lower to higher, so in this case:
// check ignore, decrypt (encryption), translate
-//
+//
// For send, it will go translate, encrypt, ignore(??), send
-//
+//
// The DB will store higher numbers here, LOWER in the protocol chain, and lower numbers
// here HIGHER in the protocol chain
@@ -216,61 +216,61 @@ typedef struct {
#define MS_PROTO_ENUMPROTOS "Proto/EnumProtos"
-//determines if a protocol module is loaded or not
-//wParam = 0
-//lParam = (LPARAM)(const char*)szName
-//Returns a pointer to the PROTOACCOUNT if the protocol is loaded, or
-//NULL if it isn't.
+// determines if a protocol module is loaded or not
+// wParam = 0
+// lParam = (LPARAM)(const char*)szName
+// Returns a pointer to the PROTOACCOUNT if the protocol is loaded, or
+// NULL if it isn't.
#define MS_PROTO_ISPROTOCOLLOADED "Proto/IsProtocolLoaded"
-//gets the network-level protocol associated with a contact
-//wParam = (MCONTACT)hContact
-//lParam = 0
-//Returns a char* pointing to the asciiz name of the protocol or NULL if the
-//contact has no protocol. There is no need to free() it or anything.
-//This is the name of the module that actually accesses the network for that
-//contact.
+// gets the network-level protocol associated with a contact
+// wParam = (MCONTACT)hContact
+// lParam = 0
+// Returns a char* pointing to the asciiz name of the protocol or NULL if the
+// contact has no protocol. There is no need to free() it or anything.
+// This is the name of the module that actually accesses the network for that
+// contact.
#define MS_PROTO_GETCONTACTBASEPROTO "Proto/GetContactBaseProto"
__forceinline char* GetContactProto(MCONTACT hContact)
{ return (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, hContact, 0);
}
-//determines whether the specified contact has the given protocol in its chain
-//wParam = (MCONTACT)hContact
-//lParam = (LPARAM)(const char*)szName
-//Returns -1 if it is base protocol, positive number if it is filter and 0 if it doesn't
+// determines whether the specified contact has the given protocol in its chain
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(const char*)szName
+// Returns -1 if it is base protocol, positive number if it is filter and 0 if it doesn't
#define MS_PROTO_ISPROTOONCONTACT "Proto/IsProtoOnContact"
#define PROTOTYPE_SELFTYPING_OFF 0
#define PROTOTYPE_SELFTYPING_ON 1
-//This service is for notifying protocols that the user is typing a message v0.3.3+
-//in a message dialog.
-//This is typically sent by a message dialog when a user in the clist is typing.
-//wParam = (MCONTACT)hContact
-//lParam = (LPARAM)(int)typing state
-//NOTE: Only protocols should generally call this service
+// This service is for notifying protocols that the user is typing a message v0.3.3+
+// in a message dialog.
+// This is typically sent by a message dialog when a user in the clist is typing.
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(int)typing state
+// NOTE: Only protocols should generally call this service
#define MS_PROTO_SELFISTYPING "Proto/SelfIsTyping"
#define PROTOTYPE_CONTACTTYPING_OFF 0
#define PROTOTYPE_CONTACTTYPING_INFINITE 2147483647
-//This service is for notifying message dialogs/other plugins of a user typing. v0.3.3+
-//This is typically sent by a protocol when a user in the clist is typing.
-//wParam = (MCONTACT)hContact
-//lParam = (LPARAM)(int)time (secs)
-//NOTE: The time in seconds is used to tell a message dialog (or other plugin)
-//how long to display its notification. If time is 0, then notification
-//of typing ends.
-//NOTE: Only protocols should generally call this service
+// This service is for notifying message dialogs/other plugins of a user typing. v0.3.3+
+// This is typically sent by a protocol when a user in the clist is typing.
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(int)time (secs)
+// NOTE: The time in seconds is used to tell a message dialog (or other plugin)
+// how long to display its notification. If time is 0, then notification
+// of typing ends.
+// NOTE: Only protocols should generally call this service
#define MS_PROTO_CONTACTISTYPING "Proto/ContactIsTyping"
-//This hook notifies when a user is typing. If a message dialog supports sending v0.3.3+
-//typing notifications it should hook this event and fire the
-//ProtoService PSS_USERISTYPING to the contacts protocol *after* verifying
-//that the hContact is not NULL and the the user wishes to send notifications
-//to this user (checked visibility, individual typing blocking, etc).
-//wParam = (MCONTACT)hContact
-//lParam = (LPARAM)(int)typing state
+// This hook notifies when a user is typing. If a message dialog supports sending v0.3.3+
+// typing notifications it should hook this event and fire the
+// ProtoService PSS_USERISTYPING to the contacts protocol *after* verifying
+// that the hContact is not NULL and the the user wishes to send notifications
+// to this user (checked visibility, individual typing blocking, etc).
+// wParam = (MCONTACT)hContact
+// lParam = (LPARAM)(int)typing state
#define ME_PROTO_CONTACTISTYPING "Proto/ContactIsTypingEvent"
// -------------- accounts support --------------------- 0.8.0+
@@ -295,28 +295,46 @@ typedef struct tagACCOUNT
}
PROTOACCOUNT;
-//account enumeration service
-//wParam = (WPARAM)(int*)piNumAccounts
-//lParam = (LPARAM)(PROTOACCOUNT**)paAccounts
+// account enumeration service
+// wParam = (WPARAM)(int*)piNumAccounts
+// lParam = (LPARAM)(PROTOACCOUNT**)paAccounts
#define MS_PROTO_ENUMACCOUNTS "Proto/EnumAccounts"
__forceinline INT_PTR ProtoEnumAccounts(int* accNumber, PROTOACCOUNT*** accArray)
{ return CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)accNumber, (LPARAM)accArray);
}
-//retrieves an account's interface by its physical name (database module)
-//wParam = 0
-//lParam = (LPARAM)(char*)szAccountName
-//return value = PROTOACCOUNT* or NULL
+// creates new account
+// wParam = 0
+// lParam = (LPARAM)(ACC_CREATE*) account definition
+// return value = PROTOACCOUNT* or NULL
+#define MS_PROTO_CREATEACCOUNT "Proto/CreateAccount"
+
+typedef struct tagACC_CREATE
+{
+ const char *pszBaseProto;
+ const char *pszInternal;
+ const TCHAR *ptszAccountName;
+} ACC_CREATE;
+
+__forceinline PROTOACCOUNT* ProtoCreateAccount(ACC_CREATE *pAccountDef)
+{ return (PROTOACCOUNT*)CallService(MS_PROTO_CREATEACCOUNT, 0, (LPARAM)pAccountDef);
+}
+
+// retrieves an account's interface by its physical name (database module)
+// wParam = 0
+// lParam = (LPARAM)(char*)szAccountName
+// return value = PROTOACCOUNT* or NULL
#define MS_PROTO_GETACCOUNT "Proto/GetAccount"
__forceinline PROTOACCOUNT* ProtoGetAccount(const char* accName)
-{ return (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)accName);
+{
+ return (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)accName);
}
-//this event is fired when the accounts list gets changed
-//wParam = event type (1 - added, 2 - changed, 3 - deleted, 4 - upgraded, 5 - enabled/disabled)
-//lParam = (LPARAM)(PROTOACCOUNT*) - account being changed
+// this event is fired when the accounts list gets changed
+// wParam = event type (1 - added, 2 - changed, 3 - deleted, 4 - upgraded, 5 - enabled/disabled)
+// lParam = (LPARAM)(PROTOACCOUNT*) - account being changed
#define PRAC_ADDED 1
#define PRAC_CHANGED 2
@@ -324,18 +342,17 @@ __forceinline PROTOACCOUNT* ProtoGetAccount(const char* accName)
#define PRAC_UPGRADED 4
#define PRAC_CHECKED 5
-
#define ME_PROTO_ACCLISTCHANGED "Proto/AccListChanged"
-//displays the Account Manager
-//wParam = 0
-//lParam = 0
+// displays the Account Manager
+// wParam = 0
+// lParam = 0
#define MS_PROTO_SHOWACCMGR "Protos/ShowAccountManager"
-//determines if an account is enabled or not
-//wParam = 0
-//lParam = (LPARAM)(PROTOACCOUNT*)
-//Returns 1 if an account is valid and enabled, 0 otherwise
+// determines if an account is enabled or not
+// wParam = 0
+// lParam = (LPARAM)(PROTOACCOUNT*)
+// Returns 1 if an account is valid and enabled, 0 otherwise
#define MS_PROTO_ISACCOUNTENABLED "Proto/IsAccountEnabled"
__forceinline int IsAccountEnabled(const PROTOACCOUNT *pa)
@@ -343,20 +360,20 @@ __forceinline int IsAccountEnabled(const PROTOACCOUNT *pa)
return (int)CallService(MS_PROTO_ISACCOUNTENABLED, 0, (LPARAM)pa);
}
-//determines if an account is locked or not
-//wParam = 0
-//lParam = (LPARAM)(char*)szAccountName
-//Returns 1 if an account is locked and not supposed to change status, 0 otherwise
+// determines if an account is locked or not
+// wParam = 0
+// lParam = (LPARAM)(char*)szAccountName
+// Returns 1 if an account is locked and not supposed to change status, 0 otherwise
#define MS_PROTO_ISACCOUNTLOCKED "Proto/IsAccountLocked"
-//gets the account associated with a contact
-//wParam = (MCONTACT)hContact
-//lParam = 0
-//Returns a char* pointing to the asciiz name of the protocol or NULL if the
-//contact has no protocol. There is no need to mir_free() it or anything.
-//This is the name of the module that actually accesses the network for that
-//contact.
+// gets the account associated with a contact
+// wParam = (MCONTACT)hContact
+// lParam = 0
+// Returns a char* pointing to the asciiz name of the protocol or NULL if the
+// contact has no protocol. There is no need to mir_free() it or anything.
+// This is the name of the module that actually accesses the network for that
+// contact.
#define MS_PROTO_GETCONTACTBASEACCOUNT "Proto/GetContactBaseAccount"
/* -------------- avatar support ---------------------
diff --git a/src/core/miranda.h b/src/core/miranda.h
index 29c3e48a5b..ccac4fc323 100644
--- a/src/core/miranda.h
+++ b/src/core/miranda.h
@@ -144,14 +144,16 @@ void KillModuleMenus(int hLangpack);
extern LIST<PROTOACCOUNT> accounts;
-PROTOACCOUNT* __fastcall Proto_GetAccount(const char* accName);
+PROTOACCOUNT* Proto_CreateAccount(const char *szProtoName, const char *szBaseProto, const TCHAR *tszAccountName);
+
+PROTOACCOUNT* __fastcall Proto_GetAccount(const char *accName);
PROTOACCOUNT* __fastcall Proto_GetAccount(MCONTACT hContact);
-PROTOCOLDESCRIPTOR* __fastcall Proto_IsProtocolLoaded(const char* szProtoName);
+PROTOCOLDESCRIPTOR* __fastcall Proto_IsProtocolLoaded(const char *szProtoName);
bool __fastcall Proto_IsAccountEnabled(PROTOACCOUNT *pa);
bool __fastcall Proto_IsAccountLocked(PROTOACCOUNT *pa);
-PROTO_INTERFACE* AddDefaultAccount(const char* szProtoName);
+PROTO_INTERFACE* AddDefaultAccount(const char *szProtoName);
int FreeDefaultAccount(PROTO_INTERFACE* ppi);
BOOL ActivateAccount(PROTOACCOUNT *pa);
diff --git a/src/modules/protocols/protocols.cpp b/src/modules/protocols/protocols.cpp
index 6d57eb10e9..f45378d173 100644
--- a/src/modules/protocols/protocols.cpp
+++ b/src/modules/protocols/protocols.cpp
@@ -319,6 +319,20 @@ PROTOACCOUNT* __fastcall Proto_GetAccount(const char* accName)
return accounts[idx];
}
+static INT_PTR srvProto_CreateAccount(WPARAM, LPARAM lParam)
+{
+ ACC_CREATE *p = (ACC_CREATE*)lParam;
+ if (p == NULL)
+ return NULL;
+
+ PROTOACCOUNT *pa = Proto_CreateAccount(p->pszBaseProto, p->pszInternal, p->ptszAccountName);
+ if (pa) {
+ WriteDbAccounts();
+ NotifyEventHooks(hAccListChanged, PRAC_ADDED, (LPARAM)pa);
+ }
+ return (INT_PTR)pa;
+}
+
static INT_PTR srvProto_GetAccount(WPARAM, LPARAM lParam)
{
return (INT_PTR)Proto_GetAccount((char*)lParam);
@@ -682,6 +696,7 @@ int LoadProtocolsModule(void)
CreateServiceFunction("Proto/EnumProtocols", Proto_EnumAccounts);
CreateServiceFunction(MS_PROTO_ENUMACCOUNTS, Proto_EnumAccounts);
+ CreateServiceFunction(MS_PROTO_CREATEACCOUNT, srvProto_CreateAccount);
CreateServiceFunction(MS_PROTO_GETACCOUNT, srvProto_GetAccount);
CreateServiceFunction(MS_PROTO_ISACCOUNTENABLED, srvProto_IsAccountEnabled);
diff --git a/src/modules/protocols/protoopts.cpp b/src/modules/protocols/protoopts.cpp
index 724684609a..54ec8ceed4 100644
--- a/src/modules/protocols/protoopts.cpp
+++ b/src/modules/protocols/protoopts.cpp
@@ -59,16 +59,121 @@ extern HANDLE hAccListChanged;
int UnloadPlugin(TCHAR* buf, int bufLen);
+PROTOACCOUNT* Proto_CreateAccount(const char *szModuleName, const char *szBaseProto, const TCHAR *tszAccountName)
+{
+ PROTOACCOUNT *pa = (PROTOACCOUNT*)mir_calloc(sizeof(PROTOACCOUNT));
+ if (pa == NULL)
+ return NULL;
+
+ pa->cbSize = sizeof(PROTOACCOUNT);
+ pa->bIsEnabled = pa->bIsVisible = true;
+ pa->iOrder = accounts.getCount();
+ pa->szProtoName = mir_strdup(szBaseProto);
+
+ // if the internal name is empty, generate new one
+ if (lstrlenA(szModuleName) == 0) {
+ char buf[100];
+ int count = 1;
+ while (true) {
+ mir_snprintf(buf, SIZEOF(buf), "%s_%d", szBaseProto, count++);
+ if (ptrA(db_get_sa(NULL, buf, "AM_BaseProto")) == NULL)
+ break;
+ }
+ pa->szModuleName = mir_strdup(buf);
+ }
+ else pa->szModuleName = mir_strdup(szModuleName);
+
+ pa->tszAccountName = mir_tstrdup(tszAccountName);
+
+ db_set_s(NULL, pa->szModuleName, "AM_BaseProto", szBaseProto);
+ accounts.insert(pa);
+
+ if (ActivateAccount(pa)) {
+ pa->ppro->OnEvent(EV_PROTO_ONLOAD, 0, 0);
+ if (!db_get_b(NULL, "CList", "MoveProtoMenus", true))
+ pa->ppro->OnEvent(EV_PROTO_ONMENU, 0, 0);
+ }
+
+ return pa;
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
// Account edit form
// Gets PROTOACCOUNT* as a parameter, or NULL to edit a new one
-typedef struct
+struct AccFormDlgParam
{
int action;
PROTOACCOUNT *pa;
+};
+
+static bool FindAccountByName(const char *szModuleName)
+{
+ if (!lstrlenA(szModuleName))
+ return false;
+
+ for (int i = 0; i < accounts.getCount(); i++)
+ if (_stricmp(szModuleName, accounts[i]->szModuleName) == 0)
+ return true;
+
+ return false;
+}
+
+static bool OnCreateAccount(HWND hwndDlg)
+{
+ AccFormDlgParam* param = (AccFormDlgParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ PROTOACCOUNT *pa = param->pa;
+
+ TCHAR tszAccName[256];
+ GetDlgItemText(hwndDlg, IDC_ACCNAME, tszAccName, SIZEOF(tszAccName));
+ rtrimt(tszAccName);
+ if (tszAccName[0] == 0) {
+ MessageBox(hwndDlg, TranslateT("Account name must be filled."), TranslateT("Account error"), MB_ICONERROR | MB_OK);
+ return false;
+ }
+
+ if (param->action == PRAC_ADDED) {
+ char buf[200];
+ GetDlgItemTextA(hwndDlg, IDC_ACCINTERNALNAME, buf, SIZEOF(buf));
+ if (FindAccountByName(rtrim(buf))) {
+ MessageBox(hwndDlg, TranslateT("Account name has to be unique. Please enter unique name."), TranslateT("Account error"), MB_ICONERROR | MB_OK);
+ return false;
+ }
+ }
+
+ if (param->action == PRAC_UPGRADED) {
+ BOOL oldProto = pa->bOldProto;
+ TCHAR szPlugin[MAX_PATH];
+ mir_sntprintf(szPlugin, SIZEOF(szPlugin), _T("%s.dll"), StrConvT(pa->szProtoName));
+ int idx = accounts.getIndex(pa);
+ UnloadAccount(pa, false, false);
+ accounts.remove(idx);
+ if (oldProto && UnloadPlugin(szPlugin, SIZEOF(szPlugin))) {
+ TCHAR szNewName[MAX_PATH];
+ mir_sntprintf(szNewName, SIZEOF(szNewName), _T("%s~"), szPlugin);
+ MoveFile(szPlugin, szNewName);
+ }
+ param->action = PRAC_ADDED;
+ }
+
+ if (param->action == PRAC_ADDED) {
+ char buf[200];
+ GetDlgItemTextA(hwndDlg, IDC_PROTOTYPECOMBO, buf, SIZEOF(buf));
+ char *szBaseProto = NEWSTR_ALLOCA(buf);
+
+ GetDlgItemTextA(hwndDlg, IDC_ACCINTERNALNAME, buf, SIZEOF(buf));
+ rtrim(buf);
+
+ pa = Proto_CreateAccount(buf, szBaseProto, tszAccName);
+ }
+ else replaceStrT(pa->tszAccountName, tszAccName);
+
+ WriteDbAccounts();
+ NotifyEventHooks(hAccListChanged, param->action, (LPARAM)pa);
+
+ SendMessage(GetParent(hwndDlg), WM_MY_REFRESH, 0, 0);
+ return true;
}
- AccFormDlgParam;
static INT_PTR CALLBACK AccFormDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
@@ -116,95 +221,8 @@ static INT_PTR CALLBACK AccFormDlgProc(HWND hwndDlg, UINT message, WPARAM wParam
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDOK:
- {
- AccFormDlgParam* param = (AccFormDlgParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- PROTOACCOUNT *pa = param->pa;
-
- if (param->action == PRAC_ADDED) {
- char buf[200];
- GetDlgItemTextA(hwndDlg, IDC_ACCINTERNALNAME, buf, SIZEOF(buf));
- rtrim(buf);
- if (buf[0]) {
- for (int i=0; i < accounts.getCount(); i++)
- if (_stricmp(buf, accounts[i]->szModuleName) == 0) {
- MessageBox(hwndDlg, TranslateT("Account name has to be unique. Please enter unique name."), TranslateT("Account error"), MB_ICONERROR | MB_OK);
- return FALSE;
- }
- }
- }
-
- switch(param->action) {
- case PRAC_UPGRADED:
- {
- BOOL oldProto = pa->bOldProto;
- TCHAR szPlugin[MAX_PATH];
- mir_sntprintf(szPlugin, SIZEOF(szPlugin), _T("%s.dll"), StrConvT(pa->szProtoName));
- int idx = accounts.getIndex(pa);
- UnloadAccount(pa, false, false);
- accounts.remove(idx);
- if (oldProto && UnloadPlugin(szPlugin, SIZEOF(szPlugin))) {
- TCHAR szNewName[MAX_PATH];
- mir_sntprintf(szNewName, SIZEOF(szNewName), _T("%s~"), szPlugin);
- MoveFile(szPlugin, szNewName);
- }
- }
- // fall through
-
- case PRAC_ADDED:
- pa = (PROTOACCOUNT*)mir_calloc(sizeof(PROTOACCOUNT));
- pa->cbSize = sizeof(PROTOACCOUNT);
- pa->bIsEnabled = TRUE;
- pa->bIsVisible = TRUE;
-
- pa->iOrder = accounts.getCount();
- break;
- }
- {
- TCHAR buf[256];
- GetDlgItemText(hwndDlg, IDC_ACCNAME, buf, SIZEOF(buf));
- mir_free(pa->tszAccountName);
- pa->tszAccountName = mir_tstrdup(buf);
- }
- if (param->action == PRAC_ADDED || param->action == PRAC_UPGRADED) {
- char buf[200];
- GetDlgItemTextA(hwndDlg, IDC_PROTOTYPECOMBO, buf, SIZEOF(buf));
- pa->szProtoName = mir_strdup(buf);
- GetDlgItemTextA(hwndDlg, IDC_ACCINTERNALNAME, buf, SIZEOF(buf));
- rtrim(buf);
- if (buf[0] == 0) {
- int count = 1;
- for (;;) {
- DBVARIANT dbv;
- mir_snprintf(buf, SIZEOF(buf), "%s_%d", pa->szProtoName, count++);
- if (db_get_s(NULL, buf, "AM_BaseProto", &dbv))
- break;
- db_free(&dbv);
- }
- }
- pa->szModuleName = mir_strdup(buf);
-
- if (!pa->tszAccountName[0]) {
- mir_free(pa->tszAccountName);
- pa->tszAccountName = mir_a2t(buf);
- }
-
- db_set_s(NULL, pa->szModuleName, "AM_BaseProto", pa->szProtoName);
- accounts.insert(pa);
-
- if ( ActivateAccount(pa)) {
- pa->ppro->OnEvent(EV_PROTO_ONLOAD, 0, 0);
- if (!db_get_b(NULL, "CList", "MoveProtoMenus", TRUE))
- pa->ppro->OnEvent(EV_PROTO_ONMENU, 0, 0);
- }
- }
-
- WriteDbAccounts();
- NotifyEventHooks(hAccListChanged, param->action, (LPARAM)pa);
-
- SendMessage(GetParent(hwndDlg), WM_MY_REFRESH, 0, 0);
- }
-
- EndDialog(hwndDlg, TRUE);
+ if (OnCreateAccount(hwndDlg))
+ EndDialog(hwndDlg, TRUE);
break;
case IDCANCEL:
@@ -463,59 +481,57 @@ INT_PTR CALLBACK AccMgrDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM
switch(message) {
case WM_INITDIALOG:
- {
- TAccMgrData *dat = (TAccMgrData *)mir_alloc(sizeof(TAccMgrData));
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
-
- TranslateDialogDefault(hwndDlg);
- Window_SetIcon_IcoLib(hwndDlg, SKINICON_OTHER_ACCMGR);
-
- Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("New account"));
- Button_SetIcon_IcoLib(hwndDlg, IDC_EDIT, SKINICON_OTHER_RENAME, LPGEN("Edit"));
- Button_SetIcon_IcoLib(hwndDlg, IDC_REMOVE, SKINICON_OTHER_DELETE, LPGEN("Remove account"));
- Button_SetIcon_IcoLib(hwndDlg, IDC_OPTIONS, SKINICON_OTHER_OPTIONS, LPGEN("Configure..."));
- Button_SetIcon_IcoLib(hwndDlg, IDC_UPGRADE, SKINICON_OTHER_ACCMGR, LPGEN("Upgrade account"));
-
- EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT), FALSE);
- EnableWindow( GetDlgItem(hwndDlg, IDC_REMOVE), FALSE);
- EnableWindow( GetDlgItem(hwndDlg, IDC_OPTIONS), FALSE);
- EnableWindow( GetDlgItem(hwndDlg, IDC_UPGRADE), FALSE);
- {
- LOGFONT lf;
- GetObject((HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- dat->hfntText = CreateFontIndirect(&lf);
+ TranslateDialogDefault(hwndDlg);
+ Window_SetIcon_IcoLib(hwndDlg, SKINICON_OTHER_ACCMGR);
- GetObject((HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0), sizeof(lf), &lf);
- lf.lfWeight = FW_BOLD;
- dat->hfntTitle = CreateFontIndirect(&lf);
+ dat = (TAccMgrData *)mir_alloc(sizeof(TAccMgrData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
- HDC hdc = GetDC(hwndDlg);
- HFONT hfnt = (HFONT)SelectObject(hdc, dat->hfntTitle);
+ Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("New account"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_EDIT, SKINICON_OTHER_RENAME, LPGEN("Edit"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_REMOVE, SKINICON_OTHER_DELETE, LPGEN("Remove account"));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_OPTIONS, SKINICON_OTHER_OPTIONS, LPGEN("Configure..."));
+ Button_SetIcon_IcoLib(hwndDlg, IDC_UPGRADE, SKINICON_OTHER_ACCMGR, LPGEN("Upgrade account"));
- TEXTMETRIC tm;
- GetTextMetrics(hdc, &tm);
- dat->titleHeight = tm.tmHeight;
- SelectObject(hdc, dat->hfntText);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_EDIT), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OPTIONS), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_UPGRADE), FALSE);
+ {
+ LOGFONT lf;
+ GetObject((HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ dat->hfntText = CreateFontIndirect(&lf);
- GetTextMetrics(hdc, &tm);
- dat->textHeight = tm.tmHeight;
- SelectObject(hdc, hfnt);
- ReleaseDC(hwndDlg, hdc);
+ GetObject((HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0), sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ dat->hfntTitle = CreateFontIndirect(&lf);
- dat->normalHeight = 4 + max(dat->titleHeight, GetSystemMetrics(SM_CYSMICON));
- dat->selectedHeight = dat->normalHeight + 4 + 2 * dat->textHeight;
+ HDC hdc = GetDC(hwndDlg);
+ HFONT hfnt = (HFONT)SelectObject(hdc, dat->hfntTitle);
- SendDlgItemMessage(hwndDlg, IDC_NAME, WM_SETFONT, (WPARAM)dat->hfntTitle, 0);
- SendDlgItemMessage(hwndDlg, IDC_TXT_ACCOUNT, WM_SETFONT, (WPARAM)dat->hfntTitle, 0);
- SendDlgItemMessage(hwndDlg, IDC_TXT_ADDITIONAL, WM_SETFONT, (WPARAM)dat->hfntTitle, 0);
- }
+ TEXTMETRIC tm;
+ GetTextMetrics(hdc, &tm);
+ dat->titleHeight = tm.tmHeight;
+ SelectObject(hdc, dat->hfntText);
- dat->iSelected = -1;
- sttSubclassAccList( GetDlgItem(hwndDlg, IDC_ACCLIST), TRUE);
- SendMessage(hwndDlg, WM_MY_REFRESH, 0, 0);
+ GetTextMetrics(hdc, &tm);
+ dat->textHeight = tm.tmHeight;
+ SelectObject(hdc, hfnt);
+ ReleaseDC(hwndDlg, hdc);
- Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, "AccMgr", "");
+ dat->normalHeight = 4 + max(dat->titleHeight, GetSystemMetrics(SM_CYSMICON));
+ dat->selectedHeight = dat->normalHeight + 4 + 2 * dat->textHeight;
}
+
+ SendDlgItemMessage(hwndDlg, IDC_NAME, WM_SETFONT, (WPARAM)dat->hfntTitle, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TXT_ACCOUNT, WM_SETFONT, (WPARAM)dat->hfntTitle, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TXT_ADDITIONAL, WM_SETFONT, (WPARAM)dat->hfntTitle, 0);
+
+ dat->iSelected = -1;
+ sttSubclassAccList( GetDlgItem(hwndDlg, IDC_ACCLIST), TRUE);
+ SendMessage(hwndDlg, WM_MY_REFRESH, 0, 0);
+
+ Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, "AccMgr", "");
return TRUE;
case WM_CTLCOLORSTATIC:
@@ -542,8 +558,6 @@ INT_PTR CALLBACK AccMgrDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM
case WM_DRAWITEM:
{
- int tmp;
- TCHAR *text;
HBRUSH hbrBack;
SIZE sz;
@@ -552,7 +566,6 @@ INT_PTR CALLBACK AccMgrDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM
LPDRAWITEMSTRUCT lps = (LPDRAWITEMSTRUCT)lParam;
PROTOACCOUNT *acc = (PROTOACCOUNT *)lps->itemData;
-
if ((lps->CtlID != IDC_ACCLIST) || (lps->itemID == -1) || !acc)
break;
@@ -571,6 +584,7 @@ INT_PTR CALLBACK AccMgrDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM
lps->rcItem.top += 2;
lps->rcItem.bottom -= 2;
+ int tmp;
if (acc->bOldProto)
tmp = SKINICON_OTHER_ON;
else if (acc->bDynDisabled)
@@ -593,7 +607,7 @@ INT_PTR CALLBACK AccMgrDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM
int length = SendDlgItemMessage(hwndDlg, IDC_ACCLIST, LB_GETTEXTLEN, lps->itemID, 0);
int size = max(length+1, 256);
- text = (TCHAR *)_alloca(sizeof(TCHAR) * size);
+ TCHAR *text = (TCHAR *)_alloca(sizeof(TCHAR) * size);
SendDlgItemMessage(hwndDlg, IDC_ACCLIST, LB_GETTEXT, lps->itemID, (LPARAM)text);
SelectObject(lps->hDC, dat->hfntTitle);