/****************************************************************************
** $Id: qcursor_pm.cpp 8 2005-11-16 19:36:46Z dmik $
**
** Implementation of QCursor class for OS/2
**
** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
** Copyright (C) 2004 Norman ASA.  Initial OS/2 Port.
** Copyright (C) 2005 netlabs.org.  Further OS/2 Development.
**
** This file is part of the kernel module of the Qt GUI Toolkit.
**
** This file may be distributed under the terms of the Q Public License
** as defined by Trolltech AS of Norway and appearing in the file
** LICENSE.QPL included in the packaging of this file.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
** licenses may use this file in accordance with the Qt Commercial License
** Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
**   information about Qt Commercial License Agreements.
** See http://www.trolltech.com/qpl/ for QPL licensing information.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/

#include "qcursor.h"
#include "qbitmap.h"
#include "qapplication.h"
#include "qapplication_p.h"
#include "qimage.h"
#include "qdatastream.h"
#include "qt_os2.h"

static QCursor cursorTable[Qt::LastCursor+1];

QT_STATIC_CONST_IMPL QCursor & Qt::arrowCursor = cursorTable[0];
QT_STATIC_CONST_IMPL QCursor & Qt::upArrowCursor = cursorTable[1];
QT_STATIC_CONST_IMPL QCursor & Qt::crossCursor = cursorTable[2];
QT_STATIC_CONST_IMPL QCursor & Qt::waitCursor = cursorTable[3];
QT_STATIC_CONST_IMPL QCursor & Qt::ibeamCursor = cursorTable[4];
QT_STATIC_CONST_IMPL QCursor & Qt::sizeVerCursor = cursorTable[5];
QT_STATIC_CONST_IMPL QCursor & Qt::sizeHorCursor = cursorTable[6];
QT_STATIC_CONST_IMPL QCursor & Qt::sizeBDiagCursor = cursorTable[7];
QT_STATIC_CONST_IMPL QCursor & Qt::sizeFDiagCursor = cursorTable[8];
QT_STATIC_CONST_IMPL QCursor & Qt::sizeAllCursor = cursorTable[9];
QT_STATIC_CONST_IMPL QCursor & Qt::blankCursor = cursorTable[10];
QT_STATIC_CONST_IMPL QCursor & Qt::splitVCursor = cursorTable[11];
QT_STATIC_CONST_IMPL QCursor & Qt::splitHCursor = cursorTable[12];
QT_STATIC_CONST_IMPL QCursor & Qt::pointingHandCursor = cursorTable[13];
QT_STATIC_CONST_IMPL QCursor & Qt::forbiddenCursor = cursorTable[14];
QT_STATIC_CONST_IMPL QCursor & Qt::whatsThisCursor = cursorTable[15];
QT_STATIC_CONST_IMPL QCursor & Qt::busyCursor = cursorTable[16];


/*****************************************************************************
  Internal QCursorData class
 *****************************************************************************/

struct QCursorData : public QShared {
    QCursorData( int s = 0 );
   ~QCursorData();
    int	      cshape;
    QBitmap  *bm, *bmm;
    short     hx, hy;
    HPOINTER  hptr;
    bool      is_sysptr;
};

QCursorData::QCursorData( int s )
{
    cshape = s;
    hptr = 0;
    is_sysptr = false;
    bm = bmm = 0;
    hx = hy  = 0;
}

QCursorData::~QCursorData()
{
    if ( bm ) delete bm;
    if ( bmm ) delete bmm;
    if ( hptr && !is_sysptr )
        WinDestroyPointer( hptr );
}


/*****************************************************************************
  QCursor member functions
 *****************************************************************************/

QCursor *QCursor::find_cur( int shape )	// find predefined cursor
{
    return (uint)shape <= LastCursor ? &cursorTable[shape] : 0;
}


static bool initialized = FALSE;

