/*
================================ COPYRIGHT ================================
The contents of this file are subject to the VTech Informations Ltd. License
of VT-OS Ver. 1.1 operating system (the "License"); you may not use this 
file except in compliance with the License.  

Software distributed under the License is distributed on an "AS IS" basis, 
WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License 
for the specific language governing rights and limitations under the License.
  
The Original Code is VT-OS Ver. 1.1 Operating System, released 
on October 1st, 1999
	
The Initial Developer of the Original Code is VTech Informations Ltd.  All 
codes are Copyright (C) VTech Informations Ltd. 1999.  All Rights Reserved.
===========================================================================
*/

/*
===========================================================================
File        :   psyncfx2.c
Author(s)   :   Kenny Ng
Company     :   VTech Informations Ltd.
Project     :   Helio 
Date:	    :   October 1st, 1999
Purpose:	:   application c file
Revision    :   1.1
Note        :   None
===========================================================================
*/              

#include "uartmgr.h"
#include "syncfx.h"
#include "comctrl.h"
#include "pdasync.h"
#include "synctout.h"
#include "combuf.h"
#include "app.h"
#include "lcddebug.h"
#include "sch.h"
#include "telecom.h"
#include "expdef.h"
#include "Uart.h"

UBYTE		SendBuffer[3072];
UBYTE 		need_del;
RecordID 	del_recid;
DatabaseID 	del_dbid;

USHORT 	IntHookISR(USHORT ISRID, USHORT int_no, UWORD offset);
void    UartWriteBuf(WORD port, BYTE *buf, WORD length);
void 	InitUart();
void 	DeleteFailRecord();
void 	DispStr(BYTE *msg);

extern 	UWORD hport;
extern 	BYTE timeoutmsg[100];
extern 	AppID new_app_id;
extern 	MatInfoList *mat_info_ptr[TOTAL_SLOT];

#define SBlockAddrS(sblock)      (mat_info_ptr[SBlockMat(sblock)]->base_addr + (((sblock & 0x0000FFFF) + 1) << 12))
#define EL32(x)         (x <<24 | (x &0xff00) <<8 | (x &0xff0000) >>8 | x>>24)


void SendBData(UWORD sblock, UWORD offset, UWORD num_byte, USHORT *cs)
{
	UWORD i;
	BYTE *dest_addr;
	UWORD base_addr;
	USHORT block;
	
	base_addr = SBlockAddrS(sblock);
	dest_addr = (BYTE*)(base_addr + offset);
	
	for(i=0;i<num_byte;i++)
	{
		if((UWORD)dest_addr >= base_addr + BLOCK_SIZE)
		{
			if (MemoryNextBlock(mat_info_ptr[SBlockMat(sblock)], SBlockBlock(sblock), &block) != TRUE)
			{
				
			}
			sblock = MakeSBlock(SBlockMat(sblock), block);
			base_addr = SBlockAddrS(sblock);
			dest_addr = (BYTE*)(base_addr + RECHEADER_SIZE) ;
		}
		(*cs) ^= *(dest_addr);
		PortSendChar(*(dest_addr++));
	}
}


/*************************************
Send record info
**************************************/
void SyncRecInfoReq()
{
	BufferEmpty();	
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncRecInfoReq2);
    PortWaitForChar(RECINFO_SEQ,RECINFO_SEQ,RECINFO_SEQ,TRUE);
    PortSendChar(RECINFO_ACK);
}

void SyncRecInfoReq2(UBYTE x)
{
	SetWaitReturnFct(SyncRecInfoReq3);
    PortWaitForLength(6);   /* dbid + cs */
}

void SyncRecInfoReq3(UBYTE x)
{
	DatabaseID dbid;
	RecordID recid;
	SHORT cs, i, j, b;
	USHORT block;
	UWORD rec_num, sblock, len;
	BYTE *data;
	RecordHeader* rec_ptr;
	UWORD total_rec = 0;
	
	
	SetWaitReturnFct(NULL);
	dbid = *(DatabaseID*) sync_buf;
	
	cs = *(SHORT*) &sync_buf[8];
	BufferEmpty();
	
	for(b=0;b<TOTAL_SLOT;b++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[b], dbid, &block) == TRUE)
            break;
		if(BlockType(mat_info_ptr[b]->mat[block].attribute) == MAT_BLOCK_DB_REC)
			break;
	}
	if(b>=TOTAL_SLOT)
	{
#ifdef DEBUG
		LcdPrintf(" DB not found");
#endif
		BufferEmpty();
		PortSendChar(NAK);
	}
	else
	{
		cs = 0;
		if((DataOpenDB(dbid, DB_NO_SORT, OPEN_RW)) != TRUE)
		{
#ifdef DEBUG
			LcdPrintf("cannot open DB");
#endif
			BufferEmpty();
			PortSendChar(NAK);
		}
		else
		{
			DataTotalRecord(dbid, &total_rec);
			PortSendChar(RECINFO_DATA_ACK);
			data = (BYTE*) &total_rec;
			for(i=0;i<4;i++)
			{
                cs ^= data[i];
                PortSendChar(data[i]);
			}
			for(i=0;i<total_rec;i++)
			{
				DataNumtoRecID(dbid, i, &recid);
				
				if(DataRecordBlock(MakeSBlock(b,block), recid, &sblock,
                    &rec_ptr) != TRUE)  /* error */
				{
					/* send rubbish to PC */
					for(j=0;j<RECHEADER_SIZE;j++)
					{
#ifdef DEBUG
						LcdPrintf(" error: cannot read record ");
#endif
						cs ^= 0;
						PortSendChar(0);
					}
					continue;
				}
				
				data = (BYTE*) rec_ptr;
				for(j=0;j<RECHEADER_SIZE;j++)
				{
					cs ^= data[j];
					PortSendChar(data[j]);
				}
			}
			data = (BYTE*) &cs;
			PortSendChar(data[0]);
			BufferEmpty();
			PortSendChar(data[1]);                                  
			
		}
	}
	DataCloseAllDB();
	SetComHandleEvent(SyncStateDBEnq);
#ifdef DEBUG
	LcdPrintf(" eria ");
#endif
}


void SyncSchReadDate(DatabaseID dbid, UWORD total_rec)
{
	USHORT cs = 0;
	RecordID recid;
	UWORD i, tr, j;
	UWORD br;
	BYTE *rb;	
	
	for(i=0;i<total_rec;i++)
	{
		DataOpenRecord(dbid, i, &recid, NULL);
		DataGetField(dbid, recid, 0, &rb, &br);
		
		for(j=0;j<3;j++)
		{
			cs ^= rb[j];
			PortSendChar(rb[j]);
		}
		
		if(SyncCheckScheduleRecordChange(dbid, recid) == TRUE)
		{
			PortSendChar(0x01);
			cs ^= 0x01;
		}
		else
		{
			PortSendChar(0x00);
			cs ^= 0x00;
		}
		
		DataCloseRecord(dbid, recid);
	}
	rb = (BYTE*)&cs;
	PortSendChar(rb[0]);
	PortSendChar(rb[1]);
}



/*************************************
Send Sch record info
rec header + field 0
**************************************/
void SyncSchRecInfoReq()
{
	SetComHandleEvent(NULL);
	SetWaitReturnFct(SyncSchRecInfoReq2);
	PortWaitForChar(RECINFO_SEQ,RECINFO_SEQ,RECINFO_SEQ,TRUE);
	PortSendChar(SCHRECINFO_ACK);
}

void SyncSchRecInfoReq2(UBYTE x)
{
	SetWaitReturnFct(SyncSchRecInfoReq3);
	PortWaitForLength(6);   /* dbid + cs */
}

void SyncSchRecInfoReq3(UBYTE x)
{
	DatabaseID dbid;
	RecordID recid;
	SHORT cs, i, j, b;
	USHORT block;
	UWORD rec_num, sblock, len;
	BYTE *data;
	RecordHeader* rec_ptr;
	UWORD total_rec = 0;
	BYTE *f_buf;
	UWORD br;
	
	SetWaitReturnFct(NULL);
	
	dbid = *(DatabaseID*) sync_buf;
	
	
	cs = *(SHORT*) &sync_buf[8];
	BufferEmpty();
	
	for(b=0;b<TOTAL_SLOT;b++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[b], dbid, &block) == TRUE)
            break;
		if(BlockType(mat_info_ptr[b]->mat[block].attribute) == MAT_BLOCK_DB_REC)
			break;
	}
	if(b>=TOTAL_SLOT)
	{
		BufferEmpty();
		PortSendChar(NAK);
	}
	else
	{
		cs = 0;
		if((DataOpenDB(dbid, 0, OPEN_RW)) != TRUE)
		{
			BufferEmpty();
			PortSendChar(NAK);
		}
		else
		{
			DataTotalRecord(dbid, &total_rec);
			PortSendChar(RECINFO_DATA_ACK);
			data = (BYTE*) &total_rec;
			for(i=0;i<4;i++)
			{
                cs ^= data[i];
                PortSendChar(data[i]);
			}
			if(total_rec)
			{                 
                for(i=0;i<total_rec;i++)
				{
					DataNumtoRecID(dbid, i, &recid);
					if(DataRecordBlock(MakeSBlock(b,block), recid, &sblock,
						&rec_ptr) != TRUE)  /* error */
					{
                        /* send rubbish to PC */
						for(j=0;j<RECHEADER_SIZE;j++)
						{
							cs ^= 0;
							PortSendChar(0);
						}
						continue;
					}
					
					data = (BYTE*) rec_ptr;
					for(j=0;j<RECHEADER_SIZE;j++)
					{
                        cs ^= data[j];
                        PortSendChar(data[j]);
					}
				}
				
				data = (BYTE*) &cs;
				PortSendChar(data[0]);
				BufferEmpty();
				PortSendChar(data[1]);
				SyncSchReadDate(dbid, total_rec);
				
			}
		}
	}
	
	DataCloseAllDB();//(dbid);
	SetComHandleEvent(SyncStateDBEnq);
}


/*************************************
Send archive record info
**************************************/
void SyncRecArcInfoReq()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncRecArcInfoReq2);
    PortWaitForChar(RECARCINFO_SEQ,RECARCINFO_SEQ,RECARCINFO_SEQ,TRUE);
    PortSendChar(RECARCINFO_ACK);
}

void SyncRecArcInfoReq2(UBYTE x)
{
	SetWaitReturnFct(SyncRecArcInfoReq3);
	PortWaitForLength(6);   /* dbid + cs */
}

