Logo Search packages:      
Sourcecode: harbour version File versions  Download package

gtdos.c

/*
 * $Id: gtdos.c,v 1.34 2004/02/14 04:29:47 vszakats Exp $
 */

/*
 * Harbour Project source code:
 * Video subsystem for DOS compilers
 *
 * Copyright 1999 {list of individual authors and e-mail addresses}
 * www - http://www.harbour-project.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
 *
 * As a special exception, the Harbour Project gives permission for
 * additional uses of the text contained in its release of Harbour.
 *
 * The exception is that, if you link the Harbour libraries with other
 * files to produce an executable, this does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * Your use of that executable is in no way restricted on account of
 * linking the Harbour library code into it.
 *
 * This exception does not however invalidate any other reasons why
 * the executable file might be covered by the GNU General Public License.
 *
 * This exception applies only to the code released by the Harbour
 * Project under the name Harbour.  If you copy code from other
 * Harbour Project or Free Software Foundation releases into a copy of
 * Harbour, as the General Public License permits, the exception does
 * not apply to the code that you add in this way.  To avoid misleading
 * anyone as to the status of such modified files, you must delete
 * this exception notice from them.
 *
 * If you write modifications of your own for Harbour, it is your choice
 * whether to permit this exception to apply to your modifications.
 * If you do not wish that, delete this exception notice.
 *
 */

/*
 * The following parts are Copyright of the individual authors.
 * www - http://www.harbour-project.org
 *
 * Copyright 1999-2001 Viktor Szakats <viktor.szakats@syenar.hu>
 *    hb_gt_CtrlBrkHandler()
 *    hb_gt_CtrlBrkRestore()
 *
 * Copyright 1999 David G. Holm <dholm@jsd-llc.com>
 *    hb_gt_ReadKey()
 *
 * Copyright 2000 Alejandro de Garate <alex_degarate@hotmail.com>
 *    vmode12x40()
 *    vmode25x40()
 *    vmode28x40()
 *    vmode50x40()
 *    vmode12x80()
 *    vmode25x80()
 *    vmode28x80()
 *    vmode43x80()
 *    vmode50x80()
 *    hb_gt_SetMode()
 *    hb_gt_GetDisplay()
 *
 * See doc/license.txt for licensing terms.
 *
 */

/*
 *  This module is based on VIDMGR by Andrew Clarke and modified for
 *  the Harbour project
 */

/* NOTE: User programs should never call this layer directly! */

#include "hbapi.h"
#include "hbapigt.h"
#include "hbset.h" /* For Ctrl+Break handling */
#include "hbvm.h" /* For Ctrl+Break handling */
#include "inkey.ch"

#include <string.h>
#include <time.h>
#include <conio.h>

#if defined(__DJGPP__)
   #include <pc.h>
   #include <sys\exceptn.h>
   #include <sys\farptr.h>
#elif defined(_MSC_VER)
   #include <signal.h>
#endif

/* For screen support */
#if defined(__POWERC) || (defined(__TURBOC__) && !defined(__BORLANDC__)) || (defined(__ZTC__) && !defined(__SC__))
   #define FAR far
#elif defined(HB_OS_DOS) && !defined(__DJGPP__) && !defined(__RSX32__) && !defined(__WATCOMC__)
   #define FAR _far
#else
   #define FAR
#endif

#if !defined(__DJGPP__)
   #ifndef MK_FP
      #define MK_FP( seg, off ) \
         ((void FAR *)(((unsigned long)(seg) << 16)|(unsigned)(off)))
   #endif
#endif

static void hb_gt_xGetXY( USHORT cRow, USHORT cCol, BYTE * attr, BYTE * ch );
static void hb_gt_xPutch( USHORT cRow, USHORT cCol, BYTE attr, BYTE ch );

static char hb_gt_GetScreenMode( void );
static void hb_gt_SetCursorSize( char start, char end );
static void hb_gt_GetCursorSize( char * start, char * end );

#if defined(__WATCOMC__)
   #if defined(__386__)
      #define FAR
   #endif
   #include <signal.h>
#endif
#if !defined(__DJGPP__)
   static char FAR * scrnPtr;
   static char FAR * scrnStealth = NULL;
   static char FAR * hb_gt_ScreenAddress( void );
#endif

static BOOL s_bBreak; /* Used to signal Ctrl+Break to hb_inkeyPoll() */
static USHORT s_uiDispCount;

#if defined(__RSX32__)

static int kbhit( void )
{
   union REGS regs;

   regs.h.ah = 0x0B;
   HB_DOS_INT86( 0x21, &regs, &regs );

   return regs.HB_XREGS.ax;
}

#endif

#if !defined(__DJGPP__) && !defined(__RSX32__)
#if defined(__WATCOMC__) || defined(_MSC_VER)
static void hb_gt_CtrlBreak_Handler( int iSignal )
{
   /* Ctrl-Break was pressed */
   /* NOTE: the layout of this function is forced by the compiler
    */
   HB_SYMBOL_UNUSED( iSignal );
   s_bBreak = TRUE;
}
#else
static int s_iOldCtrlBreak = 0;

static int hb_gt_CtrlBrkHandler( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_CtrlBrkHandler()"));
   s_bBreak = TRUE;
   return 1;
}
#endif

static void hb_gt_CtrlBrkRestore( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_CtrlBrkRestore()"));
   #if defined(__WATCOMC__)
      signal( SIGBREAK, SIG_DFL );
   #elif defined(_MSC_VER)
      signal( SIGINT, SIG_DFL );
   #elif !defined(__RSX32__)
      setcbrk( s_iOldCtrlBreak );
   #endif
}
#endif

void hb_gt_Init( int iFilenoStdin, int iFilenoStdout, int iFilenoStderr )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Init()"));

   HB_SYMBOL_UNUSED( iFilenoStdin );
   HB_SYMBOL_UNUSED( iFilenoStdout );
   HB_SYMBOL_UNUSED( iFilenoStderr );

   s_bBreak = FALSE;
   s_uiDispCount = 0;

   /* Set the Ctrl+Break handler [vszakats] */

#if defined(__DJGPP__)

   gppconio_init();
   __djgpp_hwint_flags |= 2;     /* Count Ctrl+Break instead of killing program */
   __djgpp_set_ctrl_c( 0 );      /* Disable Ctrl+C */
   __djgpp_set_sigquit_key( 0 ); /* Disable Ctrl+\ */

