[GDI32]
[reactos.git] / reactos / win32ss / gdi / gdi32 / misc / misc.c
1 /*
2 * ReactOS GDI lib
3 * Copyright (C) 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * PROJECT: ReactOS gdi32.dll
21 * FILE: dll/win32/gdi32/misc/misc.c
22 * PURPOSE: Miscellaneous functions
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
24 * UPDATE HISTORY:
25 * 2004/09/04 Created
26 */
27
28 #include <precomp.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33 PGDI_TABLE_ENTRY GdiHandleTable = NULL;
34 PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable = NULL;
35 HANDLE CurrentProcessId = NULL;
36 DWORD GDI_BatchLimit = 1;
37
38
39 BOOL
40 WINAPI
41 GdiAlphaBlend(
42 HDC hDCDst,
43 int DstX,
44 int DstY,
45 int DstCx,
46 int DstCy,
47 HDC hDCSrc,
48 int SrcX,
49 int SrcY,
50 int SrcCx,
51 int SrcCy,
52 BLENDFUNCTION BlendFunction
53 )
54 {
55 if ( hDCSrc == NULL ) return FALSE;
56
57 if (GDI_HANDLE_GET_TYPE(hDCSrc) == GDI_OBJECT_TYPE_METADC) return FALSE;
58
59 return NtGdiAlphaBlend(
60 hDCDst,
61 DstX,
62 DstY,
63 DstCx,
64 DstCy,
65 hDCSrc,
66 SrcX,
67 SrcY,
68 SrcCx,
69 SrcCy,
70 BlendFunction,
71 0 );
72 }
73
74 /*
75 * @implemented
76 */
77 HGDIOBJ
78 WINAPI
79 GdiFixUpHandle(HGDIOBJ hGdiObj)
80 {
81 PGDI_TABLE_ENTRY Entry;
82
83 if (((ULONG_PTR)(hGdiObj)) & GDI_HANDLE_UPPER_MASK )
84 {
85 return hGdiObj;
86 }
87
88 /* FIXME is this right ?? */
89
90 Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
91
92 /* Rebuild handle for Object */
93 return hGdiObj = (HGDIOBJ)(((LONG_PTR)(hGdiObj)) | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
94 }
95
96 /*
97 * @implemented
98 */
99 PVOID
100 WINAPI
101 GdiQueryTable(VOID)
102 {
103 return (PVOID)GdiHandleTable;
104 }
105
106 BOOL GdiIsHandleValid(HGDIOBJ hGdiObj)
107 {
108 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
109 // We are only looking for TYPE not the rest here, and why is FullUnique filled up with CRAP!?
110 // DPRINT1("FullUnique -> %x\n", Entry->FullUnique);
111 if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) != 0 &&
112 ( (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK ) ==
113 GDI_HANDLE_GET_TYPE(hGdiObj))
114 {
115 HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
116 if(pid == NULL || pid == CurrentProcessId)
117 {
118 return TRUE;
119 }
120 }
121 return FALSE;
122 }
123
124 BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, DWORD ObjectType, PVOID *UserData)
125 {
126 PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj);
127
128 /* Check if twe have the correct type */
129 if (GDI_HANDLE_GET_TYPE(hGdiObj) != ObjectType ||
130 ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK) != ObjectType ||
131 (Entry->Type & GDI_ENTRY_BASETYPE_MASK) != (ObjectType & GDI_ENTRY_BASETYPE_MASK))
132 {
133 return FALSE;
134 }
135
136 /* Check if we are the owner */
137 if ((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) != CurrentProcessId)
138 {
139 return FALSE;
140 }
141
142 *UserData = Entry->UserData;
143 return TRUE;
144 }
145
146 PLDC
147 FASTCALL
148 GdiGetLDC(HDC hdc)
149 {
150 PDC_ATTR pdcattr;
151
152 /* Get the DC attribute */
153 pdcattr = GdiGetDcAttr(hdc);
154 if (pdcattr == NULL)
155 {
156 return NULL;
157 }
158
159 /* Return the LDC pointer */
160 return pdcattr->pvLDC;
161 }
162
163 BOOL
164 FASTCALL
165 GdiSetLDC(HDC hdc, PVOID pvLDC)
166 {
167 PDC_ATTR pdcattr;
168
169 /* Get the DC attribute */
170 pdcattr = GdiGetDcAttr(hdc);
171 if (pdcattr == NULL)
172 {
173 return FALSE;
174 }
175
176 /* Set the LDC pointer */
177 pdcattr->pvLDC = pvLDC;
178 return TRUE;
179 }
180
181
182 VOID GdiSAPCallback(PLDC pldc)
183 {
184 DWORD Time, NewTime = GetTickCount();
185
186 Time = NewTime - pldc->CallBackTick;
187
188 if ( Time < SAPCALLBACKDELAY) return;
189
190 pldc->CallBackTick = NewTime;
191
192 if ( !pldc->pAbortProc(pldc->hDC, 0) )
193 {
194 CancelDC(pldc->hDC);
195 AbortDoc(pldc->hDC);
196 }
197 }
198
199 /*
200 * @implemented
201 */
202 DWORD
203 WINAPI
204 GdiSetBatchLimit(DWORD Limit)
205 {
206 DWORD OldLimit = GDI_BatchLimit;
207
208 if ( (!Limit) ||
209 (Limit >= GDI_BATCH_LIMIT))
210 {
211 return Limit;
212 }
213
214 GdiFlush();
215 GDI_BatchLimit = Limit;
216 return OldLimit;
217 }
218
219
220 /*
221 * @implemented
222 */
223 DWORD
224 WINAPI
225 GdiGetBatchLimit()
226 {
227 return GDI_BatchLimit;
228 }
229
230 /*
231 * @unimplemented
232 */
233 BOOL
234 WINAPI
235 GdiReleaseDC(HDC hdc)
236 {
237 return 0;
238 }
239
240 INT
241 WINAPI
242 ExtEscape(HDC hDC,
243 int nEscape,
244 int cbInput,
245 LPCSTR lpszInData,
246 int cbOutput,
247 LPSTR lpszOutData)
248 {
249 return NtGdiExtEscape(hDC, NULL, 0, nEscape, cbInput, (LPSTR)lpszInData, cbOutput, lpszOutData);
250 }
251
252 /*
253 * @implemented
254 */
255 VOID
256 WINAPI
257 GdiSetLastError(DWORD dwErrCode)
258 {
259 NtCurrentTeb()->LastErrorValue = (ULONG) dwErrCode;
260 }
261
262 BOOL
263 WINAPI
264 GdiAddGlsBounds(HDC hdc,LPRECT prc)
265 {
266 //FIXME: Lookup what 0x8000 means
267 return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
268 }
269
270 extern PGDIHANDLECACHE GdiHandleCache;
271
272 HGDIOBJ
273 FASTCALL
274 hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr)
275 {
276 int Number, Offset, MaxNum, GdiType;
277 HANDLE Lock;
278 HGDIOBJ Handle = NULL;
279
280 Lock = InterlockedCompareExchangePointer( (PVOID*)&GdiHandleCache->ulLock,
281 NtCurrentTeb(),
282 NULL );
283
284 if (Lock) return Handle;
285
286 Number = GdiHandleCache->ulNumHandles[Type];
287
288 if (Type == hctBrushHandle)
289 {
290 Offset = 0;
291 MaxNum = CACHE_BRUSH_ENTRIES;
292 GdiType = GDILoObjType_LO_BRUSH_TYPE;
293 }
294 else if (Type == hctPenHandle)
295 {
296 Offset = CACHE_BRUSH_ENTRIES;
297 MaxNum = CACHE_PEN_ENTRIES;
298 GdiType = GDILoObjType_LO_PEN_TYPE;
299 }
300 else if (Type == hctRegionHandle)
301 {
302 Offset = CACHE_BRUSH_ENTRIES+CACHE_PEN_ENTRIES;
303 MaxNum = CACHE_REGION_ENTRIES;
304 GdiType = GDILoObjType_LO_REGION_TYPE;
305 }
306 else // Font is not supported here.
307 {
308 return Handle;
309 }
310
311 if ( Number && Number <= MaxNum )
312 {
313 PBRUSH_ATTR pBrush_Attr;
314 HGDIOBJ *hPtr;
315 hPtr = GdiHandleCache->Handle + Offset;
316 Handle = hPtr[Number - 1];
317
318 if (GdiGetHandleUserData( Handle, GdiType, (PVOID) &pBrush_Attr))
319 {
320 if (pBrush_Attr->AttrFlags & ATTR_CACHED)
321 {
322 DPRINT("Get Handle! Type %d Count %lu PEB 0x%p\n", Type, GdiHandleCache->ulNumHandles[Type], NtCurrentTeb()->ProcessEnvironmentBlock);
323 pBrush_Attr->AttrFlags &= ~ATTR_CACHED;
324 hPtr[Number - 1] = NULL;
325 GdiHandleCache->ulNumHandles[Type]--;
326 if ( Type == hctBrushHandle ) // Handle only brush.
327 {
328 if ( pBrush_Attr->lbColor != cr )
329 {
330 pBrush_Attr->lbColor = cr ;
331 pBrush_Attr->AttrFlags |= ATTR_NEW_COLOR;
332 }
333 }
334 }
335 }
336 else
337 {
338 Handle = NULL;
339 }
340 }
341 (void)InterlockedExchangePointer((PVOID*)&GdiHandleCache->ulLock, Lock);
342 return Handle;
343 }
344