/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* 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.                                */
/*                                                                           */
/*****************************************************************************/
/*****************************************************************************
 *
 * SOURCE FILE NAME = VdhGetCP.C
 *
 * DESCRIPTIVE NAME = Get CodePage Fonts from the Font File 
 *
 *
 * VERSION      V2.0
 *
 * DATE         
 *
 * DESCRIPTION 
 *
 * FUNCTIONS    BVSDINIT
 *
 * NOTES        NONE
 *
 * STRUCTURES   NONE
 *
 * EXTERNAL REFERENCES  CDIB                                                
 *
 * EXTERNAL FUNCTIONS   DOSOPEN, DOSREAD, DOSCHGFILEPTR, DOSCLOSE,
 *                      DOSGETSHRSEG, DOSFREESEG, DOSALLOCSEG, DOSREALLOCSEG          
 *
*/


/*****************************************************************************
 *                                                                          
 * SUBROUTINE NAME:  GetPreparedCodePages                                   
 *                                                                          
 * DESCRIPTIVE NAME:   Get the Prepared CodePages for the VDH               
 *                                                                          
 * FUNCTION:   Copies all prepared CodePage fonts to a getable seg.         
 *                                                                          
 * NOTES:  Executes on Level 3                                              
 *                                                                          
 * ENTRY POINT:  GetCodePage                                                
 *   LINKAGE:  Call GetCodePage                                             
 *                                                                          
 * INPUT:                                                                   
 *                                                                          
 * EXIT-NORMAL:  AX = 0                                                     
 *                                                                          
 * EXIT-ERROR:  AX = DOSxxx return code                                     
 *                                                                          
 * EFFECTS:  None                                                           
 *                                                                          
 * INTERNAL REFERENCES: None                                                
 *                                                                          
 * EXTERNAL REFERENCES:  CDIB                                               
 *   ROUTINES: DOSOPEN, DOSREAD, DOSCHGFILEPTR, DOSCLOSE,                   
 *             DOSGETSHRSEG, DOSFREESEG, DOSALLOCSEG, DOSREALLOCSEG         
 ****************************************************************************/

#define  INCL_BASE                     /* ALL of OS/2 Base                  */
#define  INCL_OS2STD                   /* Needed for NULL definition in     */
                                       /* OS2STD.H                          */
#include <os2.h>
#include <cdib.h>                      /* CDIB defines                      */
#include "vdhctl.h"                    /* Conditional compilation control   */
#include "vdh.h"                       /* Type definitions                  */

/*
**  Externally defined global variables
*/

extern USHORT ROMCP_NUM;               /* number of fonts in table          */
extern rcp_addr RomCP_tbl;             /* table for CP and ROM font info    */
extern cp_addr CodePage;               /* buffer for codepage fonts         */
extern UCHAR CodePage_Support;         /* flag for codepage support         */

/***************************************************************************
 *
 * FUNCTION NAME = GetCodePage
 *
 * DESCRIPTION   = 
 *
 * INPUT         =  NONE
 * OUTPUT        =  NONE
 *
 * RETURN-NORMAL =  NONE
 * RETURN-ERROR  =  NONE
 *
 **************************************************************************/

void PASCAL near GetCodePage()

