/*
 * QT Console
 *
 * Copyright 2013 Przemyslaw Czerpak <druzus /at/ priv.onet.pl>
 * Slightly based on GTQTC
 * Copyright 2009-2011 Pritpal Bedi <pritpal@vouchcac.com>
 *
 * 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 program; see the file LICENSE.txt.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
 *
 * 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.
 *
 */

#include "gtqtc.h"

static  int                   s_GtId;
static  HB_GT_FUNCS           SuperTable;
#define HB_GTSUPER            ( &SuperTable )
#define HB_GTID_PTR           ( &s_GtId )

#define HB_GTQTC_GET( p )     ( static_cast< PHB_GTQTC >( HB_GTLOCAL( p ) ) )


#if defined( HB_OS_UNIX )
#  if ! defined( HB_QT_NEEDLOCKS )
#     define HB_QT_NEEDLOCKS
#  endif
#  if ! defined( HB_XLIB_NEEDLOCKS )
/* #     define HB_XLIB_NEEDLOCKS */
#  endif
#endif

#ifdef HB_QT_NEEDLOCKS
#  if QT_VERSION >= 0x060000
      static QRecursiveMutex s_qMtx;
#  else
      static QMutex s_qMtx( QMutex::Recursive );
#  endif
#  define HB_QTC_LOCK()       do { s_qMtx.lock()
#  define HB_QTC_UNLOCK()     s_qMtx.unlock(); } while( 0 )
#else
#  define HB_QTC_LOCK()       do {} while( 0 )
#  define HB_QTC_UNLOCK()     do {} while( 0 )
#endif

static QApplication * s_qtapp = NULL;

/* --- */

static void hb_gt_qtc_appFree( void * cargo )
{
   HB_SYMBOL_UNUSED( cargo );

   s_qtapp->quit();
   delete s_qtapp;
   s_qtapp = NULL;
}

static void hb_gt_qtc_itemGetQString( PHB_ITEM pItem, QString * pqStr )
{
   const HB_WCHAR * wStr;
   HB_SIZE nSize;
   void * hStr;

   if( ( wStr = hb_itemGetStrU16( pItem, HB_CDP_ENDIAN_NATIVE, &hStr, &nSize ) ) != NULL )
   {
#if defined( HB_OS_WIN )
      * pqStr = QString::fromWCharArray( wStr, nSize );
#elif QT_VERSION >= 0x060000
      * pqStr = QString::fromUtf16( ( char16_t * ) wStr, nSize );
#else
      * pqStr = QString::fromUtf16( wStr, nSize );
#endif
      hb_strfree( hStr );
   }
}

static PHB_ITEM hb_gt_qtc_itemPutQString( PHB_ITEM pItem, const QString * pqStr )
{
#if defined( HB_OS_WIN )
   return hb_itemPutStrLenU16( pItem, HB_CDP_ENDIAN_NATIVE,
                               reinterpret_cast< const HB_WCHAR * >( pqStr->utf16() ),
                               pqStr->size() );
#else
   return hb_itemPutStrLenU16( pItem, HB_CDP_ENDIAN_NATIVE,
                               pqStr->utf16(), pqStr->size() );
#endif
}

/* --- */

#define hb_bm_paint_begin( qBitMap )         do { \
            QPainter painter( qBitMap ); \
            painter.setBackgroundMode( Qt::OpaqueMode ); \
            painter.setBrush( Qt::SolidPattern ); \
            painter.setPen( Qt::SolidLine )

#define hb_bm_paint_end()           } while( 0 )

#define hb_bm_color( c )                  painter.setPen( QTC_NUM2RGB( c ) )
#define hb_bm_rect( x, y, w, h )          painter.drawRect( x, y, w, h )
#define hb_bm_fillrectc( x, y, w, h, c )  painter.fillRect( x, y, w, h, QTC_NUM2RGB( c ) )

#define hb_bm_line( x1, y1, x2, y2 )      painter.drawLine( x1, y1, x2, y2 )
#define hb_bm_point( x, y )               painter.drawPoint( x, y )
#define hb_bm_fillrect( x, y, w, h )      painter.fillRect( x, y, w, h, Qt::color1 )
#define hb_bm_polygon( pts, n )           painter.drawPolygon( pts, n )
#define hb_bm_invertrect( x, y, w, h )    do { \
               painter.setCompositionMode( QPainter::RasterOp_SourceXorDestination ); \
               painter.fillRect( 0, 0, w, h, Qt::color1 ); \
            } while( 0 )
#define hb_bm_text( ch )                  do { \
               QPainter painter( qBitMap ); \
               painter.setBackgroundMode( Qt::OpaqueMode ); \
               painter.setFont( QFont( pQTC->qWnd->qConsole->font, painter.device() ) ); \
               painter.drawText( 0, pQTC->fontAscent, QString( ch ) ); \
            } while( 0 )

static QBitmap * hb_gt_qtc_bitmap_char( int cellx, int celly )
{
   QBitmap * qBitMap = new QBitmap( cellx, celly );
   qBitMap->clear();
   return qBitMap;
}

static QBitmap * hb_gt_qtc_defineBoxButtonL( int cellx, int celly )
{
   QBitmap * qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );

   hb_bm_paint_begin( qBitMap );

   hb_bm_line( cellx - 1, 0, 0, 0 );
   hb_bm_line( 0, 0, 0, celly - 1 );
   hb_bm_line( 0, celly - 1, cellx - 1, celly - 1 );

   hb_bm_line( 2, celly - 2, cellx - 1, celly - 2 );

   hb_bm_paint_end();

   return qBitMap;
}

static QBitmap * hb_gt_qtc_defineBoxButtonR( int cellx, int celly )
{
   QBitmap * qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );

   hb_bm_paint_begin( qBitMap );

   hb_bm_line( 0, 0, cellx - 1, 0 );
   hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
   hb_bm_line( cellx - 1, celly - 1, 0, celly - 1 );

   hb_bm_line( cellx - 2, 3, cellx - 2, celly - 2 );
   hb_bm_line( cellx - 2, celly - 2, 0, celly - 2 );

   hb_bm_paint_end();

   return qBitMap;
}

