/*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	      : EDDJPROF.C				      */
/*								      */
/*   Description      : PM Display Driver DBCS handling routine       */
/*			PROFILE handling functions for DBCS	      */
/*								      */
/*   Created	      : 03/31/92				      */
/*   Author	      : Yohji Nakamura (JL04328 at YMTVM6)	      */
/*								      */
/*   Notes	      : 					      */
/*								      */
/*			OCO Source Materials			      */
/*			XXXX-XXX				      */
/**********************************************************************/
/**********************************************************************/
/* DBCS Change History: 					      */
/*								      */
/* Stamp Date	Origin	       Description			      */
/* ---- ------ ------------ --------------------------------------    */
/* @D01 930610 Y.Nakamura   Change for Daiichi Seimei Project:	      */
/*			      Check COMPATIBLEPALETTE keyword in      */
/*			      CONFIG.SYS.  If it is ON, use ATLAS     */
/*			      compatible palette (i.e. stop palette   */
/*			      fudging for seamless support.  See      */
/*			      FUDGEPAL.C)			      */
/*								      */
/**********************************************************************/
#define INCL_WINSHELLDATA	       /* for Prfxx function defs     */
#define INCL_DEV		       /* for CAPS_ definition	      */
#define INCL_DOSMISC		       /* for DosScanEnv def.	      */
#define INCL_DOSERRORS

#include <eddinclt.h>		       /* this include all files      */
#include <eddjdef.h>		       /*			      */
#include <eddjprof.h>		       /*			      */

/*====================================================================*/
/* external variables						      */
/*====================================================================*/
extern ULONG QueryCapsTable[];	       /*			      */

/*====================================================================*/
/* global variables						      */
/*====================================================================*/
/*--------------------------------------------------------------------*/
/* driver compatibility options 				      */
/*--------------------------------------------------------------------*/
ULONG ulDrvCompat;		       /* overall compatibility       */
ULONG ulDrvFontRes;		       /* font resolution for hi-res  */
				       /*			      */
/*--------------------------------------------------------------------*/
/* application compatibility					      */
/*--------------------------------------------------------------------*/
BOOL flDrvSaveScreenBits;	       /* enable debugging PM app w/  */
				       /*   codeview (REALLY?)	      */
BOOL flDrvAdjustCellSize;	       /* adjust cell size to 1.x     */
				       /*   compatible		      */
BOOL flDrvDbcsProportional;	       /* enable true proportional    */
				       /*   DBCS font handling.       */
				       /* (i.e. all 2bytes codepoints */
				       /*  should have different size)*/
BOOL flDrvMode1040;		       /* if TRUE 1040x768 mode is    */
				       /*   available		      */
BOOL flDrvCompatPalette;	       /* if TRUE seamless support    *//*@D01*/
				       /*   (for palette) is disabled *//*@D01*/
/*====================================================================*/
/* private functions						      */
/*====================================================================*/
LONG StringToUshort( PSZ pszSource, PUSHORT pusResult );
BOOL CompareEnvSwitch( PSZ pszEnvVar, PSZ pszValue );
VOID GetAvioCellSize( VOID );

/*===================== Exported Routine =============================*/
/*	 eddj_GetCompatibilityOptions				      */
/*								      */
/* Get DBCS option values for compatibility et al. from .INI file     */
/*								      */
/* Entry       :	None					      */
/*								      */
/* Returns     :	None					      */
/*								      */
/* Error Returns :	None					      */
/*								      */
/* Note        :						      */
/*    - The flags below are set in this function:		      */
/*		usSysFontHeight :	DBCS system font height       */
/*		usSysFontWidth	:	DBCS system font width	      */
/*		szSysFontName	:	DBCS system font facename     */
/*		szVioFontName	:	DBCS VIO font facename	      */
/*								      */
/*		ulDrvCompat	:	Driver compatibility option   */
/*		ulDrvFontRes	:	Font Resolution compatibility */
/*								      */
/*	All compatibility options above can take:		      */
/*		DRVCOMPAT_DEFAULT	driver's own version          */
/*		DRVCOMPAT_1		OS/2 J1.x compatible	      */
/*		DRVCOMPAT_2		OS/2 J2.x compatible	      */
/*								      */
/*    - Also switches are set according to SET= in CONFIG.SYS:	      */
/*		flDrvSaveScreenBits				      */
/*		flDrvAdjustCellSize				      */
/*		flDrvDbcsProportional				      */
/*		flDrvMode1040					      */
/*		flCompatPalette 				      *//*@D01*/
/*								      */
/*								      */
/* Calls       :	None					      */
/*								      */
/*====================================================================*/
/*--------------------------------------------------------------------*/
/* Appname/Keyname for PROFILE					      */
/*--------------------------------------------------------------------*/
static CHAR szAppDisplay[] = "PMNLS_Display";
static CHAR szKeyCompat[] = "Compatibility";
static CHAR szKeyFontRes[] = "FontResolution";
static CHAR szKeySysFont[] = "SystemFont";
static CHAR szKeyVioFont[] = "VioFonts";
#define cDelimiter	','