#elif defined(__WATCOMC__)

   signal( SIGBREAK, hb_gt_CtrlBreak_Handler );
   atexit( hb_gt_CtrlBrkRestore );

#elif defined(_MSC_VER)

   signal( SIGINT, hb_gt_CtrlBreak_Handler );
   atexit( hb_gt_CtrlBrkRestore );

#elif defined(__RSX32__)

   /* TODO */

#else

   ctrlbrk( hb_gt_CtrlBrkHandler );
   s_iOldCtrlBreak = getcbrk();
   setcbrk( 1 );
   atexit( hb_gt_CtrlBrkRestore );

#endif

   /* */

#if !defined(__DJGPP__)
   scrnStealth = ( char * ) -1;
   scrnPtr = hb_gt_ScreenAddress();
#endif

   hb_mouse_Init();
}

void hb_gt_Exit( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Exit()"));

   hb_mouse_Exit();
#if !defined(__DJGPP__)
  if( scrnStealth != ( char * ) -1 )
     hb_xfree( scrnStealth );
#endif
}

int hb_gt_ExtendedKeySupport()
{
   return 0;
}
int hb_gt_ReadKey( HB_inkey_enum eventmask )
{
   int ch = 0;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_ReadKey(%d)", (int) eventmask));

#if defined(__DJGPP__)
   /* Check to see if Ctrl+Break has been detected */
   if( __djgpp_cbrk_count )
   {
      __djgpp_cbrk_count = 0; /* Indicate that Ctrl+Break has been handled */
      ch = HB_BREAK_FLAG; /* Note that Ctrl+Break was pressed */
   }
#else
   /* First check for Ctrl+Break, which is handled by gt/gtdos.c,
      with the exception of the DJGPP compiler */
   if( s_bBreak )
   {
      s_bBreak = FALSE; /* Indicate that Ctrl+Break has been handled */
      ch = HB_BREAK_FLAG; /* Note that Ctrl+Break was pressed */
   }
#endif
   else if( kbhit() )
   {
      /* A key code is available in the BIOS keyboard buffer, so read it */
#if defined(__DJGPP__)
      if( eventmask & INKEY_RAW ) ch = getxkey();
      else ch = getkey();
      if( ch == 256 )
         /* Ignore Ctrl+Break, because it is being handled as soon as it
            happens (see above) rather than waiting for it to show up in
            the keyboard input queue */
         ch = -1;
#else
      /* A key code is available in the BIOS keyboard buffer */
      ch = getch();                  /* Get the key code */
      if( ch == 0 && kbhit() )
      {
         /* It was a function key lead-in code, so read the actual
            function key and then offset it by 256 */
         ch = getch() + 256;
      }
      else if( ch == 224 && kbhit() )
      {
         /* It was an extended function key lead-in code, so read
            the actual function key and then offset it by 256,
            unless extended keyboard events are allowed, in which
            case offset it by 512 */
         if( eventmask & INKEY_RAW ) ch = getch() + 512;
         else ch = getch() + 256;
      }
#endif
   }

   /* Perform key translations */
   switch( ch )
   {
      case -1:  /* No key available */
         return 0;
      case 328:  /* Up arrow */
         ch = K_UP;
         break;
      case 336:  /* Down arrow */
         ch = K_DOWN;
         break;
      case 331:  /* Left arrow */
         ch = K_LEFT;
         break;
      case 333:  /* Right arrow */
         ch = K_RIGHT;
         break;
      case 327:  /* Home */
         ch = K_HOME;
         break;
      case 335:  /* End */
         ch = K_END;
         break;
      case 329:  /* Page Up */
         ch = K_PGUP;
         break;
      case 337:  /* Page Down */
         ch = K_PGDN;
         break;
      case 371:  /*  Ctrl + Left arrow */
         ch = K_CTRL_LEFT;
         break;
      case 372:  /* Ctrl + Right arrow */
         ch = K_CTRL_RIGHT;
         break;
      case 375:  /* Ctrl + Home */
         ch = K_CTRL_HOME;
         break;
      case 373:  /* Ctrl + End */
         ch = K_CTRL_END;
         break;
      case 388:  /* Ctrl + Page Up */
         ch = K_CTRL_PGUP;
         break;
      case 374:  /* Ctrl + Page Down */
         ch = K_CTRL_PGDN;
         break;
      case 338:  /* Insert */
         ch = K_INS;
         break;
      case 339:  /* Delete */
         ch = K_DEL;
         break;
      case 315:  /* F1 */
         ch = K_F1;
         break;
      case 316:  /* F2 */
      case 317:  /* F3 */
      case 318:  /* F4 */
      case 319:  /* F5 */
      case 320:  /* F6 */
      case 321:  /* F7 */
      case 322:  /* F8 */
      case 323:  /* F9 */
      case 324:  /* F10 */
         ch = 315 - ch;
         break;
      case 340:  /* Shift + F1 */
      case 341:  /* Shift + F2 */
      case 342:  /* Shift + F3 */
      case 343:  /* Shift + F4 */
      case 344:  /* Shift + F5 */
      case 345:  /* Shift + F6 */
      case 346:  /* Shift + F7 */
      case 347:  /* Shift + F8 */
      case 348:  /* Shift + F9 */
      case 349:  /* Shift + F10 */
      case 350:  /* Ctrl + F1 */
      case 351:  /* Ctrl + F2 */
      case 352:  /* Ctrl + F3 */
      case 353:  /* Ctrl + F4 */
      case 354:  /* Ctrl + F5 */
      case 355:  /* Ctrl + F6 */
      case 356:  /* Ctrl + F7 */
      case 357:  /* Ctrl + F8 */
      case 358:  /* Ctrl + F9 */
      case 359:  /* Ctrl + F10 */
      case 360:  /* Alt + F1 */
      case 361:  /* Alt + F2 */
      case 362:  /* Alt + F3 */
      case 363:  /* Alt + F4 */
      case 364:  /* Alt + F5 */
      case 365:  /* Alt + F6 */
      case 366:  /* Alt + F7 */
      case 367:  /* Alt + F8 */
      case 368:  /* Alt + F9 */
      case 369:  /* Alt + F10 */
         ch = 330 - ch;
         break;
      case 389:  /* F11 */
      case 390:  /* F12 */
      case 391:  /* Shift + F11 */
      case 392:  /* Shift + F12 */
      case 393:  /* Ctrl + F11 */
      case 394:  /* Ctrl + F12 */
      case 395:  /* Alt + F11 */
      case 396:  /* Alt + F12 */
         ch = 349 - ch;
   }

   return ch;
}