void SyncRecArcInfoReq3(UBYTE x)
{
	DatabaseID dbid;
	RecordID recid;
	SHORT cs, i, j, b;
	USHORT block;
	UWORD rec_num, sblock, len, delay;
	BYTE *data;
	RecordHeader* rec_ptr;
	SortTableLnkPtr sort_tbl;
	UWORD total_rec = 0;
	
	SetWaitReturnFct(NULL);
	
	dbid = *(DatabaseID*) sync_buf;
	
	cs = *(SHORT*) &sync_buf[8];
	BufferEmpty();
	
	for(b=0;b<TOTAL_SLOT;b++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[b], dbid, &block) == TRUE)
            if(BlockType(mat_info_ptr[b]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	if(b>=TOTAL_SLOT)
	{
#ifdef DEBUG
		LcdPrintf(" DB not found");
#endif
		BufferEmpty();
		PortSendChar(NAK);
	}
	else
	{
		cs = 0;
		
		if(DataBuildArchiveSortTable(MakeSBlock(b,block), DB_NO_SORT, &sort_tbl) != TRUE)
		{
			SetComHandleEvent(SyncStateDBEnq);
			BufferEmpty();
			PortSendChar(NAK);
			return;
		}
		
		total_rec = 0;
		for(i=0;i<sort_tbl->total_entry;i++)
		{
			if (sort_tbl->rec_id[i] != 0xFFFFFFFF)
				total_rec++;
			else
				break;
		}
		
#ifdef DEBUG
		//                LcdPrintf("ttl: %d ", total_rec);
#endif
		
		for(delay=0;delay<0x1ff;delay++);      // delay for a while
		PortSendChar(RECARCINFO_DATA_ACK);
#ifdef DEBUG
		LcdPrintf("\nRec_data_ack sent ");
#endif
		for(delay=0;delay<0x1ff;delay++);      // delay for a while
		data = (BYTE*) &total_rec;
		for(i=0;i<4;i++)
		{
			cs ^= data[i];
			PortSendChar(data[i]);
		}
		for(i=0;i<total_rec;i++)
		{
			recid = sort_tbl->rec_id[i];
			
			if(DataRecordBlock(MakeSBlock(b,block), recid, &sblock,
				&rec_ptr) != TRUE)  /* error */
			{
				/* send rubbish to PC */
				for(j=0;j<RECHEADER_SIZE;j++)
				{
#ifdef DEBUG
					//                                        LcdPrintf(" err in read record id %ld ", recid);
#endif
					cs ^= 0;
					PortSendChar(0);
				}
				continue;
			}
			
			data = (BYTE*) rec_ptr;
			for(j=0;j<RECHEADER_SIZE;j++)
			{
				cs ^= data[j];
				PortSendChar(data[j]);
			}
		}
		data = (BYTE*) &cs;
		PortSendChar(data[0]);
		BufferEmpty();
		qfree((sort_tbl)->rec_id);
		qfree(sort_tbl);
		PortSendChar(data[1]);                                  
	}
	SetComHandleEvent(SyncStateDBEnq);
#ifdef DEBUG
	LcdPrintf(" eai ");
#endif
}


/*************************************
Send modified record info
**************************************/
void SyncReadRecInf()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncReadRecInf2);
    PortWaitForChar(RECINFO_SEQ,RECINFO_SEQ,RECINFO_SEQ,TRUE);
    PortSendChar(MODIREC_ACK);
}

void SyncReadRecInf2(UBYTE x)
{
	SetWaitReturnFct(SyncReadRecInf3);
	PortWaitForLength(10);   /* dbid + modidate + cs */
}

void SyncReadRecInf3(UBYTE x)
{
	DatabaseID dbid;
	RecordID recid;
	SHORT cs, i, j, b;
	USHORT block;
	UWORD modidate;
	UWORD rec_num, sblock, len;
	BYTE *data;
	RecordHeader* rec_ptr;
	UWORD total_rec = 0;
	
	SetWaitReturnFct(NULL);
	BufferEmpty();
	
	dbid = *(DatabaseID*) sync_buf;
	modidate = *(((UWORD*) sync_buf) + 1);
	
	cs = *(SHORT*) &sync_buf[8];
	
	for(b=0;b<TOTAL_SLOT;b++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[b], dbid, &block) == TRUE)
            if(BlockType(mat_info_ptr[b]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	if(b>=TOTAL_SLOT)
	{
		BufferEmpty();
		PortSendChar(NAK);
#ifdef DEBUG
		LcdPrintf(" DB not found");
#endif
	}
	else
	{
		cs = 0;
		if((DataOpenDB(dbid, DB_NO_SORT, OPEN_RW)) != TRUE)
		{
#ifdef DEBUG
			LcdPrintf( " db not found ");
#endif
			BufferEmpty();
			PortSendChar(NAK);
		}
		else
		{
			DataTotalRecord(dbid, &total_rec);
#ifdef DEBUG
			//                LcdPrintf("ttl: %ld ", total_rec);
#endif
			PortSendChar(RECINFO_DATA_ACK);
			data = (BYTE*) &total_rec;
			for(i=0;i<4;i++)
			{
                cs ^= data[i];
                PortSendChar(data[i]);
			}
			for(i=0;i<total_rec;i++)
			{
				DataNumtoRecID(dbid, i, &recid);
				
				if(DataRecordBlock(MakeSBlock(b,block), recid, &sblock,
                    &rec_ptr) != TRUE)  /* error */
				{
#ifdef DEBUG
					LcdPrintf(" rec miss ");
#endif
					/* send rubbish to PC */
					for(j=0;j<RECHEADER_SIZE;j++)
					{
						cs ^= 0;
						PortSendChar(0);
					}
					continue;
				}
				data = (BYTE*) rec_ptr;
				for(j=0;j<RECHEADER_SIZE;j++)
				{
					cs ^= data[j];
					PortSendChar(data[j]);
				}
			}
			data = (BYTE*) &cs;
			PortSendChar(data[0]);
			BufferEmpty();
			PortSendChar(data[1]);
		}
	}
	DataCloseAllDB();(dbid);
	SetComHandleEvent(SyncStateDBEnq);
#ifdef DEBUG
	LcdPrintf(" ereci ");
#endif
}

/*************************************
Send a record
**************************************/
void SyncReadRec()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncReadRec2);
    PortWaitForChar(RECDATA_SEQ, RECDATA_SEQ, RECDATA_SEQ, TRUE);
    PortSendChar(RECDATA_ACK);
}

void SyncReadRec2(UBYTE x)
{
	SetWaitReturnFct(SyncReadRec3);
    PortWaitForLength(10);   /* dbid + recid + cs */
}

RecordHeader* read_rec_ptr;
UWORD read_rec_sblock;
UWORD read_rec_len;
UWORD read_rec_tran_len;
UWORD read_rec_tran_remain;
void SyncReadRec3(UBYTE x)
{
	DatabaseID dbid;
	RecordID recid;
	SHORT cs;
	UWORD i;
	USHORT block;
	UWORD rec_num ;
	BYTE *data;
	UWORD rec_size;
	
	SetWaitReturnFct(NULL);
	
	dbid = *(DatabaseID*) sync_buf;        
	recid = *(((RecordID*) sync_buf)+1);        
	
	cs = *(SHORT*) &sync_buf[8];
	
	for(i = 0; i < TOTAL_SLOT; i++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[i], dbid, &block) == TRUE)
            if(BlockType(mat_info_ptr[i]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	
	
	if(i >= TOTAL_SLOT)
	{
		BufferEmpty();
		PortSendChar(REC_NAK);
	}
	else
	{
		DataClearFieldCache();
		if((DataRecordBlock(MakeSBlock(i,block), recid, &read_rec_sblock, &read_rec_ptr))!=TRUE)
		{
			BufferEmpty();
			PortSendChar(REC_NAK);
		}
		else
		{
			DataRecordInfo(dbid, recid, &rec_size, NULL, NULL, NULL, NULL);
			PortSendChar(REC_DATA);
			i = rec_size / (BLOCK_SIZE - RECHEADER_SIZE);  /* number of block */
			read_rec_len = rec_size - i * RECHEADER_SIZE + 2;// + RECHEADER_SIZE;
			read_rec_tran_len = read_rec_len -  2;
			read_rec_tran_remain = read_rec_tran_len;
			
			
			BufferEmpty();
			data = (BYTE*) &read_rec_len;
			for(i=0;i<3;i++)
                PortSendChar(data[i]);
			
			SetWaitReturnFct(SyncReadRec4);
			PortWaitForChar(REC_ACK, REC_NAK, REC_ACK, TRUE);
			PortSendChar(data[i]);
			
			return;
			
		}
	}
	BufferEmpty();
	SetComHandleEvent(SyncStateDBEnq);
}

WORD this_size;
USHORT read_rec_cs;
BYTE *read_rec_data;

UWORD last_read_rec_sblock;
BYTE *last_read_rec_data;
UWORD last_read_rec_tran_remain;

void SyncReadRec4(UBYTE x)
{
	USHORT cs = 0;
	UWORD i;
	
	
#ifdef DEBUG
	BYTE sbuf[50];
	sprintf(sbuf, "\n ReadRec4 ", this_size);
	LcdPrintf(sbuf);
#endif
	
	
	read_rec_data = (BYTE*) read_rec_ptr;
	
	BufferEmpty();
	SetWaitReturnFct(NULL);
	if( x == REC_NAK)
	{
		SetComHandleEvent(SyncStateDBEnq);
		return;
	}
	read_rec_cs = 0;
	for(i=0;i<RECHEADER_SIZE;i++)
	{
		read_rec_cs ^= read_rec_data[i];
		PortSendChar(read_rec_data[i]);
	}
	
	_valid_ptr(&read_rec_sblock, &read_rec_data, RECHEADER_SIZE, NULL);
	
	if(read_rec_tran_remain >= TRAN_PACKET_SIZE)                   
		this_size = TRAN_PACKET_SIZE - RECHEADER_SIZE;
	else
		this_size = read_rec_tran_remain - RECHEADER_SIZE;
#ifdef DEBUG
	sprintf(sbuf, "\n this size %d ", this_size);
	LcdPrintf(sbuf);
#endif
	
	read_rec_tran_remain -= RECHEADER_SIZE;
	
	
	//LcdPrintf("@");
	last_read_rec_sblock = read_rec_sblock;
	last_read_rec_data = read_rec_data;
	last_read_rec_tran_remain = read_rec_tran_remain;
	
	
	SyncReadRec5(ACK);
	
	
}

void SyncReadRec5(UBYTE x)
{
    UWORD 		i;
    UBYTE		*TempSendBuffer = SendBuffer;
    UBYTE 		data_to_send;
	
    if(x == REC_NAK)
    {
        read_rec_sblock = last_read_rec_sblock;
        read_rec_data = last_read_rec_data;
        read_rec_tran_remain = last_read_rec_tran_remain;
    }
    else
    {
		if(x == NAK)
		{
			BufferEmpty();
			SetWaitReturnFct(NULL);
			SetComHandleEvent(SyncStateDBEnq);
		}
	}      	
	
    last_read_rec_sblock 		= read_rec_sblock;
    last_read_rec_data 		= read_rec_data;
    last_read_rec_tran_remain 	= read_rec_tran_remain;
	
	
    for(i = 0; i < this_size - 1; i++)
    {
		read_rec_cs ^= *read_rec_data;
        *TempSendBuffer = (UBYTE)(*read_rec_data);
        TempSendBuffer ++;
        _valid_ptr(&read_rec_sblock, &read_rec_data, 1, NULL);		
    }
	
    read_rec_tran_remain -= this_size;    
    if(read_rec_tran_remain > 0)
    {
		if(read_rec_tran_remain >= TRAN_PACKET_SIZE)                   
			this_size 	= TRAN_PACKET_SIZE;
        else
            this_size 	= read_rec_tran_remain;
        
        read_rec_cs 	^= *read_rec_data;
        data_to_send 	= *read_rec_data;
        _valid_ptr(&read_rec_sblock, &read_rec_data, 1, NULL);
        SetWaitReturnFct(SyncReadRec5);
        PortWaitForChar(ACK, NAK, REC_NAK, TRUE);  // rec_nak = time out        
        BufferEmpty();
        *TempSendBuffer = (UBYTE)(data_to_send);        
        TempSendBuffer ++;
        ComSendData(hport, (BYTE*)SendBuffer, (UWORD)(TempSendBuffer - SendBuffer));
    }
    else
    {
        read_rec_cs ^= *read_rec_data;
        *TempSendBuffer = (UBYTE)(*read_rec_data);
        TempSendBuffer ++;
        _valid_ptr(&read_rec_sblock, &read_rec_data, 1, NULL);
        read_rec_data = (BYTE*) &read_rec_cs;
        *TempSendBuffer = (UBYTE)(read_rec_data[0]);        
        TempSendBuffer ++;
        BufferEmpty();
        SetWaitReturnFct(NULL);
        SetComHandleEvent(SyncStateDBEnq);
        *TempSendBuffer = (UBYTE)(read_rec_data[1]);        
        TempSendBuffer ++;       
        ComSendData(hport, (BYTE*)SendBuffer, (UWORD)(TempSendBuffer - SendBuffer));
    } 
}


/*************************************
Send a field
**************************************/
void SyncReadField()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncReadField2);
    PortWaitForLength(12);  // dbid + recid + fieldnum + cs
    PortSendChar(RECFIELD_ACK);
}

