wine/objects/gdiobj.c
Alexandre Julliard f1aa3030a6 Release 960805
Sun Aug  4 18:18:48 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/scroll.c]
	Attempted to implement undocumented scroll-bar messages.

	* [tools/build.c] [include/callback.h] [windows/winproc.c]
	CallTo16_* functions now get DS from the previous 16-bit stackframe.

	* [if1632/thunk.c] [include/callback.h]
	Added thunks to implement callbacks for the emulator. Now all the
	Enum* functions always take a real function pointer even in the
	emulator.
	
	* [loader/builtin.c]
	Removed binary search in BUILTIN_GetEntryPoint32(), as it didn't
 	work with NULL entry points. Using linear search now.

	* [loader/module.c]
	Implemented IsSharedSelector().

	* [loader/task.c]
	Changed SwitchStackTo/Back to use the instance data to store the
	previous stack instead of the TDB. Also copy the local variables
	onto the new stack.
	Added GetExeVersion() and SetTackSignalProc().
	Implemented SetSigHandler().

Sat Aug  3 22:19:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [controls/menu.c]
	"Fixed" problem in deleting menus where win32 could get into an
	endless loop when it crashed. I think I've fixed the symptoms, not
	the original problem so it might be worth further investigation.

	* [debugger/registers.c]
	Added missing #ifdefs on FS_REG and GS_REG, needed for FreeBSD to
	compile wine properly.

	* [files/dos_fs.c]
	Made DOSFS_Hash and DOSFS_Match non-static so they can be called
	from win32/findfile.c (q.v.).

	* [if1632/gdi32.spec]
	Added SetMapMode (call existing function)

	* [if1632/kernel32.spec]
	Added FindFirstFileA and SetFileAttributesA.

	* [if1632/user32.spec]
	Added BringWindowToTop, CreatePopupMenu, GetKeyState, GetParent,
	IsDlgButtonChecked (call existing functions) and IsDialogMessageA,
	UnhookWindowsHookEx.

	* [win32/file.c]
	Added stub function SetFileAttributes32A. It's a stub because I
	can't really work out what this function should do with most
	attributes in a Unix environment. Anyone care to expand it?

	* [win32/findfile.c]
	New file. Initial stab at FindFirstFile. This doesn't work as
	specified yet, though a lot of the groundwork is there. I haven't
	time to work on this for the next month, so if anyone wants to pick
	it up and run with it please do.

	* [win32/memory.c]
	Removed malloc.h from includes (covered by stdlib.h include, and
	gets rid of a warning in FreeBSD).

	* [win32/newfns.c]
	UnhookWindowsHookEx32A stub added.

	* [win32/user32.c]
	Added implementation of IsDialogMessage32A.

	* [windows/dialog.c]
	IsDlgButtonChecked now calls SendDlgItemMessage32A instead of
	SendDlgItemMessage16.

Sat Aug  3 18:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [windows/graphics.c]
	Removed rectangle checking (conflicted with nonstandard
	mapping modes). 

	* [windows/dialog.c]
	Added check for child-style dialogs to DS_ABSALIGN
	coordinate conversion.

	* [objects/color.c]
	Cleaned up misc. bits

Thu Aug  1 10:51:45 1996  Andrew Lewycky <plewycky@oise.utoronto.ca>

	* [windows/focus.c] [windows/event.c] [windows/win.c]
	  [windows/defdlg.c]
	Fixes to focusing and activation.

	* [windows/defdlg.c]
	Properly(?) handle DM_GETDEFID.

	* [controls/combo.c]
	Handle CB_FINDSTRINGEXACT, CB_SETEDITSEL, CB_GETEDITSEL.
	CBCheckSize: Adjust edit position.

Tue Jul 30 09:46:36 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [files/file.c] [include/file.h] [loader/module.c] [loader/ne_image.c]
	Pass HFILEs instead of unix-fds to self-loader code.

Mon Jul 29 21:48:25 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [include/metafile.h] [objects/metafile.c] [objects/text.c]
	Implemented handling of some new metafile records (META_...)
	in PlayMetaFileRecord(), rewrite of 'case META_EXTTEXTOUT'.
	Added functions like MF_StretchBlt() for usage in metafiles.
	Minor bugfix in CopyMetafile().

	* [objects/bitmap.c][objects/dib.c]
	Added check for metafile-DC in Bitmap and DIB functions:
	CreateCompatibleBitmap() etc.
1996-08-05 17:42:43 +00:00

555 lines
15 KiB
C