BOOL hb_gt_AdjustPos( BYTE * pStr, ULONG ulLen )
{
   union REGS regs;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_AdjustPos(%s, %lu)", pStr, ulLen ));

   HB_SYMBOL_UNUSED( pStr );
   HB_SYMBOL_UNUSED( ulLen );

   regs.h.ah = 0x03;
   regs.h.bh = 0;
   HB_DOS_INT86( 0x10, &regs, &regs );

   hb_gtSetPos( regs.h.dh, regs.h.dl );

   return TRUE;
}

BOOL hb_gt_IsColor( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_IsColor()"));

   return hb_gt_GetScreenMode() != 7;
}

#if !defined(__DJGPP__)
static char FAR * hb_gt_ScreenAddress()
{
   char FAR * ptr;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_ScreenAddress()"));

   #if defined(__WATCOMC__) && defined(__386__)
      if( hb_gt_IsColor() )
         ptr = ( char * ) ( 0xB800 << 4 );
      else
         ptr = ( char * )( 0xB000 << 4 );
   #else
      if( hb_gt_IsColor() )
         ptr = ( char FAR * ) MK_FP( 0xB800, 0x0000 );
      else
         ptr = ( char FAR * ) MK_FP( 0xB000, 0x0000 );
   #endif

   return ptr;
}
#endif

#if !defined(__DJGPP__)
char FAR * hb_gt_ScreenPtr( USHORT cRow, USHORT cCol )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_ScreenPtr(%hu, %hu)", cRow, cCol));

   return scrnPtr + ( cRow * hb_gt_GetScreenWidth() * 2 ) + ( cCol * 2 );
}
#endif

static char hb_gt_GetScreenMode( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetScreenMode()"));

#if defined(__WATCOMC__) && defined(__386__)
   return *( ( char * ) 0x0449 );
#elif defined(__DJGPP__)
   return _farpeekb( 0x0040, 0x0049 );
#else
   return *( ( char FAR * ) MK_FP( 0x0040, 0x0049 ) );
#endif
}

USHORT hb_gt_GetScreenWidth( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetScreenWidth()"));

#if defined(__WATCOMC__) && defined(__386__)
   return ( USHORT ) *( ( char * ) 0x044A );
#elif defined(__DJGPP__)
   return ( USHORT ) _farpeekb( 0x0040, 0x004A );
#else
   return ( USHORT ) *( ( char FAR * ) MK_FP( 0x0040, 0x004A ) );
#endif
}

USHORT hb_gt_GetScreenHeight( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetScreenHeigth()"));

#if defined(__WATCOMC__) && defined(__386__)
   return ( USHORT ) ( char ) ( *( ( char * ) 0x0484 ) + 1 );
#elif defined(__DJGPP__)
   return ( USHORT ) _farpeekb( 0x0040, 0x0084 ) + 1;
#else
   return ( USHORT ) ( ( char ) ( *( ( char FAR * ) MK_FP( 0x0040, 0x0084 ) ) + 1 ) );
#endif
}

void hb_gt_SetPos( SHORT iRow, SHORT iCol, SHORT iMethod )
{
   union REGS regs;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetPos(%hd, %hd, %hd)", iRow, iCol, iMethod));

   HB_SYMBOL_UNUSED( iMethod );

   regs.h.ah = 0x02;
   regs.h.bh = 0;
   regs.h.dh = ( BYTE ) iRow;
   regs.h.dl = ( BYTE ) iCol;
   HB_DOS_INT86( 0x10, &regs, &regs );
}

static void hb_gt_SetCursorSize( char start, char end )
{
   union REGS regs;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetCursorSize(%d, %d)", (int) start, (int) end));

   regs.h.ah = 0x01;
   regs.h.ch = start;
   regs.h.cl = end;
   HB_DOS_INT86( 0x10, &regs, &regs );
}

static void hb_gt_GetCursorSize( char * start, char *end )
{
   union REGS regs;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetCursorSize(%p, %p)", start, end));

   regs.h.ah = 0x03;
   regs.h.bh = 0;
   HB_DOS_INT86( 0x10, &regs, &regs );
   *start = regs.h.ch;
   *end = regs.h.cl;
}

USHORT hb_gt_GetCursorStyle( void )
{
   char start, end;
   int rc;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetCursorStyle()"));

   hb_gt_GetCursorSize( &start, &end );

   if( ( start == 32 ) && ( end == 32 ) )
      rc = SC_NONE;

   else if( ( start == 6 ) && ( end == 7 ) )
      rc = SC_NORMAL;

   else if( ( start == 4 ) && ( end == 7 ) )
      rc = SC_INSERT;

   else if( ( start == 0 ) && ( end == 7 ) )
      rc = SC_SPECIAL1;

   else if( ( start == 0 ) && ( end == 3 ) )
      rc = SC_SPECIAL2;

   else
      rc = SC_NONE;

   return rc;
}

void hb_gt_SetCursorStyle( USHORT style )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetCursorStyle(%hu)", style));

   switch( style )
   {
   case SC_NONE:
      hb_gt_SetCursorSize( 32, 32 );
      break;

   case SC_NORMAL:
      hb_gt_SetCursorSize( 6, 7 );
      break;

   case SC_INSERT:
      hb_gt_SetCursorSize( 4, 7 );
      break;

   case SC_SPECIAL1:
      hb_gt_SetCursorSize( 0, 7 );
      break;

   case SC_SPECIAL2:
      hb_gt_SetCursorSize( 0, 3 );
      break;

   default:
      break;
   }
}