void SyncReadField2(UBYTE x)
{
    DatabaseID dbid;
    RecordID recid;
    SHORT cs, i;
    USHORT block;
    USHORT fieldnum;
    UWORD rec_num, sblock, len;
    BYTE *data, *buf;
    RecordHeader* rec_ptr;
    UWORD rec_size, tmp, recnum;
	
    UWORD fsize, start_sblock, first_offset, last_size;
    USHORT num_block;
	Err result;
	BOOLEAN frag;
	
	
	SetWaitReturnFct(NULL);
	
	dbid = *(DatabaseID*) sync_buf;
	recid = *(((RecordID*) sync_buf)+1);
	fieldnum = *(USHORT*) (&sync_buf[8]);
	
	cs = *(SHORT*) &sync_buf[10];
	
	
	for(i=0;i<TOTAL_SLOT;i++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[i], dbid, &block) == TRUE)
			if(BlockType(mat_info_ptr[i]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	if(i >= TOTAL_SLOT)
    {
		BufferEmpty();
		SetComHandleEvent(SyncStateDBEnq);
		PortSendChar(REC_NAK); // db not found
		return;
    }
	
	sblock = MakeSBlock(i,block);
	
    result = DataFieldInfo(sblock, recid, fieldnum, &fsize, &start_sblock, &first_offset,
		&num_block, &last_size, &frag);
	
	if(result != TRUE)
    {
		BufferEmpty();
		SetComHandleEvent(SyncStateDBEnq);
		PortSendChar(REC_NAK); // db not found
		return;
    }
	
	PortSendChar(RECFIELD_DATA);
	
	
	len = 4 + fsize + 2; // len + fieldsize + cs
	data = (BYTE*) &len;
	cs = 0;
	for(i=0;i<4;i++)
	{
		PortSendChar(data[i]);
		cs ^= data[i];
	}
	
	
	DataOpenDB(dbid, DB_NO_SORT, OPEN_RW);
	
	DataRecIDtoNum(dbid, recid, &recnum);
	
	DataOpenRecord(dbid, recnum, &recid, NULL);
	buf = NULL;
	DataGetField(dbid, recid, fieldnum, &buf, &tmp);
	DataCloseRecord(dbid, recid);
	DataCloseAllDB();//(dbid);
	
	//        SendBData(start_sblock, first_offset, fsize, &cs);  // send field data
	for(i=0;i<fsize;i++)
	{
		if(buf)
		{
			PortSendChar(buf[i]);
			cs ^= buf[i];
		}
		else
			PortSendChar(0);
	}
	
	if(buf)
		qfree(buf);
	
	
	data = (BYTE*) &cs;
	PortSendChar(data[0]);
	SetComHandleEvent(SyncStateDBEnq);
	PortSendChar(data[1]);
#ifdef DEBUG
	LcdPrintf(" ereadfid ");
#endif
}





/*************************************
Delete a record
**************************************/
void SyncRecDel()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncRecDel2);
    BufferEmpty();
    PortWaitForLength(10);   /* dbid + recid + cs */
    BufferEmpty();
    PortSendChar(DELREC_ACK);
}

void SyncRecDel2(UBYTE x)
{
	DatabaseID 		dbid;
    RecordID 		recid;
    UWORD 			i, sblock;
    SHORT 			cs;
    USHORT 			block;
    RecordHeader 	*rec_ptr;
	
	
    dbid = *(DatabaseID*) sync_buf;
    recid = *(((RecordID*) sync_buf)+1);
	
    cs = *(SHORT*) &sync_buf[8];
	
    for(i=0;i<TOTAL_SLOT;i++)     /* find all slot for the db */
    {
		if(MemoryFindStartBlock(mat_info_ptr[i], dbid, &block) == TRUE)
			break;
		if(BlockType(mat_info_ptr[i]->mat[block].attribute) == MAT_BLOCK_DB_REC)
			break;
    }
    
    if(i >= TOTAL_SLOT)
    {
		BufferEmpty();
		PortSendChar(REC_NAK);
    }
    else
    {
		sblock = MakeSBlock(i, block);
		DataClearFieldCache();
		if(DataRecordBlock(sblock, recid, &sblock, &rec_ptr)!=TRUE)
		{
			BufferEmpty();
			PortSendChar(REC_NAK);
		}
		else
		{	
			DataDeleteRecordAction(sblock, rec_ptr, FALSE);	
			BufferEmpty();
			PortSendChar(DELREC_ACK);
        }
    }
    SetComHandleEvent(SyncStateDBUp);
}


void  SyncSetMaxRecID()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncSetMaxRecID3);
    PortWaitForLength(10);   /* dbid + recid + cs */
    BufferEmpty();
    PortSendChar(MAX_RECID_ACK);
}

void SyncSetMaxRecID2(UBYTE x)
{
	SetWaitReturnFct(SyncReadRec3);
	PortWaitForLength(10);   /* dbid + recid + cs */
}

void SyncSetMaxRecID3(UBYTE x)
{
	DatabaseID dbid;
	RecordID recid;
	SHORT cs;
	UWORD i;
	USHORT block;
	UWORD rec_num ;
	BYTE *data;
	UWORD rec_size;
	DBHeader *dbheader;
	
	SetWaitReturnFct(NULL);
	
	dbid = *(DatabaseID*) sync_buf;
	recid = *(((RecordID*) sync_buf)+1);
	
	cs = *(SHORT*) &sync_buf[8];
	
	need_del = 0;
	
	for(i=0;i<TOTAL_SLOT;i++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[i], dbid, &block) == TRUE)
            if(BlockType(mat_info_ptr[i]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	
	if(i>=TOTAL_SLOT)
	{
		BufferEmpty();
		SetComHandleEvent(SyncStateDBUp);
		PortSendChar(REC_NAK); // db not found
		return;
	}
	
	dbheader = (DBHeader*) SBlockAddr(block);
	dbheader->next_rec_id = recid;
	BufferEmpty();
	SetComHandleEvent(SyncStateDBUp);
	PortSendChar(REC_DATA);
}



Err SyncReasignRecIDAction(DatabaseID dbid, UWORD offset, RecordID exclude_recid)
{
	UWORD sblock;
	USHORT i, block;
	RecordHeader *rec_ptr, *old_rec_ptr = NULL;
	DBHeader *db_ptr;
	RecordID max_recid;
	//        char buf[50];
	
	//LcdPrintf("@");
	
	sblock = 0xFFFFFFFF;
	for(i=0;i<TOTAL_SLOT;i++)
		if ( (MemoryFindStartBlock((mat_info_ptr[i]), dbid, &block)) == TRUE)
		{
			sblock = MakeSBlock(i, block);
			break;
		}
		
		if(sblock == 0xFFFFFFFF)
        {
			return ERR_DATA_DB_MISS;
        }
		
		db_ptr = (DBHeader*) SBlockAddr(sblock);
		
		/*
        max_recid = db_ptr->next_rec_id - 1;
		
		  if(exclude_recid > db_ptr->next_rec_id)
		  max_recid = exclude_recid;
		*/
        max_recid = (exclude_recid > db_ptr->next_rec_id)? exclude_recid :db_ptr->next_rec_id  - 1;
		
        if(max_recid < 1000)
			max_recid = 1000;
        if((max_recid - 1000) <= offset)
			max_recid = 1000 + offset;
		
		PortSendChar(REC_ACK);
		
		rec_ptr = (RecordHeader*) (SBlockAddr(sblock) + db_ptr->length);
        if((rec_ptr->size != DATA_CHUNK_END) && NormRecID(rec_ptr->rec_id))
            if( (rec_ptr->rec_id < 0x3fffffff) && (rec_ptr->rec_id > exclude_recid))
            {
				//                sprintf(buf, "\nrec_id = %d chg to %d ", rec_ptr->rec_id, rec_ptr->rec_id + offset);
				//                LcdPrintf(buf);
				
                
                rec_ptr->rec_id += offset;
                if(rec_ptr->rec_id > max_recid)
					max_recid=rec_ptr->rec_id;
				
			}
			while(1)
			{
				PortSendChar(REC_ACK);
				while(1)
				{
					PortSendChar(REC_ACK);
					if( (((UWORD)rec_ptr) + rec_ptr->size) < ((((UWORD)rec_ptr) & PTR_ALIGIN_MASK) + BLOCK_SIZE))
					{
						rec_ptr = (RecordHeader*)((UWORD)rec_ptr + rec_ptr->size);  /* next record */
						if((rec_ptr->size != DATA_CHUNK_END) && NormRecID(rec_ptr->rec_id))
							if( (rec_ptr->rec_id < 0x3fffffff) && (rec_ptr->rec_id > exclude_recid))
							{
								
								//                sprintf(buf, "\nrec_id = %d chg to %d ", rec_ptr->rec_id, rec_ptr->rec_id + offset);
								//                LcdPrintf(buf);
								
								rec_ptr->rec_id += offset;
								if(rec_ptr->rec_id > max_recid)
									max_recid=rec_ptr->rec_id;
								
								
							}
							break;
					}
					else
					{
						if(MemoryNextBlock((mat_info_ptr[SBlockMat(sblock)]), block, &block) != TRUE)
						{
							db_ptr->next_rec_id = max_recid + 1;
							
							return TRUE;
						}
						sblock = MakeSBlock(SBlockMat(sblock), block);
						old_rec_ptr = rec_ptr;
						rec_ptr = (RecordHeader *) SBlockAddr(sblock);
						
						if((rec_ptr->size != DATA_CHUNK_END) && NormRecID(rec_ptr->rec_id))
							if( (rec_ptr->rec_id < 0x3fffffff) && (rec_ptr->rec_id > exclude_recid))
							{
								
								//                sprintf(buf, "\nrec_id = %d chg to %d ", rec_ptr->rec_id, rec_ptr->rec_id + offset);
								//                LcdPrintf(buf);
								
								rec_ptr->rec_id += offset;
								if(rec_ptr->rec_id > max_recid)
									max_recid=rec_ptr->rec_id;
								
								
							}
							if(!(FragRec(rec_ptr)))
								break;
					}
				}
				/*
				if((rec_ptr->size != DATA_CHUNK_END) && NormRecID(rec_ptr->rec_id))
				if( (rec_ptr->rec_id < 0x3fffffff) && (rec_ptr->rec_id > exclude_recid))
				{
                rec_ptr->rec_id += offset;
                if(rec_ptr->rec_id > max_recid)
				max_recid=rec_ptr->rec_id;
				
				  
					}
				*/
				
				if(((UWORD)rec_ptr - SBlockAddr(sblock)) >= (BLOCK_SIZE - RECHEADER_SIZE))  /* next record on next block */
				{
					if(MemoryNextBlock((mat_info_ptr[SBlockMat(sblock)]), block, &block) != TRUE)
					{
						db_ptr->next_rec_id = max_recid + 1;
						return TRUE;
					}
					sblock = MakeSBlock(SBlockMat(sblock), block);
					old_rec_ptr = rec_ptr;
					rec_ptr = (RecordHeader *) SBlockAddr(sblock);
					/*
					if( (rec_ptr->rec_id < 0x3fffffff) && (rec_ptr->rec_id > exclude_recid))
					{
					rec_ptr->rec_id += offset;
					if(rec_ptr->rec_id > max_recid)
					max_recid=rec_ptr->rec_id;
					
					  
						}
					*/
					
					if((rec_ptr->size != DATA_CHUNK_END) && NormRecID(rec_ptr->rec_id))
						if( (rec_ptr->rec_id < 0x3fffffff) && (rec_ptr->rec_id > exclude_recid))
						{
							//                sprintf(buf, "\nrec_id = %d chg to %d ", rec_ptr->rec_id, rec_ptr->rec_id + offset);
							//                LcdPrintf(buf);
							
							
							rec_ptr->rec_id += offset;
							if(rec_ptr->rec_id > max_recid)
								max_recid=rec_ptr->rec_id;
							
							
						}
						
						
				}
				else
					if(rec_ptr->size == DATA_CHUNK_END) /* end of records in this block, any for next block? */
					{
						if(MemoryNextBlock((mat_info_ptr[SBlockMat(sblock)]), block, &block) != TRUE)
						{
							db_ptr->next_rec_id = max_recid + 1;
							
							
							return TRUE;
						}
						sblock = MakeSBlock(SBlockMat(sblock), block);
						old_rec_ptr = rec_ptr;
						rec_ptr = (RecordHeader *) SBlockAddr(sblock);
						if((rec_ptr->size != DATA_CHUNK_END) && NormRecID(rec_ptr->rec_id))
							if( (rec_ptr->rec_id < 0x3fffffff) && (rec_ptr->rec_id > exclude_recid))
							{
								//                sprintf(buf, "\nrec_id = %d chg to %d ", rec_ptr->rec_id, rec_ptr->rec_id + offset);
								//                LcdPrintf(buf);
								
								
								rec_ptr->rec_id += offset;
								if(rec_ptr->rec_id > max_recid)
									max_recid=rec_ptr->rec_id;
								
								
							}
					}
	}
	
	db_ptr->next_rec_id = max_recid + 1;
	
	
	
	return TRUE;
	
	
}


void  SyncReasignRecID()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncReasignRecID2);
    PortWaitForLength(14);   /* dbid + recid + + exclude recid +  cs */
    BufferEmpty();
    PortSendChar(REASIGN_RECID_ACK);
}

