/*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          = EDDVSUBR                                       */
/*                                                                    */
/*   Description     = Display Device Driver AVIO subroutine          */
/*                     CheckFont                                      */
/*                                                                    */
/*   Function        = Ensures that the correct AVIO font is selected */
/*                                                                    */
/*   Reference       = Winthorn Functional Specification              */
/*                     Device Driver Interface Specification          */
/*                     Display Device Driver Design Specification     */
/*                                                                    */
/*                                                                    */
/**********************************************************************/
#define INCL_DDICOMFLAGS
#define INCL_DDIMISC
#define INCL_GRE_FONTS
#include <eddinclt.h>

#include <edddtypt.h>
#include <eddttypt.h>

#include <eddmcone.h>
#include <eddvcone.h>

#include <eddbextf.h>
#include <eddmextf.h>
#include <eddtextf.h>
#include <eddvextf.h>

#include <eddhcone.h>
#include <eddhtype.h>
#include <eddhmacr.h>

#include <cursor.h>

#include <eddesres.h>

extern AvioFontTableType        AvioBaseFont[NO_OF_AVIO_FONTS];
extern AvioDefaultFontTableType AvioDefaultFont[NO_OF_VIDEO_MODES];

extern PFONTCACHEINFO           pFontCacheInfo;
extern DDTType                  DDT;

extern ULONG                    FreeVRAM;
extern AVIOPB                   AIxfer;
extern USHORT                   usDefaultCodePage;

#ifdef BPP24
ULONG                           CouldntCache;
#endif

/**********************************************************************/
/* CheckFonts is a function called by the AVIO drawing routines.      */
/* It looks at the cell size in the VioPS and sets up the current     */
/* fonts accordingly.                                                 */
/* If the VioPS cell size does not match any of                       */
/* the base AVIO fonts exactly then the  values in the VioPS are      */
/* altered to match the size of the nearest AVIO font that is smaller */
/* than the requested size.                                           */
/* If any of the logical fonts 1..3 have been defined and are the     */
/* same size as the current cell size, then they are set up,          */
/* otherwise they are set up to use the base font  (as used by LCID 0)*/
/*                                                                    */
/* NOTE big changes: no locking now. If base font has changed, must   */
/* free old from cache, and set in the new. Also for the 3 extended   */
/* attribute fonts...                                                 */
/* If only cp has changed , no need to change lcid fonts.             */
/**********************************************************************/

VOID DRIVERCALL CheckAVIOFonts(PVIOPS  VioPS)