static void hb_gt_xGetXY( USHORT cRow, USHORT cCol, BYTE * attr, BYTE * ch )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_xGetXY(%hu, %hu, %p, %p", cRow, cCol, ch, attr));

#if defined(__DJGPP__TEXT)
   {
     short ch_attr;
     gettext( cCol + 1, cRow + 1, cCol + 1, cRow + 1, &ch_attr );
     *ch = ch_attr >> 8;
     *attr = ch_attr & 0xFF;
   }
#elif defined(__DJGPP__)
   {
      ScreenGetChar( (int *)ch, (int *)attr, cCol, cRow );
   }
#else
   {
     char FAR *p;
     p = hb_gt_ScreenPtr( cRow, cCol );
     *ch = *p;
     *attr = *( p + 1 );
   }
#endif
}

static void hb_gt_xPutch( USHORT cRow, USHORT cCol, BYTE attr, BYTE ch )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_xPutch(%hu, %hu, %d, %d", cRow, cCol, (int) attr, (int) ch));

#if defined(__DJGPP__TEXT)
   {
     long ch_attr;
     ch_attr = ( ch << 8 ) | attr;
     puttext( cCol + 1, cRow + 1, cCol + 1, cRow + 1, &ch_attr );
   }
#elif defined(__DJGPP__)
   {
      ScreenPutChar( ch, attr, cCol, cRow );
   }
#else
   {
     USHORT FAR * p = (USHORT FAR *) hb_gt_ScreenPtr( cRow, cCol );
     *p = (attr << 8) + ch;
   }
#endif
}

void hb_gt_PutCharAttr( SHORT uiRow, SHORT uiCol, BYTE byChar, BYTE byAttr )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_PutCharAttr(%hu, %hu, %i, %d)", uiRow, uiCol, byChar, (int) byAttr));

#if defined(__DJGPP__TEXT)
   {
     long ch_attr = ( byChar << 8 ) | byAttr;
     puttext( uiCol + 1, uiRow + 1, uiCol + 1, uiRow + 1, &ch_attr );
   }
#elif defined(__DJGPP__)
   {
      ScreenPutChar( byChar, byAttr, uiCol, uiRow );
   }
#else
   {
     USHORT FAR * p = (USHORT FAR *) hb_gt_ScreenPtr( uiRow, uiCol );
     *p = (byAttr << 8) + byChar;
   }
#endif
}

void hb_gt_PutChar( SHORT uiRow, SHORT uiCol, BYTE byChar )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_PutChar(%hu, %hu, %i)", uiRow, uiCol, byChar));

   /* TODO */

   HB_SYMBOL_UNUSED( uiRow );
   HB_SYMBOL_UNUSED( uiCol );
   HB_SYMBOL_UNUSED( byChar );
}

void hb_gt_PutAttr( SHORT uiRow, SHORT uiCol, BYTE byAttr )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_PutAttr(%hu, %hu, %d)", uiRow, uiCol, (int) byAttr));

   /* TODO */

   HB_SYMBOL_UNUSED( uiRow );
   HB_SYMBOL_UNUSED( uiCol );
   HB_SYMBOL_UNUSED( byAttr );
}

void hb_gt_GetCharAttr( SHORT uiRow, SHORT uiCol, BYTE * pbyChar, BYTE * pbyAttr )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetCharAttr(%hu, %hu, %p, %p)", uiRow, uiCol, pbyChar, pbyAttr));

#if defined(__DJGPP__TEXT)
   {
     short ch_attr;
     gettext( uiCol + 1, uiRow + 1, uiCol + 1, uiRow + 1, &ch_attr );
     *pbyChar = ch_attr >> 8;
     *pbyAttr = ch_attr & 0xFF;
   }
#elif defined(__DJGPP__)
   {
      ScreenGetChar( (int *) pbyChar, (int *) pbyAttr, uiCol, uiRow );
   }
#else
   {
     char FAR *p = hb_gt_ScreenPtr( uiRow, uiCol );
     *pbyChar = *p;
     *pbyAttr = *( p + 1 );
   }
#endif
}

void hb_gt_GetChar( SHORT uiRow, SHORT uiCol, BYTE * pbyChar )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetChar(%hu, %hu, %p)", uiRow, uiCol, pbyChar));

   /* TODO */

   HB_SYMBOL_UNUSED( uiRow );
   HB_SYMBOL_UNUSED( uiCol );
   HB_SYMBOL_UNUSED( pbyChar );
}

void hb_gt_GetAttr( SHORT uiRow, SHORT uiCol, BYTE * pbyAttr )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetAttr(%hu, %hu, %p)", uiRow, uiCol, pbyAttr));

   /* TODO */

   HB_SYMBOL_UNUSED( uiRow );
   HB_SYMBOL_UNUSED( uiCol );
   HB_SYMBOL_UNUSED( pbyAttr );
}

void hb_gt_Puts( USHORT cRow, USHORT cCol, BYTE attr, BYTE *str, ULONG len )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Puts(%hu, %hu, %d, %p, %lu", cRow, cCol, (int) attr, str, len));

#if defined(__DJGPP__TEXT)
   {
     int i;
     int bottom, left, right, top;
     int width;
     BYTE * ch_attr;
     BYTE * ptr;

     i = ( int ) len;
     left = cCol;
     top = cRow;
     width = hb_gt_GetScreenWidth();
     ptr = ch_attr = hb_xgrab( i * 2 );
     while( i-- )
       {
         *ptr++ = *str++;
         *ptr++ = attr;
       }
     i = len - 1; /* We want end position, not next cursor position */
     right = left;
     bottom = top;
     if( right + i > width - 1 )
       {
         /*
          * Calculate end row position and the remainder size for the
          * end column adjust.
          */
         bottom += ( i / width );
         i = i % width;
       }
     right += i;
     if( right > width - 1 )
       {
         /* Column movement overflows into next row */
         bottom++;
         right -= width;
       }
     puttext( left + 1, top + 1, right + 1, bottom + 1, ch_attr );
     hb_xfree( ch_attr );
   }
#elif defined(__DJGPP__)
   {
      int i;
      for( i=0; i<len; i++ )
         ScreenPutChar( str[ i ], attr, cCol++, cRow );
   }
#else
   {
      USHORT FAR *p;
      register USHORT byAttr = attr << 8;

      p = (USHORT FAR *) hb_gt_ScreenPtr( cRow, cCol );
      while( len-- )
      {
         *p++ = byAttr + (*str++);
      }
   }
#endif
}