static QBitmap * hb_gt_qtc_defineBoxChar( PHB_GTQTC pQTC, HB_USHORT usCh )
{
   QBitmap * qBitMap = NULL;
   int cellx = pQTC->cellX;
   int celly = pQTC->cellY;
   int i, y, x, yy, xx;
   QPoint pts[ 3 ];

   if( usCh >= HB_BOXCH_RC_MIN && usCh <= HB_BOXCH_RC_MAX )
      switch( usCh )
      {
         case HB_BOXCH_RC_ARROW_DL:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = celly / 2 - 1;
            for( y = celly - 4, x = cellx - 1; x >= 3 && y >= yy; --x, --y )
               hb_bm_line( x, y, cellx - 1, y );
            xx = HB_MAX( cellx * 2 / 5, 3 ) | 1;
            for( x = cellx - xx / 2 - 1; y >= 3; --y )
               hb_bm_line( x, y, cellx - 1, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_DR:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly + 1 ) / 2;
            for( y = celly - 5, x = 0; x < cellx - 4 && y >= yy; ++x, --y )
               hb_bm_line( 0, y, x, y );
            xx = HB_MAX( cellx * 2 / 5, 3 ) | 1;
            for( x = xx / 2 - 1; y >= 3; --y )
               hb_bm_line( 0, y, x, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_UL:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly + 1 ) / 2;
            for( y = 3, x = cellx - 1; x >= 3 && y <= yy; --x, ++y )
               hb_bm_line( x, y, cellx - 1, y );
            xx = HB_MAX( cellx * 2 / 5, 3 ) | 1;
            for( x = cellx - xx / 2 - 1; y < celly - 3; ++y )
               hb_bm_line( x, y, cellx - 1, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_UR:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly + 1 ) / 2;
            for( y = 4, x = 0; x < cellx - 4 && y <= yy; ++x, ++y )
               hb_bm_line( 0, y, x, y );
            xx = HB_MAX( cellx * 2 / 5, 3 ) | 1;
            for( x = xx / 2 - 1; y < celly - 3; ++y )
               hb_bm_line( 0, y, x, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_VL:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly - 1 ) / 2;
            for( y = 3, x = cellx - 1; x >= 3 && y < yy; --x, ++y )
               hb_bm_line( x, y, cellx - 1, y );
            for( y = yy + 2, ++x; x <= cellx - 1 && y < celly - 3; ++x, ++y )
               hb_bm_line( x, y, cellx - 1, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_VR:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly - 1 ) / 2;
            for( y = 4, x = 0; x < cellx - 4 && y < yy; ++x, ++y )
               hb_bm_line( 0, y, x, y );
            for( y = yy + 2, --x; x >= 0 && y < celly - 3; --x, ++y )
               hb_bm_line( 0, y, x, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BUTTON_L:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            break;

         case HB_BOXCH_RC_BUTTON_R:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            break;

         case HB_BOXCH_RC_ARROW_LL:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly - 1 ) / 2;
            for( x = 3, y = 0; x < cellx; ++x, ++y )
               hb_bm_line( x, yy - y, x, yy + y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_LR:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = HB_MAX( celly / 5, 3 ) | 1;
            for( y = ( celly - yy ) / 2; yy--; ++y )
               hb_bm_line( 0, y, cellx - 4, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_RL:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = HB_MAX( celly / 5, 3 ) | 1;
            for( y = ( celly - yy ) / 2; yy--; ++y )
               hb_bm_line( 3, y, cellx - 1, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ARROW_RR:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly - 1 ) / 2;
            for( x = cellx - 4, y = 0; x >= 0; --x, ++y )
               hb_bm_line( x, yy - y, x, yy + y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_ENTER1:
            /* TODO */
            break;
         case HB_BOXCH_RC_ENTER2:
            /* TODO */
            break;
         case HB_BOXCH_RC_ENTER3:
            /* TODO */
            break;

         case HB_BOXCH_RC_VSCRL_LD:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            hb_bm_line( 0, 0, 0, celly - 1 );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( 2, celly / 2 - 1, cellx - 1, celly / 2 - 1 );

            for( y = celly / 2 + 1; y < celly; y++ )
            {
               for( x = ( y & 1 ) + 2; x < cellx; x += 2 )
                  hb_bm_point( x, y );
            }
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_VSCRL_RD:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
            hb_bm_line( cellx - 2, 0, cellx - 2, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( 0, celly / 2 - 1, cellx - 1, celly / 2 - 1 );

            for( y = celly / 2 + 1; y < celly; y++ )
            {
               for( x = ( y ^ cellx ) & 1; x < cellx - 2; x += 2 )
                  hb_bm_point( x, y );
            }
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_VSCRL_LU:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            hb_bm_line( 0, 0, 0, celly - 1 );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );

            for( y = 0; y < celly / 2; y++ )
            {
               for( x = ( y & 1 ) + 2; x < cellx; x += 2 )
                  hb_bm_point( x, y );
            }
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_VSCRL_RU:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( cellx - 2, celly / 2 + 3, cellx - 2, celly - 1 );

            for( y = 0; y < celly / 2; y++ )
            {
               for( x = ( y ^ cellx ) & 1; x < cellx - 2; x += 2 )
                  hb_bm_point( x, y );
            }
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_VSCRL_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            hb_bm_line( 0, 0, 0, celly - 1 );

            for( y = 0; y < celly; y++ )
            {
               for( x = ( y & 1 ) + 2; x < cellx; x += 2 )
                  hb_bm_point( x, y );
            }
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_VSCRL_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );

            for( y = 0; y < celly; y++ )
            {
               for( x = ( y ^ cellx ) & 1; x < cellx - 2; x += 2 )
                  hb_bm_point( x, y );
            }
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_HSCRL:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            hb_bm_line( 0, 0, cellx - 1, 0 );
            hb_bm_line( 0, celly - 1, cellx - 1, celly - 1 );

            for( y = 2; y < celly - 2; y++ )
            {
               for( x = y & 1; x < cellx; x += 2 )
                  hb_bm_point( x, y );
            }
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_0:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "0" );
            break;

         case HB_BOXCH_RC_1:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "1" );
            break;

         case HB_BOXCH_RC_2:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "2" );
            break;

         case HB_BOXCH_RC_3:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "3" );
            break;

         case HB_BOXCH_RC_4:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "4" );
            break;

         case HB_BOXCH_RC_5:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "5" );
            break;

         case HB_BOXCH_RC_6:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "6" );
            break;

         case HB_BOXCH_RC_7:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "7" );
            break;

         case HB_BOXCH_RC_8:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "8" );
            break;

         case HB_BOXCH_RC_9:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "9" );
            break;

         case HB_BOXCH_RC_DOT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "." );
            break;

         case HB_BOXCH_RC_ACC:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_text( "'" );
            break;

         case HB_BOXCH_RC_BOX_ML:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( 0, 0, 0, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_MR:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_HWND_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx - 1, 0, 0, 0 );
            hb_bm_line( 0, 0, 0, celly - 1 );
            hb_bm_line( 0, celly - 1, cellx - 1, celly - 1 );
            hb_bm_line( cellx - 1, celly / 4 + 2, cellx / 4 + 1, celly / 4 + 2 );
            hb_bm_line( cellx / 4 + 1, celly / 4 + 2, cellx / 4 + 1, celly - 4 - celly / 4 );
            hb_bm_line( cellx / 4 + 1, celly - 4 - celly / 4, cellx - 1, celly - 4 - celly / 4 );
            hb_bm_line( cellx / 4 + 2, celly - 3 - celly / 4, cellx - 1, celly - 3 - celly / 4 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_HWND_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, 0, cellx - 1, 0 );
            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
            hb_bm_line( cellx - 1, celly - 1, 0, celly - 1 );
            hb_bm_line( 0, celly / 4 + 2, cellx - cellx / 4 - 2, celly / 4 + 2 );
            hb_bm_line( cellx - cellx / 4 - 2, celly / 4 + 2, cellx - cellx / 4 - 2, celly - 4 - celly / 4 );
            hb_bm_line( cellx - cellx / 4 - 2, celly - 4 - celly / 4, 0, celly - 4 - celly / 4 );
            hb_bm_line( 0, celly - 3 - celly / 4, cellx - cellx / 4 - 1, celly - 3 - celly / 4 );
            hb_bm_line( cellx - cellx / 4 - 1, celly - 3 - celly / 4, cellx - cellx / 4 - 1, celly / 4 + 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_TL:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, 0, cellx - 1, 0 );
            hb_bm_line( 0, 0, 0, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_T:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, 0, cellx - 1, 0 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_TR:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, 0, cellx - 1, 0 );
            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_BR:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx - 1, 0, cellx - 1, celly - 1 );
            hb_bm_line( 0, celly - 1, cellx - 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_B:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly - 1, cellx - 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_BL:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, 0, 0, celly - 1 );
            hb_bm_line( 0, celly - 1, cellx - 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, 0, 0, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_MT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( 0, 0, cellx - 1, 0 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BOX_MB:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( 0, celly - 1, cellx - 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BUTTON_CL:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = celly - 2 / 3;
            xx = cellx - 4;
            if( yy > xx )
               yy = xx;
            xx = ( xx * 2 + 1 ) / 3;
            if( xx < 2 )
               xx = 2;
            for( y = celly - yy - 3 - xx, i = 0; i < xx; ++y, ++i )
               hb_bm_line( 3, y, 3 + yy - 1, y + yy - 1 );
            y = celly - 5 - xx;
            hb_bm_line( cellx - 1, y, cellx - 1, y + xx - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_BUTTON_CR:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = celly - 2 / 3;
            xx = cellx - 4;
            if( yy > xx )
               yy = xx;
            xx = ( xx * 2 + 1 ) / 3;
            if( xx < 2 )
               xx = 2;
            for( y = celly - 6 - xx, i = 0; i < xx; ++y, ++i )
               hb_bm_line( 0, y, yy, y - yy );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_FARROW_DL:
            qBitMap = hb_gt_qtc_defineBoxButtonL( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly - cellx ) / 2 + 1;
            yy = HB_MAX( yy, 2 );
            for( y = celly - yy - 1, x = cellx - 1; x >= 2 && y >= 3; --x, --y )
               hb_bm_line( x, y, cellx - 1, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_FARROW_DR:
            qBitMap = hb_gt_qtc_defineBoxButtonR( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            yy = ( celly - cellx ) / 2 + 1;
            yy = HB_MAX( yy, 2 );
            for( y = celly - yy - 2, x = 0; x < cellx - 3 && y >= 3; ++x, --y )
               hb_bm_line( 0, y, x, y );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_DOTS:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            for( x = 1; x < cellx; x += 2 )
               hb_bm_point( x, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_DOTS_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            i = cellx / 2;
            xx = i - i / 2;
            yy = HB_MAX( 2, xx - 1 );

            hb_bm_fillrect( cellx - xx / 2 - i, celly / 3 * 2, xx    , yy );
            hb_bm_fillrect( cellx - xx / 2    , celly / 3 * 2, xx / 2, yy );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_RC_DOTS_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            i = cellx / 2;
            xx = i - i / 2;
            yy = HB_MAX( 2, xx - 1 );

            hb_bm_fillrect( 0         , celly / 3 * 2, xx - xx / 2, yy );
            hb_bm_fillrect( i - xx / 2, celly / 3 * 2, xx         , yy );
            hb_bm_paint_end();
            break;
      }
   else
      switch( usCh )
      {
         case HB_BOXCH_FILLER1:
         case HB_BOXCH_FILLER2:
         case HB_BOXCH_FILLER3:
         {
            int skip, start, mod;

            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            if( usCh == HB_BOXCH_FILLER1 )
            {
               skip = 4;
               start = mod = 1;
            }
            else if( usCh == HB_BOXCH_FILLER2 )
            {
               skip = 2;
               start = 0;
               mod = 1;
            }
            else
            {
               skip = 4;
               start = mod = 0;
            }
            for( y = 0; y < celly; y++ )
            {
               for( x = start + ( skip >> 1 ) * ( ( y & 1 ) ^ mod ); x < cellx; x += skip )
                  hb_bm_point( x, y );
            }
            if( usCh == HB_BOXCH_FILLER3 )
               hb_bm_invertrect( 0, 0, cellx, celly );
            hb_bm_paint_end();
            break;
         }
         case HB_BOXCH_ARROW_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            i = HB_MIN( ( celly >> 1 ), cellx ) - 3;
            pts[ 0 ].setX( ( cellx - i ) >> 1 );
            pts[ 0 ].setY( ( celly >> 1 ) - i );
            pts[ 1 ].setX( pts[ 0 ].x() + i );
            pts[ 1 ].setY( pts[ 0 ].y() + i );
            pts[ 2 ].setX( pts[ 1 ].x() - i );
            pts[ 2 ].setY( pts[ 1 ].y() + i );
            hb_bm_polygon( pts, 3 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_ARROW_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            i = HB_MIN( ( celly >> 1 ), cellx ) - 3;
            pts[ 0 ].setX( ( ( cellx - i ) >> 1 ) + i );
            pts[ 0 ].setY( ( celly >> 1 ) - i );
            pts[ 1 ].setX( pts[ 0 ].x() - i );
            pts[ 1 ].setY( pts[ 0 ].y() + i );
            pts[ 2 ].setX( pts[ 1 ].x() + i );
            pts[ 2 ].setY( pts[ 1 ].y() + i );
            hb_bm_polygon( pts, 3 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_ARROW_U:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            i = HB_MIN( celly, cellx >> 1 );
            pts[ 0 ].setX( ( cellx >> 1 ) - i );
            pts[ 0 ].setY( ( ( celly - i ) >> 1 ) + i );
            pts[ 1 ].setX( pts[ 0 ].x() + i );
            pts[ 1 ].setY( pts[ 0 ].y() - i );
            pts[ 2 ].setX( pts[ 1 ].x() + i );
            pts[ 2 ].setY( pts[ 1 ].y() + i );
            hb_bm_polygon( pts, 3 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_ARROW_D:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );

            i = HB_MIN( celly, cellx >> 1 );
            pts[ 0 ].setX( ( cellx >> 1 ) - i );
            pts[ 0 ].setY( ( celly - i ) >> 1 );
            pts[ 1 ].setX( pts[ 0 ].x() + i );
            pts[ 1 ].setY( pts[ 0 ].y() + i );
            pts[ 2 ].setX( pts[ 1 ].x() + i );
            pts[ 2 ].setY( pts[ 1 ].y() - i );
            hb_bm_polygon( pts, 3 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_FULL:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_fillrect( 0, 0, cellx, celly );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_FULL_B:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_fillrect( 0, celly / 2 + 1, cellx, ( celly + 1 ) / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_FULL_T:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_fillrect( 0, 0, cellx, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_FULL_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_fillrect( cellx / 2 + 1, 0, ( cellx + 1 ) / 2, celly );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_FULL_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_fillrect( 0, 0, cellx / 2, celly );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_LT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, celly - 1, cellx / 2, celly / 2 );
            hb_bm_line( cellx / 2, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_TD:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( cellx / 2, celly / 2, cellx / 2, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_RT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, celly - 1, cellx / 2, celly / 2 );
            hb_bm_line( cellx / 2, celly / 2, 0, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_LB:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly / 2 );
            hb_bm_line( cellx / 2, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_BU:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly / 2 );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_RB:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly / 2 );
            hb_bm_line( cellx / 2, celly / 2, 0, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_VL:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( cellx / 2, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_VR:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( cellx / 2, celly / 2, 0, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_CRS:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_HOR:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_VRT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_LT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, celly - 1, cellx / 2 - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly - 1, cellx / 2 + 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_TD:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx / 2 - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 + 1, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, cellx / 2 + 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_RT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, celly - 1, cellx / 2 - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 + 1, 0, celly / 2 + 1 );
            hb_bm_line( cellx / 2 + 1, celly - 1, cellx / 2 + 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 - 1, 0, celly / 2 - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_LB:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_BU:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_line( 0, celly / 2 - 1, cellx / 2 - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 - 1, cellx / 2 - 1, 0 );
            hb_bm_line( cellx / 2 + 1, celly / 2 - 1, cellx / 2 + 1, 0 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_RB:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 - 1, 0, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, 0, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_VL:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, cellx / 2 + 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_VR:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly - 1 );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 + 1, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 - 1, 0, celly / 2 - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 + 1, 0, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_CRS:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 + 1, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 - 1, 0, celly / 2 - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2 + 1, 0, celly / 2 + 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, cellx / 2 + 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_HOR:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_VRT:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_L_DBL_T:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2, celly / 2 - 1, cellx / 2, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_T_DBL_D:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( cellx / 2 - 1, celly / 2, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2, cellx / 2 + 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_R_DBL_T:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx / 2 + 1, celly / 2 );
            hb_bm_line( cellx / 2 - 1, celly / 2, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2, cellx / 2 + 1, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_L_DBL_B:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_B_DBL_U:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly / 2 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_R_DBL_B:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2, cellx / 2 + 1, celly / 2 );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly / 2 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_V_DBL_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( cellx / 2, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( cellx / 2, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_V_DBL_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( 0, celly / 2 - 1, cellx / 2, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx / 2, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SNG_DBL_CRS:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly - 1 );
            hb_bm_line( 0, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_L_SNG_T:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, celly / 2, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2, cellx / 2 + 1, celly - 1 );
            hb_bm_line( cellx / 2 - 1, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_T_SNG_D:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2, celly / 2 + 1, cellx / 2, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_R_SNG_T:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2 - 1, cellx / 2, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx / 2, celly / 2 + 1 );
            hb_bm_line( cellx / 2, celly / 2 - 1, cellx / 2, celly - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_L_SNG_B:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly / 2 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly / 2 );
            hb_bm_line( cellx / 2 - 1, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_B_SNG_U:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2 - 1, cellx - 1, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx - 1, celly / 2 + 1 );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly / 2 - 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_R_SNG_B:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( 0, celly / 2 - 1, cellx / 2, celly / 2 - 1 );
            hb_bm_line( 0, celly / 2 + 1, cellx / 2, celly / 2 + 1 );
            hb_bm_line( cellx / 2, 0, cellx / 2, celly / 2 + 1 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_V_SNG_L:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_V_SNG_R:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly - 1 );
            hb_bm_line( 0, celly / 2, cellx / 2 - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_DBL_SNG_CRS:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            hb_bm_line( cellx / 2 - 1, 0, cellx / 2 - 1, celly - 1 );
            hb_bm_line( cellx / 2 + 1, 0, cellx / 2 + 1, celly - 1 );
            hb_bm_line( 0, celly / 2, cellx - 1, celly / 2 );
            hb_bm_paint_end();
            break;

         case HB_BOXCH_SQUARE:
            qBitMap = hb_gt_qtc_bitmap_char( cellx, celly );
            hb_bm_paint_begin( qBitMap );
            xx = yy = cellx - HB_MAX( cellx >> 2, 2 );
            hb_bm_fillrect( ( cellx - xx ) >> 1, ( celly - yy ) >> 1, xx, yy );
            hb_bm_paint_end();
            break;
      }

   return qBitMap;
}

static QBitmap * hb_gt_qtc_getBoxChar( PHB_GTQTC pQTC, HB_USHORT * puc16 )
{
   HB_USHORT uc16 = *puc16;
   int iPos, iTrans;

   if( ( pQTC->fontAttribute & HB_GTI_FONTA_DRAWBOX ) == 0 )
      return NULL;

   if( uc16 >= HB_BOXCH_RC_0 && uc16 <= HB_BOXCH_RC_ACC )
   {
      switch( uc16 )
      {
         case HB_BOXCH_RC_0:
            *puc16 = '0';
            break;
         case HB_BOXCH_RC_1:
            *puc16 = '1';
            break;
         case HB_BOXCH_RC_2:
            *puc16 = '2';
            break;
         case HB_BOXCH_RC_3:
            *puc16 = '3';
            break;
         case HB_BOXCH_RC_4:
            *puc16 = '4';
            break;
         case HB_BOXCH_RC_5:
            *puc16 = '5';
            break;
         case HB_BOXCH_RC_6:
            *puc16 = '6';
            break;
         case HB_BOXCH_RC_7:
            *puc16 = '7';
            break;
         case HB_BOXCH_RC_8:
            *puc16 = '8';
            break;
         case HB_BOXCH_RC_9:
            *puc16 = '9';
            break;
         case HB_BOXCH_RC_DOT:
            *puc16 = '.';
            break;
         case HB_BOXCH_RC_ACC:
            *puc16 = '\'';
            break;
      }
      return NULL;
   }

   if     ( uc16 == HB_BOXCH_ARROW_R )
      iPos = 0;
   else if( uc16 == HB_BOXCH_ARROW_L )
      iPos = 1;
   else if( uc16 == HB_BOXCH_ARROW_U )
      iPos = 2;
   else if( uc16 == HB_BOXCH_ARROW_D )
      iPos = 3;
   else if( uc16 >= HB_BOXCH_BOX_MIN && uc16 <= HB_BOXCH_BOX_MAX )
      iPos = HB_BOXCH_CHR_BASE +
             ( uc16 - HB_BOXCH_BOX_MIN );
   else if( uc16 >= HB_BOXCH_RC_MIN && uc16 <= HB_BOXCH_RC_MAX )
      iPos = HB_BOXCH_CHR_BASE + ( HB_BOXCH_BOX_MAX - HB_BOXCH_BOX_MIN + 1 ) +
             ( uc16 - HB_BOXCH_RC_MIN );
   else
      return NULL;

   iTrans = pQTC->boxIndex[ iPos ];
   if( iTrans == HB_BOXCH_TRANS_MAX )
   {
      if( pQTC->boxCount < HB_BOXCH_TRANS_MAX - 1 )
      {
         iTrans = pQTC->boxCount + 1;
         pQTC->boxImage[ iTrans ] = hb_gt_qtc_defineBoxChar( pQTC, uc16 );
         if( pQTC->boxImage[ iTrans ] )
            pQTC->boxCount = iTrans;
         else
            iTrans = 0;
      }
      else
         iTrans = 0;
      pQTC->boxIndex[ iPos ] = iTrans;
   }

   return pQTC->boxImage[ iTrans ];
}

static void hb_gt_qtc_resetBoxCharBitmaps( PHB_GTQTC pQTC )
{
   int i;

   for( i = 1; i <= pQTC->boxCount; i++ )
      delete pQTC->boxImage[ i ];

   memset( pQTC->boxImage, 0, sizeof( pQTC->boxImage ) );
   pQTC->boxCount = 0;

   for( i = 0; i < HB_BOXCH_TRANS_COUNT; ++i )
      pQTC->boxIndex[ i ] = HB_BOXCH_TRANS_MAX;
}

/* --- */

static void hb_gt_qtc_free( PHB_GTQTC pQTC )
{
   if( pQTC->qEventLoop )
   {
      pQTC->qEventLoop->exit();
      delete pQTC->qEventLoop;
   }

   if( pQTC->qWnd )
      delete pQTC->qWnd;

   hb_gt_qtc_resetBoxCharBitmaps( pQTC );

   if( pQTC->fontName )
      delete pQTC->fontName;

   if( pQTC->wndTitle )
      delete pQTC->wndTitle;

   if( pQTC->qIcon )
      delete pQTC->qIcon;

   if( pQTC->textLine )
      hb_xfree( pQTC->textLine );

   hb_xfree( pQTC );
}

static PHB_GTQTC hb_gt_qtc_new( PHB_GT pGT )
{
   PHB_GTQTC pQTC;

   pQTC = static_cast< PHB_GTQTC >( hb_xgrabz( sizeof( HB_GTQTC ) ) );
   pQTC->pGT = pGT;

   pQTC->colors[  0 ] = BLACK;
   pQTC->colors[  1 ] = BLUE;
   pQTC->colors[  2 ] = GREEN;
   pQTC->colors[  3 ] = CYAN;
   pQTC->colors[  4 ] = RED;
   pQTC->colors[  5 ] = MAGENTA;
   pQTC->colors[  6 ] = BROWN;
   pQTC->colors[  7 ] = LIGHT_GRAY;
   pQTC->colors[  8 ] = GRAY;
   pQTC->colors[  9 ] = BRIGHT_BLUE;
   pQTC->colors[ 10 ] = BRIGHT_GREEN;
   pQTC->colors[ 11 ] = BRIGHT_CYAN;
   pQTC->colors[ 12 ] = BRIGHT_RED;
   pQTC->colors[ 13 ] = BRIGHT_MAGENTA;
   pQTC->colors[ 14 ] = YELLOW;
   pQTC->colors[ 15 ] = WHITE;

   pQTC->iRows         = QTC_DEFAULT_ROWS;
   pQTC->iCols         = QTC_DEFAULT_COLS;

   pQTC->textLine      = static_cast< QChar * >( hb_xgrab( pQTC->iCols * sizeof( QChar ) ) );

   pQTC->iNewPosX      = -1;
   pQTC->iNewPosY      = -1;

   pQTC->fontWidth     = QTC_DEFAULT_FONT_WIDTH;
   pQTC->fontHeight    = QTC_DEFAULT_FONT_HEIGHT;
   pQTC->fontWeight    = QTC_DEFAULT_FONT_WEIGHT;
   pQTC->fontAttribute = QTC_DEFAULT_FONT_ATTRIBUTE;
   pQTC->fontAscent    = 0;
   pQTC->fontName      = new QString( QTC_DEFAULT_FONT_NAME );
   pQTC->cellY         = pQTC->fontHeight;
   pQTC->cellX         = pQTC->fontWidth == 0 ? pQTC->cellY / 2: pQTC->fontWidth;
   pQTC->iCloseMode    = 0;
   pQTC->iResizeMode   = HB_GTI_RESIZEMODE_FONT;
   pQTC->fResizable    = HB_TRUE;
   pQTC->fResizeInc    = HB_FALSE;
   pQTC->fAltEnter     = HB_FALSE;
   pQTC->fMaximized    = HB_FALSE;
   pQTC->fMinimized    = HB_FALSE;
   pQTC->fFullScreen   = HB_FALSE;
   pQTC->fSelectCopy   = HB_FALSE;
   pQTC->fMsgAlert     = HB_FALSE;
   pQTC->fRepaint      = HB_TRUE;

   {
      PHB_ITEM pItem = hb_itemPutCPtr( NULL, hb_cmdargBaseProgName() );
      pQTC->wndTitle = new QString();
      hb_gt_qtc_itemGetQString( pItem, pQTC->wndTitle );
      hb_itemRelease( pItem );
   }
   return pQTC;
}

static void hb_gt_qtc_updateCursor( PHB_GTQTC pQTC )
{
   int cursorType = pQTC->cursorVisible ? pQTC->cursorType : SC_NONE;

   if( pQTC->lastCursorType != cursorType ||
       pQTC->lastCursorCol != pQTC->cursorCol ||
       pQTC->lastCursorRow != pQTC->cursorRow )
   {
      switch( cursorType )
      {
         case SC_NORMAL:
            pQTC->cursorSize   = 2;
            pQTC->cursorOffset = pQTC->cellY - pQTC->cursorSize - 1;
            break;
         case SC_INSERT:
            pQTC->cursorSize   = ( pQTC->cellY - 2 ) >> 1;
            pQTC->cursorOffset = pQTC->cellY - pQTC->cursorSize - 1;
            break;
         case SC_SPECIAL1:
            pQTC->cursorSize   = pQTC->cellY - 2;
            pQTC->cursorOffset = 1;
            break;
         case SC_SPECIAL2:
            pQTC->cursorSize   = ( pQTC->cellY - 2 ) >> 1;
            pQTC->cursorOffset = 1;
            break;
         default:
            pQTC->cursorSize   = 0;
            break;
      }
      if( pQTC->lastCursorType != SC_NONE )
      {
         pQTC->qWnd->qConsole->update( pQTC->lastCursorCol * pQTC->cellX + pQTC->marginLeft,
                                       pQTC->lastCursorRow * pQTC->cellY + pQTC->marginTop,
                                       pQTC->cellX, pQTC->cellY );
      }
      if( pQTC->cursorSize != 0 &&
          ( pQTC->lastCursorType == SC_NONE ||
            pQTC->lastCursorCol != pQTC->cursorCol ||
            pQTC->lastCursorRow != pQTC->cursorRow ) )
      {
         pQTC->qWnd->qConsole->update( pQTC->cursorCol * pQTC->cellX + pQTC->marginLeft,
                                       pQTC->cursorRow * pQTC->cellY + pQTC->marginTop,
                                       pQTC->cellX, pQTC->cellY );
      }
      pQTC->lastCursorType = cursorType;
      pQTC->lastCursorCol  = pQTC->cursorCol;
      pQTC->lastCursorRow  = pQTC->cursorRow;
   }
}

/*
 *  functions for handling the input queues for the mouse and keyboard
 */
static void hb_gt_qtc_addKeyToInputQueue( PHB_GTQTC pQTC, int iKey )
{
   int iHead = pQTC->keyHead;

   if( pQTC->keyHead != pQTC->keyTail )
   {
      if( HB_INKEY_ISMOUSEPOS( iKey ) )
      {
         int iLastKey = pQTC->keyBuffer[ pQTC->keyLast ];

         /* Clipper strips repeated mouse movemnt - let's do the same */
         if( HB_INKEY_ISMOUSEPOS( iLastKey ) )
         {
            pQTC->keyBuffer[ pQTC->keyLast ] = iKey;
            return;
         }
      }
      else if( iKey == HB_K_RESIZE &&
               iKey == pQTC->keyBuffer[ pQTC->keyLast ] )
         return;
   }

   /* When the buffer is full new event overwrite the last one
    * in the buffer - it's Clipper behavior [druzus]
    */
   pQTC->keyBuffer[ pQTC->keyLast = iHead ] = iKey;
   if( ++iHead >= QTC_KEY_QUEUE_SIZE )
      iHead = 0;
   if( iHead != pQTC->keyTail )
      pQTC->keyHead = iHead;
}

static HB_BOOL hb_gt_qtc_getKeyFromInputQueue( PHB_GTQTC pQTC, int * piKey )
{
   if( pQTC && pQTC->keyTail != pQTC->keyHead )
   {
      *piKey = pQTC->keyBuffer[ pQTC->keyTail ];
      if( ++pQTC->keyTail >= QTC_KEY_QUEUE_SIZE )
         pQTC->keyTail = 0;
      return HB_TRUE;
   }
   *piKey = 0;
   return HB_FALSE;
}

static int hb_gt_qtc_getKbdState( void )
{
   int iKbdState = 0;
   Qt::KeyboardModifiers kbState = QApplication::keyboardModifiers();

   if( kbState & Qt::ShiftModifier   ) iKbdState |= HB_GTI_KBD_SHIFT;
   if( kbState & Qt::ControlModifier ) iKbdState |= HB_GTI_KBD_CTRL;
   if( kbState & Qt::AltModifier     ) iKbdState |= HB_GTI_KBD_ALT;

   return iKbdState;
}

static int hb_gt_qtc_getKeyFlags( Qt::KeyboardModifiers keyFlags )
{
   int iFlags = 0;

   if( keyFlags & Qt::AltModifier     ) iFlags |= HB_KF_ALT;
   if( keyFlags & Qt::ControlModifier ) iFlags |= HB_KF_CTRL;
   if( keyFlags & Qt::ShiftModifier   ) iFlags |= HB_KF_SHIFT;
   if( keyFlags & Qt::KeypadModifier  ) iFlags |= HB_KF_KEYPAD;
#ifdef HB_OS_DARWIN
   if( keyFlags & Qt::MetaModifier )    iFlags |= HB_KF_CTRL;
#elif defined( HB_OS_ANDROID )
   if( ( keyFlags & Qt::AltModifier ) != 0 &&
       ( keyFlags & Qt::ShiftModifier ) != 0 &&
       ( keyFlags & Qt::ControlModifier ) == 0 )
      iFlags = ( iFlags & ~( HB_KF_ALT | HB_KF_SHIFT ) ) | HB_KF_CTRL;
#endif

   return iFlags;
}

static void hb_gt_qtc_setMouseKey( PHB_GTQTC pQTC, int x, int y, int iKey,
                                   Qt::KeyboardModifiers keyFlags )
{
   x -= pQTC->marginLeft;
   y -= pQTC->marginTop;
   pQTC->mousePosX = x;
   pQTC->mousePosY = y;
   x /= pQTC->cellX;
   y /= pQTC->cellY;
   if( pQTC->mouseCol != x || pQTC->mouseRow != y )
   {
      pQTC->mouseCol = x;
      pQTC->mouseRow = y;
      hb_gt_qtc_addKeyToInputQueue( pQTC, HB_INKEY_NEW_MPOS( x, y ) );
   }

   if( iKey != 0 )
   {
      int iFlags = hb_gt_qtc_getKeyFlags( keyFlags );
      hb_gt_qtc_addKeyToInputQueue( pQTC, HB_INKEY_NEW_MKEY( iKey, iFlags ) );
   }
}

static HB_BOOL hb_gt_qtc_setWindowSize( PHB_GTQTC pQTC, int iRows, int iCols )
{
   if( HB_GTSELF_RESIZE( pQTC->pGT, iRows, iCols ) )
   {
      if( pQTC->iCols != iCols )
         pQTC->textLine = static_cast< QChar * >( hb_xrealloc( pQTC->textLine,
                                                               iCols * sizeof( QChar ) ) );

      if( pQTC->qWnd && ( iRows != pQTC->iRows || iCols != pQTC->iCols ) )
         hb_gt_qtc_addKeyToInputQueue( pQTC, HB_K_RESIZE );

      pQTC->iRows = iRows;
      pQTC->iCols = iCols;

      return HB_TRUE;
   }
   return HB_FALSE;
}

static void hb_gt_qtc_setWindowFlags( PHB_GTQTC pQTC, Qt::WindowFlags flags, HB_BOOL fSet )
{
   Qt::WindowFlags currFlags = pQTC->qWnd->windowFlags(), newFlags;

   if( fSet )
      newFlags = currFlags | flags;
   else
      newFlags = currFlags & ~flags;

   if( newFlags != currFlags )
   {
      pQTC->qWnd->setWindowFlags( newFlags );
      HB_QTC_LOCK();
      pQTC->qWnd->show();
      HB_QTC_UNLOCK();
   }
}

static void hb_gt_qtc_setWindowState( PHB_GTQTC pQTC, Qt::WindowStates state, HB_BOOL fSet, HB_BOOL fShow )
{
   Qt::WindowStates currState = pQTC->qWnd->windowState(), newState;

   if( fSet )
      newState = currState | state;
   else
      newState = currState & ~state;

   if( newState != currState )
   {
      pQTC->qWnd->setWindowState( newState );
      if( fShow )
      {
         HB_QTC_LOCK();
         pQTC->qWnd->show();
         HB_QTC_UNLOCK();
      }
   }
}

static QSize hb_gt_qtc_screenSize( PHB_GTQTC pQTC )
{
   if( pQTC->qWnd )
   {
#if QT_VERSION >= 0x050E00
      /* return pQTC->qWnd->screen()->availableSize(); */
      return pQTC->qWnd->screen()->size();
#else
      /* return QApplication::desktop()->availableGeometry( pQTC->qWnd ).size(); */
      return QApplication::desktop()->screenGeometry( pQTC->qWnd ).size();
#endif
   }
   else
   {
#if QT_VERSION >= 0x050600
      /* return QGuiApplication::primaryScreen()->availableSize(); */
      return QGuiApplication::primaryScreen()->size();
#else
      /* return QApplication::desktop()->availableGeometry().size(); */
      return QApplication::desktop()->screenGeometry().size();
#endif
   }
}

static void hb_gt_qtc_initWindow( PHB_GTQTC pQTC, HB_BOOL fCenter )
{
   pQTC->qWnd->qConsole->resetWindowSize();
   if( fCenter || pQTC->iNewPosX < 0 || pQTC->iNewPosY < 0 )
   {
#if QT_VERSION >= 0x050E00
      QRect rc( pQTC->qWnd->screen()->availableGeometry() );
#else
      QRect rc( QApplication::desktop()->availableGeometry( pQTC->qWnd ) );
#endif

      pQTC->iNewPosX = rc.left() + ( ( rc.width() - pQTC->qWnd->width() ) >> 1 );
      pQTC->iNewPosY = rc.top() + ( ( rc.height() - pQTC->qWnd->height() ) >> 1 );
   }
   /* initial moving fulscreen or maximized window in MS-Windows
    * disables this modes [druzus]
    */
   if( ( pQTC->qWnd->windowState() & ( Qt::WindowMaximized | Qt::WindowFullScreen ) ) == 0 )
      pQTC->qWnd->move( pQTC->iNewPosX, pQTC->iNewPosY );
}

static void hb_gt_qtc_createConsoleWindow( PHB_GTQTC pQTC )
{
   pQTC->qWnd = new QTCWindow( pQTC );
   if( ! pQTC->qWnd )
      hb_errInternal( 10002, "Failed to create QTC window", NULL, NULL );

   hb_gt_qtc_initWindow( pQTC, HB_FALSE );

   HB_QTC_LOCK();
   pQTC->qWnd->show();
   HB_QTC_UNLOCK();
   pQTC->qWnd->update();
}

static int hb_gt_qtc_messageBox( PHB_GTQTC pQTC, PHB_ITEM pText, PHB_ITEM pButtons, double dDelay )
{
   int iRet = 0;

   if( pText )
   {
      QMessageBox qMsg( pQTC->qWnd );
      QString qStr;
      PHB_ITEM pTitle, pInfoText, pDetailed;
      int iLen;

      pTitle = pInfoText = pDetailed = NULL;

      if( HB_IS_HASH( pText ) )
      {
         if( ! pButtons || ! HB_IS_ARRAY( pButtons ) )
            pButtons = hb_hashGetCItemPtr( pText, "BTN" );
         if( dDelay <= 0 )
         {
            PHB_ITEM pVal = hb_hashGetCItemPtr( pText, "TIM" );
            if( pVal && HB_IS_NUMERIC( pVal ) )
              dDelay = hb_itemGetND( pVal );
         }
         pTitle    = hb_hashGetCItemPtr( pText, "TIT" );
         pInfoText = hb_hashGetCItemPtr( pText, "INF" );
         pDetailed = hb_hashGetCItemPtr( pText, "DTL" );
         pText     = hb_hashGetCItemPtr( pText, "TXT" );
      }

      if( pTitle && HB_IS_STRING( pTitle ) )
      {
         hb_gt_qtc_itemGetQString( pTitle, &qStr );
         qMsg.setWindowTitle( qStr );
      }
      else if( ! pQTC->wndTitle->isNull() )
         qMsg.setWindowTitle( *pQTC->wndTitle );
      if( pText && HB_IS_STRING( pText ) )
      {
         hb_gt_qtc_itemGetQString( pText, &qStr );
         qMsg.setText( qStr );
      }
      if( pInfoText && HB_IS_STRING( pInfoText ) )
      {
         hb_gt_qtc_itemGetQString( pInfoText, &qStr );
         qMsg.setInformativeText( qStr );
      }
      if( pDetailed && HB_IS_STRING( pDetailed ) )
      {
         hb_gt_qtc_itemGetQString( pDetailed, &qStr );
         qMsg.setDetailedText( qStr );
      }
      if( pButtons && HB_IS_ARRAY( pButtons ) &&
          ( iLen = ( int ) hb_arrayLen( pButtons ) ) > 0 )
      {
         int i;

#if defined( HB_OS_ANDROID )
         qputenv( "QT_USE_ANDROID_NATIVE_DIALOGS", "0" );
#endif

         for( i = 1; i <= iLen; ++i )
         {
            PHB_ITEM pItem = hb_arrayGetItemPtr( pButtons, i );

            if( HB_IS_STRING( pItem ) )
            {
               hb_gt_qtc_itemGetQString( pItem, &qStr );
               qMsg.addButton( qStr, QMessageBox::ActionRole );
            }
         }
      }

      QAction * act = new QAction( &qMsg );
      act->setShortcut( Qt::Key_Escape );
      qMsg.connect( act, SIGNAL( triggered( bool ) ), SLOT( reject() ) );
      qMsg.addAction( act );

      if( dDelay * 100 >= 1 )
         QTimer::singleShot( ( int ) ( dDelay * 1000 ), &qMsg, SLOT( reject() ) );

      qMsg.exec();

      iRet = qMsg.buttons().indexOf( qMsg.clickedButton() ) + 1;
   }

   return iRet;
}

/* --- */

static void hb_gt_qtc_InitMT( void );

static void hb_gt_qtc_Init( PHB_GT pGT, HB_FHANDLE hFilenoStdin, HB_FHANDLE hFilenoStdout, HB_FHANDLE hFilenoStderr )
{
   PHB_GTQTC pQTC;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Init(%p,%p,%p,%p)", pGT, ( void * ) ( HB_PTRUINT ) hFilenoStdin, ( void * ) ( HB_PTRUINT ) hFilenoStdout, ( void * ) ( HB_PTRUINT ) hFilenoStderr ) );

   if( ! s_qtapp )
   {
      hb_gt_qtc_InitMT();

      s_qtapp = qApp;
      if( ! s_qtapp )
      {
         /* QT requires these variables to be valid for whole application life
          * so we have to declare them as static [druzus]
          */
         static char ** s_argv;
         static int s_argc;

         s_argc = hb_cmdargARGC();
         s_argv = hb_cmdargARGV();

         s_qtapp = new QApplication( s_argc, s_argv );
         if( ! s_qtapp )
            hb_errInternal( 10001, "QT initialization error.", NULL, NULL );

         hb_vmAtQuit( hb_gt_qtc_appFree, NULL );
         hb_cmdargInit( s_argc, s_argv );
      }
   }

   pQTC = hb_gt_qtc_new( pGT );
   HB_GTLOCAL( pGT ) = static_cast< void * >( pQTC );

   if( ! pQTC->qEventLoop )
      pQTC->qEventLoop = new QEventLoop();

   /* SUPER GT initialization */
   HB_GTSUPER_INIT( pGT, hFilenoStdin, hFilenoStdout, hFilenoStderr );
   HB_GTSELF_RESIZE( pGT, pQTC->iRows, pQTC->iCols );
   HB_GTSELF_SETFLAG( pGT, HB_GTI_REDRAWMAX, 1 );
   HB_GTSELF_SEMICOLD( pGT );
}

/* --- */

static void hb_gt_qtc_Exit( PHB_GT pGT )
{
   PHB_GTQTC pQTC;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Exit(%p)", ( void * ) pGT ) );

   pQTC = HB_GTQTC_GET( pGT );
   HB_GTSUPER_EXIT( pGT );

   if( pQTC )
      hb_gt_qtc_free( pQTC );
}

/* --- */

static void hb_gt_qtc_Redraw( PHB_GT pGT, int iRow, int iCol, int iSize )
{
   PHB_GTQTC pQTC;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Redraw(%p,%d,%d,%d)", ( void * ) pGT, iRow, iCol, iSize ) );

   pQTC = HB_GTQTC_GET( pGT );
   if( pQTC )
   {
      if( !pQTC->qWnd )
         hb_gt_qtc_createConsoleWindow( pQTC );

      pQTC->qWnd->qConsole->repaintChars( QRect( iCol * pQTC->cellX,
                                                 iRow * pQTC->cellY,
                                                 iSize * pQTC->cellX,
                                                 pQTC->cellY ) );
   }
}

/* --- */

static void hb_gt_qtc_Refresh( PHB_GT pGT )
{
   PHB_GTQTC pQTC;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Refresh(%p)", ( void * ) pGT ) );

   HB_GTSUPER_REFRESH( pGT );

   pQTC = HB_GTQTC_GET( pGT );
   if( pQTC )
   {
      HB_GTSELF_GETSCRCURSOR( pGT, &pQTC->cursorRow, &pQTC->cursorCol,
                                   &pQTC->cursorType );
      if( pQTC->qWnd )
         hb_gt_qtc_updateCursor( pQTC );
   }
}

/* --- */

static HB_BOOL hb_gt_qtc_SetMode( PHB_GT pGT, int iRows, int iCols )
{
   PHB_GTQTC pQTC;
   HB_BOOL fResult, fCenter;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_SetMode(%p,%d,%d)", ( void * ) pGT, iRows, iCols ) );

   pQTC = HB_GTQTC_GET( pGT );
   fCenter = iRows != pQTC->iRows || iCols != pQTC->iCols;
   fResult = hb_gt_qtc_setWindowSize( pQTC, iRows, iCols );
   if( fResult )
   {
      if( pQTC->qWnd )
      {
         hb_gt_qtc_initWindow( pQTC, fCenter );
         HB_GTSELF_REFRESH( pGT );
      }
      else
         HB_GTSELF_SEMICOLD( pGT );
   }

   return fResult;
}

/* --- */

static const char * hb_gt_qtc_Version( PHB_GT pGT, int iType )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Version(%p,%d)", ( void * ) pGT, iType ) );

   HB_SYMBOL_UNUSED( pGT );

   if( iType == 0 )
      return HB_GT_DRVNAME( HB_GT_NAME );
   else if( iType == 2 )
   {
      static const char * s_pszVersion = NULL;
      static char s_szBuffer[ 12 ];
      if( s_pszVersion == NULL )
      {
         hb_snprintf( s_szBuffer, sizeof( s_szBuffer ), "%d.%d.%d",
                      ( QT_VERSION >> 16 ) & 0xFF,
                      ( QT_VERSION >> 8 ) & 0xFF,
                      QT_VERSION & 0xFF );
         s_pszVersion = s_szBuffer;
      }
      return s_pszVersion;
   }

   return "Harbour Terminal: QT GUI console (QTC)";
}

/* --- */

static int hb_gt_qtc_ReadKey( PHB_GT pGT, int iEventMask )
{
   PHB_GTQTC pQTC;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_ReadKey(%p,%d)", ( void * ) pGT, iEventMask ) );

   HB_SYMBOL_UNUSED( iEventMask );

   pQTC = HB_GTQTC_GET( pGT );
   if( pQTC )
   {
      int iKey;

      HB_QTC_LOCK();
      if( pQTC->qEventLoop )
         pQTC->qEventLoop->processEvents( QEventLoop::AllEvents );
      else
         QApplication::processEvents( QEventLoop::AllEvents );
      HB_QTC_UNLOCK();

      if( hb_gt_qtc_getKeyFromInputQueue( pQTC, &iKey ) )
         return iKey;
   }
   return 0;
}

/* --- */

static void hb_gt_qtc_Tone( PHB_GT pGT, double dFrequency, double dDuration )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Tone(%p,%lf,%lf)", ( void * ) pGT, dFrequency, dDuration ) );

   HB_SYMBOL_UNUSED( pGT );
   HB_SYMBOL_UNUSED( dFrequency );
   HB_SYMBOL_UNUSED( dDuration );

   /* TODO: add support for something more advanced then simple system beep */
   QApplication::beep();
}

/* --- */

static HB_BOOL hb_gt_qtc_mouse_IsPresent( PHB_GT pGT )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_mouse_IsPresent(%p)", ( void * ) pGT ) );

   HB_SYMBOL_UNUSED( pGT );

   return HB_TRUE;
}

static void hb_gt_qtc_mouse_GetPos( PHB_GT pGT, int * piRow, int * piCol )
{
   PHB_GTQTC pQTC;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_mouse_GetPos(%p,%p,%p)", ( void * ) pGT, piRow, piCol ) );

   pQTC = HB_GTQTC_GET( pGT );
   *piRow = pQTC->mouseRow;
   *piCol = pQTC->mouseCol;
}

static HB_BOOL hb_gt_qtc_mouse_ButtonState( PHB_GT pGT, int iButton )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_mouse_ButtonState(%p,%i)", ( void * ) pGT, iButton ) );

   HB_SYMBOL_UNUSED( pGT );

   switch( iButton )
   {
      case 0:
         return ( QApplication::mouseButtons() & Qt::LeftButton ) != 0;
      case 1:
         return ( QApplication::mouseButtons() & Qt::RightButton ) != 0;
      case 2:
#if QT_VERSION >= 0x060000
         return ( QApplication::mouseButtons() & Qt::MiddleButton ) != 0;
#else
         return ( QApplication::mouseButtons() & Qt::MidButton ) != 0;
#endif
   }
   return HB_FALSE;
}

static int hb_gt_qtc_mouse_CountButton( PHB_GT pGT )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_mouse_CountButton(%p)", ( void * ) pGT ) );

   HB_SYMBOL_UNUSED( pGT );

   return 3;
}

/* --- */

static int hb_gt_qtc_Alert( PHB_GT pGT, PHB_ITEM pMessage, PHB_ITEM pOptions,
                            int iClrNorm, int iClrHigh, double dDelay )
{
   PHB_GTQTC pQTC;
   int iRet;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Alert(%p,%p,%p,%d,%d,%f)", ( void * ) pGT, ( void * ) pMessage, ( void * ) pOptions, iClrNorm, iClrHigh, dDelay ) );

   pQTC = HB_GTQTC_GET( pGT );

   if( pQTC->fMsgAlert && pMessage &&
       ( HB_IS_STRING( pMessage ) || HB_IS_HASH( pMessage ) ) )
      iRet = hb_gt_qtc_messageBox( pQTC, pMessage, pOptions, dDelay );
   else
      iRet = HB_GTSUPER_ALERT( pGT, pMessage, pOptions, iClrNorm, iClrHigh, dDelay );

   return iRet;
}

static HB_BOOL hb_gt_qtc_Info( PHB_GT pGT, int iType, PHB_GT_INFO pInfo )
{
   PHB_GTQTC pQTC;
   int iVal;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_Info(%p,%d,%p)", ( void * ) pGT, iType, ( void * ) pInfo ) );

   pQTC = HB_GTQTC_GET( pGT );

   switch( iType )
   {
      case HB_GTI_ISSCREENPOS:
      case HB_GTI_KBDSUPPORT:
      case HB_GTI_ISGRAPHIC:
      case HB_GTI_ISUNICODE:
         pInfo->pResult = hb_itemPutL( pInfo->pResult, HB_TRUE );
         break;

      case HB_GTI_ONLINE:
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->qWnd != NULL );
         break;

      case HB_GTI_FONTSIZE:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->cellY );
         iVal = hb_itemGetNI( pInfo->pNewVal );
         if( iVal > 0 )
         {
            pQTC->fontHeight = iVal;
            if( pQTC->qWnd )
            {
               pQTC->qWnd->qConsole->resetWindowSize();
               HB_GTSELF_REFRESH( pGT );
            }
         }
         break;

      case HB_GTI_FONTWIDTH:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->cellX );
         iVal = hb_itemGetNI( pInfo->pNewVal );
         if( iVal > 0 )
            /* store font status for next operation on fontsize */
            pQTC->fontWidth = iVal;
         break;

      case HB_GTI_FONTWEIGHT:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->fontWeight );
         if( hb_itemType( pInfo->pNewVal ) & HB_IT_NUMERIC )
         {
            /* store font status for next operation on fontsize */
            iVal = hb_itemGetNI( pInfo->pNewVal );
            switch( iVal )
            {
               case HB_GTI_FONTW_THIN:
               case HB_GTI_FONTW_NORMAL:
               case HB_GTI_FONTW_BOLD:
                  pQTC->fontWeight = iVal;
                  break;
            }
         }
         break;

      case HB_GTI_FONTNAME:
         pInfo->pResult = hb_gt_qtc_itemPutQString( pInfo->pResult, pQTC->fontName );
         if( pInfo->pNewVal && HB_IS_STRING( pInfo->pNewVal ) )
            /* store font status for next operation on fontsize */
            hb_gt_qtc_itemGetQString( pInfo->pNewVal, pQTC->fontName );
         break;

      case HB_GTI_FONTATTRIBUTE:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->fontAttribute );
         if( hb_itemType( pInfo->pNewVal ) & HB_IT_NUMERIC )
            pQTC->fontAttribute = hb_itemGetNI( pInfo->pNewVal ) &
                                                ( HB_GTI_FONTA_FIXMETRIC |
                                                  HB_GTI_FONTA_CLRBKG    |
                                                  HB_GTI_FONTA_CTRLCHARS |
                                                  HB_GTI_FONTA_DRAWBOX   |
                                                  HB_GTI_FONTA_NOSTRETCH );
         break;

      case HB_GTI_SCREENHEIGHT:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->cellY * pQTC->iRows );
         iVal = hb_itemGetNI( pInfo->pNewVal );
         if( iVal > 0 )
            HB_GTSELF_SETMODE( pGT, static_cast< HB_USHORT >( iVal / pQTC->cellY ), pQTC->iCols );
         break;

      case HB_GTI_SCREENWIDTH:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->cellX * pQTC->iCols );
         iVal = hb_itemGetNI( pInfo->pNewVal );
         if( iVal > 0 )
            HB_GTSELF_SETMODE( pGT, pQTC->iRows, static_cast< HB_USHORT >( iVal / pQTC->cellX ) );
         break;

      case HB_GTI_DESKTOPWIDTH:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult,
                                        hb_gt_qtc_screenSize( pQTC ).width() );
         break;

      case HB_GTI_DESKTOPHEIGHT:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult,
                                        hb_gt_qtc_screenSize( pQTC ).height() );
         break;

      case HB_GTI_DESKTOPCOLS:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult,
                                        hb_gt_qtc_screenSize( pQTC ).width() / pQTC->cellX );
         break;

      case HB_GTI_DESKTOPROWS:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult,
                                        hb_gt_qtc_screenSize( pQTC ).height() / pQTC->cellY );
         break;

      case HB_GTI_WINTITLE:
         pInfo->pResult = hb_gt_qtc_itemPutQString( pInfo->pResult, pQTC->wndTitle );
         if( pInfo->pNewVal )
         {
            if( HB_IS_STRING( pInfo->pNewVal ) )
            {
               hb_gt_qtc_itemGetQString( pInfo->pNewVal, pQTC->wndTitle );
               if( pQTC->qWnd )
                  pQTC->qWnd->setWindowTitle( *pQTC->wndTitle );
            }
            else if( HB_IS_LOGICAL( pInfo->pNewVal ) )
            {
               pQTC->fNoFrame = hb_itemGetL( pInfo->pNewVal );
               if( pQTC->qWnd )
               {
                  Qt::WindowFlags flags = Qt::CustomizeWindowHint;

                  if( pQTC->fNoFrame )
                  {
                     hb_gt_qtc_setWindowFlags( pQTC, /*Qt::WindowTitleHint |
                                                     Qt::WindowSystemMenuHint |*/
                                                     Qt::WindowMinimizeButtonHint |
                                                     Qt::WindowMaximizeButtonHint |
                                                     Qt::WindowCloseButtonHint, HB_FALSE );
                     flags |= Qt::FramelessWindowHint;
                  }
                  else
                  {
                     if( pQTC->iCloseMode < 2 )
                        flags |= Qt::WindowCloseButtonHint;
                     if( pQTC->fResizable )
                        flags |= Qt::WindowMaximizeButtonHint;
                     flags |= Qt::WindowMinimizeButtonHint;
                  }
                  hb_gt_qtc_setWindowFlags( pQTC, flags, pQTC->fNoFrame );
               }
            }
         }
         break;

      case HB_GTI_ICONFILE:
         if( pInfo->pNewVal && HB_IS_STRING( pInfo->pNewVal ) )
         {
            QString qStr;
            hb_gt_qtc_itemGetQString( pInfo->pNewVal, &qStr );
            if( pQTC->qIcon )
               delete pQTC->qIcon;
            pQTC->qIcon = new QIcon( qStr );
            if( pQTC->qWnd )
               pQTC->qWnd->setWindowIcon( *pQTC->qIcon );
         }
         break;

      case HB_GTI_KBDSHIFTS:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, hb_gt_qtc_getKbdState() );
         break;

      case HB_GTI_CURSORBLINKRATE:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, QApplication::cursorFlashTime() );
         if( pInfo->pNewVal && HB_IS_NUMERIC( pInfo->pNewVal ) )
         {
            iVal = hb_itemGetNI( pInfo->pNewVal );
            if( iVal < 0 )
               iVal = 0;
            QApplication::setCursorFlashTime( iVal );
            if( pQTC->qWnd )
            {
               if( pQTC->qWnd->qConsole->timer->isActive() )
                  pQTC->qWnd->qConsole->timer->stop();
               if( QApplication::cursorFlashTime() / 2 > 0 )
                  pQTC->qWnd->qConsole->timer->start( QApplication::cursorFlashTime() / 2, pQTC->qWnd->qConsole );
            }
         }
         break;

      case HB_GTI_CLIPBOARDDATA:
      {
         QString qStr = QApplication::clipboard()->text();
         if( qStr.isEmpty() && QApplication::clipboard()->supportsSelection() )
         {
            qStr = QApplication::clipboard()->text( QClipboard::Selection );
            if( qStr.isEmpty() && QApplication::clipboard()->supportsFindBuffer() )
               qStr = QApplication::clipboard()->text( QClipboard::FindBuffer );
         }
         pInfo->pResult = hb_gt_qtc_itemPutQString( pInfo->pResult, &qStr );
         if( pInfo->pNewVal && HB_IS_STRING( pInfo->pNewVal ) )
         {
            hb_gt_qtc_itemGetQString( pInfo->pNewVal, &qStr );
            QApplication::clipboard()->setText( qStr );
            if( QApplication::clipboard()->supportsSelection() )
               QApplication::clipboard()->setText( qStr, QClipboard::Selection );
         }
         break;
      }
      case HB_GTI_SCREENSIZE:
         if( ! pInfo->pResult )
            pInfo->pResult = hb_itemNew( NULL );

         hb_arrayNew( pInfo->pResult, 2 );
         hb_arraySetNI( pInfo->pResult, 2, pQTC->cellY * pQTC->iRows );
         hb_arraySetNI( pInfo->pResult, 1, pQTC->cellX * pQTC->iCols );
         break;

      case HB_GTI_MAXIMIZED:
         if( pQTC->qWnd )
            pQTC->fMaximized = ( pQTC->qWnd->windowState() & Qt::WindowMaximized ) != 0;
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fMaximized );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) &&
             ( hb_itemGetL( pInfo->pNewVal ) ? ! pQTC->fMaximized : pQTC->fMaximized ) )
         {
            pQTC->fMaximized = ! pQTC->fMaximized;
            if( pQTC->qWnd )
               hb_gt_qtc_setWindowState( pQTC, Qt::WindowMaximized, pQTC->fMaximized, HB_TRUE );
         }
         break;

      case HB_GTI_ISFULLSCREEN:
         if( pQTC->qWnd )
            pQTC->fFullScreen = ( pQTC->qWnd->windowState() & Qt::WindowFullScreen ) != 0;
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fFullScreen );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) &&
             ( hb_itemGetL( pInfo->pNewVal ) ? ! pQTC->fFullScreen : pQTC->fFullScreen ) )
         {
            pQTC->fFullScreen = ! pQTC->fFullScreen;
            if( pQTC->qWnd )
               hb_gt_qtc_setWindowState( pQTC, Qt::WindowFullScreen, pQTC->fFullScreen, HB_TRUE );
         }
         break;

      case HB_GTI_ALTENTER:
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fAltEnter );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) )
            pQTC->fAltEnter = hb_itemGetL( pInfo->pNewVal );
         break;

      case HB_GTI_MINIMIZED:
         if( pQTC->qWnd )
            pQTC->fMinimized = ( pQTC->qWnd->windowState() & Qt::WindowMinimized ) != 0;
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fMinimized );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) &&
             ( hb_itemGetL( pInfo->pNewVal ) ? ! pQTC->fMinimized : pQTC->fMinimized ) )
         {
            pQTC->fMinimized = ! pQTC->fMinimized;
            if( pQTC->qWnd )
               hb_gt_qtc_setWindowState( pQTC, Qt::WindowMinimized, pQTC->fMinimized, ! pQTC->fMinimized );
         }
         break;

      case HB_GTI_CLOSABLE:
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->iCloseMode == 0 );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) &&
             ( hb_itemGetL( pInfo->pNewVal ) ? ( pQTC->iCloseMode != 0 ) :
                                               ( pQTC->iCloseMode == 0 ) ) )
         {
            iVal = pQTC->iCloseMode;
            pQTC->iCloseMode = iVal == 0 ? 1 : 0;
            if( pQTC->qWnd )
               hb_gt_qtc_setWindowFlags( pQTC, Qt::WindowCloseButtonHint, pQTC->iCloseMode < 2 );
         }
         break;

      case HB_GTI_CLOSEMODE:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->iCloseMode );
         if( pInfo->pNewVal && HB_IS_NUMERIC( pInfo->pNewVal ) )
         {
            iVal = hb_itemGetNI( pInfo->pNewVal );
            if( iVal >= 0 && iVal <= 2 )
            {
               pQTC->iCloseMode = iVal;
               if( pQTC->qWnd )
                  hb_gt_qtc_setWindowFlags( pQTC, Qt::WindowCloseButtonHint, pQTC->iCloseMode < 2 );
            }
         }
         break;

      case HB_GTI_RESIZABLE:
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fResizable );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) &&
             ( hb_itemGetL( pInfo->pNewVal ) ? ! pQTC->fResizable : pQTC->fResizable ) )
         {
            pQTC->fResizable = ! pQTC->fResizable;
            if( pQTC->qWnd )
            {
               pQTC->qWnd->setResizing();
               hb_gt_qtc_setWindowFlags( pQTC, Qt::WindowMaximizeButtonHint, pQTC->fResizable );
            }
         }
         break;

      case HB_GTI_RESIZEMODE:
         pInfo->pResult = hb_itemPutNI( pInfo->pResult, pQTC->iResizeMode );
         if( pInfo->pNewVal && HB_IS_NUMERIC( pInfo->pNewVal ) )
         {
            iVal = hb_itemGetNI( pInfo->pNewVal );
            switch( iVal )
            {
               case HB_GTI_RESIZEMODE_FONT:
               case HB_GTI_RESIZEMODE_ROWS:
                  if( pQTC->iResizeMode != iVal )
                  {
                     pQTC->iResizeMode = iVal;
                     if( pQTC->qWnd )
                        pQTC->qWnd->setResizing();
                  }
                  break;
            }
         }
         break;

      case HB_GTI_RESIZESTEP:
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fResizeInc );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) &&
             ( hb_itemGetL( pInfo->pNewVal ) ? ! pQTC->fResizeInc : pQTC->fResizeInc ) )
         {
            pQTC->fResizeInc = ! pQTC->fResizeInc;
            if( pQTC->qWnd )
               pQTC->qWnd->setResizing();
         }
         break;

      case HB_GTI_SELECTCOPY:
         pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fSelectCopy );
         if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) )
            pQTC->fSelectCopy = hb_itemGetL( pInfo->pNewVal );
         break;

      case HB_GTI_MOUSEPOS_XY:
         if( ! pInfo->pResult )
            pInfo->pResult = hb_itemNew( NULL );
         hb_arrayNew( pInfo->pResult, 2 );
         hb_arraySetNI( pInfo->pResult, 1, pQTC->mousePosX );
         hb_arraySetNI( pInfo->pResult, 2, pQTC->mousePosY );
         break;

      case HB_GTI_SETPOS_XY:
      case HB_GTI_SETPOS_ROWCOL:
      {
         int x = pQTC->iNewPosX, y = pQTC->iNewPosY;

         if( pQTC->qWnd )
         {
            x = pQTC->qWnd->pos().x();
            y = pQTC->qWnd->pos().y();
         }
         if( ! pInfo->pResult )
            pInfo->pResult = hb_itemNew( NULL );
         hb_arrayNew( pInfo->pResult, 2 );

         if( iType == HB_GTI_SETPOS_ROWCOL )
         {
            iVal = x;
            x = y / pQTC->cellY;
            y = iVal / pQTC->cellX;
         }
         hb_arraySetNI( pInfo->pResult, 1, x );
         hb_arraySetNI( pInfo->pResult, 2, y );

         if( pInfo->pNewVal && HB_IS_NUMERIC( pInfo->pNewVal ) &&
             pInfo->pNewVal2 && HB_IS_NUMERIC( pInfo->pNewVal2 ) )
         {
            x = hb_itemGetNI( pInfo->pNewVal );
            y = hb_itemGetNI( pInfo->pNewVal2 );
         }
         else if( pInfo->pNewVal && HB_IS_ARRAY( pInfo->pNewVal ) &&
                  hb_arrayLen( pInfo->pNewVal ) == 2 )
         {
            x = hb_arrayGetNI( pInfo->pNewVal, 1 );
            y = hb_arrayGetNI( pInfo->pNewVal, 2 );
         }
         else
            break;

         if( iType == HB_GTI_SETPOS_ROWCOL )
         {
            iVal = x;
            x = y * pQTC->cellX;
            y = iVal * pQTC->cellY;
         }
         if( pQTC->qWnd )
            pQTC->qWnd->move( x, y );
         else
         {
            pQTC->iNewPosX = x;
            pQTC->iNewPosY = y;
         }
         break;
      }
      case HB_GTI_PALETTE:
      {
         HB_BOOL fExpose = HB_FALSE;

         if( pInfo->pNewVal && HB_IS_NUMERIC( pInfo->pNewVal ) )
         {
            iVal = hb_itemGetNI( pInfo->pNewVal );
            if( iVal >= 0 && iVal < 16 )
            {
               pInfo->pResult = hb_itemPutNI( pInfo->pResult,
                                              QTC_RGB2NUM( pQTC->colors[ iVal ] ) );
               if( pInfo->pNewVal2 && HB_IS_NUMERIC( pInfo->pNewVal2 ) )
               {
                  int iColor = hb_itemGetNI( pInfo->pNewVal2 );
                  QRgb rgb = QTC_NUM2RGB( iColor );
                  if( rgb != pQTC->colors[ iVal ] )
                  {
                     pQTC->colors[ iVal ] = rgb;
                     fExpose = HB_TRUE;
                  }
               }
            }
         }
         else
         {
            if( ! pInfo->pResult )
               pInfo->pResult = hb_itemNew( NULL );
            hb_arrayNew( pInfo->pResult, 16 );
            for( iVal = 0; iVal < 16; iVal++ )
               hb_arraySetNL( pInfo->pResult, iVal + 1,
                              QTC_RGB2NUM( pQTC->colors[ iVal ] ) );
            if( pInfo->pNewVal && HB_IS_ARRAY( pInfo->pNewVal ) &&
                hb_arrayLen( pInfo->pNewVal ) == 16 )
            {
               for( iVal = 0; iVal < 16; iVal++ )
               {
                  int iColor = hb_arrayGetNI( pInfo->pNewVal, iVal + 1 );
                  QRgb rgb = QTC_NUM2RGB( iColor );
                  if( rgb != pQTC->colors[ iVal ] )
                  {
                     pQTC->colors[ iVal ] = rgb;
                     fExpose = HB_TRUE;
                  }
               }
            }
         }
         if( fExpose && pQTC->qWnd )
            HB_GTSELF_EXPOSEAREA( pQTC->pGT, 0, 0, pQTC->iRows, pQTC->iCols );
         break;
      }
      case HB_GTI_WINHANDLE:
         pInfo->pResult = hb_itemPutPtr( pInfo->pResult, pQTC->qWnd );
         break;

      case HB_GTI_DISPIMAGE:
         if( pQTC->qWnd &&
             ( hb_itemType( pInfo->pNewVal ) & ( HB_IT_STRING | HB_IT_ARRAY ) ) )
         {
            QImage qImg = QImage();

            /* filename or resource */
            if( HB_IS_STRING( pInfo->pNewVal ) )
            {
               if( hb_itemGetCLen( pInfo->pNewVal ) > 0 )
               {
                  QString qStr;
                  hb_gt_qtc_itemGetQString( pInfo->pNewVal, &qStr );
                  qImg = QImage( qStr );
               }
            }
            else if( hb_arrayLen( pInfo->pNewVal ) == static_cast< HB_SIZE >
                     ( ( hb_arrayGetType( pInfo->pNewVal, 4 ) & HB_IT_NUMERIC ) ? 4 : 3 ) &&
                     ( hb_arrayGetType( pInfo->pNewVal, 1 ) & ( HB_IT_POINTER | HB_IT_STRING ) ) &&
                     ( hb_arrayGetType( pInfo->pNewVal, 2 ) & HB_IT_NUMERIC ) &&
                     ( hb_arrayGetType( pInfo->pNewVal, 3 ) & HB_IT_NUMERIC ) )
            {
               HB_SIZE nSize = hb_arrayGetCLen( pInfo->pNewVal, 1 );
               int iWidth  = hb_arrayGetNI( pInfo->pNewVal, 2 );
               int iHeight = hb_arrayGetNI( pInfo->pNewVal, 3 );
               int iDepth  = hb_arrayGetNI( pInfo->pNewVal, 4 );
               int iPitch  = 0;
               const uchar * data = NULL;
               QImage::Format format;

               switch( iDepth )
               {
                  case 0:
                     iDepth = 32;
                     /* fallthrough */
                  case 32:
                     format = QImage::Format_RGB32;
                     break;
                  case 16:
                     format = QImage::Format_RGB16;
                     break;
                  case 1:
                     format = QImage::Format_Mono;
                     break;
                  default:
                     format = QImage::Format_Invalid;
                     break;
               }

               if( format != QImage::Format_Invalid && iWidth > 0 && iHeight > 0 )
               {
                  if( nSize > 0 )
                  {
                     int iPad = 32;
                     while( data == NULL && iPad >= 8 )
                     {
                        iPitch = ( iWidth * iDepth + iPad - 1 ) / iPad;
                        if( nSize == static_cast< HB_SIZE >( iHeight * iPitch ) )
                           data = reinterpret_cast< const uchar * >( hb_arrayGetCPtr( pInfo->pNewVal, 1 ) );
                        else
                           iPad >>= 1;
                     }
                  }
                  else
                     data = reinterpret_cast< const uchar * >( hb_arrayGetPtr( pInfo->pNewVal, 1 ) );
               }
               if( data != NULL )
               {
                  if( iPitch == 0 )
                     qImg = QImage( data, iWidth, iHeight, QImage::Format_RGB32 );
                  else
                     qImg = QImage( data, iWidth, iHeight, iPitch, QImage::Format_RGB32 );
               }
            }

            QRect rx = pQTC->qWnd->qConsole->image->rect();

            if( pInfo->pNewVal2 && HB_IS_ARRAY( pInfo->pNewVal2 ) )
            {
               switch( hb_arrayLen( pInfo->pNewVal2 ) )
               {
                  case 2:
                     rx.setLeft( hb_arrayGetNI( pInfo->pNewVal2, 1 ) );
                     rx.setTop( hb_arrayGetNI( pInfo->pNewVal2, 2 ) );
                     if( ! qImg.isNull() )
                        rx.setSize( qImg.size() );
                     break;
                  case 4:
                     rx.setCoords( hb_arrayGetNI( pInfo->pNewVal2, 1 ),
                                   hb_arrayGetNI( pInfo->pNewVal2, 2 ),
                                   hb_arrayGetNI( pInfo->pNewVal2, 3 ),
                                   hb_arrayGetNI( pInfo->pNewVal2, 4 ) );
               }
            }
            else if( ! qImg.isNull() && hb_itemGetL( pInfo->pNewVal2 ) )
            {
               iVal = qImg.height() * rx.width() / qImg.width();
               if( iVal <= rx.height() )
                  rx.setHeight( iVal );
               else
                  rx.setWidth( qImg.width() * rx.height() / qImg.height() );
               rx.moveCenter( pQTC->qWnd->qConsole->image->rect().center() );
            }

            if( qImg.isNull() )
               pQTC->qWnd->qConsole->repaintChars( rx );
            else
            {
               QPainter painter( pQTC->qWnd->qConsole->image );
               painter.drawImage( rx, qImg );
            }
            pQTC->qWnd->qConsole->update();
         }
         break;

      case HB_GTI_MSGBOX:
         if( ! pInfo->pNewVal || HB_IS_LOGICAL( pInfo->pNewVal ) || HB_IS_NIL( pInfo->pNewVal ) )
         {
            pInfo->pResult = hb_itemPutL( pInfo->pResult, pQTC->fMsgAlert );
            if( pInfo->pNewVal && HB_IS_LOGICAL( pInfo->pNewVal ) )
               pQTC->fMsgAlert = hb_itemGetL( pInfo->pNewVal );
         }
         else
            pInfo->pResult = hb_itemPutNI( pInfo->pResult,
                                           hb_gt_qtc_messageBox( pQTC, pInfo->pNewVal, pInfo->pNewVal2, -1 ) );
         break;