void SyncReasignRecID2(UBYTE x)
{
	DatabaseID dbid;
	UWORD offset;
	SHORT cs;
	UWORD i;
	USHORT block;
	UWORD rec_num ;
	BYTE *data;
	UWORD rec_size;
	RecordID exclude_recid;
	DBHeader *dbheader;
	
	SetWaitReturnFct(NULL);
	
	dbid = *(DatabaseID*) sync_buf;
	offset = *(((RecordID*) sync_buf)+1);
	exclude_recid = *(((RecordID*) sync_buf)+2);
	
	cs = *(SHORT*) &sync_buf[8];
	
	
	if(SyncReasignRecIDAction(dbid, offset, exclude_recid) != TRUE)
	{
		BufferEmpty();
		SetComHandleEvent(SyncStateDBUp);
		PortSendChar(REC_NAK); // db not found
		return;
	}
	BufferEmpty();
	SetComHandleEvent(SyncStateDBUp);
	PortSendChar(REC_DATA);
}


/*************************************
Add a record
**************************************/
void SyncRecAdd()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncRecAdd2);
    PortWaitForChar(ADDREC_SEQ, ADDREC_SEQ, ADDREC_SEQ,TRUE);
    PortSendChar(ADDREC_ACK);
}

void SyncRecAdd2(UBYTE x)
{
	SetWaitReturnFct(SyncRecAdd3);
    PortWaitForLength(10);   /* dbid + recid + num_field */
}

UWORD sync_num_field;
DatabaseID sync_dbid;
RecordID sync_recid;
UWORD sync_field_size[70];
UBYTE *sync_data;
UWORD sync_total_size;
UWORD sync_sblock;

void SyncRecAdd3(UBYTE x)
{
	int i;
	
    sync_dbid 		= *(DatabaseID*) sync_buf;
    sync_recid 		= *(((RecordID*) sync_buf)+1);
    sync_num_field 	= *(USHORT*) (sync_buf + 8);
	
    SetWaitReturnFct(SyncRecAdd4);
    PortWaitForLength(10 + sync_num_field * 4 + 2); /* total field * 4(field size) + cs */
    PortSendChar(ACK);
	
}

void SyncRecAdd4(UBYTE x)
{
	UWORD rec_num;
	USHORT block, b, i;
	RecordHeader *rec_ptr;
	BYTE retc;
	WORD endata, byte_use;
	UWORD dum, count;
	BYTE *temp;
	
    for(b=0;b<TOTAL_SLOT;b++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[b], sync_dbid, &block) == TRUE)
			if(BlockType(mat_info_ptr[b]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	if(b>=TOTAL_SLOT)
		goto db_not_found;
	
	sync_sblock = MakeSBlock(b,block);
	
	if(DataOpenDB(sync_dbid, DB_NO_SORT, OPEN_RW) != TRUE)
		goto db_not_found;
	else
	{
		if(DataRecIDtoNum(sync_dbid, sync_recid, &rec_num) == TRUE)
			goto rec_exists;
		if(DataNewRecordWithID(sync_dbid, sync_recid, 0, sync_num_field) != TRUE)
			goto no_space;
		
		need_del = 1;
		del_dbid = sync_dbid;
		del_recid = sync_recid;
		sync_total_size = 0;
		
		temp = (BYTE*) sync_field_size;
		for(i=0;i<sync_num_field * 4;i++)
		{
			*(temp++) = sync_buf[i+10];
		}
		for(i=0; i<sync_num_field; i++)
		{
			UWORD acc_size = 0;
			
#define ACC_COUNT 2000
			
			DataClearFieldCache();
			if(sync_field_size[i] > ACC_COUNT )
			{
				for(count=0;count < sync_field_size[i] / ACC_COUNT ; count++)
				{
					acc_size += ACC_COUNT;
					
					if(MemoryCheckMemLow())
						goto no_space2;
					
					if(DataResizeField2(sync_dbid, sync_recid, i, acc_size  ) != TRUE)
						goto no_space2;
					
				}
				if(MemoryCheckMemLow())
					goto no_space2;
				
				if(DataResizeField2(sync_dbid, sync_recid, i, sync_field_size[i])!=TRUE)
				{
					/*Not enough space in PDA */
					goto no_space2;
				}
			}
			else
			{
				if(MemoryCheckMemLow())
					goto no_space2;
				
				if(DataResizeField2(sync_dbid, sync_recid, i, sync_field_size[i])!=TRUE)
				{
					/*Not enough space in PDA */
					goto no_space2;
				}
			}
			
			sync_total_size += sync_field_size[i];
			dum = sync_field_size[i];
			EnFieldSize(endata, dum, byte_use);
			sync_total_size += byte_use;
        }
        DataClearFieldCache();
		if (DataRecordBlock(sync_sblock, sync_recid, &sync_sblock, &rec_ptr) != TRUE)
			goto internal_error;
		sync_data = (BYTE*) rec_ptr;
		retc = ADDREC_ACK;
		DataCloseAllDB();
		SetWaitReturnFct(SyncRecAdd5);
		BufferEmpty();
		PortWaitForLength(1 + RECHEADER_SIZE + 2);  /* ack + rec header + cs */
		goto common_end;
	}
	
db_not_found:
#ifdef DEBUG
	LcdPrintf(" db miss ");
#endif
	retc = NAK;
	goto error_end;
rec_exists:
#ifdef DEBUG
	LcdPrintf(" rec exist ");
#endif
	DataCloseAllDB();//(sync_dbid);
	retc = REC_NAK;
	goto error_end;
	
internal_error:
#ifdef DEBUG
	LcdPrintf(" rec blk miss ");
#endif
no_space2:
#ifdef DEBUG
	LcdPrintf(" no sp for field ");
#endif
	DataDeleteRecord(sync_dbid, sync_recid, FALSE);
	DataClearFieldCache();
no_space:
#ifdef DEBUG
	LcdPrintf(" no sp for new rec ");
#endif
	DataCloseAllDB();//(sync_dbid);
	retc = REC_SIZE_NAK;
	
error_end:
	need_del = 0;
	BufferEmpty();
	SetComHandleEvent(SyncStateDBUp);
common_end:
	PortSendChar(retc);
}

UWORD rec_byte;
BYTE *b_buffer;

void SyncRecAdd5(UBYTE x )
{
	/* get header first */
    UWORD i;
    RecordHeader *recptr, *src_recptr;
	
    BufferRemove(1);    /* remove ADDREC_ST */
    recptr = (RecordHeader*) sync_data;
    src_recptr = (RecordHeader*) sync_buf;
    recptr->modi_date = src_recptr->modi_date;
    recptr->cat = src_recptr->cat;
    recptr->attribute = src_recptr->attribute;
    _valid_ptr(&sync_sblock, (BYTE**) &sync_data, RECHEADER_SIZE, NULL);
	
    rec_byte = 0;
    b_buffer = (BYTE*)qmalloc(sync_total_size+3);
    SetBufferDoneFct(SyncRecAdd6);                    //V 2byte-Chk sum
    ComCapture(hport, COM_MODE_BUFFER, 1000, sync_total_size + 2, b_buffer);
	
    PortSendChar(REC_ACK);
}

extern UWORD sync_buf_len;

void SyncRecAdd6(UBYTE x)
{
    UWORD i;
    UWORD fs;
    BYTE *b;
	
	
	SetBufferDoneFct(NULL);
	for(i = 0; i < sync_total_size; i++)
	{
		*sync_data = b_buffer[i];
		_valid_ptr(&sync_sblock, (BYTE**) &sync_data, 1, NULL);
	}
	qfree(b_buffer);
	
	ComCapture(hport, COM_MODE_CHAR, 0, 0, NULL);  
   	SetWaitReturnFct(NULL);
   	BufferEmpty();
   	SetComHandleEvent(SyncStateDBUp);
   	need_del = 0;
   	PortSendChar(REC_ACK);
}





/*************************************
Add a cat
**************************************/
void SyncCatAdd()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncCatAdd2);
    PortWaitForChar(ADDREC_SEQ,ADDREC_SEQ,ADDREC_SEQ,TRUE);
    PortSendChar(ADDCAT_ACK);
}

void SyncCatAdd2(UBYTE x)
{
#ifdef DEBUG
	LcdPrintf(" AR2 ");
#endif
	SetWaitReturnFct(SyncCatAdd3);
	PortWaitForLength(10);   /* dbid + recid + num_field */
}

void SyncCatAdd3(UBYTE x)
{
	int i;
#ifdef DEBUG        
	LcdPrintf(" AR3 ");
#endif
	sync_dbid = *(DatabaseID*) sync_buf;
	sync_recid = *(((RecordID*) sync_buf)+1);
	sync_num_field = *(USHORT*) (sync_buf + 8);
	
	for(i=0;i<12;i++)
	{
#ifdef DEBUG
		sprintf(buf, " %d ", sync_buf[i]);
		LcdPrintf(buf);
#endif
	}
	
	SetWaitReturnFct(SyncCatAdd4);
	PortWaitForLength(10 + sync_num_field * 4 + 2); /* total field * 4(field size) + cs */
	PortSendChar(ACK);
}