int hb_gt_RectSize( USHORT rows, USHORT cols )
{
   return rows * cols * 2;
}

void hb_gt_GetText( USHORT usTop, USHORT usLeft, USHORT usBottom, USHORT usRight, BYTE * dest )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetText(%hu, %hu, %hu, %hu, %p", usTop, usLeft, usBottom, usRight, dest));

#if defined(__DJGPP__TEXT) || defined(__DJGPP__)
   {
     gettext( usLeft + 1, usTop + 1, usRight + 1, usBottom + 1, dest );
   }
#else
   {
     USHORT x, y;

     for( y = usTop; y <= usBottom; y++ )
       {
         for( x = usLeft; x <= usRight; x++ )
           {
             hb_gt_xGetXY( y, x, dest + 1, dest );
             dest += 2;
           }
       }
   }
#endif
}

void hb_gt_PutText( USHORT usTop, USHORT usLeft, USHORT usBottom, USHORT usRight, BYTE * srce )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_PutText(%hu, %hu, %hu, %hu, %p", usTop, usLeft, usBottom, usRight, srce));

#if defined(__DJGPP__TEXT) || defined(__DJGPP__)
   {
     puttext( usLeft + 1, usTop + 1, usRight + 1, usBottom + 1, srce );
   }
#else
   {
     USHORT x, y;

     for( y = usTop; y <= usBottom; y++ )
       {
         for( x = usLeft; x <= usRight; x++ )
           {
             hb_gt_xPutch( y, x, *( srce + 1 ), *srce );
             srce += 2;
           }
       }
   }
#endif
}

void hb_gt_SetAttribute( USHORT usTop, USHORT usLeft, USHORT usBottom, USHORT usRight, BYTE attr )
{
   USHORT x, y;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetAttribute(%hu, %hu, %hu, %hu, %d", usTop, usLeft, usBottom, usRight, (int) attr));

   for( y = usTop; y <= usBottom; y++ )
   {
      BYTE scratchattr;
      BYTE ch;

      for( x = usLeft; x <= usRight; x++ )
      {
         hb_gt_xGetXY( y, x, &scratchattr, &ch );
         hb_gt_xPutch( y, x, attr, ch );
      }
   }
}

SHORT hb_gt_Col( void )
{
   union REGS regs;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Col()"));

   regs.h.ah = 0x03;
   regs.h.bh = 0;
   HB_DOS_INT86( 0x10, &regs, &regs );

   return regs.h.dl;
}

SHORT hb_gt_Row( void )
{
   union REGS regs;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Row()"));

   regs.h.ah = 0x03;
   regs.h.bh = 0;
   HB_DOS_INT86( 0x10, &regs, &regs );

   return regs.h.dh;
}

void hb_gt_Scroll( USHORT usTop, USHORT usLeft, USHORT usBottom, USHORT usRight, BYTE attr, SHORT sVert, SHORT sHoriz )
{
   int iRows = sVert, iCols = sHoriz;

   /* NOTE: 'SHORT' is used intentionally to correctly compile
   *  with C++ compilers
   */
   SHORT usRow, usCol;
   UINT uiSize;
   int iLength = ( usRight - usLeft ) + 1;
   int iCount, iColOld, iColNew, iColSize;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Scroll(%hu, %hu, %hu, %hu, %d, %hd, %hd)", usTop, usLeft, usBottom, usRight, (int) attr, sVert, sHoriz));

   hb_gtGetPos( &usRow, &usCol );

   if( hb_gtRectSize( usTop, usLeft, usBottom, usRight, &uiSize ) == 0 )
   {
      /* NOTE: 'unsigned' is used intentionally to correctly compile
       * with C++ compilers
       */
      unsigned char * fpBlank = ( unsigned char * ) hb_xgrab( iLength );
      unsigned char * fpBuff = ( unsigned char * ) hb_xgrab( iLength * 2 );

      memset( fpBlank, ' ', iLength );

      iColOld = iColNew = usLeft;
      if( iCols >= 0 )
      {
         iColOld += iCols;
         iColSize = ( int ) ( usRight - usLeft );
         iColSize -= iCols;
      }
      else
      {
         iColNew -= iCols;
         iColSize = ( int ) ( usRight - usLeft );
         iColSize += iCols;
      }

      for( iCount = ( iRows >= 0 ? usTop : usBottom );
           ( iRows >= 0 ? iCount <= usBottom : iCount >= usTop );
           ( iRows >= 0 ? iCount++ : iCount-- ) )
      {
         int iRowPos = iCount + iRows;

         /* Blank the scroll region in the current row */
         hb_gt_Puts( iCount, usLeft, attr, fpBlank, iLength );

         if( ( iRows || iCols ) && iRowPos <= usBottom && iRowPos >= usTop )
         {
            /* Read the text to be scrolled into the current row */
            hb_gt_GetText( iRowPos, iColOld, iRowPos, iColOld + iColSize, fpBuff );

            /* Write the scrolled text to the current row */
            hb_gt_PutText( iCount, iColNew, iCount, iColNew + iColSize, fpBuff );
         }
      }

      hb_xfree( fpBlank );
      hb_xfree( fpBuff );
   }

   hb_gtSetPos( usRow, usCol );
}

void hb_gt_DispBegin( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_DispBegin()"));

/* ptucker */
#if !defined(__DJGPP__)
   if( ++s_uiDispCount == 1 )
   {
      char FAR * ptr;
      ULONG nSize;

      nSize = hb_gt_GetScreenWidth() * hb_gt_GetScreenHeight() * 2;

      ptr = scrnPtr;
      if( ( scrnPtr = scrnStealth ) == ( char * ) -1 )
         scrnPtr = ( char FAR * ) hb_xgrab( nSize );
      scrnStealth = ptr;
      memcpy( ( void * ) scrnPtr, ( void * ) ptr, nSize );
   }
#endif
}

void hb_gt_DispEnd( void )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_DispEnd()"));

/* ptucker */
#if !defined(__DJGPP__)
   if( --s_uiDispCount == 0 )
   {
      char FAR * ptr;
      ULONG nSize;

      nSize = hb_gt_GetScreenWidth() * hb_gt_GetScreenHeight() * 2;

      ptr = scrnPtr;
      scrnPtr = scrnStealth;
      scrnStealth = ptr;
      memcpy( ( void * ) scrnPtr, ( void * )ptr, nSize );
   }
#endif
}

