/*static char *SCCSID = "@(#)codepage.c	6.1 90/11/18";*/
/*static char *SCCSID = "@(#)codepage.c 13.4 90/01/30";*/
/***	CODEPAGE.C - Routines to check and read codepage information
 *
 *	CHKDSK
 *	Peter A. Williams
 *	Copyright 1988 Microsoft Corporation
 *
 *	Modification history:
 *	P.A. Williams	06/29/89     Original for Pinball 1.0.
 *	P.A. Williams	07/05/89     Changed rc = ( ? : ) - ( ? : ) line
 *				     in chk_strnicmp. This was failing
 *				     because of a compiler bug.
 *	P.A. Williams   07/09/89     Fixed subscripting error in chk_strnicmp.
 *				   
 */

#include "ldefs.h"
#include "ltypes.h"
#include "globals.h"
#include <pr_chk.h>


/***	chk_check_dbcs - check if given character is DBCS lead-byte
 *
 *	This function determines whether a given character is a
 *	DBCS lead byte or not.
 *
 *	chk_check_dbcs (c, cp_index)
 *
 *	ENTRY		c 	 - character to be checked
 *			cp_index - code page index
 *
 *	EXIT		value          meaning
 *
 *        		0             single byte
 *        		1             DBCS lead-byte
 *
 *	CALLS		none
 *
 *	WARNINGS	None
 *
 *	EFFECTS 	None
 */
USHORT chk_check_dbcs (c, cp_index)
  UCHAR c;
  USHORT cp_index;
{
  USHORT temp;

#if defined(CPTRACE) || defined(DEBUG)
   if ((cp_index != PREMAPPED) && ((ULONG)cp_index > spb.culCP))  {
      fprintf (stderr, "*** chk_check_dbcs: cp_index=%x invalid ***\n",
	       cp_index);
      cp_index = 0;
      fflush (stderr);
      DOSBEEP
   }
#endif


  if (cp_index == PREMAPPED)
     return (0);

  else {
      temp = c;
      temp = temp & 0x00FF;

      if ( temp < 0x0080 )
         return( 0 );

      return( chk_dbcs_flag [cp_index][temp & 0x007F] );
  }

}

/***	chk_check_dbcs_pos - Check if current position is DBCS or not
 *
 *	This function determines whether the current character position
 *	is DBCS lead-byte, DBCS trail-byte, or a non-DBCS character.
 *
 *	chk_check_dbcs_pos (str, cp_index, pos)
 *
 *	ENTRY 		str      - pointer to the string
 *			cp_index - code page index
 *                	pos      - character position to be tested in a line
 *
 *	EXIT		value		meaning
 *
 *        		0		single byte
 *        		1		DBCS 1st byte
 *			2		DBCS 2nd byte
 *
 *	CALLS		chk_check_dbcs
 *
 *	WARNINGS	None
 *
 *	EFFECTS 	None
 */
USHORT chk_check_dbcs_pos (line, cp_index, pos)
  UCHAR * line;
  USHORT cp_index;
  USHORT pos;
{
  register USHORT i;

  for (i=0 ; pos > i ; i++ )
     if (chk_check_dbcs(line[i], cp_index) == DBCS )
        i++;

  if (pos == i) {
    if (chk_check_dbcs(line[pos], cp_index) == DBCS )
      return(DBCS);
    else
      return(SBCS);
  } else {
    return(DBCS_2);
  }

}

/***	chk_strnicmp - compare two strings relative to individual casemap tables
 *
 *	This function compares two strings after mapping each character 
 *	through its individual casemap table. This makes the comparison
 *	case insensitive.
 *
 *	chk_strnicmp (str1, cp_index1, str2, cp_index2, len)
 *
 *	ENTRY		str1      - pointer to a str of characters
 *			cp_index1 - code page index for str1.
 *	     		str2      - pointer to a str of characters
 *			cp_index2 - code page index for str2.
 *			len       - the number of characters to be checked
 *
 *  	EXIT   		integer
 *       		value            meaning
 *       		less than 0      str1 less than str2
 *       		0                str1 identical to str2
 *       		greater than 0   str1 greater than str2
 *
 *	CALLS		chk_check_dbcs
 *
 *	WARNINGS	First character of str1 and str2 must be 
 *			single byte code or first byte of 2 byte code.
 *
 *	EFFECTS 	None
 */

