/*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 = VDHINFO.c
 *
 * DESCRIPTIVE NAME = Base video device handlers - Cursor/Variable info 
 *
 *
 * VERSION      V2.0
 *
 * DATE         
 *
 * DESCRIPTION  This source file contains VDH entry points for setting 
 *              and getting cursor information and setting and getting
 *              variable information.
 *
 *              These routines execute as ring 2 conforming
 *
 * FUNCTIONS    GetCursorInfo,   SetCursorInfo   
 *              GetVariableInfo, SetVariableInfo 
 *              GetDBCSDisplayInfo, GetLVBInfo   
 *
 * NOTES        NONE
 *
 * STRUCTURES   NONE
 *
 * EXTERNAL REFERENCES
 *
 *              SaveRegs, RestoreRegs
 *              AccessCursorPos, AccessCursorType
 *              AccessBlink, AccessOverscan, AccessUnderscore
 *              AccessVideoEnable, AccessDisplayMask          
 *
 * EXTERNAL FUNCTIONS
 *
 *              NONE
 *
*/

/*
**      Include files                                                      
*/

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

/*
**  Externally defined global variables                                    
*/

extern VIDEOMODE Modes[];              /* Supported modes                   */
extern MEMORYMAPS MemoryMaps[];        /* Memory map info for each mode     */
extern short HugeShift;                /* Huge shift value                  */
extern UCHAR READABLE;
extern USHORT VGA_PRESENT;             /* TRUE if VGA VDH has been          */
                                       /* installed                         */
extern USHORT(APIENTRY *ChainedCallVectorTable[MaxFn])();/*             @T24*/
extern USHORT OEMFlags;             /* OEM specific features @MS27 */

#if      FONT_SUPPORT                  /* @MS00 */


extern USHORT ROMCP_NUM;               /* number of fonts in table      @C10*/
extern rcp_addr RomCP_tbl;             /* table for CP and ROM font info    */
                                       /*                               @C10*/
#endif    

#if      !(VDH8514A)                   /* @MS00 */

/*****************************************************************************
 *                                                                          
 *  SUBROUTINE NAME: GetCursorInfo                                          
 *                                                                          
 *  DESCRIPTIVE NAME: Get cursor position and/or cursor type                
 *                                                                          
 *  FUNCTION: GetCursorInfo is called by BVS to return selected             
 *            information about either the cursor position or the           
 *            cursor type.  If the request specifies hardware and the       
 *            hardware is readable, the actual hardware setting will        
 *            be read and returned.  Otherwise the returned                 
 *            information will be taken from the environment buffer,        
 *            if it has been passed.                                        
 *                                                                          
 *  ENTRY POINT: GetCursorInfo                                              
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 265 )       
 *                                                                          
 *  INPUT: (Passed on stack)                                                
 *             FAR *Environment ( Environment buffer for the session )      
 *             FAR *ParmBlock                                               
 *                     USHORT Length = length of this packet                
 *                     USHORT Flags  = 0 - Environment buffer only          
 *                                     1 - Hardware also                    
 *                     USHORT Row                                           
 *                     USHORT Column                                        
 *                     USHORT TopScanLine                                   
 *                     USHORT BottomScanLine                                
 *                     USHORT Width                                         
 *                     USHORT Attribute                                     
 *             ULONG Function ( Call vector table entry = 265 )             
 *                                                                          
 *  EXIT-NORMAL: AX = 0                                                     
 *               Cursor information is returned.                            
 *                                                                          
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                                
 *                                                                          
 *  EFFECTS: If hardware specified and hardware is readable, the            
 *           environment buffer is updated, if passed.                      
 *                                                                          
 *  INTERNAL REFERENCES:                                                    
 *    ROUTINES: NONE                                                        
 *                                                                          
 *  EXTERNAL REFERENCES:                                                    
 *    ROUTINES: AccessCursorPos, AccessCursorType                           
 *
 ****************************************************************************/


USHORT EXPENTRY GetCursorInfo(Environment,ParmBlock,Function)

ENVIRONMENT far *Environment;
VDH_CURSOR far *ParmBlock;
ULONG Function;

{
  USHORT rc,ModeColumns,ColorMode,EnvBufferPassed;

  union
  {
    USHORT Position;

    struct
    {
      UCHAR Low;
      UCHAR High;
    } 
    Pos;
  } 
  Cursor;

  USHORT ReqFlags;                     /*                               @S11*/

  ReqFlags = ParmBlock->Flags;         /*                               @S11*/
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */
 
  if ((EnvBufferPassed) && (Function == FnGetCursorInfo) && /* Valid funct  */
     !(ReqFlags&~VALID_CURSOR_FLAG) &&                      /* valid flg@@S1*/
     (ParmBlock->Length >= MinSLen_Cursor_Pos))             /* min length   */
  {                                    

/*
**  Flags are valid - Get cursor type if enough room provided               
**                    Get cursor position if enough room provided           
*/

    rc = ERROR_VIO_MODE;               /* Preset invalid mode               */
 
    if (!(Environment->ModeData.fbType&GRAPHICS))
    {                                  /* Text mode only                    */
      rc = NO_ERROR;                   /* Initialize no error               */
 
 
/*
**  Get cursor position -                                                   
**   If requesting application is running in foreground,                    
**     - Return hardware value                                              
**   If requesting application is running in background,                    
**     - Return environment buffer value                                    
*/

      if (ReqFlags&CURSOR_POSITION)
      {                                /*                               @@S1*/
 
        if (ReqFlags&UPDATE_HARDWARE)
        {

#if      VDHVGA                           /* Read/write hardware            */
                                          /* @MS00                          */

          ModeColumns = HardwareColumns();/* Current # of columns (hw)      */
          ColorMode = HardwareColor();    /* color/mono mode ( hardware )   */

#else                                     /* Write-only hardware            */

          ModeColumns = Environment->ModeData.col;/* Current #cols -env buff*/
          ColorMode = Environment->ModeData.fbType&NOT_MONO;/* color/mono   */
                                          /* mode (env buffer)              */
#endif   

/*
**  Get cursor position directly from the hardware                          
*/

          AccessCursorPos(ModeColumns, ColorMode, GET, &ParmBlock->Row);
        } 
 
        else
        {

/*
**  Requesting application is running in the background -                  
**  Copy cursor position from env buffer to caller's parameter area         
*/

          Cursor.Pos.Low = Environment->Hardware.CRTCtlRegs.Regs.CursorLocLow;
          Cursor.Pos.High = 
                 Environment->Hardware.CRTCtlRegs.Regs.CursorLocHigh;

          ParmBlock->Row = Cursor.Position/Environment->ModeData.col;
          ParmBlock->Column = Cursor.Position-Environment->ModeData.col 
                 * ParmBlock->Row;
        } 
      }                                /*                               @@S1*/
 
      if (ParmBlock->Length >= MinSLen_Cursor_Type && ReqFlags&CURSOR_TYPE)
      {                                /*                               @@S1*/

/*
**  Get cursor type -                                                       
**   If requesting application is running in foreground,                    
**     - Return hardware value if hardware can be read                      
**     - Otherwise return environment buffer value                          
**      ( Do nothing if write-only hardware and no env buffer passed )      
**   If requesting application is running in background,                    
**     - Return environment buffer value                                    
*/

        if ((ReqFlags&UPDATE_HARDWARE) && READABLE)
        {                              /* i.e. VGA in FG                    */

/*
**  Get type position directly from the hardware                            
*/

#if      VDHVGA                       /* Read/write hardware               */
                 
          AccessCursorType(HardwareColor(), GET, &ParmBlock->TopScanLine);

/*
**  Copy cursor type from caller's parmeter area to the env buffer          
*/

          Environment->Hardware.CRTCtlRegs.Regs.CursorStart &= 0xC0;
          Environment->Hardware.CRTCtlRegs.Regs.CursorStart |= 
             ParmBlock->TopScanLine;

          Environment->Hardware.CRTCtlRegs.Regs.CursorEnd &= 0xE0;       
          Environment->Hardware.CRTCtlRegs.Regs.CursorStart |= 
             ParmBlock->BottomScanLine;

/*
**  Since -1 indicates hidden cursor and any other value means              
**  cursor is not hidden, return the exact value that the caller            
**  specified last to indicate not hidden                                   
*/

          if ((ParmBlock->Attribute != 0xFFFF) && 
             (Environment->CursorAttribute != 0xFFFF))
            ParmBlock->Attribute = Environment->CursorAttribute;
 
          else
            Environment->Hardware.CRTCtlRegs.Regs.CursorStart |= 0x20;
  #endif    
        } 
 
        else
        {

/*
**  Requesting application is running in the background OR                  
**  the hardware is write-only                                              
**  Copy cursor type from env buffer to the caller's parameter area         
*/

#if      !(VDHVGA)                 /* Get Top scan line if not VGA @B10,@MS00*/

          Environment->Hardware.CRTCtlRegs.Regs.CursorStart            /*@B10*/
          = (UCHAR)Environment->EGAShadowTopScanLine;         /*    @B10,@C24*/

#endif    
          ParmBlock->TopScanLine = 
             Environment->Hardware.CRTCtlRegs.Regs.CursorStart&0x1F;

          ParmBlock->BottomScanLine = 
             Environment->Hardware.CRTCtlRegs.Regs.CursorEnd&0x1F;

          ParmBlock->Width = 1;
          ParmBlock->Attribute = Environment->CursorAttribute;
        } 
      } 
    } 
  } 

  return (rc);
} 