BOOL hb_gt_GetBlink()
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_GetBlink()"));

#if defined(__WATCOMC__) && defined(__386__)
   return *( ( char * ) 0x0465 ) & 0x10;
#elif defined(__DJGPP__)
   return _farpeekb( 0x0040, 0x0065 ) & 0x10;
#else
   return *( ( char FAR * ) MK_FP( 0x0040, 0x0065 ) ) &0x10;
#endif
}

void hb_gt_SetBlink( BOOL bBlink )
{
   union REGS regs;

   HB_TRACE(HB_TR_DEBUG, ("hb_gt_SetBlink(%d)", (int) bBlink));

   regs.h.ah = 0x10;
   regs.h.al = 0x03;
   regs.h.bh = 0;
   regs.h.bl = bBlink;
   HB_DOS_INT86( 0x10, &regs, &regs );
}

void hb_gt_Tone( double dFrequency, double dDuration )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Tone(%lf, %lf)", dFrequency, dDuration));

   /* The conversion from Clipper timer tick units to
      milliseconds is * 1000.0 / 18.2. */

   dFrequency = HB_MIN( HB_MAX( 0.0, dFrequency ), 32767.0 );
   dDuration = dDuration * CLOCKS_PER_SEC / 18.2 ; /* clocks */

#if defined(__BORLANDC__) || defined(__WATCOMC__)
   sound( ( unsigned ) dFrequency );
#elif defined(__DJGPP__)
   sound( ( int ) dFrequency );
#endif

   while( dDuration > 0.0 )
   {
      /* Use USHORT, because this variable gets added to clock()
         to form end_clock and we want to minimize overflow risk */
      USHORT temp = ( USHORT ) HB_MIN( HB_MAX( 0, dDuration ), USHRT_MAX );
      clock_t end_clock;

      dDuration -= temp;
      if( temp <= 0 )
      {
         /* Ensure that the loop gets terminated when
            only a fraction of the delay time remains. */
         dDuration = -1.0;
      }
      else
      {
         /* Note: delay() in <dos.h> for DJGPP does not work and
                  delay() in <dos.h> for BORLANDC is not multi-
                  tasking friendly. */
         end_clock = clock() + temp;
         while( clock() < end_clock )
            hb_idleState();
      }
   }

#if defined(__BORLANDC__) || defined(__WATCOMC__)
   nosound();
#elif defined(__DJGPP__)
   sound( 0 );
#endif
}

char * hb_gt_Version( void )
{
   return "Harbour Terminal: DOS console";
}

USHORT hb_gt_DispCount()
{
   return s_uiDispCount;
}

void hb_gt_Replicate( USHORT uiRow, USHORT uiCol, BYTE byAttr, BYTE byChar, ULONG nLength )
{
   HB_TRACE(HB_TR_DEBUG, ("hb_gt_Replicate(%hu, %hu, %i, %i, %lu)", uiRow, uiCol, byAttr, byChar, nLength));

#if defined(__DJGPP__TEXT)
   {
     int i;
     int bottom, left, right, top;
     int width;
     BYTE * ch_attr;
     BYTE * ptr;

     i = ( int ) nLength;
     left = cCol;
     top = cRow;
     width = hb_gt_GetScreenWidth();
     ptr = ch_attr = hb_xgrab( i * 2 );
     while( i-- )
       {
         *ptr++ = byChar;
         *ptr++ = byAttr;
       }
     i = nLength - 1; /* We want end position, not next cursor position */
     right = left;
     bottom = top;
     if( right + i > width - 1 )
       {
         /*
          * Calculate end row position and the remainder size for the
          * end column adjust.
          */
         bottom += ( i / width );
         i = i % width;
       }
     right += i;
     if( right > width - 1 )
       {
         /* Column movement overflows into next row */
         bottom++;
         right -= width;
       }
     puttext( left + 1, top + 1, right + 1, bottom + 1, ch_attr );
     hb_xfree( ch_attr );
   }
#elif defined(__DJGPP__)
   {
      while( nLength-- )
         ScreenPutChar( byChar, byAttr, uiCol++, uiRow );
   }
#else
   {
      USHORT FAR *p;
      USHORT byte = (byAttr << 8) + byChar;

      p = (USHORT FAR *) hb_gt_ScreenPtr( uiRow, uiCol );
      while( nLength-- )
      {
         *p++ = byte;
      }
   }
#endif
}

