/*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          = EDDJINIT.C                                     */
/*                                                                    */
/*   Description     = PM Display Driver DBCS handling routine        */
/*                     Subfunctions for initializing DBCS handler     */
/*                                                                    */
/*   Function        =                                                */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/*   CHANGE HISTORY:                                                  */
/*                                                                    */
/**********************************************************************/



#define ALL_AVIO_CELLSIZES             /* not apply AVIO font size    */
                                       /*   limit (I'm not sure if    */
                                       /*   this is necessary.  But   */
                                       /*   probably user should have */
                                       /*   maximum selection!)       */

#include <eddinclt.h>                  /* this include all files      */
#include <edddtypt.h>                  /* not included in eddinclt.h  */
#include <eddvcone.h>
#include <memman.h>

#include <eddjdef.h>
#include <eddjfm.h>                    /* font manager definition     */
#include <eddjfont.h>                  /* I/F to 16-bit routines      */
#include <eddjcp.h>
#include <eddjprof.h>

/*====================================================================*/
/*      constants                                                     */
/*====================================================================*/
#define GR_CHAR_HT_HI 24               /* hires GPI def char height   */
#define GR_CHAR_WD_HI 11               /*                    width    */
#define GR_CHAR_HT_LO 18               /* lores GPI def char height   */
#define GR_CHAR_WD_LO 8                /*                    width    */

#define MIN_VIOCELL_WD_HI 5            /*hires min width for AVIO cell*/
#define MAX_VIOCELL_WD_HI 13           /*      max                    */
#define MAX_VIOCELL_HT_HI 32           /*      max height             */

#define MIN_VIOCELL_WD_LO 5            /*lores min width for AVIO cell*/
#define MAX_VIOCELL_WD_LO 8            /*      max                    */
#define MAX_VIOCELL_HT_LO 20           /*      max height             */
                                       /* NOTE: VGA-DBCS calc this as */
                                       /* 13 (350/24), but improbable!*/

#define DECIPOINT       720            /* 1 decipoint = 1/720 inch    */

/*====================================================================*/
/*      external reference                                            */
/*====================================================================*/
extern PFOCAFONT pDefaultFont;         /* ptr to Gpi default font     */
extern USHORT DBCSResidentFonts;       /* #fonts managed by DBCS FM   */

extern DDTType DDT;                    /* device description table    */

extern BYTE DefaultSmallFont;          /* index of AVIO small font    */
extern BYTE DefaultNormalFont;         /* index of AVIO normal font   */
extern AvioFontTableType AvioBaseFont[];

/*====================================================================*/
/*      global variables                                              */
/*====================================================================*/
#define INVALID_FONT_SIZE       0xffff /* means not initialized       */
#define DEFAULT_FONT_NAME       "MINCHO"

USHORT usSysFontHeight = INVALID_FONT_SIZE;
USHORT usSysFontWidth  = INVALID_FONT_SIZE;
                                       /* if not set in OEMINIT, will */
                                       /*   be calculated later       */
CHAR szSysFontName[SIZE_FACENAME] = DEFAULT_FONT_NAME;
CHAR szVioFontName[SIZE_FACENAME] = DEFAULT_FONT_NAME;
                                       /* if not set in OEMINIT, this */
                                       /*   name will be used         */
#ifdef ALL_AVIO_CELLSIZES
USHORT usDefAVIOFontWidth = INVALID_FONT_SIZE;
USHORT usDefAVIOFontHeight = INVALID_FONT_SIZE;
#else /* ALL_AVIO_CELLSIZES */
USHORT usMaxAVIOFontWidth;
USHORT usMaxAVIOFontHeight;
#endif

USHORT usMinAVIOFontWidth;
USHORT swFlags;                        /* runtime option flags        */

/*====================================================================*/
/*      internal functions                                            */
/*====================================================================*/
VOID SetupDBCSFontSize( VOID );
VOID SortAVIOFonts( VOID );