{

  union faraddr
  {
    struct part p;
    struct CDIB *CDIBptr;
    struct CDIB_codepage_section *cp_ptr;
    struct CDIB_device_section *screen_ptr;
    struct CDIB_cp_id_section *cp_id_ptr;
    PSZ str_ptr;
  } 

  Addr,fontfn;

  union faraddr2
  {
    struct part p;
    FONTHDR *font_ptr;
    FONTFILEHDR *ff_ptr;
  } 

  hdr_info;

  union faraddr3
  {
    struct part p;
    ULONG *ofs_ptr;
  } 

  next_font;

  USHORT rc,CP_cnt,font_num,i,CP_id,j,base_needed,rows,cols;
  HFILE font_handle;
  SEL selector;
  ULONG distance,RomCP_tbl_len,scratch;
  ROMCP_TABLE *rtbl_ptr,*btbl_ptr;

  /*
  ** get access to the CDIB segment              
  */

  rc = DosGetShrSeg("\\SHAREMEM\\DOS\\CDIB", 
                    (PSEL)&Addr.p.Selector);
 
  if (!rc)
  {
    Addr.p.Offset = 0;                 /* setup ptr to codepage section     */

    /*
    ** get ptr to screen device section                                   
    */

    fontfn.p.Selector = Addr.p.Selector;
    fontfn.p.Offset = (USHORT)Addr.CDIBptr->CDIB_screen_ptr;

    /*
    ** get ptr to codepage section and get number of codepages            
    */

    Addr.p.Offset = (USHORT)Addr.CDIBptr->CDIB_codepage_ptr;
    CP_cnt = Addr.cp_ptr->CDIB_cp_number_codepages;

    /*
    ** if there are prepared codepages AND a ptr to the screen device
    ** section AND a ptr to the font filename (does assign at same time)
    */

    if (CP_cnt && fontfn.p.Offset && (fontfn.p.Offset = (USHORT)
       fontfn.screen_ptr->CDIB_dev_filename_ptr))
    {
      font_handle = 0;
      hdr_info.p.Selector = 0;
      hdr_info.p.Offset = 0;

      /*
      ** open font file, allocate room for font info. and read
      ** font file hdr
      */

      if (!(rc = DosOpen(fontfn.str_ptr, &font_handle, 
           (PUSHORT)&scratch,
           (ULONG)0, 0, 1, 0x20, (ULONG)0)) && 
           !(rc = DosAllocSeg(sizeof(FONTHDR), 
           (PSEL)&(hdr_info.p.Selector), 0)) && 
           !(rc = DosChgFilePtr (font_handle, (ULONG)0, 0, &scratch)) &&
           !(rc = DosRead(font_handle, (PVOID)hdr_info.ff_ptr, 
           sizeof(FONTFILEHDR), (PUSHORT)&scratch)))
      {
        font_num = hdr_info.ff_ptr->ffh_numfonts;/* # of fonts in file      */
        next_font.p.Offset = 0;
        next_font.p.Selector = 0;

        /*
        ** get offset to table of file offsets to fonts and read it
        */

        distance = (ULONG)(hdr_info.ff_ptr->ffh_ptroffset);
 
        if (!(rc = DosAllocSeg(font_num *4, (PSEL)&(next_font.p.Selector), 0))
           && !(rc = DosChgFilePtr(font_handle, distance, 0, &scratch)) && 
           !(rc = DosRead(font_handle, (PVOID)next_font.ofs_ptr, font_num * 4,
           (PUSHORT)&scratch)))
        {
          RomCP_tbl_len = 1;           /* initialize table length       @C15*/

          /*
          ** get ptr to the first prepared codepage section              
          */

          Addr.p.Offset += 2*sizeof(unsigned);
 
          for (i = 0; i < CP_cnt; i++) /* loop thru all CPs                 */
          {
            CP_id = Addr.cp_id_ptr->CDIB_cp_id;/* get CP id                 */
 
            for (j = 0; j < font_num; j++)/* loop thru fonts                */
            {

              /*
              ** read in font header                                     
              */

              if (!(rc = DosChgFilePtr(font_handle, 
                 *(next_font.ofs_ptr), 0, &scratch)) && 
                 !(rc = DosRead(font_handle, 
                 (PVOID) hdr_info.font_ptr, sizeof(FONTHDR), 
                 (PUSHORT)&scratch)))
              {
                /*
                ** if codepage we're looking for                         
                */

                if (CP_id == hdr_info.font_ptr->fh_cpid)
                {

                  /*
                  ** if table ptr already exists then reallocate for
                  ** next font
                  */
 
                  if (RomCP_tbl.ptr)
                  {
                    rc = DosReallocSeg(sizeof(ROMCP_TABLE)*++ROMCP_NUM, 
                                       (SEL)RomCP_tbl.p.Selector);

                    rc = DosReallocSeg((USHORT)(RomCP_tbl_len +
                                       hdr_info.font_ptr->fh_datalen),
                                       (SEL)CodePage.p.Selector);
                  } 


                  else
                  {

                    /*
                    ** need to allocate table and buffer with fonts for
                    ** the first time
                    */

                    RomCP_tbl.p.Offset = 0;/* table                         */
                    RomCP_tbl.p.Selector = 0;

                    rc = DosAllocSeg(sizeof(ROMCP_TABLE), 
                                     (PSEL)&(RomCP_tbl.p.Selector), 
                                     0x02);

                    CodePage.p.Offset = 0;/* font buffer                    */
                    CodePage.p.Selector = 0;

                    rc = DosAllocSeg(hdr_info.font_ptr->fh_datalen+1, /*@C15*/
                                     (PSEL)&(CodePage.p.Selector), 
                                     0x02);

                    base_needed = 0;
                    ++ROMCP_NUM;
                  } 
 
                  if (!rc)             /* fill in table info                */
                  {
                    RomCP_tbl_len += hdr_info.font_ptr->fh_datalen + 1;
                                                             /* @C15*/
                                                                        
                    RomCP_tbl.ptr->CodePageID = CP_id;
                    RomCP_tbl.ptr->BaseFontPTR = NULL;
                    RomCP_tbl.ptr->PelRows = hdr_info.font_ptr->fh_cellrows;
                    RomCP_tbl.ptr->PelColumns = hdr_info.font_ptr->fh_cellcols;
                    RomCP_tbl.ptr->FontPTR = CodePage.ptr;

                    /*
                    ** if override font, save base rows and cols    
                    */

                    if (RomCP_tbl.ptr->PelColumns == 9)
                    {
                      RomCP_tbl.ptr->BaseRows = hdr_info.font_ptr->fh_baserows;
                      RomCP_tbl.ptr->BaseColumns = 
                             hdr_info.font_ptr->fh_basecols;
                      base_needed++;
                    } 

                    RomCP_tbl.ptr++;

                    /*
                    ** get offset from current file position to font data
                    ** and read it into font buffer
                    */

                    distance = *next_font.ofs_ptr+
                       hdr_info.font_ptr->fh_dataoffset;
 
                    if (!(rc = DosChgFilePtr(font_handle, distance, 0, 
                          &scratch)))
                    {
                      rc = DosRead(font_handle, 
                                   (PVOID)CodePage.ptr, 
                                   (USHORT)hdr_info.font_ptr->fh_datalen, 
                                   (PUSHORT)&scratch);

                      CodePage.p.Offset += hdr_info.font_ptr->fh_datalen;
                      *CodePage.ptr = 0;/*                              @C15*/
                      CodePage.ptr++;   /*                              @C15*/
                    } 
                  } 
                } 
              } 
 
              if (rc)                  /* if error, set cntrs to exit loop  */
              {                        /* and free table and buffer segs    */
                i = CP_cnt;
                j = font_num;

                ROMCP_NUM = 0;
 
                if (RomCP_tbl.p.Selector)
                {
                  DosFreeSeg(RomCP_tbl.p.Selector);
 
                  if (CodePage.p.Selector)
                    DosFreeSeg(CodePage.p.Selector);
                } 
              } 
 
              else
              {
                next_font.ofs_ptr++;   /* go to offset for next font        */
                hdr_info.p.Offset = 0; /* reset ptr                         */
              } 
            } 

            next_font.p.Offset = 0;    /* back to beg of fonts              */
            Addr.cp_id_ptr++;          /* go to next cp_id_section          */
          } 

          /*
          ** if codepages read in w/o error, then setup pointers to
          ** base font for override fonts
          */

          if (!rc)
          {
 
            if (ROMCP_NUM)             /* have CP fonts in table            */
            {
              CodePage_Support = TRUE;
              RomCP_tbl.p.Offset = 0;  /* reset ptrs to beginning           */
              CodePage.p.Offset = 0;

              /*
              ** search thru table for override fonts and if so, search
              ** thru table again to find the matching base font
              */

              for (rtbl_ptr = RomCP_tbl.ptr; base_needed; rtbl_ptr++)
              {
 
                if (rtbl_ptr->PelColumns == 9)
                {
                  CP_id = rtbl_ptr->CodePageID;
                  cols = rtbl_ptr->BaseColumns;
                  rows = rtbl_ptr->BaseRows;
                  btbl_ptr = RomCP_tbl.ptr;
 
                  for (j = 0; j < ROMCP_NUM; j++)
                  {
 
                    if ((btbl_ptr->CodePageID == CP_id) && 
                       (btbl_ptr->PelColumns == cols) && 
                       (btbl_ptr->PelRows == rows))
                    {
                      rtbl_ptr->BaseFontPTR = btbl_ptr->FontPTR;
                      j = ROMCP_NUM;
                      base_needed--;
                    } 
 
                    else
                      btbl_ptr++;
                  } 

                  /*
                  ** if no base found, can't use font so 0 out   
                  */

                  if (!rtbl_ptr->BaseFontPTR)
                  {
                    rtbl_ptr->PelColumns = 0;
                    rtbl_ptr->PelRows = 0;
                  } 
                } 
              } 
            } 
 
            else                       /* no codepages return error         */
              rc = ERROR_VIO_BAD_CP;
          }                            /* codepages read in ok              */
        }                              /* if font offsets read              */
      }                                /* if no errors from Dos calls       */
 
      if (font_handle)                 /* free handles and allocated        */
                                       /* selectors                         */
      {
        DosClose(font_handle);
 
        if (hdr_info.p.Selector)
        {
          DosFreeSeg(hdr_info.p.Selector);
 
          if (next_font.p.Selector)
            DosFreeSeg(next_font.p.Selector);
        } 
      } 
    }                                  /* if CP_cnt                         */
  }                                    /* if !rc from DosGetShrSeg          */
} 