/*
* GDI functions
*
* Copyright 1993 Alexandre Julliard
*/
#include <stdlib.h>
#include <stdio.h>
#include "gdi.h"
#include "color.h"
#include "bitmap.h"
#include "brush.h"
#include "font.h"
#include "heap.h"
#include "module.h"
#include "palette.h"
#include "pen.h"
#include "region.h"
#include "stddebug.h"
#include "debug.h"
#include "xmalloc.h"
WORD GDI_HeapSel = 0;
/* Object types for EnumObjects() */
#define OBJ_PEN 1
#define OBJ_BRUSH 2
/***********************************************************************
* GDI stock objects
*/
static BRUSHOBJ WhiteBrush =
{
{ 0, BRUSH_MAGIC, 1, 0 }, /* header */
{ BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
};
static BRUSHOBJ LtGrayBrush =
{
{ 0, BRUSH_MAGIC, 1, 0 }, /* header */
{ BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
};
static BRUSHOBJ GrayBrush =
{
{ 0, BRUSH_MAGIC, 1, 0 }, /* header */
{ BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
};
static BRUSHOBJ DkGrayBrush =
{
{ 0, BRUSH_MAGIC, 1, 0 }, /* header */
{ BS_SOLID, RGB(64,64,64), 0 } /* logbrush */
};
static BRUSHOBJ BlackBrush =
{
{ 0, BRUSH_MAGIC, 1, 0 }, /* header */
{ BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
};
static BRUSHOBJ NullBrush =
{
{ 0, BRUSH_MAGIC, 1, 0 }, /* header */
{ BS_NULL, 0, 0 } /* logbrush */
};
static PENOBJ WhitePen =
{
{ 0, PEN_MAGIC, 1, 0 }, /* header */
{ PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
};
static PENOBJ BlackPen =
{
{ 0, PEN_MAGIC, 1, 0 }, /* header */
{ PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
};
static PENOBJ NullPen =
{
{ 0, PEN_MAGIC, 1, 0 }, /* header */
{ PS_NULL, { 1, 0 }, 0 } /* logpen */
};
static FONTOBJ OEMFixedFont =
{
{ 0, FONT_MAGIC, 1, 0 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
};
static FONTOBJ AnsiFixedFont =
{
{ 0, FONT_MAGIC, 1, 0 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
};
static FONTOBJ AnsiVarFont =
{
{ 0, FONT_MAGIC, 1, 0 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
};
static FONTOBJ SystemFont =
{
{ 0, FONT_MAGIC, 1, 0 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
};
static FONTOBJ DeviceDefaultFont =
{
{ 0, FONT_MAGIC, 1, 0 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
};
static FONTOBJ SystemFixedFont =
{
{ 0, FONT_MAGIC, 1, 0 }, /* header */
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
};
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 COLOR_Init */
(GDIOBJHDR *) &SystemFixedFont
};
static FARPROC16 defDCHookCallback;
/***********************************************************************
* GDI_Init
*
* GDI initialization.
*/
BOOL32 GDI_Init(void)
{
HPALETTE16 hpalette;
defDCHookCallback = (FARPROC16)MODULE_GetEntryPoint(GetModuleHandle("USER"),
362 /* DCHook */ );
dprintf_gdi( stddeb, "DCHook: 16-bit callback is %08x\n",
(unsigned)defDCHookCallback );
/* Create default palette */
if (!(hpalette = COLOR_Init())) return FALSE;
StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LIN_ADDR( hpalette );
/* Create default bitmap */
if (!BITMAP_Init()) return FALSE;
/* Initialize brush dithering */
if (!BRUSH_Init()) return FALSE;
/* Initialize fonts */
if (!FONT_Init()) return FALSE;
return TRUE;
}
/***********************************************************************
* GDI_GetDefDCHook
*/
FARPROC16 GDI_GetDefDCHook(void)
{
return defDCHookCallback;
}
/***********************************************************************
* GDI_AllocObject
*/
HANDLE16 GDI_AllocObject( WORD size, WORD magic )
{
static DWORD count = 0;
GDIOBJHDR * obj;
HANDLE handle = GDI_HEAP_ALLOC( size );
if (!handle) return 0;
obj = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
obj->hNext = 0;
obj->wMagic = magic;
obj->dwCount = ++count;
return handle;
}
/***********************************************************************
* GDI_FreeObject
*/
BOOL32 GDI_FreeObject( HANDLE16 handle )
{
GDIOBJHDR * object;
/* Can't free stock objects */
if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
return TRUE;
object = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( 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.
*/
GDIOBJHDR * GDI_GetObjPtr( HANDLE16 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_LIN_ADDR( handle );
if (!ptr) return NULL;
if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) return NULL;
return ptr;
}
/***********************************************************************
* DeleteObject (GDI.69)
*/
BOOL DeleteObject( HGDIOBJ16 obj )
{
/* Check if object is valid */
GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( obj );
if (!header) return FALSE;
dprintf_gdi(stddeb, "DeleteObject: %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;
}
/***********************************************************************
* GetStockObject (GDI.87)
*/
HANDLE GetStockObject( int obj )
{
if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
if (!StockObjects[obj]) return 0;
dprintf_gdi(stddeb, "GetStockObject: returning %d\n",
FIRST_STOCK_HANDLE + obj );
return (HANDLE)(FIRST_STOCK_HANDLE + obj);
}
/***********************************************************************
* GetObject16 (GDI.82)
*/
INT16 GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
{
GDIOBJHDR * ptr = NULL;
dprintf_gdi(stddeb, "GetObject16: %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_LIN_ADDR( handle );
if (!ptr) return 0;
switch(ptr->wMagic)
{
case PEN_MAGIC:
return PEN_GetObject( (PENOBJ *)ptr, count, buffer );
case BRUSH_MAGIC:
return BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
case BITMAP_MAGIC:
return BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
case FONT_MAGIC:
return FONT_GetObject( (FONTOBJ *)ptr, count, buffer );
case PALETTE_MAGIC:
return PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
}
return 0;
}
/***********************************************************************
* GetObject32A (GDI32.204)
*/
INT32 GetObject32A( HANDLE32 handle, INT32 count, LPVOID buffer )
{
GDIOBJHDR * ptr = NULL;
dprintf_gdi(stddeb, "GetObject32A: %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_LIN_ADDR( handle );
if (!ptr) return 0;
switch(ptr->wMagic)
{
case BITMAP_MAGIC:
return BITMAP_GetObject32( (BITMAPOBJ *)ptr, count, buffer );
case PEN_MAGIC:
case BRUSH_MAGIC:
case FONT_MAGIC:
case PALETTE_MAGIC:
fprintf( stderr, "GetObject32: magic %04x not implemented\n",
ptr->wMagic );
break;
}
return 0;
}
/***********************************************************************
* GetObject32W (GDI32.206)
*/
INT32 GetObject32W( HANDLE32 handle, INT32 count, LPVOID buffer )
{
return GetObject32A( handle, count, buffer );
}
/***********************************************************************
* SelectObject (GDI.45)
*/
HANDLE SelectObject( HDC hdc, HANDLE handle )
{
GDIOBJHDR * ptr = NULL;
DC * dc;
dprintf_gdi(stddeb, "SelectObject: hdc=%04x %04x\n", hdc, handle );
if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
else
ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
if (!ptr) return 0;
dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
if (!dc)
{
dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
if (!dc) return 0;
}
switch(ptr->wMagic)
{
case PEN_MAGIC:
return PEN_SelectObject( dc, handle, (PENOBJ *)ptr );
case BRUSH_MAGIC:
return BRUSH_SelectObject( dc, handle, (BRUSHOBJ *)ptr );
case BITMAP_MAGIC:
return BITMAP_SelectObject( dc, handle, (BITMAPOBJ *)ptr );
case FONT_MAGIC:
return FONT_SelectObject( dc, handle, (FONTOBJ *)ptr );
case REGION_MAGIC:
return (HANDLE)SelectClipRgn( hdc, handle );
}
return 0;
}
/***********************************************************************
* UnrealizeObject (GDI.150)
*/
BOOL UnrealizeObject( HANDLE obj )
{
/* Check if object is valid */
GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( obj );
if (!header) return FALSE;
dprintf_gdi( stddeb, "UnrealizeObject: %04x\n", obj );
/* Unrealize object */
switch(header->wMagic)
{
case PALETTE_MAGIC:
return PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
case BRUSH_MAGIC:
/* Windows resets the brush origin. We don't need to. */
break;
}
return TRUE;
}
/***********************************************************************
* EnumObjects (GDI.71)
*/
INT EnumObjects( HDC hdc, INT 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)
};
int i, retval = 0;
LOGPEN16 *pen;
LOGBRUSH16 *brush = NULL;
dprintf_gdi( stddeb, "EnumObjects: %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 );
dprintf_gdi( stddeb, "EnumObject: 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 );
dprintf_gdi( stddeb, "EnumObject: 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 );
dprintf_gdi( stddeb, "EnumObject: hatched brush %d, ret=%d\n",
i, retval);
if (!retval) break;
}
SEGPTR_FREE(brush);
break;
default:
fprintf( stderr, "EnumObjects: invalid type %d\n", nObjType );
break;
}
return retval;
}
/***********************************************************************
* IsGDIObject (GDI.462)
*/
BOOL IsGDIObject(HANDLE handle)
{
GDIOBJHDR *object;
object = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
/* FIXME: should check magic here */
return (object != NULL);
}
/***********************************************************************
* MulDiv16 (GDI.128)
*/
INT16 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)
*/
INT32 MulDiv32( INT32 foo, INT32 bar, INT32 baz )
{
#ifdef __GNUC__
long long ret;
if (!baz) return -1;
ret = ((long long)foo * bar) / baz;
if ((ret > 2147483647) || (ret < -2147483647)) return -1;
return ret;
#else
if (!baz) return -1;
return (foo * bar) / baz;
#endif
}