/*****************************************************************************
 *                                                                             
 *  SUBROUTINE NAME: SetCursorInfo                                             
 *                                                                             
 *  DESCRIPTIVE NAME: Set cursor position and/or cursor type                   
 *                                                                             
 *  FUNCTION: SetCursorInfo is called by BVS to set selected                   
 *            information about either the cursor position or the              
 *            cursor type.  If the request specifies hardware, the             
 *            hardware and the environment buffer, if passed, will be          
 *            updated.  Otherwise just the environment buffer, if              
 *            passed, will be updated.                                         
 *                                                                             
 *  ENTRY POINT: SetCursorInfo                                                 
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 266 )          
 *                                                                             
 *  INPUT: (Passed on stack)                                                   
 *             FAR *Environment ( Environment buffer for the session )         
 *             FAR *ParmBlock                                                  
 *                     USHORT Length = length of this packet                   
 *                     USHORT Flags  = 0 - Environment buffer only             
 *                                     1 - Hardware also                       
 *                     USHORT Row                                              
 *                     USHORT Column                                           
 *                     USHORT TopScanLine                                      
 *                     USHORT BottomScanLine                                   
 *                     USHORT Width                                            
 *                     USHORT Attribute                                        
 *             ULONG Function ( Call vector table entry = 266 )                
 *                                                                             
 *  EXIT-NORMAL: AX = 0                                                        
 *               Cursor information is set                                     
 *                                                                             
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                                   
 *                                                                             
 *  INTERNAL REFERENCES:                                                       
 *    ROUTINES: NONE                                                           
 *                                                                             
 *  EXTERNAL REFERENCES:                                                       
 *    ROUTINES: AccessCursorPos, AccessCursorType                              
 *                                                                             
 ****************************************************************************/


USHORT EXPENTRY SetCursorInfo(Environment,ParmBlock,Function)

ENVIRONMENT far *Environment;
VDH_CURSOR far *ParmBlock;
ULONG Function;

{
  USHORT rc,ModeColumns,ColorMode,EnvBufferPassed;

  union
  {
    USHORT Position;

    struct
    {
      UCHAR Low;
      UCHAR High;
    } 
    Pos;

  } 
  Cursor;

  USHORT register ReqRow,ReqCol;         /*                             @S11*/
  USHORT ReqFlags;                       /*                             @S11*/

  ReqFlags = ParmBlock->Flags;           /*                             @S11*/
  rc = ERROR_VIO_INVALID_PARMS;          /* Initialize to error             */
  EnvBufferPassed = SEG(Environment);    /* Non-zero = TRUE                 */
 
  if ((EnvBufferPassed) && (Function == FnSetCursorInfo) && /* Valid funct  */
     ((ReqFlags & ~UPDATE_HARDWARE) ||   /* An option specified             */
     (ReqFlags & UPDATE_HARDWARE)) &&    /* Foreground                      */
     !(ReqFlags & ~VALID_CURSOR_FLAG) && /* No illegal options              */
     (ParmBlock->Length >= MinSLen_Cursor_Pos))
  {                                      /* At least min length             */

/*
**  Flags are valid - Set cursor type if requested                            
**                    Set cursor position if requested                       
*/
 
    rc = ERROR_VIO_MODE;               /* Preset invalid mode               */
 
    if (!(Environment->ModeData.fbType&GRAPHICS))
    {                                  /* Text mode only                    */
      rc = NO_ERROR;                   /* Initialize no error               */

/*
**  Parameter checking                                                       
*/

      if ((ReqFlags&CURSOR_POSITION))
      {                                /*                               @C12*/
        ReqRow = ParmBlock->Row;       /*                               @S11*/
        ReqCol = ParmBlock->Column;    /*                               @S11*/

/*
**  Check set cursor position parameters:
**        If Foreground, validate using hardware settings
**        If Background, validate using env buf mode data
*/

        if (ReqFlags&UPDATE_HARDWARE)
        {                              /* Foreground                        */

#if      VDHVGA                        /* Read/write hardware               */
                                       /* @MS00 */
 
          if ((ReqCol >= HardwareColumns()) || (ReqCol > 
             Environment->ScrollRect.Right) || /*                        @P1*/
             (ReqCol < Environment->ScrollRect.Left))/*                  @P1*/

#else
 
            if ((ReqCol >= Environment->ModeData.col) || (ReqCol > 
               Environment->ScrollRect.Right) || /*                      @P1*/
               (ReqCol < Environment->ScrollRect.Left))/*                @P1*/
#endif    
                 rc = ERROR_VIO_COL;
        } 
 
        else
        {                              /* "Background"                      */
 
          if ((ReqCol >= Environment->ModeData.col) || (ReqCol > 
             Environment->ScrollRect.Right) || /*                        @P1*/
             (ReqCol < Environment->ScrollRect.Left))/*                  @P1*/

            rc = ERROR_VIO_COL;
        } 
 
        if (!rc)
        {                              /*                               @T40*/
 
          if ((ReqRow >= Environment->ModeData.row) || (ReqRow > 
             Environment->ScrollRect.Bottom) || /*                       @P1*/
             (ReqRow < Environment->ScrollRect.Top))/*                   @P1*/

            rc = ERROR_VIO_ROW;
        }                              /*                               @T40*/
      } 
    }                                  /*                               @C12*/
 
    if ((ReqFlags&CURSOR_TYPE) && !rc)
    {                                  /* No errors encounted,@S11          */

/*
**  Check set cursor type parameters                                         
*/

      if ((ParmBlock->Length < MinSLen_Cursor_Type) || /*Missing parameters*/
         (ParmBlock->TopScanLine >= (Environment->ModeData.vres/
         Environment->ModeData.row)) || (ParmBlock->BottomScanLine > 
         (MAX_FONT_SIZE-1)))           /* Invalid parameters @MS08          */

        rc = ERROR_VIO_INVALID_PARMS;
 
      if (!rc && (ParmBlock->Width > 1))
        rc = ERROR_VIO_WIDTH;
    } 
 
    if (!rc)
    {                                  /* No errors encountered             */

/*
**  Parameters are valid - Update environment buffer if it was passed         
**                       - Update hardware if in foreground                   
*/

      if (EnvBufferPassed)
      {
 
        if (ReqFlags&CURSOR_POSITION)
        {

/*
**  Copy cursor position from caller's parmeter area to the env buffer       
*/

          Cursor.Position = Environment->ModeData.col * ReqRow+ReqCol;
          Environment->Hardware.CRTCtlRegs.Regs.CursorLocLow = Cursor.Pos.Low;
          Environment->Hardware.CRTCtlRegs.Regs.CursorLocHigh = 
                                Cursor.Pos.High;
        } 
 
        if (ReqFlags&CURSOR_TYPE)
        {

/*
**  Copy cursor type from caller's parmeter area to the env buffer           
*/

/*
** If not VGA, shadow the top scan line 
*/
                                     /*                                @B10 */

#if      !(VDHVGA)                   /*                          @B10,@MS00 */

          Environment->EGAShadowTopScanLine = ParmBlock->TopScanLine; 

#endif    
          Environment->Hardware.CRTCtlRegs.Regs.CursorStart &= 0xC0;
                                     /*           Preserve unused bits      */

          Environment->Hardware.CRTCtlRegs.Regs.CursorStart |= 
             ParmBlock->TopScanLine;
 
          if (ParmBlock->Attribute == 0xFFFF)

#if      VDHVGA                      /*                          @T23,@MS00*/

          Environment->Hardware.CRTCtlRegs.Regs.CursorStart |= 0x20;


#else                                /*                               @T23  */

          Environment->Hardware.CRTCtlRegs.Regs.CursorStart |= 0xF0;/*  @T23*/
#endif    
          Environment->Hardware.CRTCtlRegs.Regs.CursorEnd &= 0xE0;/*        
                                          Preserve unused bits              */
          Environment->Hardware.CRTCtlRegs.Regs.CursorEnd |= 
             ParmBlock->BottomScanLine;

          /*
          ** This must be saved separately so that it can be returned
          */
          Environment->CursorAttribute = ParmBlock->Attribute;

        } 
      } 
 
      if (ReqFlags&UPDATE_HARDWARE)
      {

#if      VDHVGA                      /* Read/write hardware               */
                                        /* @MS00 */
        ColorMode = HardwareColor();   /* color/mono mode ( hardware )      */

#else                                  /* Write-only hardware               */

        ColorMode = Environment->ModeData.fbType&NOT_MONO;  /* color/mono   */
                                                            /* mode(env buf */

#endif    
 
        if (ReqFlags&CURSOR_POSITION)
        {

#if      VDHVGA                      /* Read/write hardware               */
                                     /* @MS00 */
          ModeColumns = HardwareColumns(); /* Current # of columns (hw)   */

#else                                      /* Write-only hardware         */

          ModeColumns = Environment->ModeData.col;/* Current #cols -env bu*/

#endif    

/*
**  Set cursor position directly on the hardware                             
*/

          AccessCursorPos(ModeColumns, ColorMode, SET, &ParmBlock->Row);
        } 
 
        if (ReqFlags&CURSOR_TYPE)

/*
**  Set cursor type directly on the hardware                                 
*/

          AccessCursorType(ColorMode, SET, &ParmBlock->TopScanLine);
      } 
    } 
  } 

  return (rc);
} 

