/* # skkinput (Simple Kana-Kanji Input)
 *
 * This file is part of skkinput.
 * Copyright (C) 2002
 * Takashi SAKAMOTO (PXG01715@nifty.ne.jp)
 *
 * 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, 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 skkinput; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */
//#include "local.h"
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include "XIMPacketP.h"

XIMPacket*
XIMPacket_Create (
	register Boolean		fBigEndian)
{
	XIMPacket*	pPacket ;

	pPacket	= malloc (sizeof (XIMPacket)) ;
	if (pPacket == NULL)
		return	NULL ;

	if (! (TVarbuffer_Initialize (&pPacket->m_bufData, sizeof (CARD8))) ||
		! (TVarbuffer_Require (&pPacket->m_bufData, XIM_HEADER_SIZE))) {
		free (pPacket) ;
		return	NULL ;
	}
	pPacket->m_fBigEndian		= fBigEndian ;
	pPacket->m_pInputContext	= NULL ;
	pPacket->m_uSyncMode		= XIMPS_NO ;
	pPacket->m_nRefer			= 1 ;
	return	pPacket ;
}

void
XIMPacket_AddRef (
	register XIMPacket*		pPacket)
{
	assert (pPacket != NULL) ;
	pPacket->m_nRefer	++ ;
	assert (pPacket->m_nRefer > 0) ;
	return ;
}

void
XIMPacket_Release (
	register XIMPacket*		pPacket)
{
	assert (pPacket != NULL) ;

	pPacket->m_nRefer	-- ;
	if (pPacket->m_nRefer <= 0) {
		TVarbuffer_Uninitialize (&pPacket->m_bufData) ;
		free (pPacket) ;
	}
	return ;
}

Boolean
XIMPacket_SetHeader (
	register XIMPacket*		pPacket,
	register int			nMajor,
	register int			nMinor)
{
	register CARD8*		pData ;

	assert (pPacket != NULL) ;

	pData	= TVarbuffer_GetBuffer (&pPacket->m_bufData) ;
	assert (pData != NULL) ;
	*pData	++		= nMajor ;
	*pData	++		= nMinor ;
	/*	CARD16 分の 0 を入れる。*/
	*pData	++		= 0 ;
	*pData	++		= 0 ;
	return	True ;
}

void
XIMPacket_GetHeader (
	register XIMPacket*		pPacket,
	register int*			pnMajor,
	register int*			pnMinor)
{
	register CARD8*		pData ;

	assert (pPacket != NULL) ;

	pData	= TVarbuffer_GetBuffer (&pPacket->m_bufData) ;
	assert (pData != NULL) ;
	if (pnMajor != NULL)
		*pnMajor	= *pData ;
	pData	++ ;
	if (pnMinor != NULL)
		*pnMinor	= *pData ;
	return ;
}

Boolean
XIMPacket_SetEndian (
	register XIMPacket*		pPacket,
	register Boolean		fBigEndian)
{
	assert (pPacket != NULL) ;
	pPacket->m_fBigEndian	= fBigEndian ;
	return	True ;
}

Boolean
XIMPacket_GetEndian (
	register XIMPacket*		pPacket)
{
	assert (pPacket != NULL) ;
	return	pPacket->m_fBigEndian ;
}

Boolean
XIMPacket_SetInputContext (
	register XIMPacket*			pPacket,
	register XIMInputContext*	pInputContext)
{
	assert (pPacket != NULL) ;
	pPacket->m_pInputContext	= pInputContext ;
	return	True ;
}

Boolean
XIMPacket_SetSyncMode (
	register XIMPacket*			pPacket,
	register XIMPacketSyncMode	uMode)
{
	assert (pPacket != NULL) ;
	pPacket->m_uSyncMode	= uMode ;
	return	True ;
}

XIMPacketSyncMode
XIMPacket_GetSyncMode (
	register XIMPacket*			pPacket)
{
	assert (pPacket != NULL) ;
	return	pPacket->m_uSyncMode ;
}

XIMInputContext*
XIMPacket_GetInputContext (
	register XIMPacket*			pPacket)
{
	assert (pPacket != NULL) ;
	return	pPacket->m_pInputContext ;
}