int chk_strnicmp (str1, cp_index1, str2, cp_index2, len)
UCHAR *str1; 
USHORT cp_index1;
UCHAR *str2;
USHORT cp_index2;
USHORT len;
{
USHORT j;
UCHAR char1, char2;
int rc;

 /* loop thru strings checking the upper cases for
    equality. If a double byte character is found,
    the second byte must not be fed to toupper before
    comparison */

#ifdef CPTRACE
   fprintf (stderr, "chk_strnicmp ('%s', \n              '%s', \n              indx1=%x, indx2=%x, len=%x)\n",
	    str1, str2, cp_index1, cp_index2, len);
   fflush (stderr);
#endif

#if defined(CPTRACE) || defined(DEBUG)

   /* ensure that codepage indices are good */

   if ((cp_index1 != PREMAPPED) && (cp_index1 > (USHORT)spb.culCP)) {
      fprintf (stderr, "*** chk_strnicmp: cp_index1=%u invalid ***\n",
				cp_index1);
      cp_index1 = 0;
      fflush (stderr);
      DOSBEEP
   }
  if ((cp_index2 != PREMAPPED) && (cp_index2 >= (USHORT)spb.culCP)) {
      fprintf (stderr, "*** chk_strnicmp: cp_index2=%u invalid ***\n",
				cp_index2);
      cp_index2 = 0;
      fflush (stderr);
      DOSBEEP
   }
#endif

 for (j = 0; j < len; j++, str1++, str2++) {

         if ((cp_index1 != PREMAPPED) && 
	      (chk_check_dbcs(*str1, cp_index1) == DBCS)) {   /* @@ if DBCS */
            if (rc=(*str1 - *str2))
               return(rc);
	    if (rc=(*(++str1) - *(++str2)))
	       return(rc);

	 } else {

	    if (cp_index1 == PREMAPPED)
	       char1 = *str1;
	    else
	       char1 = chk_casemap[cp_index1][*str1];

	    if (cp_index2 == PREMAPPED) 
	       char2 = *str2;
	    else
	       char2 = chk_casemap[cp_index2][*str2];

            if (rc=(char1 - char2))
               return(rc);
	 }
 }

 return(0);     /* if we haven't returned yet, the strings are the same */

}

/***	chk_strnupr - convert n bytes of a string to upper case
 *
 *	chk_strnupr (string, cp_index, len)
 *
 *	ENTRY		string   - pointer to a string of characters
 *			cp_index - code page index
 *			len      - the number of characters to be converted
 *
 *	EXIT		Returns a pointer to the converted string
 *
 *	CALLS		chk_check_dbcs
 *
 *	WARNINGS	None
 *
 *	EFFECTS 	None
 */
UCHAR *chk_strnupr(string, cp_index, len)
   UCHAR *string;
   USHORT cp_index;
   USHORT len;
{
   UCHAR *strptr;
   strptr = string;

#ifdef CPTRACE
   fprintf (stderr, "chk_strupr ('%s', \n            indx=%x, len=%x)\n",
	    string, cp_index, len);
   fflush (stderr);
#endif

#if defined(CPTRACE) || defined(DEBUG)

   /* make sure code page index is valid. If not fix it. */

   if ((cp_index != PREMAPPED) && (cp_index > (USHORT)spb.culCP)) {
      fprintf (stderr, "*** cp_index=%u invalid ***\n", cp_index);
      cp_index = 0;
      fflush (stderr);
      DOSBEEP
   }
#endif

   for ( ; len; len--)
      if (chk_check_dbcs(*strptr, cp_index) == DBCS) 
	 strptr += 2;
      else {
         *strptr = chk_casemap[cp_index][*strptr];
         strptr++;
      }

   return(string);
}