/*===================== Exported Routine =============================*/
/*      eddj_GetRuntimeOptions                                        */
/*                                                                    */
/* Check runtime environment and decide if DBCS functions should be   */
/* enabled.  Global variable 'swFlags' is set according to the result.*/
/*                                                                    */
/* Entry       :        System default codepage                       */
/*                                                                    */
/* Returns     :        None                                          */
/*                                                                    */
/* Error Returns :      None                                          */
/*                                                                    */
/* Note        :                                                      */
/*                    - VGA-DBCS tries to create SBCS/DBCS vector map */
/*                      table to validate given CP.  We do not do it, */
/*                      since GreQueryCodePageVectors function is not */
/*                      available when this function is called.  (See */
/*                      EDDJCP.C)  Instead we will assume the CP is   */
/*                      usable if NLS parsing flag can be get.  (I.e. */
/*                      PMNLS.DLL knows about that CP.)               */
/*                                                                    */
/* Calls       :                                                      */
/*                                                                    */
/*====================================================================*/
VOID eddj_GetRuntimeOptions( ULONG cp )
{
  USHORT fsFlags;                      /* CP parsing rule flags       */

  swFlags = 0;                         /* no DBCS capability assumed  */

  eddj_TweakProfileString();           /* modify profile before we    */
                                       /*   load font manager (needed */
                                       /*   to use system font managed*/
                                       /*   by non-default font drvr) */
  if (!eddj_LoadFontManager()          /* if cannot load Font Manager */
   || !eddj_InitCPVectorsTable())      /* or cannot create CP table   */
  {
      return;                          /* DBCS not capable!           */
  }

  swFlags |= ENV_DBCS_CAPABLE;         /* QueryCPVectors need this    */
  if (!eddj_QueryCPVectors( cp, NULL, NULL, &fsFlags ))
  {                                    /* just query CP flags (no map)*/
      swFlags = 0;                     /* ==> def CP=DBCS, but cannot */
      return;                          /*   handle DBCS codepage      */
  }

  if (fsFlags & (NLSCA_DBCS | NLSCA_MBCS))
  {
      swFlags |= ENV_DBCS_DEFCP;       /* default CP is DBCS/MBCS     */
  }
}