void SyncCatAdd4(UBYTE x)
{
	UWORD rec_num;
	USHORT block, b, i;
	RecordHeader *rec_ptr;
	BYTE retc;
	WORD endata, byte_use;
	UWORD dum, count;
	BYTE *temp;
	
	
#ifdef DEBUG_NEWREC
	char buf[70];
	LcdPrintf("@");
#endif
	
	
#ifdef DEBUG
	Err err;
	LcdPrintf(" AR4 ");
#endif
	for(b=0;b<TOTAL_SLOT;b++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[b], sync_dbid, &block) == TRUE)
			if(BlockType(mat_info_ptr[b]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	if(b>=TOTAL_SLOT)
		goto db_not_found;
	
	sync_sblock = MakeSBlock(b,block);
	
	if(DataOpenDB(sync_dbid, DB_NO_SORT, OPEN_RW) != TRUE)
		goto db_not_found;
	else
	{
		DataDeleteRecord(sync_dbid, sync_recid, FALSE); /* del the cat */
		if(DataNewRecordWithID(sync_dbid, sync_recid, 0, sync_num_field) != TRUE)
			goto no_space;
		need_del = 1;
		del_recid = sync_recid;
		del_dbid = sync_dbid;
		
		
#ifdef DEBUG
		sprintf(buf, "\ndbid = %08x New record id = %08x  field = %d ", sync_dbid, sync_recid, sync_num_field);
		LcdPrintf(buf);
#endif
		
#ifdef DEBUG
		strcpy(buf, " fc ");
		LcdPrintf(buf);
#endif
		sync_total_size = 0;
		temp = (BYTE*) sync_field_size;
		for(i=0;i<sync_num_field * 4;i++)
		{
			*(temp++) = sync_buf[i+10];
#ifdef DEBUG
			sprintf(buf, " %x ", sync_buf[i+10]);
			LcdPrintf(buf);
#endif
		}
		for(i=0; i<sync_num_field; i++)
		{
			UWORD acc_size = 0;
			
#define ACC_COUNT 2000
			
#ifdef DEBUG_NEWREC
			sprintf(buf, "f%d: %d ", i, sync_field_size[i]);
			LcdPrintf(buf);
#endif
			DataClearFieldCache();
			if(sync_field_size[i] > ACC_COUNT )
			{
				for(count=0;count < sync_field_size[i] / ACC_COUNT ; count++)
				{
					acc_size += ACC_COUNT;
					
#ifdef DEBUG_NEWREC
					sprintf(buf, " acc %d ", acc_size);
					LcdPrintf(buf);
#endif
					
					if(MemoryCheckMemLow())
						goto no_space2;
					
					if(DataResizeField2(sync_dbid, sync_recid, i, acc_size  ) != TRUE)
						goto no_space2;
					
				}
#ifdef DEBUG_NEWREC
				sprintf(buf, "\nLast Size %d ", sync_field_size[i]);
				LcdPrintf(buf);
#endif
				
				if(MemoryCheckMemLow())
					goto no_space2;
				
				if(DataResizeField2(sync_dbid, sync_recid, i, sync_field_size[i])!=TRUE)
				{
					/*Not enough space in PDA */
#ifdef DEBUG
					strcpy(buf, " re fail ");
					LcdPrintf(buf);
#endif
					goto no_space2;
				}
			}
			else
			{
				if(MemoryCheckMemLow())
					goto no_space2;
				
				if(DataResizeField2(sync_dbid, sync_recid, i, sync_field_size[i])!=TRUE)
				{
					/*Not enough space in PDA */
					goto no_space2;
				}
			}
			
			sync_total_size += sync_field_size[i];
			dum = sync_field_size[i];
			EnFieldSize(endata, dum, byte_use);
			sync_total_size += byte_use;
        }
        DataClearFieldCache();
		if (DataRecordBlock(sync_sblock, sync_recid, &sync_sblock, &rec_ptr) != TRUE)
			goto internal_error;
		sync_data = (BYTE*) rec_ptr;
		retc = ADDREC_ACK;
		DataCloseAllDB();//(sync_dbid);
		SetWaitReturnFct(SyncCatAdd5);
		BufferEmpty();
		PortWaitForLength(1 + RECHEADER_SIZE + 2);  /* ack + rec header + cs */
		goto common_end;
         }
		 
db_not_found:
#ifdef DEBUG
		 LcdPrintf(" db miss ");
#endif
		 retc = NAK;
		 goto error_end;
rec_exists:
#ifdef DEBUG
		 LcdPrintf(" rec exist ");
#endif
		 DataCloseAllDB();//(sync_dbid);
		 retc = REC_NAK;
		 goto error_end;
		 
internal_error:
#ifdef DEBUG
		 LcdPrintf(" rec blk miss ");
#endif
no_space2:
#ifdef DEBUG
		 LcdPrintf(" no sp for field ");
#endif
		 DataDeleteRecord(sync_dbid, sync_recid, FALSE);
no_space:
#ifdef DEBUG
		 LcdPrintf(" no sp for new rec ");
#endif
		 DataCloseAllDB();//(sync_dbid);
		 retc = REC_SIZE_NAK;
		 
error_end:
		 need_del = 0;
		 BufferEmpty();
		 SetComHandleEvent(SyncStateDBUp);
common_end:
		 PortSendChar(retc);
}


void SyncCatAdd5(UBYTE x )
{
	/* get header first */
    UWORD i;
    RecordHeader *recptr, *src_recptr;
	
    BufferRemove(1);    /* remove ADDREC_ST */
#ifdef DEBUG
    LcdPrintf("\nheader\n");
    for(i=0;i<RECHEADER_SIZE;i++)
    {
		sprintf(buf, " %x ", sync_buf[i]);
		LcdPrintf(buf);
    }
#endif
    recptr = (RecordHeader*) sync_data;
    src_recptr = (RecordHeader*) sync_buf;
    recptr->modi_date = src_recptr->modi_date;
    recptr->cat = src_recptr->cat;
	//    recptr->attribute = src_recptr->attribute;
    _valid_ptr(&sync_sblock, (BYTE**) &sync_data, RECHEADER_SIZE, NULL);
	//    SetComHandleEvent(SyncRecAdd6);
	
    rec_byte = 0;
    b_buffer = (BYTE*)qmalloc(sync_total_size+3);
    SetBufferDoneFct(SyncRecAdd6);                    //V 2byte-Chk sum
    ComCapture(hport, COM_MODE_BUFFER, 1000, sync_total_size + 2, b_buffer);
	
	
    PortSendChar(REC_ACK);
}


void SyncCatAdd6(UBYTE x)
{
	UWORD i;
	UWORD fs;
	BYTE *b;
	
	SetBufferDoneFct(NULL);
	for(i=0;i<sync_total_size;i++)
	{
		*sync_data = b_buffer[i];
		_valid_ptr(&sync_sblock, (BYTE**) &sync_data, 1, NULL);
	}
	qfree(b_buffer);
	ComCapture(hport, COM_MODE_CHAR, 0, 0, NULL);
	
	SetWaitReturnFct(NULL);
	BufferEmpty();
	SetComHandleEvent(SyncStateDBUp);
	
	need_del = 0;
	PortSendChar(REC_ACK);
}



UWORD icon_slot, install_inf_slot;
UWORD GetIconSlot()
{
	UWORD i;
	InstallAppInf *handle;
	UBYTE icon_slot_c[APP_MAX - TOTAL_PRE_INSTALL_APP];
	
#ifdef DEBUG_APP_INSTALL
	LcdPrintf("\nGetIcon Slot");
#endif
	
	for(i=0;i<APP_MAX - TOTAL_PRE_INSTALL_APP;i++)
		icon_slot_c[i] = 1;
	
	SysGetInstallAppHandle(&handle);
	
	for(i=0;i<APP_MAX - TOTAL_PRE_INSTALL_APP;i++)
	{
		if(handle[i].icon_index < APP_MAX - TOTAL_PRE_INSTALL_APP)
			icon_slot_c[handle[i].icon_index] = 0;
	}
	
	for(i=0;i<APP_MAX - TOTAL_PRE_INSTALL_APP;i++)
		if(icon_slot_c[i])  break;
		
        if(i >= APP_MAX - TOTAL_PRE_INSTALL_APP)
			/* cannot hold any more prog */
			return 0xff;
#ifdef DEBUG_APP_INSTALL
		sprintf(buf, " slot = %d ", i);
		LcdPrintf(buf);
#endif
        icon_slot = i;
        return i;      
}

UWORD GetInstallInfEntry()
{
	WORD i;
	InstallAppInf *handle;
#ifdef DEBUG_APP_INSTALL
	LcdPrintf("\nInstall Inf Entry");
#endif
	
	SysGetInstallAppHandle(&handle);
	
	install_inf_slot = 0xff;
	
	for(i=0;i<APP_MAX - TOTAL_PRE_INSTALL_APP;i++)
		if(handle[i].reg_entry_index == 0xff)
		{
			install_inf_slot = i;
			break;
		}
#ifdef DEBUG_APP_INSTALL
		sprintf(buf, " %d ", install_inf_slot);
		LcdPrintf(buf);
#endif
        return install_inf_slot;      
}

void SyncNewApp()
{
	if((GetInstallInfEntry() == 0xff) || (GetIconSlot() == 0xff))
    {  /* cannot hold more app */
		SetWaitReturnFct(NULL);
        BufferEmpty();
        SetComHandleEvent(SyncStateNewApp);
        PortSendChar(REC_SIZE_NAK);
    }
    else
    {
		SetComHandleEvent(NULL);
        SetWaitReturnFct(SyncNewApp2);
        PortWaitForLength(22);          /* App Name + cs */
        PortSendChar(ADDAPP_ACK);
    }
}


BYTE new_app_name[24];

void SyncNewApp2(UBYTE x)
{  /* get app name */
	AppID appid;
	
	sync_buf[19] = 0x00;
	if(SysGetAppID(sync_buf, &appid) == TRUE)
	{
		SetWaitReturnFct(NULL);
		BufferEmpty();
		SetComHandleEvent(SyncStateNewApp);
		PortSendChar(NAK);
		return;
	}
	
	strcpy(new_app_name, sync_buf);
	
#ifdef DEBUG_APP_INSTALL
	sprintf(buf, "\nApp Name: %s ", new_app_name);
	LcdPrintf(buf);
#endif
	
	BufferEmpty();
	SetWaitReturnFct(SyncNewApp3);
	PortWaitForLength(24); /* progsize + res offset + bss size +  extra_size + attribute + cs */
	PortSendChar(ACK);
}

UWORD packet_size;
UWORD app_size;
UWORD app_res_offset;
UWORD app_bss_size;
USHORT app_attribute;
UWORD dd_extra_size;
USHORT install_mode;
void SyncNewApp3(UBYTE x)
{
	/* Get the received info */
	/* Psize + res-offset + bss size + attribute + cs  + AppName + cs */
	
	BYTE *ptr;
	USHORT cs;
	UBYTE re_value;
	
	ptr = sync_buf;
	packet_size = *(UWORD*)ptr;
	ptr += 4;
	app_size = *(UWORD*)ptr;
	ptr += 4;
	app_res_offset = *(UWORD*) ptr;
	ptr += 4;
	app_bss_size = *(UWORD*) ptr;
	ptr += 4;
	dd_extra_size = *(UWORD*) ptr;
	ptr += 4;
	app_attribute = *(USHORT*) ptr;
	ptr += 2;
	cs = *(USHORT*) ptr;
	
#ifdef DEBUG_APP_INSTALL
	sprintf(buf, "\napp size = %x ", packet_size);
	LcdPrintf(buf);
	sprintf(buf, " res offset = %x ", app_res_offset);
	LcdPrintf(buf);
	sprintf(buf, "bss size = %x ", app_bss_size);
	LcdPrintf(buf);
	sprintf(buf, "attri = %x \n", app_attribute);
	LcdPrintf(buf);
	sprintf(buf, "extra_size = %x \n", dd_extra_size);
	LcdPrintf(buf);
	
	for(cs=0;cs<16;cs++)
	{
		sprintf(buf, "%x ", sync_buf[cs]);
		LcdPrintf(buf);
	}
#endif
	
	BufferEmpty();
	
	if(app_res_offset >= packet_size)
	{
		re_value = NAK;
		goto errterm;
	}
	if(MemoryTotalFree() < ( packet_size / BLOCK_SIZE + 32)) /* at least 32*4k free after install the app */
	{
		re_value = NAK;
		goto errterm;
	}
	
	install_mode = 0; /* norm app */
	
	if( *((BYTE*)&app_attribute) & BIT_TYPE)  /* Device driver */
	{
		install_mode = 1;
	}
	{
#define APP_ICON_SIZE (APP_ICON_WIDTH * APP_ICON_HEIGHT * APP_ICON_BIT_PER_PIXEL / 8)
		SetWaitReturnFct(SyncNewApp4);
		PortWaitForLength(APP_ICON_SIZE + dd_extra_size + 2); /* icon image + cs */
		
#ifdef DEBUG_APP_INSTALL
		sprintf(buf, "\nWait for len %d , cur_len = %d ", APP_ICON_SIZE + 2, BufferGetLength());
		LcdPrintf(buf);
#endif
		
		PortSendChar(ACK);
	}
	return;
errterm:
	SetWaitReturnFct(NULL);
	SetComHandleEvent(SyncStateNewApp);
	PortSendChar(re_value);
}

UBYTE *code_data_ptr;
BYTE install_revert;
AppID new_app_id;
UWORD wait_len;

struct _HOOK_TABLE
{
	UWORD int_num;
	UWORD fct_offset;
};

typedef struct _HOOK_TABLE hook_table;

hook_table *pHookTbl;
UWORD *ptable;

void SyncNewApp4(UBYTE x)
{
	/* process the icon */
	UBYTE *idata;
	UBYTE *bufdata = sync_buf;
	UWORD i,j;
	
	/* icon data:
	| icon0 header |  icon0 data  |  icon1 header | icon 1 data | ...
	<-    56      -><- 408 byte- >                     
	<-------------  472 byte ------>                           */
	
#ifdef DEBUG_APP_INSTALL
	LcdPrintf(" Icon OK ");
#endif
	idata = ResGetInstallIconData();
	
	idata += 56;
	
	idata += icon_slot * 472;  /* position to icon data start */
	//        idata += icon_slot * 464;  /* position to icon data start */
	
	for(i=0;i<APP_ICON_SIZE;i++)
		*idata++ = *bufdata++;
	if(dd_extra_size)
		pHookTbl = (hook_table*) qmalloc(dd_extra_size+10);
	else
		pHookTbl = NULL;
	
	idata = (BYTE*)pHookTbl;
	for(i=0;i<dd_extra_size;i++)
	{
		*idata++ = *bufdata++;
	}
#ifdef DEBUG_APP_INSTALL
	
	for(i=0;i<dd_extra_size/8;i++)
	{
		sprintf(buf, " %d ", pHookTbl[i].int_num);
		LcdPrintf(buf);
	}
	
#endif
#ifdef DEBUG_APP_INSTALL
	LcdPrintf(" copy ICON ok ");
#endif
	
	/* prepare prog block */
	/* method: alloc block, set block type to mat_free, remember
	first block, after down, mark block in the link to prog_code */
	BufferEmpty();
	
#ifdef DEBUG_APP_INSTALL
	sprintf(buf, "\nAttri %x ", *(BYTE*)&app_attribute);
	LcdPrintf(buf);
	sprintf(buf, "RunSpec %x ", *(((BYTE*)&app_attribute)+ 1));
	LcdPrintf(buf);
#endif
	
	if( MemoryInstallProg(new_app_name, app_size , *(BYTE*)&app_attribute, *(((BYTE*)&app_attribute)+ 1), app_bss_size, app_res_offset, &new_app_id, &code_data_ptr, &ptable) != TRUE)
	{
		SetWaitReturnFct(NULL);
		SetComHandleEvent(SyncStateNewApp);
		install_revert = 0;
		PortSendChar(NAK);
		return;
	}
#ifdef DEBUG_APP_INSTALL
	LcdPrintf("\nInstall App ok ");
	
	for(i=0;i< *(ptable-1) - 1; i++)
	{
        sprintf(buf, "\n%d %08x ", i, *(ptable+i));
        LcdPrintf(buf);
	}
#endif
	
	install_revert = 1;
	wait_len = packet_size + 2;
	SetWaitReturnFct(SyncNewApp5);
	BufferEmpty();
	
	if((packet_size + 2 )>= TRAN_PACKET_SIZE)  /* 2 byte cs */
	{
#ifdef DEBUG_APP_INSTALL
		//sprintf(buf, "\n1st packet expected len = %d ", TRAN_PACKET_SIZE);
		//LcdPrintf(buf);
#endif
		PortWaitForLength(TRAN_PACKET_SIZE);
	}
	else
	{
#ifdef DEBUG_APP_INSTALL
		//sprintf(buf, "\n1st packet expected len = %d ", packet_size+2);
		//LcdPrintf(buf);
#endif
		PortWaitForLength(packet_size+2);
    }
	PortSendChar(ACK);
}

void  InstallDeviceDriverInt();

void SyncNewApp5(UBYTE x)
{
	UWORD i;
	UBYTE *data = sync_buf;
	
	if(wait_len <= TRAN_PACKET_SIZE)
	{
		InstallAppInf *handle;
		USHORT reg_index;
		USHORT total_item;
		BYTE inst_msg[50] = INSTALL;
		
#ifdef DEBUG_APP_INSTALL
		LcdPrintf("\nApp Rec Completed ");
#endif
		
		if(wait_len > 2)   /* not check sum */
			for(i=0;i<(wait_len - 2)% TRAN_PACKET_SIZE;i++)
				*code_data_ptr++ = *data++;
			
			if( ((BYTE)(*(BYTE*)&app_attribute) & (BYTE) 0x10) == (BYTE)0x10)
			{
				SysGetInstallAppHandle(&handle);
				SysGetAppEntryIndex(new_app_id, &reg_index);
				handle[install_inf_slot].reg_entry_index = reg_index;
				handle[install_inf_slot].icon_index = icon_slot;
			}
			
#ifdef DEBUG_APP_INSTALL
			sprintf(buf, "\nInstall to inf slot %d", install_inf_slot);
			LcdPrintf(buf);
			sprintf(buf, "\nInstall to icon slot %d", icon_slot);
			LcdPrintf(buf);
			sprintf(buf, "\nRegIndex = %d ", reg_index);
			LcdPrintf(buf);
#endif
			if(dd_extra_size)
			{
#ifdef DEBUG_APP_INSTALL
				LcdPrintf( "\nInst int");
#endif       
				InstallDeviceDriverInt();
				if(pHookTbl)
					qfree(pHookTbl);
			}
			
			strcpy(inst_msg + strlen(inst_msg), new_app_name);
			strcpy(inst_msg + strlen(inst_msg), " Ok");
			
			DispStr(inst_msg);
			/*
			ListGetNumOfItems(LIST_SYNC_LOG, &total_item);
			ListInsertItem(LIST_SYNC_LOG, total_item, inst_msg);
			UpdateDisp();
			*/
			BufferEmpty();
			install_revert = 0;
			SetWaitReturnFct(NULL);
			SetComHandleEvent(SyncStateNewApp);
			PortSendChar(ACK);
			return;
	}
#ifdef DEBUG_APP_INSTALL
	LcdPrintf("\nPacket Reced ");
#endif
	for(i=0;i<sync_buf_len;i++)
		*code_data_ptr++ = *data++;
	
	//        wait_len -= TRAN_PACKET_SIZE;
	wait_len -= sync_buf_len;
	BufferEmpty();
	
#ifdef DEBUG_APP_INSTALL
	//sprintf(buf, "\nRemain size = %d ", wait_len);
	//LcdPrintf(buf);
#endif
	
	if(wait_len > TRAN_PACKET_SIZE)
	{
#ifdef DEBUG_APP_INSTALL
		//LcdPrintf("\nExpected 1 packet for next");
#endif
		PortWaitForLength(TRAN_PACKET_SIZE);
	}
	else
	{
		
#ifdef DEBUG_APP_INSTALL
		//sprintf(buf, "\nExpect last packet size %d ", wait_len % TRAN_PACKET_SIZE);
		//LcdPrintf(buf);
#endif
		if(wait_len == TRAN_PACKET_SIZE)
			PortWaitForLength(TRAN_PACKET_SIZE);
		else
			PortWaitForLength(wait_len % TRAN_PACKET_SIZE);
	}
	PortSendChar(ACK);
}


void UndoInstall()
{
	
	SysRemoveApp(new_app_id);
	install_revert = 0;
}

void InstallDeviceDriverInt()
{
#define MODE_SYSCALL 0
#define MODE_INTHOOK 1
#define MODE_INT_ADDR 2
	
    UWORD i;
    USHORT hook_num;
    USHORT mode = MODE_SYSCALL;
    UWORD reset_sys_call = 0, tmp;
	
#ifdef DEBUG_DRV_INSTALL
    int x;
    LcdPrintf("@");
	
    sprintf(buf, "\nextra size %d ", dd_extra_size);
    LcdPrintf(buf);
    sprintf(buf, "\npHookTbl = %08x ", pHookTbl);
    LcdPrintf(buf);
	
#endif
	
    for(i=0;i<dd_extra_size/8;i++)
    {
		if(pHookTbl[i].int_num == 0xffffffff)
		{         
			mode = MODE_INTHOOK;
			continue;
		}
		if(pHookTbl[i].int_num == 0xfffffffe)  /* int addr hook */
		{
#ifdef DEBUG_DRV_INSTALL
			int j;
			sprintf(buf, "scall offset = %d  pt = %08x", pHookTbl[i].fct_offset, ptable);
			LcdPrintf(buf);
#endif
			IntSetHookAddr((UBYTE) pHookTbl[i].fct_offset, ptable, new_app_id);
			
#ifdef DEBUG_DRV_INSTALL
			for(j=0;j<5;j++)
			{
				sprintf(buf, "\n page %d = %08x", j, ptable[j]);
				LcdPrintf(buf);
			}
#endif
			
			continue;
		}
		
#ifdef DEBUG_DRV_INSTALL
		sprintf(buf, "mode = %d ", mode);
		LcdPrintf(buf);
#endif
		
        if(mode == MODE_INTHOOK)
        {
			
#ifdef DEBUG_DRV_INSTALL
            sprintf(buf, "\nInstall hook %x  %x ", pHookTbl[i].int_num, pHookTbl[i].fct_offset);
            LcdPrintf(buf);
#endif
			
			hook_num = IntHookISR(new_app_id, pHookTbl[i].int_num, pHookTbl[i].fct_offset);
			IntSetActive(hook_num);
			
        }
        else
        {
#ifdef DEBUG_DRV_INSTALL
            sprintf(buf, "\nInstall syscall %x  %x ", pHookTbl[i].int_num, pHookTbl[i].fct_offset);
			LcdPrintf(buf);
#endif
            SysHookSyscall(new_app_id, pHookTbl[i].int_num, (UWORD*)pHookTbl[i].fct_offset);
#ifdef DEBUG_DRV_INSTALL
			LcdPrintf(" hook ok");
#endif
			
            if(!reset_sys_call)
                reset_sys_call = pHookTbl[i].int_num;
		}
    }
	
    if(reset_sys_call)
    {
		//            SysCallHooked(reset_sys_call);
    }
	
#ifdef DEBUG_DRV_INSTALL
	i = 0xfffffff;
	while(i--);
#endif
	
	
}



/*************************************
Add a record
**************************************/
void SyncRecAddLarge()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncRecAddLarge2);
    PortWaitForChar(ADDREC_SEQ,ADDREC_SEQ,ADDREC_SEQ,TRUE);
    PortSendChar(ADDREC_ACK);
}

