/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**********************************************************************/
/*   Module	      : EDDJCP.C				      */
/*								      */
/*   Description      : PM Display Driver DBCS handling routine       */
/*			Management of CP Vector table		      */
/*								      */
/*   Created	      :  3/27/92				      */
/*   Author	      : Yohji Nakamura (JL04328 at YMTVM6)	      */
/*								      */
/*   Notes	      : 					      */
/*    - This module manages CP Vector Map Table, including 2 maps     */
/*	(SBCS and DBCS) and parsing flag.  SBCS map means conversion  */
/*	table from codepoint to glyph index.  DBCS map means flag     */
/*	table where TRUE (non-0) means DBCS leading byte.  Since      */
/*	SBCS vector maps are kept by GRE, we will not hold it.	      */
/*	Map tables for only DBCS/MBCS will be saved by ourselves.     */
/*	(Since DBCS maps are not held by system, only environment     */
/*	vectors are.)						      */
/*								      */
/*   History	      : 					      */
/*								      */
/*			OCO Source Materials			      */
/*			XXXX-XXX				      */
/**********************************************************************/
#define INCL_WINCOUNTRY 	       /* for WinQueryCPList def.     */
#define INCL_DOSNLS		       /* for COUNTRYINFO def.	      */
#define INCL_DOSMODULEMGR	       /* for DosLoadModule def.      */
#define INCL_DOSERRORS		       /* for error constants	      */
#define INCL_GRE_FONTS		       /* for GreQueryCP... def.      */
#include <eddinclt.h>		       /* this include all files      */
#include <memman.h>		       /*			      */

#include <os2nlsp.h>		       /*			      */

#include <eddjfm.h>
#include <eddjdef.h>		       /*			      */
#include <eddjfont.h>							/*YOJN*/

/*====================================================================*/
/* private types						      */
/*====================================================================*/
#define BYTE_RANGE	256	       /* range of 1 byte code...     */
#define CP_MARGIN	10	       /* margin for unknown CPs...   */

typedef struct			       /*			      */
  {				       /*			      */
    BYTE bStart;		       /* start/end of DBCS leading   */
    BYTE bEnd;			       /*   byte range		      */
  } DBCSENVENTRY;		       /*			      */

#define MAX_DBCS_ENV	8	       /* Prog. Ref says 12bytes (6   */
				       /*   entries) required, so we  */
				       /*   will use this smart value.*/
typedef struct			       /*			      */
  {				       /*			      */
    BYTE bLeadingFlag[BYTE_RANGE];     /* non-0 if DBCS leading byte  */
    DBCSENVENTRY DbcsEnv[MAX_DBCS_ENV];/* DBCS environment vector     */
  } DBCSMAP;			       /*			      */

typedef DBCSMAP *PDBCSMAP;	       /*			      */

typedef struct			       /*			      */
  {				       /*			      */
    USHORT fsNlsParseFlag;	       /* NLS parsing flags	      */
				       /*   (See EDDTYPET.H)	      */
    PUSHORT pusSbcsMap; 	       /* ptr to SBCS glyph index map */
    PDBCSMAP pdmDbcsMap;	       /* ptr to DBCS leading byte map*/
  } CPMAPHEADER;		       /*			      */

typedef CPMAPHEADER *PCPMAPHEADER;     /*			      */
				       /*			      */
/*====================================================================*/
/* global variables (can be static, but for ease of debugging)	      */
/*====================================================================*/
PULONG pulCpIDTable;		       /* ptr to codepage ID table    */
PCPMAPHEADER pCpMapTable;	       /* ptr to Header array	      */
ULONG ulCpMapCount;		       /* # of CpMap entries available*/
ULONG ulCpMapValid;		       /* # of CpMap entries for which*/
				       /*   flag/map field are valid  */
ULONG ulCpMapMax;		       /* size of CP buffers at presnt*/

/*====================================================================*/
/* external variables						      */
/*====================================================================*/
//extern HAB hab;			/* set in fillphysdevblock     */

/*====================================================================*/
/* private macros (for ease of reading) 			      */
/*====================================================================*/
#define SETVALUE( ptr, value )		\
	if (ptr)			\
	  {				\
	    *(ptr) = (value);		\
	  }
				       /* if non-NULL ptr, set value  */