USHORT hb_gt_Box( SHORT Top, SHORT Left, SHORT Bottom, SHORT Right,
                  BYTE * szBox, BYTE byAttr )
{
   USHORT ret = 1;
   SHORT Row;
   SHORT Col;
   SHORT Height;
   SHORT Width;

   if( Left >= 0 || Left < hb_gt_GetScreenWidth()
   || Right >= 0 || Right < hb_gt_GetScreenWidth()
   || Top >= 0 || Top < hb_gt_GetScreenHeight()
   || Bottom >= 0 || Bottom < hb_gt_GetScreenHeight() )
   {

      /* Ensure that box is drawn from top left to bottom right. */
      if( Top > Bottom )
      {
         SHORT tmp = Top;
         Top = Bottom;
         Bottom = tmp;
      }
      if( Left > Right )
      {
         SHORT tmp = Left;
         Left = Right;
         Right = tmp;
      }

      /* Draw the box or line as specified */
      Height = Bottom - Top + 1;
      Width  = Right - Left + 1;

      hb_gt_DispBegin();

      if( Height > 1 && Width > 1 && Top >= 0 && Top < hb_gt_GetScreenHeight() && Left >= 0 && Left < hb_gt_GetScreenWidth() )
         hb_gt_xPutch( Top, Left, byAttr, szBox[ 0 ] ); /* Upper left corner */

      Col = ( Height > 1 ? Left + 1 : Left );
      if(Col < 0 )
      {
         Width += Col;
         Col = 0;
      }
      if( Right >= hb_gt_GetScreenWidth() )
      {
         Width -= Right - hb_gt_GetScreenWidth();
      }

      if( Col <= Right && Col < hb_gt_GetScreenWidth() && Top >= 0 && Top < hb_gt_GetScreenHeight() )
         hb_gt_Replicate( Top, Col, byAttr, szBox[ 1 ], Width + ( (Right - Left) > 1 ? -2 : 0 ) ); /* Top line */

      if( Height > 1 && (Right - Left) > 1 && Right < hb_gt_GetScreenWidth() && Top >= 0 && Top < hb_gt_GetScreenHeight() )
         hb_gt_xPutch( Top, Right, byAttr, szBox[ 2 ] ); /* Upper right corner */

      if( szBox[ 8 ] && Height > 2 && Width > 2 )
      {
         for( Row = Top + 1; Row < Bottom; Row++ )
         {
            if( Row >= 0 && Row < hb_gt_GetScreenHeight() )
            {
               Col = Left;
               if( Col < 0 )
                  Col = 0; /* The width was corrected earlier. */
               else
                  hb_gt_xPutch( Row, Col++, byAttr, szBox[ 7 ] ); /* Left side */
               hb_gt_Replicate( Row, Col, byAttr, szBox[ 8 ], Width - 2 ); /* Fill */
               if( Right < hb_gt_GetScreenWidth() )
                  hb_gt_xPutch( Row, Right, byAttr, szBox[ 3 ] ); /* Right side */
            }
         }
      }
      else
      {
         for( Row = ( Width > 1 ? Top + 1 : Top ); Row < ( (Right - Left ) > 1 ? Bottom : Bottom + 1 ); Row++ )
         {
            if( Row >= 0 && Row < hb_gt_GetScreenHeight() )
            {
               if( Left >= 0 && Left < hb_gt_GetScreenWidth() )
                  hb_gt_xPutch( Row, Left, byAttr, szBox[ 7 ] ); /* Left side */
               if( ( Width > 1 || Left < 0 ) && Right < hb_gt_GetScreenWidth() )
                  hb_gt_xPutch( Row, Right, byAttr, szBox[ 3 ] ); /* Right side */
            }
         }
      }

      if( Height > 1 && Width > 1 )
      {
         if( Left >= 0 && Bottom < hb_gt_GetScreenHeight() )
            hb_gt_xPutch( Bottom, Left, byAttr, szBox[ 6 ] ); /* Bottom left corner */

         Col = Left + 1;
         if( Col < 0 )
            Col = 0; /* The width was corrected earlier. */

         if( Col <= Right && Bottom < hb_gt_GetScreenHeight() )
            hb_gt_Replicate( Bottom, Col, byAttr, szBox[ 5 ], Width - 2 ); /* Bottom line */

         if( Right < hb_gt_GetScreenWidth() && Bottom < hb_gt_GetScreenHeight() )
            hb_gt_xPutch( Bottom, Right, byAttr, szBox[ 4 ] ); /* Bottom right corner */
      }
      hb_gt_DispEnd();
      ret = 0;
   }

   return ret;
}

USHORT hb_gt_BoxD( SHORT Top, SHORT Left, SHORT Bottom, SHORT Right, BYTE * pbyFrame, BYTE byAttr )
{
   return hb_gt_Box( Top, Left, Bottom, Right, pbyFrame, byAttr );
}

USHORT hb_gt_BoxS( SHORT Top, SHORT Left, SHORT Bottom, SHORT Right, BYTE * pbyFrame, BYTE byAttr )
{
   return hb_gt_Box( Top, Left, Bottom, Right, pbyFrame, byAttr );
}

USHORT hb_gt_HorizLine( SHORT Row, SHORT Left, SHORT Right, BYTE byChar, BYTE byAttr )
{
   USHORT ret = 1;
   if( Row >= 0 && Row < hb_gt_GetScreenHeight() )
   {
      if( Left < 0 )
         Left = 0;
      else if( Left >= hb_gt_GetScreenWidth() )
         Left = hb_gt_GetScreenWidth() - 1;
   
      if( Right < 0 )
         Right = 0;
      else if( Right >= hb_gt_GetScreenWidth() )
         Right = hb_gt_GetScreenWidth() - 1;

      if( Left < Right )
         hb_gt_Replicate( Row, Left, byAttr, byChar, Right - Left + 1 );
      else
         hb_gt_Replicate( Row, Right, byAttr, byChar, Left - Right + 1 );
      ret = 0;
   }
   return ret;
}

USHORT hb_gt_VertLine( SHORT Col, SHORT Top, SHORT Bottom, BYTE byChar, BYTE byAttr )
{
   USHORT ret = 1;
   SHORT Row;

   if( Col >= 0 && Col < hb_gt_GetScreenWidth() )
   {
      if( Top < 0 )
         Top = 0;
      else if( Top >= hb_gt_GetScreenHeight() )
         Top = hb_gt_GetScreenHeight() - 1;

      if( Bottom < 0 )
         Bottom = 0;
      else if( Bottom >= hb_gt_GetScreenHeight() )
         Bottom = hb_gt_GetScreenHeight() - 1;

      if( Top <= Bottom )
         Row = Top;
      else
      {
         Row = Bottom;
         Bottom = Top;
      }
      while( Row <= Bottom )
         hb_gt_xPutch( Row++, Col, byAttr, byChar );
      ret = 0;
   }
   return ret;
}

/* some definitions */
#define INT_VIDEO    0x10

#if defined(__DJGPP__)
   #define POKE_BYTE( s, o, b ) /* Do nothing */
   #define outport outportw     /* Use correct function name */
#elif defined(__RSX32__)
   #define inportb( p ) 0       /* Return 0 */
   #define outport( p, w )      /* Do nothing */
   #define outportb( p, b )     /* Do nothing */
   #define POKE_BYTE( s, o, b )  (*((BYTE FAR *)MK_FP((s),(o)) )=(BYTE)(b))
#elif defined(__WATCOMC__)
   #define outportb outp        /* Use correct function name */
   #define outport outpw        /* Use correct function name */
   #define inport inpw          /* Use correct function name */
   #define inportb inp          /* Use correct function name */
   #define POKE_BYTE( s, o, b )  (*((BYTE FAR *)MK_FP((s),(o)) )=(BYTE)(b))
#else
   #define POKE_BYTE( s, o, b )  (*((BYTE FAR *)MK_FP((s),(o)) )=(BYTE)(b))