/*--------------------------------------------------------------------*/
/* Keyname for CONFIG.SYS					      */
/*--------------------------------------------------------------------*/
static CHAR szKeySaveScreenBits[] = "SAVESCREENBITS";
static CHAR szKeyAdjustCellSize[] = "ADJUSTCELLSIZE";
static CHAR szOn[]		  = "ON";

static CHAR szKeyDbcsProportional[]  = "DBCSPROPORTIONAL";
static CHAR szKeyDefAvioCellSize[] = "AVIODEFAULTCELL";
static CHAR szKeyMode1040[]	  = "MODE1040";
static CHAR szKeyCompatPalette[]  = "COMPATIBLEPALETTE";                /*@D01*/

VOID eddj_GetCompatibilityOptions( VOID )
{				       /* top of func: GetCompatibilit*/
  LONG lResult; 		       /*			      */
  CHAR szTemp[SIZE_FACENAME * 2];      /* buffer for sysfont's        */
				       /*   facename,width,height     */
  PCHAR pch;			       /* temp ptr		      */
  USHORT usWidth, usHeight;	       /* temp width/height of sysfont*/
  ULONG ulLength;		       /*			      */
				       /*			      */
  /*==================================================================*/
  /* We do not check if this system is SBCS or MBCS, since this func  */
  /*	may be called before setting swFlags.  When running in SBCS   */
  /*	system, values set here should be just ignored later.	      */
  /*==================================================================*/
  /*------------------------------------------------------------------*/
  /* get compatibility options					      */
  /*------------------------------------------------------------------*/
  ulDrvCompat = QueryCapsTable[CAPS_DRIVER_VERSION] >> 8;
				       /* major version is default    */
				       /* Note this field contains    */
				       /*   constant value and is     */
				       /*   valid even before FillIn- */
				       /*   CapsTable is called.      */
  ulDrvCompat
    = (ULONG)PrfQueryProfileInt( HINI_USERPROFILE,
				 szAppDisplay,
				 szKeyCompat,
				 (LONG)ulDrvCompat );
				       /* query driver compatibility  */
  ulDrvFontRes = ulDrvCompat;	       /* default for each option     */
  ulDrvFontRes
    = (ULONG)PrfQueryProfileInt( HINI_USERPROFILE,
				 szAppDisplay,
				 szKeyFontRes,
				 (LONG)ulDrvFontRes );

  /*------------------------------------------------------------------*/
  /* get AVIO font spec 					      */
  /*------------------------------------------------------------------*/
  PrfQueryProfileString( HINI_USERPROFILE,
			 szAppDisplay,
			 szKeyVioFont,
			 NULL,
			 szVioFontName,
			 SIZE_FACENAME );
				       /* no default=>current value   */
				       /*   will be used as is	      */
  /*------------------------------------------------------------------*/
  /* get system font spec					      */
  /*------------------------------------------------------------------*/
  lResult =
    PrfQueryProfileString( HINI_USERPROFILE,
			   szAppDisplay,
			   szKeySysFont,
			   NULL,
			   szTemp,
			   sizeof(szTemp) );
  if (lResult <= 0 )		       /* if no  option string found  */
    {				       /*			      */
      return;			       /* nothing more to do	      */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* analyze system font spec string				      */
  /*------------------------------------------------------------------*/
  for (pch = szTemp; (*pch != cDelimiter) && (*pch != '\0'); pch++);
				       /* look for first delimiter    */
  if (*pch == '\0')                    /* if delimiter not found      */
    {				       /*			      */
      return;			       /* then not valid option string*/
    }				       /* end of if:		      */

  *pch++ = '\0';                       /* make facename a string      */
  ulLength = pch - szTemp;	       /* rememver length of string   */
				       /*  (including NULL char)      */

  pch += StringToUshort( pch, &usWidth );
				       /* ptr now points delimiter    */
  if (*pch++ != cDelimiter)	       /* if it is not delimter       */
    {				       /*			      */
      return;			       /* not valid option string     */
    }				       /* end of if:		      */

  StringToUshort( pch, &usHeight );    /* get height value	      */
  if (usWidth && usHeight)	       /* non-0 value is given to both*/
    {				       /*			      */
      memcpy( szSysFontName, szTemp, min(SIZE_FACENAME, ulLength) );
				       /* use memcpy to avoid overrun */
      usSysFontWidth = usWidth;        /* also set width/height       */
      usSysFontHeight = usHeight;      /*			      */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* check application compatibiilty options			      */
  /*------------------------------------------------------------------*/
  flDrvSaveScreenBits =
    CompareEnvSwitch( szKeySaveScreenBits, szOn );
				       /*			      */
  flDrvAdjustCellSize =
    CompareEnvSwitch( szKeyAdjustCellSize, szOn );
				       /*			      */
  flDrvDbcsProportional =
    CompareEnvSwitch( szKeyDbcsProportional, szOn );

  flDrvMode1040 =
    CompareEnvSwitch( szKeyMode1040, szOn );

  flDrvCompatPalette =							/*@D01*/
    CompareEnvSwitch( szKeyCompatPalette, szOn );			/*@D01*/

  /*------------------------------------------------------------------*/
  /* get default AVIO cell size 				      */
  /*------------------------------------------------------------------*/
  GetAvioCellSize();		       /*			      */
}				       /* end of func: GetCompatibilit*/

/*===================== Private  Routine =============================*/
/*	 StringToUshort 					      */
/*								      */
/* Convert string into USHORT value				      */
/*								      */
/* Entry       :	Ptr to string				      */
/*			Ptr to USHORT where result should be returned */
/*								      */
/* Returns     :	Number of characters processed		      */
/*								      */
/* Error Returns :	None					      */
/*								      */
/* Note        :	This is not performance-oriented, but rather  */
/*			safety-oriented routine.		      */
/*								      */
/* Calls       :	None					      */
/*								      */
/*====================================================================*/
LONG StringToUshort( PSZ pszSource, PUSHORT pusResult )
{				       /* top of func: StringToUshort */
  LONG lProcessed = 0;		       /* number of chars processed   */
  *pusResult = 0;		       /* resultant USHORT	      */
				       /*			      */
  while ((*pszSource >= '0') && (*pszSource <= '9'))
    {				       /*			      */
      *pusResult = *pusResult * 10 + (USHORT)(*pszSource - '0');
      pszSource ++;		       /*			      */
      lProcessed ++;		       /*			      */
    }				       /* end of while: 	      */

  return lProcessed;		       /*			      */
}				       /* end of func: StringToUshort */

/*===================== Private  Routine =============================*/
/*	 CompareEnvSwitch					      */
/*								      */
/* Compare environment variable to given string 		      */
/*								      */
/* Entry       :	Ptr to name of env variable		      */
/*			Ptr to a string to be compared		      */
/*								      */
/* Returns     :	TRUE if matches, FALSE if not match or	      */
/*			the env var does not exist		      */
/*								      */
/* Error Returns :	None					      */
/*								      */
/* Note        :	Given 2 string must be in upper case	      */
/*								      */
/* Calls       :	None					      */
/*								      */
/*====================================================================*/
BOOL CompareEnvSwitch( PSZ pszEnvVar, PSZ pszValue )
{				       /* top of func: CompareEnvSwitc*/
  PSZ pszEvar;			       /*			      */
				       /*			      */
  if (DosScanEnv(pszEnvVar, &pszEvar) != NO_ERROR)
    {				       /* if this is not in env var   */
      return FALSE;		       /* assume no match	      */
    }				       /* end of if:		      */

  while ((*pszEvar == ' ') || (*pszEvar == '\t'))
    {				       /*			      */
      pszEvar ++;		       /* skip blank chars	      */
    }				       /* end of while: 	      */

  while (*pszEvar && *pszValue)        /* while not end of string     */
    {				       /*			      */
      if (*pszValue !=
	    *pszEvar - ('a'<=*pszEvar && *pszEvar<='z') ? 'a'-'A' : 0)
	{			       /* compare ignoring case       */
	  return FALSE; 	       /* no match		      */
	}			       /* end of if:		      */

      pszValue ++;		       /*			      */
      pszEvar ++;		       /*			      */
    }				       /* end of while: 	      */

  if (*pszEvar == *pszValue)	       /* if both string end here     */
    {				       /*			      */
      return TRUE;		       /* match 		      */
    }				       /* end of if:		      */
  else				       /* only 1 string ends,	      */
    {				       /*			      */
      return FALSE;		       /* no match		      */
    }				       /* end of else:		      */
}				       /* end of func: CompareEnvSwitc*/

/*===================== Private  Routine =============================*/
/*	 GetAvioCellSize					      */
/*								      */
/* Retrieve default AVIO cell size from CONFIG.SYS SET statement      */
/*								      */
/* Entry       :	None					      */
/*								      */
/* Returns     :	None					      */
/*			The following variables are set:	      */
/*			  usDefAvioFontWidth			      */
/*			  usDefAvioFontHeight			      */
/*								      */
/* Error Returns :	None					      */
/*								      */
/* Note        :	None					      */
/*								      */
/* Calls       :	None					      */
/*								      */
/*====================================================================*/
extern USHORT usDefAvioFontWidth, usDefAvioFontHeight;

VOID GetAvioCellSize( VOID )
{				       /* top of func: GetAvioCellSize*/
  PSZ pszEvar;			       /*			      */
  USHORT usNum1, usNum2;	       /*			      */
				       /*			      */
  if (DosScanEnv(szKeyDefAvioCellSize, &pszEvar) != NO_ERROR)
    {				       /* if this is not in env var   */
      return;			       /* do not change 	      */
    }				       /* end of if:		      */

  while ((*pszEvar == ' ') || (*pszEvar == '\t'))
    {				       /*			      */
      pszEvar ++;		       /* skip blank chars	      */
    }				       /* end of while: 	      */

  pszEvar += StringToUshort( pszEvar, &usNum1 );
				       /* get first number (width)    */
  if (usNum1 == 0)		       /* if cannot get valid number  */
    {				       /*			      */
      return;			       /*			      */
    }				       /* end of if:		      */

  StringToUshort( ++pszEvar, &usNum2 );
				       /* get second number (height)  */
  if (usNum2 == 0)		       /* if cannot get valid number  */
    {				       /*			      */
      return;			       /*			      */
    }				       /* end of if:		      */

  usDefAvioFontWidth = usNum1;	       /*			      */
  usDefAvioFontHeight = usNum2;        /*			      */
}				       /* end of func: GetAvioCellSize*/

/*===================== Exported Routine =============================*/
/*	 eddj_TweakProfileString				      */
/*								      */
/* Handles system profile for font driver management.		      */
/*								      */
/* Entry       :	None					      */
/*								      */
/* Returns     :	None					      */
/*								      */
/* Error Returns :	None					      */
/*								      */
/* Note        :						      */
/*	--- Following description has been extracted from OEMINIT.ASM */
/*	    for VGA DBCS driver ---				      */
/*									     */
/* This routine rewrites the profile strings related to system resident      */
/* font driver by means of reffering to messages which F.D.Obj.left in	     */
/* profile during the last system's running. Following description is        */
/* breaf explanation on how message does F.D.Obj.leave in profile and	     */
/* whet do they mean to display driver. 				     */
/*									     */
/* 1) How message left by F.D.Obj.					     */
/*									     */
/*   AppName : PMNLSFNT_TMP						     */
/*     KeyName : DIRECTION						     */
/*     Value   : [key name],[remove from what AppName],[add to what AppName] */
/*		     |---------+	      ~~~~~~~		    ~~~~~~~  */
/*     KeyName : [key name]    |					     */
/*     Value   : [its value]   +---- ( same name )			     */
/*									     */
/* 2) What they mean.							     */
/*									     */
/*   a) [key name] --> KeyName which has to be removed and to be added.      */
/*   b) [remove from what AppName] --> AppName from which Display Driver     */
/*				       must remove above [key name].	     */
/*   c) [add to what AppName] --> AppName to which Display Driver must	     */
/*				  add above [key name]. 		     */
/*   d) [its value] --> Value which corresponds to [key name].		     */
/*									     */
/* 3) Example								     */
/*									     */
/*   When following description (fig.1) is found in profile,this routine     */
/*   will work like fig.2.						     */
/*									     */
/*									     */
/*	   +-----[ fig.1 : Given message from F.D.Obj. ]-----+		     */
/*	   |						     |		     */
/*	   |   AppName : PMNLSFNT_TMP			     |		     */
/*	   |	  KeyName : DIRECTION			     |		     */
/*	   |	  Value   : PMNLSFD3,PMNLSFNT,PMNLSFNT_FD    |		     */
/*	   |	  KeyName : PMNLSFD3			     |		     */
/*	   |	  Value   : \OS2\DLL\PMNLSFD3.FDR	     |		     */
/*	   |						     |		     */
/*	   +-------------------------------------------------+		     */
/*									     */
/*				||					     */
/*				\/					     */
/*									     */
/*   +----[ fig.2 : Taken action by above direction ]-------------------+    */
/*   |									|    */
/*   |	a) STEP 1							|    */
/*   |									|    */
/*   |	    AppName : PMNLSFNT						|    */
/*   |	       KeyName : xxx... 					|    */
/*   |	       Value   : xxxx...					|    */
/*   |	       KeyName : PMNLSFD3	 | ------> ERASE this portion	|    */
/*   |	       Value   : xxxxxxxxxxx...  |		if exists.	|    */
/*   |									|    */
/*   |									|    */
/*   |	b) STEP 2							|    */
/*   |									|    */
/*   |	    AppName : PMNLSFNT_FD					|    */
/*   |	       KeyName : xxx... 					|    */
/*   |	       Value   : xxxx...					|    */
/*   |	       KeyName : PMNLSFD3		| <-- ADD these stuffs	|    */
/*   |	       Value   : \OS2\DLL\PMNLSFD3.FDR	|			|    */
/*   |									|    */
/*   +------------------------------------------------------------------+    */
/*									     */
/* 4) NOTE								     */
/*									     */
/*	 Font Driver Object doesn't create the keyname 'PMNLSFNT_TMP'        */
/*	 whenever there is not any direction to Display Driver. 	     */
/*									     */
/*								      */
/* Calls       :	None					      */
/*								      */
/*====================================================================*/
#define MAX_PROFILE 64		       /*			      */

/*--------------------------------------------------------------------*/
/* appname/keyname						      */
/*--------------------------------------------------------------------*/
static CHAR szAppTemp[]    = "PMNLSFNT_TMP";
static CHAR szKeyDirect[]  = "DIRECTION";

VOID eddj_TweakProfileString( VOID )
{				       /* top of func: eddj_TweakProfi*/
  CHAR szDirBuf[MAX_PROFILE];	       /* direction buffer	      */
  CHAR szDataBuf[MAX_PROFILE];	       /* add data buffer	      */
  PSZ pszKey, pszRmvApp, pszAddApp;    /* ptr to partial strings      */
				       /*			      */
  /*------------------------------------------------------------------*/
  /* check if we have anything to do				      */
  /*------------------------------------------------------------------*/
  if (!PrfQueryProfileString( HINI_USERPROFILE,
			      szAppTemp,
			      szKeyDirect,
			      NULL,
			      szDirBuf,
			      sizeof(szDirBuf) ))
    {				       /* if this entry is not found  */
      return;			       /* we have nothing to do now   */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* analyze given direction string				      */
  /*------------------------------------------------------------------*/
  pszKey = szDirBuf;		       /* NOTE: we assume no blank or */
				       /* tab is included in string,  */
				       /* as VGA DBCS also assumes it.*/
  for (pszRmvApp = pszKey;
       *pszRmvApp && *pszRmvApp != cDelimiter;
       pszRmvApp ++);		       /* search delimiter or EOS     */

  if (*pszRmvApp)		       /* if delimiter is found       */
    {				       /*			      */
      *pszRmvApp = '\0';               /* put EOS char here           */
      pszRmvApp ++;		       /* and Remove-App begins here  */
    }				       /* end of if:		      */

  for (pszAddApp = pszRmvApp;
       *pszAddApp && *pszAddApp != cDelimiter;
       pszAddApp ++);		       /* search another delim or EOS */
				       /* NOTE: if first delimiter was*/
				       /*   not found, initial ptr    */
				       /*   value points to EOS       */
  if (*pszAddApp)		       /* if delimiter was found      */
    {				       /*			      */
      *pszAddApp = '\0';               /* put EOS                     */
      pszAddApp ++;		       /*			      */
    }				       /* end of if:		      */

  /*------------------------------------------------------------------*/
  /* Delete from App						      */
  /*------------------------------------------------------------------*/
  PrfWriteProfileString( HINI_USERPROFILE,
			 pszRmvApp,
			 pszKey,
			 NULL );       /* Remove from this app. data  */
				       /* Do not check error since    */
				       /*   this entry may not exist  */
  /*------------------------------------------------------------------*/
  /* Add to App 						      */
  /*------------------------------------------------------------------*/
  if (!PrfQueryProfileString( HINI_USERPROFILE,
			      szAppTemp,
			      pszKey,
			      NULL,
			      szDataBuf,
			      sizeof(szDataBuf) ))
    {				       /* retrieve data to be added   */
      return;			       /* if cannot find, do nothing  */
    }				       /* end of if:		      */

  PrfWriteProfileString( HINI_USERPROFILE,
			 pszAddApp,
			 pszKey,
			 szDataBuf );  /* add new entry to this app.  */
				       /* we do not check error here  */
				       /* since we can do nothing if  */
				       /* error is found here	      */
}				       /* end of func: eddj_TweakProfi*/