/*====================================================================*/
/* private functions						      */
/*====================================================================*/
USHORT QueryParsingFlag( ULONG ulCodePage,
			 DBCSENVENTRY *pEnv,
			 ULONG	ulEnvLen );
VOID CreateCPVectors( ULONG ulCodePage,
		      PCPMAPHEADER pHeader,
		      DBCSENVENTRY *pEnv );
VOID CreateDbcsVectors( PDBCSMAP pdm, DBCSENVENTRY *pEnv );

BOOL AllocateCPBuffers( ULONG ulSize );

BOOL ExpandCPBuffers( ULONG ulSize );

/*===================== Exported Routine =============================*/
/*	eddj_InitCPVectorsTable 				      */
/*								      */
/* This function does:						      */
/*	- Allocate memory for CP map index			      */
/*	- Initialize variables for management of CP vector map table  */
/*								      */
/* Entry       :	None					      */
/*								      */
/* Returns     :	Returns TRUE (non-0)			      */
/*								      */
/* Error Returns :	Returns FALSE (0) if error		      */
/*								      */
/* Note        :      - This func should be called only once.	      */
/*		      - Different from similar routine in VGA/DBCS    */
/*			driver, only header space is allocated here.  */
/*			Codepage IDs are remembered, but map table    */
/*			will be created when Query... is called for   */
/*			that CP.				      */
/*		      - Memory allocated here is used as following:   */
/*								      */
/*			pulCpIDTable --->  +-----------------------+  */
/*					   |  Codepage ID #1 (4B)  |  */
/*					   |	    :		   |  */
/*					   |  Codepage ID #N (4B)  |  */
/*			pCpMapTable ---->  +-----------------------+  */
/*					   |  CpMapHeader #1 (10B) |  */
/*					   |	    :		   |  */
/*					   |  CpMapHeader #N (10B) |  */
/*					   +-----------------------+  */
/*			(N == ulCpMapCount)			      */
/*		      - Order of codepage IDs are always maintained   */
/*			so that the first 'ulCpMapValid' entries have */
/*			valid header field (i.e. flag and map ptrs).  */
/*								      */
/* Calls       :						      */
/*								      */
/*====================================================================*/
BOOL eddj_InitCPVectorsTable( VOID )
{				       /* top of func: eddj_InitCPVect*/
  ulCpMapCount = WinQueryCpList( NULL, 0, NULL );
				       /* query # of CPs available    */
  ulCpMapMax = ulCpMapCount + CP_MARGIN;
				       /* we do not trust PMWIN should*/
				       /* know all CPs...	      */
  if (!AllocateCPBuffers( ulCpMapMax ))
    {				       /*			      */
      return FALSE;		       /*			      */
    }				       /* end of if:		      */

  WinQueryCpList( NULL, ulCpMapCount, pulCpIDTable );
				       /*			      */
  ulCpMapValid = 0;		       /* no entry has valid header   */

  return TRUE;			       /* normal end.		      */
}				       /* end of func: eddj_InitCPVect*/