#endif    

/*****************************************************************************
 *                                                                             
 *  SUBROUTINE NAME: GetState                                                  
 *                                                                             
 *  DESCRIPTIVE NAME:  Get the requested video state                           
 *                                                                             
 *  FUNCTION:                                                                  
 *                                                                             
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 280 )          
 *                                                                             
 *  INPUT: (Passed on stack)                                                   
 *             FAR *Environment ( Environment buffer for the session )         
 *             FAR *ParmBlock                                                  
 *             ULONG Function ( Call vector table entry = 280 )                
 *                                                                             
 *  EXIT-NORMAL: If OEM defines this function then                             
 *                 AX = 0                                                      
 *                 user defined information is returned                        
 *               Else                                                          
 *                 AX = ERROR_VIO_INVALID_PARMS                                
 *                                                                             
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                                   
 *                                                                             
 *  EFFECTS:  None                                                             
 *                                                                             
 *  INTERNAL REFERENCES:                                                       
 *    ROUTINES: None                                                           
 *                                                                             
 *  EXTERNAL REFERENCES:                                                       
 *    ROUTINES:  None                                                          
 *                                                                             
 ****************************************************************************/


USHORT EXPENTRY GetState(Environment,ParmBlock,Function)/* @D811           */

ENVIRONMENT far *Environment;         /* @D811                             */
VDH_STATE far *ParmBlock;             /* @D811                             */
ULONG Function;                       /* @D811                             */

{                                     /* @D811                             */

  OEM_STATE_BLOCK far *pOEMState;     /* @MS11 - BEGIN                     */
 

  if (ParmBlock->Length != sizeof(VDH_STATE))
      return (ERROR_VIO_INVALID_LENGTH);

  pOEMState = (OEM_STATE_BLOCK *)ParmBlock->OEMData;
 
  if (pOEMState->OEMLength != sizeof(OEM_STATE_BLOCK))
      return (ERROR_VIO_INVALID_LENGTH);
 
  switch (pOEMState->OEMFunction)
  {
    case  VST_EXTINT :

#if      INTEXT_SUPPORT
 
      if (OEMFlags&INT_EXT_ADAPTER)

      {

        pOEMState->OEMData1 = IntExtState(VST_EXTINT);
        return (NO_ERROR);

      } 
 
      else

#endif    
           return (ERROR_VIO_INVALID_PARMS);
    case  VST_EXTFLG :

#if      INTEXT_SUPPORT
 
      if (OEMFlags&INT_EXT_ADAPTER)
        pOEMState->OEMData1 = Can_Switch;
 
      else
        pOEMState->OEMData1 = Cannot_Switch;

#else

      pOEMState->OEMData1 = Cannot_Switch;

#endif                                 /* INTEXT_SUPPORT */

      return (NO_ERROR);
  }                                    /* @MS11 - END */

  return  ERROR_VIO_INVALID_PARMS;     /* @D811                             */

}                                      /* @D811                             */

/*****************************************************************************
 *                                                                          
 *  SUBROUTINE NAME: SetState                                               
 *                                                                          
 *  DESCRIPTIVE NAME:  Set the requested video state                        
 *                                                                          
 *  FUNCTION:                                                               
 *                                                                          
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 280 )       
 *                                                                          
 *  INPUT: (Passed on stack)                                                
 *             FAR *Environment ( Environment buffer for the session )      
 *             FAR *ParmBlock                                               
 *             ULONG Function ( Call vector table entry = 281 )             
 *                                                                          
 *  EXIT-NORMAL: If OEM defines this function then                          
 *                 AX = 0                                                   
 *                 user defined information is set                          
 *               Else                                                       
 *                 AX = ERROR_VIO_INVALID_PARMS                             
 *                                                                          
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                                
 *                                                                          
 *  EFFECTS:                                                                
 *                                                                          
 *  INTERNAL REFERENCES:                                                    
 *    ROUTINES: NONE                                                        
 *                                                                          
 *  EXTERNAL REFERENCES:                                                    
 *    ROUTINES:                                                             
 *                                                                          
 ****************************************************************************/


USHORT EXPENTRY SetState(Environment,ParmBlock,Function)/* @D811          */

ENVIRONMENT far *Environment;        /* @D811                             */
VDH_STATE far *ParmBlock;            /* @D811                             */
ULONG Function;                      /* @D811                             */

{                                    /* @D811                             */
  OEM_STATE_BLOCK far *pOEMState;    /* @MS11 - BEGIN                     */
 

  if (ParmBlock->Length != sizeof(VDH_STATE))
    return (ERROR_VIO_INVALID_LENGTH);

  pOEMState = (OEM_STATE_BLOCK *)ParmBlock->OEMData;
 
  if (pOEMState->OEMFunction == VST_EXTINT)
  {
 
    if (pOEMState->OEMLength != sizeof(OEM_STATE_BLOCK))
      return (ERROR_VIO_INVALID_LENGTH);

#if      INTEXT_SUPPORT
 
    if (OEMFlags&INT_EXT_ADAPTER)
    {
      IntExtState(pOEMState->OEMData1);
      return (NO_ERROR);
    } 

#endif                                 /* INTEXT_SUPPORT                   */

  }                                    /* @MS11 - END                      */

  return  ERROR_VIO_INVALID_PARMS;     /* @D811                            */
}                                      /* @D811                            */