#ifdef HB_QT_SOUND
      case HB_GTI_SOUND:
         if( pInfo->pNewVal && HB_IS_STRING( pInfo->pNewVal ) &&
             hb_itemGetCLen( pInfo->pNewVal ) > 0 )
         {
            QString qStr;
            hb_gt_qtc_itemGetQString( pInfo->pNewVal, &qStr );
            QSound::play( qStr );
         }
         break;
#endif

      default:
         return HB_GTSUPER_INFO( pGT, iType, pInfo );
   }

   return HB_TRUE;
}

#define hb_gfx_cord( t, l, b, r, tmp )    \
               do { \
                     if( l > r ) { tmp = r; r = l; l = tmp; } \
                     if( t > b ) { tmp = b; b = t; t = tmp; } \
               } while( 0 )

#define hb_gfx_update( x, y, w, h ) pQTC->qWnd->qConsole->update( x, y, w, h )

static int hb_gt_qtc_gfx_Primitive( PHB_GT pGT, int iType, int iTop, int iLeft, int iBottom, int iRight, int iColor )
{
   PHB_GTQTC pQTC;
   int iRet = 1;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_qtc_gfx_Primitive(%p,%d,%d,%d,%d,%d,%d)", ( void * ) pGT, iType, iTop, iLeft, iBottom, iRight, iColor ) );

   pQTC = HB_GTQTC_GET( pGT );

   if( pQTC->qWnd )
   {
      int iTmp;

      switch( iType )
      {
         case HB_GFX_MAKECOLOR:
         {
            QRgb qColor = qRgb( iTop & 0xFF, iLeft & 0xFF, iBottom & 0xFF );
            iRet = QTC_RGB2NUM( qColor );
            break;
         }
         case HB_GFX_PUTPIXEL:
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iBottom );
            hb_bm_point( iLeft, iTop );
            hb_bm_paint_end();
            hb_gfx_update( iLeft, iTop, 1, 1 );
            break;

         case HB_GFX_LINE:
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iColor );
            hb_bm_line( iLeft, iTop, iRight, iBottom );
            hb_bm_paint_end();
            hb_gfx_cord( iTop, iLeft, iBottom, iRight, iTmp );
            hb_gfx_update( iLeft, iTop, iRight - iLeft + 1, iBottom - iTop + 1 );
            break;

         case HB_GFX_RECT:
            hb_gfx_cord( iTop, iLeft, iBottom, iRight, iTmp );
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iColor );
            painter.setBrush( Qt::NoBrush );
            hb_bm_rect( iLeft, iTop, iRight - iLeft, iBottom - iTop );
            hb_bm_paint_end();
            hb_gfx_update( iLeft, iTop, iRight - iLeft + 1, iBottom - iTop + 1 );
            break;

         case HB_GFX_FILLEDRECT:
            hb_gfx_cord( iTop, iLeft, iBottom, iRight, iTmp );
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iColor );
            hb_bm_fillrectc( iLeft, iTop, iRight - iLeft, iBottom - iTop, iColor );
            hb_bm_paint_end();
            hb_gfx_update( iLeft, iTop, iRight - iLeft + 1, iBottom - iTop + 1 );
            break;

         case HB_GFX_CIRCLE:
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iRight );
            painter.setBrush( Qt::NoBrush );
            painter.drawEllipse( QPoint( iLeft, iTop ), iBottom, iBottom );
            hb_bm_paint_end();
            hb_gfx_update( iLeft - iBottom, iTop - iBottom, iLeft + iBottom, iTop + iBottom );
            break;

         case HB_GFX_FILLEDCIRCLE:
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iRight );
            painter.setBrush( QBrush( QTC_NUM2RGB( iRight ) ) );
            painter.drawEllipse( QPoint( iLeft, iTop ), iBottom, iBottom );
            hb_bm_paint_end();
            hb_gfx_update( iLeft - iBottom, iTop - iBottom, iLeft + iBottom, iTop + iBottom );
            break;

         case HB_GFX_ELLIPSE:
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iColor );
            painter.setBrush( Qt::NoBrush );
            painter.drawEllipse( QPoint( iLeft, iTop ), iRight, iBottom );
            hb_bm_paint_end();
            hb_gfx_update( iLeft - iRight, iTop - iBottom, iLeft + iRight, iTop + iBottom );
            break;

         case HB_GFX_FILLEDELLIPSE:
            hb_bm_paint_begin( pQTC->qWnd->qConsole->image );
            hb_bm_color( iColor );
            painter.setBrush( QBrush( QTC_NUM2RGB( iColor ) ) );
            painter.drawEllipse( QPoint( iLeft, iTop ), iRight, iBottom );
            hb_bm_paint_end();
            hb_gfx_update( iLeft - iRight, iTop - iBottom, iLeft + iRight, iTop + iBottom );
            break;
      }
   }

   return iRet;
}