{
    /******************************************************************/
    /* Local variables                                                */
    /******************************************************************/
    ULONG last_avio_font;
    ULONG        i;                 /* Loop variable                  */
    ULONG        NearestFont;       /* Stores best match font         */
    PFONTDETAILS pfdBaseFont;       /* pointer from DC data base font */
    PFONTDETAILS pfdLoadableFont;   /* pointer for loadable font      */
    PAVIOINFO    pAvioInfo;         /* local variable                 */


    /******************************************************************/
    /* Scan through the base AVIO fonts and select the one which is   */
    /* closest to, but not bigger than, the cell size given in the    */
    /* VioPS.                                                         */
    /* Initialise NearestFont to the default font for the current     */
    /* screen mode.  This value will be returned if the requested     */
    /* font is smaller than any that we support.  This is necessary   */
    /* because when the engine calls us with a font size of (0,0) it  */
    /* expects us to return the default font.                         */
    /******************************************************************/
    if ( DDT.ScreenWidth <= LO_RES_WIDTH )
    {
       NearestFont = AvioDefaultFont[LO_RES_AVIO_FONT_INDEX].NormalFont;
    }
    else if ( DDT.ScreenWidth <= RES_800_WIDTH )
    {
       NearestFont = AvioDefaultFont[RES_800_AVIO_FONT_INDEX].NormalFont;
    }
    else
    {
       NearestFont = AvioDefaultFont[HI_RES_AVIO_FONT_INDEX].NormalFont;
    }

    if ( DDT.ScreenWidth < HI_RES_WIDTH )
    {
      i = 0;
      last_avio_font = MAX_AVIO_FONTS_LOADED;
    }
    else
    {
      i = NO_OF_AVIO_FONTS - MAX_AVIO_FONTS_LOADED;
      last_avio_font = MAX_AVIO_FONTS_LOADED + i;
    }
    for ( ;
         (i < last_avio_font) &&
           (AvioBaseFont[i].CellWidth <= (BYTE)VioPS->CellImageWidth);
         i++)
    {
        if (AvioBaseFont[i].CellHeight <= (BYTE)VioPS->CellImageHeight)
        {
            /**********************************************************/
            /* This font is a better match than any previous ones.    */
            /**********************************************************/
            NearestFont = i;
        }
    }

    /******************************************************************/
    /* The font to be used is now in NearestFont.                     */
    /* Store its dimensions in the VioPS.                             */
    /******************************************************************/
    VioPS->CellImageWidth = (USHORT)AvioBaseFont[NearestFont].CellWidth;
    VioPS->CellImageHeight = (USHORT)AvioBaseFont[NearestFont].CellHeight;

    /******************************************************************/
    /* Check if the cell height has changed. If so, we adjust the     */
    /* cursor start/end position to match the new cell size.          */
    /******************************************************************/
    if (VioPS->CellImageHeight != VioPS->CellHeightLatch)
    {
        VioPS->CellHeightLatch = VioPS->CellImageHeight;

        VioPS->TextCursorStartLine =
        VioPS->TextCursorEndLine   = VioPS->CellImageHeight - (USHORT)1;

        /**************************************************************/
        /* Make the cursor two pels high for fonts >8 pels high.      */
        /**************************************************************/
        if (VioPS->CellImageHeight > 8)
        {
            VioPS->TextCursorStartLine--;
        }
    }

    /******************************************************************/
    /* Ensure that the cursor width matches the font cell width.      */
    /******************************************************************/
    VioPS->TextCursorWidth = VioPS->CellImageWidth;

    pfdBaseFont = &pdc->DCIAvioFonts[0];
    pAvioInfo = &pdc->DCIAvioInfo;

    if ((pAvioInfo->bCellWidth  != (BYTE)VioPS->CellImageWidth) ||
        (pAvioInfo->bCellHeight != (BYTE)VioPS->CellImageHeight) ||
        (VioPS->CodepageID != pfdBaseFont->usCodePage) )

    {
        /**************************************************************/
        /* The base font is changing, so free the old one and setup   */
        /* cache info for this new one. If the size has changed       */
        /* then also kill the 3 lcid fonts.                           */
        /**************************************************************/
        if (pfdBaseFont->pFocaFont)
        {
            /**********************************************************/
            /* There was a previous font - free from cache            */
            /**********************************************************/
            eddt_FreeCachedFont( pfdBaseFont->usFontID,
                                 pfdBaseFont->usCachedFontIndex );
        }

        /**************************************************************/
        /* Set new codepage, and get codepage vector from engine.     */
        /**************************************************************/
        pfdBaseFont->usCodePage = VioPS->CodepageID;
        if (pfdBaseFont->usCodePage)
        {
            pfdBaseFont->pCodePageVector =
                     (PUSHORT)GreQueryCodePageVector(pfdBaseFont->usCodePage);
        }
        else
        {
            /**********************************************************/
            /* CodePageID is null - use the codepage returned by      */
            /* DosGetCntryInfo.                                       */
            /**********************************************************/
            pfdBaseFont->pCodePageVector =
                     (PUSHORT)GreQueryCodePageVector(usDefaultCodePage);
        }

        /**************************************************************/
        /* Now get metrics and stuff from AvioBaseFont table.  Note   */
        /* new format for this.                                       */
        /* No copying - this is read-only...?                         */
        /**************************************************************/
        pfdBaseFont->pFocaFont = AvioBaseFont[NearestFont].pResourceData;

        /**************************************************************/
        /* Now setup cache table info.                                */
        /**************************************************************/
        eddt_LocateCachedFont(pfdBaseFont);
        pAvioInfo->pfciTable[0] =
                     &( pFontCacheInfo[pfdBaseFont->usCachedFontIndex] );

        /**************************************************************/
        /* If the base font size has changed then invalidate the      */
        /* loadable fonts.                                            */
        /**************************************************************/
        if ((VioPS->CellByteSize == 4) &&
            ( (pAvioInfo->bCellWidth != (BYTE)VioPS->CellImageWidth) ||
              (pAvioInfo->bCellHeight != (BYTE)VioPS->CellImageHeight) ) )
        {
            for ( i = 1; i <= CNT_LOADABLE_LCIDS; i++ )
            {
                pfdLoadableFont = &pdc->DCIAvioFonts[i];

                if (pfdLoadableFont->pFocaFont)
                {
                    eddt_FreeCachedFont(
                                pfdLoadableFont->usFontID,
                                pfdLoadableFont->usCachedFontIndex );
                }
                /******************************************************/
                /* we will use default font for these until a         */
                /* DeviceSetAvioFont2 sets them up.                   */
                /******************************************************/
                pfdLoadableFont->pFocaFont = FNULL;
                pAvioInfo->pfciTable[i]    = FNULL;
            }
        }

        /**************************************************************/
        /* The font size has changed so set up the correct entries in */
        /* our AVIOParms data.                                        */
        /**************************************************************/
        pAvioInfo->bCellWidth  = (BYTE)VioPS->CellImageWidth;
        pAvioInfo->bCellHeight = (BYTE)VioPS->CellImageHeight;

    }

    /******************************************************************/
    /* Calculate the grid offsets before returning.                   */
    /******************************************************************/
    CalculateGridOffsets(pAvioInfo, VioPS);
}