/*===================== Exported Routine =============================*/
/*      eddj_SetupDBCSFontInformation                                 */
/*                                                                    */
/* This function does preparation for DBCS fonts, i.e.;               */
/*      - Set number of DBCS fonts into DBCSResidentFonts.            */
/*      - Realize all DBCS fonts for system use.                      */
/*      - Select default GPI font and set it to pDefaultFont.         */
/*              Also set its size in DDT.                             */
/*      - Set available AVIO fonts' info into AvioBaseFont[] and      */
/*              AVIOFonts.         Also select SMALL and NORMAL AVIO  */
/*              fonts and set them to DefaultSmallFont and            */
/*              DefaultNormalFont.                                    */
/*                                                                    */
/* Entry       :        None                                          */
/*                                                                    */
/* Returns     :        Returns TRUE (non-0)                          */
/*                                                                    */
/* Error Returns :      Returns FALSE (0) if error                    */
/*                                                                    */
/* Note        :                                                      */
/*            - If current environment is capable to handle DBCS,     */
/*              (i.e. ENV_DBCS_CAPABLE), DBCS fonts are prepared      */
/*              no matter system default CP is SBCS.                  */
/*                                                                    */
/* Calls       :                                                      */
/*                                                                    */
/*====================================================================*/
BOOL eddj_SetupDBCSFontInformation( VOID )
{
  PFMFONTINFO pDBCSFontInfo;           /* ptr to seg allocated by FM  */
  PFOCAFONT pGpiDefFont;               /* ptr to GPI default font     */

  ULONG  index;
  FATTRS fattrs;                       /* font attribute struct       */

  PFOCAFONT pCurFont;
  PFOCAMETRICS pCurMet;
  PFONTDEFINITIONHEADER pCurDef;


  if (!CHECKENV(ENV_DBCS_CAPABLE))     /* if cannot use DBCS          */
  {
      DBCSResidentFonts = 0;           /* AVIOFonts was already set   */
                                       /*   in SetupAVIOInformation() */
      return TRUE;                     /* do nothing, return normally */
  }

  /*------------------------------------------------------------------*/
  /* Get list of fonts managed by DBCS font mgr                       */
  /*------------------------------------------------------------------*/
  DBCSResidentFonts = eddj_GetFontList( &pDBCSFontInfo, FM_PUBLIC );
                                       /* allocated segment is ret'nd */
  if (DBCSResidentFonts == 0)          /* no DBCS font exist...       */
  {
      return FALSE;                    /* we CANNOT use DBCS now...   */
  }

  /*------------------------------------------------------------------*/
  /* realize all fonts for system use                                 */
  /*------------------------------------------------------------------*/
  fattrs.usRecordLength = sizeof fattrs;
                                       /* set record size field       */
  for (index = 0; index < DBCSResidentFonts; index ++)
  {
      fattrs.lMatch = pDBCSFontInfo[index].lMatch;
                                       /* set match number            */
      eddj_RealizeFont( &fattrs );     /* realize font and discard    */
                                       /*   returned pointer          */

                                       /* Note: Font Mgr does not     */
                                       /*  check facename if match #  */
                                       /*  is supplied.  (It should!) */
  }

  if (!CHECKENV(ENV_DBCS_DEFCP))       /* if system def CP is SBCS    */
  {                                    /* then we have nothing to do  */
//    eddj_Free16Segment( pDBCSFontInfo );
      FreeMemory( pDBCSFontInfo );
      return TRUE;
  }

  /*------------------------------------------------------------------*/
  /* Realize and Check each font                                      */
  /*------------------------------------------------------------------*/
  SetupDBCSFontSize();                 /* set size of target font     */

  fattrs.fsSelection = 0;              /* no italic/bold/us/ol/so     */
  fattrs.fsType = 0;                   /* no kerning/AA               */
  fattrs.fsFontUse = 0;                /* no special usage            */

  /*------------------------------------------------------------------*/
  /* setup DBCS font info                                             */
  /*------------------------------------------------------------------*/
  pGpiDefFont = NULL;                  /* no def font is found yet    */
  AVIOFonts = 0;                       /* no AVIO font is found yet   */

  for (index = 0; index < DBCSResidentFonts; index ++)
  {
      pCurFont = pDBCSFontInfo[index].pFont;
                                       /* need to convert to flat ptr!*/
      pCurMet = &(pCurFont->fmMetrics);/* get ptr to metrics,         */
      pCurDef = &(pCurFont->fdDefinitions);
                                       /* and also get ptr to font def*/
      /*--------------------------------------------------------------*/
      /* Check common requirements                                    */
      /*        - Supports UGL codepage                               */
      /*        - Not outline font                                    */
      /*--------------------------------------------------------------*/
      if ((pCurMet->usCodePage != CP_UGL_FONT)
       || (pCurMet->fsDefn & FM_DEFN_OUTLINE))
      {
          continue;                    /* so jump to check next font  */
      }

      /*--------------------------------------------------------------*/
      /* check if it can be GPI defualt                               */
      /*        - Matches to given width/height                       */
      /*        - "Don't Care" facename is given, or                  */
      /*          facename matches                                    */
      /*--------------------------------------------------------------*/
      if (pGpiDefFont == NULL)         /* if not yet found            */
      {
          if (((USHORT)pCurMet->yMaxBaselineExt == usSysFontHeight)
           && ((USHORT)pCurMet->xAveCharWidth == usSysFontWidth)
           && ((szSysFontName[0] == '\0')
            || !strcmp( pCurMet->szFacename, szSysFontName )))
          {                            /* same conditions to VGA-DBCS */
              pGpiDefFont = pCurFont;  /* Use this as GPI default...  */
          }
      }

      /*--------------------------------------------------------------*/
      /* check if it can be AVIO font                                 */
      /*        - Matches to given width/height                       */
      /*        - Fixed pitch                                         */
      /*        - "Don't Care" facename is given, or                  */
      /*          familyname matches (<== NOTE IT IS FAMILYNAME,      */
      /*                                  INSTEAD OF FACENAME!! )     */
      /*--------------------------------------------------------------*/
      if (AVIOFonts < NO_OF_AVIO_FONTS)
      {                                /* if not reached limit yet    */
#ifdef ALL_AVIO_CELLSIZES
          if ((pCurMet->fsTypeFlags & FM_TYPE_FIXED)
           && ((szVioFontName[0] == '\0')
            || !strcmp( pCurMet->szFamilyname, szVioFontName )))
#else /*ALL_AVIO_CELLSIZES*/
          if (((USHORT)pCurDef->xCellWidth >= usMinAVIOFontWidth)
           && ((USHORT)pCurDef->xCellWidth <= usMaxAVIOFontWidth)
           && ((USHORT)pCurDef->yCellHeight <= usMaxAVIOFontHeight)
           && (pCurMet->fsTypeFlags & FM_TYPE_FIXED)
           && ((szVioFontName[0] == '\0')
            || !strcmp( pCurMet->szFamilyname, szVioFontName )))
#endif /*ALL_AVIO_CELLSIZES*/
          {
              AvioBaseFont[AVIOFonts].CellWidth
                        = (BYTE)pCurDef->xCellWidth;
              AvioBaseFont[AVIOFonts].CellHeight
                        = (BYTE)pCurDef->yCellHeight;
              AvioBaseFont[AVIOFonts].pResourceData = pCurFont;
                                       /* fill necessary field only   */
              AVIOFonts ++;
          }
      }
  }

  /*------------------------------------------------------------------*/
  /* now time to check result... GPI first                            */
  /*------------------------------------------------------------------*/
  if (pGpiDefFont == NULL)             /* no font was found for GPI...*/
  {                                    /* (Must not happen!)          */
      pGpiDefFont = pDBCSFontInfo[0].pFont;
                                       /* use first font anyway       */
  }

  pDefaultFont = pGpiDefFont;          /* use this as GPI default...  */

  /*------------------------------------------------------------------*/
  /* update char box definition                                       */
  /*    H:V should be 1:1 (2.x driver) or 1:2 (1.3 compatibility)     */
  /*------------------------------------------------------------------*/
  DDT.graphics_char_height = pGpiDefFont->fmMetrics.yEmHeight;
//                           * pGpiDefFont->fmMetrics.yDeviceRes
//                           / DECIPOINT;
#ifdef TMP                                                  
//********************************************************************
// Changed to get graphics_char_width from EmHeight to EmInc to fix
// JD20/JSxxxxx. I think the old logic was once raised as JP20 DCR
// but seems to be revised... We must obey to VGA/ATLAS logic...
//*********************************************************************
  DDT.graphics_char_width  = pGpiDefFont->fmMetrics.xEmInc;
#else                                                       
  DDT.graphics_char_width  = pGpiDefFont->fmMetrics.yEmHeight;
//                           * pGpiDefFont->fmMetrics.xDeviceRes
//                           / DECIPOINT;
  if (ulDrvCompat == DRVCOMPAT_1)      /* if 1.xx compatibility req'd */
  {
      DDT.graphics_char_width /= 2;    /* V:H should be 2:1           */
  }
#endif 

  /*------------------------------------------------------------------*/
  /* then check for AVIO...                                           */
  /*------------------------------------------------------------------*/
  if (AVIOFonts == 0)                  /* if no AVIO font was found   */
  {
//    eddj_Free16Segment(pDBCSFontInfo);
      FreeMemory( pDBCSFontInfo );
      return FALSE;                    /* no way. we cannot use other.*/
  }

  SortAVIOFonts();                     /* sort avio fonts in a list   */

  /*------------------------------------------------------------------*/
  /* select AVIO default font                                         */
  /*            We will assume the list is already sorted by width,   */
  /*                    then by height                                */
  /*------------------------------------------------------------------*/
#ifdef ALL_AVIO_CELLSIZES
  for (index = 0; index < AVIOFonts; index ++)
  {
      if ((USHORT)AvioBaseFont[index].CellWidth >=
             usMinAVIOFontWidth)       /* pick up smallest with enough*/
      {                                /*    size                     */
          break;
      }
  }

  if (index >= AVIOFonts)              /* if could not find any       */
  {
      DefaultSmallFont = 0;            /* will use 1st and last       */
      DefaultNormalFont = (BYTE)(AVIOFonts-1);
  }
  else
  {
      DefaultSmallFont = index;
      for (index = AVIOFonts-1; index >= DefaultSmallFont; index --)
      {
          if (((USHORT)AvioBaseFont[index].CellWidth <=
                 usDefAVIOFontWidth) &&
              ((USHORT)AvioBaseFont[index].CellHeight <=
                 usDefAVIOFontHeight))
          {
              break;
          }
      }

      if (index == DefaultSmallFont)
      {                                /* want to be different        */
          DefaultNormalFont = (BYTE)(AVIOFonts-1);
      }
      else
      {
          DefaultNormalFont = index;
      }
  }
#else /* ALL_AVIO_CELLSIZES */
  DefaultNormalFont = (BYTE)(AVIOFonts-1);
  DefulatSmallFont = 0;
#endif

//eddj_Free16Segment( pDBCSFontInfo ); /* no more use for a while     */
  FreeMemory( pDBCSFontInfo );
  return TRUE;
}