/*****************************************************************************
 *                                                                       
 *  SUBROUTINE NAME: GetVariableInfo                                     
 *                                                                       
 *  DESCRIPTIVE NAME: Get selected variable information                  
 *                                                                       
 *  FUNCTION: GetVariableInfo is called by BVS to return selected        
 *            information about video state - blink versus background    
 *            intensity, overscan color, underscore scan line, video     
 *            enable, or 8514/A display mask. If the request specifies   
 *            hardware and the hardware is readable, the actual          
 *            hardware setting will be read and returned.  Otherwise     
 *            the returned information will be taken from the            
 *            environment buffer, if it has been passed.                 
 *                                                                       
 *  ENTRY POINT: GetVariableInfo                                         
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 269 )    
 *                                                                       
 *  INPUT: (Passed on stack)                                             
 *             FAR *Environment ( Environment buffer for the session )   
 *             FAR *ParmBlock                                            
 *                     USHORT Length = length of this packet             
 *                     USHORT Flags  = 0 - Environment buffer only       
 *                                     1 - Hardware also                 
 *                     USHORT Blink                                      
 *                     USHORT Overscan                                   
 *                     USHORT Underscore                                 
 *                     USHORT VideoEnable                                
 *                     ULONG  DisplayMask                                
 *                     USHORT CodePageID                                 
 *                     USHORT ScrollLeft                                 
 *                     USHORT ScrollTop                                  
 *                     USHORT ScrollRight                                
 *                     USHORT ScrollBottom                               
 *                     USHORT ScreenRows                                 
 *                     USHORT ScreenCols                                 
 *             ULONG Function ( Call vector table entry = 269 )          
 *                                                                       
 *  EXIT-NORMAL: AX = 0                                                  
 *               Selected variable information is returned               
 *                                                                       
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                             
 *                                                                       
 *  EFFECTS: If hardware specified and hardware is readable, the         
 *           environment buffer is updated, if passed.                   
 *                                                                       
 *  INTERNAL REFERENCES:                                                 
 *    ROUTINES: NONE                                                     
 *                                                                       
 *  EXTERNAL REFERENCES:                                                 
 *    ROUTINES: AccessCursorBlink, AccessCursorOverscan                  
 *              AccessCursorUnderscore, AccessCursorVideoEnable          
 *              AccessDisplayMask                                        
 *                                                                       
 ****************************************************************************/


USHORT EXPENTRY GetVariableInfo(Environment,ParmBlock,Function)

ENVIRONMENT far *Environment;
VDH_VARIABLE far *ParmBlock;
ULONG Function;

{

  USHORT rc,EnvBufferPassed;
  USHORT ReqFlags;                     /*                               @S11*/

  ReqFlags = ParmBlock->Flags;         /*                               @S11*/
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */
 
  if ((Function == FnGetVariableInfo) && /* Valid function request          */
     (ReqFlags&VALID_VARIABLE_FLAG) && /*                      @@BVALIDFLAGS*/
     (EnvBufferPassed ||               /* Env buffer passed                 */
     (ReqFlags&UPDATE_HARDWARE)) &&    /* or is foreground                  */
     (ParmBlock->Length >= MinSLen_Var_Blink))
  {                                    /* At least min length               */

/*
**  Flags are valid - Get blink versus background if enough room provided     
**                    Get overscan color if enough room provided              
**                    Get underscore scan line if enough room provided        
**                    Get video enable if enough room provided                
**                    Get display mask if enough room provided                
**                    Get code page ID if enough room provided                
**                    Get scrollable region of the screen@P1   |
**                    GET ACTUAL SCREEN HEIGHT AND WIDTH               
*/

    rc = NO_ERROR;                     /* Initialize no error               */

#if      VDH8514A                      /* @MS00 */

/*
**  If VDHVGA.DLL has been successfully installed, call GetVariableInfo in    
**  VDHVGA.DLL.  Otherwise, just return the Display Mask ( if enough room )   
**  Don't let VGA process the displaymask since an error is returned for
**  NON-8514A ADAPTERS IF THIS CALL IS ISSUED.                          
*/

    if ((VGA_PRESENT)&                 /*                               @Y00*/
    (!(ReqFlags&VARIABLE_DISPLAYMASK)))/*                               @Y00*/
      rc = ChainedVDHGetVariableInfo(
                     (ENVIRONMENT far *)&Environment->VGAEnvironment,
                      ParmBlock, Function);
 
    if (!rc && EnvBufferPassed)
    {

/*
**  Copy the display mask to the caller's parameter area                    
*/

      if (ReqFlags&VARIABLE_DISPLAYMASK)
      {                                /*                           @@B,@S24*/
 
        if (ParmBlock->Length >= MinSLen_Var_DisplayMask)
        {                              /*                               @S24*/
 
          if (ReqFlags&UPDATE_HARDWARE)
          {                            /* 8514/A in FG,                 @S24*/

            AccessDisplayMask(GET, &Environment->DisplayMask);/* Ring2,@S24 */

          }                            /*                               @S24*/

          ParmBlock->DisplayMask = Environment->DisplayMask;/*          @S24*/
        } 
 
        else
        {                              /*                               @S24*/

          rc = ERROR_VIO_INVALID_LENGTH;/*                          @@B,@S24*/

        }                              /*                               @S24*/
      }                                /*                               @S24*/
    } 

#else                                  /* Not VDH8514A                      */

/*
**  If requesting DISPLAYMASK for non-8514/A, set error      
*/

    if (ReqFlags&VARIABLE_DISPLAYMASK) /*                               @Y00*/
      rc = ERROR_VIO_INVALID_PARMS;    /*                               @Y00*/
 
    if ((ReqFlags&UPDATE_HARDWARE) && READABLE)
    {                                  /* i.e. VGA in FG                    */

#if      VDHVGA                      /* Read/write hardware               */
                                        /* @MS00 */

/*
**  Get blink versus background intensity directly from the hardware         
*/

      if (ReqFlags&VARIABLE_BLINK)     /*                                @@B*/
      {
 
        if (Environment->ModeData.fbType&GRAPHICS)/*                     @@C*/
          rc = ERROR_VIO_MODE;         /*                                @@C*/
 
        else                           /*                                @@C*/
          AccessBlink(HardwareColor(), GET, &ParmBlock->Blink);
      } 

/*
**  Get overscan color directly from the hardware                            
*/

      if ((ReqFlags&VARIABLE_OVERSCAN) && !rc)/*                    @@B,@S11*/
      {
 
        if (ParmBlock->Length >= MinSLen_Var_Overscan)
          AccessOverscan(HardwareColor(), GET, &ParmBlock->Overscan);
 
        else
          rc = ERROR_VIO_INVALID_LENGTH;/*                               @@B*/
      } 

/*
**  Get underscore scan line directly from the hardware                      
*/

      if ((ReqFlags&VARIABLE_UNDERSCORE) && !rc)/*                  @@B,@S11*/
      {
 
        if (ParmBlock->Length >= MinSLen_Var_Underscore)
          AccessUnderscore(HardwareColor(), GET, &ParmBlock->Underscore);
 
        else
          rc = ERROR_VIO_INVALID_LENGTH;/*                               @@B*/
      } 

/*
**  Get Video enable directly from the hardware                              
*/

      if ((ReqFlags&VARIABLE_VIDEOENABLE) && !rc)
      {                                /*                           @@B,@S11*/
 
        if (ParmBlock->Length >= MinSLen_Var_VideoEnable)
          AccessVideoEnable(HardwareColor(), GET, &ParmBlock->VideoEnable);
                                       /*   ring 2 callgate                */
 
        else
          rc = ERROR_VIO_INVALID_LENGTH;/*                               @@B*/
      } 
 

      if (!rc && EnvBufferPassed)
      {

/*
**  Copy blink setting from caller's parmeter area to the env buffer         
*/

        if (ReqFlags&VARIABLE_BLINK)   /*                                @@B*/
        {
          Environment->Hardware.Attributes.Regs.ModeControl &= 0xF7;
 
          if (ParmBlock->Blink == 0)
            Environment->Hardware.Attributes.Regs.ModeControl |= 0x08;/*    
                                       /*  Enable blink                     */
        } 

/*
**  Copy overscan from caller's parmeter area to the env buffer              
*/

        if (ReqFlags&VARIABLE_OVERSCAN)/*                                @@B*/
            Environment->Hardware.Attributes.Regs.Overscan =
                            (UCHAR) ParmBlock->Overscan;

/*
**  Copy underscore from caller's parmeter area to the env buffer            
*/

        if (ReqFlags&VARIABLE_UNDERSCORE)/*                              @@B*/
        {
          Environment->Hardware.CRTCtlRegs.Regs.Underline &= 0xE0;
          Environment->Hardware.CRTCtlRegs.Regs.Underline |= 
              ParmBlock->Underscore;
        } 

/*
**  Copy video enable from caller's parmeter area to the env buffer          
*/

        if (ReqFlags&VARIABLE_VIDEOENABLE)/*                             @@B*/
        {
          Environment->VideoEnable = ParmBlock->VideoEnable;/*          @C21*/
        } 
      } 
  #endif    
    } 
 
    else
    {

/*
**  Requesting application is running in the background OR                    
**  the hardware is write-only                                                
*/

      if (EnvBufferPassed)
      {

/*
**  Copy blink setting from env buffer to caller's parameter area            
*/

        if (ReqFlags&VARIABLE_BLINK)   /*                                @@B*/
        {
 
          if (Environment->ModeData.fbType&GRAPHICS)/*                   @@C*/
            rc = ERROR_VIO_MODE;       /*                                @@C*/
 
          else
          {

#if     BLINK_SUPPORT               /* @MS00 */

#if     VDHCGA                    /* @MS00 */
        ParmBlock->Blink = !(Environment->Hardware.CGAModeControl&0x20);

#else
        ParmBlock->Blink =
           !(Environment->Hardware.Attributes.Regs.ModeControl&0x08);

#endif    

#else                                /*                                @@B*/
        rc = ERROR_VIO_INVALID_PARMS;        /*                        @@B*/

#endif    
          } 
        } 

/*
**  Copy overscan from env buffer to the caller's parameter area             
*/

        if ((ReqFlags&VARIABLE_OVERSCAN) && !rc)/*               @@B,@S11*/
        {

#if      OVERSCAN_SUPPORT            /* @MS00 */
 
          if (ParmBlock->Length >= MinSLen_Var_Overscan)
          {

#if      VDHCGA                    /* @MS00 */
            ParmBlock->Overscan = (USHORT)Environment->Hardware.CGAColorSelect;

#else                              /* @MS00 */

#if      VDHEGA                  /*                          @@B,@MS00*/
 
            if (Environment->ModeData.vres != 200)/*                     @@B*/
              rc = ERROR_VIO_INVALID_PARMS;/*                            @@B*/
 
            else                       /*                                @@B*/
#endif    
                 ParmBlock->Overscan = 
                   (USHORT) Environment->Hardware.Attributes.Regs.Overscan;

#endif    
          } 
 
          else
            rc = ERROR_VIO_INVALID_LENGTH;/*                             @@B*/

#else                                /*                          @@B,@MS00*/
  rc = ERROR_VIO_INVALID_PARMS;        /*                                @@B*/

#endif    
        } 

/*
**  Copy underscore from env buffer to the caller's parameter area           
*/

        if ((ReqFlags&VARIABLE_UNDERSCORE) && !rc)/*                @@B,@S11*/
        {

#if      UNDERSCORE_SUPPORT          /* @MS00 */
 
          if (ParmBlock->Length >= MinSLen_Var_Underscore)
            ParmBlock->Underscore = 
               Environment->Hardware.CRTCtlRegs.Regs.Underline&0x1F;
 
          else
            rc = ERROR_VIO_INVALID_LENGTH;/*                             @@B*/

#else                                  /*                          @@B,@MS00*/
  rc = ERROR_VIO_INVALID_PARMS;        /*                                @@B*/

#endif    
        } 

/*
**  Copy video enable from env buffer to the caller's parameter area         
*/

        if ((ReqFlags&VARIABLE_VIDEOENABLE) && !rc)/*               @@B,@S11*/
        {
 
          if (ParmBlock->Length >= MinSLen_Var_VideoEnable)
            ParmBlock->VideoEnable = Environment->VideoEnable;
 
          else
            rc = ERROR_VIO_INVALID_LENGTH;/*                             @@B*/

        } 
      } 
 
      else
        rc = ERROR_VIO_INVALID_PARMS;  /* Write-only, no env buffer         */

    } 

/*
**  Copy code page ID                                                        
*/

    if ((ReqFlags&VARIABLE_CODEPAGE) && !rc)/*                      @@B,@S11*/
    {
 
      if (ParmBlock->Length >= MinSLen_Var_CodePage)
      {

  #if      FONT_SUPPORT                /* @MS00 */
 
        if (Environment->UserFont == USER_FONT_SELECTABLE)/*             @@A*/
          rc = ERROR_VIO_USER_FONT;    /*                                @@A*/
 
        else                           /*                                @@A*/
          ParmBlock->CodePageID = Environment->CodePageID;/*             @@A*/

  #else
        ParmBlock->CodePageID = ROM_FONT;

  #endif    
      } 
 
      else
        rc = ERROR_VIO_INVALID_LENGTH; /*                                @@B*/
    } 

/*
**  Scrollable rectangle@P1  
*/

    if ((ReqFlags&VARIABLE_SCROLLRECT) && !rc)
    {                                  /*                           @P1,@S11*/
 
      if (ParmBlock->Length >= MinSLen_Var_ScrollRect)/*                 @P1*/
      {                                /*                                @P1*/
        ParmBlock->ScrlLeft = Environment->ScrollRect.Left;/*            @P1*/
        ParmBlock->ScrlTop = Environment->ScrollRect.Top;/*              @P1*/
        ParmBlock->ScrlRight = Environment->ScrollRect.Right;/*          @P1*/
        ParmBlock->ScrlBottom = Environment->ScrollRect.Bottom;/*        @P1*/
      }                                /*                                @P1*/
 
      else
        rc = ERROR_VIO_INVALID_LENGTH; /*                                @P1*/
    }                                  /*                                @P1*/

/*
**  Actual Screen Dimensions@P1  
*/

    if ((ReqFlags&VARIABLE_SCREENDIM) && !rc)
    {                                  /*                           @P1,@S11*/
 
      if (ParmBlock->Length >= MinSLen_Var_ScreenDim)/*                  @P1*/
      {                                /*                                @P1*/
        ParmBlock->ScreenRows = Environment->ModeData.row;/*             @P1*/
        ParmBlock->ScreenCols = Environment->ModeData.col;/*             @P1*/
      }                                /*                                @P1*/
 
      else
        rc = ERROR_VIO_INVALID_LENGTH; /*                                @P1*/
    }                                  /*                                @P1*/
#endif    
  } 

  return (rc);
} 