/**********************************************************************/
/* Calculate the grid offsets.                                        */
/**********************************************************************/
VOID DRIVERCALL CalculateGridOffsets(PAVIOINFO pAvioInfo,
                                     PVIOPS    VioPS)
{
    /******************************************************************/
    /* Calculate the grid x offset.                                   */
    /******************************************************************/
    pAvioInfo->sXoffset = pdc->DCIOrigin.X % VioPS->CellImageWidth;

    if (pAvioInfo->sXoffset > 0)
    {
        pAvioInfo->sXoffset -= VioPS->CellImageWidth;
    }

    /******************************************************************/
    /* Calculate the grid y offset.                                   */
    /******************************************************************/
    pAvioInfo->sYoffset = ((DDT.ScreenHeight - 1 -
                    (pdc->DCIOrigin.Y +
                    (signed CHAR)VioPS->PartialCellAdjust) + 1) %
                                           VioPS->CellImageHeight);
    if (pAvioInfo->sYoffset > 0)
    {
        pAvioInfo->sYoffset -= VioPS->CellImageHeight;
    }
}


/**********************************************************************/
/* Ensure that all the AVIO fonts are in the cache                    */
/**********************************************************************/
VOID DRIVERCALL CheckAVIOFontsCached(PVIOPS  VioPS)
{
    ULONG       i;
    BOOL        AllCached;

    if (VioPS->CellByteSize != 4)
    {
        /**************************************************************/
        /* Just the base font.                                        */
        /**************************************************************/
        if ( pdc->DCIAvioFonts[0].usFontID !=
             pFontCacheInfo[ pdc->DCIAvioFonts[0].usCachedFontIndex
                              ].usFontID )
        {
            /**********************************************************/
            /* Its been evicted - locate it.                          */
            /**********************************************************/
            eddt_LocateCachedFont( &(pdc->DCIAvioFonts[0]) );
            pdc->DCIAvioInfo.pfciTable[0] = &( pFontCacheInfo[
                         pdc->DCIAvioFonts[0].usCachedFontIndex ] );
        }
    }
    else
    {
        /**************************************************************/
        /* Extended attribute mode: may have four fonts.              */
        /* Keep caching and checking till all the fonts are cached.   */
        /**************************************************************/
        do
        {
            for (i = 0; i <= CNT_LOADABLE_LCIDS; i++ )
            {
                if ( pdc->DCIAvioFonts[i].pFocaFont &&
                     ( pdc->DCIAvioFonts[i].usFontID !=
                       pFontCacheInfo[ pdc->DCIAvioFonts[i].
                                        usCachedFontIndex].usFontID )  )
                {
                    eddt_LocateCachedFont( &(pdc->DCIAvioFonts[i]) );
                    pdc->DCIAvioInfo.pfciTable[i] = &(pFontCacheInfo[
                          pdc->DCIAvioFonts[i].usCachedFontIndex ] );
                }
            }
            AllCached = TRUE;
            for (i = 0; AllCached && (i <= CNT_LOADABLE_LCIDS); i++ )
            {
                if ( pdc->DCIAvioFonts[i].pFocaFont &&
                     ( pdc->DCIAvioFonts[i].usFontID !=
                       pFontCacheInfo[ pdc->DCIAvioFonts[i].
                                        usCachedFontIndex].usFontID )  )
                {
                    AllCached = FALSE;
                }
            }
        } while ( !AllCached );

    }
}


