/*static char *SCCSID = "@(#)cmdbcs.c	6.2 91/02/22";*/
/* static char *SCCSID = "@(#)cmdbcs.c	6.2 91/02/22"; */

/********************************************************************/
/*	 IBM/Microsoft Confidential				    */
/*								    */
/*	 Copyright (c) IBM Corporation 1987, 1989		    */
/*	 Copyright (c) Microsoft Corporation 1987, 1989 	    */
/*								    */
/*	 All Rights Reserved					    */
/********************************************************************/


char DbcsFlags[128];
/************* START OF SPECIFICATIONS ********* IBM CONFIDENTIAL ****/
/*								     */
/* SOURCE FILE NAME: CMDBCS.C					     */
/*								     */
/* DESCRIPTIVE NAME: COMMON ROUTINES FOR DBCS COMMON ROUTINES	     */
/*								     */
/* FUNCTION:							     */
/*								     */
/*     This routines allocate memory for DBCS vector range and	     */
/*     case map data.  The DBCS support common routines below	     */
/*     call routines in this module to get necessary information     */
/*     to handle DBCS characters.				     */
/*								     */
/*	    common subroutine	     C library functions to be	     */
/*				     replaced.			     */
/*								     */
/*	      com_substr	     not available		     */
/*	      com_strchr	     strchr			     */
/*	      com_strrchr	     strrchr			     */
/*	      com_strupr	     strupr			     */
/*	      com_strlwr	     strlwr			     */
/*	      com_strcmpi	     strcmpi			     */
/*	      com_toupper	     touuper, _toupper		     */
/*	      com_tolower	     tolower, _tolower		     */
/*								     */
/* NOTES:							     */
/*								     */
/* ENTRY POINTS:						     */
/*								     */
/*     com_settble    - set up DBCS enviroment vector table and      */
/*			case map table. 			     */
/*     check_dbcs     - check if a character is DBCS or not.	     */
/*			case map table. 			     */
/*  com_chkdbcs       - Check if current position is DBCS or not     */
/* EXTERNAL REFERENCE:						     */
/*								     */
/*     DOSCASEMAP     - convert a string to uppercase		     */
/*     DOSGETDBCSEV   - get DBCS enviroment vector		     */
/*								     */
/* RELEASE:							     */
/*								     */
/*   VERSION	  DATE		 REASON 			     */
/*								     */
/*     1.00	5/13/1986      initial version			     */
/*     2.00	5/22/1986      initial system integration version    */
/*     2.01	5/27/1986      i/f change of DOSCASEMAP, DOSGETDBCSEV*/
/*     2.02	5/28/1986      chage back i/f of DOSCASEMAP,	     */
/*			       DOSGETDBCSEV  (far => long far)	     */
/*     2.03	6/16/1986      devide DBCS support src to 7 modules  */
/*     2.04	6/26/1986      fix large model bug in com_strupr.    */
/*				 add #include <malloc.h>	     */
/*     2.05	6/30/1986      replace "doscall.h" with "doscalls.h".*/
/*     3.00    11/06/1986      enlarge DBCS vector table size to 10  */
/*     3.01    12/05/1986      change i/f to DOSGETDBCSEV,	     */
/*			       and DOSCASEMAP.			     */
/*     3.02    12/09/1986      impliment debugging macro	     */
/*     3.03    12/12/1986      fix a bug in creating casemap_lo buf  */
/*     3.04    02/11/1987      eliminate warning for compile option  */
/*			       -W2 and -DLINT_ARGS		     */
/*     4.00    03/23/1988      add com_chkdbcs function (Cora Yang)  */
/*     5.00    03/28/1988      modify check_dbcs to improve	     */
/*			       performance (Cora Yang)		     */
/*								     */
/* B001 02/20/91 fgw  B718926: warning messages for C6 compiles      */
/*********************************************************************/
#include <doscall.h>				 /* define external		 */
#include <string.h>				 /* define external		 */
#include "cmdbcs.h"                              /* dbcs data                    */
#include "cmdebug.h"                             /* debug macro                  */
						 /*				 */

/*******************************/
/*  external variables	       */
/*******************************/
extern unsigned char casemap_lo[CASEMAP_SIZE];	 /* corresponding lower case code*/
extern unsigned char casemap_up[CASEMAP_SIZE];	 /* corresponding upper case code*/

/*******************************/
/*  define static variable     */
/*******************************/
    struct DbcsEnvVector {			 /* DBCS enviroment vector	 */
	unsigned char lo_limit; 		 /* lower limit 		 */
	unsigned char up_limit; 		 /* upper limit 		 */
	} dbcsvec[DBCSVEC_SIZE];

