Release 940405
[wine/gsoc-2012-control.git] / windows / dce.c
blob3dfe56ef66cebd313c1a31762a6df334b31ca253
1 /*
2 * USER DCE functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include "dce.h"
10 #include "class.h"
11 #include "win.h"
12 #include "gdi.h"
13 #include "user.h"
16 #define NB_DCE 5 /* Number of DCEs created at startup */
18 extern Display * display;
20 static HANDLE firstDCE = 0;
21 static HDC defaultDCstate = 0;
24 /***********************************************************************
25 * DCE_AllocDCE
27 * Allocate a new DCE.
29 HANDLE DCE_AllocDCE( DCE_TYPE type )
31 DCE * dce;
32 HANDLE handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(DCE) );
33 if (!handle) return 0;
34 dce = (DCE *) USER_HEAP_ADDR( handle );
35 if (!(dce->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL )))
37 USER_HEAP_FREE( handle );
38 return 0;
40 dce->hwndCurrent = 0;
41 dce->type = type;
42 dce->inUse = (type != DCE_CACHE_DC);
43 dce->xOrigin = 0;
44 dce->yOrigin = 0;
45 dce->hNext = firstDCE;
46 firstDCE = handle;
47 return handle;
51 /***********************************************************************
52 * DCE_FreeDCE
54 void DCE_FreeDCE( HANDLE hdce )
56 DCE * dce;
57 HANDLE *handle = &firstDCE;
59 if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return;
60 while (*handle && (*handle != hdce))
62 DCE * prev = (DCE *) USER_HEAP_ADDR( *handle );
63 handle = &prev->hNext;
65 if (*handle == hdce) *handle = dce->hNext;
66 DeleteDC( dce->hdc );
67 USER_HEAP_FREE( hdce );
71 /***********************************************************************
72 * DCE_Init
74 void DCE_Init()
76 int i;
77 HANDLE handle;
78 DCE * dce;
80 for (i = 0; i < NB_DCE; i++)
82 if (!(handle = DCE_AllocDCE( DCE_CACHE_DC ))) return;
83 dce = (DCE *) USER_HEAP_ADDR( handle );
84 if (!defaultDCstate) defaultDCstate = GetDCState( dce->hdc );
89 /***********************************************************************
90 * DCE_GetVisRect
92 * Return the visible rectangle of a window, i.e. the client or
93 * window area clipped by the client area of all ancestors.
95 static void DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
97 int xoffset, yoffset;
99 *lprect = clientArea ? wndPtr->rectClient : wndPtr->rectWindow;
100 xoffset = lprect->left;
101 yoffset = lprect->top;
103 while (wndPtr->dwStyle & WS_CHILD)
105 WND *parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
106 xoffset += parentPtr->rectClient.left;
107 yoffset += parentPtr->rectClient.top;
108 OffsetRect( lprect, parentPtr->rectClient.left,
109 parentPtr->rectClient.top );
111 /* Warning!! we assume that IntersectRect() handles the case */
112 /* where the destination is the same as one of the sources. */
113 IntersectRect( lprect, lprect, &parentPtr->rectClient );
114 wndPtr = parentPtr;
116 OffsetRect( lprect, -xoffset, -yoffset );
120 /***********************************************************************
121 * GetDCEx (USER.359)
123 /* Unimplemented flags: DCX_CLIPSIBLINGS, DCX_LOCKWINDOWUPDATE, DCX_PARENTCLIP
125 HDC GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
127 HANDLE hdce;
128 RECT clipRect;
129 HDC hdc = 0;
130 DCE * dce;
131 DC * dc;
132 WND * wndPtr;
134 if (hwnd)
136 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
138 else wndPtr = NULL;
140 if (flags & DCX_USESTYLE)
142 /* Not sure if this is the real meaning of the DCX_USESTYLE flag... */
143 flags &= ~(DCX_CACHE | DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS);
144 if (wndPtr)
146 if (!(wndPtr->flags & (WIN_CLASS_DC | WIN_OWN_DC)))
147 flags |= DCX_CACHE;
148 if (wndPtr->dwStyle & WS_CLIPCHILDREN) flags |= DCX_CLIPCHILDREN;
149 if (wndPtr->dwStyle & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
151 else flags |= DCX_CACHE;
154 if (flags & DCX_CACHE)
156 for (hdce = firstDCE; (hdce); hdce = dce->hNext)
158 if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return 0;
159 if ((dce->type == DCE_CACHE_DC) && (!dce->inUse)) break;
162 else hdce = wndPtr->hdce;
164 if (!hdce) return 0;
165 dce = (DCE *) USER_HEAP_ADDR( hdce );
166 dce->hwndCurrent = hwnd;
167 dce->inUse = TRUE;
168 hdc = dce->hdc;
170 /* Initialize DC */
172 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
174 if (wndPtr)
176 dc->u.x.drawable = wndPtr->window;
177 if (flags & DCX_WINDOW)
179 dc->w.DCOrgX = 0;
180 dc->w.DCOrgY = 0;
181 dc->w.DCSizeX = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
182 dc->w.DCSizeY = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
184 else
186 dc->w.DCOrgX = wndPtr->rectClient.left - wndPtr->rectWindow.left;
187 dc->w.DCOrgY = wndPtr->rectClient.top - wndPtr->rectWindow.top;
188 dc->w.DCSizeX = wndPtr->rectClient.right - wndPtr->rectClient.left;
189 dc->w.DCSizeY = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
192 DCE_GetVisRect( wndPtr, !(flags & DCX_WINDOW), &clipRect );
193 IntersectVisRect( hdc, clipRect.left, clipRect.top,
194 clipRect.right, clipRect.bottom );
196 else dc->u.x.drawable = rootWindow;
198 if (flags & DCX_CLIPCHILDREN)
199 XSetSubwindowMode( display, dc->u.x.gc, ClipByChildren );
200 else XSetSubwindowMode( display, dc->u.x.gc, IncludeInferiors);
202 if ((flags & DCX_INTERSECTRGN) || (flags & DCX_EXCLUDERGN))
204 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
205 if (hrgn)
207 if (CombineRgn( hrgn, InquireVisRgn(hdc), hrgnClip,
208 (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ))
209 SelectVisRgn( hdc, hrgn );
210 DeleteObject( hrgn );
214 #ifdef DEBUG_DC
215 printf( "GetDCEx(%d,%d,0x%x): returning %d\n", hwnd, hrgnClip, flags, hdc);
216 #endif
217 return hdc;
221 /***********************************************************************
222 * GetDC (USER.66)
224 HDC GetDC( HWND hwnd )
226 return GetDCEx( hwnd, 0, DCX_USESTYLE );
230 /***********************************************************************
231 * GetWindowDC (USER.67)
233 HDC GetWindowDC( HWND hwnd )
235 int flags = DCX_CACHE | DCX_WINDOW;
236 if (hwnd)
238 WND * wndPtr;
239 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
240 if (wndPtr->dwStyle & WS_CLIPCHILDREN) flags |= DCX_CLIPCHILDREN;
241 if (wndPtr->dwStyle & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
243 return GetDCEx( hwnd, 0, flags );
247 /***********************************************************************
248 * ReleaseDC (USER.68)
250 int ReleaseDC( HWND hwnd, HDC hdc )
252 HANDLE hdce;
253 DCE * dce = NULL;
255 #ifdef DEBUG_DC
256 printf( "ReleaseDC: %d %d\n", hwnd, hdc );
257 #endif
259 for (hdce = firstDCE; (hdce); hdce = dce->hNext)
261 if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return 0;
262 if (dce->inUse && (dce->hdc == hdc)) break;
264 if (!hdce) return 0;
266 if (dce->type == DCE_CACHE_DC)
268 SetDCState( dce->hdc, defaultDCstate );
269 dce->inUse = FALSE;
271 return 1;