/*****************************************************************************
 *                                                                         
 *  SUBROUTINE NAME: SetVariableInfo                                       
 *                                                                         
 *  DESCRIPTIVE NAME: Set selected variable information                    
 *                                                                         
 *  FUNCTION: SetVariableInfo is called by BVS to set selected             
 *            information about video state - blink versus background      
 *            intensity, overscan color, underscore scan line, video       
 *            enable, or 8514/A display mask. If the request specifies     
 *            hardware the hardware and the environment buffer, if         
 *            passed, will be updated.  Otherwise just the environment     
 *            buffer, if passed, will be updated.                          
 *                                                                         
 *  ENTRY POINT: SetVariableInfo                                           
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 270 )      
 *                                                                         
 *  INPUT: (Passed on stack)                                               
 *             FAR *Environment ( Environment buffer for the session )     
 *             FAR *ParmBlock                                              
 *                     USHORT Length = length of this packet               
 *                     USHORT Flags  = 0 - Environment buffer only         
 *                                     1 - Hardware also                   
 *                     USHORT Blink                                        
 *                     USHORT Overscan                                     
 *                     USHORT Underscore                                   
 *                     USHORT VideoEnable                                  
 *                     ULONG  DisplayMask                                  
 *                     USHORT CodePageID                                   
 *             ULONG Function ( Call vector table entry = 270 )            
 *                                                                         
 *  EXIT-NORMAL: AX = 0                                                    
 *               Selected variable information is set                      
 *                                                                         
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                               
 *                                                                         
 *  INTERNAL REFERENCES:                                                   
 *    ROUTINES: NONE                                                       
 *                                                                         
 *  EXTERNAL REFERENCES:                                                   
 *    ROUTINES: AccessCursorBlink, AccessCursorOverscan                    
 *              AccessCursorUnderscore, AccessCursorVideoEnable            
 *              AccessDisplayMask                                          
 *                                                                         
 ****************************************************************************/


USHORT EXPENTRY SetVariableInfo(Environment,ParmBlock,Function)

  ENVIRONMENT far *Environment;
  VDH_VARIABLE far *ParmBlock;
  ULONG Function;