void QCursor::initialize()
{
    int shape;
    for( shape = 0; shape <= LastCursor; shape++ )
	cursorTable[shape].data = new QCursorData( shape );
    initialized = TRUE;
    qAddPostRoutine( cleanup );
}

void QCursor::cleanup()
{
    int shape;
    for( shape = 0; shape <= LastCursor; shape++ ) {
	if ( cursorTable[shape].data && cursorTable[shape].data->deref() )
	    delete cursorTable[shape].data;
	cursorTable[shape].data = 0;
    }
    initialized = FALSE;
}

QCursor::QCursor()
{
    if ( !initialized ) {
	if ( qApp->startingUp() ) {
	    data = 0;
	    return;
	}
	initialize();
    }
    QCursor* c = (QCursor *)&arrowCursor;
    c->data->ref();
    data = c->data;
}

QCursor::QCursor( int shape )
{
    if ( !initialized )
	initialize();
    QCursor *c = find_cur( shape );
    if ( !c )					// not found
	c = (QCursor *)&arrowCursor;	//   then use arrowCursor
    c->data->ref();
    data = c->data;
}


void QCursor::setBitmap( const QBitmap &bitmap, const QBitmap &mask,
			 int hotX, int hotY )
{
    if ( !initialized )
	initialize();
    if ( bitmap.depth() != 1 || mask.depth() != 1 ||
	 bitmap.size() != mask.size() ) {
#if defined(QT_CHECK_NULL)
	qWarning( "QCursor: Cannot create bitmap cursor; invalid bitmap(s)" );
#endif
	QCursor *c = (QCursor *)&arrowCursor;
	c->data->ref();
	data = c->data;
	return;
    }
    data = new QCursorData;
    Q_CHECK_PTR( data );
    data->bm  = new QBitmap( bitmap );
    data->bmm = new QBitmap( mask );
    data->hptr = 0;
    data->cshape = BitmapCursor;
    data->hx = hotX >= 0 ? hotX : bitmap.width()/2;
    data->hy = hotY >= 0 ? hotY : bitmap.height()/2;
}

QCursor::QCursor( const QCursor &c )
{
    if ( !initialized )
	initialize();
    data = c.data;
    data->ref();
}

QCursor::~QCursor()
{
    if ( data && data->deref() )
	delete data;
}


QCursor &QCursor::operator=( const QCursor &c )
{
    if ( !initialized )
	initialize();
    if ( !initialized )
	initialize();
    c.data->ref();				// avoid c = c
    if ( data && data->deref() )
	delete data;
    data = c.data;
    return *this;
}


int QCursor::shape() const
{
    if ( !initialized )
	initialize();
    return data->cshape;
}

void QCursor::setShape( int shape )
{
    if ( !initialized )
	initialize();
    QCursor *c = find_cur( shape );		// find one of the global ones
    if ( !c )					// not found
	c = (QCursor *)&arrowCursor;	//   then use arrowCursor
    c->data->ref();
    if ( data->deref() )			// make shallow copy
	delete data;
    data = c->data;
}


const QBitmap *QCursor::bitmap() const
{
    if ( !initialized )
	initialize();
    return data->bm;
}

const QBitmap *QCursor::mask() const
{
    if ( !initialized )
	initialize();
    return data->bmm;
}

QPoint QCursor::hotSpot() const
{
    if ( !initialized )
	initialize();
    return QPoint( data->hx, data->hy );
}


HPOINTER QCursor::handle() const
{
    if ( !initialized )
	initialize();
    if ( !data->hptr && data->cshape != BlankCursor )
	update();
    return data->hptr;
}

QCursor::QCursor( HPOINTER handle )
{
    data = new QCursorData;
    data->hptr = handle;
}

QPoint QCursor::pos()
{
    POINTL p;
    WinQueryPointerPos( HWND_DESKTOP, &p);
    // flip y coordinate
    p.y = QApplication::desktop()->height() - (p.y + 1);
    return QPoint( p.x, p.y );
}

void QCursor::setPos( int x, int y )
{
    WinSetPointerPos( HWND_DESKTOP, x, y);
}