/* --- */

static HB_BOOL hb_gt_FuncInit( PHB_GT_FUNCS pFuncTable )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_FuncInit(%p)", ( void * ) pFuncTable ) );

   pFuncTable->Init                 = hb_gt_qtc_Init;
   pFuncTable->Exit                 = hb_gt_qtc_Exit;
   pFuncTable->SetMode              = hb_gt_qtc_SetMode;
   pFuncTable->Redraw               = hb_gt_qtc_Redraw;
   pFuncTable->Refresh              = hb_gt_qtc_Refresh;
   pFuncTable->Version              = hb_gt_qtc_Version;
   pFuncTable->Tone                 = hb_gt_qtc_Tone;
   pFuncTable->Info                 = hb_gt_qtc_Info;
   pFuncTable->Alert                = hb_gt_qtc_Alert;
   pFuncTable->ReadKey              = hb_gt_qtc_ReadKey;

   pFuncTable->MouseIsPresent       = hb_gt_qtc_mouse_IsPresent;
   pFuncTable->MouseGetPos          = hb_gt_qtc_mouse_GetPos;
   pFuncTable->MouseButtonState     = hb_gt_qtc_mouse_ButtonState;
   pFuncTable->MouseCountButton     = hb_gt_qtc_mouse_CountButton;

   pFuncTable->GfxPrimitive         = hb_gt_qtc_gfx_Primitive;

   return HB_TRUE;
}