/**********************************************************************/
/* CGAText                                                            */
/* Draws a rectangle of avio text in CGA (2 bytes/cell) mode.         */
/* Ensures characters are all cached before calling asm code          */
/**********************************************************************/
VOID DRIVERCALL CGAText(VOID)
{
    PFONTDETAILS pfdBaseFont;  /* pointer to base avio font in DC */
    PAVIOINFO    pAvioInfo;    /* pointer to AVIOINFO in DC       */

    #ifdef  BPP24
    CouldntCache = FALSE;      /* Assume we'll cache the fonts    */
    #endif

    if (!AIxfer.bAcross && !AIxfer.bDown)
    {
        /**************************************************************/
        /* Zero size - nothing to draw.                               */
        /**************************************************************/
        return;
    }

    pAvioInfo   = &pdc->DCIAvioInfo;
    pfdBaseFont = &pdc->DCIAvioFonts[0];

    if ( !update_cache_charrect_2(pfdBaseFont, pAvioInfo) )
    {
        /**************************************************************/
        /* Cache has been trashed: locate font and then try again.    */
        /**************************************************************/
        eddt_LocateCachedFont(  pfdBaseFont );
        pAvioInfo->pfciTable[0] =
                     &( pFontCacheInfo[pfdBaseFont->usCachedFontIndex] );

        if ( !update_cache_charrect_2( pfdBaseFont, pAvioInfo) )
        {
            /**********************************************************/
            /* This should NEVER happen, as the cache is empty!       */
            /* Could log an error here.                               */
            /**********************************************************/
            /* Defect 75086.  In 640x480x16M, we don't have room for  */
            /* large fonts. So, we'll blt them directly (like we do   */
            /* for non-grey). EKF                                     */
            /**********************************************************/
            #ifdef  BPP24
            if ( DDT.BitCount == 24 )
               CouldntCache = TRUE;
            else
               return;
            #else
            return;
            #endif
        }
    }
    /******************************************************************/
    /* Call to 386 code to draw avio rectangle                        */
    /******************************************************************/
    CGATextBlock( pfdBaseFont, pAvioInfo );
}


/**********************************************************************/
/* MFIText                                                            */
/* Draws a rectangle of avio text in MFI (4 bytes/cell) mode.         */
/* Ensures characters are all cached before calling asm code          */
/**********************************************************************/
VOID DRIVERCALL MFIText(VOID)
{
    PFONTDETAILS pfdBaseFont;  /* pointer to base avio font in DC */
    PAVIOINFO    pAvioInfo;    /* pointer to AVIOINFO in DC       */
    ULONG        i;

    if (!AIxfer.bAcross && !AIxfer.bDown)
    {
        /**************************************************************/
        /* Zero size - nothing to draw.                               */
        /**************************************************************/
        return;
    }

    pAvioInfo   = &pdc->DCIAvioInfo;
    pfdBaseFont = &pdc->DCIAvioFonts[0];

    if ( !update_cache_charrect_4( pfdBaseFont, pAvioInfo) )
    {
        /**************************************************************/
        /* Cache has been trashed: try again                          */
        /**************************************************************/
        for (i = 0; i <= CNT_LOADABLE_LCIDS; i++ )
        {

           /***********************************************************/
           /* Defect 60806 - We may not have CNT_LOADABLE_LCIDS fonts */
           /* defined so we should check before calling off to        */
           /* eddt_LocateCachedFont.                                  */
           /***********************************************************/
           if ( pdc->DCIAvioFonts[i].pFocaFont )
               eddt_LocateCachedFont(  &(pdc->DCIAvioFonts[i]) );

            pAvioInfo->pfciTable[i] =
                   &( pFontCacheInfo[pfdBaseFont->usCachedFontIndex] );
        }

        if ( !update_cache_charrect_4( pfdBaseFont, pAvioInfo) )
        {
            /**********************************************************/
            /* This should NEVER happen, as the cache is empty!       */
            /* Could log an error here.                               */
            /**********************************************************/
            return;
        }
    }

    /******************************************************************/
    /* Call to 386 code to draw avio rectangle                        */
    /******************************************************************/
    MFITextBlock( pfdBaseFont, pAvioInfo );
}