/*===================== Exported Routine =============================*/
/*	eddj_QueryCPVectors					      */
/*								      */
/* Returns ptr to Vector Map Header structure for given Codepage      */
/*								      */
/* Entry       :      - Codepage ID				      */
/*		      - Address of ptr where SBCS map address should  */
/*			be returned (May be NULL)		      */
/*		      - Address of ptr where DBCS map address should  */
/*			be returned (May be NULL)		      */
/*		      - Address of USHORT where CP flag should be     */
/*			returned    (MUST NOT BE NULL!) 	      */
/*								      */
/* Returns     :	Returns TRUE				      */
/*								      */
/* Error Returns :	Returns FALSE if error			      */
/*								      */
/* Note        :						      */
/*		      - If no map is requested (i.e. NULL pointers    */
/*			are passed in 'ppusSbcsMap' and 'pbDbcsMap',  */
/*			this routine does not try to create map now.  */
/*			It is because this function may be called     */
/*			in system init time, (InitializeSystem in     */
/*			PMWIN -> GreInitialize32 -> FillLDB -> FillPDB*/
/*			-> GetRuntimeOptions -> this!) and in this    */
/*			case, GreQueryCodepageVectors cannot be called*/
/*			as Initialize of PMWIN and PMGRE has not been */
/*			finished.				      */
/*		      - DO NOT FORGET that SBCS map vector table      */
/*			returned by this routine is to map given CP   */
/*			to UGL codepage (850).	When font to be used  */
/*			is not UGL font, it should not be used.       */
/*			(DBCS map may be usable, as it does not depend*/
/*			on the font's CP.)                            */
/*		      - This func returns FALSE only if:	      */
/*			 1a. SBCS map is requested (i.e. non-NULL is  */
/*			     passed), and			      */
/*			 1b. Given codepage is not 850, and	      */
/*			 1c. No SBCS map vector is available	      */
/*				or				      */
/*			 2.  Cannot allocate memory for DBCS map      */
/*				or				      */
/*			 3.  Given CP does not belong to CP list      */
/*			     returned by WinQueryCpList()	      */
/*								      */
/*			In other case, we should do our best effort.  */
/*								      */
/*		      - Now GRE passes IFI font with CP in metrics    */
/*			== 0.  This means the font can be used for    */
/*			any CP without SBCS mapping.		      */
/*								      */
/* Calls       :						      */
/*								      */
/*====================================================================*/
BOOL pascal eddj_QueryCPVectors( ULONG ulCodePage,
				 PUSHORT *ppusSbcsMap,
				 PBYTE	 *ppbDbcsMap,
				 PUSHORT pfsFlags )
{				       /* top of func: eddj_QueryCPVec*/
  ULONG ulIndex;		       /*			      */
  DBCSENVENTRY aEnv[MAX_DBCS_ENV];     /* buffer for DBCS env vector  */
  PCPMAPHEADER pCurHeader;	       /*			      */
				       /*			      */
#ifdef FIREWALLS
  if (!pfsFlags)		       /* if flag is not requested    */
    {				       /*			      */
      haltproc();		       /*   must be calling error!    */
    }				       /* end of if:		      */
#endif				       /*			      */

  if (ulCodePage == 0)		       /* IFI font case...	      */
    {				       /*			      */
      *pfsFlags = NLSCA_SBCS;	       /*			      */
//    SETVALUE( ppusSbcsMap, NULL );   /*			      */
      return TRUE;		       /*			      */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* if SBCS-only system, just pass to GRE...			      */
  /*------------------------------------------------------------------*/
  if (!CHECKENV(ENV_DBCS_CAPABLE))     /*			      */
    {				       /*			      */
      SETVALUE( ppbDbcsMap, NULL );    /* must not have DBCS map      */

      if (ulCodePage == CP_UGL_FONT)
	{
	  *pfsFlags = NLSCA_SBCS;
//	  SETVALUE( ppusSbcsMap, NULL );
	  return TRUE;		       /*			      */
	}			       /* end of if:		      */

      *pfsFlags = NLSCA_SBCS | NLSCA_MAP_SBCS;
				       /* not UGL CP => have map      */
      if (ppusSbcsMap)		       /* if SBCS map is requested    */
	{
	  *ppusSbcsMap = (PUSHORT)GreQueryCodePageVector(ulCodePage);
				       /* call GRE to get vector map  */
	  if (*ppusSbcsMap == GPI_ERROR)
	    {			       /*			      */
	      return FALSE;	       /*			      */
	    }			       /* end of if:		      */
	}			       /* end of if:		      */

      return TRUE;		       /*			      */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* DBCS capable system: Look if we already have the map vectors     */
  /*------------------------------------------------------------------*/
  for (ulIndex=0;
       (ulIndex < ulCpMapCount)&&(pulCpIDTable[ulIndex] != ulCodePage);
       ulIndex++);

  if (ulIndex >= ulCpMapCount)	       /* if we do not know this CP   */
    {				       /* in init time, ask GRE anyway*/
      if ((ulCpMapCount == ulCpMapMax) &&
	  (!ExpandCPBuffers(CP_MARGIN)))/*if no more spare buffer and */
	{			       /* cannot expand any more      */
	  return FALSE; 	       /* no way		      */
	}			       /* end of if:		      */

      ulCpMapCount ++;		       /* now we will add this new CP */
      pulCpIDTable[ulIndex] = ulCodePage;
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* if we have not created map for it, then create now.	      */
  /*------------------------------------------------------------------*/
  if (ulIndex >= ulCpMapValid)	       /* if flag/map is not created  */
    {
      /*--------------------------------------------------------------*/
      /* create NLS parsing flags				      */
      /*--------------------------------------------------------------*/
      *pfsFlags =
	QueryParsingFlag( ulCodePage,
			  aEnv,
			  sizeof(DBCSENVENTRY) * MAX_DBCS_ENV );
				       /* create parsing flag	      */
      if (!ppusSbcsMap && !ppbDbcsMap) /* if no map is requested      */
	{			       /* then return only flags      */
	  return TRUE;		       /*			      */
	}			       /*			      */

      /*--------------------------------------------------------------*/
      /* move the codepage info to the end of valid IDs 	      */
      /*--------------------------------------------------------------*/
      pulCpIDTable[ulIndex] = pulCpIDTable[ulCpMapValid];
      pulCpIDTable[ulCpMapValid] = ulCodePage;
				       /* move found CP ID to tail of */
				       /*   valid ID area	      */
      pCurHeader = pCpMapTable + ulCpMapValid;
				       /* do not inc valid # yet      */
      /*--------------------------------------------------------------*/
      /* create SBCS/DBCS vector map				      */
      /*--------------------------------------------------------------*/
      pCurHeader->fsNlsParseFlag = *pfsFlags;
				       /* save parsing flag	      */
      CreateCPVectors( ulCodePage, pCurHeader, aEnv );
      if ((ppusSbcsMap && !pCurHeader->pusSbcsMap &&
		(pCurHeader->fsNlsParseFlag & NLSCA_MAP_SBCS)) ||
	  (ppbDbcsMap && !pCurHeader->pdmDbcsMap &&
		(pCurHeader->fsNlsParseFlag & NLSCA_MAP_DBCS)))
	{			       /* if requested, and should    */
				       /*   have, but not have map,   */
	  return FALSE; 	       /*   then error		      */
	}			       /* end of if:		      */

      ulCpMapValid ++;		       /* IS valid entry, at last!    */
    }				       /* end of if:		      */
  else				       /* or if we already have maps  */
    {				       /*			      */
      pCurHeader = pCpMapTable + ulIndex;
				       /* will work with this entry   */
      *pfsFlags = pCurHeader->fsNlsParseFlag;
    }				       /* end of else:		      */

  SETVALUE( ppusSbcsMap, pCurHeader->pusSbcsMap );
  SETVALUE( ppbDbcsMap, (PBYTE)pCurHeader->pdmDbcsMap );
  return TRUE;			       /*			      */
}				       /* end of func: eddj_QueryCPVec*/

/*===================== Private  Routine =============================*/
/*	QueryParsingFlag					      */
/*								      */
/* Create NLS parsing flag for given codepage			      */
/*								      */
/* Entry       :      - Codepage ID				      */
/*		      - Pointer to DBCS environment buffer where env  */
/*			vectors should be returned. (MUST be non-NULL)*/
/*		      - Size (in bytes) of env buffer		      */
/*								      */
/* Returns     :	Returns Parsing flag			      */
/*								      */
/* Error Returns :	None.  if some error is detected, SBCS is     */
/*			assumed.				      */
/*								      */
/* Note        :						      */
/*								      */
/* Calls       :						      */
/*								      */
/*====================================================================*/
USHORT QueryParsingFlag( ULONG ulCodePage,
			 DBCSENVENTRY *pEnv,
			 ULONG	ulEnvLen )
{				       /* top of func: QueryParseFlag */
  COUNTRYCODE cc;		       /* for DosQueryDBCSEnv call    */
  ULONG ulRC;			       /*			      */
				       /*			      */
  if (ulCodePage == CP_UGL_FONT)       /* UGL CP is special case...   */
    {				       /*			      */
      return NLSCA_SBCS;	       /*			      */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* query DBCS environment vector				      */
  /*------------------------------------------------------------------*/
  cc.country = 0;		       /* use system default country  */
  cc.codepage = ulCodePage;

  ulRC = DosQueryDBCSEnv( ulEnvLen, &cc, (PCHAR)pEnv );
  if ((ulRC != NO_ERROR) ||
      ((pEnv[0].bStart == 0) && (pEnv[0].bEnd == 0)))
    {				       /* on error, we assume SBCS    */
      return NLSCA_SBCS | NLSCA_MAP_SBCS;
				       /* since not UGL, must have map*/
				       /* we will check later if GRE  */
				       /*   really knows about this CP*/
    }				       /* end of if:		      */

  if ((pEnv[0].bStart == 0) && (pEnv[0].bEnd == 0xFF))
    {				       /*			      */
      return NLSCA_DBCS;	       /* pure DBCS: has no map       */
    }				       /* end of if:		      */

  return NLSCA_MBCS | NLSCA_MAP_SBCS | NLSCA_MAP_DBCS;
				       /* assume to have both map now.*/
				       /* check later if necessary    */
}				       /* end of func: QueryParseFlag */

/*===================== Private  Routine =============================*/
/*	CreateCPVectors 					      */
/*								      */
/* Create codepage vector table entry for given codepage	      */
/*								      */
/* Entry       :      - Codepage ID				      */
/*		      - Ptr to CpMapHeader structure to be filled     */
/*		      - Ptr to DBCS env vector table for this CP      */
/*								      */
/* Returns     :	None					      */
/*								      */
/*		      - If cannot create SBCS/DBCS map, that ptr      */
/*			becomes NULL, while NLSCA_MAP_SBCS/DBCS flag  */
/*			remains unchanged.  Caller should check it.   */
/*								      */
/* Error Returns :	None					      */
/*								      */
/* Note        :						      */
/*		      - Assumes all fields, except for ptr to SBCS/   */
/*			DBCS maps, are previously set by caller       */
/*								      */
/* Calls       :						      */
/*								      */
/*====================================================================*/
VOID CreateCPVectors( ULONG ulCodePage,
		      PCPMAPHEADER pHeader,
		      DBCSENVENTRY *pEnv )
{				       /* top of func: CreateCPVectors*/
  PUSHORT pusMap;		       /* temp ptr to SBCS map table  */
  PDBCSMAP pdmMap;		       /* temp ptr to MBCS map table  */

  /*------------------------------------------------------------------*/
  /* SBCS mapping vectors					      */
  /*------------------------------------------------------------------*/
  if (pHeader->fsNlsParseFlag & NLSCA_MAP_SBCS)
    {
      pusMap = (PUSHORT)GreQueryCodePageVector( ulCodePage );
				       /* call GRE to get vector map  */
      if (!pusMap)		       /* if GRE does not know the CP */
	{			       /*			      */
	  pHeader->pusSbcsMap = NULL;  /* map is not available	      */
	}			       /* end of if:		      */
      else			       /*			      */
	{
	  pHeader->pusSbcsMap = pusMap;/* we do not copy but use it!  */
	}			       /* end of else:		      */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* MBCS mapping vectors					      */
  /*------------------------------------------------------------------*/
  if (pHeader->fsNlsParseFlag & NLSCA_MAP_DBCS)
    {				       /*			      */
      pdmMap = AllocateMemory( sizeof(DBCSMAP), MT_CODEPAGE, MO_SHARED );
      if (!pdmMap)		       /*			      */
	{			       /*			      */
	  pHeader->pdmDbcsMap = NULL;  /* map is not available	      */
	}			       /* end of if:		      */
      else			       /*			      */
	{
	  CreateDbcsVectors( pdmMap, pEnv );
				       /* create MBCS map structure   */
	  pHeader->pdmDbcsMap = pdmMap;/* have MBCS map 	      */
	}			       /* end of else:		      */
    }				       /* end of if:		      */
}				       /* end of func: CreateCPVectors*/

/*===================== Private  Routine =============================*/
/*	CreateDbcsVectors					      */
/*								      */
/* Create DBCS leading byte map from given environment vectors	      */
/*								      */
/* Entry       :	Ptr to structure where DBCS map is created    */
/*			Ptr to DBCS environment vectors 	      */
/*								      */
/* Returns     :	None					      */
/*								      */
/* Error Returns :	None					      */
/*								      */
/* Note        :						      */
/*								      */
/* Calls       :						      */
/*								      */
/*====================================================================*/
VOID CreateDbcsVectors( PDBCSMAP pdm, DBCSENVENTRY *pEnv )
{				       /* top of func: CreateDbcsVecto*/
  memcpy( pdm->DbcsEnv, pEnv, sizeof(DBCSENVENTRY)*MAX_DBCS_ENV );
				       /* copy DBCS env vectors       */
  memset( pdm->bLeadingFlag, FALSE, sizeof(BYTE)*BYTE_RANGE );
				       /* first, clear all flags      */
  while (pEnv->bStart || pEnv->bEnd)   /*			      */
    {				       /*			      */
      memset( pdm->bLeadingFlag + pEnv->bStart,
	      TRUE,
	      sizeof(BYTE) * (pEnv->bEnd - pEnv->bStart + 1) );
      pEnv ++;			       /*			      */
    }				       /* end of while: 	      */
}				       /* end of func: CreateDbcsVecto*/

/*===================== Private  Routine =============================*/
/*	AllocateCPBuffers					      */
/*								      */
/* Allocate CP buffers with given size				      */
/*								      */
/* Entry       :	size of buffer (# of CPs)		      */
/*								      */
/* Returns     :	Returns TRUE if completes		      */
/*			  2 global variables (pulCpIDTable and	      */
/*			  pCpMapTable ) are set to top of each buff.  */
/*								      */
/* Error Returns :	Returns FALSE if cannot allocate memory       */
/*								      */
/* Note        :						      */
/*		      - If allocation fails, no global var changes.   */
/*								      */
/* Calls       :						      */
/*								      */
/*====================================================================*/
BOOL AllocateCPBuffers( ULONG ulSize )
{				       /* top of func: AllocateCPBuffe*/
  PULONG pulID; 		       /*			      */

  pulID =
    AllocateMemory( (sizeof(ULONG) + sizeof(CPMAPHEADER)) * ulSize,
		    MT_CODEPAGE, MO_SHARED );
				       /* allocate enough mem for buff*/
  if (pulID == NULL)		       /*			      */
    {				       /*			      */
      return FALSE;		       /* Error should be already     */
				       /*   logged in AllocMem()      */
    }				       /* end of if:		      */

  pulCpIDTable = pulID; 	       /*			      */
  pCpMapTable = (PCPMAPHEADER)(pulID + ulSize);
				       /* top of header buffer	      */
  return TRUE;			       /*			      */
}				       /* end of func: AllocateCPBuffe*/

/*===================== Private  Routine =============================*/
/*	ExpandCPBuffers 					      */
/*								      */
/* Allocate new and larger CP buffer and copy contents		      */
/*								      */
/* Entry       :	Size of expansion (# of additional CPs)       */
/*								      */
/* Returns     :	Returns TRUE if completes		      */
/*			Global variables are changed:		      */
/*			  pulCpIDTable, pCpMapTable : points new buff */
/*			  ulCpMapMax : new size of buffers	      */
/*								      */
/* Error Returns :	Returns FALSE if cannot allocate memory       */
/*			Global variables are not changed in this case.*/
/*								      */
/* Note        :						      */
/*								      */
/* Calls       :						      */
/*								      */
/*====================================================================*/
BOOL ExpandCPBuffers( ULONG ulSize )
{				       /* top of func: ExpandCPBuffers*/
  PULONG pulOldID = pulCpIDTable;      /*			      */
  PCPMAPHEADER pOldHeader = pCpMapTable;
				       /*			      */
  if (!AllocateCPBuffers( ulCpMapMax + ulSize ))
    {				       /* if cannot allocate new buff */
      return FALSE;		       /*			      */
    }				       /* end of if:		      */

  memcpy( pulOldID, pulCpIDTable, sizeof(ULONG)*ulCpMapCount );
  memcpy( pOldHeader, pCpMapTable, sizeof(CPMAPHEADER)*ulCpMapValid );
  FreeMemory( pulOldID );	       /*			      */
  return TRUE;			       /*			      */
}				       /* end of func: ExpandCPBuffers*/
