source: trunk/src/user32/dc.cpp@ 1073

Last change on this file since 1073 was 1073, checked in by dengert, 26 years ago

minor dc changes

File size: 32.2 KB
Line 
1/* $Id: dc.cpp,v 1.8 1999-09-27 18:21:25 dengert Exp $ */
2
3/*
4 * DC functions for USER32
5 *
6 * Project Odin Software License can be found in LICENSE.TXT
7 *
8 */
9
10#define INCL_WIN
11#define INCL_GPI
12#define INCL_GREALL
13#define INCL_DEV
14#include <os2.h>
15#include <pmddi.h>
16#include <os2sel.h>
17#include <stdlib.h>
18#include "win32type.h"
19#include <winconst.h>
20#include <wprocess.h>
21#include <misc.h>
22#include <win32wbase.h>
23#include <math.h>
24#include <limits.h>
25#include "oslibwin.h"
26#include "dcdata.h"
27
28#undef SEVERITY_ERROR
29#include <winerror.h>
30
31#ifndef OPEN32API
32#define OPEN32API _System
33#endif
34
35/*********************/
36typedef struct
37{
38 HDC hdc;
39 BOOL fErase;
40 RECT rcPaint;
41 BOOL fRestore;
42 BOOL IncUpdate;
43 BYTE rgbReserved[32];
44} PAINTSTRUCT_W, *PPAINTSTRUCT_W, *LPPAINTSTRUCT_W;
45
46#define PS_SOLID_W 0x00000000
47#define PS_DASH_W 0x00000001
48#define PS_DOT_W 0x00000002
49#define PS_DASHDOT_W 0x00000003
50#define PS_DASHDOTDOT_W 0x00000004
51#define PS_NULL_W 0x00000005
52#define PS_INSIDEFRAME_W 0x00000006
53#define PS_USERSTYLE_W 0x00000007
54#define PS_ALTERNATE_W 0x00000008
55#define PS_STYLE_MASK_W 0x0000000f
56
57typedef struct
58{
59 UINT lopnStyle;
60 POINT lopnWidth;
61 ULONG lopnColor;
62} LOGPEN_W, *LPLOGPEN_W;
63
64typedef struct tagEXTLOGPEN
65{
66 DWORD elpPenStyle;
67 DWORD elpWidth;
68 DWORD elpBrushStyle;
69 DWORD elpColor;
70 DWORD elpNumEntries;
71 DWORD elpStyleEntry[1];
72} EXTLOGPEN_W, *PEXTLOGPEN_W, *NPEXTLOGPEN_W, *LPEXTLOGPEN_W;
73
74typedef struct
75{
76 UINT lbStyle;
77 ULONG lbColor;
78 INT lbHatch;
79} LOGBRUSH_W, *LPLOGBRUSH_W;
80
81typedef struct _penobject
82{
83 ULONG filler[9];
84 union {
85 struct {
86 PEXTLOGPEN_W pExtLogPen;
87 LOGBRUSH_W logbrush;
88 LOGPEN_W logpen;
89 } ExtPen;
90 struct {
91 LOGPEN_W logpen;
92 } Pen;
93 };
94} tPenObject, *pPenObject;
95
96/* DC Graphics Mode */
97#define GM_COMPATIBLE_W 1
98#define GM_ADVANCED_W 2
99
100#define DCX_WINDOW_W 0x00000001L
101#define DCX_CACHE_W 0x00000002L
102#define DCX_NORESETATTRS_W 0x00000004L
103#define DCX_CLIPCHILDREN_W 0x00000008L
104#define DCX_CLIPSIBLINGS_W 0x00000010L
105#define DCX_PARENTCLIP_W 0x00000020L
106#define DCX_EXCLUDERGN_W 0x00000040L
107#define DCX_INTERSECTRGN_W 0x00000080L
108#define DCX_EXCLUDEUPDATE_W 0x00000100L
109#define DCX_INTERSECTUPDATE_W 0x00000200L
110#define DCX_LOCKWINDOWUPDATE_W 0x00000400L
111#define DCX_VALIDATE_W 0x00200000L
112
113#define RDW_INVALIDATE_W 0x0001
114#define RDW_INTERNALPAINT_W 0x0002
115#define RDW_ERASE_W 0x0004
116#define RDW_VALIDATE_W 0x0008
117#define RDW_NOINTERNALPAINT_W 0x0010
118#define RDW_NOERASE_W 0x0020
119#define RDW_NOCHILDREN_W 0x0040
120#define RDW_ALLCHILDREN_W 0x0080
121#define RDW_UPDATENOW_W 0x0100
122#define RDW_ERASENOW_W 0x0200
123#define RDW_FRAME_W 0x0400
124#define RDW_NOFRAME_W 0x0800
125
126typedef struct _RGNDATAHEADER_W {
127 DWORD dwSize;
128 DWORD iType;
129 DWORD nCount;
130 DWORD nRgnSize;
131 RECT rcBound;
132} RGNDATAHEADER_W, *LPRGNDATAHEADER_W;
133
134typedef struct _RGNDATA_W {
135 RGNDATAHEADER_W rdh;
136 char Buffer[1];
137} RGNDATA_W , *PRGNDATA_W , *LPRGNDATA_W ;
138
139
140/* Xform FLAGS */
141#define MWT_IDENTITY_W 1
142#define MWT_LEFTMULTIPLY_W 2
143#define MWT_RIGHTMULTIPLY_W 3
144
145/* Mapping Modes */
146#define MM_TEXT_W 1
147#define MM_LOMETRIC_W 2
148#define MM_HIMETRIC_W 3
149#define MM_LOENGLISH_W 4
150#define MM_HIENGLISH_W 5
151#define MM_TWIPS_W 6
152#define MM_ISOTROPIC_W 7
153#define MM_ANISOTROPIC_W 8
154
155/*********************/
156
157BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight);
158LONG APIENTRY GpiQueryYInversion (HPS hps);
159PVOID APIENTRY GpiAllocateDCData (HPS GpiH, ULONG size);
160PVOID APIENTRY GpiQueryDCData (HPS hps);
161HDC OPEN32API HPSToHDC (HWND hwnd, HPS hps, HDC hdc, PVOID);
162void OPEN32API DeleteHDC (HDC hdc);
163BOOL OPEN32API _O32_EndPaint (HWND hwnd, const PAINTSTRUCT_W *lpps);
164int OPEN32API _O32_GetUpdateRgn (HWND hwnd, HRGN hrgn, BOOL erase);
165ULONG OPEN32API _O32_GetRegionData (HRGN hrgn, ULONG count, PRGNDATA_W pData);
166BOOL OPEN32API _O32_DeleteObject (LHANDLE hgdiobj);
167int OPEN32API _O32_ReleaseDC (HWND hwnd, HDC hdc);
168VOID OPEN32API _O32_SetLastError( DWORD );
169
170#ifndef DEVESC_SETPS
171 #define DEVESC_SETPS 49149L
172#endif
173
174#define FLOAT_TO_FIXED(x) ((FIXED) ((x) * 65536.0))
175#define MICRO_HPS_TO_HDC(x) ((x) & 0xFFFFFFFE)
176
177#define PMRECT_FROM_WINRECT( pmRect, winRect ) \
178{ \
179 (pmRect).xLeft = (winRect).left; \
180 (pmRect).yBottom = (winRect).bottom; \
181 (pmRect).xRight = (winRect).right; \
182 (pmRect).yTop = (winRect).top; \
183}
184
185#define WINRECT_FROM_PMRECT( winRect, pmRect ) \
186{ \
187 (winRect).left = (pmRect).xLeft; \
188 (winRect).top = (pmRect).yTop; \
189 (winRect).right = (pmRect).xRight; \
190 (winRect).bottom = (pmRect).yBottom; \
191}
192
193#define MEM_HPS_MAX 768
194
195const XFORM_W XFORMIdentity = { 1.0, 0.0, 0.0, 1.0, 0, 0 };
196const MATRIXLF matrixlfIdentity = { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0};
197
198BOOL setPageXForm(Win32BaseWindow *wnd, pDCData pHps);
199BOOL changePageXForm(Win32BaseWindow *wnd, pDCData pHps, PPOINTL pValue, int x, int y, PPOINTL pPrev);
200LONG clientHeight(Win32BaseWindow *wnd, HWND hwnd, pDCData pHps);
201
202void TestWideLine (pDCData pHps)
203{
204 const LOGPEN_W *pLogPen;
205
206 pHps->isWideLine = FALSE;
207 pLogPen = pHps->penIsExtPen ?
208 &(pHps->lastPenObject->ExtPen.logpen) :
209 &(pHps->lastPenObject->Pen.logpen);
210
211 if (((pLogPen->lopnStyle & PS_STYLE_MASK_W) != PS_NULL_W) &&
212 (pLogPen->lopnWidth.x > 0))
213 {
214 POINTL aptl[2] = { 0, 0, pLogPen->lopnWidth.x, pLogPen->lopnWidth.x };
215
216 GpiConvert(pHps->hps, CVTC_WORLD, CVTC_DEVICE, 2, aptl);
217
218 ULONG dx = abs(aptl[0].x - aptl[1].x);
219 ULONG dy = abs(aptl[0].y - aptl[1].y);
220
221 pHps->isWideLine = (dx > 1) || (dy > 1);
222 }
223}
224
225void Calculate1PixelDelta(pDCData pHps)
226{
227 POINTL aptl[2] = {0, 0, 1, 1};
228
229 GpiConvert(pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, aptl);
230 pHps->worldYDeltaFor1Pixel = (int)(aptl[1].y - aptl[0].y);
231 pHps->worldXDeltaFor1Pixel = (int)(aptl[1].x - aptl[0].x); // 171182
232}
233
234//******************************************************************************
235
236int setMapMode(Win32BaseWindow *wnd, pDCData pHps, int mode)
237{
238 int prevMode = 0;
239 ULONG flOptions;
240
241 switch (mode)
242 {
243 case MM_HIENGLISH_W : flOptions = PU_HIENGLISH; break;
244 case MM_LOENGLISH_W : flOptions = PU_LOENGLISH; break;
245 case MM_HIMETRIC_W : flOptions = PU_HIMETRIC ; break;
246 case MM_LOMETRIC_W : flOptions = PU_LOMETRIC ; break;
247 case MM_TEXT_W : flOptions = PU_PELS ; break;
248 case MM_TWIPS_W : flOptions = PU_TWIPS ; break;
249 case MM_ANISOTROPIC_W: flOptions = PU_PELS ; break;
250 case MM_ISOTROPIC_W : flOptions = PU_LOMETRIC ; break;
251 default:
252 _O32_SetLastError (ERROR_INVALID_PARAMETER);
253 return FALSE;
254 }
255
256 prevMode = pHps->MapMode; /* store previous mode */
257 pHps->MapMode = mode;
258
259 if (mode == MM_TEXT_W)
260 {
261 pHps->viewportXExt =
262 pHps->viewportYExt = 1.0;
263 pHps->windowExt.cx =
264 pHps->windowExt.cy = 1;
265 }
266 else if (mode != MM_ANISOTROPIC_W)
267 {
268 RECTL rectl;
269 SIZEL sizel;
270 ULONG data[3];
271
272 data[0] = flOptions;
273 data[1] = data[2] = 0;
274
275 if (DevEscape(pHps->hdc ? pHps->hdc : pHps->hps, DEVESC_SETPS, 12, (PBYTE)data, 0, 0) == DEVESC_ERROR)
276 {
277 _O32_SetLastError (ERROR_INVALID_PARAMETER);
278 return 0;
279 }
280
281 GpiQueryPageViewport(pHps->hps, &rectl);
282 pHps->viewportXExt = (double)rectl.xRight;
283 pHps->viewportYExt = -(double)rectl.yTop;
284
285 GreGetPageUnits(pHps->hdc? pHps->hdc : pHps->hps, &sizel);
286 pHps->windowExt.cx = sizel.cx;
287 pHps->windowExt.cy = sizel.cy;
288
289 data[0] = PU_PELS;
290 DevEscape(pHps->hdc ? pHps->hdc : pHps->hps, DEVESC_SETPS, 12, (PBYTE)data, 0, 0);
291 }
292
293 if (((prevMode != MM_ISOTROPIC_W) && (prevMode != MM_ANISOTROPIC_W)) &&
294 ((mode == MM_ISOTROPIC_W) || (mode == MM_ANISOTROPIC_W)))
295 {
296 if (pHps->lWndXExtSave && pHps->lWndYExtSave)
297 {
298 changePageXForm (wnd, pHps, (PPOINTL)&pHps->windowExt,
299 pHps->lWndXExtSave, pHps->lWndYExtSave, NULL );
300 pHps->lWndXExtSave = pHps->lWndYExtSave = 0;
301 }
302 if (pHps->lVwpXExtSave && pHps->lVwpYExtSave)
303 {
304 changePageXForm (wnd, pHps, NULL,
305 pHps->lVwpXExtSave, pHps->lVwpYExtSave, NULL );
306 pHps->lVwpXExtSave = pHps->lVwpYExtSave = 0;
307 }
308 }
309
310 setPageXForm(wnd, pHps);
311
312 return prevMode;
313}
314
315BOOL setPageXForm(Win32BaseWindow *wnd, pDCData pHps)
316{
317 MATRIXLF mlf;
318 BOOL rc = TRUE;
319
320 pHps->height = clientHeight(wnd, 0, pHps) - 1;
321
322 double xScale = pHps->viewportXExt / (double)pHps->windowExt.cx;
323 double yScale = pHps->viewportYExt / (double)pHps->windowExt.cy;
324
325 mlf.fxM11 = FLOAT_TO_FIXED(xScale);
326 mlf.fxM12 = 0;
327 mlf.lM13 = 0;
328 mlf.fxM21 = 0;
329 mlf.fxM22 = FLOAT_TO_FIXED(yScale);
330 mlf.lM23 = 0;
331 mlf.lM31 = pHps->viewportOrg.x - (LONG)(pHps->windowOrg.x * xScale);
332 mlf.lM32 = pHps->viewportOrg.y - (LONG)(pHps->windowOrg.y * yScale);
333
334 pHps->isLeftLeft = mlf.fxM11 >= 0;
335 pHps->isTopTop = mlf.fxM22 >= 0;
336
337 BOOL bEnableYInversion = FALSE;
338 if ((mlf.fxM22 > 0) ||
339 ((pHps->graphicsMode == GM_ADVANCED_W) &&
340 ((pHps->MapMode == MM_ANISOTROPIC_W) ||
341 (pHps->MapMode == MM_ISOTROPIC_W))))
342 {
343 bEnableYInversion = TRUE;
344 }
345 else
346 {
347 bEnableYInversion = FALSE;
348 mlf.lM32 = pHps->HPStoHDCInversionHeight + pHps->height - mlf.lM32;
349 mlf.fxM22 = -mlf.fxM22;
350 }
351
352 if (!pHps->isMetaPS)
353// if ((!pHps->isMetaPS) ||
354// (pHps->pMetaFileObject && pHps->pMetaFileObject->isEnhanced()))
355 rc = GpiSetDefaultViewMatrix(pHps->hps, 8, &mlf, TRANSFORM_REPLACE);
356
357 if (bEnableYInversion)
358 GpiEnableYInversion(pHps->hps, pHps->height + pHps->HPStoHDCInversionHeight);
359 else
360 GpiEnableYInversion(pHps->hps, 0);
361
362 TestWideLine(pHps);
363 Calculate1PixelDelta(pHps);
364 return rc;
365}
366
367BOOL changePageXForm(Win32BaseWindow *wnd, pDCData pHps, PPOINTL pValue, int x, int y, PPOINTL pPrev)
368{
369 BOOL result = FALSE;
370
371 if (pValue)
372 {
373 if (pPrev)
374 *pPrev = *pValue;
375
376 if ((pValue->x == x) && (pValue->y == y)) {
377 return TRUE;
378 }
379 pValue->x = x;
380 pValue->y = y;
381 }
382 else
383 {
384 if (pPrev)
385 {
386 pPrev->x = (int)pHps->viewportXExt;
387 pPrev->y = (int)pHps->viewportYExt;
388 }
389 pHps->viewportXExt = (double)x;
390 pHps->viewportYExt = (double)y;
391 }
392
393 if (pHps->MapMode == MM_ISOTROPIC_W)
394 {
395 double xExt = fabs(pHps->viewportXExt);
396 double yExt = fabs(pHps->viewportYExt);
397 double sf = fabs((double)pHps->windowExt.cx / pHps->windowExt.cy);
398
399 if (xExt > (yExt * sf))
400 {
401 xExt = yExt * sf;
402
403 if ((double)LONG_MAX <= xExt) return (result);
404
405 if (pHps->viewportXExt < 0.0)
406 pHps->viewportXExt = -xExt;
407 else
408 pHps->viewportXExt = xExt;
409 }
410 else
411 {
412 yExt = xExt / sf;
413
414 if ((double)LONG_MAX <= yExt) return (result);
415
416 if (pHps->viewportYExt < 0.0)
417 pHps->viewportYExt = -yExt;
418 else
419 pHps->viewportYExt = yExt;
420 }
421 }
422 result = setPageXForm(wnd, pHps);
423
424 return (result);
425}
426
427LONG clientHeight(Win32BaseWindow *wnd, HWND hwnd, pDCData pHps)
428{
429 if ((hwnd == 0) && (pHps != 0))
430 hwnd = pHps->hwnd;
431
432 if ((hwnd != 0) || (pHps == 0))
433 {
434 if (wnd)
435 return (wnd->getWindowHeight());
436 else
437 return OSLibQueryScreenHeight();
438 }
439 else if (pHps->bitmapHandle)
440 {
441 return pHps->bitmapHeight;
442 }
443 else if (pHps->isMetaPS)
444 {
445 return 0;
446 }
447 else if (pHps->isPrinter)
448 {
449 return pHps->printPageHeight;
450 }
451 else
452 {
453 return MEM_HPS_MAX;
454 }
455}
456
457VOID removeClientArea(pDCData pHps)
458{
459 pHps->isClient = FALSE;
460
461 if (pHps->isClientArea)
462 {
463 pHps->isClientArea = FALSE;
464 GreSetupDC(pHps->hps,
465 pHps->hrgnVis,
466 pHps->ptlOrigin.x,
467 pHps->ptlOrigin.y,
468 0,
469 SETUPDC_ORIGIN | SETUPDC_VISRGN | SETUPDC_RECALCCLIP);
470 }
471}
472
473BOOL selectClientArea(Win32BaseWindow *wnd, pDCData pHps, PRECTL prclPaint)
474{
475 RECTL rcl;
476 HRGN hrgnRect;
477 HWND hwnd;
478
479 if (!wnd) return (FALSE);
480
481 pHps->isClient = TRUE;
482 hwnd = pHps->hwnd;
483
484 rcl.xLeft = rcl.yBottom = 0;
485 rcl.xRight = wnd->getWindowWidth();
486 rcl.yTop = wnd->getWindowHeight();
487
488 WinMapWindowPoints(hwnd, HWND_DESKTOP, (PPOINTL) &rcl, 2);
489 pHps->ptlOrigin = *((PPOINTL) &rcl);
490
491 if (pHps->hrgnVis == 0)
492 pHps->hrgnVis = GreCreateRectRegion(pHps->hps, &rcl, 1);
493
494 hrgnRect = GreCreateRectRegion(pHps->hps, &rcl, 1);
495
496 if (!pHps->isClientArea)
497 GreCopyClipRegion(pHps->hps, pHps->hrgnVis, 0, COPYCRGN_VISRGN);
498
499 GreCombineRegion(pHps->hps, hrgnRect, pHps->hrgnVis, hrgnRect, CRGN_AND);
500 GreSetupDC(pHps->hps,
501 hrgnRect,
502 rcl.xLeft,
503 rcl.yBottom,
504 prclPaint,
505 SETUPDC_ORIGIN | SETUPDC_VISRGN | SETUPDC_RECALCCLIP);
506
507 pHps->isClientArea = TRUE;
508 GreDestroyRegion(pHps->hps, hrgnRect);
509
510 return (TRUE);
511}
512
513HDC sendEraseBkgnd (Win32BaseWindow *wnd)
514{
515 BOOL erased;
516 HWND hwnd;
517 HDC hdc;
518 HPS hps;
519 HRGN hrgnUpdate, hrgnOld, hrgnClip, hrgnCombined;
520 RECTL rectl = { 1, 1, 2, 2 };
521
522 hwnd = wnd->getOS2WindowHandle();
523 hps = WinGetPS(hwnd);
524
525 hrgnUpdate = GpiCreateRegion (hps, 1, &rectl);
526 WinQueryUpdateRegion (hwnd, hrgnUpdate);
527 hrgnClip = GpiQueryClipRegion (hps);
528
529 if (hrgnClip == NULLHANDLE)
530 {
531 GpiSetClipRegion (hps, hrgnUpdate, &hrgnOld);
532 }
533 else
534 {
535 hrgnCombined = GpiCreateRegion (hps, 1, &rectl);
536 GpiCombineRegion (hps, hrgnCombined, hrgnClip, hrgnUpdate, CRGN_AND);
537 GpiSetClipRegion (hps, hrgnCombined, &hrgnOld);
538 GpiDestroyRegion (hps, hrgnUpdate);
539 GpiDestroyRegion (hps, hrgnClip);
540 }
541 if (hrgnOld != NULLHANDLE)
542 GpiDestroyRegion (hps, hrgnOld);
543
544 hdc = HPSToHDC (hwnd, hps, NULL, NULL);
545
546 erased = wnd->MsgEraseBackGround (hdc);
547
548 DeleteHDC (hdc);
549 WinReleasePS (hps);
550
551 return erased;
552}
553
554void releaseOwnDC (HDC hps)
555{
556 pDCData pHps = (pDCData)GpiQueryDCData ((HPS)hps);
557
558 if (pHps) {
559 if (pHps->hrgnHDC)
560 GpiDestroyRegion (pHps->hps, pHps->hrgnHDC);
561
562 GpiSetBitmap (pHps->hps, NULL);
563 _O32_DeleteObject (pHps->nullBitmapHandle);
564 GpiDestroyPS(pHps->hps);
565
566 if (pHps->hdc)
567 DevCloseDC(pHps->hdc);
568
569// how can a memory chunk allocated by GpiAllocateDCData freed by delete?
570// delete pHps;
571 }
572}
573
574HDC WIN32API BeginPaint (HWND hWnd, PPAINTSTRUCT_W lpps)
575{
576 HWND hwnd = hWnd ? hWnd : HWND_DESKTOP;
577 pDCData pHps = NULLHANDLE;
578 RECTL rect;
579 HPS hPS_ownDC = NULLHANDLE;
580
581 dprintf (("USER32: BeginPaint(%x)", hWnd));
582
583 if ( !lpps )
584 {
585 _O32_SetLastError (ERROR_INVALID_PARAMETER);
586 return (HDC)NULLHANDLE;
587 }
588
589 USHORT sel = RestoreOS2FS();
590 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
591
592 if ((hwnd != HWND_DESKTOP) && wnd->isOwnDC())
593 {
594 hPS_ownDC = wnd->getOwnDC();
595 pHps = (pDCData)GpiQueryDCData(hPS_ownDC);
596 if (!pHps)
597 {
598 _O32_SetLastError (ERROR_INVALID_PARAMETER);
599 SetFS(sel);
600 return (HDC)NULLHANDLE;
601 }
602 }
603
604 HWND hwndClient = wnd->getOS2WindowHandle();
605 HPS hps = WinBeginPaint(hwndClient, hPS_ownDC, &rect);
606
607 if (!pHps)
608 {
609 HDC hdc = HPSToHDC (hwndClient, hps, NULL, NULL);
610 pHps = (pDCData)GpiQueryDCData(hps);
611 }
612
613 if (wnd->isFrameWindow())
614 {
615// WinSendMsg( hwnd, /* WM_DRAW */ 0x20D, (MPARAM)hps, MPVOID );
616 selectClientArea(wnd, pHps, &rect);
617 }
618
619 if (hPS_ownDC == 0)
620 setMapMode (wnd, pHps, MM_TEXT_W);
621 else
622 setPageXForm (wnd, pHps);
623
624 pHps->hdcType = TYPE_3;
625 lpps->hdc = (HDC)hps;
626
627 if (wnd->isEraseBkgnd())
628 wnd->setEraseBkgnd (FALSE, !wnd->MsgEraseBackGround(lpps->hdc));
629 wnd->setSupressErase (FALSE);
630 lpps->fErase = wnd->isPSErase();
631
632 if (!hPS_ownDC)
633 {
634 long height = wnd->getWindowHeight();
635 rect.yTop = height - rect.yTop;
636 rect.yBottom = height - rect.yBottom;
637 }
638 else
639 {
640 rect.yTop--;
641 rect.yBottom--;
642 GpiConvert(pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)&rect);
643 }
644
645 WINRECT_FROM_PMRECT(lpps->rcPaint, rect);
646
647 SetFS(sel);
648 _O32_SetLastError(0);
649 return (HDC)pHps->hps;
650}
651
652BOOL WIN32API EndPaint (HWND hwnd, const PAINTSTRUCT_W *pPaint)
653{
654dprintf (("USER32: EndPaint(%x)", hwnd));
655
656 if (!pPaint || !pPaint->hdc )
657 return TRUE;
658
659 USHORT sel = RestoreOS2FS();
660 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
661
662 if (!wnd) goto exit;
663
664 if (wnd->isOwnDC())
665 {
666 pDCData pHps = (pDCData)GpiQueryDCData((HPS)pPaint->hdc);
667 if (pHps && (pHps->hdcType == TYPE_3))
668 {
669 removeClientArea (pHps);
670 WinEndPaint (pHps->hps);
671 }
672 }
673 else
674 {
675 _O32_EndPaint (HWND_DESKTOP, pPaint);
676 }
677
678exit:
679 SetFS(sel);
680 _O32_SetLastError(0);
681 return TRUE;
682}
683
684BOOL WIN32API GetUpdateRect (HWND hwnd, LPRECT pRect, BOOL erase)
685{
686 if (hwnd)
687 {
688 _O32_SetLastError (ERROR_INVALID_HANDLE);
689 return FALSE;
690 }
691
692 RECTL rectl;
693 USHORT sel = RestoreOS2FS();
694 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
695
696 BOOL updateRegionExists = WinQueryUpdateRect (hwnd, pRect ? &rectl : NULL);
697 if (!pRect) {
698 SetFS(sel);
699 return (updateRegionExists);
700 }
701
702 if (updateRegionExists)
703 {
704 if (wnd->isOwnDC())
705 {
706 pDCData pHps = NULL;
707 pHps = (pDCData)GpiQueryDCData(wnd->getOwnDC());
708 if (!pHps)
709 {
710 _O32_SetLastError (ERROR_INVALID_HANDLE);
711 SetFS(sel);
712 return FALSE;
713 }
714 GpiConvert (pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)&rectl);
715 }
716 else
717 {
718 long height = wnd->getWindowHeight();
719 rectl.yTop = height - rectl.yTop;
720 rectl.yBottom = height - rectl.yBottom;
721 }
722
723 if (pRect)
724 WINRECT_FROM_PMRECT (*pRect, rectl);
725
726 if (erase)
727 sendEraseBkgnd (wnd);
728 }
729 else
730 {
731 if (pRect)
732 pRect->left = pRect->top = pRect->right = pRect->bottom = 0;
733 }
734
735 SetFS(sel);
736 return updateRegionExists;
737}
738
739int WIN32API GetUpdateRgn (HWND hwnd, HRGN hrgn, BOOL erase)
740{
741 USHORT sel = RestoreOS2FS();
742 LONG Complexity;
743
744 Complexity = _O32_GetUpdateRgn (hwnd, hrgn, FALSE);
745 if (erase && (Complexity > NULLREGION_W)) {
746 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
747 sendEraseBkgnd (wnd);
748 }
749
750 SetFS(sel);
751 return Complexity;
752}
753
754// This implementation of GetDCEx supports
755// DCX_WINDOW
756// DCX_CACHE
757// DCX_EXCLUDERGN (complex regions allowed)
758// DCX_INTERSECTRGN (complex regions allowed)
759
760HDC WIN32API GetDCEx (HWND hwnd, HRGN hrgn, ULONG flags)
761{
762 USHORT sel = RestoreOS2FS();
763 Win32BaseWindow *wnd = NULL;
764 HWND hWindow;
765 BOOL success;
766 pDCData pHps = NULL;
767 HPS hps = NULLHANDLE;
768 BOOL drawingAllowed = TRUE;
769 BOOL isWindowOwnDC;
770 BOOL creatingOwnDC = FALSE;
771 PS_Type psType;
772
773 if (hwnd)
774 {
775 wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
776 if (flags & DCX_WINDOW_W)
777 hWindow = wnd->getOS2FrameWindowHandle();
778 else
779 hWindow = wnd->getOS2WindowHandle();
780 }
781 else
782 hWindow = HWND_DESKTOP;
783
784dprintf (("User32: GetDCEx hwnd %x (%x %x) -> wnd %x", hwnd, hrgn, flags, wnd));
785
786 isWindowOwnDC = (((hWindow == HWND_DESKTOP) ? FALSE : wnd->isOwnDC())
787 && !(flags & DCX_CACHE_W));
788 if (isWindowOwnDC)
789 {
790 hps = wnd->getOwnDC();
791 if (hps)
792 {
793 pDCData pHps = (pDCData)GpiQueryDCData (hps);
794 if (!pHps)
795 goto error;
796
797 if (flags & DCX_WINDOW_W)
798 removeClientArea (pHps);
799 else
800 selectClientArea (wnd, pHps, 0);
801
802 setPageXForm (wnd, pHps);
803
804 pHps->hdcType = TYPE_1;
805 SetFS(sel);
806 return (HDC)hps;
807 }
808 else
809 creatingOwnDC = TRUE;
810 }
811
812 if (isWindowOwnDC)
813 {
814 SIZEL sizel = {0,0};
815 hps = GpiCreatePS (WinQueryAnchorBlock (hWindow),
816 WinOpenWindowDC (hWindow),
817 &sizel, PU_PELS | GPIT_MICRO | GPIA_ASSOC );
818 psType = MICRO;
819 }
820 else
821 {
822 if (hWindow == HWND_DESKTOP)
823 hps = WinGetScreenPS (hWindow);
824 else
825 hps = WinGetPS (hWindow);
826
827 psType = MICRO_CACHED;
828 }
829
830 if (!hps)
831 goto error;
832
833 HPSToHDC (hWindow, hps, NULL, NULL);
834 pHps = (pDCData)GpiQueryDCData (hps);
835
836 if (!(flags & DCX_WINDOW_W)) {
837 if (selectClientArea (wnd, pHps, 0))
838 setMapMode (wnd, pHps, MM_TEXT_W);
839 }
840
841 if ((flags & DCX_EXCLUDERGN_W) || (flags & DCX_INTERSECTRGN_W))
842 {
843 ULONG BytesNeeded;
844 PRGNDATA_W RgnData;
845 PRECTL pr;
846 int i;
847 LONG height = OSLibQueryScreenHeight();
848
849 if (!hrgn)
850 goto error;
851
852 BytesNeeded = _O32_GetRegionData (hrgn, 0, NULL);
853 RgnData = (PRGNDATA_W)_alloca (BytesNeeded);
854 if (RgnData == NULL)
855 goto error;
856 _O32_GetRegionData (hrgn, BytesNeeded, RgnData);
857
858 i = RgnData->rdh.nCount;
859 pr = (PRECTL)(RgnData->Buffer);
860
861 success = TRUE;
862 if (flags & DCX_EXCLUDERGN_W)
863 for (; (i > 0) && success; i--, pr++) {
864 LONG y = pr->yBottom;
865
866 pr->yBottom = height - pr->yTop;
867 pr->yTop = height - y;
868 success &= GpiExcludeClipRectangle (pHps->hps, pr);
869 }
870 else
871 for (; (i > 0) && success; i--, pr++) {
872 LONG y = pr->yBottom;
873
874 pr->yBottom = height - pr->yTop;
875 pr->yTop = height - y;
876 success &= GpiIntersectClipRectangle (pHps->hps, pr);
877 }
878 if (!success)
879 goto error;
880 }
881
882 if (creatingOwnDC)
883 wnd->setOwnDC ((HDC)hps);
884
885 pHps->psType = psType;
886 pHps->hdcType = TYPE_1;
887 GpiSetDrawControl (hps, DCTL_DISPLAY, drawingAllowed ? DCTL_ON : DCTL_OFF);
888
889 SetFS(sel);
890 return (HDC)pHps->hps;
891
892error:
893 /* Something went wrong; clean up
894 */
895 if (pHps)
896 {
897 if (pHps->hps)
898 {
899 if(pHps->psType == MICRO_CACHED)
900 WinReleasePS(pHps->hps);
901 else
902 GpiDestroyPS(pHps->hps);
903 }
904
905 if (pHps->hdc) DevCloseDC(pHps->hdc);
906 if (pHps->hrgnHDC) GpiDestroyRegion(pHps->hps, pHps->hrgnHDC);
907
908 _O32_DeleteObject (pHps->nullBitmapHandle);
909 }
910 _O32_SetLastError (ERROR_INVALID_PARAMETER);
911 SetFS(sel);
912 return NULL;
913}
914
915HDC WIN32API GetDC (HWND hwnd)
916{
917 return GetDCEx (hwnd, NULL, 0);
918}
919
920HDC WIN32API GetWindowDC (HWND hwnd)
921{
922 return GetDCEx (hwnd, NULL, DCX_WINDOW_W);
923}
924
925int WIN32API ReleaseDC (HWND hwnd, HDC hdc)
926{
927 USHORT sel = RestoreOS2FS();
928 BOOL isOwnDC = FALSE;
929 int rc;
930
931 if (hwnd)
932 {
933 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
934 isOwnDC = wnd->isOwnDC();
935 }
936 if (isOwnDC)
937 rc = TRUE;
938 else
939 rc = _O32_ReleaseDC (0, hdc);
940
941 SetFS(sel);
942 dprintf(("ReleaseDC %x %x", hwnd, hdc));
943 return (rc);
944}
945
946BOOL WIN32API UpdateWindow (HWND hwnd)
947{
948 if (!hwnd)
949 return FALSE;
950
951 USHORT sel = RestoreOS2FS();
952 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
953
954dprintf (("User32: UpdateWindow hwnd %x -> wnd %x", hwnd, wnd));
955
956 if (WinQueryUpdateRect (wnd->getOS2WindowHandle(), NULL))
957 sendEraseBkgnd (wnd);
958
959 wnd->MsgPaint(0);
960
961 SetFS(sel);
962 return (TRUE);
963}
964
965// This implementation of RedrawWindow supports
966// RDW_ERASE
967// RDW_NOERASE
968// RDW_INTERNALPAINT
969// RDW_NOINTERNALPAINT
970// RDW_INVALIDATE
971// RDW_VALIDATE
972// RDW_ERASENOW
973// RDW_UPDATENOW
974
975BOOL WIN32API RedrawWindow (HWND hwnd, const RECT *pRect, HRGN hrgn, DWORD redraw)
976{
977 Win32BaseWindow *wnd;
978
979 if (redraw & (RDW_FRAME_W | RDW_NOFRAME_W))
980 {
981 _O32_SetLastError (ERROR_NOT_SUPPORTED);
982 return FALSE;
983 }
984
985 USHORT sel = RestoreOS2FS();
986 dprintf(("USER32: RedrawWindow %X, %X %X %X", hwnd, pRect, hrgn, redraw));
987
988 if (hwnd == NULLHANDLE) {
989 hwnd = HWND_DESKTOP;
990 wnd = Win32BaseWindow::GetWindowFromOS2Handle(OSLIB_HWND_DESKTOP);
991 }
992 else
993 {
994 wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
995
996 if (!wnd)
997 {
998 _O32_SetLastError (ERROR_INVALID_PARAMETER);
999 SetFS(sel);
1000 return FALSE;
1001 }
1002 hwnd = wnd->getOS2WindowHandle();
1003 }
1004
1005 BOOL IncludeChildren = redraw & RDW_ALLCHILDREN_W ? TRUE : FALSE;
1006 BOOL success = TRUE;
1007 HPS hpsTemp = NULLHANDLE;
1008 HRGN hrgnTemp = NULLHANDLE;
1009 RECTL rectl;
1010
1011 if (redraw & RDW_UPDATENOW_W) redraw &= ~RDW_ERASENOW_W;
1012
1013 if (redraw & RDW_NOERASE_W)
1014 wnd->setEraseBkgnd (FALSE);
1015
1016 if (redraw & RDW_UPDATENOW_W)
1017 wnd->setSupressErase (FALSE);
1018 else if (redraw & RDW_ERASENOW_W)
1019 wnd->setSupressErase (FALSE);
1020#if 0
1021 else
1022 {
1023 QMSG qmsg;
1024 BOOL erase;
1025
1026 erase = (WinPeekMsg (HABX, &qmsg, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE)
1027 && (redraw & RDW_NOERASE_W) == 0);
1028
1029 wnd->setSupressErase (!erase);
1030 }
1031
1032 if (redraw & (RDW_NOINTERNALPAINT_W | RDW_INTERNALPAINT_W))
1033 {
1034 QMSG qmsg;
1035
1036 WinPeekMsg( (HAB)0, &qmsg, hwnd, WM_VIRTUAL_INTERNALPAINT,
1037 WM_VIRTUAL_INTERNALPAINT, PM_REMOVE );
1038 }
1039#endif
1040
1041 if (hrgn)
1042 {
1043 ULONG BytesNeeded;
1044 PRGNDATA_W RgnData;
1045 PRECTL pr;
1046 int i;
1047 LONG height = wnd ? wnd->getWindowHeight() : OSLibQueryScreenHeight();
1048
1049 if (!hrgn)
1050 goto error;
1051
1052 BytesNeeded = _O32_GetRegionData (hrgn, 0, NULL);
1053 RgnData = (PRGNDATA_W)_alloca (BytesNeeded);
1054 if (RgnData == NULL)
1055 goto error;
1056 _O32_GetRegionData (hrgn, BytesNeeded, RgnData);
1057
1058 pr = (PRECTL)(RgnData->Buffer);
1059 for (i = RgnData->rdh.nCount; i > 0; i--, pr++) {
1060 LONG temp = pr->yTop;
1061 pr->yTop = height - pr->yBottom;
1062 pr->yBottom = height - temp;
1063 }
1064
1065 hpsTemp = WinGetScreenPS (HWND_DESKTOP);
1066 hrgnTemp = GpiCreateRegion (hpsTemp, RgnData->rdh.nCount, (PRECTL)(RgnData->Buffer));
1067 if (!hrgnTemp) goto error;
1068 }
1069 else if (pRect)
1070 {
1071 LONG height = wnd ? wnd->getWindowHeight() : OSLibQueryScreenHeight();
1072
1073 PMRECT_FROM_WINRECT (rectl, *pRect);
1074 rectl.yTop = height - rectl.yTop;
1075 rectl.yBottom = height - rectl.yBottom;
1076 }
1077
1078 if (redraw & RDW_INVALIDATE_W)
1079 {
1080 if (redraw & RDW_ERASE_W)
1081 wnd->setEraseBkgnd (TRUE, TRUE);
1082
1083 if (!pRect && !hrgn)
1084 success = WinInvalidateRect (hwnd, NULL, IncludeChildren);
1085 else if (hrgn)
1086 success = WinInvalidateRegion (hwnd, hrgnTemp, IncludeChildren);
1087 else
1088 success = WinInvalidateRect (hwnd, &rectl, IncludeChildren);
1089 if (!success) goto error;
1090 }
1091 else if (redraw & RDW_VALIDATE_W)
1092 {
1093 if (WinQueryUpdateRect (hwnd, NULL))
1094 {
1095 if (!pRect && !hrgn)
1096 success = WinValidateRect (hwnd, NULL, IncludeChildren);
1097 else if (hrgn)
1098 success = WinValidateRegion (hwnd, hrgnTemp, IncludeChildren);
1099 else
1100 success = WinValidateRect (hwnd, &rectl, IncludeChildren);
1101 if (!success) goto error;
1102 }
1103 }
1104
1105 if (WinQueryUpdateRect (hwnd, NULL))
1106 {
1107 if (redraw & RDW_UPDATENOW_W)
1108 wnd->MsgPaint (0, FALSE);
1109
1110 else if ((redraw & RDW_ERASE_W) && (redraw & RDW_ERASENOW_W))
1111 wnd->setEraseBkgnd (FALSE, !sendEraseBkgnd (wnd));
1112 }
1113 else if ((redraw & RDW_INTERNALPAINT_W) && !(redraw & RDW_INVALIDATE_W))
1114 {
1115 if (redraw & RDW_UPDATENOW_W)
1116 wnd->MsgPaint (0, FALSE);
1117// else
1118// WinPostMsg( hwnd, WM_VIRTUAL_INTERNALPAINT, MPVOID, MPVOID );
1119 }
1120
1121error:
1122 /* clean up */
1123 if (hrgnTemp)
1124 GpiDestroyRegion (hpsTemp, hrgnTemp);
1125
1126 if (hpsTemp)
1127 WinReleasePS (hpsTemp);
1128
1129 if ((redraw & RDW_INVALIDATE_W) == 0)
1130 wnd->setSupressErase (FALSE);
1131 else if ((redraw & RDW_ERASENOW_W) == RDW_ERASENOW_W)
1132 wnd->setSupressErase (TRUE);
1133
1134 if (!success)
1135 _O32_SetLastError (ERROR_INVALID_PARAMETER);
1136
1137 SetFS(sel);
1138 return (success);
1139}
1140
1141BOOL WIN32API InvalidateRect (HWND hwnd, const RECT *pRect, BOOL erase)
1142{
1143 USHORT sel = RestoreOS2FS();
1144// Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1145 BOOL result;
1146
1147// todo !!
1148// if ( isFrame without client )
1149// erase = TRUE;
1150
1151 result = RedrawWindow (hwnd, pRect, NULLHANDLE,
1152 RDW_ALLCHILDREN_W | RDW_INVALIDATE_W |
1153 (erase ? RDW_ERASE_W : 0) |
1154 (hwnd == NULLHANDLE ? RDW_UPDATENOW_W : 0));
1155 SetFS(sel);
1156 return (result);
1157}
1158
1159BOOL WIN32API InvalidateRgn (HWND hwnd, HRGN hrgn, BOOL erase)
1160{
1161 USHORT sel = RestoreOS2FS();
1162// Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1163 BOOL result;
1164
1165// todo !!
1166// if ( isFrame without client )
1167// erase = TRUE;
1168
1169 result = RedrawWindow (hwnd, NULL, hrgn,
1170 RDW_ALLCHILDREN_W | RDW_INVALIDATE_W |
1171 (erase ? RDW_ERASE_W : 0) |
1172 (hwnd == NULLHANDLE ? RDW_UPDATENOW_W : 0));
1173 SetFS(sel);
1174 return (result);
1175}
1176//******************************************************************************
1177//******************************************************************************
1178BOOL WIN32API ScrollWindow(HWND hwnd, int dx, int dy, const RECT *pScroll, const RECT *pClip)
1179{
1180 Win32BaseWindow *window;
1181 APIRET rc;
1182 RECTL clientRect;
1183 RECTL scrollRect;
1184 RECTL clipRect;
1185 PRECTL pScrollRect = NULL;
1186 PRECTL pClipRect = NULL;
1187 ULONG scrollFlags = SW_INVALIDATERGN;
1188
1189 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
1190 if(!window) {
1191 dprintf(("ScrollWindow, window %x not found", hwnd));
1192 return 0;
1193 }
1194 dprintf(("ScrollWindow %x %d %d\n", hwnd, dx, dy));
1195 MapWin32ToOS2Rectl(window->getClientRect(), (PRECTLOS2)&clientRect);
1196 //Rectangle could be relative to parent window, so fix this
1197 if(clientRect.yBottom != 0) {
1198 clientRect.yTop -= clientRect.yBottom;
1199 clientRect.yBottom = 0;
1200 }
1201 if(clientRect.xLeft != 0) {
1202 clientRect.xRight -= clientRect.xLeft;
1203 clientRect.xLeft = 0;
1204 }
1205 if(pScroll) {
1206 MapWin32ToOS2Rectl((RECT *)pScroll, (PRECTLOS2)&scrollRect);
1207 pScrollRect = &scrollRect;
1208
1209 //Scroll rectangle relative to client area
1210 pScrollRect->xLeft += clientRect.xLeft;
1211 pScrollRect->xRight += clientRect.xLeft;
1212 pScrollRect->yTop += clientRect.yBottom;
1213 pScrollRect->yBottom += clientRect.yBottom;
1214 WinIntersectRect ((HAB) 0, pScrollRect, pScrollRect, &clientRect);
1215 }
1216 else scrollFlags |= SW_SCROLLCHILDREN;
1217
1218 if(pClip) {
1219 MapWin32ToOS2Rectl((RECT *)pClip, (PRECTLOS2)&clipRect);
1220 pClipRect = &clipRect;
1221
1222 //Clip rectangle relative to client area
1223 pClipRect->xLeft += clientRect.xLeft;
1224 pClipRect->xRight += clientRect.xLeft;
1225 pClipRect->yTop += clientRect.yBottom;
1226 pClipRect->yBottom += clientRect.yBottom;
1227 WinIntersectRect ((HAB) 0, pClipRect, pClipRect, &clientRect);
1228 }
1229
1230 dy = -dy; //always correct?
1231
1232 rc = WinScrollWindow(window->getOS2WindowHandle(), dx, dy,
1233 pScrollRect, pClipRect, NULLHANDLE,
1234 NULL, scrollFlags);
1235
1236 return (rc != RGN_ERROR);
1237}
1238//******************************************************************************
1239//TODO: Implement this one
1240//******************************************************************************
1241INT WIN32API ScrollWindowEx(HWND hwnd, int dx, int dy, const RECT *pScroll, const RECT *pClip,
1242 HRGN hrgnUpdate, PRECT pRectUpdate, UINT scrollFlag)
1243{
1244 dprintf(("USER32: ScrollWindowEx NOT CORRECTLY IMPLEMENTED\n"));
1245 return ScrollWindow(hwnd, dx, dy, pScroll, pClip);
1246}
1247//******************************************************************************
1248//******************************************************************************
Note: See TracBrowser for help on using the repository browser.