/******************** START OF SPECIFICATION *************************/
/*								     */
/* SUBROUTINE NAME:  COM_SETTBL 				     */
/*								     */
/* DESCRIPTIVE NAME:  SET UP CASE MAPPING TABLE AND DBCS ENVIROMENT  */
/*		      VECTOR TABLE				     */
/*								     */
/* FUNCTION:							     */
/*								     */
/*     Set up the case mapping table and DBCS enviroment table	     */
/*     by DOSCASEMAP and DOSGETDBCSEV respectively.		     */
/*     The content of these table is filled by the information	     */
/*     in current country code. 				     */
/*								     */
/* NOTES:							     */
/*								     */
/*     Once these table is set, it does not do the same process      */
/*     when invoked again for a reason of efficiency.		     */
/*								     */
/* ENTRY POINT:  com_settbl					     */
/*   LINKAGE  : 						     */
/*								     */
/* INPUT:   none						     */
/*								     */
/* EXIT-NORMAL: 						     */
/*   RETURN CODE SYMBOL:  OK					     */
/*								     */
/* EXIT-ERROR:							     */
/*   RETURN CODE SYMBOL:					     */
/*								     */
/*	  API function error code				     */
/*								     */
/* EFFECTS:							     */
/*								     */
/* INTERNAL REFERENCES: none					     */
/*   ROUTINES:							     */
/*								     */
/* EXTERNAL REFERENCES: 					     */
/*   ROUTINES:							     */
/*		  DOSGETDBCSEV	 - get DBCS enviroment vector	     */
/*		  DOSCASEMAP	 - case mapping 		     */
/*								     */
/******************* END OF SPECIFICATIONS ***************************/

  unsigned com_settbl()
    {
     int i, j;					 /* work variable		 */
     unsigned char *strptr;			 /*				 */
     static unsigned long countrycode = 0;	 /*				 */
     static int setup_flag = OFF;		 /* setup comp flag		 */
     static int rc;				 /* func return code		 */
						 /*				 */
  /*************************************/
  /*				       */
  /*   check initialization	       */
  /*				       */
  /*************************************/
    if (setup_flag == ON)			 /* table already set?		 */
      { 					 /*				 */
       return(OK);				 /*  yes-> normal return	 */
      } 					 /*				 */

  /*************************************/
  /*				       */
  /*   get DBCS environment vector     */
  /*				       */
  /*************************************/

    DCALL(DOSGETDBCSEV);/*debug*/
    if ((rc =					 /*  get DBCS enviroment vector  */
       DOSGETDBCSEV(				 /*				 */
       (unsigned)DBCSVEC_SIZE*2,		 /*				 */
       (struct countrycode far *)&countrycode,	 /*				 */
       (char far *)dbcsvec))			 /*				 */
			    != OK)		 /* if error,			 */
      { 					 /*				 */
       DRETCD;/*debug*/ 			 /*				 */
       setup_flag = ON; 			 /* set cond to not malloc mem	 */
       dbcsvec[0].lo_limit = 0; 		 /* prime for lo limit error	 */
       dbcsvec[0].up_limit = 0; 		 /* prime for up limit error	 */
       return(rc);				 /* return with error code	 */
      } 					 /*				 */
    DRETCD;/*debug*/				 /*				 */


  /**********************************************************************/
  /*									*/
  /*  setup DbcsFlags Table						*/
  /*									*/
  /* DbcsFlags[value] is set to 					*/
  /*	1 if value is a valid first byte of a double byte character	*/
  /*	0 if value is not a valid first byte of a double byte character */
  /*									*/
  /**********************************************************************/


    for (i = 0; i < DBCSVEC_SIZE; i++)	{
       if (!dbcsvec[i].lo_limit)
	   break;
       dbcsvec[i].up_limit &= 0x7f;
       for (j = (dbcsvec[i].lo_limit & 0x7f); j <= dbcsvec[i].up_limit; j++)
	   DbcsFlags[j] = 1;
    }



  /*************************************/
  /*				       */
  /*   set up casemap table	       */
  /*				       */
  /*************************************/

    for (i = 0; i < CASEMAP_SIZE; i++)		 /*  initialize case map table	 */
     {						 /*				 */
      casemap_lo[i] =				 /*				 */
      casemap_up[i] = (unsigned char)i; 	 /*				 */
     }						 /*				 */
    DCALL(DOSCASEMAP);/*debug*/ 		 /*				 */
    if ((rc =					 /*  set up upper case map table */
       DOSCASEMAP(				 /*				 */
       (unsigned)CASEMAP_SIZE,			 /*				 */
       (struct countrycode far *)&countrycode,	 /*				 */
       (char far *)casemap_up)) 		 /*				 */
				!= OK)		 /* if error			 */
      { 					 /*				 */
       DRETCD;/*debug*/ 			 /*				 */
       strupr(casemap_up);			 /*				 */
       return(rc);				 /* return with the error code	 */
      } 					 /*				 */
    DRETCD;/*debug*/				 /*				 */
    strptr = casemap_up;			 /* set strptr to casemap_up	 */

  /*************************************/
  /*				       */
  /* 'a' and … is casemaped to 'A'.    */
  /* So when 'A' is converted to       */
  /* lowercase it should be 'a'only.   */
  /*				       */
  /*************************************/

    for(i=0; i<0x80; i++, strptr++)		 /* create casemap_lw		 */
      if (i!=*strptr)				 /*				 */
	casemap_lo[*strptr]=(unsigned char)i;	 /*				 */
    setup_flag = ON;				 /* set setup_flag		 */
    return(OK); 				 /* normal return		 */
  }						 /*				 */

