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

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

Caret functions added

File size: 32.6 KB
Line 
1/* $Id: dc.cpp,v 1.9 1999-09-28 08:00:56 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
457BOOL isYup (pDCData pHps)
458{
459 if (((pHps->windowExt.cy < 0) && (pHps->viewportYExt > 0.0)) ||
460 ((pHps->windowExt.cy > 0) && (pHps->viewportYExt < 0.0)))
461 {
462 if ((pHps->graphicsMode == GM_COMPATIBLE_W) ||
463 ((pHps->graphicsMode == GM_ADVANCED_W) && (pHps->xform.eM22 >= 0.0)))
464 return TRUE;
465 }
466 else
467 {
468 if ((pHps->graphicsMode == GM_ADVANCED_W) && (pHps->xform.eM22 < 0.0))
469 return TRUE;
470 }
471 return FALSE;
472}
473
474VOID removeClientArea(pDCData pHps)
475{
476 pHps->isClient = FALSE;
477
478 if (pHps->isClientArea)
479 {
480 pHps->isClientArea = FALSE;
481 GreSetupDC(pHps->hps,
482 pHps->hrgnVis,
483 pHps->ptlOrigin.x,
484 pHps->ptlOrigin.y,
485 0,
486 SETUPDC_ORIGIN | SETUPDC_VISRGN | SETUPDC_RECALCCLIP);
487 }
488}
489
490BOOL selectClientArea(Win32BaseWindow *wnd, pDCData pHps, PRECTL prclPaint)
491{
492 RECTL rcl;
493 HRGN hrgnRect;
494 HWND hwnd;
495
496 if (!wnd) return (FALSE);
497
498 pHps->isClient = TRUE;
499 hwnd = pHps->hwnd;
500
501 rcl.xLeft = rcl.yBottom = 0;
502 rcl.xRight = wnd->getWindowWidth();
503 rcl.yTop = wnd->getWindowHeight();
504
505 WinMapWindowPoints(hwnd, HWND_DESKTOP, (PPOINTL) &rcl, 2);
506 pHps->ptlOrigin = *((PPOINTL) &rcl);
507
508 if (pHps->hrgnVis == 0)
509 pHps->hrgnVis = GreCreateRectRegion(pHps->hps, &rcl, 1);
510
511 hrgnRect = GreCreateRectRegion(pHps->hps, &rcl, 1);
512
513 if (!pHps->isClientArea)
514 GreCopyClipRegion(pHps->hps, pHps->hrgnVis, 0, COPYCRGN_VISRGN);
515
516 GreCombineRegion(pHps->hps, hrgnRect, pHps->hrgnVis, hrgnRect, CRGN_AND);
517 GreSetupDC(pHps->hps,
518 hrgnRect,
519 rcl.xLeft,
520 rcl.yBottom,
521 prclPaint,
522 SETUPDC_ORIGIN | SETUPDC_VISRGN | SETUPDC_RECALCCLIP);
523
524 pHps->isClientArea = TRUE;
525 GreDestroyRegion(pHps->hps, hrgnRect);
526
527 return (TRUE);
528}
529
530HDC sendEraseBkgnd (Win32BaseWindow *wnd)
531{
532 BOOL erased;
533 HWND hwnd;
534 HDC hdc;
535 HPS hps;
536 HRGN hrgnUpdate, hrgnOld, hrgnClip, hrgnCombined;
537 RECTL rectl = { 1, 1, 2, 2 };
538
539 hwnd = wnd->getOS2WindowHandle();
540 hps = WinGetPS(hwnd);
541
542 hrgnUpdate = GpiCreateRegion (hps, 1, &rectl);
543 WinQueryUpdateRegion (hwnd, hrgnUpdate);
544 hrgnClip = GpiQueryClipRegion (hps);
545
546 if (hrgnClip == NULLHANDLE)
547 {
548 GpiSetClipRegion (hps, hrgnUpdate, &hrgnOld);
549 }
550 else
551 {
552 hrgnCombined = GpiCreateRegion (hps, 1, &rectl);
553 GpiCombineRegion (hps, hrgnCombined, hrgnClip, hrgnUpdate, CRGN_AND);
554 GpiSetClipRegion (hps, hrgnCombined, &hrgnOld);
555 GpiDestroyRegion (hps, hrgnUpdate);
556 GpiDestroyRegion (hps, hrgnClip);
557 }
558 if (hrgnOld != NULLHANDLE)
559 GpiDestroyRegion (hps, hrgnOld);
560
561 hdc = HPSToHDC (hwnd, hps, NULL, NULL);
562
563 erased = wnd->MsgEraseBackGround (hdc);
564
565 DeleteHDC (hdc);
566 WinReleasePS (hps);
567
568 return erased;
569}
570
571void releaseOwnDC (HDC hps)
572{
573 pDCData pHps = (pDCData)GpiQueryDCData ((HPS)hps);
574
575 if (pHps) {
576 if (pHps->hrgnHDC)
577 GpiDestroyRegion (pHps->hps, pHps->hrgnHDC);
578
579 GpiSetBitmap (pHps->hps, NULL);
580 _O32_DeleteObject (pHps->nullBitmapHandle);
581 GpiDestroyPS(pHps->hps);
582
583 if (pHps->hdc)
584 DevCloseDC(pHps->hdc);
585
586// how can a memory chunk allocated by GpiAllocateDCData freed by delete?
587// delete pHps;
588 }
589}
590
591HDC WIN32API BeginPaint (HWND hWnd, PPAINTSTRUCT_W lpps)
592{
593 HWND hwnd = hWnd ? hWnd : HWND_DESKTOP;
594 pDCData pHps = NULLHANDLE;
595 RECTL rect;
596 HPS hPS_ownDC = NULLHANDLE;
597
598 dprintf (("USER32: BeginPaint(%x)", hWnd));
599
600 if ( !lpps )
601 {
602 _O32_SetLastError (ERROR_INVALID_PARAMETER);
603 return (HDC)NULLHANDLE;
604 }
605
606 USHORT sel = RestoreOS2FS();
607 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
608
609 if ((hwnd != HWND_DESKTOP) && wnd->isOwnDC())
610 {
611 hPS_ownDC = wnd->getOwnDC();
612 pHps = (pDCData)GpiQueryDCData(hPS_ownDC);
613 if (!pHps)
614 {
615 _O32_SetLastError (ERROR_INVALID_PARAMETER);
616 SetFS(sel);
617 return (HDC)NULLHANDLE;
618 }
619 }
620
621 HWND hwndClient = wnd->getOS2WindowHandle();
622 HPS hps = WinBeginPaint(hwndClient, hPS_ownDC, &rect);
623
624 if (!pHps)
625 {
626 HDC hdc = HPSToHDC (hwndClient, hps, NULL, NULL);
627 pHps = (pDCData)GpiQueryDCData(hps);
628 }
629
630 if (wnd->isFrameWindow())
631 {
632// WinSendMsg( hwnd, /* WM_DRAW */ 0x20D, (MPARAM)hps, MPVOID );
633 selectClientArea(wnd, pHps, &rect);
634 }
635
636 if (hPS_ownDC == 0)
637 setMapMode (wnd, pHps, MM_TEXT_W);
638 else
639 setPageXForm (wnd, pHps);
640
641 pHps->hdcType = TYPE_3;
642 lpps->hdc = (HDC)hps;
643
644 if (wnd->isEraseBkgnd())
645 wnd->setEraseBkgnd (FALSE, !wnd->MsgEraseBackGround(lpps->hdc));
646 wnd->setSupressErase (FALSE);
647 lpps->fErase = wnd->isPSErase();
648
649 if (!hPS_ownDC)
650 {
651 long height = wnd->getWindowHeight();
652 rect.yTop = height - rect.yTop;
653 rect.yBottom = height - rect.yBottom;
654 }
655 else
656 {
657 rect.yTop--;
658 rect.yBottom--;
659 GpiConvert(pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)&rect);
660 }
661
662 WINRECT_FROM_PMRECT(lpps->rcPaint, rect);
663
664 SetFS(sel);
665 _O32_SetLastError(0);
666 return (HDC)pHps->hps;
667}
668
669BOOL WIN32API EndPaint (HWND hwnd, const PAINTSTRUCT_W *pPaint)
670{
671dprintf (("USER32: EndPaint(%x)", hwnd));
672
673 if (!pPaint || !pPaint->hdc )
674 return TRUE;
675
676 USHORT sel = RestoreOS2FS();
677 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
678
679 if (!wnd) goto exit;
680
681 if (wnd->isOwnDC())
682 {
683 pDCData pHps = (pDCData)GpiQueryDCData((HPS)pPaint->hdc);
684 if (pHps && (pHps->hdcType == TYPE_3))
685 {
686 removeClientArea (pHps);
687 WinEndPaint (pHps->hps);
688 }
689 }
690 else
691 {
692 _O32_EndPaint (HWND_DESKTOP, pPaint);
693 }
694
695exit:
696 SetFS(sel);
697 _O32_SetLastError(0);
698 return TRUE;
699}
700
701BOOL WIN32API GetUpdateRect (HWND hwnd, LPRECT pRect, BOOL erase)
702{
703 if (hwnd)
704 {
705 _O32_SetLastError (ERROR_INVALID_HANDLE);
706 return FALSE;
707 }
708
709 RECTL rectl;
710 USHORT sel = RestoreOS2FS();
711 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
712
713 BOOL updateRegionExists = WinQueryUpdateRect (hwnd, pRect ? &rectl : NULL);
714 if (!pRect) {
715 SetFS(sel);
716 return (updateRegionExists);
717 }
718
719 if (updateRegionExists)
720 {
721 if (wnd->isOwnDC())
722 {
723 pDCData pHps = NULL;
724 pHps = (pDCData)GpiQueryDCData(wnd->getOwnDC());
725 if (!pHps)
726 {
727 _O32_SetLastError (ERROR_INVALID_HANDLE);
728 SetFS(sel);
729 return FALSE;
730 }
731 GpiConvert (pHps->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)&rectl);
732 }
733 else
734 {
735 long height = wnd->getWindowHeight();
736 rectl.yTop = height - rectl.yTop;
737 rectl.yBottom = height - rectl.yBottom;
738 }
739
740 if (pRect)
741 WINRECT_FROM_PMRECT (*pRect, rectl);
742
743 if (erase)
744 sendEraseBkgnd (wnd);
745 }
746 else
747 {
748 if (pRect)
749 pRect->left = pRect->top = pRect->right = pRect->bottom = 0;
750 }
751
752 SetFS(sel);
753 return updateRegionExists;
754}
755
756int WIN32API GetUpdateRgn (HWND hwnd, HRGN hrgn, BOOL erase)
757{
758 USHORT sel = RestoreOS2FS();
759 LONG Complexity;
760
761 Complexity = _O32_GetUpdateRgn (hwnd, hrgn, FALSE);
762 if (erase && (Complexity > NULLREGION_W)) {
763 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
764 sendEraseBkgnd (wnd);
765 }
766
767 SetFS(sel);
768 return Complexity;
769}
770
771// This implementation of GetDCEx supports
772// DCX_WINDOW
773// DCX_CACHE
774// DCX_EXCLUDERGN (complex regions allowed)
775// DCX_INTERSECTRGN (complex regions allowed)
776
777HDC WIN32API GetDCEx (HWND hwnd, HRGN hrgn, ULONG flags)
778{
779 USHORT sel = RestoreOS2FS();
780 Win32BaseWindow *wnd = NULL;
781 HWND hWindow;
782 BOOL success;
783 pDCData pHps = NULL;
784 HPS hps = NULLHANDLE;
785 BOOL drawingAllowed = TRUE;
786 BOOL isWindowOwnDC;
787 BOOL creatingOwnDC = FALSE;
788 PS_Type psType;
789
790 if (hwnd)
791 {
792 wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
793 if (flags & DCX_WINDOW_W)
794 hWindow = wnd->getOS2FrameWindowHandle();
795 else
796 hWindow = wnd->getOS2WindowHandle();
797 }
798 else
799 hWindow = HWND_DESKTOP;
800
801dprintf (("User32: GetDCEx hwnd %x (%x %x) -> wnd %x", hwnd, hrgn, flags, wnd));
802
803 isWindowOwnDC = (((hWindow == HWND_DESKTOP) ? FALSE : wnd->isOwnDC())
804 && !(flags & DCX_CACHE_W));
805 if (isWindowOwnDC)
806 {
807 hps = wnd->getOwnDC();
808 if (hps)
809 {
810 pDCData pHps = (pDCData)GpiQueryDCData (hps);
811 if (!pHps)
812 goto error;
813
814 if (flags & DCX_WINDOW_W)
815 removeClientArea (pHps);
816 else
817 selectClientArea (wnd, pHps, 0);
818
819 setPageXForm (wnd, pHps);
820
821 pHps->hdcType = TYPE_1;
822 SetFS(sel);
823 return (HDC)hps;
824 }
825 else
826 creatingOwnDC = TRUE;
827 }
828
829 if (isWindowOwnDC)
830 {
831 SIZEL sizel = {0,0};
832 hps = GpiCreatePS (WinQueryAnchorBlock (hWindow),
833 WinOpenWindowDC (hWindow),
834 &sizel, PU_PELS | GPIT_MICRO | GPIA_ASSOC );
835 psType = MICRO;
836 }
837 else
838 {
839 if (hWindow == HWND_DESKTOP)
840 hps = WinGetScreenPS (hWindow);
841 else
842 hps = WinGetPS (hWindow);
843
844 psType = MICRO_CACHED;
845 }
846
847 if (!hps)
848 goto error;
849
850 HPSToHDC (hWindow, hps, NULL, NULL);
851 pHps = (pDCData)GpiQueryDCData (hps);
852
853 if (!(flags & DCX_WINDOW_W)) {
854 if (selectClientArea (wnd, pHps, 0))
855 setMapMode (wnd, pHps, MM_TEXT_W);
856 }
857
858 if ((flags & DCX_EXCLUDERGN_W) || (flags & DCX_INTERSECTRGN_W))
859 {
860 ULONG BytesNeeded;
861 PRGNDATA_W RgnData;
862 PRECTL pr;
863 int i;
864 LONG height = OSLibQueryScreenHeight();
865
866 if (!hrgn)
867 goto error;
868
869 BytesNeeded = _O32_GetRegionData (hrgn, 0, NULL);
870 RgnData = (PRGNDATA_W)_alloca (BytesNeeded);
871 if (RgnData == NULL)
872 goto error;
873 _O32_GetRegionData (hrgn, BytesNeeded, RgnData);
874
875 i = RgnData->rdh.nCount;
876 pr = (PRECTL)(RgnData->Buffer);
877
878 success = TRUE;
879 if (flags & DCX_EXCLUDERGN_W)
880 for (; (i > 0) && success; i--, pr++) {
881 LONG y = pr->yBottom;
882
883 pr->yBottom = height - pr->yTop;
884 pr->yTop = height - y;
885 success &= GpiExcludeClipRectangle (pHps->hps, pr);
886 }
887 else
888 for (; (i > 0) && success; i--, pr++) {
889 LONG y = pr->yBottom;
890
891 pr->yBottom = height - pr->yTop;
892 pr->yTop = height - y;
893 success &= GpiIntersectClipRectangle (pHps->hps, pr);
894 }
895 if (!success)
896 goto error;
897 }
898
899 if (creatingOwnDC)
900 wnd->setOwnDC ((HDC)hps);
901
902 pHps->psType = psType;
903 pHps->hdcType = TYPE_1;
904 GpiSetDrawControl (hps, DCTL_DISPLAY, drawingAllowed ? DCTL_ON : DCTL_OFF);
905
906 SetFS(sel);
907 return (HDC)pHps->hps;
908
909error:
910 /* Something went wrong; clean up
911 */
912 if (pHps)
913 {
914 if (pHps->hps)
915 {
916 if(pHps->psType == MICRO_CACHED)
917 WinReleasePS(pHps->hps);
918 else
919 GpiDestroyPS(pHps->hps);
920 }
921
922 if (pHps->hdc) DevCloseDC(pHps->hdc);
923 if (pHps->hrgnHDC) GpiDestroyRegion(pHps->hps, pHps->hrgnHDC);
924
925 _O32_DeleteObject (pHps->nullBitmapHandle);
926 }
927 _O32_SetLastError (ERROR_INVALID_PARAMETER);
928 SetFS(sel);
929 return NULL;
930}
931
932HDC WIN32API GetDC (HWND hwnd)
933{
934 return GetDCEx (hwnd, NULL, 0);
935}
936
937HDC WIN32API GetWindowDC (HWND hwnd)
938{
939 return GetDCEx (hwnd, NULL, DCX_WINDOW_W);
940}
941
942int WIN32API ReleaseDC (HWND hwnd, HDC hdc)
943{
944 USHORT sel = RestoreOS2FS();
945 BOOL isOwnDC = FALSE;
946 int rc;
947
948 if (hwnd)
949 {
950 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
951 isOwnDC = wnd->isOwnDC();
952 }
953 if (isOwnDC)
954 rc = TRUE;
955 else
956 rc = _O32_ReleaseDC (0, hdc);
957
958 SetFS(sel);
959 dprintf(("ReleaseDC %x %x", hwnd, hdc));
960 return (rc);
961}
962
963BOOL WIN32API UpdateWindow (HWND hwnd)
964{
965 if (!hwnd)
966 return FALSE;
967
968 USHORT sel = RestoreOS2FS();
969 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
970
971dprintf (("User32: UpdateWindow hwnd %x -> wnd %x", hwnd, wnd));
972
973 if (WinQueryUpdateRect (wnd->getOS2WindowHandle(), NULL))
974 sendEraseBkgnd (wnd);
975
976 wnd->MsgPaint(0);
977
978 SetFS(sel);
979 return (TRUE);
980}
981
982// This implementation of RedrawWindow supports
983// RDW_ERASE
984// RDW_NOERASE
985// RDW_INTERNALPAINT
986// RDW_NOINTERNALPAINT
987// RDW_INVALIDATE
988// RDW_VALIDATE
989// RDW_ERASENOW
990// RDW_UPDATENOW
991
992BOOL WIN32API RedrawWindow (HWND hwnd, const RECT *pRect, HRGN hrgn, DWORD redraw)
993{
994 Win32BaseWindow *wnd;
995
996 if (redraw & (RDW_FRAME_W | RDW_NOFRAME_W))
997 {
998 _O32_SetLastError (ERROR_NOT_SUPPORTED);
999 return FALSE;
1000 }
1001
1002 USHORT sel = RestoreOS2FS();
1003 dprintf(("USER32: RedrawWindow %X, %X %X %X", hwnd, pRect, hrgn, redraw));
1004
1005 if (hwnd == NULLHANDLE) {
1006 hwnd = HWND_DESKTOP;
1007 wnd = Win32BaseWindow::GetWindowFromOS2Handle(OSLIB_HWND_DESKTOP);
1008 }
1009 else
1010 {
1011 wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1012
1013 if (!wnd)
1014 {
1015 _O32_SetLastError (ERROR_INVALID_PARAMETER);
1016 SetFS(sel);
1017 return FALSE;
1018 }
1019 hwnd = wnd->getOS2WindowHandle();
1020 }
1021
1022 BOOL IncludeChildren = redraw & RDW_ALLCHILDREN_W ? TRUE : FALSE;
1023 BOOL success = TRUE;
1024 HPS hpsTemp = NULLHANDLE;
1025 HRGN hrgnTemp = NULLHANDLE;
1026 RECTL rectl;
1027
1028 if (redraw & RDW_UPDATENOW_W) redraw &= ~RDW_ERASENOW_W;
1029
1030 if (redraw & RDW_NOERASE_W)
1031 wnd->setEraseBkgnd (FALSE);
1032
1033 if (redraw & RDW_UPDATENOW_W)
1034 wnd->setSupressErase (FALSE);
1035 else if (redraw & RDW_ERASENOW_W)
1036 wnd->setSupressErase (FALSE);
1037#if 0
1038 else
1039 {
1040 QMSG qmsg;
1041 BOOL erase;
1042
1043 erase = (WinPeekMsg (HABX, &qmsg, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE)
1044 && (redraw & RDW_NOERASE_W) == 0);
1045
1046 wnd->setSupressErase (!erase);
1047 }
1048
1049 if (redraw & (RDW_NOINTERNALPAINT_W | RDW_INTERNALPAINT_W))
1050 {
1051 QMSG qmsg;
1052
1053 WinPeekMsg( (HAB)0, &qmsg, hwnd, WM_VIRTUAL_INTERNALPAINT,
1054 WM_VIRTUAL_INTERNALPAINT, PM_REMOVE );
1055 }
1056#endif
1057
1058 if (hrgn)
1059 {
1060 ULONG BytesNeeded;
1061 PRGNDATA_W RgnData;
1062 PRECTL pr;
1063 int i;
1064 LONG height = wnd ? wnd->getWindowHeight() : OSLibQueryScreenHeight();
1065
1066 if (!hrgn)
1067 goto error;
1068
1069 BytesNeeded = _O32_GetRegionData (hrgn, 0, NULL);
1070 RgnData = (PRGNDATA_W)_alloca (BytesNeeded);
1071 if (RgnData == NULL)
1072 goto error;
1073 _O32_GetRegionData (hrgn, BytesNeeded, RgnData);
1074
1075 pr = (PRECTL)(RgnData->Buffer);
1076 for (i = RgnData->rdh.nCount; i > 0; i--, pr++) {
1077 LONG temp = pr->yTop;
1078 pr->yTop = height - pr->yBottom;
1079 pr->yBottom = height - temp;
1080 }
1081
1082 hpsTemp = WinGetScreenPS (HWND_DESKTOP);
1083 hrgnTemp = GpiCreateRegion (hpsTemp, RgnData->rdh.nCount, (PRECTL)(RgnData->Buffer));
1084 if (!hrgnTemp) goto error;
1085 }
1086 else if (pRect)
1087 {
1088 LONG height = wnd ? wnd->getWindowHeight() : OSLibQueryScreenHeight();
1089
1090 PMRECT_FROM_WINRECT (rectl, *pRect);
1091 rectl.yTop = height - rectl.yTop;
1092 rectl.yBottom = height - rectl.yBottom;
1093 }
1094
1095 if (redraw & RDW_INVALIDATE_W)
1096 {
1097 if (redraw & RDW_ERASE_W)
1098 wnd->setEraseBkgnd (TRUE, TRUE);
1099
1100 if (!pRect && !hrgn)
1101 success = WinInvalidateRect (hwnd, NULL, IncludeChildren);
1102 else if (hrgn)
1103 success = WinInvalidateRegion (hwnd, hrgnTemp, IncludeChildren);
1104 else
1105 success = WinInvalidateRect (hwnd, &rectl, IncludeChildren);
1106 if (!success) goto error;
1107 }
1108 else if (redraw & RDW_VALIDATE_W)
1109 {
1110 if (WinQueryUpdateRect (hwnd, NULL))
1111 {
1112 if (!pRect && !hrgn)
1113 success = WinValidateRect (hwnd, NULL, IncludeChildren);
1114 else if (hrgn)
1115 success = WinValidateRegion (hwnd, hrgnTemp, IncludeChildren);
1116 else
1117 success = WinValidateRect (hwnd, &rectl, IncludeChildren);
1118 if (!success) goto error;
1119 }
1120 }
1121
1122 if (WinQueryUpdateRect (hwnd, NULL))
1123 {
1124 if (redraw & RDW_UPDATENOW_W)
1125 wnd->MsgPaint (0, FALSE);
1126
1127 else if ((redraw & RDW_ERASE_W) && (redraw & RDW_ERASENOW_W))
1128 wnd->setEraseBkgnd (FALSE, !sendEraseBkgnd (wnd));
1129 }
1130 else if ((redraw & RDW_INTERNALPAINT_W) && !(redraw & RDW_INVALIDATE_W))
1131 {
1132 if (redraw & RDW_UPDATENOW_W)
1133 wnd->MsgPaint (0, FALSE);
1134// else
1135// WinPostMsg( hwnd, WM_VIRTUAL_INTERNALPAINT, MPVOID, MPVOID );
1136 }
1137
1138error:
1139 /* clean up */
1140 if (hrgnTemp)
1141 GpiDestroyRegion (hpsTemp, hrgnTemp);
1142
1143 if (hpsTemp)
1144 WinReleasePS (hpsTemp);
1145
1146 if ((redraw & RDW_INVALIDATE_W) == 0)
1147 wnd->setSupressErase (FALSE);
1148 else if ((redraw & RDW_ERASENOW_W) == RDW_ERASENOW_W)
1149 wnd->setSupressErase (TRUE);
1150
1151 if (!success)
1152 _O32_SetLastError (ERROR_INVALID_PARAMETER);
1153
1154 SetFS(sel);
1155 return (success);
1156}
1157
1158BOOL WIN32API InvalidateRect (HWND hwnd, const RECT *pRect, BOOL erase)
1159{
1160 USHORT sel = RestoreOS2FS();
1161// Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1162 BOOL result;
1163
1164// todo !!
1165// if ( isFrame without client )
1166// erase = TRUE;
1167
1168 result = RedrawWindow (hwnd, pRect, NULLHANDLE,
1169 RDW_ALLCHILDREN_W | RDW_INVALIDATE_W |
1170 (erase ? RDW_ERASE_W : 0) |
1171 (hwnd == NULLHANDLE ? RDW_UPDATENOW_W : 0));
1172 SetFS(sel);
1173 return (result);
1174}
1175
1176BOOL WIN32API InvalidateRgn (HWND hwnd, HRGN hrgn, BOOL erase)
1177{
1178 USHORT sel = RestoreOS2FS();
1179// Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle (hwnd);
1180 BOOL result;
1181
1182// todo !!
1183// if ( isFrame without client )
1184// erase = TRUE;
1185
1186 result = RedrawWindow (hwnd, NULL, hrgn,
1187 RDW_ALLCHILDREN_W | RDW_INVALIDATE_W |
1188 (erase ? RDW_ERASE_W : 0) |
1189 (hwnd == NULLHANDLE ? RDW_UPDATENOW_W : 0));
1190 SetFS(sel);
1191 return (result);
1192}
1193//******************************************************************************
1194//******************************************************************************
1195BOOL WIN32API ScrollWindow(HWND hwnd, int dx, int dy, const RECT *pScroll, const RECT *pClip)
1196{
1197 Win32BaseWindow *window;
1198 APIRET rc;
1199 RECTL clientRect;
1200 RECTL scrollRect;
1201 RECTL clipRect;
1202 PRECTL pScrollRect = NULL;
1203 PRECTL pClipRect = NULL;
1204 ULONG scrollFlags = SW_INVALIDATERGN;
1205
1206 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
1207 if(!window) {
1208 dprintf(("ScrollWindow, window %x not found", hwnd));
1209 return 0;
1210 }
1211 dprintf(("ScrollWindow %x %d %d\n", hwnd, dx, dy));
1212 MapWin32ToOS2Rectl(window->getClientRect(), (PRECTLOS2)&clientRect);
1213 //Rectangle could be relative to parent window, so fix this
1214 if(clientRect.yBottom != 0) {
1215 clientRect.yTop -= clientRect.yBottom;
1216 clientRect.yBottom = 0;
1217 }
1218 if(clientRect.xLeft != 0) {
1219 clientRect.xRight -= clientRect.xLeft;
1220 clientRect.xLeft = 0;
1221 }
1222 if(pScroll) {
1223 MapWin32ToOS2Rectl((RECT *)pScroll, (PRECTLOS2)&scrollRect);
1224 pScrollRect = &scrollRect;
1225
1226 //Scroll rectangle relative to client area
1227 pScrollRect->xLeft += clientRect.xLeft;
1228 pScrollRect->xRight += clientRect.xLeft;
1229 pScrollRect->yTop += clientRect.yBottom;
1230 pScrollRect->yBottom += clientRect.yBottom;
1231 WinIntersectRect ((HAB) 0, pScrollRect, pScrollRect, &clientRect);
1232 }
1233 else scrollFlags |= SW_SCROLLCHILDREN;
1234
1235 if(pClip) {
1236 MapWin32ToOS2Rectl((RECT *)pClip, (PRECTLOS2)&clipRect);
1237 pClipRect = &clipRect;
1238
1239 //Clip rectangle relative to client area
1240 pClipRect->xLeft += clientRect.xLeft;
1241 pClipRect->xRight += clientRect.xLeft;
1242 pClipRect->yTop += clientRect.yBottom;
1243 pClipRect->yBottom += clientRect.yBottom;
1244 WinIntersectRect ((HAB) 0, pClipRect, pClipRect, &clientRect);
1245 }
1246
1247 dy = -dy; //always correct?
1248
1249 rc = WinScrollWindow(window->getOS2WindowHandle(), dx, dy,
1250 pScrollRect, pClipRect, NULLHANDLE,
1251 NULL, scrollFlags);
1252
1253 return (rc != RGN_ERROR);
1254}
1255//******************************************************************************
1256//TODO: Implement this one
1257//******************************************************************************
1258INT WIN32API ScrollWindowEx(HWND hwnd, int dx, int dy, const RECT *pScroll, const RECT *pClip,
1259 HRGN hrgnUpdate, PRECT pRectUpdate, UINT scrollFlag)
1260{
1261 dprintf(("USER32: ScrollWindowEx NOT CORRECTLY IMPLEMENTED\n"));
1262 return ScrollWindow(hwnd, dx, dy, pScroll, pClip);
1263}
1264//******************************************************************************
1265//******************************************************************************
Note: See TracBrowser for help on using the repository browser.