# HG changeset patch # User Frank Benoit # Date 1201476142 -3600 # Node ID b868bfa989cd11aa8aaa311d21b8b998cd9f8dc3 # Parent 39834037712c2f8f475cedba073451a09298a719 Cursor diff -r 39834037712c -r b868bfa989cd dwt/dwthelper/utils.d --- a/dwt/dwthelper/utils.d Sun Jan 27 23:42:27 2008 +0100 +++ b/dwt/dwthelper/utils.d Mon Jan 28 00:22:22 2008 +0100 @@ -92,6 +92,10 @@ dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ]; } +public wchar[] toCharArray( char[] str ){ + return StrToWCHARs( str ); +} + public bool endsWith( char[] src, char[] pattern ){ if( src.length < pattern.length ){ return false; diff -r 39834037712c -r b868bfa989cd dwt/graphics/Cursor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/graphics/Cursor.d Mon Jan 28 00:22:22 2008 +0100 @@ -0,0 +1,484 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.graphics.Cursor; + + +import dwt.DWT; +import dwt.DWTError; +import dwt.internal.win32.OS; + +import dwt.graphics.Resource; +import dwt.graphics.Device; +import dwt.graphics.ImageData; +import dwt.graphics.RGB; +import dwt.graphics.PaletteData; +import dwt.graphics.Image; + +import tango.text.convert.Format; + +/** + * Instances of this class manage operating system resources that + * specify the appearance of the on-screen pointer. To create a + * cursor you specify the device and either a simple cursor style + * describing one of the standard operating system provided cursors + * or the image and mask data for the desired appearance. + *

+ * Application code must explicitly invoke the Cursor.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

+ *
+ *
Styles:
+ *
+ * CURSOR_ARROW, CURSOR_WAIT, CURSOR_CROSS, CURSOR_APPSTARTING, CURSOR_HELP, + * CURSOR_SIZEALL, CURSOR_SIZENESW, CURSOR_SIZENS, CURSOR_SIZENWSE, CURSOR_SIZEWE, + * CURSOR_SIZEN, CURSOR_SIZES, CURSOR_SIZEE, CURSOR_SIZEW, CURSOR_SIZENE, CURSOR_SIZESE, + * CURSOR_SIZESW, CURSOR_SIZENW, CURSOR_UPARROW, CURSOR_IBEAM, CURSOR_NO, CURSOR_HAND + *
+ *
+ *

+ * Note: Only one of the above styles may be specified. + *

