d72b684254a768670fbe162e74a39a761b765fc9
[reactos.git] / subsys / win32k / objects / dc.c
1 /* $Id$
2  *
3  * DC.C - Device context functions
4  *
5  */
6
7 #undef WIN32_LEAN_AND_MEAN
8 #include <windows.h>
9 #include <ddk/ntddk.h>
10 #include <ddk/ntddvid.h>
11
12 #include <win32k/bitmaps.h>
13 #include <win32k/coord.h>
14 #include <win32k/driver.h>
15 #include <win32k/dc.h>
16 #include <win32k/print.h>
17 #include <win32k/region.h>
18 #include <win32k/gdiobj.h>
19 #include <win32k/pen.h>
20 #include <win32k/text.h>
21 #include "../eng/handle.h"
22 #include <include/inteng.h>
23
24 #define NDEBUG
25 #include <win32k/debug1.h>
26
27 static GDIDEVICE PrimarySurface;
28 static BOOL PrimarySurfaceCreated = FALSE;
29
30 /* FIXME: DCs should probably be thread safe  */
31
32 /*
33  * DC device-independent Get/SetXXX functions
34  * (RJJ) swiped from WINE
35  */
36
37 #define DC_GET_VAL( func_type, func_name, dc_field ) \
38 func_type STDCALL  func_name( HDC hdc ) \
39 {                                   \
40   func_type  ft;                    \
41   PDC  dc = DC_HandleToPtr( hdc );  \
42   if (!dc)                          \
43   {                                 \
44     return 0;                       \
45   }                                 \
46   ft = dc->dc_field;                \
47   DC_ReleasePtr( hdc );                         \
48   return ft;                        \
49 }
50
51 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
52  * important that the function has the right signature, for the implementation
53  * we can do whatever we want.
54  */
55 #define DC_GET_VAL_EX( func_name, ret_x, ret_y, type ) \
56 BOOL STDCALL  func_name( HDC hdc, LP##type pt ) \
57 {                                   \
58   PDC  dc = DC_HandleToPtr( hdc );  \
59   if (!dc)                          \
60   {                                 \
61     return FALSE;                   \
62   }                                 \
63   ((LPPOINT)pt)->x = dc->ret_x;     \
64   ((LPPOINT)pt)->y = dc->ret_y;     \
65   DC_ReleasePtr( hdc );                         \
66   return  TRUE;                     \
67 }
68
69 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
70 INT STDCALL  func_name( HDC hdc, INT mode ) \
71 {                                           \
72   INT  prevMode;                            \
73   PDC  dc = DC_HandleToPtr( hdc );          \
74   if(!dc)                                   \
75   {                                         \
76     return 0;                               \
77   }                                         \
78   if ((mode < min_val) || (mode > max_val)) \
79   {                                         \
80     return 0;                               \
81   }                                         \
82   prevMode = dc->dc_field;                  \
83   dc->dc_field = mode;                      \
84   DC_ReleasePtr( hdc );                                         \
85   return prevMode;                          \
86 }
87
88
89 //  ---------------------------------------------------------  File Statics
90
91 static void  W32kSetDCState16(HDC  hDC, HDC  hDCSave);
92
93 //  -----------------------------------------------------  Public Functions
94
95 BOOL STDCALL  W32kCancelDC(HDC  hDC)
96 {
97   UNIMPLEMENTED;
98 }
99
100 HDC STDCALL  W32kCreateCompatableDC(HDC  hDC)
101 {
102   PDC  NewDC, OrigDC = NULL;
103   HBITMAP  hBitmap;
104   HDC hNewDC;
105
106   OrigDC = DC_HandleToPtr(hDC);
107   if (OrigDC == NULL)
108   {
109     hNewDC = DC_AllocDC(L"DISPLAY");
110         if( hNewDC )
111                 NewDC = DC_HandleToPtr( hNewDC );
112   }
113   else {
114     /*  Allocate a new DC based on the original DC's device  */
115     hNewDC = DC_AllocDC(OrigDC->DriverName);
116         if( hNewDC )
117                 NewDC = DC_HandleToPtr( hNewDC );
118   }
119
120   if (NewDC == NULL)
121   {
122     return  NULL;
123   }
124
125   /* Copy information from original DC to new DC  */
126   NewDC->hSelf = NewDC;
127
128   /* FIXME: Should this DC request its own PDEV?  */
129   if(OrigDC == NULL) {
130   } else {
131     NewDC->PDev = OrigDC->PDev;
132     NewDC->DMW = OrigDC->DMW;
133     memcpy(NewDC->FillPatternSurfaces,
134            OrigDC->FillPatternSurfaces,
135            sizeof OrigDC->FillPatternSurfaces);
136     NewDC->GDIInfo = OrigDC->GDIInfo;
137     NewDC->DevInfo = OrigDC->DevInfo;
138   }
139
140   /* DriverName is copied in the AllocDC routine  */
141   if(OrigDC == NULL) {
142     NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName);
143   } else {
144     NewDC->DeviceDriver = OrigDC->DeviceDriver;
145     NewDC->wndOrgX = OrigDC->wndOrgX;
146     NewDC->wndOrgY = OrigDC->wndOrgY;
147     NewDC->wndExtX = OrigDC->wndExtX;
148     NewDC->wndExtY = OrigDC->wndExtY;
149     NewDC->vportOrgX = OrigDC->vportOrgX;
150     NewDC->vportOrgY = OrigDC->vportOrgY;
151     NewDC->vportExtX = OrigDC->vportExtX;
152     NewDC->vportExtY = OrigDC->vportExtY;
153   }
154
155   /* Create default bitmap */
156   if (!(hBitmap = W32kCreateBitmap( 1, 1, 1, 1, NULL )))
157   {
158     DC_ReleasePtr( hNewDC );
159     DC_FreeDC( hNewDC );
160     return NULL;
161   }
162   NewDC->w.flags        = DC_MEMORY;
163   NewDC->w.bitsPerPixel = 1;
164   NewDC->w.hBitmap      = hBitmap;
165   NewDC->w.hFirstBitmap = hBitmap;
166   NewDC->Surface = BitmapToSurf(BITMAPOBJ_HandleToPtr(hBitmap));
167
168   if(OrigDC != NULL)
169   {
170     NewDC->w.hPalette = OrigDC->w.hPalette;
171     NewDC->w.textColor = OrigDC->w.textColor;
172     NewDC->w.textAlign = OrigDC->w.textAlign;
173   }
174   DC_ReleasePtr( hDC );
175   DC_ReleasePtr( hNewDC );
176   DC_InitDC(hNewDC);
177
178   return  hNewDC;
179 }
180
181 static BOOL STDCALL FindDriverFileNames(PUNICODE_STRING DriverFileNames)
182 {
183   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
184   UNICODE_STRING RegistryPath;
185   NTSTATUS Status;
186
187   RtlInitUnicodeString(&RegistryPath, NULL);
188   RtlZeroMemory(QueryTable, sizeof(QueryTable));
189   QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
190   QueryTable[0].Name = L"\\Device\\Video0";
191   QueryTable[0].EntryContext = &RegistryPath;
192
193   Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
194                                   L"VIDEO",
195                                   QueryTable,
196                                   NULL,
197                                   NULL);
198   if (! NT_SUCCESS(Status))
199   {
200     DPRINT1("No \\Device\\Video0 value in DEVICEMAP\\VIDEO found\n");
201     return FALSE;
202   }
203
204   DPRINT("RegistryPath %S\n", RegistryPath.Buffer);
205
206   QueryTable[0].Name = L"InstalledDisplayDrivers";
207   QueryTable[0].EntryContext = DriverFileNames;
208
209   Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
210                                   RegistryPath.Buffer,
211                                   QueryTable,
212                                   NULL,
213                                   NULL);
214   RtlFreeUnicodeString(&RegistryPath);
215   if (! NT_SUCCESS(Status))
216   {
217     DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
218     return FALSE;
219   }
220
221   DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
222
223   return TRUE;
224 }
225
226 BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver,
227                                       LPCWSTR Device)
228 {
229   PGD_ENABLEDRIVER GDEnableDriver;
230   HANDLE DeviceDriver;
231   DRVENABLEDATA DED;
232   PSURFOBJ SurfObj;
233   UNICODE_STRING DriverFileNames;
234   PWSTR CurrentName;
235   BOOL GotDriver;
236
237   /*  Open the miniport driver  */
238   if ((DeviceDriver = DRIVER_FindMPDriver(Driver)) == NULL)
239   {
240     DPRINT("FindMPDriver failed\n");
241     return(FALSE);
242   }
243
244   /*  Retrieve DDI driver names from registry */
245   RtlInitUnicodeString(&DriverFileNames, NULL);
246   if (! FindDriverFileNames(&DriverFileNames))
247   {
248     DPRINT("FindDriverFileNames failed\n");
249     return(FALSE);
250   }
251
252   /* DriverFileNames may be a list of drivers in REG_SZ_MULTI format, scan all of
253      them until a good one found */
254   CurrentName = DriverFileNames.Buffer;
255   GotDriver = FALSE;
256   while (! GotDriver && CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
257   {
258     /*  Get the DDI driver's entry point  */
259     GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
260     if (NULL == GDEnableDriver)
261     {
262       DPRINT("FindDDIDriver failed for %S\n", CurrentName);
263     }
264     else
265     {
266       /*  Call DDI driver's EnableDriver function  */
267       RtlZeroMemory(&DED, sizeof(DED));
268
269       if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
270       {
271         DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
272       }
273       else
274       {
275         GotDriver = TRUE;
276       }
277     }
278
279     if (! GotDriver)
280     {
281       /* Skip to the next name but never get past the Unicode string */
282       while (L'\0' != *CurrentName &&
283              CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
284       {
285         CurrentName++;
286       }
287       if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
288       {
289         CurrentName++;
290       }
291     }
292   }
293   RtlFreeUnicodeString(&DriverFileNames);
294   if (! GotDriver)
295   {
296     DPRINT("No suitable driver found\n");
297     return FALSE;
298   }
299
300   DPRINT("Display driver %S loaded\n", DriverName);
301
302   DPRINT("Building DDI Functions\n");
303
304   /*  Construct DDI driver function dispatch table  */
305   if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
306   {
307     DPRINT("BuildDDIFunctions failed\n");
308     return(FALSE);
309   }
310
311   /*  Allocate a phyical device handle from the driver  */
312   if (Device != NULL)
313   {
314     DPRINT("Device in u: %u\n", Device);
315 //    wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything?
316   }
317
318   DPRINT("Enabling PDev\n");
319
320   PrimarySurface.PDev =
321     PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
322                                              L"",
323                                              HS_DDI_MAX,
324                                              PrimarySurface.FillPatterns,
325                                              sizeof(PrimarySurface.GDIInfo),
326                                              (ULONG *) &PrimarySurface.GDIInfo,
327                                              sizeof(PrimarySurface.DevInfo),
328                                              &PrimarySurface.DevInfo,
329                                              NULL,
330                                              L"",
331                                              DeviceDriver);
332   if (PrimarySurface.PDev == NULL)
333   {
334     DPRINT("DrvEnablePDEV failed\n");
335     return(FALSE);
336   }
337
338   DPRINT("calling completePDev\n");
339
340   /*  Complete initialization of the physical device  */
341   PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev,
342                                               &PrimarySurface);
343
344   DPRINT("calling DRIVER_ReferenceDriver\n");
345
346   DRIVER_ReferenceDriver (Driver);
347
348   DPRINT("calling EnableSurface\n");
349
350   /*  Enable the drawing surface  */
351   PrimarySurface.Handle =
352     PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
353
354   SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
355   SurfObj->dhpdev = PrimarySurface.PDev;
356
357   return TRUE;
358 }
359
360 HDC STDCALL  W32kCreateDC(LPCWSTR  Driver,
361                   LPCWSTR  Device,
362                   LPCWSTR  Output,
363                   CONST PDEVMODEW  InitData)
364 {
365   HDC      hNewDC;
366   PDC      NewDC;
367   HDC      hDC = NULL;
368   PSURFGDI SurfGDI;
369
370   /*  Check for existing DC object  */
371   if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
372   {
373     hDC = hNewDC;
374     return  W32kCreateCompatableDC(hDC);
375   }
376
377   DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL
378
379   /*  Allocate a DC object  */
380   if ((hNewDC = DC_AllocDC(Driver)) == NULL)
381   {
382     return  NULL;
383   }
384
385   NewDC = DC_HandleToPtr( hNewDC );
386   ASSERT( NewDC );
387
388   if (!PrimarySurfaceCreated)
389     {
390       if (!W32kCreatePrimarySurface(Driver, Device))
391         {
392           DC_ReleasePtr( hNewDC );
393           DC_FreeDC(hNewDC);
394           return  NULL;
395         }
396     }
397   PrimarySurfaceCreated = TRUE;
398   NewDC->DMW = PrimarySurface.DMW;
399   NewDC->DevInfo = PrimarySurface.DevInfo;
400   NewDC->GDIInfo = PrimarySurface.GDIInfo;
401   memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
402          sizeof(NewDC->FillPatternSurfaces));
403   NewDC->PDev = PrimarySurface.PDev;
404   NewDC->Surface = PrimarySurface.Handle;
405   NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
406
407   NewDC->DMW.dmSize = sizeof(NewDC->DMW);
408   NewDC->DMW.dmFields = 0x000fc000;
409
410   /* FIXME: get mode selection information from somewhere  */
411
412   NewDC->DMW.dmLogPixels = 96;
413   SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
414   NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
415   NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
416   NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
417   NewDC->DMW.dmDisplayFlags = 0;
418   NewDC->DMW.dmDisplayFrequency = 0;
419
420   NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
421
422   NewDC->w.hPalette = NewDC->DevInfo.hpalDefault;
423
424   DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
425
426   NewDC->w.hVisRgn = W32kCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
427                                        SurfGDI->SurfObj.sizlBitmap.cy);
428   DC_ReleasePtr( hNewDC );
429
430   /*  Initialize the DC state  */
431   DC_InitDC(hNewDC);
432   W32kSetTextColor(hNewDC, RGB(0, 0, 0));
433   W32kSetTextAlign(hNewDC, TA_TOP);
434
435   return hNewDC;
436 }
437
438 HDC STDCALL W32kCreateIC(LPCWSTR  Driver,
439                          LPCWSTR  Device,
440                          LPCWSTR  Output,
441                          CONST PDEVMODEW  DevMode)
442 {
443   /* FIXME: this should probably do something else...  */
444   return  W32kCreateDC(Driver, Device, Output, DevMode);
445 }
446
447 BOOL STDCALL W32kDeleteDC(HDC  DCHandle)
448 {
449   PDC  DCToDelete;
450
451   DCToDelete = DC_HandleToPtr(DCHandle);
452   if (DCToDelete == NULL)
453     {
454       return  FALSE;
455     }
456   DPRINT( "Deleting DC\n" );
457   if ((!(DCToDelete->w.flags & DC_MEMORY))) // Don't reset the display if its a memory DC
458   {
459     if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName))
460     {
461       DPRINT( "No more references to driver, reseting display\n" );
462       DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev);
463       CHECKPOINT;
464       DCToDelete->DriverFunctions.AssertMode( DCToDelete->PDev, FALSE );
465       CHECKPOINT;
466       DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev);
467           PrimarySurfaceCreated = FALSE;
468         }
469   }
470   CHECKPOINT;
471   /*  First delete all saved DCs  */
472   while (DCToDelete->saveLevel)
473   {
474     PDC  savedDC;
475     HDC  savedHDC;
476
477     savedHDC = DC_GetNextDC (DCToDelete);
478     savedDC = DC_HandleToPtr (savedHDC);
479     if (savedDC == NULL)
480     {
481       break;
482     }
483     DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
484     DCToDelete->saveLevel--;
485         DC_ReleasePtr( savedHDC );
486     W32kDeleteDC (savedHDC);
487   }
488
489   /*  Free GDI resources allocated to this DC  */
490   if (!(DCToDelete->w.flags & DC_SAVED))
491   {
492     /*
493     W32kSelectObject (DCHandle, STOCK_BLACK_PEN);
494     W32kSelectObject (DCHandle, STOCK_WHITE_BRUSH);
495     W32kSelectObject (DCHandle, STOCK_SYSTEM_FONT);
496     DC_LockDC (DCHandle); W32kSelectObject does not recognize stock objects yet  */
497     BITMAPOBJ_ReleasePtr(DCToDelete->w.hBitmap);
498     if (DCToDelete->w.flags & DC_MEMORY)
499     {
500       EngDeleteSurface (DCToDelete->Surface);
501       W32kDeleteObject (DCToDelete->w.hFirstBitmap);
502     }
503   }
504   if (DCToDelete->w.hClipRgn)
505   {
506     W32kDeleteObject (DCToDelete->w.hClipRgn);
507   }
508   if (DCToDelete->w.hVisRgn)
509   {
510     W32kDeleteObject (DCToDelete->w.hVisRgn);
511   }
512   if (DCToDelete->w.hGCClipRgn)
513   {
514     W32kDeleteObject (DCToDelete->w.hGCClipRgn);
515   }
516 #if 0 /* FIXME */
517   PATH_DestroyGdiPath (&DCToDelete->w.path);
518 #endif
519   DC_ReleasePtr( DCToDelete );
520   DC_FreeDC (DCToDelete);
521
522   return TRUE;
523 }
524
525 INT STDCALL W32kDrawEscape(HDC  hDC,
526                     INT  nEscape,
527                     INT  cbInput,
528                     LPCSTR  lpszInData)
529 {
530   UNIMPLEMENTED;
531 }
532
533 INT STDCALL W32kEnumObjects(HDC  hDC,
534                      INT  ObjectType,
535                      GOBJENUMPROC  ObjectFunc,
536                      LPARAM  lParam)
537 {
538   UNIMPLEMENTED;
539 }
540
541 DC_GET_VAL( COLORREF, W32kGetBkColor, w.backgroundColor )
542 DC_GET_VAL( INT, W32kGetBkMode, w.backgroundMode )
543 DC_GET_VAL_EX( W32kGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
544 DC_GET_VAL( HRGN, W32kGetClipRgn, w.hClipRgn )
545
546 HGDIOBJ STDCALL W32kGetCurrentObject(HDC  hDC,
547                               UINT  ObjectType)
548 {
549   UNIMPLEMENTED;
550 }
551
552 DC_GET_VAL_EX( W32kGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
553
554 BOOL STDCALL W32kGetDCOrgEx(HDC  hDC,
555                      LPPOINT  Point)
556 {
557   PDC dc;
558
559   if (!Point)
560   {
561     return FALSE;
562   }
563   dc = DC_HandleToPtr(hDC);
564   if (dc == NULL)
565   {
566     return FALSE;
567   }
568
569   Point->x = Point->y = 0;
570
571   Point->x += dc->w.DCOrgX;
572   Point->y += dc->w.DCOrgY;
573   DC_ReleasePtr( hDC );
574   return  TRUE;
575 }
576
577 HDC STDCALL W32kGetDCState16(HDC  hDC)
578 {
579   PDC  newdc, dc;
580   HDC hnewdc;
581
582   dc = DC_HandleToPtr(hDC);
583   if (dc == NULL)
584   {
585     return 0;
586   }
587
588   hnewdc = DC_AllocDC(NULL);
589   if (hnewdc == NULL)
590   {
591         DC_ReleasePtr( hDC );
592     return 0;
593   }
594   newdc = DC_HandleToPtr( hnewdc );
595   ASSERT( newdc );
596
597   newdc->w.flags            = dc->w.flags | DC_SAVED;
598 #if 0
599   newdc->w.devCaps          = dc->w.devCaps;
600 #endif
601   newdc->w.hPen             = dc->w.hPen;
602   newdc->w.hBrush           = dc->w.hBrush;
603   newdc->w.hFont            = dc->w.hFont;
604   newdc->w.hBitmap          = dc->w.hBitmap;
605   newdc->w.hFirstBitmap     = dc->w.hFirstBitmap;
606 #if 0
607   newdc->w.hDevice          = dc->w.hDevice;
608   newdc->w.hPalette         = dc->w.hPalette;
609 #endif
610   newdc->w.totalExtent      = dc->w.totalExtent;
611   newdc->w.bitsPerPixel     = dc->w.bitsPerPixel;
612   newdc->w.ROPmode          = dc->w.ROPmode;
613   newdc->w.polyFillMode     = dc->w.polyFillMode;
614   newdc->w.stretchBltMode   = dc->w.stretchBltMode;
615   newdc->w.relAbsMode       = dc->w.relAbsMode;
616   newdc->w.backgroundMode   = dc->w.backgroundMode;
617   newdc->w.backgroundColor  = dc->w.backgroundColor;
618   newdc->w.textColor        = dc->w.textColor;
619   newdc->w.brushOrgX        = dc->w.brushOrgX;
620   newdc->w.brushOrgY        = dc->w.brushOrgY;
621   newdc->w.textAlign        = dc->w.textAlign;
622   newdc->w.charExtra        = dc->w.charExtra;
623   newdc->w.breakTotalExtra  = dc->w.breakTotalExtra;
624   newdc->w.breakCount       = dc->w.breakCount;
625   newdc->w.breakExtra       = dc->w.breakExtra;
626   newdc->w.breakRem         = dc->w.breakRem;
627   newdc->w.MapMode          = dc->w.MapMode;
628   newdc->w.GraphicsMode     = dc->w.GraphicsMode;
629 #if 0
630   /* Apparently, the DC origin is not changed by [GS]etDCState */
631   newdc->w.DCOrgX           = dc->w.DCOrgX;
632   newdc->w.DCOrgY           = dc->w.DCOrgY;
633 #endif
634   newdc->w.CursPosX         = dc->w.CursPosX;
635   newdc->w.CursPosY         = dc->w.CursPosY;
636   newdc->w.ArcDirection     = dc->w.ArcDirection;
637 #if 0
638   newdc->w.xformWorld2Wnd   = dc->w.xformWorld2Wnd;
639   newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
640   newdc->w.xformVport2World = dc->w.xformVport2World;
641   newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
642 #endif
643   newdc->wndOrgX            = dc->wndOrgX;
644   newdc->wndOrgY            = dc->wndOrgY;
645   newdc->wndExtX            = dc->wndExtX;
646   newdc->wndExtY            = dc->wndExtY;
647   newdc->vportOrgX          = dc->vportOrgX;
648   newdc->vportOrgY          = dc->vportOrgY;
649   newdc->vportExtX          = dc->vportExtX;
650   newdc->vportExtY          = dc->vportExtY;
651
652   newdc->hSelf = hnewdc;
653   newdc->saveLevel = 0;
654
655 #if 0
656   PATH_InitGdiPath( &newdc->w.path );
657 #endif
658
659   /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
660
661 #if 0
662   newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
663 #endif
664   if (dc->w.hClipRgn)
665   {
666     newdc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
667     W32kCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
668   }
669   else
670   {
671     newdc->w.hClipRgn = 0;
672   }
673   DC_ReleasePtr( hnewdc );
674   return  hnewdc;
675 }
676
677 INT STDCALL W32kGetDeviceCaps(HDC  hDC,
678                        INT  Index)
679 {
680   PDC  dc;
681   INT  ret;
682   POINT  pt;
683
684   dc = DC_HandleToPtr(hDC);
685   if (dc == NULL)
686   {
687     return 0;
688   }
689
690   /* Device capabilities for the printer */
691   switch (Index)
692   {
693     case PHYSICALWIDTH:
694       if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
695       {
696         return pt.x;
697       }
698       break;
699
700     case PHYSICALHEIGHT:
701       if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
702       {
703         return pt.y;
704       }
705       break;
706
707     case PHYSICALOFFSETX:
708       if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
709       {
710         return pt.x;
711       }
712       break;
713
714     case PHYSICALOFFSETY:
715       if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
716       {
717         return pt.y;
718       }
719       break;
720
721     case SCALINGFACTORX:
722       if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
723       {
724         return pt.x;
725       }
726       break;
727
728     case SCALINGFACTORY:
729       if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
730       {
731         return pt.y;
732       }
733       break;
734   }
735
736   if ((Index < 0) || (Index > sizeof(DEVICECAPS) - sizeof(WORD)))
737   {
738     return 0;
739   }
740
741   DPRINT("(%04x,%d): returning %d\n",
742          hDC, Index, *(WORD *)(((char *)dc->w.devCaps) + Index));
743   ret = *(WORD *)(((char *)dc->w.devCaps) + Index);
744
745   DC_ReleasePtr( hDC );
746   return ret;
747 }
748
749 DC_GET_VAL( INT, W32kGetMapMode, w.MapMode )
750 DC_GET_VAL( INT, W32kGetPolyFillMode, w.polyFillMode )
751
752 INT STDCALL W32kGetObjectA(HANDLE handle, INT count, LPVOID buffer)
753 {
754   PGDIOBJ  gdiObject;
755   INT  result = 0;
756   WORD  magic;
757
758   if (!count)
759     return  0;
760   gdiObject = GDIOBJ_LockObj (handle, GO_MAGIC_DONTCARE);
761   if (gdiObject == 0)
762     return  0;
763
764   magic = GDIOBJ_GetHandleMagic (handle);
765   switch(magic)
766   {
767 /*    case GO_PEN_MAGIC:
768       result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
769       break;
770     case GO_BRUSH_MAGIC:
771       result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
772       break; */
773     case GO_BITMAP_MAGIC:
774       result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
775       break;
776 /*    case GO_FONT_MAGIC:
777       result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer);
778
779       // FIXME: Fix the LOGFONT structure for the stock fonts
780
781       if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
782         FixStockFontSizeA(handle, count, buffer);
783       break;
784     case GO_PALETTE_MAGIC:
785       result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
786       break; */
787
788     case GO_REGION_MAGIC:
789     case GO_DC_MAGIC:
790     case GO_DISABLED_DC_MAGIC:
791     case GO_META_DC_MAGIC:
792     case GO_METAFILE_MAGIC:
793     case GO_METAFILE_DC_MAGIC:
794     case GO_ENHMETAFILE_MAGIC:
795     case GO_ENHMETAFILE_DC_MAGIC:
796       // FIXME("Magic %04x not implemented\n", magic);
797       break;
798
799     default:
800       DbgPrint("Invalid GDI Magic %04x\n", magic);
801       break;
802   }
803   GDIOBJ_UnlockObj (handle, GO_MAGIC_DONTCARE);
804   return  result;
805 }
806
807 INT STDCALL W32kGetObjectW(HANDLE handle, INT count, LPVOID buffer)
808 {
809   PGDIOBJHDR  gdiObject;
810   INT  result = 0;
811   WORD  magic;
812
813   if (!count)
814     return 0;
815   gdiObject = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
816   if (gdiObject == 0)
817     return 0;
818
819   magic = GDIOBJ_GetHandleMagic (handle);
820   switch(magic)
821   {
822 /*    case GO_PEN_MAGIC:
823       result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
824       break;
825     case GO_BRUSH_MAGIC:
826       result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
827        break; */
828     case GO_BITMAP_MAGIC:
829       result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
830       break;
831 /*    case GO_FONT_MAGIC:
832       result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
833
834       // Fix the LOGFONT structure for the stock fonts
835
836       if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
837       FixStockFontSizeW(handle, count, buffer);
838     break;
839     case GO_PALETTE_MAGIC:
840       result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
841       break; */
842     default:
843       // FIXME("Magic %04x not implemented\n", gdiObject->magic);
844       break;
845   }
846   GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
847   return  result;
848 }
849
850 INT STDCALL W32kGetObject(HANDLE handle, INT count, LPVOID buffer)
851 {
852   return W32kGetObjectW(handle, count, buffer);
853 }
854
855 DWORD STDCALL W32kGetObjectType(HANDLE handle)
856 {
857   GDIOBJHDR * ptr;
858   INT result = 0;
859   WORD  magic;
860
861   ptr = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
862   if (ptr == 0)
863     return 0;
864
865   magic = GDIOBJ_GetHandleMagic (handle);
866   switch(magic)
867   {
868     case GO_PEN_MAGIC:
869       result = OBJ_PEN;
870       break;
871     case GO_BRUSH_MAGIC:
872       result = OBJ_BRUSH;
873       break;
874     case GO_BITMAP_MAGIC:
875       result = OBJ_BITMAP;
876       break;
877     case GO_FONT_MAGIC:
878       result = OBJ_FONT;
879       break;
880     case GO_PALETTE_MAGIC:
881       result = OBJ_PAL;
882       break;
883     case GO_REGION_MAGIC:
884       result = OBJ_REGION;
885       break;
886     case GO_DC_MAGIC:
887       result = OBJ_DC;
888       break;
889     case GO_META_DC_MAGIC:
890       result = OBJ_METADC;
891       break;
892     case GO_METAFILE_MAGIC:
893       result = OBJ_METAFILE;
894       break;
895     case GO_METAFILE_DC_MAGIC:
896      result = OBJ_METADC;
897       break;
898     case GO_ENHMETAFILE_MAGIC:
899       result = OBJ_ENHMETAFILE;
900       break;
901     case GO_ENHMETAFILE_DC_MAGIC:
902       result = OBJ_ENHMETADC;
903       break;
904     default:
905       // FIXME("Magic %04x not implemented\n", magic);
906       break;
907   }
908   GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
909   return result;
910 }
911
912 DC_GET_VAL( INT, W32kGetRelAbs, w.relAbsMode )
913 DC_GET_VAL( INT, W32kGetROP2, w.ROPmode )
914 DC_GET_VAL( INT, W32kGetStretchBltMode, w.stretchBltMode )
915 DC_GET_VAL( UINT, W32kGetTextAlign, w.textAlign )
916 DC_GET_VAL( COLORREF, W32kGetTextColor, w.textColor )
917 DC_GET_VAL_EX( W32kGetViewportExtEx, vportExtX, vportExtY, SIZE )
918 DC_GET_VAL_EX( W32kGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
919 DC_GET_VAL_EX( W32kGetWindowExtEx, wndExtX, wndExtY, SIZE )
920 DC_GET_VAL_EX( W32kGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
921
922 HDC STDCALL W32kResetDC(HDC  hDC, CONST DEVMODEW *InitData)
923 {
924   UNIMPLEMENTED;
925 }
926
927 BOOL STDCALL W32kRestoreDC(HDC  hDC, INT  SaveLevel)
928 {
929   PDC  dc, dcs;
930   BOOL  success;
931
932   dc = DC_HandleToPtr(hDC);
933   if(!dc)
934   {
935     return FALSE;
936   }
937
938   if (SaveLevel == -1)
939   {
940     SaveLevel = dc->saveLevel;
941   }
942
943   if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
944   {
945     return FALSE;
946   }
947
948   success = TRUE;
949   while (dc->saveLevel >= SaveLevel)
950   {
951     HDC hdcs = DC_GetNextDC (dc);
952
953     dcs = DC_HandleToPtr (hdcs);
954     if (dcs == NULL)
955     {
956       return FALSE;
957     }
958     DC_SetNextDC (dcs, DC_GetNextDC (dcs));
959     if (--dc->saveLevel < SaveLevel)
960       {
961         W32kSetDCState16 (hDC, hdcs);
962 #if 0
963         if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
964         {
965           /* FIXME: This might not be quite right, since we're
966            * returning FALSE but still destroying the saved DC state */
967           success = FALSE;
968         }
969 #endif
970       }
971           DC_ReleasePtr( hdcs );
972     W32kDeleteDC (hdcs);
973   }
974   DC_ReleasePtr( hDC );
975   return  success;
976 }
977
978 INT STDCALL W32kSaveDC(HDC  hDC)
979 {
980   HDC  hdcs;
981   PDC  dc, dcs;
982   INT  ret;
983
984   dc = DC_HandleToPtr (hDC);
985   if (dc == NULL)
986   {
987     return 0;
988   }
989
990   if (!(hdcs = W32kGetDCState16 (hDC)))
991   {
992     return 0;
993   }
994   dcs = DC_HandleToPtr (hdcs);
995
996 #if 0
997     /* Copy path. The reason why path saving / restoring is in SaveDC/
998      * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
999      * functions are only in Win16 (which doesn't have paths) and that
1000      * SetDCState doesn't allow us to signal an error (which can happen
1001      * when copying paths).
1002      */
1003   if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
1004   {
1005     W32kDeleteDC (hdcs);
1006     return 0;
1007   }
1008 #endif
1009
1010   DC_SetNextDC (dcs, DC_GetNextDC (dc));
1011   DC_SetNextDC (dc, hdcs);
1012   ret = ++dc->saveLevel;
1013   DC_ReleasePtr( hdcs );
1014   DC_ReleasePtr( hDC );
1015
1016   return  ret;
1017 }
1018
1019 HGDIOBJ STDCALL W32kSelectObject(HDC  hDC, HGDIOBJ  hGDIObj)
1020 {
1021   HGDIOBJ   objOrg;
1022   BITMAPOBJ *pb;
1023   PDC dc;
1024   PPENOBJ pen;
1025   PBRUSHOBJ brush;
1026   PXLATEOBJ XlateObj;
1027   PPALGDI PalGDI;
1028   WORD  objectMagic;
1029   COLORREF *ColorMap;
1030   ULONG NumColors, Index;
1031
1032   if(!hDC || !hGDIObj) return NULL;
1033
1034   dc = DC_HandleToPtr(hDC);
1035   objectMagic = GDIOBJ_GetHandleMagic (hGDIObj);
1036 //  GdiObjHdr = hGDIObj;
1037
1038   // FIXME: Get object handle from GDIObj and use it instead of GDIObj below?
1039
1040   switch(objectMagic) {
1041     case GO_PEN_MAGIC:
1042       objOrg = (HGDIOBJ)dc->w.hPen;
1043       dc->w.hPen = hGDIObj;
1044
1045       // Convert the color of the pen to the format of the DC
1046       PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
1047       if( PalGDI ){
1048         XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
1049         pen = GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
1050         if( pen ){
1051           pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
1052         }
1053         GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
1054         EngDeleteXlate(XlateObj);
1055       }
1056       break;
1057
1058     case GO_BRUSH_MAGIC:
1059       objOrg = (HGDIOBJ)dc->w.hBrush;
1060       dc->w.hBrush = (HBRUSH) hGDIObj;
1061
1062       // Convert the color of the brush to the format of the DC
1063       PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
1064       if( PalGDI ){
1065         XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
1066         brush = GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
1067         if( brush ){
1068           brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
1069         }
1070         GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC);
1071         EngDeleteXlate(XlateObj);
1072       }
1073       break;
1074
1075     case GO_FONT_MAGIC:
1076       objOrg = (HGDIOBJ)dc->w.hFont;
1077       dc->w.hFont = (HFONT) hGDIObj;
1078       TextIntRealizeFont(dc->w.hFont);
1079       break;
1080
1081     case GO_BITMAP_MAGIC:
1082       // must be memory dc to select bitmap
1083       if (!(dc->w.flags & DC_MEMORY)) return NULL;
1084       objOrg = (HGDIOBJ)dc->w.hBitmap;
1085
1086       /* Release the old bitmap, lock the new one and convert it to a SURF */
1087       EngDeleteSurface(dc->Surface);
1088       BITMAPOBJ_ReleasePtr(objOrg);
1089       dc->w.hBitmap = hGDIObj;
1090       pb = BITMAPOBJ_HandleToPtr(hGDIObj);
1091       dc->Surface = BitmapToSurf(pb);
1092
1093       // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1094       if(pb->dib)
1095       {
1096         dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1097
1098         if(pb->dib->dsBmih.biBitCount <= 8)
1099         {
1100           if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
1101           if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
1102           if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
1103
1104           ColorMap = ExAllocatePool(PagedPool, sizeof(COLORREF) * NumColors);
1105           for (Index = 0; Index < NumColors; Index++)
1106             {
1107             ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
1108                                   pb->ColorMap[Index].rgbGreen,
1109                                   pb->ColorMap[Index].rgbBlue);
1110           }
1111           dc->w.hPalette = EngCreatePalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
1112           ExFreePool(ColorMap);
1113         } else
1114         if(16 == pb->dib->dsBmih.biBitCount)
1115         {
1116           dc->w.hPalette = EngCreatePalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
1117         } else
1118         if(pb->dib->dsBmih.biBitCount >= 24)
1119         {
1120           dc->w.hPalette = EngCreatePalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
1121         }
1122       } else {
1123         dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
1124       }
1125       break;
1126
1127 #if UPDATEREGIONS
1128     case GO_REGION_MAGIC:
1129       /* objOrg = (HGDIOBJ)hDC->region; */
1130       objOrg = NULL; /* FIXME? hDC->region is destroyed below */
1131       SelectClipRgn(hDC, (HRGN)hGDIObj);
1132       break;
1133 #endif
1134     default:
1135       return NULL;
1136   }
1137   DC_ReleasePtr( hDC );
1138   return objOrg;
1139 }
1140
1141 DC_SET_MODE( W32kSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
1142 DC_SET_MODE( W32kSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
1143 // DC_SET_MODE( W32kSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1144 DC_SET_MODE( W32kSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
1145 DC_SET_MODE( W32kSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
1146
1147 COLORREF STDCALL W32kSetBkColor(HDC hDC, COLORREF color)
1148 {
1149   COLORREF  oldColor;
1150   PDC  dc = DC_HandleToPtr(hDC);
1151
1152   if (!dc)
1153   {
1154     return 0x80000000;
1155   }
1156
1157   oldColor = dc->w.backgroundColor;
1158   dc->w.backgroundColor = color;
1159   DC_ReleasePtr( hDC );
1160   return  oldColor;
1161 }
1162
1163 static void  W32kSetDCState16(HDC  hDC, HDC  hDCSave)
1164 {
1165   PDC  dc, dcs;
1166
1167   dc = DC_HandleToPtr(hDC);
1168   if (dc == NULL)
1169   {
1170     return;
1171   }
1172
1173   dcs = DC_HandleToPtr(hDCSave);
1174   if (dcs == NULL)
1175   {
1176         DC_ReleasePtr( hDC );
1177     return;
1178   }
1179   if (!dcs->w.flags & DC_SAVED)
1180   {
1181     return;
1182   }
1183
1184   dc->w.flags            = dcs->w.flags & ~DC_SAVED;
1185
1186 #if 0
1187   dc->w.devCaps          = dcs->w.devCaps;
1188 #endif
1189
1190   dc->w.hFirstBitmap     = dcs->w.hFirstBitmap;
1191
1192 #if 0
1193   dc->w.hDevice          = dcs->w.hDevice;
1194 #endif
1195
1196   dc->w.totalExtent      = dcs->w.totalExtent;
1197   dc->w.ROPmode          = dcs->w.ROPmode;
1198   dc->w.polyFillMode     = dcs->w.polyFillMode;
1199   dc->w.stretchBltMode   = dcs->w.stretchBltMode;
1200   dc->w.relAbsMode       = dcs->w.relAbsMode;
1201   dc->w.backgroundMode   = dcs->w.backgroundMode;
1202   dc->w.backgroundColor  = dcs->w.backgroundColor;
1203   dc->w.textColor        = dcs->w.textColor;
1204   dc->w.brushOrgX        = dcs->w.brushOrgX;
1205   dc->w.brushOrgY        = dcs->w.brushOrgY;
1206   dc->w.textAlign        = dcs->w.textAlign;
1207   dc->w.charExtra        = dcs->w.charExtra;
1208   dc->w.breakTotalExtra  = dcs->w.breakTotalExtra;
1209   dc->w.breakCount       = dcs->w.breakCount;
1210   dc->w.breakExtra       = dcs->w.breakExtra;
1211   dc->w.breakRem         = dcs->w.breakRem;
1212   dc->w.MapMode          = dcs->w.MapMode;
1213   dc->w.GraphicsMode     = dcs->w.GraphicsMode;
1214 #if 0
1215   /* Apparently, the DC origin is not changed by [GS]etDCState */
1216   dc->w.DCOrgX           = dcs->w.DCOrgX;
1217   dc->w.DCOrgY           = dcs->w.DCOrgY;
1218 #endif
1219   dc->w.CursPosX         = dcs->w.CursPosX;
1220   dc->w.CursPosY         = dcs->w.CursPosY;
1221   dc->w.ArcDirection     = dcs->w.ArcDirection;
1222
1223 #if 0
1224   dc->w.xformWorld2Wnd   = dcs->w.xformWorld2Wnd;
1225   dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
1226   dc->w.xformVport2World = dcs->w.xformVport2World;
1227   dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
1228 #endif
1229
1230   dc->wndOrgX            = dcs->wndOrgX;
1231   dc->wndOrgY            = dcs->wndOrgY;
1232   dc->wndExtX            = dcs->wndExtX;
1233   dc->wndExtY            = dcs->wndExtY;
1234   dc->vportOrgX          = dcs->vportOrgX;
1235   dc->vportOrgY          = dcs->vportOrgY;
1236   dc->vportExtX          = dcs->vportExtX;
1237   dc->vportExtY          = dcs->vportExtY;
1238
1239   if (!(dc->w.flags & DC_MEMORY))
1240   {
1241     dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
1242   }
1243
1244 #if 0
1245   if (dcs->w.hClipRgn)
1246   {
1247     if (!dc->w.hClipRgn)
1248     {
1249       dc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
1250     }
1251     W32kCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
1252   }
1253   else
1254   {
1255     if (dc->w.hClipRgn)
1256     {
1257       W32kDeleteObject( dc->w.hClipRgn );
1258     }
1259
1260     dc->w.hClipRgn = 0;
1261   }
1262   CLIPPING_UpdateGCRegion( dc );
1263 #endif
1264
1265   W32kSelectObject( hDC, dcs->w.hBitmap );
1266   W32kSelectObject( hDC, dcs->w.hBrush );
1267   W32kSelectObject( hDC, dcs->w.hFont );
1268   W32kSelectObject( hDC, dcs->w.hPen );
1269   W32kSetBkColor( hDC, dcs->w.backgroundColor);
1270   W32kSetTextColor( hDC, dcs->w.textColor);
1271
1272 #if 0
1273   GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
1274 #endif
1275
1276   DC_ReleasePtr( hDCSave );
1277   DC_ReleasePtr( hDC );
1278 }
1279
1280 //  ----------------------------------------------------  Private Interface
1281
1282 HDC  DC_AllocDC(LPCWSTR  Driver)
1283 {
1284         PDC  NewDC;
1285         HDC  hDC;
1286
1287         hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GO_DC_MAGIC);
1288         if (hDC == NULL)
1289         {
1290           return  NULL;
1291         }
1292
1293         NewDC = (PDC) GDIOBJ_LockObj( hDC, GO_DC_MAGIC );
1294
1295         if (Driver != NULL)
1296         {
1297           NewDC->DriverName = ExAllocatePool(PagedPool, (wcslen(Driver) + 1) * sizeof(WCHAR));
1298           wcscpy(NewDC->DriverName, Driver);
1299         }
1300
1301         NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
1302         NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
1303         NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
1304         NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
1305         NewDC->w.xformWorld2Wnd.eDx = 0.0f;
1306         NewDC->w.xformWorld2Wnd.eDy = 0.0f;
1307         NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
1308         NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
1309         NewDC->w.vport2WorldValid = TRUE;
1310
1311         NewDC->w.hFont = W32kGetStockObject(SYSTEM_FONT);
1312
1313         GDIOBJ_UnlockObj( hDC, GO_DC_MAGIC );
1314         return  hDC;
1315 }
1316
1317 HDC  DC_FindOpenDC(LPCWSTR  Driver)
1318 {
1319   return NULL;
1320 }
1321
1322 /*!
1323  * Initialize some common fields in the Device Context structure.
1324 */
1325 void  DC_InitDC(HDC  DCHandle)
1326 {
1327 //  W32kRealizeDefaultPalette(DCHandle);
1328
1329   W32kSelectObject(DCHandle, W32kGetStockObject( WHITE_BRUSH ));
1330   W32kSelectObject(DCHandle, W32kGetStockObject( BLACK_PEN ));
1331   //W32kSelectObject(DCHandle, hFont);
1332
1333 //  CLIPPING_UpdateGCRegion(DCToInit);
1334
1335 }
1336
1337 void  DC_FreeDC(HDC  DCToFree)
1338 {
1339   if (!GDIOBJ_FreeObj(DCToFree, GO_DC_MAGIC, GDIOBJFLAG_DEFAULT))
1340   {
1341     DPRINT("DC_FreeDC failed\n");
1342   }
1343 }
1344
1345 BOOL DC_InternalDeleteDC( PDC DCToDelete )
1346 {
1347         if( DCToDelete->DriverName )
1348                 ExFreePool(DCToDelete->DriverName);
1349         return TRUE;
1350 }
1351
1352 HDC  DC_GetNextDC (PDC pDC)
1353 {
1354   return pDC->hNext;
1355 }
1356
1357 void  DC_SetNextDC (PDC pDC, HDC hNextDC)
1358 {
1359   pDC->hNext = hNextDC;
1360 }
1361
1362 void
1363 DC_UpdateXforms(PDC  dc)
1364 {
1365   XFORM  xformWnd2Vport;
1366   FLOAT  scaleX, scaleY;
1367
1368   /* Construct a transformation to do the window-to-viewport conversion */
1369   scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
1370   scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
1371   xformWnd2Vport.eM11 = scaleX;
1372   xformWnd2Vport.eM12 = 0.0;
1373   xformWnd2Vport.eM21 = 0.0;
1374   xformWnd2Vport.eM22 = scaleY;
1375   xformWnd2Vport.eDx  = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
1376   xformWnd2Vport.eDy  = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
1377
1378   /* Combine with the world transformation */
1379   W32kCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
1380
1381   /* Create inverse of world-to-viewport transformation */
1382   dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
1383 }
1384
1385 BOOL
1386 DC_InvertXform(const XFORM *xformSrc,
1387                XFORM *xformDest)
1388 {
1389   FLOAT  determinant;
1390
1391   determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
1392   if (determinant > -1e-12 && determinant < 1e-12)
1393   {
1394     return  FALSE;
1395   }
1396
1397   xformDest->eM11 =  xformSrc->eM22 / determinant;
1398   xformDest->eM12 = -xformSrc->eM12 / determinant;
1399   xformDest->eM21 = -xformSrc->eM21 / determinant;
1400   xformDest->eM22 =  xformSrc->eM11 / determinant;
1401   xformDest->eDx  = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
1402   xformDest->eDy  = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
1403
1404   return  TRUE;
1405 }