wine/objects/gdiobj.c
Alexandre Julliard c7c217b31c Release 980413
Sun Apr 12 12:22:23 1997  Andreas Mohr <100.30936@germany.net>

	* [files/drive.c]
	Fixed "no free space" problem with partition sizes between 1 and 2 GB
	(cluster_sectors may not exceed 0x40).

	* [windows/msgbox.c] [if1632/user.spec] [include/windows.h]
	Implemented MessageBoxIndirect16, corrected MSGBOXPARAMS16.

	* [loader/task.c]
	DOS environment strings may never exceed 127 chars
	-> truncate Unix environment strings if necessary.

Sun Apr 12 02:51:44 1998  Dimitrie O. Paun  <dimi@mail.cs.toronto.edu>

	* [files/*.c]
	All fprintf statements were converted to appropriate debug
	messages.

	* [tools/find_debug_channels]
	Updated comments at the beginning of the file.

Sat Apr 11 15:27:21 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [loader/module.c] [loader/task.c] [scheduler/process.c]
	Moved some code around to prepare the ground for CreateProcess().

	* [memory/environ.c] [loader/task.c]
	Moved Win32 environment strings functions to environ.c.
	Unified Win16 and Win32 environment management.

	* [scheduler/handle.c] [scheduler/k32obj.c] [scheduler/*.c]
	Implemented handle inheritance and DuplicateHandle().

	* [scheduler/thread.c]
	Create a 16-bit stack for all threads.

	* [windows/dialog.c]
	Implemented DIALOGEX resource format.

Fri Apr 10 20:21:51 1998  Marcus Meissner <marcus@mud.de>

	* [configure.in][include/acconfig.h][*/*][multimedia/*]
	Cleaned up the OSS detection stuff, added some more checks for
	headerfiles/functions.
	Removed a lot of OS specific #ifdefs.
	Lots of dependend multimedia cleanups.

	* [loader/pe_image.c]
	Enhanced comment, added missing reference count increase.

	* [ole/compobj.c]
	Replaced broken StringFromGUID2 by working one.

	* [misc/winsock.c]
	SO_LINGER uses unsigned 16 bit in Win16 and Win32, but unsigned
	int (32bit) for UNIX.

	* [memory/global.c]
	Allow realloc for lockcount 1 too.

Fri Apr 10 15:27:34 1998  Morten Welinder  <terra@diku.dk>

	* [graphics/x11drv/text.c]
	Handle control characters in trace.  Ignore terminating newline.

	* [multimedia/init.c]
	(MULTIMEDIA_Init): Correct allocations.

	* [tools/examine-relay]
 	Tidy up.

	* [windows/syscolor.c]
	Change highlight colour from lightblue to lightgray.  This
	looks correct for menus.

Fri Apr 10 01:49:58 1998  Douglas Ridgway  <ridgway@winehq.com>

	* [configure.in] [Make.rules.in]
	Add check for c2man before using it.

Fri Apr 10 02:59:21 1998  Douglas Ridgway  <ridgway@winehq.com>

	* [DEVELOPERS-HINTS]
	Simple description of adding API calls.

	* [include/wintypes.h] [include/windows.h]
	Get rid of Winelib16, avoid declaring some illegal functions in
	Winelib, add prototypes for some enhanced metafile functions, fix
	GetTextExtentPoint32 declarations.

	* [relay32/gdi32.spec] [objects/enhmetafile.c]
	Cosmetic and functional improvements.

	* [include/wincon.h] [programs/view/*]
	Fixes, improved compatibility with native compilers.

Thu Apr  9 15:48:49 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [win32/kernel32.c]
	Implemented FT_Thunk / FT_Prolog / FT_Exit / FT_PrologPrime.
	Fixed Common32ThkLS thunk function.

	* [tools/build.c] [relay32/relay386.c] [if1632/relay.c]
	Changed relay code to allow register functions to modify stack layout.

	* [memory/selector.c]
	Implemented AllocMappedBuffer / FreeMappedBuffer.

	* [relay32/kernel32.spec] [if1632/kernel.spec] [win32/ordinals.c]
	Added names for undocumented functions.

	* [loader/module.c]
	Bugfix: LoadLibrary16 should *not* silently load 32-bit DLL.

Thu Apr  9 03:54:58 1998  Jim Peterson <jspeter@birch.ee.vt.edu>

	* [windows/keyboard.c]
	Fix an erroneous test in TranslateAccelerator{16,32} for the end
	of the accelerator table.

Thu Apr  8 20:36:28 1998  Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de> 

	* [misc/crtdll.c]
	Implement getenv.

	* [misc/commdlg.c]
	Make Get[Save/Open]FileName work in most situations.

	* [misc/lstr.c]
	Use wvsprintf32A instead of vsprintf in FormatMessage32X

	* [misc/version]
	Make NT3.50 a recognised version

	* [graphics/x11drv/graphics.c]
	Change the algorithme to draw arcs

	* [loader/resource.c]
	Return an empty buffer in LoadString32A if no resource found.

	* [win32/code_page.c]
	Try harder to get the right size in MultiByteToWideChar.

	* [win32/process.c]
	Call WinExec32 for CreateProcess32A.

	* [windows/user.c]
	Install default Int0 Handler in InitApp().

Thu Apr  8 19:29:48 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [misc/imagelist.c]
	Preliminary fix for drawing selected images.
	Various improvements.

	* [controls/progress.c][include/progress.c][include/commctrl.h]
	Added progress bar messages and styles for IE4.01 (dll version 4.72)
	compatibility.
	Fixed led size problem.

	* [controls/updown.c][include/commctrl.h]
	Added UDM_GETRANGE32 and UDM_SETRANGE32.

	* [objects/oembitmaps.c][include/windows.h][include/bitmaps/*]
	Added Win95 icons and fixed Win95 cursor and restore button bug.
	Now they should be visible. Sorry!!!

	* [relay32/comctl32.spec]
	Added most missing function names.

Tue Apr  6 18:48:36 1998  Matthew Becker <mbecker@glasscity.net>

	* [objects/font.c] [if1632/gdi.spec]
	GetOutlineTextMetrics: stub

	* [objects/text.c]
	GetTextCharset should just call GetTextCharsetInfo.

	* [misc/mpr.c] [relay32/mpr.spec]
	WNetCachePassword: stub

	* [scheduler/thread.c] [relay32/user32.spec]
	AttachThreadInput: stub
	Updated documentation.

	* [objects/palette.c]
	Updated documentation.

Tue Mar 31 17:06:30 1998  James Juran <jrj120@psu.edu>

	* [*/*.c]
	Finished fixing USER32 ordinal numbers in function documentation.