void QCursor::update() const
{
    if ( !initialized )
	initialize();
    if ( data->hptr )				// already loaded
	return;
    if ( data->cshape == BlankCursor )          // blank pointer = null handle
        return;

    // Non-standard OS/2 cursors are created from bitmaps

    static const uchar vsplit_bits[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
	0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
	0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
	0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
	0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
	0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar vsplitm_bits[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
	0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
	0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
	0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
	0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
	0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
	0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
	0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar hsplit_bits[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
	0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
	0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03,
	0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00,
	0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
	0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar hsplitm_bits[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
	0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00,
	0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
	0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00,
	0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
	0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar phand_bits[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00,
	0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00,
	0x80, 0x1c, 0x00, 0x00, 0x80, 0xe4, 0x00, 0x00, 0x80, 0x24, 0x03, 0x00,
	0x80, 0x24, 0x05, 0x00, 0xb8, 0x24, 0x09, 0x00, 0xc8, 0x00, 0x09, 0x00,
	0x88, 0x00, 0x08, 0x00, 0x90, 0x00, 0x08, 0x00, 0xa0, 0x00, 0x08, 0x00,
	0x20, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x04, 0x00,
	0x80, 0x00, 0x04, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x01, 0x02, 0x00,
	0x00, 0x01, 0x02, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar phandm_bits[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00,
	0x80, 0x07, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00,
	0x80, 0x1f, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x80, 0xff, 0x03, 0x00,
	0x80, 0xff, 0x07, 0x00, 0xb8, 0xff, 0x0f, 0x00, 0xf8, 0xff, 0x0f, 0x00,
	0xf8, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xe0, 0xff, 0x0f, 0x00,
	0xe0, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x07, 0x00,
	0x80, 0xff, 0x07, 0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0xff, 0x03, 0x00,
	0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar whatsthis_bits[] = {
        0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
        0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
        0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
        0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00,
        0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00,
        0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00,
        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar whatsthism_bits[] = {
        0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
        0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
        0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
        0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00,
        0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00,
        0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00,
        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//    static const uchar busy_bits[] = {
//	0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
//	0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
//	0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
//	0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00,
//	0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00,
//	0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00,
//	0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00,
//	0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
//	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//    static const uchar busym_bits[] = {
//	0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
//	0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
//	0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
//	0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00,
//	0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00,
//	0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00,
//	0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00,
//	0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
//	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    static const uchar uparrow_bits[] = {
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF,
        0xDF, 0xFD, 0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xF7, 0xF7, 0xFF,
        0xFF, 0x87, 0xF0, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF, 0xBF, 0xFE,
        0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF, 0xBF,
        0xFE, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF,
        0xBF, 0xFE, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF,
        0xFF, 0xBF, 0xFE, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFF, 0x3F, 0xFE,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    static const uchar uparrowm_bits[] = {
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00,
       0xE0, 0x03, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xF8, 0x0F, 0x00,
       0x00, 0xF8, 0x0F, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01,
       0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0,
       0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00,
       0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00,
       0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x01,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

    static const uchar cross_bits_os2[] = {
        // AND mask (XBitmap, flipped top to bottom)
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        // XOR mask (XBitmap, flipped top to bottom)
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
        0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0xFF,
        0xFF, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
        0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

    LONG id = 0;
    const uchar *bits = 0;
    const uchar *mask = 0;
    BOOL isbitmap = FALSE;

    switch ( data->cshape ) {			// map to OS/2 cursor
    case ArrowCursor:
	id = SPTR_ARROW;
	break;
    case WaitCursor:
	id = SPTR_WAIT;
	break;
    case IbeamCursor:
	id = SPTR_TEXT;
	break;
    case SizeVerCursor:
	id = SPTR_SIZENS;
	break;
    case SizeHorCursor:
	id = SPTR_SIZEWE;
	break;
    case SizeBDiagCursor:
	id = SPTR_SIZENESW;
	break;
    case SizeFDiagCursor:
	id = SPTR_SIZENWSE;
	break;
    case SizeAllCursor:
	id = SPTR_MOVE;
	break;
    case ForbiddenCursor:
	id = SPTR_ILLEGAL;
	break;
    case WhatsThisCursor:
        bits = whatsthis_bits;
        mask = whatsthism_bits;
        data->hx = data->hy = 0;
	break;
//    case BusyCursor:
//        bits = busy_bits;
//        mask = busym_bits;
//        data->hx = data->hy = 0;
//        break;
    case PointingHandCursor:
        bits = phand_bits;
        mask = phandm_bits;
        data->hx = 7;
        data->hy = 0;
        break;
    case SplitVCursor:
        bits = vsplit_bits;
        mask = vsplitm_bits;
        data->hx = data->hy = 16;
        break;
    case SplitHCursor:
        bits = hsplit_bits;
        mask = hsplitm_bits;
        data->hx = data->hy = 16;
        break;
    case UpArrowCursor:
        bits = uparrow_bits;
        mask = uparrowm_bits;
        data->hx = 15;
        data->hy = 6;
        break;
    case BitmapCursor:
        isbitmap = TRUE;
        break;
    case CrossCursor: {
        QBitmap ptr( 32, 64, cross_bits_os2, TRUE );
        GpiSetBitmap( ptr.handle(), 0 );
        data->hx = data->hy = 16;
        data->hptr = WinCreatePointer(
            HWND_DESKTOP, ptr.hbm(), TRUE, data->hx, 31 - data->hy
        );
	return;
    }
    case BusyCursor: {
        // we create a busy cursor below as a combination of the standard
        // arrow and wait cursors
        POINTERINFO piarrow, piwait;
        HPOINTER harrow = WinQuerySysPointer( HWND_DESKTOP, SPTR_ARROW, FALSE );
        WinQueryPointerInfo( harrow, &piarrow );
        HPOINTER hwait = WinQuerySysPointer( HWND_DESKTOP, SPTR_WAIT, FALSE );
        WinQueryPointerInfo( hwait, &piwait );
        if ( piarrow.hbmColor ) {
            QPixmap ptr( 32, 32 );
            HPS hpsPtr = ptr.handle();
            QPixmap tmp( 32, 32 );
            HPS hpsTmp = tmp.handle();
            QBitmap mask( 32, 64, TRUE );
            HPS hpsMask = mask.handle();
            // copy the overlying pointer
            POINTL ptls[] = { { 0, 0 }, { 31, 31 }, { 0, 0 }, { 32, 32 } };
            GpiWCBitBlt( hpsTmp, piarrow.hbmColor, 4, ptls, ROP_SRCCOPY, BBO_IGNORE );
            // make its transparent pixels black
            ptls[2].y += 32; ptls[3].y += 32;
            GpiSetColor( hpsTmp, CLR_TRUE );
            GpiSetBackColor( hpsTmp, CLR_FALSE );
            GpiWCBitBlt( hpsTmp, piarrow.hbmPointer, 4, ptls, 0x22, BBO_IGNORE );
            // copy the underlying pointer
            ptls[2].y -= 32; ptls[3].y -= 32;
            GpiWCBitBlt( hpsPtr, piwait.hbmColor, 4, ptls, ROP_SRCCOPY, BBO_IGNORE );
            // make non-transparent pixels from the overlying pointer black
            ptls[2].y += 32; ptls[3].y += 32;
            GpiSetColor( hpsPtr, CLR_TRUE );
            GpiSetBackColor( hpsPtr, CLR_FALSE );
            GpiWCBitBlt( hpsPtr, piarrow.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE );
            // put the overlying pointer there
            ptls[2].y -= 32; ptls[3].y -= 32;
            ptls[1].x ++; ptls[1].y ++;
            GpiBitBlt( hpsPtr, hpsTmp, 4, ptls, ROP_SRCPAINT, BBO_IGNORE );
            // copy both underlying pointer's masks
            ptls[1].x --; ptls[1].y --;
            ptls[1].y += 32; ptls[3].y += 32;
            GpiWCBitBlt( hpsMask, piwait.hbmPointer, 4, ptls, ROP_SRCCOPY, BBO_IGNORE );
            // add overlying pointer's XOR mask
            ptls[1].y -= 32; ptls[3].y -= 32;
            GpiWCBitBlt( hpsMask, piarrow.hbmPointer, 4, ptls, ROP_SRCPAINT, BBO_IGNORE );
            // add overlying pointer's AND mask
            ptls[0].y += 32; ptls[2].y += 32;
            ptls[1].y += 32; ptls[3].y += 32;
            GpiWCBitBlt( hpsMask, piarrow.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE );
            // create the new pointer
            GpiSetBitmap( hpsPtr, 0 );
            GpiSetBitmap( hpsMask, 0 );
            piarrow.hbmColor = ptr.hbm();
            piarrow.hbmPointer = mask.hbm();
            piarrow.hbmMiniColor = 0;
            piarrow.hbmMiniPointer = 0;
            data->hptr = WinCreatePointerIndirect( HWND_DESKTOP, &piarrow );
        } else {
            QBitmap ptr( 32, 64, TRUE );
            HPS hps = ptr.handle();
            POINTL ptls[] = { { 0, 0 }, { 31, 63 }, { 0, 0 }, { 32, 64 } };
            // make a copy of the underlying pointer
            GpiWCBitBlt( hps, piwait.hbmPointer, 4, ptls, ROP_SRCCOPY, BBO_IGNORE );
            // combine AND masks
            ptls[0].y += 32; ptls[2].y += 32;
            GpiWCBitBlt( hps, piarrow.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE );
            // apply the overlying AND mask to the underlying XOR mask
            ptls[0].y -= 32; ptls[1].y -= 32;
            GpiWCBitBlt( hps, piarrow.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE );
            // apply the overlying XOR mask to the underlying XOR mask
            ptls[2].y -= 32; ptls[3].y -= 32;
            GpiWCBitBlt( hps, piarrow.hbmPointer, 4, ptls, ROP_SRCINVERT, BBO_IGNORE );
            // create the new pointer
            GpiSetBitmap( hps, 0 );
            data->hptr = WinCreatePointer(
                HWND_DESKTOP, ptr.hbm(), TRUE, piarrow.xHotspot, piarrow.yHotspot
            );
        }
        data->hx = piarrow.xHotspot;
        data->hy = 31 - piarrow.yHotspot;
        return;
    }
    default:
#if defined(QT_CHECK_RANGE)
	qWarning( "QCursor::update: Invalid cursor shape %d",
		  data->cshape );
#endif
	return;
    }

    if ( (bits && mask) || isbitmap ) {
        QBitmap bm = isbitmap ? *data->bm : QBitmap( 32, 32, bits, TRUE );
        QBitmap bmm = isbitmap ? *data->bmm : QBitmap( 32, 32, mask, TRUE );
        QBitmap ptr( 32, 64, TRUE );
        // prepare XOR mask
        bitBlt( &ptr, 0, 32, &bm, 0, 0, -1, -1, NotCopyROP, TRUE );
        // crop XOR mask
        bitBlt( &ptr, 0, 32, &bmm, 0, 0, -1, -1, AndROP, TRUE );
        // set AND mask
        bitBlt( &ptr, 0, 0, &bmm, 0, 0, -1, -1, NotCopyROP, TRUE );
        GpiSetBitmap( ptr.handle(), 0 );
        data->hptr = WinCreatePointer(
            HWND_DESKTOP, ptr.hbm(), TRUE, data->hx, 31 - data->hy
        );
    } else {
        data->hptr = WinQuerySysPointer( HWND_DESKTOP, id, FALSE );
        data->is_sysptr = true;
    }
}
