/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svl.hxx"

#define UNICODE

#include <string.h>
#include "ddeimp.hxx"
#include <svl/svdde.hxx>

// --- DdeInternal::InfCallback() ----------------------------------

#ifdef WNT
HDDEDATA CALLBACK DdeInternal::InfCallback(
				WORD, WORD, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD )
#else
#if defined ( MTW ) || ( defined ( GCC ) && defined ( OS2 )) || defined( ICC )
HDDEDATA CALLBACK __EXPORT DdeInternal::InfCallback(
				WORD, WORD, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD )
#else
HDDEDATA CALLBACK _export DdeInternal::InfCallback(
				WORD, WORD, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD )
#endif
#endif
{
	return (HDDEDATA)DDE_FNOTPROCESSED;
}

// --- DdeServiceList::DdeServiceList() ----------------------------

DdeServiceList::DdeServiceList( const String* pTopic )
{
	DWORD       hDdeInst = NULL;
	HCONVLIST   hConvList = NULL;
	HCONV       hConv = NULL;
	UINT        nStatus = DMLERR_NO_ERROR;
	HSZ         hTopic = NULL;

#ifndef OS2 // YD FIXME

	nStatus = DdeInitialize( &hDdeInst, (PFNCALLBACK) DdeInternal::InfCallback,
							 APPCLASS_STANDARD | APPCMD_CLIENTONLY |
							 CBF_FAIL_ALLSVRXACTIONS |
							 CBF_SKIP_ALLNOTIFICATIONS, 0L );

	if ( nStatus == DMLERR_NO_ERROR )
	{
		if ( pTopic )
		{
			LPCTSTR p = reinterpret_cast<LPCTSTR>(pTopic->GetBuffer());
#ifdef __MINGW32__
			hTopic = DdeCreateStringHandle( hDdeInst, const_cast<LPTSTR>(p), CP_WINUNICODE );
#else
			hTopic = DdeCreateStringHandle( hDdeInst, p, CP_WINUNICODE );
#endif
		}

		hConvList = DdeConnectList( hDdeInst, NULL, hTopic, NULL, NULL );
		nStatus = DdeGetLastError( hDdeInst );
	}

	if ( nStatus == DMLERR_NO_ERROR )
	{
		while ( ( hConv = DdeQueryNextServer( hConvList, hConv ) ) != NULL)
		{
			CONVINFO    aInf;
			TCHAR       buf[256], *p;
			HSZ         h;
#ifdef OS2
			aInf.nSize = sizeof( aInf );
#else
			aInf.cb = sizeof( aInf );
#endif
			if( DdeQueryConvInfo( hConv, QID_SYNC, &aInf))
			{
				h = aInf.hszServiceReq;
				if ( !h )
#ifndef OS2
					h = aInf.hszSvcPartner;
#else
					h = aInf.hszPartner;
#endif
				DdeQueryString( hDdeInst, h, buf, sizeof(buf) / sizeof(TCHAR), CP_WINUNICODE );
				p = buf + lstrlen( buf );
				*p++ = '|'; *p = 0;
				DdeQueryString( hDdeInst, aInf.hszTopic, p, sizeof(buf)/sizeof(TCHAR)-lstrlen( buf ),
								CP_WINUNICODE );
				aServices.Insert( new String( reinterpret_cast<const sal_Unicode*>(buf) ) );
			}
		}
		DdeDisconnectList( hConvList );
	}

	if ( hTopic)
		DdeFreeStringHandle( hDdeInst, hTopic );
	if ( hDdeInst )
		DdeUninitialize( hDdeInst );

#endif

}

// --- DdeServiceList::~DdeServiceList() ---------------------------

DdeServiceList::~DdeServiceList()
{
	String* s;
	while ( ( s = aServices.First() ) != NULL )
	{
		aServices.Remove( s );
		delete s;
	}
}

// --- DdeTopicList::DdeTopicList() --------------------------------

DdeTopicList::DdeTopicList( const String& rService )
{
	DdeConnection aSys( rService, String( reinterpret_cast<const sal_Unicode*>(SZDDESYS_TOPIC) ) );

	if ( !aSys.GetError() )
	{
		DdeRequest aReq( aSys, String( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_TOPICS) ), 500 );
		aReq.SetDataHdl( LINK( this, DdeTopicList, Data ) );
		aReq.Execute();
	}
}

// --- DdeTopicList::~DdeTopicList() -------------------------------

DdeTopicList::~DdeTopicList()
{
	String* s;
	while ( ( s = aTopics.First() ) != NULL )
	{
		aTopics.Remove( s );
		delete s;
	}
}

// --- DdeTopicList::Data() --------------------------------------------

IMPL_LINK( DdeTopicList, Data, DdeData*, pData )
{
	char*   p = (char*) (const void *) *pData;
	char*   q = p;
	short   i;
	char    buf[256];

	while ( *p && *p != '\r' && *p != '\n' )
	{
		q = buf; i = 0;
		while ( i < 255 && *p && *p != '\r' && *p != '\n' && *p != '\t' )
			*q++ = *p++, i++;
		*q = 0;
		while ( *p && *p != '\r' && *p != '\n' && *p != '\t' )
			p++;
		aTopics.Insert( new String( String::CreateFromAscii(buf) ) );
		if ( *p == '\t' )
			p++;
	}
	return 0;
}