+ */ + +public final class Cursor : Resource { + + /** + * the handle to the OS cursor resource + * (Warning: This field is platform dependent) + *

+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *

+ */ + public HCURSOR handle; + + bool isIcon; + + /** + * data used to create a HAND cursor. + */ + static const byte[] HAND_SOURCE = [ + cast(byte)0xf9,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x3f,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x07,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x03,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x00,cast(byte)0xff,cast(byte)0xff, + + cast(byte)0x10,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0x80,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xc0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xe0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xf0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff, + cast(byte)0xf8,cast(byte)0x00,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xfc,cast(byte)0x01,cast(byte)0xff,cast(byte)0xff, + + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff, + cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff + ]; + static const byte[] HAND_MASK = [ + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0xc0,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0xd8,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x06,cast(byte)0xd8,cast(byte)0x00,cast(byte)0x00, + + cast(byte)0x07,cast(byte)0xdb,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x67,cast(byte)0xfb,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x3f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x1f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x0f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x07,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x03,cast(byte)0xfe,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00, + cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00 + ]; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this() { +} + +/** + * Constructs a new cursor given a device and a style + * constant describing the desired cursor appearance. + *

+ * You must dispose the cursor when it is no longer required. + *

+ * + * @param device the device on which to allocate the cursor + * @param style the style of cursor to allocate + * + * @exception IllegalArgumentException + * @exception DWTError + * + * @see DWT#CURSOR_ARROW + * @see DWT#CURSOR_WAIT + * @see DWT#CURSOR_CROSS + * @see DWT#CURSOR_APPSTARTING + * @see DWT#CURSOR_HELP + * @see DWT#CURSOR_SIZEALL + * @see DWT#CURSOR_SIZENESW + * @see DWT#CURSOR_SIZENS + * @see DWT#CURSOR_SIZENWSE + * @see DWT#CURSOR_SIZEWE + * @see DWT#CURSOR_SIZEN + * @see DWT#CURSOR_SIZES + * @see DWT#CURSOR_SIZEE + * @see DWT#CURSOR_SIZEW + * @see DWT#CURSOR_SIZENE + * @see DWT#CURSOR_SIZESE + * @see DWT#CURSOR_SIZESW + * @see DWT#CURSOR_SIZENW + * @see DWT#CURSOR_UPARROW + * @see DWT#CURSOR_IBEAM + * @see DWT#CURSOR_NO + * @see DWT#CURSOR_HAND + */ +public this(Device device, int style) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + this.device = device; + int lpCursorName = 0; + switch (style) { + case DWT.CURSOR_HAND: lpCursorName = OS.IDC_HAND; break; + case DWT.CURSOR_ARROW: lpCursorName = OS.IDC_ARROW; break; + case DWT.CURSOR_WAIT: lpCursorName = OS.IDC_WAIT; break; + case DWT.CURSOR_CROSS: lpCursorName = OS.IDC_CROSS; break; + case DWT.CURSOR_APPSTARTING: lpCursorName = OS.IDC_APPSTARTING; break; + case DWT.CURSOR_HELP: lpCursorName = OS.IDC_HELP; break; + case DWT.CURSOR_SIZEALL: lpCursorName = OS.IDC_SIZEALL; break; + case DWT.CURSOR_SIZENESW: lpCursorName = OS.IDC_SIZENESW; break; + case DWT.CURSOR_SIZENS: lpCursorName = OS.IDC_SIZENS; break; + case DWT.CURSOR_SIZENWSE: lpCursorName = OS.IDC_SIZENWSE; break; + case DWT.CURSOR_SIZEWE: lpCursorName = OS.IDC_SIZEWE; break; + case DWT.CURSOR_SIZEN: lpCursorName = OS.IDC_SIZENS; break; + case DWT.CURSOR_SIZES: lpCursorName = OS.IDC_SIZENS; break; + case DWT.CURSOR_SIZEE: lpCursorName = OS.IDC_SIZEWE; break; + case DWT.CURSOR_SIZEW: lpCursorName = OS.IDC_SIZEWE; break; + case DWT.CURSOR_SIZENE: lpCursorName = OS.IDC_SIZENESW; break; + case DWT.CURSOR_SIZESE: lpCursorName = OS.IDC_SIZENWSE; break; + case DWT.CURSOR_SIZESW: lpCursorName = OS.IDC_SIZENESW; break; + case DWT.CURSOR_SIZENW: lpCursorName = OS.IDC_SIZENWSE; break; + case DWT.CURSOR_UPARROW: lpCursorName = OS.IDC_UPARROW; break; + case DWT.CURSOR_IBEAM: lpCursorName = OS.IDC_IBEAM; break; + case DWT.CURSOR_NO: lpCursorName = OS.IDC_NO; break; + default: + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + handle = OS.LoadCursor(null, cast(wchar*)lpCursorName); + /* + * IDC_HAND is supported only on Windows 2000 and Windows 98. + * Create a hand cursor if running in other Windows platforms. + */ + if (handle is null && style is DWT.CURSOR_HAND) { + int width = OS.GetSystemMetrics(OS.SM_CXCURSOR); + int height = OS.GetSystemMetrics(OS.SM_CYCURSOR); + if (width is 32 && height is 32) { + auto hInst = OS.GetModuleHandle(null); + if (OS.IsWinCE) DWT.error(DWT.ERROR_NOT_IMPLEMENTED); + handle = OS.CreateCursor(hInst, 5, 0, 32, 32, HAND_SOURCE.ptr, HAND_MASK.ptr); + + } + } + if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs a new cursor given a device, image and mask + * data describing the desired cursor appearance, and the x + * and y coordinates of the hotspot (that is, the point + * within the area covered by the cursor which is considered + * to be where the on-screen pointer is "pointing"). + *

+ * The mask data is allowed to be null, but in this case the source + * must be an ImageData representing an icon that specifies both + * color data and mask data. + *

+ * You must dispose the cursor when it is no longer required. + *

+ * + * @param device the device on which to allocate the cursor + * @param source the color data for the cursor + * @param mask the mask data for the cursor (or null) + * @param hotspotX the x coordinate of the cursor's hotspot + * @param hotspotY the y coordinate of the cursor's hotspot + * + * @exception IllegalArgumentException + * @exception DWTError + */ +public this(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + this.device = device; + if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (mask is null) { + if (source.getTransparencyType() !is DWT.TRANSPARENCY_MASK) { + DWT.error(DWT.ERROR_NULL_ARGUMENT); + } + mask = source.getTransparencyMask(); + } + /* Check the bounds. Mask must be the same size as source */ + if (mask.width !is source.width || mask.height !is source.height) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + /* Check the hotspots */ + if (hotspotX >= source.width || hotspotX < 0 || + hotspotY >= source.height || hotspotY < 0) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + /* Convert depth to 1 */ + mask = ImageData.convertMask(mask); + source = ImageData.convertMask(source); + + /* Make sure source and mask scanline pad is 2 */ + byte[] sourceData = ImageData.convertPad(source.data, source.width, source.height, source.depth, source.scanlinePad, 2); + byte[] maskData = ImageData.convertPad(mask.data, mask.width, mask.height, mask.depth, mask.scanlinePad, 2); + + /* Create the cursor */ + auto hInst = OS.GetModuleHandle(null); + if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED); + handle = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData.ptr, maskData.ptr); + if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs a new cursor given a device, image data describing + * the desired cursor appearance, and the x and y coordinates of + * the hotspot (that is, the point within the area + * covered by the cursor which is considered to be where the + * on-screen pointer is "pointing"). + *

+ * You must dispose the cursor when it is no longer required. + *

+ * + * @param device the device on which to allocate the cursor + * @param source the image data for the cursor + * @param hotspotX the x coordinate of the cursor's hotspot + * @param hotspotY the y coordinate of the cursor's hotspot + * + * @exception IllegalArgumentException + * @exception DWTError + * + * @since 3.0 + */ +public this(Device device, ImageData source, int hotspotX, int hotspotY) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + this.device = device; + if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + /* Check the hotspots */ + if (hotspotX >= source.width || hotspotX < 0 || + hotspotY >= source.height || hotspotY < 0) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + ImageData mask = source.getTransparencyMask(); + int[] result = Image.init(device, null, source, mask); + auto hBitmap = cast(HBITMAP)result[0]; + auto hMask = cast(HBITMAP)result[1]; + /* Create the icon */ + ICONINFO info; + info.fIcon = false; + info.hbmColor = hBitmap; + info.hbmMask = hMask; + info.xHotspot = hotspotX; + info.yHotspot = hotspotY; + handle = OS.CreateIconIndirect(&info); + if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); + OS.DeleteObject(hBitmap); + OS.DeleteObject(hMask); + isIcon = true; + if (device.tracking) device.new_Object(this); +} + +/** + * Disposes of the operating system resources associated with + * the cursor. Applications must dispose of all cursors which + * they allocate. + */ +public void dispose () { + if (handle is null) return; + if (device.isDisposed()) return; + + /* + * It is an error in Windows to destroy the current + * cursor. Check that the cursor that is about to + * be destroyed is the current cursor. If so, set + * the current cursor to be IDC_ARROW. Note that + * Windows shares predefined cursors so the call to + * LoadCursor() does not leak. + */ + // TEMPORARY CODE +// if (OS.GetCursor() is handle) { +// OS.SetCursor(OS.LoadCursor(0, OS.IDC_ARROW)); +// } + + if (isIcon) { + OS.DestroyIcon(handle); + } else { + /* + * The MSDN states that one should not destroy a shared + * cursor, that is, one obtained from LoadCursor. + * However, it does not appear to do any harm, so rather + * than keep track of how a cursor was created, we just + * destroy them all. If this causes problems in the future, + * put the flag back in. + */ + if (!OS.IsWinCE) OS.DestroyCursor(handle); + } + handle = null; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +public override int opEquals (Object object) { + if (object is this) return true; + if (!(cast(Cursor)object)) return false; + Cursor cursor = cast(Cursor) object; + return device is cursor.device && handle is cursor.handle; +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +public override hash_t toHash () { + return cast(hash_t)handle; +} + +/** + * Returns true if the cursor has been disposed, + * and false otherwise. + *

+ * This method gets the dispose state for the cursor. + * When a cursor has been disposed, it is an error to + * invoke any other method using the cursor. + * + * @return true when the cursor is disposed and false otherwise + */ +public bool isDisposed() { + return handle is null; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public char[] toString () { + if (isDisposed()) return "Cursor {*DISPOSED*}"; + return Format( "Cursor {{{}}", handle ); +} + +/** + * Invokes platform specific functionality to allocate a new cursor. + *

+ * IMPORTANT: This method is not part of the public + * API for Cursor. It is marked public only so that it + * can be shared within the packages provided by DWT. It is not + * available on all platforms, and should never be called from + * application code. + *

+ * + * @param device the device on which to allocate the color + * @param handle the handle for the cursor + * @return a new cursor object containing the specified device and handle + */ +public static Cursor win32_new(Device device, HCURSOR handle) { + if (device is null) device = Device.getDevice(); + Cursor cursor = new Cursor(); + cursor.handle = handle; + cursor.device = device; + return cursor; +} + +} diff -r 39834037712c -r b868bfa989cd dwt/internal/win32/OS.d --- a/dwt/internal/win32/OS.d Sun Jan 27 23:42:27 2008 +0100 +++ b/dwt/internal/win32/OS.d Mon Jan 28 00:22:22 2008 +0100 @@ -4264,6 +4264,7 @@ alias WINAPI.HeapAlloc HeapAlloc; alias WINAPI.HeapFree HeapFree; alias WINAPI.HideCaret HideCaret; +alias WINAPI.IIDFromString IIDFromString; alias WINAPI.ImageList_Add ImageList_Add; alias WINAPI.ImageList_AddMasked ImageList_AddMasked; alias WINAPI.ImageList_Create ImageList_Create; diff -r 39834037712c -r b868bfa989cd dwt/internal/win32/WINAPI.d --- a/dwt/internal/win32/WINAPI.d Sun Jan 27 23:42:27 2008 +0100 +++ b/dwt/internal/win32/WINAPI.d Mon Jan 28 00:22:22 2008 +0100 @@ -40,6 +40,8 @@ int nHeightSrc, // height of source rectangle UINT crTransparent // color to make transparent ); +int IIDFromString (wchar* lpsz, byte* lpiid); + }