Mon Mar 30 20:27:38 1998  Morten Welinder  <terra@diku.dk>

	* [misc/debugstr.c] [include/debugstr.h]
	Moved _dumpstr from relay32/relay386.c.  Improved control
	character handling.

	* [msdos/int21.c]
	Implement 215E00 -- get machine name.

	* [windows/winpos.c]
	SetWindowPos32: Make an extra sync when mapping managed
	windows.  This makes sure the reconfigure event has been
	handled.  See Mshearts' what's-your-name window.

Mon Mar 30 01:13:50 1998  Alexander V. Lukyanov <lav@long.yar.ru>

	* [Makefile.in]
	Install includes from TOPSRCDIR.
1998-04-13 12:21:30 +00:00

910 lines
25 KiB
C

/*
* GDI functions
*
* Copyright 1993 Alexandre Julliard
*/
#include <stdlib.h>
#include <stdio.h>
#include "color.h"
#include "bitmap.h"
#include "brush.h"
#include "dc.h"
#include "font.h"
#include "heap.h"
#include "options.h"
#include "palette.h"
#include "pen.h"
#include "region.h"
#include "debug.h"
#include "gdi.h"
/***********************************************************************
* GDI stock objects
*/
static BRUSHOBJ WhiteBrush =
{
{ 0, BRUSH_MAGIC, 1 }, /* header */
{ BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
};
static BRUSHOBJ LtGrayBrush =
{
{ 0, BRUSH_MAGIC, 1 }, /* header */
/* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
{ BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
};
static BRUSHOBJ GrayBrush =
{
{ 0, BRUSH_MAGIC, 1 }, /* header */
/* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
{ BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
};
static BRUSHOBJ DkGrayBrush =
{
{ 0, BRUSH_MAGIC, 1 }, /* header */
/* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
/* NB_HATCH_STYLES is an index into HatchBrushes */
{ BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
};
static BRUSHOBJ BlackBrush =
{
{ 0, BRUSH_MAGIC, 1 }, /* header */
{ BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
};
static BRUSHOBJ NullBrush =
{
{ 0, BRUSH_MAGIC, 1 }, /* header */
{ BS_NULL, 0, 0 } /* logbrush */
};
static PENOBJ WhitePen =
{
{ 0, PEN_MAGIC, 1 }, /* header */
{ PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
};
static PENOBJ BlackPen =
{
{ 0, PEN_MAGIC, 1 }, /* header */
{ PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
};
static PENOBJ NullPen =
{
{ 0, PEN_MAGIC, 1 }, /* header */
{ PS_NULL, { 1, 0 }, 0 } /* logpen */
};
static FONTOBJ OEMFixedFont =
{
{ 0, FONT_MAGIC, 1 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
};
/* Filler to make the location counter dword aligned again. This is necessary
since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
segment, and (c) Solaris assembler is stupid. */
static UINT16 align_OEMFixedFont = 1;
static FONTOBJ AnsiFixedFont =
{
{ 0, FONT_MAGIC, 1 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
};
static UINT16 align_AnsiFixedFont = 1;
static FONTOBJ AnsiVarFont =
{
{ 0, FONT_MAGIC, 1 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
};
static UINT16 align_AnsiVarFont = 1;
static FONTOBJ SystemFont =
{
{ 0, FONT_MAGIC, 1 },
{ 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
};
static UINT16 align_SystemFont = 1;
static FONTOBJ DeviceDefaultFont =
{
{ 0, FONT_MAGIC, 1 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
};
static UINT16 align_DeviceDefaultFont = 1;
static FONTOBJ SystemFixedFont =
{
{ 0, FONT_MAGIC, 1 }, /* header */
{ 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
};
static UINT16 align_SystemFixedFont = 1;
/* FIXME: Is this correct? */
static FONTOBJ DefaultGuiFont =
{
{ 9, FONT_MAGIC, 1 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
};
static UINT16 align_DefaultGuiFont = 1;
static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
{
(GDIOBJHDR *) &WhiteBrush,
(GDIOBJHDR *) &LtGrayBrush,
(GDIOBJHDR *) &GrayBrush,
(GDIOBJHDR *) &DkGrayBrush,
(GDIOBJHDR *) &BlackBrush,
(GDIOBJHDR *) &NullBrush,
(GDIOBJHDR *) &WhitePen,
(GDIOBJHDR *) &BlackPen,
(GDIOBJHDR *) &NullPen,
NULL,
(GDIOBJHDR *) &OEMFixedFont,
(GDIOBJHDR *) &AnsiFixedFont,
(GDIOBJHDR *) &AnsiVarFont,
(GDIOBJHDR *) &SystemFont,
(GDIOBJHDR *) &DeviceDefaultFont,
NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
(GDIOBJHDR *) &SystemFixedFont,
(GDIOBJHDR *) &DefaultGuiFont
};
/******************************************************************************
*
* void ReadFontInformation(
* char const *fontName,
* FONTOBJ *font,
* int defHeight,
* int defBold,
* int defItalic,
* int defUnderline,
* int defStrikeOut )
*
* ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
* section for entries containing fontName.Height, fontName.Bold, etc.,
* where fontName is the name specified in the call (e.g., "System"). It
* attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
* the first character in the boolean attributes (bold, italic, and
* underline).
*****************************************************************************/
static void ReadFontInformation(
char const *fontName,
FONTOBJ *font,
int defHeight,
int defBold,
int defItalic,
int defUnderline,
int defStrikeOut )
{
char key[256];
sprintf(key, "%s.Height", fontName);
font->logfont.lfHeight =
PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
sprintf(key, "%s.Bold", fontName);
font->logfont.lfWeight =
(PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
FW_BOLD : FW_NORMAL;
sprintf(key, "%s.Italic", fontName);
font->logfont.lfItalic =
PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
sprintf(key, "%s.Underline", fontName);
font->logfont.lfUnderline =
PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
sprintf(key, "%s.StrikeOut", fontName);
font->logfont.lfStrikeOut =
PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
return;
}
/***********************************************************************
* GDI_Init
*
* GDI initialization.
*/
BOOL32 GDI_Init(void)
{
extern BOOL32 X11DRV_Init(void);
extern BOOL32 DIB_Init(void);
/* Kill some warnings. */
(void)align_OEMFixedFont;
(void)align_AnsiFixedFont;
(void)align_AnsiVarFont;
(void)align_SystemFont;
(void)align_DeviceDefaultFont;
(void)align_SystemFixedFont;
(void)align_DefaultGuiFont;
/* TWEAK: Initialize font hints */
ReadFontInformation("OEMFixed", &OEMFixedFont, 12, 0, 0, 0, 0);
ReadFontInformation("AnsiFixed", &AnsiFixedFont, 12, 0, 0, 0, 0);
ReadFontInformation("AnsiVar", &AnsiVarFont, 12, 0, 0, 0, 0);
ReadFontInformation("System", &SystemFont, 16, 1, 0, 0, 0);
ReadFontInformation("SystemFixed", &SystemFixedFont, 12, 1, 0, 0, 0);
/* Initialize drivers */
DIB_Init(); /* always before X11DRV_Init() */
if( X11DRV_Init() )
{
/* Create default palette */
/* DR well *this* palette can't be moveable (?) */
HPALETTE16 hpalette = PALETTE_Init();
if( hpalette )
{
StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
return TRUE;
}
}
return FALSE;
}
/***********************************************************************
* GDI_AllocObject
*/
HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
{
static DWORD count = 0;
GDIOBJHDR * obj;
HGDIOBJ16 handle;
if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
handle = GDI_HEAP_ALLOC( size );
else
handle = GDI_HEAP_ALLOC_MOVEABLE( size );
if (!handle) return 0;
obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
obj->hNext = 0;
obj->wMagic = magic;
obj->dwCount = ++count;
GDI_HEAP_UNLOCK( handle );
return handle;
}
/***********************************************************************
* GDI_FreeObject
*/
BOOL32 GDI_FreeObject( HGDIOBJ16 handle )
{
GDIOBJHDR * object;
/* Can't free stock objects */
if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
return TRUE;
object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
if (!object) return FALSE;
object->wMagic = 0; /* Mark it as invalid */
/* Free object */
GDI_HEAP_FREE( handle );
return TRUE;
}
/***********************************************************************
* GDI_GetObjPtr
*
* Return a pointer to the GDI object associated to the handle.
* Return NULL if the object has the wrong magic number.
* Movable GDI objects are locked in memory: it is up to the caller to unlock
* it after the caller is done with the pointer.
*/
GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
{
GDIOBJHDR * ptr = NULL;
if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
else
ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
if (!ptr) return NULL;
if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
{
GDI_HEAP_UNLOCK( handle );
return NULL;
}
return ptr;
}
/***********************************************************************
* DeleteObject16 (GDI.69)
*/
BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
{
return DeleteObject32( obj );
}
/***********************************************************************
* DeleteObject32 (GDI32.70)
*/
BOOL32 WINAPI DeleteObject32( HGDIOBJ32 obj )
{
/* Check if object is valid */
GDIOBJHDR * header;
if (HIWORD(obj)) return FALSE;
if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
return TRUE;
if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
TRACE(gdi, "%04x\n", obj );
/* Delete object */
switch(header->wMagic)
{
case PEN_MAGIC: return GDI_FreeObject( obj );
case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
case FONT_MAGIC: return GDI_FreeObject( obj );
case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
}
return FALSE;
}
/***********************************************************************
* GetStockObject16 (GDI.87)
*/
HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
{
return (HGDIOBJ16)GetStockObject32( obj );
}
/***********************************************************************
* GetStockObject32 (GDI32.220)
*/
HGDIOBJ32 WINAPI GetStockObject32( INT32 obj )
{
if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
if (!StockObjects[obj]) return 0;
TRACE(gdi, "returning %d\n",
FIRST_STOCK_HANDLE + obj );
return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
}
/***********************************************************************
* GetObject16 (GDI.82)
*/
INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
{
GDIOBJHDR * ptr = NULL;
INT16 result = 0;
TRACE(gdi, "%04x %d %p\n", handle, count, buffer );
if (!count) return 0;
if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
else
ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
if (!ptr) return 0;
switch(ptr->wMagic)
{
case PEN_MAGIC:
result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
break;
case BRUSH_MAGIC:
result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
break;
case BITMAP_MAGIC:
result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
break;
case FONT_MAGIC:
result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
break;
case PALETTE_MAGIC:
result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
break;
}
GDI_HEAP_UNLOCK( handle );
return result;
}
/***********************************************************************
* GetObject32A (GDI32.204)
*/
INT32 WINAPI GetObject32A( HANDLE32 handle, INT32 count, LPVOID buffer )
{
GDIOBJHDR * ptr = NULL;
INT32 result = 0;
TRACE(gdi, "%08x %d %p\n", handle, count, buffer );
if (!count) return 0;
if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
else
ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
if (!ptr) return 0;
switch(ptr->wMagic)
{
case PEN_MAGIC:
result = PEN_GetObject32( (PENOBJ *)ptr, count, buffer );
break;
case BRUSH_MAGIC:
result = BRUSH_GetObject32( (BRUSHOBJ *)ptr, count, buffer );
break;
case BITMAP_MAGIC:
result = BITMAP_GetObject32( (BITMAPOBJ *)ptr, count, buffer );
break;
case FONT_MAGIC:
result = FONT_GetObject32A( (FONTOBJ *)ptr, count, buffer );
break;
case PALETTE_MAGIC:
result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
break;
default:
fprintf( stderr, "GetObject32: magic %04x not implemented\n",
ptr->wMagic );
break;
}
GDI_HEAP_UNLOCK( handle );
return result;
}
/***********************************************************************
* GetObjectType (GDI32.205)
*/
DWORD WINAPI GetObjectType( HANDLE32 handle )
{
GDIOBJHDR * ptr = NULL;
INT32 result = 0;
TRACE(gdi, "%08x\n", handle );
if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
else
ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
if (!ptr) return 0;
switch(ptr->wMagic)
{
case PEN_MAGIC:
result = OBJ_PEN;
break;
case BRUSH_MAGIC:
result = OBJ_BRUSH;
break;
case BITMAP_MAGIC:
result = OBJ_BITMAP;
break;
case FONT_MAGIC:
result = OBJ_FONT;
break;
case PALETTE_MAGIC:
result = OBJ_PAL;
break;
case REGION_MAGIC:
result = OBJ_REGION;
break;
case DC_MAGIC:
result = OBJ_DC;
break;
case META_DC_MAGIC:
result = OBJ_METADC;
break;
case METAFILE_MAGIC:
result = OBJ_METAFILE;
break;
case METAFILE_DC_MAGIC:
result = OBJ_METADC;
break;
default:
fprintf( stderr, "GetObjectType: magic %04x not implemented\n",
ptr->wMagic );
break;
}
GDI_HEAP_UNLOCK( handle );
return result;
}
/***********************************************************************
* GetObject32W (GDI32.206)
*/
INT32 WINAPI GetObject32W( HANDLE32 handle, INT32 count, LPVOID buffer )
{
return GetObject32A( handle, count, buffer );
}
/***********************************************************************
* GetCurrentObject (GDI32.166)
*/
HANDLE32 WINAPI GetCurrentObject(HDC32 hdc,UINT32 type)
{
DC * dc = DC_GetDCPtr( hdc );
if (!dc)
return 0;
switch (type) {
case OBJ_PEN: return dc->w.hPen;
case OBJ_BRUSH: return dc->w.hBrush;
case OBJ_PAL: return dc->w.hPalette;
case OBJ_FONT: return dc->w.hFont;
case OBJ_BITMAP: return dc->w.hBitmap;
default:
/* the SDK only mentions those above */
fprintf(stderr,"GetCurrentObject(%08x,%d), unknown type.\n",hdc,type);
return 0;
}
}
/***********************************************************************
* SelectObject16 (GDI.45)
*/
HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
{
return (HGDIOBJ16)SelectObject32( hdc, handle );
}
/***********************************************************************
* SelectObject32 (GDI32.299)
*/
HGDIOBJ32 WINAPI SelectObject32( HDC32 hdc, HGDIOBJ32 handle )
{
DC * dc = DC_GetDCPtr( hdc );
if (!dc || !dc->funcs->pSelectObject) return 0;
TRACE(gdi, "hdc=%04x %04x\n", hdc, handle );
return dc->funcs->pSelectObject( dc, handle );
}
/***********************************************************************
* UnrealizeObject16 (GDI.150)
*/
BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
{
return UnrealizeObject32( obj );
}
/***********************************************************************
* UnrealizeObject (GDI32.358)
*/
BOOL32 WINAPI UnrealizeObject32( HGDIOBJ32 obj )
{
BOOL32 result = TRUE;
/* Check if object is valid */
GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
if (!header) return FALSE;
TRACE(gdi, "%04x\n", obj );
/* Unrealize object */
switch(header->wMagic)
{
case PALETTE_MAGIC:
result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
break;
case BRUSH_MAGIC:
/* Windows resets the brush origin. We don't need to. */
break;
}
GDI_HEAP_UNLOCK( obj );
return result;
}
/***********************************************************************
* EnumObjects16 (GDI.71)
*/
INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
{
/* Solid colors to enumerate */
static const COLORREF solid_colors[] =
{ RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
};
INT16 i, retval = 0;
LOGPEN16 *pen;
LOGBRUSH16 *brush = NULL;
TRACE(gdi, "%04x %d %08lx %08lx\n",
hdc, nObjType, (DWORD)lpEnumFunc, lParam );
switch(nObjType)
{
case OBJ_PEN:
/* Enumerate solid pens */
if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
{
pen->lopnStyle = PS_SOLID;
pen->lopnWidth.x = 1;
pen->lopnWidth.y = 0;
pen->lopnColor = solid_colors[i];
retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
TRACE(gdi, "solid pen %08lx, ret=%d\n",
solid_colors[i], retval);
if (!retval) break;
}
SEGPTR_FREE(pen);
break;
case OBJ_BRUSH:
/* Enumerate solid brushes */
if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
{
brush->lbStyle = BS_SOLID;
brush->lbColor = solid_colors[i];
brush->lbHatch = 0;
retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
TRACE(gdi, "solid brush %08lx, ret=%d\n",
solid_colors[i], retval);
if (!retval) break;
}
/* Now enumerate hatched brushes */
if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
{
brush->lbStyle = BS_HATCHED;
brush->lbColor = RGB(0,0,0);
brush->lbHatch = i;
retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
TRACE(gdi, "hatched brush %d, ret=%d\n",
i, retval);
if (!retval) break;
}
SEGPTR_FREE(brush);
break;
default:
fprintf( stderr, "EnumObjects16: invalid type %d\n", nObjType );
break;
}
return retval;
}
/***********************************************************************
* EnumObjects32 (GDI32.89)
*/
INT32 WINAPI EnumObjects32( HDC32 hdc, INT32 nObjType,
GOBJENUMPROC32 lpEnumFunc, LPARAM lParam )
{
/* Solid colors to enumerate */
static const COLORREF solid_colors[] =
{ RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
};
INT32 i, retval = 0;
LOGPEN32 pen;
LOGBRUSH32 brush;
TRACE(gdi, "%04x %d %08lx %08lx\n",
hdc, nObjType, (DWORD)lpEnumFunc, lParam );
switch(nObjType)
{
case OBJ_PEN:
/* Enumerate solid pens */
for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
{
pen.lopnStyle = PS_SOLID;
pen.lopnWidth.x = 1;
pen.lopnWidth.y = 0;
pen.lopnColor = solid_colors[i];
retval = lpEnumFunc( &pen, lParam );
TRACE(gdi, "solid pen %08lx, ret=%d\n",
solid_colors[i], retval);
if (!retval) break;
}
break;
case OBJ_BRUSH:
/* Enumerate solid brushes */
for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
{
brush.lbStyle = BS_SOLID;
brush.lbColor = solid_colors[i];
brush.lbHatch = 0;
retval = lpEnumFunc( &brush, lParam );
TRACE(gdi, "solid brush %08lx, ret=%d\n",
solid_colors[i], retval);
if (!retval) break;
}
/* Now enumerate hatched brushes */
if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
{
brush.lbStyle = BS_HATCHED;
brush.lbColor = RGB(0,0,0);
brush.lbHatch = i;
retval = lpEnumFunc( &brush, lParam );
TRACE(gdi, "hatched brush %d, ret=%d\n",
i, retval);
if (!retval) break;
}
break;
default:
/* FIXME: implement Win32 types */
fprintf( stderr, "EnumObjects32: invalid type %d\n", nObjType );
break;
}
return retval;
}
/***********************************************************************
* IsGDIObject (GDI.462)
*
* returns type of object if valid (W95 system programming secrets p. 264-5)
*/
BOOL16 WINAPI IsGDIObject( HGDIOBJ16 handle )
{
if (handle >= FIRST_STOCK_HANDLE )
return TRUE;
else
{
GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
if (object)
{
UINT16 magic = object->wMagic;
GDI_HEAP_UNLOCK( handle );
if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
return magic - PEN_MAGIC + 1;
}
}
return FALSE;
}
/***********************************************************************
* SetObjectOwner16 (GDI.461)
*/
void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
{
/* Nothing to do */
}
/***********************************************************************
* SetObjectOwner32 (GDI32.386)
*/
void WINAPI SetObjectOwner32( HGDIOBJ32 handle, HANDLE32 owner )
{
/* Nothing to do */
}
/***********************************************************************
* GdiFlush (GDI32.128)
*/
BOOL32 WINAPI GdiFlush(void)
{
return TRUE; /* FIXME */
}
/***********************************************************************
* GdiGetBatchLimit (GDI32.129)
*/
DWORD WINAPI GdiGetBatchLimit(void)
{
return 1; /* FIXME */
}
/***********************************************************************
* GdiSetBatchLimit (GDI32.139)
*/
DWORD WINAPI GdiSetBatchLimit( DWORD limit )
{
return 1; /* FIXME */
}
/***********************************************************************
* GdiSeeGdiDo (GDI.452)
*/
DWORD WINAPI GdiSeeGdiDo( WORD wReqType, WORD wParam1, WORD wParam2,
WORD wParam3 )
{
switch (wReqType)
{
case 0x0001: /* LocalAlloc */
return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
case 0x0002: /* LocalFree */
return LOCAL_Free( GDI_HeapSel, wParam1 );
case 0x0003: /* LocalCompact */
return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
case 0x0103: /* LocalHeap */
return GDI_HeapSel;
default:
fprintf(stderr, "GdiSeeGdiDo: wReqType %04x (unknown)", wReqType);
return (DWORD)-1;
}
}
/***********************************************************************
* MulDiv16 (GDI.128)
*/
INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
{
INT32 ret;
if (!baz) return -32768;
ret = (foo * bar) / baz;
if ((ret > 32767) || (ret < -32767)) return -32768;
return ret;
}
/***********************************************************************
* MulDiv32 (KERNEL32.391)
* RETURNS
* Result of multiplication and division
* -1: Overflow occurred or Divisor was 0
*/
INT32 WINAPI MulDiv32(
INT32 nMultiplicand,
INT32 nMultiplier,
INT32 nDivisor
) {
#if (SIZEOF_LONG_LONG >= 8)
long long ret;
if (!nDivisor) return -1;
ret = ((long long)nMultiplicand * nMultiplier) / nDivisor;
if ((ret > 2147483647) || (ret < -2147483647)) return -1;
return ret;
#else
if (!nDivisor) return -1;
return (nMultiplicand * nMultiplier) / nDivisor;
#endif
}