{
  USHORT rc,row,col,                   /*                               @C10*/
     ColorMode,EnvBufferPassed;
  SHORT i;                             /*                               @C10*/
  REGADDRESS RegAddress;

#if      FONT_SUPPORT                  /*                         @C10,@MS00*/
ROMCP_TABLE *rcp_tbl_ptr;              /*                               @C10*/

#endif    

  VDH_CURSOR CurParmBlock;             /* for set scrollable rect        @P1*/
  USHORT DoSet;                        /*                                @P1*/
  USHORT ReqFlags;                     /*                               @S11*/


  ReqFlags = ParmBlock->Flags;         /*                               @S11*/
  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
  EnvBufferPassed = SEG(Environment);  /* Non-zero = TRUE                   */
 
  if ((Function == FnSetVariableInfo) && /* Valid function request          */
     (ReqFlags & ~UPDATE_HARDWARE) &&    /* An option specified             */
     (EnvBufferPassed ||                 /* Env buffer passed               */
     (ReqFlags & UPDATE_HARDWARE)) &&    /* or is foreground                */
     !(ReqFlags & ~VALID_VARIABLE_FLAG))
  {                                      /* No illegal options              */

/*
**  Flags are valid - Set blink versus background intensity if requested     
**                    Set overscan (border) color if requested               
**                    Set scan line for underscore if requested              
**                    Set video enable if requested                          
**                    Set display mask (8514/A) if requested                 
**                    Set codepage if requested  
**                    FORCE CODEPAGE SET (OVERRIDE MODE) IF REQUESTED 
**                    SET SCROLLABLE REGION OF THE SCREEN               @P1  
*/

    rc = NO_ERROR;                     /* Initialize no error               */

#if      VDH8514A                      /* @MS00 */

/*
**  If VDHVGA.DLL has been successfully installed AND a request was made to  
**  set information other than the DisplayMask, call GetVariableInfo in   )  
**  VDHVGA.DLL.  Otherwise, just set the Display Mask                        
*/

    if (VGA_PRESENT && (ReqFlags&~(UPDATE_HARDWARE&VARIABLE_DISPLAYMASK)))
      rc = ChainedVDHSetVariableInfo((ENVIRONMENT far *)
         &Environment->VGAEnvironment, ParmBlock, Function);

/*
**  Parameter checking for 8514A adapters                                    
**---------------------------------------------------------------------------
**  Check set display mask (8514/A) parameters                               
*/

    if ((ReqFlags&VARIABLE_DISPLAYMASK) && !rc)/* No errors encounted,@S11  */
 
      if (ParmBlock->Length < MinSLen_Var_DisplayMask)/* Missing parameter  */
        rc = ERROR_VIO_INVALID_LENGTH;
 
    if (!rc)
    {                                  /* No errors encountered             */

/*
**  Parameters are valid - Update environment buffer if it was passed        
**                       - Update hardware if in foreground                  
*/

      if (EnvBufferPassed)
      {
 
        if (ReqFlags&VARIABLE_DISPLAYMASK)

/*
**  Copy display mask from caller's parmeter area to the env buffer          
*/

          Environment->DisplayMask = ParmBlock->DisplayMask;
      } 
 
      if (ReqFlags&UPDATE_HARDWARE)
      {
        ColorMode = Environment->ModeData.fbType&NOT_MONO;/* color/mono     */
                                                       /* mode (env buffer) */
 
        if (ReqFlags&VARIABLE_DISPLAYMASK)

/*
**  Set display mask (8514/A) directly on the hardware                       
*/

          AccessDisplayMask(SET, &ParmBlock->DisplayMask);/* ring 2         */
                                                          /* callgate       */
      } 
    } 

#else               /*  Not VDH8514A  @MS00  */

/*
**  If requesting DISPLAYMASK for non-8514/A, set error@Y00         
*/

    if (ReqFlags&VARIABLE_DISPLAYMASK) /*                               @Y00*/
      rc = ERROR_VIO_INVALID_PARMS;    /*                               @Y00*/

/*
**  Parameter checking for non-8514A adapters                                
**---------------------------------------------------------------------------
**  Check set blink versus background parameters                             
*/

    if (ReqFlags&VARIABLE_BLINK)
    {                                  /* No errors encountered,@S11        */
 
      if (Environment->ModeData.fbType&GRAPHICS)/*                       @@C*/
        rc = ERROR_VIO_MODE;           /*                                @@C*/

  #if      BLINK_SUPPORT               /* @MS00 */
 
      else
      {
 
        if (ParmBlock->Length < MinSLen_Var_Blink)/* Missing parameter      */
          rc = ERROR_VIO_INVALID_LENGTH;
 
        else
 
          if (ParmBlock->Blink > 1)    /* Invalid parameter                 */
            rc = ERROR_VIO_INVALID_PARMS;
      } 

  #else                                /*                         @C27,@MS00*/
 
      else                             /*                               @C27*/
        rc = ERROR_VIO_INVALID_PARMS;  /*                               @C27*/

  #endif    

    } 

/*
**  Check set overscan (border) color parameters                             
*/

    if ((ReqFlags&VARIABLE_OVERSCAN) && !rc)
    {                                  /* No errors,@S11                    */

  #if      OVERSCAN_SUPPORT            /* @MS00 */
 
      if (ParmBlock->Length < MinSLen_Var_Overscan)/* Missing parm          */
        rc = ERROR_VIO_INVALID_LENGTH;
 
      else
 
        if (ParmBlock->Overscan&~0x00FF)/* Invalid parm                     */
          rc = ERROR_VIO_INVALID_PARMS;

  #else                                /*                         @C27,@MS00*/
  rc = ERROR_VIO_INVALID_PARMS;        /*                               @C27*/

  #endif    

  #if      VDHEGA                      /*                         @T6,@MS00*/
 
      if (!rc && Environment->ModeData.vres != 200)/*                    @T6*/
        rc = ERROR_VIO_INVALID_PARMS;  /*                                @T6*/

  #endif    
    } 

/*
**  Check set scan line for underscore parameters                            
*/

    if ((ReqFlags&VARIABLE_UNDERSCORE) && !rc)
    {                                  /* No errors,@S11                    */

  #if      UNDERSCORE_SUPPORT          /* @MS00 */
 
      if (ParmBlock->Length < MinSLen_Var_Underscore)/* Missing parm        */
        rc = ERROR_VIO_INVALID_LENGTH;
 
      else

        if (ParmBlock->Underscore > (MAX_FONT_SIZE-1))/* Invalid parm       */
          rc = ERROR_VIO_INVALID_PARMS;

  #else                                /*                         @C27,@MS00*/
  rc = ERROR_VIO_INVALID_PARMS;        /*                               @C27*/

  #endif    
    } 

/*
**  Check set video enable parameters                                        
*/

    if ((ReqFlags&VARIABLE_VIDEOENABLE) && !rc)
    {                                  /* No errors,@S11                    */
 
      if (ParmBlock->Length < MinSLen_Var_VideoEnable)/* Missing parameter  */
        rc = ERROR_VIO_INVALID_LENGTH;
 
      if (!rc && (ParmBlock->VideoEnable > 1))/* Invalid parameter          */
        rc = ERROR_VIO_INVALID_PARMS;
    } 

/*
**  Check set code page parameters                                           
*/


    if ((ReqFlags&VARIABLE_CODEPAGE) && !rc)
    {                                  /* No errors,@S11                    */

  #if      FONT_SUPPORT                /* @MS00 */
 
      if (ParmBlock->Length < MinSLen_Var_CodePage)
      {                                /* Missing parameter                 */

        rc = ERROR_VIO_INVALID_LENGTH;

      } 
 
      else
 
        if (ParmBlock->CodePageID != ROM_FONT)
        {
 
          if ((ParmBlock->CodePageID != USER_FONT_SELECTABLE)/*     @C7,@C10*/
             && (ParmBlock->CodePageID != USER_FONT_NOT_SELECTABLE))
          {                            /*                                @C7*/

            rc = ERROR_VIO_BAD_CP;     /* Code page not prepared            */
            rcp_tbl_ptr = RomCP_tbl.ptr;/*                              @C10*/
            row = Environment->ModeData.vres/Environment->ModeData.row;
                                                                      
            col = Environment->ModeData.hres/Environment->ModeData.col;
                                                                  
 
            for (i = 0; i < ROMCP_NUM; i++)/*                           @C10*/
            {                          /*                               @C10*/
 
              if ((ParmBlock->CodePageID == rcp_tbl_ptr->CodePageID) && /*  
                                                                        @C10*/
                 (row == rcp_tbl_ptr->PelRows) && /*                    @C10*/
                 (col == rcp_tbl_ptr->PelColumns))/*                    @C10*/

              {                        /*                               @C10*/
                Environment->ROMFontIndex = (UCHAR)i;/*                 @C10*/
                Environment->ActiveFontPTR = (UCHAR far *)CP_FONT;/*    @C10*/
                i = ROMCP_NUM;         /*                               @C10*/
                rc = 0;                /*                               @C10*/
              }                        /*                               @C10*/
 
              else                     /*                               @C10*/
                rcp_tbl_ptr++;         /*                               @C10*/
 
              if ((i == (ROMCP_NUM-1)) && rc && (col == 9))/*           @C10*/
              {                        /*                               @C10*/
                col = 8;               /*                               @C10*/
                i = -1;                /*                               @C10*/
                rcp_tbl_ptr = RomCP_tbl.ptr;/*                          @C10*/

              }                        /*                               @C10*/
            }                          /*                               @C10*/
          } 
        } 

  #else
                                                                    /* NS00 */
      rc = ERROR_VIO_NA_CP;            /* No code page support              */
  #endif    
    } 

/*
**  Scrollable rectangle
*/

    if ((ReqFlags&VARIABLE_SCROLLRECT) && !rc)
    {                                  /*                           @P1,@S11*/
 
      if ((ParmBlock->Length >= MinSLen_Var_ScrollRect) && /*            @P1*/
         (Environment->ModeData.col > ParmBlock->ScrlLeft) && /*         @P1*/
         (Environment->ModeData.col > ParmBlock->ScrlRight) && /*        @P1*/
         (Environment->ModeData.row > ParmBlock->ScrlTop) && /*          @P1*/
         (Environment->ModeData.row > ParmBlock->ScrlBottom) && /*       @P1*/
         (ParmBlock->ScrlLeft <= ParmBlock->ScrlRight) && /*             @P1*/
         (ParmBlock->ScrlTop <= ParmBlock->ScrlBottom))

      {                                /*                                @P1*/
        Environment->ScrollRect.Left = ParmBlock->ScrlLeft;/*            @P1*/
        Environment->ScrollRect.Top = ParmBlock->ScrlTop;/*              @P1*/
        Environment->ScrollRect.Right = ParmBlock->ScrlRight;/*          @P1*/
        Environment->ScrollRect.Bottom = ParmBlock->ScrlBottom;/*        @P1*/
        CurParmBlock.Length = sizeof(VDH_CURSOR);/*                      @P1*/
        CurParmBlock.Flags = (ReqFlags&UPDATE_HARDWARE)|/*               @P1*/
           CURSOR_POSITION;            /*                                @P1*/

        DoSet = FALSE;                 /*                                @P1*/
 
        if (!GetCursorInfo(Environment, &CurParmBlock, FnGetCursorInfo))
        {
 
          if (CurParmBlock.Column < Environment->ScrollRect.Left)
          {
            CurParmBlock.Column = Environment->ScrollRect.Left;/*        @P1*/
            DoSet = TRUE;              /*                                @P1*/
          }                            /*                                @P1*/
 
          if (CurParmBlock.Column > Environment->ScrollRect.Right)
          {
            CurParmBlock.Column = Environment->ScrollRect.Right;/*       @P1*/
            DoSet = TRUE;              /*                                @P1*/
          }                            /*                                @P1*/
 
          if (CurParmBlock.Row < Environment->ScrollRect.Top)
          {                            /*                                @P1*/
            CurParmBlock.Row = Environment->ScrollRect.Top;/*            @P1*/
            DoSet = TRUE;              /*                                @P1*/
          }                            /*                                @P1*/
 
          if (CurParmBlock.Row > Environment->ScrollRect.Bottom)
          {                            /*                                @P1*/
            CurParmBlock.Row = Environment->ScrollRect.Bottom;/*         @P1*/
            DoSet = TRUE;              /*                                @P1*/
          }                            /*                                @P1*/
 
          if (DoSet)                   /*                                @P1*/
            SetCursorInfo(Environment, &CurParmBlock, FnSetCursorInfo);
        }                              /*                                @P1*/
      }                                /*                                @P1*/
 
      else
        rc = ERROR_VIO_INVALID_LENGTH; /*                                @P1*/
    }                                  /*                                @P1*/
 

    if (!rc)
    {                                  /* No errors encountered             */

/*
**  Parameters are valid - Update environment buffer if it was passed        
**                       - Update hardware if in foreground                  
*/

      if (EnvBufferPassed)
      {

  #if      BLINK_SUPPORT               /* @MS00 */
 
        if (ReqFlags&VARIABLE_BLINK)
        {

/*
**  Copy blink setting from caller's parmeter area to the env buffer         
*/

    #if      VDHCGA             /* @MS00 */  /* Select background intensity */ 
          Environment->Hardware.CGAModeControl &= ~0x20;
                                                    
 
          if (ParmBlock->Blink == 0)                    /* Enable blink    */ 
            Environment->Hardware.CGAModeControl |= 0x20;

    #else                                    /* Select background intensity */ 
          Environment->Hardware.Attributes.Regs.ModeControl &= 0xF7;
                                             
 
          if (ParmBlock->Blink == 0)      /*  Enable blink            */           
            Environment->Hardware.Attributes.Regs.ModeControl |= 0x08;
                                          
    #endif    
        } 
  #endif    

  #if      OVERSCAN_SUPPORT            /* @MS00 */
 
        if (ReqFlags&VARIABLE_OVERSCAN)

/*
**  Copy border color from caller's parmeter area to the env buffer          
*/

    #if      VDHCGA                    /* @MS00 */
             Environment->Hardware.CGAColorSelect = (UCHAR)ParmBlock->Overscan;

    #else
        Environment->Hardware.Attributes.Regs.Overscan = (UCHAR)
           ParmBlock->Overscan;
    #endif    
  #endif    

  #if      UNDERSCORE_SUPPORT          /* @MS00 */
 
        if (ReqFlags&VARIABLE_UNDERSCORE)
        {

/*
**  Copy underscore SL from caller's parameter area to the env buffer
*/

          Environment->Hardware.CRTCtlRegs.Regs.Underline &= 0xE0;
          Environment->Hardware.CRTCtlRegs.Regs.Underline |= 
             ParmBlock->Underscore;
        } 
  #endif    
 
        if (ReqFlags&VARIABLE_VIDEOENABLE)
        {

/*
**  Copy video enable from caller's parmeter area to the env buffer          
*/

          Environment->VideoEnable = ParmBlock->VideoEnable;
        } 

  #if      FONT_SUPPORT                /* @MS00 */

/*
**  Copy code page ID from caller's parmeter area to the Environment buffer. 
**  Setting the CodePage makes the user font unselectable.                   
*/

        if (ReqFlags&VARIABLE_CODEPAGE)
        {
 
          if ((ParmBlock->CodePageID != USER_FONT_SELECTABLE) && 
             (ParmBlock->CodePageID != USER_FONT_NOT_SELECTABLE))

          {
            Environment->CodePageID = ParmBlock->CodePageID;
            Environment->UserFont = USER_FONT_NOT_SELECTABLE;
          } 
 
          else
          {
            Environment->UserFont = ParmBlock->CodePageID;

          } 

          /*
          ** call FindFont to setup Env for new font         
          */

          FindFont(Environment->ModeIndex, Environment->ModeData.row,
             Environment);             /*                               @C10*/
        } 
  #endif    
      } 
 
      if (ReqFlags&UPDATE_HARDWARE)
      {

#if      VDHVGA                        /* Read/write hardware               */
                                       /* @MS00 */
        ColorMode = HardwareColor();   /* color/mono mode ( hardware )      */

  #else         /* Write-only hardware, color/mono mode (env buffer)        */
        ColorMode = Environment->ModeData.fbType&NOT_MONO;

  #endif    

  #if      BLINK_SUPPORT               /* @MS00 */
 
        if (ReqFlags&VARIABLE_BLINK)

/*
**  Set blink versus background intensity directly on the hardware           
*/

    #if      VDHCGA
        {                              /*                               @T37*/
          RegAddress.DataPort = CGAModeCtlReg;
          AccessRegister(&RegAddress, SET, 
             &Environment->Hardware.CGAModeControl);
        }                              /*                               @T37*/

    #else
          AccessBlink(ColorMode, SET, &ParmBlock->Blink);

    #endif    
  #endif    

  #if      OVERSCAN_SUPPORT            /* @MS00 */
 
        if (ReqFlags&VARIABLE_OVERSCAN)

/*
**  Set overscan (border) color directly on the hardware                     
*/

    #if      VDHCGA                    /* @MS00 */
        {                              /*                               @T37*/
          RegAddress.DataPort = CGAColorSelReg;
          AccessRegister(&RegAddress, SET, 
             &Environment->Hardware.CGAColorSelect);
        }                              /*                               @T37*/

    #else
          AccessOverscan(ColorMode, SET, &ParmBlock->Overscan);

    #endif    
  #endif    

  #if      UNDERSCORE_SUPPORT          /* @MS00 */
 
        if (ReqFlags&VARIABLE_UNDERSCORE)

/*
**  Set underscore scan line directly on the hardware                        
*/

          AccessUnderscore(ColorMode, SET, &ParmBlock->Underscore);
  #endif    
 
        if (ReqFlags&VARIABLE_VIDEOENABLE)

/*
**  Set video enable directly on the hardware                                
*/

          AccessVideoEnable(ColorMode, SET, &ParmBlock->VideoEnable);
                                                         /* ring 2 callgate */

  #if      FONT_SUPPORT                /* @MS00 */
 
        if (ReqFlags&VARIABLE_CODEPAGE)

/*
**  Set code page font                                                       
*/

          rc = SetHWFont(Environment, Environment->ActiveFontPTR,
                                                                 /*@C10,@T53*/
             (UCHAR far *)PHYSICAL_FONT_BUFFER);
  #endif    
      }                                /* End of foreground service         */
    } 
#endif   
  } 

  return (rc);
} 