/*===================== Private  Routine =============================*/
/*       SetupDBCSFontSize                                            */
/*                                                                    */
/* Set size of DBCS fonts based on screen resolution:                 */
/*      - GPI default font size --> usSysFontHeight/usSysFontWidth    */
/*      - AVIO font size range  --> usMinAVIOFontWidth  (*1)          */
/*                                                                    */
/*                                  usMaxAVIOFontWidth  (*2)          */
/*                                  usMaxAVIOFontHeight (*2)          */
/*                                                                    */
/*                                  usDefAVIOFontWidth  (*3)          */
/*                                  usDefAVIOFontHeight (*3)          */
/*              (*1) : Be set always                                  */
/*              (*2) : Be set when ALL_AVIO_CELLSIZES is not defined  */
/*              (*3) : Be set when ALL_... is not defined             */
/*                                                                    */
/* Entry       :        None                                          */
/*                                                                    */
/* Returns     :        None                                          */
/*                                                                    */
/* Error Returns :      None                                          */
/*                                                                    */
/* Note        :        None                                          */
/*                                                                    */
/* Calls       :                                                      */
/*                                                                    */
/*====================================================================*/
VOID SetupDBCSFontSize( VOID )
{
  if (DDT.fScreenFlags & DM_HI_RES)    /* this is set also when 1040  */
  {
      if (usSysFontHeight == INVALID_FONT_SIZE)
      {                                /* if size not given by user   */
          usSysFontHeight = GR_CHAR_HT_HI;
      }

      if (usSysFontWidth == INVALID_FONT_SIZE)
      {
          usSysFontWidth = GR_CHAR_WD_HI;
      }

      usMinAVIOFontWidth = MIN_VIOCELL_WD_HI;
#ifndef ALL_AVIO_CELLSIZES
      usMaxAVIOFontWidth = MAX_VIOCELL_WD_HI;
      usMaxAVIOFontHeight = MAX_VIOCELL_HT_HI;
                                       /* will be used later          */
#endif
  }
  else                                 /* when in low res mode        */
  {
      if (usSysFontHeight == INVALID_FONT_SIZE)
      {                                /* if size not given by user   */
          usSysFontHeight = GR_CHAR_HT_LO;
      }

      if (usSysFontWidth == INVALID_FONT_SIZE)
      {
          usSysFontWidth = GR_CHAR_WD_LO;
      }

      usMinAVIOFontWidth = MIN_VIOCELL_WD_LO;
#ifndef ALL_AVIO_CELLSIZES
      usMaxAVIOFontWidth = MAX_VIOCELL_WD_LO;
      usMaxAVIOFontHeight = MAX_VIOCELL_HT_LO;
#endif
  }

#ifdef ALL_AVIO_CELLSIZES
  if (usDefAVIOFontWidth == INVALID_FONT_SIZE)
  {
      usDefAVIOFontWidth = usSysFontWidth;
      usDefAVIOFontHeight = usSysFontHeight;
                                       /* if we do not use size limit */
                                       /*  for AVIO fonts, and are not*/
                                       /*  given default cell size,   */
                                       /*  this is the best choice for*/
                                       /*  default AVIO font...       */
  }
#endif

}