int
XIMPacket_SetLength (
	register XIMPacket*			pPacket)
{
	register int	nLength ;

	assert (pPacket != NULL) ;
	nLength	= (TVarbuffer_GetUsage (&pPacket->m_bufData) - XIM_HEADER_SIZE) / 4 ;
	XIMPacket_SetCard16 (pPacket, 2, (CARD16) nLength) ;
	return	nLength ;
}

CARD8*
XIMPacket_GetData (
	register XIMPacket*			pPacket)
{
	assert (pPacket != NULL) ;
	return	TVarbuffer_GetBuffer (&pPacket->m_bufData) ;
}

int
XIMPacket_GetDataSize (
	register XIMPacket*			pPacket)
{
	assert (pPacket != NULL) ;
	return	TVarbuffer_GetUsage (&pPacket->m_bufData) ;
}

Boolean
XIMPacket_AddCard8 (
	register XIMPacket*			pPacket,
	CARD8						c8Data)
{
	assert (pPacket != NULL) ;
	return	TVarbuffer_Add (&pPacket->m_bufData, &c8Data, 1) ;
}

Boolean
XIMPacket_AddCard8N (
	register XIMPacket*			pPacket,
	register int				nCard8)
{
	assert (pPacket != NULL) ;
	return	TVarbuffer_Require (&pPacket->m_bufData, nCard8) ;
}

Boolean
XIMPacket_AddCard16 (
	register XIMPacket*			pPacket,
	register CARD16				c16Data)
{
	CARD8			rc8Data [2] ;
	register CARD8*	ptr ;

	assert (pPacket != NULL) ;

	ptr	= rc8Data ;
	if (pPacket->m_fBigEndian) {
		*ptr ++	= (CARD8) (c16Data >> 8) ;
		*ptr ++	= (CARD8) (c16Data >> 0) ;
	} else {
		*ptr ++	= (CARD8) (c16Data >> 0) ;
		*ptr ++	= (CARD8) (c16Data >> 8) ;
	}
	return	TVarbuffer_Add (&pPacket->m_bufData, rc8Data, 2) ;
}

Boolean
XIMPacket_AddCard32 (
	register XIMPacket*			pPacket,
	register CARD32				c32Data)
{
	CARD8			rc8Data [4] ;
	register CARD8*	ptr ;

	assert (pPacket != NULL) ;

	ptr	= rc8Data ;
	if (pPacket->m_fBigEndian) {
		*ptr ++	= (CARD8) (c32Data >> 24) ;
		*ptr ++	= (CARD8) (c32Data >> 16) ;
		*ptr ++	= (CARD8) (c32Data >>  8) ;
		*ptr ++	= (CARD8) (c32Data >>  0) ;
	} else {
		*ptr ++	= (CARD8) (c32Data >>  0) ;
		*ptr ++	= (CARD8) (c32Data >>  8) ;
		*ptr ++	= (CARD8) (c32Data >> 16) ;
		*ptr ++	= (CARD8) (c32Data >> 24) ;
	}
	return	TVarbuffer_Add (&pPacket->m_bufData, rc8Data, 4) ;
}

Boolean
XIMPacket_AddBitmask16 (
	register XIMPacket*			pPacket,
	register BITMASK16			bm16)
{
	return	XIMPacket_AddCard16 (pPacket, (CARD16)bm16) ;
}

Boolean
XIMPacket_AddBitmask32 (
	register XIMPacket*			pPacket,
	register BITMASK32			bm32)
{
	return	XIMPacket_AddCard32 (pPacket, (CARD32)bm32) ;
}

Boolean
XIMPacket_AddString8 (
	register XIMPacket*			pPacket,
	register const char*		pString,
	register int				nString)
{
	assert (pPacket != NULL) ;

	if (pString == NULL || nString <= 0)
		return	True ;
	return	TVarbuffer_Add (&pPacket->m_bufData, pString, nString) ;
}

Boolean
XIMPacket_AddPad (
	register XIMPacket*			pPacket,
	register size_t				nLength)
{
	assert (pPacket != NULL) ;
	return	TVarbuffer_Require (&pPacket->m_bufData, IMPAD (nLength)) ;
}

Boolean
XIMPacket_SetCard8 (
	register XIMPacket*			pPacket,
	register int 				nIndex,
	register CARD8				c8Data)
{
	register CARD8*	pData ;

	assert (pPacket != NULL) ;

	if (nIndex < 0 || nIndex >= TVarbuffer_GetUsage (&pPacket->m_bufData))
		return	False ;
	pData	= TVarbuffer_GetBuffer (&pPacket->m_bufData) ;
	*(pData + nIndex)	= c8Data ;
	return	True ;
}