/*****************************************************************************
 *                                                                         
 *  SUBROUTINE NAME: GetDBCSDisplayInfo                                    
 *                                                                         
 *  DESCRIPTIVE NAME: Return DBCS display infromation for current mode     
 *                                                                         
 *  FUNCTION: GetDBCSDisplayInfo is called by BVS to get information       
 *            about the display width of characters on the screen.         
 *            Characters may be one or two cells wide.  This routine       
 *            returns the range of characters that require two cells       
 *            on the screen to be displayed.                               
 *                                                                         
 *  ENTRY POINT: GetDBCSDisplayInfo                                        
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 261 )      
 *                                                                         
 *  INPUT: (Passed on stack)                                               
 *             FAR *Environment ( Environment buffer for the session )     
 *             FAR *ParmBlock                                              
 *                     USHORT Length = length of this packet               
 *                     USHORT Flags  = 0 - Environment buffer only         
 *                                     1 - Hardware also                   
 *                     USHORT TableLen                                     
 *                     USHORT TableOffset                                  
 *             ULONG Function ( Call vector table entry = 261 )            
 *                                                                         
 *  EXIT-NORMAL: AX = 0                                                    
 *               The DBCS display information is returned                  
 *                                                                         
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                               
 *                                                                         
 *  INTERNAL REFERENCES:                                                   
 *    ROUTINES: NONE                                                       
 *                                                                         
 *  EXTERNAL REFERENCES:                                                   
 *    ROUTINES: NONE                                                       
 *                                                                         
 ****************************************************************************/