/*===================== Private  Routine =============================*/
/*       SortAVIOFonts                                                */
/*                                                                    */
/* Sort AVIO fonts listed in AvioBaseFont, by cell width, then height */
/*                                                                    */
/* Entry       :        None                                          */
/*                                                                    */
/* Returns     :        None                                          */
/*                                                                    */
/* Error Returns :      None                                          */
/*                                                                    */
/* Note        :                                                      */
/*            - Since this routine is called only once when this      */
/*              driver is loaded, simplest algorhythm would be enough.*/
/*              Here we will use 'Search the minimum -- Put it top'   */
/*              method.  (I don't remember its name...)               */
/*            - ATLAS and VGA sort this list 'by Width in same height'*/
/*              but we do  'by height in same width', since it should */
/*              work too, and AVIO font selection logic assumes it.   */
/*                                                                    */
/* Calls       :        None                                          */
/*                                                                    */
/*====================================================================*/
VOID SortAVIOFonts( VOID )
{
  AvioFontTableType *pOuter, *pInner,
                    *pCentinel, *pPriority,
                    TempFont;

  pOuter = AvioBaseFont;               /* prepare for sorting         */
  pCentinel = pOuter + AVIOFonts;      /* entry next to the last      */

  while ((pInner = pOuter+1) != pCentinel)
  {
      pPriority = pOuter;              /* assume it has top priority  */

      do
      {
          if ((pPriority->CellWidth > pInner->CellWidth)
                                       /* if it has smaller width, or */
           || ((pPriority->CellWidth == pInner->CellWidth)
            && (pPriority->CellHeight > pInner->CellHeight)))
                                       /* same wd and smaller height  */
          {                            /*   then it has priority      */
              pPriority = pInner;
          }

          pInner ++;                   /* advance to next entry       */
      }
      while (pInner != pCentinel);     /* until the end of font list  */

      if (pPriority != pOuter)         /* if higher priority found    */
      {
          TempFont = *pOuter;          /* swap them                   */
          *pOuter = *pPriority;
          *pPriority = TempFont;
      }

      pOuter ++;
  }
}