/* --- */

static const HB_GT_INIT gtInit = { HB_GT_DRVNAME( HB_GT_NAME ),
                                   hb_gt_FuncInit,
                                   HB_GTSUPER,
                                   HB_GTID_PTR };

HB_GT_ANNOUNCE( HB_GT_NAME )

HB_CALL_ON_STARTUP_BEGIN( _hb_startup_gt_Init_ )
   hb_gtRegister( &gtInit );
HB_CALL_ON_STARTUP_END( _hb_startup_gt_Init_ )

#if defined( HB_PRAGMA_STARTUP )
   #pragma startup _hb_startup_gt_Init_
#elif defined( HB_MSC_STARTUP )
   #if defined( HB_OS_WIN_64 )
      #pragma section( HB_MSC_START_SEGMENT, long, read )
   #endif
   #pragma data_seg( HB_MSC_START_SEGMENT )
   static HB_$INITSYM hb_vm_auto__hb_startup_gt_Init_ = _hb_startup_gt_Init_;
   #pragma data_seg()
#endif

/* --- */

QTConsole::QTConsole( PHB_GTQTC pStructQTC, QWidget *parnt ) : QWidget( parnt )
{
   pQTC = pStructQTC;

   resizeMode = false;
   selectMode = false;
   image = NULL;
   timer = NULL;

   setAttribute( Qt::WA_StaticContents );
   setAttribute( Qt::WA_OpaquePaintEvent );
   setAttribute( Qt::WA_NoSystemBackground );
   /* Warning! Qt::WA_KeyCompression attribute creates problems when
    * barcode readers are used - some characters are eaten [druzus]
    */
   #if 0
   setAttribute( Qt::WA_KeyCompression );
   #endif

   /* Qt::WA_InputMethodEnabled disables support for
    * national characters in few European countries
    * (f.e. Polish characters with ALT in macOS)
    * If some Asian users needs it then we will have
    * to enable it optionally [druzus]
    */
   #if 0
   setAttribute( Qt::WA_InputMethodEnabled );
   #endif

#if defined( HB_OS_ANDROID ) || defined( HB_OS_IOS ) || defined( HB_OS_WIN_CE )
   setInputMethodHints( Qt::ImhNoPredictiveText );
#endif

   setFocusPolicy( Qt::StrongFocus );
   setMouseTracking( true );

   image = new QImage();

   timer = new QBasicTimer();
   if( QApplication::cursorFlashTime() / 2 > 0 )
      timer->start( QApplication::cursorFlashTime() / 2, this );
}