USHORT EXPENTRY GetDBCSInfo(Environment,ParmBlock,Function)

  ENVIRONMENT far *Environment;
  VDH_DBCS far *ParmBlock;
  ULONG Function;

{
  USHORT rc;

  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
 
  if ((Function == FnGetDBCSDisplayInfo))
  {                                    /* Valid function request            */
    rc = NO_ERROR;                     /* Initialize no error               */
 
    if (ParmBlock->Length == 2)        /* user wants table size             */
      ParmBlock->Length = 6;           /* return ParmBlock size             */
 
    else
 
      if (ParmBlock->Length >= 6)      /* user wants info                   */
        ParmBlock->CellTableLen = 0;   /* no Double cell characters         */
 
      else
        rc = ERROR_VIO_INVALID_PARMS;  /* Initialize to error               */
  } 

  return (rc);
} 

/*****************************************************************************
 *                                                                             
 *  SUBROUTINE NAME: GetLVBInfo                                                
 *                                                                             
 *  DESCRIPTIVE NAME: Return LVB size and default attribute information        
 *                                                                             
 *  FUNCTION: GetLVBInfo is called by BVS to determine the size of the         
 *            LVB required for a given display size.  Based on the             
 *            mode and its associated LVB format the allocation size           
 *            of the LVB is returned.  Also a default attribute may            
 *            be returned.                                                     
 *                                                                             
 *  ENTRY POINT: GetLVBInfo                                                    
 *    LINKAGE:   CALL FAR ( via BVS-DDI call vector table entry 2xx )          
 *                                                                             
 *  INPUT: (Passed on stack)                                                   
 *             FAR *Environment ( Environment buffer for the session )         
 *             FAR *ParmBlock                                                  
 *                     USHORT Length = length of this packet                   
 *                     USHORT Flags  = 0 - Environment buffer only             
 *                                     1 - Hardware also                       
 *                     UCHAR  FormatId;                                        
 *                     UCHAR  AttrCount;                                       
 *                     USHORT LVBWidth;                                        
 *                     USHORT LVBHeight;                                       
 *                     ULONG  LVBSize;                                         
 *                     USHORT AttrBufSize;                                     
 *                     UCHAR far *AttrBufAddr;                                 
 *             ULONG Function ( Call vector table entry = 261 )                
 *                                                                             
 *  EXIT-NORMAL: AX = 0                                                        
 *               The correct size of the LVB is returned                       
 *                                                                             
 *  EXIT-ERROR: AX = ERROR_VIO_INVALID_PARMS                                   
 *                                                                             
 *  INTERNAL REFERENCES:                                                       
 *    ROUTINES: NONE                                                           
 *                                                                             
 *  EXTERNAL REFERENCES:                                                       
 *    ROUTINES: NONE                                                           
 *                                                                             
*****************************************************************************/


USHORT EXPENTRY GetLVBInfo(Environment,ParmBlock,Function)

  ENVIRONMENT far *Environment;
  VDH_LVB far *ParmBlock;
  ULONG Function;

{
  USHORT rc;
  USHORT i;
  USHORT size;                         
                                       /* another C runtime                 */

  rc = ERROR_VIO_INVALID_PARMS;        /* Initialize to error               */
 
  if ((Function == FnGetLVBInfo))
  {                                    /* Valid function request            */
 
    if (ParmBlock->Length >= MinGLen_LVB_Size)
    {                                  /* user wants LVB size               */
      rc = NO_ERROR;                   /* Initialize no error               */
      size = 2;
 
      if (((ParmBlock->FormatId  == WorldFormat) &&
           (ParmBlock->AttrCount == WorldAttrCount)) ||
          ((ParmBlock->FormatId  == 0) &&
           (ParmBlock->AttrCount == 0) &&
           (Environment->ModeData.fmt_ID == WorldFormat) &&
           (Environment->ModeData.attrib == WorldAttrCount)))
      {
        size = 4;
      } 
 
      if (ParmBlock->LVBWidth == 0)    /* cells width of LVB                */
        size *= Environment->ModeData.col;
 
      else
        size *= ParmBlock->LVBWidth;
 
      if (ParmBlock->LVBHeight == 0)   /* cells width of LVB                */
        size *= Environment->ModeData.row;
 
      else
        size *= ParmBlock->LVBHeight;

      ParmBlock->LVBSize = size;       /* size of the LVB                   */
 
      if (ParmBlock->Length >= MinGLen_LVB_AttrBufSize)
      {
 
        if (ParmBlock->AttrBufSize == 0)
          ParmBlock->AttrBufSize = Environment->AttrBufSize;
 
        else
 
          if (ParmBlock->AttrBufSize >= Environment->AttrBufSize)
          {
 
            if (ParmBlock->Length >= MinGLen_LVB_AttrBufAddr)
            {
 
              for (i = 0; i < Environment->AttrBufSize; i++)
                ParmBlock->AttrBufAddr[i] = Environment->AttrBuf[i];
            } 
 
            else
              rc = ERROR_VIO_INVALID_LENGTH;
          } 
 
          else
            rc = ERROR_VIO_INVALID_PARMS;
      } 
    } 
  } 

  return (rc);
} 