#endif

static void vmode12x40( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x0001;               /* video mode 40 cols */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   outportb( 0x03D4, 0x09 );         /* update cursor size / pointers */
   regs.h.al = ( inportb( 0x03D5 ) | 0x80 );
   outportb( 0x03D5, regs.h.al );
   POKE_BYTE( 0x40, 0x84, 11);       /* 11 rows number update */
}

static void vmode25x40( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x0001;
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
}

static void vmode28x40( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x0001;               /* video mode 40 cols */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.bx = 0;                    /* load block 0 (BL = 0) */
   regs.HB_XREGS.ax = 0x1111;               /* load 8x8 monochrome char set into RAM */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
}

static void vmode50x40( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x0001;
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.bx = 0;                    /* load block 0 (BL = 0) */
   regs.HB_XREGS.ax = 0x1112;               /* load 8x8 double dot char set into RAM */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   outport( 0x03D4, 0x060A );
}

static void vmode12x80( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x0003;                  /* mode in AL, if bit 7 is on, No CLS */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   outportb( 0x03D4, 0x09 );            /* update cursor size / pointers */
   regs.h.al = ( inportb( 0x03D5 ) | 0x80 );
   outportb( 0x03D5, regs.h.al );
   POKE_BYTE( 0x40, 0x84, 11);          /* 11 rows number update */
}

static void vmode25x80( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x1202;              /* select 350 scan line mode */
   regs.h.bl = 0x30;
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.ax = 0x0083;              /* mode in AL, if higher bit is on, No CLS */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.bx = 0;                   /* load block 0 (BL = 0) */
   regs.HB_XREGS.ax = 0x1114;              /* load 8x14 VGA char set into RAM */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
}

static void vmode28x80( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x0003;              /* mode in AL, if higher bit is on, No CLS */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.bx = 0;                   /* load block 0 (BL = 0) */
   regs.HB_XREGS.ax = 0x1111;              /* load 8x8 monochrome char set into RAM */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
}

static void vmode43x80( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x1201;              /*  select 350 scan line mode */
   regs.h.bl = 0x30;
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.ax = 0x0003;              /* mode in AL, if higher bit is on, No CLS */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.h.bh = 0x1;                 /* bytes per character */
   regs.h.bl = 0x0;                 /* load block 0 */
   regs.HB_XREGS.ax = 0x1112;              /* load 8x8 double dot char set into RAM */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   outport( 0x03D4, 0x060A );       /* update cursor size / pointers */
   POKE_BYTE( 0x40, 0x84, 42);      /* 42 rows number update */
}

static void vmode50x80( void )
{
   union REGS regs;
   regs.HB_XREGS.ax = 0x1202;               /*  select 400 scan line mode */
   regs.h.bl = 0x30;
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.ax = 0x0003;               /* mode in AL, if bit 7 is on, No CLS */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
   regs.HB_XREGS.bx = 0;                    /* load block 0 (BL = 0) */
   regs.HB_XREGS.ax = 0x1112;               /* load 8x8 double dot char set into RAM */
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);
}

/***************************************************************************
 * Return the display combination: monitor + video card
 *
 * INT 10 - VIDEO - GET DISPLAY COMBINATION CODE (PS,VGA/MCGA)
 *         AX = 1A00h
 * Return: AL = 1Ah if function was supported
 *         BL = active display code (see below)
 *         BH = alternate display code
 *
 * Values for display combination code:
 *  00h    no display
 *  01h    monochrome adapter w/ monochrome display
 *  02h    CGA w/ color display
 *  03h    reserved
 *  04h    EGA w/ color display
 *  05h    EGA w/ monochrome display
 *  06h    PGA w/ color display
 *  07h    VGA w/ monochrome analog display
 *  08h    VGA w/ color analog display
 *  09h    reserved
 *  0Ah    MCGA w/ digital color display
 *  0Bh    MCGA w/ monochrome analog display
 *  0Ch    MCGA w/ color analog display
 *  FFh    unknown display type
 ****************************************************************************/

static USHORT hb_gt_GetDisplay( void )
{
   union REGS regs;

   regs.HB_XREGS.ax = 0x1A00;
   HB_DOS_INT86( INT_VIDEO, &regs, &regs);

   return ( regs.h.al == 0x1A ) ? regs.h.bl : 0xFF;
}

BOOL hb_gt_SetMode( USHORT uiRows, USHORT uiCols )
{
   /* hb_gt_IsColor() test for color card, we need to know if it is a VGA board...*/
   BOOL bIsVGA     = ( hb_gt_GetDisplay() == 8 );
   BOOL bIsVesa    = FALSE;
   USHORT bSuccess = FALSE;

   HB_TRACE( HB_TR_DEBUG, ("hb_gt_SetMode(%hu, %hu)", usRows, usCols) );

   /* Available modes in B&N and color screens */
   if( uiCols == 40 )
   {
      if( uiRows == 12 )
          vmode12x40();

      if( uiRows == 25 )
          vmode25x40();

      if( uiRows == 28 )
          vmode28x40();

      if( uiRows == 50 )
          vmode50x40();
   }

   if( bIsVGA )
   {
      if( uiCols == 80)
      {
         if( uiRows == 12 )
             vmode12x80();

         if( uiRows == 25 )
             vmode25x80();

         if( uiRows == 28 )
             vmode28x80();

         if( uiRows == 43 )
             vmode43x80();

         if( uiRows == 50 )
             vmode50x80();
      }

      if( uiCols > 80 && bIsVesa )
      {
         /* In development process
          * return( hb_gt_Modevesa( nMode) );
          */
      }
   }

   /* Check for succesful */

   if( ( hb_gtMaxRow() == uiRows - 1 ) &&
       ( hb_gtMaxCol() == uiCols - 1 ) )
   {
      bSuccess = TRUE;
   }
   else
   {
      vmode25x80();
      bSuccess = FALSE;
   }

   return bSuccess;
}

BOOL hb_gt_PreExt()
{
   return TRUE;
}

BOOL hb_gt_PostExt()
{
   return TRUE;
}

BOOL hb_gt_Suspend()
{
   return TRUE;
}

BOOL hb_gt_Resume()
{
   return TRUE;
}

Generated by  Doxygen 1.6.0   Back to index