/******************** START OF SPECIFICATION *************************/
/*								     */
/* SUBROUTINE NAME:  CHECK_DBCS 				     */
/*								     */
/* DESCRIPTIVE NAME:  CHECK GIVEN CHARACTER DBCS OR NOT 	     */
/*								     */
/* FUNCTION:							     */
/*								     */
/* NOTES:							     */
/*								     */
/* ENTRY POINT:  check_dbcs					     */
/*   LINKAGE  : 						     */
/*								     */
/* INPUT:    char c   - character to be checked 		     */
/*								     */
/* EXIT:   integer						     */
/*								     */
/*	 value		meaning 				     */
/*								     */
/*	  0		sungle byte				     */
/*	  1		DBCS 1st byte				     */
/*								     */
/* EXIT-ERROR:							     */
/*	 none							     */
/*								     */
/* EFFECTS:							     */
/*								     */
/* INTERNAL REFERENCES: none					     */
/*   ROUTINES:							     */
/*								     */
/* EXTERNAL REFERENCES: note					     */
/*   ROUTINES:							     */
/*								     */
/******************* END OF SPECIFICATIONS ***************************/

  int check_dbcs(c)
  unsigned char c;
  {

	unsigned temp;

	temp = c;
	temp = temp & 0x00FF;

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

	return( DbcsFlags[ temp & 0x7F ] );

  }


/******************** START OF SPECIFICATION *************************/
/*								     */
/* SUBROUTINE NAME:  COM_CHKDBCS				     */
/*								     */
/* DESCRIPTIVE NAME: Check if current position is DBCS or not	     */
/*								     */
/* FUNCTION:  Check if current position is DBCS or not		     */
/*								     */
/* NOTES:							     */
/*								     */
/* ENTRY POINT:  check_dbcs					     */
/*   LINKAGE  : 						     */
/*								     */
/* INPUT:							     */
/*		  line --> pointer to the string		     */
/*		  pos  --> character position to be tested in a line */
/*								     */
/* EXIT:							     */
/*		  return value					     */
/*			 if SBCS --> SBCS			     */
/*			    DBCS(1) --> DBCS			     */
/*			    DBCS(2) --> DBCS_2			     */
/*								     */
/*	 value		meaning 				     */
/*								     */
/*	  0		sungle byte				     */
/*	  1		DBCS 1st byte				     */
/*	  2		DBCS 2nd byte				     */
/*								     */
/* EXIT-ERROR:							     */
/*	 none							     */
/*								     */
/* EFFECTS:							     */
/*								     */
/* INTERNAL REFERENCES: none					     */
/*   ROUTINES:							     */
/*								     */
/* EXTERNAL REFERENCES: none					     */
/*   ROUTINES:							     */
/*								     */
/******************* END OF SPECIFICATIONS ***************************/
int com_chkdbcs(line,pos)
unsigned char line[];
int	 pos;
{
	extern	 int check_dbcs(unsigned char); 	    /*;BN001;*/
	register int i;

	for (i=0 ; pos > i ; i++ ){
	  if (check_dbcs(line[i]) == DBCS ){
	    i++;
	  }
	} /* endfor */
	if (pos == i){
	  if (check_dbcs(line[pos]) == DBCS ){
	    return(DBCS);
	  } else {
	    return(SBCS);
	  } /* endif */
	} else {
	  return(DBCS_2);
	} /* endif */

}