QTConsole::~QTConsole( void )
{
   delete image;

   if( timer->isActive() )
      timer->stop();
   delete timer;
}

void QTConsole::resetWindowSize( void )
{
   font = QFont( *pQTC->fontName );
   if( pQTC->fontWeight )
      font.setWeight( pQTC->fontWeight == HB_GTI_FONTW_THIN ? QFont::Light :
                      ( pQTC->fontWeight == HB_GTI_FONTW_BOLD ? QFont::Bold :
                        QFont::Normal ) ) ;
   font.setFixedPitch( true );
   font.setKerning( false );
   setFontSize( pQTC->fontHeight, pQTC->fontWidth );
   pQTC->qWnd->setWindowSize();
}

void QTConsole::setFontSize( int iFH, int iFW )
{
   int iDec = 0, iHeight, iWidth, iAscent;
   bool bStretch = ( pQTC->fontAttribute & HB_GTI_FONTA_NOSTRETCH ) == 0;
   bool bMaxSize = ( pQTC->qWnd->windowState() &
                     ( Qt::WindowMaximized | Qt::WindowFullScreen ) ) != 0;

   if( iFH < 4 )
      iFH = 4;

   font.setStretch( 100 );
   do
   {
      font.setPixelSize( iFH - iDec );
      QFontMetrics fm( font );
      iHeight = fm.height();
      iWidth  = fm.averageCharWidth();
      iAscent = fm.ascent();
      if( iHeight <= iFH && ( bStretch || ! bMaxSize || iWidth <= iFW ) )
         break;
   }
   while( iFH - ++iDec >= 4 );

   if( iFW > 0 && bStretch )
   {
      if( iFW < 2 )
         iFW = 2;

      if( iWidth != iFW )
      {
         int iDir;

         iDec = ( iFW * 100 ) / iWidth;
         if( iDec < 1 )
            iDec = 1;
         else if( iDec >= 4000 )
            iDec = 3999;
         iDir = iDec;
         do
         {
            font.setStretch( iDec );
            QFontMetrics fm( font );
            iHeight = fm.height();
            iWidth  = fm.averageCharWidth();
            iAscent = fm.ascent();

            if( iWidth == iFW )
               break;

            if( iWidth < iFW )
            {
               if( iDir > iDec )
                  break;
               ++iDec;
            }
            else /* iWidth > iFW */
            {
               if( --iDec <= iDir )
                  iDir = iDec + 1;
            }
         }
         while( iDec > ( iDir >> 1 ) && iDec < ( iDir << 1 ) && iDec < 4000 );
      }
   }

   if( ( iHeight < iFH || iWidth < iFW ) &&
       ( pQTC->fontAttribute & HB_GTI_FONTA_CLRBKG ) != 0 &&
       ( pQTC->fontAttribute & HB_GTI_FONTA_DRAWBOX ) != 0 &&
       ( pQTC->fontAttribute & HB_GTI_FONTA_FIXMETRIC ) != 0 )
   {
      if( iHeight < iFH )
         iHeight = iFH;
      if( iWidth < iFW )
         iWidth = iFW;
   }

   pQTC->fontHeight = iHeight;
   pQTC->fontWidth  = iWidth;
   pQTC->fontAscent = iAscent;

   pQTC->fRepaint = pQTC->cellX != pQTC->fontWidth ||
                    pQTC->cellY != pQTC->fontHeight;

   pQTC->cellX = pQTC->fontWidth;
   pQTC->cellY = pQTC->fontHeight;

   if( pQTC->fRepaint || image->isNull() )
   {
      hb_gt_qtc_resetBoxCharBitmaps( pQTC );
      if( ! image->isNull() && pQTC->iResizeMode == HB_GTI_RESIZEMODE_ROWS )
         hb_gt_qtc_setWindowSize( pQTC, pQTC->qWnd->height() / pQTC->cellY,
                                        pQTC->qWnd->width() / pQTC->cellX );
   }
   setImageSize();
}

void QTConsole::setImageSize( void )
{
   int iWidth  = pQTC->cellX * pQTC->iCols;
   int iHeight = pQTC->cellY * pQTC->iRows;

   if( iWidth != image->width() || iHeight != image->height() )
   {
      delete image;
      image = new QImage( iWidth, iHeight, QImage::Format_RGB32 );
      pQTC->fRepaint = HB_TRUE;
   }
   if( pQTC->fRepaint )
   {
      image->fill( BLACK );
      repaintChars( image->rect() );
      pQTC->fRepaint = HB_FALSE;
   }
}

void QTConsole::resizeEvent( QResizeEvent * evt )
{
   int iWidth  = width();
   int iHeight = height();

   if( iWidth != image->width() || iHeight != image->height() )
   {
      resizeMode = true;

      if( pQTC->iResizeMode == HB_GTI_RESIZEMODE_ROWS )
      {
         int iRows  = iHeight / pQTC->cellY;
         int iCols  = iWidth / pQTC->cellX;

         if( hb_gt_qtc_setWindowSize( pQTC, iRows, iCols ) )
            setImageSize();
      }
      else
         setFontSize( iHeight / pQTC->iRows, iWidth / pQTC->iCols );

      update();
   }
   else
      QWidget::resizeEvent( evt );
}