void SyncRecAddLarge2(UBYTE x)
{
#ifdef DEBUG
	LcdPrintf(" AR2 ");
#endif
	SetWaitReturnFct(SyncRecAddLarge3);
	PortWaitForLength(10);   /* dbid + recid + num_field */
}

void SyncRecAddLarge3(UBYTE x)
{
	int i;
#ifdef DEBUG        
	LcdPrintf(" AR3 ");
#endif
	sync_dbid = *(DatabaseID*) sync_buf;
	sync_recid = *(((RecordID*) sync_buf)+1);
	sync_num_field = *(USHORT*) (sync_buf + 8);
	
#ifdef DEBUG
	for(i=0;i<12;i++)
	{
		sprintf(buf, " %d ", sync_buf[i]);
		LcdPrintf(buf);
	}
#endif
	
	SetWaitReturnFct(SyncRecAddLarge4);
	PortWaitForLength(10 + sync_num_field * 4 + 2); /* total field * 4(field size) + cs */
	PortSendChar(ACK);
}

void SyncRecAddLarge4(UBYTE x)
{
	UWORD rec_num;
	USHORT block, b, i;
	RecordHeader *rec_ptr;
	BYTE retc;
	WORD endata, byte_use;
	UWORD dum, count;
	BYTE *temp;
	
	
#ifdef DEBUG_NEWREC
	char buf[70];
	LcdPrintf("@");
#endif
	
#ifdef DEBUG
	Err err;
	LcdPrintf(" AR4 ");
#endif
	for(b=0;b<TOTAL_SLOT;b++)     /* find all slot for the db */
	{
		if(MemoryFindStartBlock(mat_info_ptr[b], sync_dbid, &block) == TRUE)
			if(BlockType(mat_info_ptr[b]->mat[block].attribute) == MAT_BLOCK_DB_REC)
				break;
	}
	if(b>=TOTAL_SLOT)
		goto db_not_found;
	
	sync_sblock = MakeSBlock(b,block);
	
	if(DataOpenDB(sync_dbid, DB_NO_SORT, OPEN_RW) != TRUE)
		goto db_not_found;
	else
	{
		if(DataRecIDtoNum(sync_dbid, sync_recid, &rec_num) == TRUE)
			goto rec_exists;
		if(DataNewRecordWithID(sync_dbid, sync_recid, 0, sync_num_field) != TRUE)
			goto no_space;
		
		need_del = 1;
		del_recid = sync_recid;
		del_dbid = sync_dbid;
		
		
#ifdef DEBUG
		sprintf(buf, "\ndbid = %08x New record id = %08x  field = %d ", sync_dbid, sync_recid, sync_num_field);
		LcdPrintf(buf);
#endif
		
#ifdef DEBUG
		strcpy(buf, " fc ");
		LcdPrintf(buf);
#endif
		sync_total_size = 0;
		temp = (BYTE*) sync_field_size;
		for(i=0;i<sync_num_field * 4;i++)
		{
			*(temp++) = sync_buf[i+10];
#ifdef DEBUG
			sprintf(buf, " %x ", sync_buf[i+10]);
			LcdPrintf(buf);
#endif
		}
		for(i=0; i<sync_num_field; i++)
		{
			UWORD acc_size = 0;
			
			
#ifdef DEBUG_NEWREC
			sprintf(buf, "f%d: %d ", i, sync_field_size[i]);
			LcdPrintf(buf);
#endif
			DataClearFieldCache();
			if(sync_field_size[i] > ACC_COUNT )
			{
				for(count=0;count < sync_field_size[i] / ACC_COUNT ; count++)
				{
					acc_size += ACC_COUNT;
					
#ifdef DEBUG_NEWREC
					sprintf(buf, " acc %d ", acc_size);
					LcdPrintf(buf);
#endif
					
					if(MemoryCheckMemLow())
						goto no_space2;
					
					if(DataResizeField2(sync_dbid, sync_recid, i, acc_size  ) != TRUE)
						goto no_space2;
					
				}
#ifdef DEBUG_NEWREC
				sprintf(buf, "\nLast Size %d ", sync_field_size[i]);
				LcdPrintf(buf);
#endif
				if(MemoryCheckMemLow())
					goto no_space2;
				
				if(DataResizeField2(sync_dbid, sync_recid, i, sync_field_size[i])!=TRUE)
				{
					/*Not enough space in PDA */
					goto no_space2;
				}
			}
			else
			{
				if(MemoryCheckMemLow())
					goto no_space2;
				
				if(DataResizeField2(sync_dbid, sync_recid, i, sync_field_size[i])!=TRUE)
				{
					/*Not enough space in PDA */
					goto no_space2;
				}
			}
			DataClearFieldCache();
			sync_total_size += sync_field_size[i];
			dum = sync_field_size[i];
			EnFieldSize(endata, dum, byte_use);
			sync_total_size += byte_use;
        }
#ifdef DEBUG_NEWREC
        LcdPrintf("\nB4 RB ");
		
		for(i=0; i<sync_num_field; i++)
		{
			LcdPrintf("\n");
			rec_num = 0;
			DataFieldSize(sync_dbid, sync_recid, i, &rec_num);
			sprintf(buf, "f %d s:%d ", i, rec_num);
			LcdPrintf(buf);
		}
#endif
        DataClearFieldCache();
		if (DataRecordBlock(sync_sblock, sync_recid, &sync_sblock, &rec_ptr) != TRUE)
			goto internal_error;
		sync_data = (BYTE*) rec_ptr;
		retc = ADDREC_ACK;
		DataCloseAllDB();//(sync_dbid);
#ifdef DEBUG
		LcdPrintf(" RecOK ");
#endif
		SetWaitReturnFct(SyncRecAddLarge5);
		BufferEmpty();
		PortWaitForLength(1 + RECHEADER_SIZE + 2);  /* ack + rec header + cs */
		goto common_end;
         }
		 
db_not_found:
#ifdef DEBUG
		 LcdPrintf(" db miss ");
#endif
		 retc = NAK;
		 goto error_end;
rec_exists:
#ifdef DEBUG
		 LcdPrintf(" rec exist ");
#endif
		 DataCloseAllDB();//(sync_dbid);
		 retc = REC_NAK;
		 goto error_end;
		 
internal_error:
#ifdef DEBUG
		 LcdPrintf(" rec blk miss ");
#endif
no_space2:
#ifdef DEBUG
		 LcdPrintf(" no sp for field ");
#endif
		 DataDeleteRecord(sync_dbid, sync_recid, FALSE);
no_space:
#ifdef DEBUG
		 LcdPrintf(" no sp for new rec ");
#endif
		 DataCloseAllDB();//(sync_dbid);
		 retc = REC_SIZE_NAK;
		 
error_end:
		 need_del = 0;
		 BufferEmpty();
		 SetComHandleEvent(SyncStateDBUp);
common_end:
		 PortSendChar(retc);
}