Boolean
XIMPacket_SetCard16 (
	register XIMPacket*			pPacket,
	register int				nIndex,
	register CARD16				c16Data)
{
	register CARD8*	pData ;

	assert (pPacket != NULL) ;

	if (nIndex < 0 || (nIndex + 2) > TVarbuffer_GetUsage (&pPacket->m_bufData))
		return	False ;
	pData	= (CARD8 *)TVarbuffer_GetBuffer (&pPacket->m_bufData) + nIndex ;
	if (pPacket->m_fBigEndian) {
		*pData ++	= (CARD8) (c16Data >> 8) ;
		*pData ++	= (CARD8) (c16Data >> 0) ;
	} else {
		*pData ++	= (CARD8) (c16Data >> 0) ;
		*pData ++	= (CARD8) (c16Data >> 8) ;
	}
	return	True ;
}

Boolean
XIMPacket_SetCard32 (
	register XIMPacket*			pPacket,
	register int				nIndex,
	register CARD32				c32Data)
{
	register CARD8*	pData ;

	assert (pPacket != NULL) ;

	if (nIndex < 0 || (nIndex + 4) > TVarbuffer_GetUsage (&pPacket->m_bufData))
		return	False ;
	pData	= (CARD8 *)TVarbuffer_GetBuffer (&pPacket->m_bufData) + nIndex ;
	if (pPacket->m_fBigEndian) {
		*pData ++	= (CARD8) (c32Data >> 24) ;
		*pData ++	= (CARD8) (c32Data >> 16) ;
		*pData ++	= (CARD8) (c32Data >>  8) ;
		*pData ++	= (CARD8) (c32Data >>  0) ;
	} else {
		*pData ++	= (CARD8) (c32Data >>  0) ;
		*pData ++	= (CARD8) (c32Data >>  8) ;
		*pData ++	= (CARD8) (c32Data >> 16) ;
		*pData ++	= (CARD8) (c32Data >> 24) ;
	}
	return	True ;
}

Boolean
XIMPacket_GetCard16 (
	register XIMPacket*			pPacket,
	register int				nIndex,
	register CARD16*			pc16Data)
{
	register CARD8*			pData ;
	register unsigned int	uData ;

	assert (pPacket != NULL) ;
	assert (pc16Data != NULL) ;

	if (nIndex < 0 || (nIndex + 2) > TVarbuffer_GetUsage (&pPacket->m_bufData))
		return	False ;
	pData	= (CARD8 *)TVarbuffer_GetBuffer (&pPacket->m_bufData) + nIndex ;
	if (pPacket->m_fBigEndian) {
		uData		= *pData ++ ;
		uData		= (uData << 8) | *pData ;
	} else {
		uData		= *pData ++ ;
		uData		= ((CARD16) *pData << 8) | uData ;
	}
	*pc16Data	= uData ;
	return	True ;
}

void
XIMPacket_Clear (
	register XIMPacket*			pPacket)
{
	assert (pPacket != NULL) ;
	TVarbuffer_Clear   (&pPacket->m_bufData) ;
	TVarbuffer_Require (&pPacket->m_bufData, XIM_HEADER_SIZE) ;
	return ;
}

void
XIMPacket_Show (
	register XIMPacket*			pPacket)
{
	register CARD8*		pData ;
	register int		nSize, nMajor, nMinor, nLength ;

	assert (pPacket != NULL) ;

	pData	= TVarbuffer_GetBuffer (&pPacket->m_bufData) ;
	nSize	= TVarbuffer_GetUsage  (&pPacket->m_bufData) ;
	if (nSize < XIM_HEADER_SIZE) {
		fprintf (stderr, "Packet(%d): Bad packet\n", nSize) ;
		return ;
	}
	nMajor	= *pData ++ ;
	nMinor	= *pData ++ ;
	if (pPacket->m_fBigEndian) {
		nLength	= *pData ++ ;
		nLength	= (nLength << 8) | *pData ;
	} else {
		nLength	= *pData ++ ;
		nLength	= nLength | ((CARD16)*pData << 8) ;
	}
	fprintf (stderr, "Packet(%d): Major(%d), Minor(%d), Length(%d)",
			 nSize, nMajor, nMinor, nLength) ;
	return ;
}