static QRect hb_gt_qtc_cellToPixel( PHB_GTQTC pQTC, const QRect & rc )
{
   return QRect( rc.left()   * pQTC->cellX,
                 rc.top()    * pQTC->cellY,
                 rc.width()  * pQTC->cellX,
                 rc.height() * pQTC->cellY );
}

static QRect hb_gt_qtc_pixelToCell( PHB_GTQTC pQTC, const QRect & rx )
{
   QRect rc;
   rc.setCoords( rx.left()   / pQTC->cellX,
                 rx.top()    / pQTC->cellY,
                 rx.right()  / pQTC->cellX,
                 rx.bottom() / pQTC->cellY );
   return rc;
}

static QRect hb_gt_qtc_mapRect( PHB_GTQTC pQTC, const QImage * image, const QRect & rx )
{
   return hb_gt_qtc_pixelToCell( pQTC,
             ( rx.normalized() & QRect( pQTC->marginLeft, pQTC->marginTop,
                                        image->width(), image->height() ) )
             .translated( -pQTC->marginLeft, -pQTC->marginTop ) );
}

static QRect hb_gt_qtc_unmapRect( PHB_GTQTC pQTC, const QRect & rc )
{
   return hb_gt_qtc_cellToPixel( pQTC, rc ).translated( pQTC->marginLeft,
                                                        pQTC->marginTop );
}

void QTConsole::copySelection( void )
{
   const QRect rc = hb_gt_qtc_mapRect( pQTC, image, selectRect );
   int iRow, iCol;
   QString qStrEol( hb_conNewLine() );
   QString qStr( "" );

   qStr.reserve( rc.height() * ( rc.width() + qStrEol.size() ) );

   selectMode = false;
   update( hb_gt_qtc_unmapRect( pQTC, rc ) );

   for( iRow = rc.top(); iRow <= rc.bottom(); ++iRow )
   {
      for( iCol = rc.left(); iCol <= rc.right(); ++iCol )
      {
         int iColor;
         HB_BYTE bAttr;
         HB_USHORT usChar;

         if( ! HB_GTSELF_GETSCRCHAR( pQTC->pGT, iRow, iCol, &iColor, &bAttr, &usChar ) )
            break;
         qStr += QChar( usChar );
      }
      if( rc.height() > 1 )
         qStr += qStrEol;
   }

   QApplication::clipboard()->setText( qStr );
   if( QApplication::clipboard()->supportsSelection() )
      QApplication::clipboard()->setText( qStr, QClipboard::Selection );
}

void QTConsole::repaintChars( const QRect & rx )
{
   int       iRow, iColor, iTextColor = 0;
   HB_BYTE   bAttr;
   HB_USHORT usChar;
   bool      bClrBkg = ( pQTC->fontAttribute & HB_GTI_FONTA_CLRBKG ) != 0;
   bool      bFixMetric = ( pQTC->fontAttribute & HB_GTI_FONTA_FIXMETRIC ) != 0;
   QRect     rc = hb_gt_qtc_pixelToCell( pQTC, rx );

   QPainter painter( image );
   painter.setFont( QFont( font, painter.device() ) );
   if( bClrBkg )
      painter.setBackgroundMode( Qt::TransparentMode );
   else
      painter.setBackgroundMode( Qt::OpaqueMode );

   for( iRow = rc.top(); iRow <= rc.bottom(); ++iRow )
   {
      int iCol, iStartCol, iLen;

      iCol = iStartCol = rc.left();
      iLen = 0;

      while( iCol <= rc.right() )
      {
         if( ! HB_GTSELF_GETSCRCHAR( pQTC->pGT, iRow, iCol, &iColor, &bAttr, &usChar ) )
            break;

         if( ( pQTC->fontAttribute & HB_GTI_FONTA_CTRLCHARS ) == 0 )
            usChar = hb_cdpGetU16Ctrl( usChar );
         iColor &= 0xff;

         QBitmap * qBitMap = hb_gt_qtc_getBoxChar( pQTC, &usChar );

         if( iLen > 0 && ( iColor != iTextColor || bFixMetric || qBitMap ) )
         {
            if( bClrBkg )
               painter.fillRect( iStartCol * pQTC->cellX, iRow * pQTC->cellY,
                                 iLen * pQTC->cellX, pQTC->cellY,
                                 pQTC->colors[ iTextColor >> 4 ] );
            else
               painter.setBackground( QBrush( pQTC->colors[ iTextColor >> 4 ] ) );
            painter.setPen( pQTC->colors[ iTextColor & 0x0F ] );
            painter.drawText( iStartCol * pQTC->cellX,
                              ( iRow * pQTC->cellY ) + pQTC->fontAscent,
                              QString( pQTC->textLine, iLen ) );
            iLen = 0;
         }
         if( qBitMap )
         {
            painter.setBackgroundMode( Qt::OpaqueMode );
            painter.setBackground( QBrush( pQTC->colors[ iColor >> 4 ] ) );
            painter.setPen( pQTC->colors[ iColor & 0x0F ] );
            painter.drawPixmap( iCol * pQTC->cellX, iRow * pQTC->cellY, *qBitMap );
            if( bClrBkg )
               painter.setBackgroundMode( Qt::TransparentMode );
         }
         else
         {
            if( iLen == 0 )
            {
               iTextColor = iColor;
               iStartCol  = iCol;
            }
            pQTC->textLine[ iLen++ ] = usChar;
         }
         iCol++;
      }
      if( iLen > 0 )
      {
         if( bClrBkg )
            painter.fillRect( iStartCol * pQTC->cellX, iRow * pQTC->cellY,
                              iLen * pQTC->cellX, pQTC->cellY,
                              pQTC->colors[ iTextColor >> 4 ] );
         else
            painter.setBackground( QBrush( pQTC->colors[ iTextColor >> 4 ] ) );
         painter.setPen( pQTC->colors[ iTextColor & 0x0F ] );
         painter.drawText( iStartCol * pQTC->cellX,
                           ( iRow * pQTC->cellY ) + pQTC->fontAscent,
                           QString( pQTC->textLine, iLen ) );
      }
   }

   update( rx.translated( pQTC->marginLeft, pQTC->marginTop ) );
}

void QTConsole::paintEvent( QPaintEvent * evt )
{
   QPainter painter( this );
   QRect rEvt = evt->rect();

   if( rEvt.left() < pQTC->marginLeft )
   {
      QRect rc = rEvt;
      rc.setRight( pQTC->marginLeft );
      painter.fillRect( rc, QBrush( BLACK ) );
      rEvt.setLeft( pQTC->marginLeft );
   }
   if( rEvt.top() < pQTC->marginTop )
   {
      QRect rc = rEvt;
      rc.setBottom( pQTC->marginTop );
      painter.fillRect( rc, QBrush( BLACK ) );
      rEvt.setTop( pQTC->marginTop );
   }
   if( rEvt.right() > pQTC->marginLeft + image->width() )
   {
      QRect rc = rEvt;
      rc.setLeft( pQTC->marginLeft + image->width() );
      painter.fillRect( rc, QBrush( BLACK ) );
      rEvt.setRight( pQTC->marginLeft + image->width() - 1 );
   }
   if( rEvt.bottom() > pQTC->marginTop + image->height() )
   {
      QRect rc = rEvt;
      rc.setTop( pQTC->marginTop + image->height() );
      painter.fillRect( rc, QBrush( BLACK ) );
      rEvt.setBottom( pQTC->marginTop + image->height() - 1 );
   }

   painter.drawImage( rEvt, *image, rEvt.translated( -pQTC->marginLeft, -pQTC->marginTop ) );

   if( selectMode )
   {
      /* Display selection */
      QRect rSel = hb_gt_qtc_unmapRect( pQTC, hb_gt_qtc_mapRect( pQTC, image, selectRect ) );
      if( rSel.intersects( rEvt ) )
      {
#if defined( HB_OS_DARWIN )
         /* RasterOp operations are not supported in macOS */
         rEvt &= rSel;
         image->invertPixels();
         painter.drawImage( rEvt, *image, rEvt.translated( -pQTC->marginLeft, -pQTC->marginTop ) );
         image->invertPixels();
#else
         painter.setCompositionMode( QPainter::RasterOp_SourceXorDestination );
         painter.fillRect( rSel & rEvt, Qt::color0 );
#endif
      }
   }
   else if( pQTC->cursorType != SC_NONE && pQTC->cursorSize != 0 )
   {
      /* Display cursor */
      QRect rCrs( pQTC->cursorCol * pQTC->cellX + pQTC->marginLeft,
                  pQTC->cursorRow * pQTC->cellY + pQTC->marginTop + pQTC->cursorOffset,
                  pQTC->cellX, pQTC->cursorSize );
      if( rEvt.intersects( rCrs ) )
      {
#if defined( HB_OS_DARWIN )
         /* RasterOp operations are not supported in macOS,
          * use foreground cell color like hardware VGA cursor
          */
         HB_BYTE   bAttr;
         HB_USHORT usChar;
         int       iColor;

         if( HB_GTSELF_GETSCRCHAR( pQTC->pGT, pQTC->cursorRow, pQTC->cursorCol,
                                   &iColor, &bAttr, &usChar ) )
         {
            painter.fillRect( rCrs, pQTC->colors[ iColor & 0x0F ] );
         }
#else
         painter.setCompositionMode( QPainter::RasterOp_SourceXorDestination );
         /* TODO? use foreground cell color like hardware VGA cursor ? */
         painter.fillRect( rCrs, Qt::color0 );
#endif
      }
   }
}

void QTConsole::timerEvent( QTimerEvent * evt )
{
   if( evt->timerId() == timer->timerId() )
   {
      if( hasFocus() )
      {
         pQTC->cursorVisible = ! pQTC->cursorVisible;
         hb_gt_qtc_updateCursor( pQTC );
      }
   }
   else
      QWidget::timerEvent( evt );
}

void QTConsole::focusInEvent( QFocusEvent * evt )
{
   hb_gt_qtc_addKeyToInputQueue( pQTC, HB_K_GOTFOCUS );
   QWidget::focusInEvent( evt );
#if defined( HB_OS_ANDROID ) || defined( HB_OS_IOS ) || defined( HB_OS_WIN_CE )
   QEvent reqSIPevent( QEvent::RequestSoftwareInputPanel );
   QApplication::sendEvent( pQTC->qWnd, &reqSIPevent );
#endif
}

void QTConsole::focusOutEvent( QFocusEvent * evt )
{
   hb_gt_qtc_addKeyToInputQueue( pQTC, HB_K_LOSTFOCUS );
   QWidget::focusOutEvent( evt );
}

void QTConsole::mouseMoveEvent( QMouseEvent * evt )
{
   if( pQTC->fSelectCopy && selectMode )
   {
      QRect rSel1 = hb_gt_qtc_unmapRect( pQTC, hb_gt_qtc_mapRect( pQTC, image, selectRect ) );
      selectRect.setBottomRight( evt->pos() );
      QRect rSel2 = hb_gt_qtc_unmapRect( pQTC, hb_gt_qtc_mapRect( pQTC, image, selectRect ) );
      if( rSel1 != rSel2 )
         update( QRegion( rSel1 ).xored( QRegion( rSel2 ) ) );
   }
   else
   {
      QPoint pos = evt->pos();
      hb_gt_qtc_setMouseKey( pQTC, pos.x(), pos.y(), 0, evt->modifiers() );
   }
}

void QTConsole::wheelEvent( QWheelEvent * evt )
{
#if QT_VERSION >= 0x050E00
   QPoint delta = evt->angleDelta();

   if( delta.y() != 0 || delta.x() != 0 )
   {
      QPoint pos = evt->position().toPoint();

      if( delta.y() != 0 )
         hb_gt_qtc_setMouseKey( pQTC, pos.x(), pos.y(), delta.y() < 0 ? K_MWBACKWARD : K_MWFORWARD, evt->modifiers() );
      if( delta.x() != 0 )
         hb_gt_qtc_setMouseKey( pQTC, pos.x(), pos.y(), delta.x() < 0 ? K_MWRIGHT : K_MWLEFT, evt->modifiers() );
   }
   else
     QWidget::wheelEvent( evt );
#else
   int iKey;

   switch( evt->orientation() )
   {
      case Qt::Vertical:
         iKey = evt->delta() < 0 ? K_MWBACKWARD : K_MWFORWARD;
         break;

      case Qt::Horizontal:
         iKey = evt->delta() < 0 ? K_MWRIGHT : K_MWLEFT;
         break;

      default:
         QWidget::wheelEvent( evt );
         return;
   }

   hb_gt_qtc_setMouseKey( pQTC, evt->x(), evt->y(), iKey, evt->modifiers() );
#endif
}

void QTConsole::mouseDoubleClickEvent( QMouseEvent * evt )
{
   int iKey;

   switch( evt->button() )
   {
      case Qt::LeftButton:
#if defined( HB_OS_ANDROID ) || defined( HB_OS_IOS ) || defined( HB_OS_WIN_CE )
         {
            QEvent reqSIPevent( QEvent::RequestSoftwareInputPanel );
            QApplication::sendEvent( pQTC->qWnd, &reqSIPevent );
         }
#endif
         iKey = K_LDBLCLK;
         break;

      case Qt::RightButton:
         iKey = K_RDBLCLK;
         break;

#if QT_VERSION >= 0x060000
      case Qt::MiddleButton:
#else
      case Qt::MidButton:
#endif
         iKey = K_MDBLCLK;
         break;

      default:
         QWidget::mouseDoubleClickEvent( evt );
         return;
   }

   QPoint pos = evt->pos();
   hb_gt_qtc_setMouseKey( pQTC, pos.x(), pos.y(), iKey, evt->modifiers() );
}

void QTConsole::mousePressEvent( QMouseEvent * evt )
{
   int iKey;

   switch( evt->button() )
   {
      case Qt::LeftButton:
         if( ! selectMode && ( evt->modifiers() & Qt::ShiftModifier ) )
         {
            QPoint pos = evt->pos();

            selectMode = true;
            selectRect.setCoords( pos.x(), pos.y(), pos.x(), pos.y() );
            update( hb_gt_qtc_unmapRect( pQTC, hb_gt_qtc_mapRect( pQTC, image, selectRect ) ) );
            return;
         }
         iKey = K_LBUTTONDOWN;
         break;

      case Qt::RightButton:
         iKey = K_RBUTTONDOWN;
         break;

#if QT_VERSION >= 0x060000
      case Qt::MiddleButton:
#else
      case Qt::MidButton:
#endif
         iKey = K_MBUTTONDOWN;
         break;

      default:
         QWidget::mousePressEvent( evt );
         return;
   }

   QPoint pos = evt->pos();
   hb_gt_qtc_setMouseKey( pQTC, pos.x(), pos.y(), iKey, evt->modifiers() );
}

void QTConsole::mouseReleaseEvent( QMouseEvent * evt )
{
   int iKey;

   switch( evt->button() )
   {
      case Qt::LeftButton:
         if( selectMode )
         {
            copySelection();
            return;
         }
         iKey = K_LBUTTONUP;
         break;

      case Qt::RightButton:
         iKey = K_RBUTTONUP;
         break;

#if QT_VERSION >= 0x060000
      case Qt::MiddleButton:
#else
      case Qt::MidButton:
#endif
         iKey = K_MBUTTONUP;
         break;

      default:
         QWidget::mouseReleaseEvent( evt );
         return;
   }

   QPoint pos = evt->pos();
   hb_gt_qtc_setMouseKey( pQTC, pos.x(), pos.y(), iKey, evt->modifiers() );
}