void SyncRecAddLarge5(UBYTE x )
{
	/* get header first */
    UWORD i;
    RecordHeader *recptr, *src_recptr;
	
    BufferRemove(1);    /* remove ADDREC_ST */
    recptr = (RecordHeader*) sync_data;
    src_recptr = (RecordHeader*) sync_buf;
    recptr->modi_date = src_recptr->modi_date;
    recptr->cat = src_recptr->cat;
    _valid_ptr(&sync_sblock, (BYTE**) &sync_data, RECHEADER_SIZE, NULL);
	
    rec_byte = 0;
	
    packet_size = sync_total_size;
    SetWaitReturnFct(SyncRecAddLarge6);
	
   	BufferEmpty();
   	wait_len = packet_size + 2;
	
   	if((packet_size + 2 )>= TRAN_PACKET_SIZE)  /* 2 byte cs */
		PortWaitForLength(TRAN_PACKET_SIZE);
   	else
       	PortWaitForLength(packet_size+2);
	
    PortSendChar(REC_ACK);
}


void SyncRecAddLarge6(UBYTE x)
{
	UWORD i;
	UBYTE *data = sync_buf;
	
	if(wait_len <= TRAN_PACKET_SIZE)
	{
		
		if(wait_len > 2)   /* not check sum */
		{
	           for(i=0;i<(wait_len - 2)% TRAN_PACKET_SIZE;i++)
			   {
				   *sync_data = data[i];
				   _valid_ptr(&sync_sblock, (BYTE**) &sync_data, 1, NULL);
			   }
		}	
		
		BufferEmpty();
		SetWaitReturnFct(NULL);
		SetComHandleEvent(SyncStateDBUp);
		need_del = 0;
		PortSendChar(REC_ACK);
		return;
	}
	for(i = 0; i < sync_buf_len; i++)
	{
		*sync_data = data[i];
		_valid_ptr(&sync_sblock, (BYTE**) &sync_data, 1, NULL);
	}
	
	wait_len -= sync_buf_len;
	BufferEmpty();
	
	
	if(wait_len > TRAN_PACKET_SIZE)
		PortWaitForLength(TRAN_PACKET_SIZE);
	else
	{
		
		if(wait_len == TRAN_PACKET_SIZE)
			PortWaitForLength(TRAN_PACKET_SIZE);
		else
			PortWaitForLength(wait_len % TRAN_PACKET_SIZE);
	}
	PortSendChar(ACK);
}


BOOLEAN SyncCheckScheduleRecordChange(DatabaseID dbid, RecordID rec_id)
{
	BYTE			*buffer;
	BOOLEAN                 result = FALSE;
	UWORD                   byte_read;
	WORD			num_appmt, count = 0;
	AppointmentDB           *appmt_rec; 
	
	DataGetField(dbid, rec_id, 1, &buffer, &byte_read);
	
	SchedulerDBGetAppmtRec(buffer, byte_read, (AppointmentDB **)&appmt_rec, &num_appmt);
	qfree(buffer);
	
	
	while (count < num_appmt)
	{
		if 	((appmt_rec[count].appmt_num & (0x80000000)))
		{
			result = TRUE;
			break;
		}
		count ++;	
	}
	qfree(appmt_rec);
	return result;
}


void SchedulerDBGetAppmtRec(BYTE *string_buffer, UWORD num_bytes, AppointmentDB **appmt_rec, WORD *num_appmt)
{
	BYTE *temp_ptr;
	WORD acc_num_appmt = 0;
	WORD count;
	
	*num_appmt = num_bytes/sizeof(AppointmentDB);
	if (*num_appmt == 0)
	{
		*appmt_rec = NULL;
		return;
	}
	
	temp_ptr = string_buffer;
	
	*appmt_rec = (AppointmentDB *)qmalloc(*num_appmt * sizeof(AppointmentDB));
	acc_num_appmt = 0;
	for (count = 0; count < *num_appmt; count++)
	{
		(*appmt_rec)[count] = *((AppointmentDB*)(temp_ptr));
		temp_ptr += sizeof(AppointmentDB);
	}
}


void SyncChgSchApptNum()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncChgSchApptNum2);
    PortWaitForLength(6);  /* offset + cs */
    BufferEmpty();
    PortSendChar(SCH_ACK);
}

BOOLEAN SyncChangeSchDBAptNum(UWORD offset);

void SyncChgSchApptNum2(UBYTE x)
{
	UWORD offset;
	SHORT cs;
	
	offset = *(UWORD*) sync_buf;
	cs = *(SHORT*) &sync_buf[4];
	BufferEmpty();
	
	SyncChangeSchDBAptNum(offset);
	SetWaitReturnFct(NULL);
	SetComHandleEvent(SyncStateDBEnq);
}


