void mwIm_conversation_opened(mwConversation *conv) {
	mwIdBlock *idb = mwConversation_getTarget(conv);
	HANDLE hContact = FindContactByUserId(idb->user);

	if(!hContact) {
		mwSametimeList *user_list = mwSametimeList_new();
		mwSametimeGroup *stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None"));
		mwSametimeUser *stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, idb);

		AddContact(stuser, (options.add_contacts ? false : true));
		GetMoreDetails(idb->user);
	}
	
	ContactMessageQueue::iterator i;
	EnterCriticalSection(&q_cs);
	if((i = contact_message_queue.find(hContact)) != contact_message_queue.end()) {
		while(i->second.size()) {
			mwConversation_send(conv, mwImSend_PLAIN, (gconstpointer)i->second.front().c_str());
			i->second.pop();
		}
		contact_message_queue.erase(i);
	}
	LeaveCriticalSection(&q_cs);

	// gives linker error 'unresolved external symbol' :( So instead we will either add ciphers to the session or not (see session.cpp)
	//mwConversation_setEncrypted(conv, options.encrypt_session);
}
/** A message has been received on a conversation */
void mwIm_conversation_recv(mwConversation *conv, mwImSendType type, gconstpointer msg) {
	mwIdBlock *idb = mwConversation_getTarget(conv);
	HANDLE hContact = FindContactByUserId(idb->user);

	if(type == mwImSend_TYPING) {
		CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, (LPARAM)(GPOINTER_TO_UINT(msg) == 0 ? 0 : 2));
		return;
	}

	if(type != mwImSend_PLAIN) return;

	wchar_t temp[MAX_MESSAGE_SIZE];
	char text[MAX_MESSAGE_SIZE];

	MultiByteToWideChar(CP_UTF8, 0, (const char *)msg, -1, temp, MAX_MESSAGE_SIZE);
	WideCharToMultiByte(CallService(MS_LANGPACK_GETCODEPAGE, 0, 0), WC_COMPOSITECHECK, temp, -1, text, MAX_MESSAGE_SIZE * sizeof(char), 0, 0);

	CCSDATA ccs = {0};
	PROTORECVEVENT pre = {0};

	ccs.hContact = hContact;
	ccs.szProtoService = PSR_MESSAGE;
	ccs.wParam = 0;
	ccs.lParam = (LPARAM)⪯

	pre.timestamp = (DWORD)time(0);

	int tMsgBodyLen = strlen(text);
	int tRealBodyLen = wcslen(temp);

	int tMsgBufLen = (tMsgBodyLen+1) * sizeof(char) + (tRealBodyLen+1)*sizeof( wchar_t );
	char* tMsgBuf = ( char* )malloc( tMsgBufLen );

	char* p = tMsgBuf;

	strcpy( p, text );
	p += (tMsgBodyLen+1);

	if ( tRealBodyLen != 0 ) {
		wcscpy((wchar_t *)p, temp);
		pre.flags = PREF_UNICODE;
	}

	pre.szMessage = tMsgBuf;

	DBDeleteContactSetting(hContact, "CList", "Hidden");

	CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);

	free(tMsgBuf);
}
/** A conversation has been closed */
void mwIm_conversation_closed(mwConversation *conv, guint32 err) {
	if(err & ERR_FAILURE && err != CONNECTION_RESET) {
		char *msg = mwError(err);
		TCHAR *ts = u2t(msg);
		//MessageBox(0, ts, TranslateT("Sametime Error"), MB_OK | MB_ICONWARNING);
		ShowError(TranslateTS(ts));
		g_free(msg);
		free(ts);
	}

	mwIdBlock *idb = mwConversation_getTarget(conv);
	HANDLE hContact = FindContactByUserId(idb->user);
	if(hContact) {
		ContactMessageQueue::iterator i;
		EnterCriticalSection(&q_cs);
		if((i = contact_message_queue.find(hContact)) != contact_message_queue.end()) {
			contact_message_queue.erase(i);
		}
		LeaveCriticalSection(&q_cs);
	}
}
MeanwhileContact *MeanwhileSession::conversationContact(
        struct mwConversation *conv)
{
    struct mwIdBlock *target = mwConversation_getTarget(conv);
    if (target == 0L || target->user == 0L) {
        return 0L;
    }
    QString user(target->user);

    MeanwhileContact *contact = static_cast<MeanwhileContact *>(account->contacts().value(user));

    struct mwLoginInfo *logininfo = mwConversation_getTargetInfo(conv);
    QString name = getNickName(logininfo);

    if (!contact) {
	account->addContact(user, name, 0L, Kopete::Account::Temporary);
	    contact = static_cast<MeanwhileContact *>(account->contacts().value(user));
    } else
        contact->setNickName(name);

    return contact;
}