bool QTConsole::event( QEvent * evt )
{
   if( evt->type() == QEvent::KeyPress )
   {
      QKeyEvent * kevt = static_cast< QKeyEvent * >( evt );
      if( kevt->key() == Qt::Key_Tab )
      {
         keyPressEvent( kevt );
         return true;
      }
   }
   if( resizeMode )
   {
      switch( evt->type() )
      {
         case QEvent::Enter:
         case QEvent::Leave:
         case QEvent::MouseMove:
         case QEvent::FocusIn:
         case QEvent::FocusOut:
         case QEvent::ChildRemoved:
         case QEvent::UpdateRequest:
            resizeMode = false;
            update();
            pQTC->qWnd->setWindowSize();
            break;
         default:
            break;
      }
   }

   return QWidget::event( evt );
}

void QTConsole::inputMethodEvent( QInputMethodEvent * evt )
{
   /* It's for SoftwareInputPanel in Andorid. */

   QString qStr = evt->commitString();

   if( qStr.size() > 0 )
   {
      for( int i = 0; i < qStr.size(); ++i )
      {
         HB_WCHAR wc = qStr[ i ].unicode();
         hb_gt_qtc_addKeyToInputQueue( pQTC, HB_INKEY_NEW_UNICODE( wc ) );
      }
      evt->accept();
   }
   else
      QWidget::inputMethodEvent( evt );
}

void QTConsole::keyReleaseEvent( QKeyEvent * evt )
{
   if( selectMode && ( evt->modifiers() & Qt::ShiftModifier ) == 0 )
      copySelection();

   QWidget::keyReleaseEvent( evt );
}

void QTConsole::keyPressEvent( QKeyEvent * evt )
{
   int iKey = 0, iFlags = hb_gt_qtc_getKeyFlags( evt->modifiers() ),
       iSize;

   /* support for national characters */
   if( ( iSize = evt->text().size() ) > 0 )
   {
      QString qStr = evt->text();
      HB_WCHAR wc = qStr[ 0 ].unicode();

      if( iSize > 1 || ( wc >= 32 && wc != 127 ) )
      {
         int i;

         if( ( iFlags & HB_KF_CTRL ) != 0 && ( iFlags & HB_KF_ALT ) != 0 )
            /* workaround for AltGR and German keyboard */
            iFlags &= ~( HB_KF_CTRL | HB_KF_ALT );

         for( i = 0; i < iSize; ++i )
         {
            wc = qStr[ i ].unicode();
            hb_gt_qtc_addKeyToInputQueue( pQTC,
                                          wc < 127 &&
                                          ( iFlags & ( HB_KF_CTRL | HB_KF_ALT ) ) ?
                                          HB_INKEY_NEW_KEY( wc, iFlags ) :
                                          HB_INKEY_NEW_UNICODEF( wc, iFlags ) );
         }
         return;
      }
   }

   switch( evt->key() )
   {
      case Qt::Key_F1:
         iKey = HB_KX_F1;
         break;
      case Qt::Key_F2:
         iKey = HB_KX_F2;
         break;
      case Qt::Key_F3:
         iKey = HB_KX_F3;
         break;
      case Qt::Key_F4:
         iKey = HB_KX_F4;
         break;
      case Qt::Key_F5:
         iKey = HB_KX_F5;
         break;
      case Qt::Key_F6:
         iKey = HB_KX_F6;
         break;
      case Qt::Key_F7:
         iKey = HB_KX_F7;
         break;
      case Qt::Key_F8:
         iKey = HB_KX_F8;
         break;
      case Qt::Key_F9:
         iKey = HB_KX_F9;
         break;
      case Qt::Key_F10:
         iKey = HB_KX_F10;
         break;
      case Qt::Key_F11:
         iKey = HB_KX_F11;
         break;
      case Qt::Key_F12:
         iKey = HB_KX_F12;
         break;
      case Qt::Key_Up:
         iKey = HB_KX_UP;
         break;
      case Qt::Key_Down:
         iKey = HB_KX_DOWN;
         break;
      case Qt::Key_Left:
         iKey = HB_KX_LEFT;
         break;
      case Qt::Key_Right:
         iKey = HB_KX_RIGHT;
         break;
      case Qt::Key_Home:
         iKey = HB_KX_HOME;
         break;
      case Qt::Key_End:
         iKey = HB_KX_END;
         break;
      case Qt::Key_PageUp:
         iKey = HB_KX_PGUP;
         break;
      case Qt::Key_PageDown:
         iKey = HB_KX_PGDN;
         break;
      case Qt::Key_Insert:
         iKey = HB_KX_INS;
         break;
      case Qt::Key_Delete:
         iKey = HB_KX_DEL;
         break;
      case Qt::Key_Backspace:
         iKey = HB_KX_BS;
         break;
      case Qt::Key_Tab:
         iKey = HB_KX_TAB;
         break;
      case Qt::Key_Backtab:
         iKey = HB_KX_TAB;
         iFlags |= HB_KF_SHIFT;
         break;
      case Qt::Key_Escape:
         iKey = HB_KX_ESC;
         break;
      case Qt::Key_Return:
      case Qt::Key_Enter:
         if( pQTC->fAltEnter && ( iFlags & HB_KF_ALT ) != 0 &&
                                ( iFlags & HB_KF_KEYPAD ) == 0 )
         {
            pQTC->fFullScreen = ( pQTC->qWnd->windowState() & Qt::WindowFullScreen ) == 0;
            hb_gt_qtc_setWindowState( pQTC, Qt::WindowFullScreen, pQTC->fFullScreen, HB_TRUE );
            return;
         }
         iKey = HB_KX_ENTER;
         break;
      case Qt::Key_Menu:
         hb_gt_qtc_addKeyToInputQueue( pQTC, HB_K_MENU );
         break;
      case Qt::Key_Clear:
         iKey = HB_KX_CENTER;
         break;
      case Qt::Key_Print:
         iKey = HB_KX_PRTSCR;
         break;
      case Qt::Key_Pause:
         iKey = HB_KX_PAUSE;
         break;
      case Qt::Key_Space:
         iKey = ' ';
         break;
      case Qt::Key_Exclam:
         iKey = '!';
         break;
      case Qt::Key_QuoteDbl:
         iKey = '"';
         break;
      case Qt::Key_NumberSign:
         iKey = '#';
         break;
      case Qt::Key_Dollar:
         iKey = '$';
         break;
      case Qt::Key_Percent:
         iKey = '%';
         break;
      case Qt::Key_Ampersand:
         iKey = '&';
         break;
      case Qt::Key_Apostrophe:
         iKey = '\'';
         break;
      case Qt::Key_ParenLeft:
         iKey = '(';
         break;
      case Qt::Key_ParenRight:
         iKey = ')';
         break;
      case Qt::Key_Asterisk:
         iKey = '*';
         break;
      case Qt::Key_Plus:
         iKey = '+';
         break;
      case Qt::Key_Comma:
         iKey = ',';
         break;
      case Qt::Key_Minus:
         iKey = '-';
         break;
      case Qt::Key_Period:
         iKey = '.';
         break;
      case Qt::Key_Slash:
         iKey = '/';
         break;
      case Qt::Key_0:
         iKey = '0';
         break;
      case Qt::Key_1:
         iKey = '1';
         break;
      case Qt::Key_2:
         iKey = '2';
         break;
      case Qt::Key_3:
         iKey = '3';
         break;
      case Qt::Key_4:
         iKey = '4';
         break;
      case Qt::Key_5:
         iKey = '5';
         break;
      case Qt::Key_6:
         iKey = '6';
         break;
      case Qt::Key_7:
         iKey = '7';
         break;
      case Qt::Key_8:
         iKey = '8';
         break;
      case Qt::Key_9:
         iKey = '9';
         break;
      case Qt::Key_Colon:
         iKey = ':';
         break;
      case Qt::Key_Semicolon:
         iKey = ';';
         break;
      case Qt::Key_Less:
         iKey = '<';
         break;
      case Qt::Key_Equal:
         iKey = '=';
         break;
      case Qt::Key_Greater:
         iKey = '>';
         break;
      case Qt::Key_Question:
         iKey = '?';
         break;
      case Qt::Key_At:
         iKey = '@';
         break;
      case Qt::Key_A:
         iKey = 'A';
         break;
      case Qt::Key_B:
         iKey = 'B';
         break;
      case Qt::Key_C:
         iKey = 'C';
         break;
      case Qt::Key_D:
         iKey = 'D';
         break;
      case Qt::Key_E:
         iKey = 'E';
         break;
      case Qt::Key_F:
         iKey = 'F';
         break;
      case Qt::Key_G:
         iKey = 'G';
         break;
      case Qt::Key_H:
         iKey = 'H';
         break;
      case Qt::Key_I:
         iKey = 'I';
         break;
      case Qt::Key_J:
         iKey = 'J';
         break;
      case Qt::Key_K:
         iKey = 'K';
         break;
      case Qt::Key_L:
         iKey = 'L';
         break;
      case Qt::Key_M:
         iKey = 'M';
         break;
      case Qt::Key_N:
         iKey = 'N';
         break;
      case Qt::Key_O:
         iKey = 'O';
         break;
      case Qt::Key_P:
         iKey = 'P';
         break;
      case Qt::Key_Q:
         iKey = 'Q';
         break;
      case Qt::Key_R:
         iKey = 'R';
         break;
      case Qt::Key_S:
         iKey = 'S';
         break;
      case Qt::Key_T:
         iKey = 'T';
         break;
      case Qt::Key_U:
         iKey = 'U';
         break;
      case Qt::Key_V:
         iKey = 'V';
         break;
      case Qt::Key_W:
         iKey = 'W';
         break;
      case Qt::Key_X:
         iKey = 'X';
         break;
      case Qt::Key_Y:
         iKey = 'Y';
         break;
      case Qt::Key_Z:
         iKey = 'Z';
         break;
      case Qt::Key_BracketLeft:
         iKey = '[';
         break;
      case Qt::Key_Backslash:
         iKey = '\\';
         break;
      case Qt::Key_BracketRight:
         iKey = ']';
         break;
      case Qt::Key_AsciiCircum:
         iKey = '^';
         break;
      case Qt::Key_Underscore:
         iKey = '_';
         break;
      case Qt::Key_QuoteLeft:
         iKey = '`';
         break;
      case Qt::Key_BraceLeft:
         iKey = '{';
         break;
      case Qt::Key_Bar:
         iKey = '|';
         break;
      case Qt::Key_BraceRight:
         iKey = '}';
         break;
      case Qt::Key_AsciiTilde:
         iKey = '~';
         break;
      default:
         break;
   }

   if( iKey != 0 )
      hb_gt_qtc_addKeyToInputQueue( pQTC, HB_INKEY_NEW_KEY( iKey, iFlags ) );
   else
      QWidget::keyPressEvent( evt );
}

/* --- */

QTCWindow::QTCWindow( PHB_GTQTC pQTC )
{
   Qt::WindowFlags flags = ( windowFlags() & Qt::WindowType_Mask ) |
                           Qt::CustomizeWindowHint                 |
                           Qt::Window;
   if( pQTC->fNoFrame )
   {
      flags |= Qt::FramelessWindowHint;
   }
   else
   {
      if( pQTC->iCloseMode < 2 )
         flags |= Qt::WindowCloseButtonHint;
      if( pQTC->fResizable )
         flags |= Qt::WindowMaximizeButtonHint;
      flags |= Qt::WindowMinimizeButtonHint |
               Qt::WindowSystemMenuHint |
               Qt::WindowTitleHint;
   }

   setWindowFlags( flags );

   /* set default size used when leaving initial
    * fullscreen or maximized mode [druzus]
    */
   resize( pQTC->cellX * pQTC->iCols, pQTC->cellY * pQTC->iRows );

   if( pQTC->fFullScreen )
      setWindowState( windowState() | Qt::WindowFullScreen );
   else if( pQTC->fMaximized )
      setWindowState( windowState() | Qt::WindowMaximized );
   else if( pQTC->fMinimized )
      setWindowState( windowState() | Qt::WindowMinimized );

   if( pQTC->qIcon )
      setWindowIcon( *pQTC->qIcon );
   setWindowTitle( *pQTC->wndTitle );

   qConsole = new QTConsole( pQTC );
   setCentralWidget( qConsole );
   setFocusProxy( qConsole );
   setFocusPolicy( Qt::StrongFocus );
   /* In windows it helps to keep focus in fullscreen or maximized
    * windows [druzus]
    */
   setFocus( Qt::OtherFocusReason );
}

QTCWindow::~QTCWindow( void )
{
   delete qConsole;
}

void QTCWindow::closeEvent( QCloseEvent * evt )
{
   if( qConsole->pQTC->iCloseMode == 0 )
      hb_vmRequestQuit();
   else
      hb_gt_qtc_addKeyToInputQueue( qConsole->pQTC, HB_K_CLOSE );

   evt->ignore();
}

void QTCWindow::setWindowSize( void )
{
   if( ( windowState() & ( Qt::WindowMaximized | Qt::WindowFullScreen ) ) != 0 )
   {
      qConsole->pQTC->marginLeft = width() - qConsole->image->width();
      if( qConsole->pQTC->marginLeft > 0 )
         qConsole->pQTC->marginLeft >>= 1;
      else
         qConsole->pQTC->marginLeft = 0;

      qConsole->pQTC->marginTop = height() - qConsole->image->height();
      if( qConsole->pQTC->marginTop > 0 )
         qConsole->pQTC->marginTop >>= 1;
      else
         qConsole->pQTC->marginTop = 0;
   }
   else
   {
      qConsole->pQTC->marginLeft = qConsole->pQTC->marginTop = 0;
      resize( qConsole->image->size() );
   }
   setResizing();
}

void QTCWindow::setResizing( void )
{
   if( qConsole->pQTC->fResizable )
   {
#if QT_VERSION >= 0x050E00
      /* setMaximumSize( screen()->availableSize() ); */
      setMaximumSize( screen()->size() );
#else
      /* setMaximumSize( screen()->availableGeometry( this ).size() ); */
      setMaximumSize( QApplication::desktop()->screenGeometry( this ).size() );
#endif
      if( qConsole->pQTC->iResizeMode == HB_GTI_RESIZEMODE_ROWS )
      {
         setMinimumSize( qConsole->pQTC->cellX << 1, qConsole->pQTC->cellY << 1 );
         if( ! qConsole->pQTC->fResizeInc || ( windowState() & Qt::WindowMaximized ) != 0 )
            setSizeIncrement( 0, 0 );
         else
            setSizeIncrement( qConsole->pQTC->cellX, qConsole->pQTC->cellY );
      }
      else
      {
         setMinimumSize( qConsole->pQTC->iCols << 1, qConsole->pQTC->iRows << 2 );
         if( ! qConsole->pQTC->fResizeInc || ( windowState() & Qt::WindowMaximized ) != 0 )
            setSizeIncrement( 0, 0 );
         else
            setSizeIncrement( qConsole->pQTC->iCols, qConsole->pQTC->iRows );
      }
   }
   else
   {
      setFixedSize( size() );
      setSizeIncrement( 0, 0 );
   }
}

/* --- */

#ifdef HB_XLIB_NEEDLOCKS

#include <X11/Xlib.h>

static void hb_gt_qtc_InitMT( void )
{
   if( hb_vmIsMt() )
   {
      if( ! XInitThreads() )
         hb_errInternal( 10002, "XInitThreads() failed !!!", NULL, NULL );
   }
}

#else

static void hb_gt_qtc_InitMT( void ) { }

#endif

/* --- */