BOOLEAN SyncChangeSchDBAptNum(UWORD offset)
{
	BYTE			*buffer;
	BOOLEAN                 result = FALSE;
	UWORD                   byte_read;
	WORD                    num_appmt, count = 0;
	AppointmentDB           *appmt_rec;
	DatabaseID dbid;
	UWORD tr,i,j;
	RecordID recid;
	UWORD max_count = 1000 + offset + 1;
	
	if(DataFindDB(SCHAPPDB, &dbid) != TRUE)
		goto err_end2;
	
	DataOpenDB(dbid, 0, OPEN_RW);
	
	if(DataTotalRecord(dbid, &tr) != TRUE)
        goto err_end1;
	
	for(i=0;i<tr;i++)
	{
        if(DataOpenRecord(dbid, i, &recid, NULL) == TRUE)
        {
			byte_read = 0;
			DataGetField(dbid, recid, 1, (BYTE**)&appmt_rec, &byte_read);
			for(j=0;j<byte_read/sizeof(AppointmentDB);j++)
			{
                appmt_rec[j].appmt_num += offset;
                if(appmt_rec[j].appmt_num > max_count)
					max_count = appmt_rec[j].appmt_num;
			}
			DataWriteField(dbid, recid, 1, byte_read, (BYTE*)appmt_rec);
			if(byte_read)
                qfree(appmt_rec);
			DataCloseRecord(dbid, recid);
        }
        PortSendChar(REC_ACK);
	}
	
#define RESTART                 0
#define SCH_STATUS      0x80001000
	
	if (DataRecordInfo(dbid, SCH_STATUS, NULL, NULL, NULL, NULL, NULL) != TRUE)
	{
		BYTE	application_status;
        BYTE        font_size = SMALL_FONT;
		
        application_status = RESTART;
		
        DataNewRecordWithID(dbid, SCH_STATUS, 0, 4);
        DataWriteField(dbid, SCH_STATUS, 0, 1, &application_status);
        DataWriteField(dbid, SCH_STATUS, 1, 1, &font_size);
        DataWriteField(dbid, SCH_STATUS, 2, sizeof(UWORD), (BYTE*)&count);
	}
	max_count++;
	DataWriteField(dbid, SCH_STATUS, 3, sizeof(UWORD), (BYTE*)&max_count);
	
	PortSendChar(ACK);
	goto norm_end;
err_end1:
err_end2:
	PortSendChar(NAK);
norm_end:
	DataCloseAllDB();//(dbid);
}

void ExpenseDatabaseInit()
{
	WORD			i = 0;
	BYTE			textbox_string[15] = {0}, bchar_pos = 0;
	DatabaseID		Expense_dbid;
	BYTE			curr_to_cat;
	
	/* New Database */
	if (!DataFindDB(EXPDB, &Expense_dbid))
		if (DataNewDB(EXPDB, F_DATE, EXPAPP, &Expense_dbid) == ERR_DATA_NO_SPACE)
            return;
		
		if (DataOpenDB(Expense_dbid, F_DATE, OPEN_RW) != TRUE)
			return;
		
        if (DataNewRecordWithID(Expense_dbid, EXPENSE_CURR_REC_ID, 0, NUM_FLODERS) != TRUE)
			return;
        curr_to_cat = (BYTE)NONE_CURR;
        for(i=0; i<NUM_FLODERS; i++)
			if (DataWriteField(Expense_dbid, EXPENSE_CURR_REC_ID, (USHORT)i, sizeof(BYTE), &curr_to_cat) != TRUE)
				return;
			if (DataNewRecordWithID(Expense_dbid, EXPENSE_MAIN_APP_SAVE, 0, 15) != TRUE)
				return;
			if (DataWriteField(Expense_dbid, EXPENSE_MAIN_APP_SAVE, F_ExpTextboxString, 16*sizeof(BYTE), (BYTE*)textbox_string) != TRUE)
				return;
			if (DataWriteField(Expense_dbid, EXPENSE_MAIN_APP_SAVE, F_ExpTextboxCharPos, sizeof(BYTE), (BYTE*)&bchar_pos) != TRUE)
				return;
			if (DataNewRecordWithID(Expense_dbid, EXPENSE_MDB_APP_SAVE, 0, 18) != TRUE)
				return;
}

//reg

/*************************************
Add a database
**************************************/
void SyncDBNew()
{
	SetComHandleEvent(NULL);
	SetWaitReturnFct(SyncDBNew2);
	PortWaitForChar(NEWDB_SEQ,NEWDB_SEQ,NEWDB_SEQ,TRUE);
	PortSendChar(NEWDB_ACK);
}

void SyncDBNew2(UBYTE x)
{
#ifdef DEBUG
	LcdPrintf("\nSyncDBNew2()");
#endif
	SetTimeOutFct(SyncNormalAbort);
	SetWaitReturnFct(SyncDBNew3);
	PortWaitForLength(6); // wait for len + CS
}

void SyncDBNew3(UBYTE x)
{
	UWORD len;
	
#ifdef DEBUG
    LcdPrintf("\nSyncDBNew3()");
#endif
    memcpy(&len,sync_buf, 4);
    SetTimeOutFct(SyncNormalAbort);
    SetWaitReturnFct(SyncDBNew4);
    BufferEmpty();
    PortWaitForLength(len);
    PortSendChar(ACK);
}

void SyncDBNew4(UBYTE x)
{
	BYTE* dbname;
	USHORT dbversion;
	BYTE* dbowner;
	UWORD retc;
	DatabaseID dbid;
	BYTE inst_msg[80];
	
	dbname = qmalloc(sizeof(BYTE) * strlen(sync_buf) + 1);
	strcpy(dbname, sync_buf);
	memcpy(&dbversion,sync_buf + strlen(dbname) + 1, 2);
	dbowner = qmalloc(sizeof(BYTE) * strlen(sync_buf + strlen(dbname) + 3) + 1);
	strcpy(dbowner, sync_buf + strlen(dbname) + 3);
	strcpy(inst_msg, dbname);
	SetTimeOutFct(SyncNormalAbort);
	retc = DataNewDB(dbname, dbversion, dbowner, &dbid);
	switch(retc)
	{
	case 1:
		strcat(inst_msg, " OK");
		PortSendChar(NEWDB_ACK);
		break;
	case ERR_DATA_DB_EXIST:
		strcat(inst_msg, " Failed");
		PortSendChar(NEWDB_EXIST_NAK);
		break;
	case ERR_DATA_NO_SPACE:
		strcat(inst_msg, " Failed");
		PortSendChar(NEWDB_SIZE_NAK);
		break;
	default:
		strcat(inst_msg, " Failed");
		PortSendChar(NEWDB_NAK);
		break;
		
	}
	BufferEmpty();
	SetWaitReturnFct(NULL);
	SetComHandleEvent(SyncStateDBUp);
	DispStr(inst_msg);
	qfree(dbname);
	qfree(dbowner);
}

//RecordHeader sync_header;
UBYTE sync_header[16];
//UWORD  rec_header_size;
//USHORT rec_header_total_fields;
//UWORD  rec_header_rec_id;

/*************************************
Add a new record
**************************************/
void SyncRecNew()
{
	SetComHandleEvent(NULL);
    SetWaitReturnFct(SyncRecNew2);
    PortWaitForChar(NEWREC_SEQ,NEWREC_SEQ,NEWREC_SEQ,TRUE);
    PortSendChar(NEWREC_ACK);
}

void SyncRecNew2(UBYTE x)
{
	SetTimeOutFct(SyncNormalAbort);
    SetWaitReturnFct(SyncRecNew3);
    PortWaitForLength(4 + sizeof(RecordHeader) + 2);
}

UBYTE		*HDBData, *HDBDataTemp;
UWORD		HDBLen, HDBWaitLen;


void SyncRecNew3(UBYTE x)
{
	UBYTE			cat;
	int 			retc = 0;
	UBYTE 			open_mode;
	USHORT 			sort_field;
	int 			i;
	BYTE 			*data;
    SHORT 			cs = 0;
	RecordHeader 	rec_header;
	UBYTE			*TempSendBuffer = SendBuffer;
	
    memcpy(&sync_dbid,sync_buf,4);
    memcpy(&rec_header,sync_buf+4,sizeof(RecordHeader));
    SetTimeOutFct(SyncNormalAbort);
	
	//open DB if closed
	if(DataIsDBOpen(sync_dbid, &open_mode, &sort_field)==FALSE)
		if(DataOpenDB(sync_dbid, 0, OPEN_RW)!=TRUE)	
			retc = -1;	//mark as failed
		
		if(retc==0)
			retc= DataNewRecord(sync_dbid, rec_header.cat, rec_header.total_field, &rec_header.rec_id);
		
		if(retc != TRUE)
		{
			SetWaitReturnFct(SyncRecNew5);
			PortWaitForLength(2);		
			switch(retc)
			{
			case ERR_DATA_INV_PARAM:
				PortSendChar(NEWREC_INV_NAK);
				break;
			case ERR_DATA_NO_SPACE:
				PortSendChar(NEWREC_SIZE_NAK);
				break;
			default:
				PortSendChar(NEWREC_NAK);
				break;
				
			}
			BufferEmpty();
		}                         
		else
		{
			memcpy(sync_header,&rec_header,sizeof(RecordHeader));
			PortSendChar(NEWREC_ACK);
			//for(i=0; i<sizeof(RecordHeader); i++)
			//	PortSendChar(sync_header[i]);
			for(i=0; i<sizeof(RecordHeader); i++)
			{
				*TempSendBuffer = sync_header[i];        
				TempSendBuffer ++;
			}        	
			data = (BYTE*) &cs;
			//PortSendChar(data[0]);	    
			*TempSendBuffer = data[0];        
			TempSendBuffer ++;	    
			//PortSendChar(data[1]);
			*TempSendBuffer = data[1];        
			TempSendBuffer ++;	    
			ComSendData(hport, (BYTE*)SendBuffer, (UWORD)(TempSendBuffer - SendBuffer));
			
			BufferEmpty();
			SetWaitReturnFct(SyncRecNew4);
			//PortWaitForLength(rec_header.size + 2);
			HDBLen = rec_header.size + 2;
			HDBData = (UBYTE*)qmalloc(HDBLen * sizeof(UBYTE));
			HDBDataTemp = HDBData;
			
			if (HDBLen > 2048)
				HDBWaitLen = 2048;		
			else
				HDBWaitLen = HDBLen;
			PortWaitForLength(HDBWaitLen);								
			
		}
}

void SyncRecNew4(UBYTE x)
{
	BYTE			*record_buffer;
	BYTE			*buf_ptr;
	UWORD 			decoded_len,decoded_byte_count;
	int 			i;
	int 			retc = 0;
	RecordHeader 	rec_header;
	
	PortSendChar(ACK);	    
	memcpy(HDBDataTemp, sync_buf, HDBWaitLen);
	HDBDataTemp += HDBWaitLen;
	HDBLen -= HDBWaitLen;
	
	SetWaitReturnFct(SyncRecNew4);
	if (HDBLen > 2048)
	{
		BufferEmpty();
		HDBWaitLen = 2048;		
		PortWaitForLength(HDBWaitLen);
	}
	else if (HDBLen > 0)
	{
		BufferEmpty();
		HDBWaitLen = HDBLen;		
		PortWaitForLength(HDBWaitLen);
	}
	else
	{
		memcpy(&rec_header, sync_header, sizeof(RecordHeader));
		
		//now add data to records
		buf_ptr = HDBData;
		decoded_len = 0;
		for(i=0;i<rec_header.total_field;i++)
		{
			buf_ptr += decoded_len;
			DeFieldSize(buf_ptr,decoded_len,decoded_byte_count);
			retc = DataWriteField(sync_dbid, rec_header.rec_id,i, decoded_len, buf_ptr);
		}	
		DataCloseDB(sync_dbid);
		qfree(HDBData);
		
		PortSendChar(NEWREC_ACK);
		BufferEmpty();
		SetWaitReturnFct(NULL);
		SetComHandleEvent(SyncStateDBUp);
	}		
}

void SyncRecNew5(UBYTE x)
{
	SetWaitReturnFct(NULL);
    SetComHandleEvent(SyncStateDBUp);
    PortSendChar(ACK);
}

