xref: /petsc/src/sys/classes/draw/impls/win32/win32draw.c (revision 5c6c1daec53e1d9ab0bec9db5309fd8fc7645b8d)
1*5c6c1daeSBarry Smith 
2*5c6c1daeSBarry Smith #include <petscsys.h>
3*5c6c1daeSBarry Smith #include <petsc-private/drawimpl.h>
4*5c6c1daeSBarry Smith #include <../src/sys/draw/impls/win32/win32draw.h>
5*5c6c1daeSBarry Smith 
6*5c6c1daeSBarry Smith #define IDC_FOUR       109
7*5c6c1daeSBarry Smith #define IDI_FOUR       107
8*5c6c1daeSBarry Smith #define IDM_EXIT       105
9*5c6c1daeSBarry Smith #define IDR_POPUP      103
10*5c6c1daeSBarry Smith #define MAX_LOADSTRING 100
11*5c6c1daeSBarry Smith 
12*5c6c1daeSBarry Smith #if !defined(SelectPen)
13*5c6c1daeSBarry Smith #define SelectPen(hdc, hpen)      ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen)))
14*5c6c1daeSBarry Smith #endif
15*5c6c1daeSBarry Smith #if !defined(SelectFont)
16*5c6c1daeSBarry Smith #define SelectFont(hdc,hfont)    ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
17*5c6c1daeSBarry Smith #endif
18*5c6c1daeSBarry Smith #if !defined(SelectBrush)
19*5c6c1daeSBarry Smith #define SelectBrush(hdc,hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush)))
20*5c6c1daeSBarry Smith #endif
21*5c6c1daeSBarry Smith #if !defined(GetStockBrush)
22*5c6c1daeSBarry Smith #define GetStockBrush(i)      ((HBRUSH)GetStockObject(i))
23*5c6c1daeSBarry Smith #endif
24*5c6c1daeSBarry Smith 
25*5c6c1daeSBarry Smith #define XTRANS(draw,win,x) \
26*5c6c1daeSBarry Smith    (int)(((win)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)*\
27*5c6c1daeSBarry Smith                                    ((draw)->port_xr - (draw)->port_xl))/\
28*5c6c1daeSBarry Smith                                    ((draw)->coor_xr - (draw)->coor_xl))))
29*5c6c1daeSBarry Smith #define YTRANS(draw,win,y) \
30*5c6c1daeSBarry Smith    (int)(((win)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)*\
31*5c6c1daeSBarry Smith                                    ((draw)->port_yr - (draw)->port_yl))/\
32*5c6c1daeSBarry Smith                                    ((draw)->coor_yr - (draw)->coor_yl))))
33*5c6c1daeSBarry Smith 
34*5c6c1daeSBarry Smith HINSTANCE     hInst;
35*5c6c1daeSBarry Smith HANDLE        g_hWindowListMutex = NULL;
36*5c6c1daeSBarry Smith WindowNode    WindowListHead     = NULL;
37*5c6c1daeSBarry Smith 
38*5c6c1daeSBarry Smith /* Hard coded color hue until hue.c works with this */
39*5c6c1daeSBarry Smith unsigned char RedMap[]   = {255,0,255,0,0,0,255,127,34,255,238,165,255,255,190,255,255,238,0,255,105,154,135,0,0,244,152,176,220,216,50,255};
40*5c6c1daeSBarry Smith unsigned char GreenMap[] = {255,0,0,255,255,0,0,255,139,165,130,42,182,127,190,255,215,162,197,246,105,205,206,100,0,164,245,224,17,191,205,240};
41*5c6c1daeSBarry Smith unsigned char BlueMap[]  = {255,0,0,0,255,255,225,212,34,0,238,42,193,80,190,0,0,173,205,143,105,50,235,0,128,96,255,230,120,216,50,245};
42*5c6c1daeSBarry Smith 
43*5c6c1daeSBarry Smith /* Foward declarations of functions included in this code module: */
44*5c6c1daeSBarry Smith LRESULT  CALLBACK PetscWndProc(HWND, UINT, WPARAM, LPARAM);
45*5c6c1daeSBarry Smith static PetscErrorCode TranslateColor_Win32(PetscDraw,int);
46*5c6c1daeSBarry Smith static PetscErrorCode AverageColorRectangle_Win32(PetscDraw,int,int,int,int);
47*5c6c1daeSBarry Smith static PetscErrorCode AverageColorTriangle_Win32(PetscDraw,int,int,int);
48*5c6c1daeSBarry Smith static PetscErrorCode deletemouselist_Win32(WindowNode);
49*5c6c1daeSBarry Smith static void OnPaint_Win32(HWND);
50*5c6c1daeSBarry Smith static void OnDestroy_Win32(HWND);
51*5c6c1daeSBarry Smith static PetscErrorCode MouseRecord_Win32(HWND,PetscDrawButton);
52*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw,PetscDraw *);
53*5c6c1daeSBarry Smith 
54*5c6c1daeSBarry Smith #undef __FUNCT__
55*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawSetDoubleBuffer_Win32"
56*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
57*5c6c1daeSBarry Smith {
58*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
59*5c6c1daeSBarry Smith   HDC             hdc      = GetDC(windraw->hWnd);
60*5c6c1daeSBarry Smith 
61*5c6c1daeSBarry Smith   PetscFunctionBegin;
62*5c6c1daeSBarry Smith   windraw->node->DoubleBuffer = CreateCompatibleDC(hdc);
63*5c6c1daeSBarry Smith   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
64*5c6c1daeSBarry Smith   windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
65*5c6c1daeSBarry Smith   /* Fill background of second buffer */
66*5c6c1daeSBarry Smith   ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
67*5c6c1daeSBarry Smith   /* Copy current buffer into seconf buffer and set window data as double buffered */
68*5c6c1daeSBarry Smith   BitBlt(windraw->node->DoubleBuffer,
69*5c6c1daeSBarry Smith          0,0,
70*5c6c1daeSBarry Smith          windraw->w,windraw->h,
71*5c6c1daeSBarry Smith          windraw->node->Buffer,
72*5c6c1daeSBarry Smith          0,0,
73*5c6c1daeSBarry Smith          SRCCOPY);
74*5c6c1daeSBarry Smith 
75*5c6c1daeSBarry Smith   windraw->node->DoubleBuffered = PETSC_TRUE;
76*5c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd,hdc);
77*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
78*5c6c1daeSBarry Smith }
79*5c6c1daeSBarry Smith 
80*5c6c1daeSBarry Smith #undef __FUNCT__
81*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawFlush_Win32"
82*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
83*5c6c1daeSBarry Smith {
84*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
85*5c6c1daeSBarry Smith   HDC             hdc = GetDC(windraw->hWnd);
86*5c6c1daeSBarry Smith 
87*5c6c1daeSBarry Smith   PetscFunctionBegin;
88*5c6c1daeSBarry Smith   /* flush double buffer into primary buffer */
89*5c6c1daeSBarry Smith   BitBlt(windraw->node->Buffer,
90*5c6c1daeSBarry Smith          0,0,
91*5c6c1daeSBarry Smith          windraw->w,windraw->h,
92*5c6c1daeSBarry Smith          windraw->node->DoubleBuffer,
93*5c6c1daeSBarry Smith          0,0,
94*5c6c1daeSBarry Smith          SRCCOPY);
95*5c6c1daeSBarry Smith   /* flush double buffer into window */
96*5c6c1daeSBarry Smith   BitBlt(hdc,
97*5c6c1daeSBarry Smith          0,0,
98*5c6c1daeSBarry Smith          windraw->w,windraw->h,
99*5c6c1daeSBarry Smith          windraw->node->DoubleBuffer,
100*5c6c1daeSBarry Smith          0,0,
101*5c6c1daeSBarry Smith          SRCCOPY);
102*5c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd,hdc);
103*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
104*5c6c1daeSBarry Smith }
105*5c6c1daeSBarry Smith 
106*5c6c1daeSBarry Smith #undef __FUNCT__
107*5c6c1daeSBarry Smith #define __FUNCT__ "deletemouselist_Win32"
108*5c6c1daeSBarry Smith static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
109*5c6c1daeSBarry Smith {
110*5c6c1daeSBarry Smith   /* Called upon window close. Frees memory of linked list of stored mouse commands */
111*5c6c1daeSBarry Smith   MouseNode node;
112*5c6c1daeSBarry Smith 
113*5c6c1daeSBarry Smith   while(deletelist->MouseListHead != NULL) {
114*5c6c1daeSBarry Smith     node = deletelist->MouseListHead;
115*5c6c1daeSBarry Smith     if (deletelist->MouseListHead->mnext != NULL) {
116*5c6c1daeSBarry Smith       deletelist->MouseListHead = deletelist->MouseListHead->mnext;
117*5c6c1daeSBarry Smith     }
118*5c6c1daeSBarry Smith     PetscFree(node);
119*5c6c1daeSBarry Smith   }
120*5c6c1daeSBarry Smith   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
121*5c6c1daeSBarry Smith   if (deletelist->wprev != NULL) {
122*5c6c1daeSBarry Smith     deletelist->wprev->wnext = deletelist->wnext;
123*5c6c1daeSBarry Smith   }
124*5c6c1daeSBarry Smith   if (deletelist->wnext != NULL) {
125*5c6c1daeSBarry Smith     deletelist->wnext->wprev = deletelist->wprev;
126*5c6c1daeSBarry Smith   }
127*5c6c1daeSBarry Smith   PetscFree(deletelist);
128*5c6c1daeSBarry Smith   return 0;
129*5c6c1daeSBarry Smith }
130*5c6c1daeSBarry Smith 
131*5c6c1daeSBarry Smith #undef __FUNCT__
132*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawGetMouseButton_Win32"
133*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
134*5c6c1daeSBarry Smith {
135*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
136*5c6c1daeSBarry Smith   WindowNode      current;
137*5c6c1daeSBarry Smith   MouseNode       node=0;
138*5c6c1daeSBarry Smith 
139*5c6c1daeSBarry Smith   PetscFunctionBegin;
140*5c6c1daeSBarry Smith   /* Make sure no other code is using the linked list at this moment */
141*5c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
142*5c6c1daeSBarry Smith   /* Look for the node that matches the window you are using */
143*5c6c1daeSBarry Smith   current = WindowListHead;
144*5c6c1daeSBarry Smith   while (current != NULL) {
145*5c6c1daeSBarry Smith     if (current->hWnd == windraw->hWnd) {
146*5c6c1daeSBarry Smith       current->IsGetMouseOn = TRUE;
147*5c6c1daeSBarry Smith       break;
148*5c6c1daeSBarry Smith     } else {
149*5c6c1daeSBarry Smith       current = current->wnext;
150*5c6c1daeSBarry Smith     }
151*5c6c1daeSBarry Smith   }
152*5c6c1daeSBarry Smith   /* If no actions have occured, wait for one */
153*5c6c1daeSBarry Smith   node = current->MouseListHead;
154*5c6c1daeSBarry Smith   if (!node) {
155*5c6c1daeSBarry Smith     ReleaseMutex(g_hWindowListMutex);
156*5c6c1daeSBarry Smith     WaitForSingleObject(current->event, INFINITE);
157*5c6c1daeSBarry Smith     WaitForSingleObject(g_hWindowListMutex, INFINITE);
158*5c6c1daeSBarry Smith   }
159*5c6c1daeSBarry Smith   /* once we have the information, assign the pointers to it */
160*5c6c1daeSBarry Smith   *button = current->MouseListHead->Button;
161*5c6c1daeSBarry Smith   *x_user = current->MouseListHead->user.x;
162*5c6c1daeSBarry Smith   *y_user = current->MouseListHead->user.y;
163*5c6c1daeSBarry Smith   /* optional arguments */
164*5c6c1daeSBarry Smith   if (x_phys) *x_phys = current->MouseListHead->phys.x;
165*5c6c1daeSBarry Smith   if (y_phys) *y_phys = current->MouseListHead->phys.y;
166*5c6c1daeSBarry Smith   /* remove set of information from sub linked-list, delete the node */
167*5c6c1daeSBarry Smith   current->MouseListHead = current->MouseListHead->mnext;
168*5c6c1daeSBarry Smith   if (!current->MouseListHead) {
169*5c6c1daeSBarry Smith     ResetEvent(current->event);
170*5c6c1daeSBarry Smith     current->MouseListTail = NULL;
171*5c6c1daeSBarry Smith   }
172*5c6c1daeSBarry Smith   if (node) PetscFree(node);
173*5c6c1daeSBarry Smith 
174*5c6c1daeSBarry Smith   /* Release mutex so that  other code can use
175*5c6c1daeSBarry Smith      the linked list now that we are done with it */
176*5c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
177*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
178*5c6c1daeSBarry Smith }
179*5c6c1daeSBarry Smith 
180*5c6c1daeSBarry Smith #undef __FUNCT__
181*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawPause_Win32"
182*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
183*5c6c1daeSBarry Smith {
184*5c6c1daeSBarry Smith   PetscFunctionBegin;
185*5c6c1daeSBarry Smith   PetscSleep(draw->pause);
186*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
187*5c6c1daeSBarry Smith }
188*5c6c1daeSBarry Smith 
189*5c6c1daeSBarry Smith #undef __FUNCT__
190*5c6c1daeSBarry Smith #define __FUNCT__ "TranslateColor_Win32"
191*5c6c1daeSBarry Smith static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
192*5c6c1daeSBarry Smith {
193*5c6c1daeSBarry Smith   /* Maps single color value into the RGB colors in our tables */
194*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
195*5c6c1daeSBarry Smith   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
196*5c6c1daeSBarry Smith   return 0;
197*5c6c1daeSBarry Smith }
198*5c6c1daeSBarry Smith 
199*5c6c1daeSBarry Smith #undef __FUNCT__
200*5c6c1daeSBarry Smith #define __FUNCT__ "AverageColorRectangle_Win32"
201*5c6c1daeSBarry Smith static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
202*5c6c1daeSBarry Smith {
203*5c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
204*5c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
205*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
206*5c6c1daeSBarry Smith   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
207*5c6c1daeSBarry Smith                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
208*5c6c1daeSBarry Smith                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
209*5c6c1daeSBarry Smith   return 0;
210*5c6c1daeSBarry Smith }
211*5c6c1daeSBarry Smith 
212*5c6c1daeSBarry Smith #undef __FUNCT__
213*5c6c1daeSBarry Smith #define __FUNCT__ "AverageColorTriangle_Win32"
214*5c6c1daeSBarry Smith static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
215*5c6c1daeSBarry Smith {
216*5c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
217*5c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
218*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
219*5c6c1daeSBarry Smith   windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
220*5c6c1daeSBarry Smith                               (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
221*5c6c1daeSBarry Smith                               (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
222*5c6c1daeSBarry Smith   return 0;
223*5c6c1daeSBarry Smith }
224*5c6c1daeSBarry Smith 
225*5c6c1daeSBarry Smith #undef __FUNCT__
226*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawRectangle_Win32"
227*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
228*5c6c1daeSBarry Smith {
229*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
230*5c6c1daeSBarry Smith   HBRUSH          hbrush;
231*5c6c1daeSBarry Smith   RECT            rect;
232*5c6c1daeSBarry Smith   int             x1,yone,x2,y2;
233*5c6c1daeSBarry Smith   HDC             hdc;
234*5c6c1daeSBarry Smith 
235*5c6c1daeSBarry Smith   PetscFunctionBegin;
236*5c6c1daeSBarry Smith   x1 = XTRANS(draw,windraw,xl);
237*5c6c1daeSBarry Smith   x2 = XTRANS(draw,windraw,xr);
238*5c6c1daeSBarry Smith   yone = YTRANS(draw,windraw,yl);
239*5c6c1daeSBarry Smith   y2 = YTRANS(draw,windraw,yr);
240*5c6c1daeSBarry Smith   SetRect(&rect,x1,y2,x2,yone);
241*5c6c1daeSBarry Smith   if (c1==c2 && c2==c3 && c3==c4) {
242*5c6c1daeSBarry Smith     TranslateColor_Win32(draw,c1);
243*5c6c1daeSBarry Smith   } else {
244*5c6c1daeSBarry Smith     AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
245*5c6c1daeSBarry Smith   }
246*5c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
247*5c6c1daeSBarry Smith 
248*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
249*5c6c1daeSBarry Smith     hdc = windraw->node->DoubleBuffer;
250*5c6c1daeSBarry Smith   } else {
251*5c6c1daeSBarry Smith     hdc = windraw->node->Buffer;
252*5c6c1daeSBarry Smith   }
253*5c6c1daeSBarry Smith   FillRect(hdc,&rect,hbrush);
254*5c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
255*5c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
256*5c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
257*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
258*5c6c1daeSBarry Smith }
259*5c6c1daeSBarry Smith 
260*5c6c1daeSBarry Smith #undef __FUNCT__
261*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawLine_Win32"
262*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
263*5c6c1daeSBarry Smith {
264*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
265*5c6c1daeSBarry Smith   HPEN            hpen;
266*5c6c1daeSBarry Smith   int             x1,yone,x2,y2;
267*5c6c1daeSBarry Smith   HDC             hdc;
268*5c6c1daeSBarry Smith 
269*5c6c1daeSBarry Smith   PetscFunctionBegin;
270*5c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
271*5c6c1daeSBarry Smith   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
272*5c6c1daeSBarry Smith   yone   = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
273*5c6c1daeSBarry Smith   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
274*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
275*5c6c1daeSBarry Smith     hdc = windraw->node->DoubleBuffer;
276*5c6c1daeSBarry Smith   } else {
277*5c6c1daeSBarry Smith     hdc = windraw->node->Buffer;
278*5c6c1daeSBarry Smith   }
279*5c6c1daeSBarry Smith   SelectPen(hdc,hpen);
280*5c6c1daeSBarry Smith   MoveToEx(hdc,x1,yone,NULL);
281*5c6c1daeSBarry Smith   LineTo(hdc,x2,y2);
282*5c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
283*5c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
284*5c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
285*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
286*5c6c1daeSBarry Smith }
287*5c6c1daeSBarry Smith 
288*5c6c1daeSBarry Smith #undef __FUNCT__
289*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawLineSetWidth_Win32"
290*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
291*5c6c1daeSBarry Smith {
292*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
293*5c6c1daeSBarry Smith   int             averagesize,finalwidth;
294*5c6c1daeSBarry Smith   RECT            rect;
295*5c6c1daeSBarry Smith 
296*5c6c1daeSBarry Smith   PetscFunctionBegin;
297*5c6c1daeSBarry Smith   GetClientRect(windraw->hWnd,&rect);
298*5c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
299*5c6c1daeSBarry Smith   finalwidth  = (int)floor(averagesize*width);
300*5c6c1daeSBarry Smith   if (finalwidth < 1) {
301*5c6c1daeSBarry Smith     finalwidth = 1; /* minimum size PetscDrawLine can except */
302*5c6c1daeSBarry Smith   }
303*5c6c1daeSBarry Smith   windraw->linewidth = finalwidth;
304*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
305*5c6c1daeSBarry Smith }
306*5c6c1daeSBarry Smith 
307*5c6c1daeSBarry Smith #undef __FUNCT__
308*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawLineGetWidth_Win32"
309*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
310*5c6c1daeSBarry Smith {
311*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
312*5c6c1daeSBarry Smith 
313*5c6c1daeSBarry Smith   PetscFunctionBegin;
314*5c6c1daeSBarry Smith   *width = (PetscReal)windraw->linewidth;
315*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
316*5c6c1daeSBarry Smith }
317*5c6c1daeSBarry Smith 
318*5c6c1daeSBarry Smith #undef __FUNCT__
319*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawPoint_Win32"
320*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
321*5c6c1daeSBarry Smith {
322*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
323*5c6c1daeSBarry Smith   HBRUSH          hbrush;
324*5c6c1daeSBarry Smith   HRGN            hrgn;
325*5c6c1daeSBarry Smith   int             radius;
326*5c6c1daeSBarry Smith   int             x1,yone;
327*5c6c1daeSBarry Smith   HDC             hdc;
328*5c6c1daeSBarry Smith 
329*5c6c1daeSBarry Smith   PetscFunctionBegin;
330*5c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
331*5c6c1daeSBarry Smith   x1     = XTRANS(draw,windraw,x);
332*5c6c1daeSBarry Smith   yone     = YTRANS(draw,windraw,y);
333*5c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
334*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
335*5c6c1daeSBarry Smith     hdc = windraw->node->DoubleBuffer;
336*5c6c1daeSBarry Smith   } else {
337*5c6c1daeSBarry Smith     hdc = windraw->node->Buffer;
338*5c6c1daeSBarry Smith   }
339*5c6c1daeSBarry Smith   /* desired size is one logical pixel so just turn it on */
340*5c6c1daeSBarry Smith   if (windraw->pointdiameter == 1) {
341*5c6c1daeSBarry Smith     SetPixelV(hdc,x1,yone,windraw->currentcolor);
342*5c6c1daeSBarry Smith   } else {
343*5c6c1daeSBarry Smith     /* draw point around position determined */
344*5c6c1daeSBarry Smith     radius = windraw->pointdiameter/2; /* integer division */
345*5c6c1daeSBarry Smith     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
346*5c6c1daeSBarry Smith     FillRgn(hdc,hrgn,hbrush);
347*5c6c1daeSBarry Smith   }
348*5c6c1daeSBarry Smith   /* Forces a WM_PAINT and erases background */
349*5c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
350*5c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
351*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
352*5c6c1daeSBarry Smith }
353*5c6c1daeSBarry Smith 
354*5c6c1daeSBarry Smith #undef __FUNCT__
355*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawPointSetSize_Win32"
356*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
357*5c6c1daeSBarry Smith {
358*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
359*5c6c1daeSBarry Smith   int             averagesize,diameter;
360*5c6c1daeSBarry Smith   RECT            rect;
361*5c6c1daeSBarry Smith 
362*5c6c1daeSBarry Smith   PetscFunctionBegin;
363*5c6c1daeSBarry Smith   GetClientRect(windraw->hWnd,&rect);
364*5c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
365*5c6c1daeSBarry Smith   diameter    = (int)floor(averagesize*width);
366*5c6c1daeSBarry Smith   if (diameter < 1) diameter = 1;
367*5c6c1daeSBarry Smith   windraw->pointdiameter     = diameter;
368*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
369*5c6c1daeSBarry Smith }
370*5c6c1daeSBarry Smith 
371*5c6c1daeSBarry Smith #undef __FUNCT__
372*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawString_Win32"
373*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
374*5c6c1daeSBarry Smith {
375*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
376*5c6c1daeSBarry Smith   RECT            r;
377*5c6c1daeSBarry Smith   HFONT           hfont;
378*5c6c1daeSBarry Smith   LOGFONT         logfont;
379*5c6c1daeSBarry Smith   int             x1,yone;
380*5c6c1daeSBarry Smith   HDC             hdc;
381*5c6c1daeSBarry Smith 
382*5c6c1daeSBarry Smith   PetscFunctionBegin;
383*5c6c1daeSBarry Smith   x1              = XTRANS(draw,windraw,x);
384*5c6c1daeSBarry Smith   yone              = YTRANS(draw,windraw,y);
385*5c6c1daeSBarry Smith   r.bottom        = yone;
386*5c6c1daeSBarry Smith   r.left          = x1;
387*5c6c1daeSBarry Smith   r.right         = x1 + 1;
388*5c6c1daeSBarry Smith   r.top           = yone + 1;
389*5c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
390*5c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
391*5c6c1daeSBarry Smith   logfont.lfEscapement     = 0;
392*5c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
393*5c6c1daeSBarry Smith   logfont.lfCharSet        = 0;
394*5c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
395*5c6c1daeSBarry Smith   logfont.lfItalic         = 0;
396*5c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
397*5c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
398*5c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
399*5c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
400*5c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
401*5c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
402*5c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
403*5c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
404*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
405*5c6c1daeSBarry Smith     hdc = windraw->node->DoubleBuffer;
406*5c6c1daeSBarry Smith   } else {
407*5c6c1daeSBarry Smith     hdc = windraw->node->Buffer;
408*5c6c1daeSBarry Smith   }
409*5c6c1daeSBarry Smith   SelectFont(hdc,hfont);
410*5c6c1daeSBarry Smith   SetTextColor(hdc,windraw->currentcolor);
411*5c6c1daeSBarry Smith   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
412*5c6c1daeSBarry Smith   DeleteObject(hfont);
413*5c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
414*5c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
415*5c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
416*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
417*5c6c1daeSBarry Smith }
418*5c6c1daeSBarry Smith 
419*5c6c1daeSBarry Smith #undef __FUNCT__
420*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawStringVertical_Win32"
421*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
422*5c6c1daeSBarry Smith {
423*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
424*5c6c1daeSBarry Smith   RECT            r;
425*5c6c1daeSBarry Smith   HFONT           hfont;
426*5c6c1daeSBarry Smith   LOGFONT         logfont;
427*5c6c1daeSBarry Smith   int             x1,yone;
428*5c6c1daeSBarry Smith   HDC             hdc;
429*5c6c1daeSBarry Smith 
430*5c6c1daeSBarry Smith   PetscFunctionBegin;
431*5c6c1daeSBarry Smith   x1           = XTRANS(draw,windraw,x);
432*5c6c1daeSBarry Smith   yone           = YTRANS(draw,windraw,y);
433*5c6c1daeSBarry Smith   r.left       = x1;
434*5c6c1daeSBarry Smith   r.bottom     = yone + 30;
435*5c6c1daeSBarry Smith   r.right      = x1 + 1;
436*5c6c1daeSBarry Smith   r.top        = yone - 30;
437*5c6c1daeSBarry Smith   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
438*5c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
439*5c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
440*5c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
441*5c6c1daeSBarry Smith   logfont.lfCharSet        = DEFAULT_CHARSET;
442*5c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
443*5c6c1daeSBarry Smith   logfont.lfItalic         = 0;
444*5c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
445*5c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
446*5c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
447*5c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
448*5c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
449*5c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
450*5c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
451*5c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
452*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
453*5c6c1daeSBarry Smith     hdc = windraw->node->DoubleBuffer;
454*5c6c1daeSBarry Smith   } else {
455*5c6c1daeSBarry Smith     hdc = windraw->node->Buffer;
456*5c6c1daeSBarry Smith   }
457*5c6c1daeSBarry Smith   SelectFont(hdc,hfont);
458*5c6c1daeSBarry Smith   SetTextColor(hdc,windraw->currentcolor);
459*5c6c1daeSBarry Smith   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE );
460*5c6c1daeSBarry Smith   DeleteObject(hfont);
461*5c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
462*5c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
463*5c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
464*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
465*5c6c1daeSBarry Smith }
466*5c6c1daeSBarry Smith 
467*5c6c1daeSBarry Smith #undef __FUNCT__
468*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawStringSetSize_Win32"
469*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
470*5c6c1daeSBarry Smith {
471*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
472*5c6c1daeSBarry Smith   int             w,h;
473*5c6c1daeSBarry Smith 
474*5c6c1daeSBarry Smith   PetscFunctionBegin;
475*5c6c1daeSBarry Smith   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
476*5c6c1daeSBarry Smith   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
477*5c6c1daeSBarry Smith   if (h < 1) h = 1;
478*5c6c1daeSBarry Smith   if (w < 1) w = 1;
479*5c6c1daeSBarry Smith   windraw->stringheight = h;
480*5c6c1daeSBarry Smith   windraw->stringwidth  = w;
481*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
482*5c6c1daeSBarry Smith }
483*5c6c1daeSBarry Smith #undef __FUNCT__
484*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawStringGetSize_Win32"
485*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
486*5c6c1daeSBarry Smith {
487*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
488*5c6c1daeSBarry Smith   double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
489*5c6c1daeSBarry Smith   double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
490*5c6c1daeSBarry Smith 
491*5c6c1daeSBarry Smith   PetscFunctionBegin;
492*5c6c1daeSBarry Smith   *height = (double)windraw->stringheight*scaleY;
493*5c6c1daeSBarry Smith   *width  = (double)windraw->stringwidth*scaleX;
494*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
495*5c6c1daeSBarry Smith }
496*5c6c1daeSBarry Smith 
497*5c6c1daeSBarry Smith #undef __FUNCT__
498*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawResizeWindow_Win32"
499*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
500*5c6c1daeSBarry Smith {
501*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
502*5c6c1daeSBarry Smith   RECT            r;
503*5c6c1daeSBarry Smith 
504*5c6c1daeSBarry Smith   PetscFunctionBegin;
505*5c6c1daeSBarry Smith   GetWindowRect(windraw->hWnd,&r);
506*5c6c1daeSBarry Smith   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
507*5c6c1daeSBarry Smith   /* set all variable dealing with window dimensions */
508*5c6c1daeSBarry Smith   windraw->node->bitheight = windraw->h = draw->h = h;
509*5c6c1daeSBarry Smith   windraw->node->bitwidth  = windraw->w = draw->w = w;
510*5c6c1daeSBarry Smith   /* set up graphic buffers with the new size of window */
511*5c6c1daeSBarry Smith   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
512*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
513*5c6c1daeSBarry Smith     SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
514*5c6c1daeSBarry Smith   }
515*5c6c1daeSBarry Smith   windraw->haveresized = PETSC_TRUE;
516*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
517*5c6c1daeSBarry Smith }
518*5c6c1daeSBarry Smith 
519*5c6c1daeSBarry Smith #undef __FUNCT__
520*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawCheckResizeWindow_Win32"
521*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
522*5c6c1daeSBarry Smith {
523*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
524*5c6c1daeSBarry Smith 
525*5c6c1daeSBarry Smith   PetscFunctionBegin;
526*5c6c1daeSBarry Smith   if (windraw->haveresized == 1) {
527*5c6c1daeSBarry Smith     PetscFunctionReturn(1);
528*5c6c1daeSBarry Smith   } else {
529*5c6c1daeSBarry Smith     PetscFunctionReturn(0);
530*5c6c1daeSBarry Smith   }
531*5c6c1daeSBarry Smith 
532*5c6c1daeSBarry Smith }
533*5c6c1daeSBarry Smith 
534*5c6c1daeSBarry Smith #undef __FUNCT__
535*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawSetTitle_Win32"
536*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
537*5c6c1daeSBarry Smith {
538*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
539*5c6c1daeSBarry Smith 
540*5c6c1daeSBarry Smith   PetscFunctionBegin;
541*5c6c1daeSBarry Smith   SetWindowText(windraw->hWnd,title);
542*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
543*5c6c1daeSBarry Smith }
544*5c6c1daeSBarry Smith 
545*5c6c1daeSBarry Smith #undef __FUNCT__
546*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawClear_Win32"
547*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
548*5c6c1daeSBarry Smith {
549*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
550*5c6c1daeSBarry Smith 
551*5c6c1daeSBarry Smith   PetscFunctionBegin;
552*5c6c1daeSBarry Smith   /* clear primary buffer */
553*5c6c1daeSBarry Smith   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
554*5c6c1daeSBarry Smith   /* if exists clear secondary buffer */
555*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
556*5c6c1daeSBarry Smith     ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
557*5c6c1daeSBarry Smith   }
558*5c6c1daeSBarry Smith   /* force WM_PAINT message so cleared buffer will show */
559*5c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
560*5c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
561*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
562*5c6c1daeSBarry Smith }
563*5c6c1daeSBarry Smith 
564*5c6c1daeSBarry Smith #undef __FUNCT__
565*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawTriangle_Win32"
566*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
567*5c6c1daeSBarry Smith 			      PetscReal x3,PetscReal y3,int c1,int c2,int c3)
568*5c6c1daeSBarry Smith {
569*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
570*5c6c1daeSBarry Smith   HBRUSH          hbrush;
571*5c6c1daeSBarry Smith   HPEN            hpen;
572*5c6c1daeSBarry Smith   int             p1x,p1y,p2x,p2y,p3x,p3y;
573*5c6c1daeSBarry Smith   HDC             bit;
574*5c6c1daeSBarry Smith 
575*5c6c1daeSBarry Smith   PetscFunctionBegin;
576*5c6c1daeSBarry Smith   AverageColorTriangle_Win32(draw,c1,c2,c3);
577*5c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
578*5c6c1daeSBarry Smith   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
579*5c6c1daeSBarry Smith   p1x = XTRANS(draw,windraw,x1);
580*5c6c1daeSBarry Smith   p2x = XTRANS(draw,windraw,x2);
581*5c6c1daeSBarry Smith   p3x = XTRANS(draw,windraw,x3);
582*5c6c1daeSBarry Smith   p1y = YTRANS(draw,windraw,yone);
583*5c6c1daeSBarry Smith   p2y = YTRANS(draw,windraw,y2);
584*5c6c1daeSBarry Smith   p3y = YTRANS(draw,windraw,y3);
585*5c6c1daeSBarry Smith 
586*5c6c1daeSBarry Smith   if (windraw->node->DoubleBuffered) {
587*5c6c1daeSBarry Smith     bit = windraw->node->DoubleBuffer;
588*5c6c1daeSBarry Smith   } else {
589*5c6c1daeSBarry Smith     bit = windraw->node->Buffer;
590*5c6c1daeSBarry Smith   }
591*5c6c1daeSBarry Smith   BeginPath(bit);
592*5c6c1daeSBarry Smith   MoveToEx(bit,p1x,p1y,NULL);
593*5c6c1daeSBarry Smith   LineTo(bit,p2x,p2y);
594*5c6c1daeSBarry Smith   LineTo(bit,p3x,p3y);
595*5c6c1daeSBarry Smith   LineTo(bit,p1x,p1y);
596*5c6c1daeSBarry Smith   EndPath(bit);
597*5c6c1daeSBarry Smith   SelectPen(bit,hpen);
598*5c6c1daeSBarry Smith   SelectBrush(bit,hbrush);
599*5c6c1daeSBarry Smith   StrokeAndFillPath(bit);
600*5c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
601*5c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
602*5c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
603*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
604*5c6c1daeSBarry Smith }
605*5c6c1daeSBarry Smith 
606*5c6c1daeSBarry Smith #undef __FUNCT__
607*5c6c1daeSBarry Smith #define __FUNCT__ "PopMessageLoopThread_Win32"
608*5c6c1daeSBarry Smith void PopMessageLoopThread_Win32(PetscDraw popdraw)
609*5c6c1daeSBarry Smith {
610*5c6c1daeSBarry Smith   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
611*5c6c1daeSBarry Smith   MSG             msg;
612*5c6c1daeSBarry Smith   HWND            hWnd = NULL;
613*5c6c1daeSBarry Smith   char            PopClassName [MAX_LOADSTRING + 1];
614*5c6c1daeSBarry Smith   RECT            r;
615*5c6c1daeSBarry Smith   int             width,height;
616*5c6c1daeSBarry Smith   WNDCLASSEX      myclass;
617*5c6c1daeSBarry Smith   LPVOID          lpMsgBuf;
618*5c6c1daeSBarry Smith 
619*5c6c1daeSBarry Smith   PetscFunctionBegin;
620*5c6c1daeSBarry Smith   /* initialize window class parameters */
621*5c6c1daeSBarry Smith   myclass.cbSize        = sizeof(WNDCLASSEX);
622*5c6c1daeSBarry Smith   myclass.style         = CS_OWNDC;
623*5c6c1daeSBarry Smith   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
624*5c6c1daeSBarry Smith   myclass.cbClsExtra    = 0;
625*5c6c1daeSBarry Smith   myclass.cbWndExtra    = 0;
626*5c6c1daeSBarry Smith   myclass.hInstance     = NULL;
627*5c6c1daeSBarry Smith   myclass.hIcon         = NULL;
628*5c6c1daeSBarry Smith   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
629*5c6c1daeSBarry Smith   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
630*5c6c1daeSBarry Smith   myclass.lpszMenuName  = NULL;
631*5c6c1daeSBarry Smith   myclass.lpszClassName = PopClassName;
632*5c6c1daeSBarry Smith   myclass.hIconSm       = NULL;
633*5c6c1daeSBarry Smith 
634*5c6c1daeSBarry Smith   RegisterClassEx(&myclass);
635*5c6c1daeSBarry Smith 
636*5c6c1daeSBarry Smith   SetRect(&r,0,0,450,450);
637*5c6c1daeSBarry Smith 
638*5c6c1daeSBarry Smith   width    = (r.right - r.left) / 3;
639*5c6c1daeSBarry Smith   height   = (r.bottom - r.top) / 3;
640*5c6c1daeSBarry Smith 
641*5c6c1daeSBarry Smith   hWnd = CreateWindowEx(0,
642*5c6c1daeSBarry Smith                         PopClassName,
643*5c6c1daeSBarry Smith                         NULL,
644*5c6c1daeSBarry Smith                         WS_POPUPWINDOW | WS_CAPTION,
645*5c6c1daeSBarry Smith                         0,0,
646*5c6c1daeSBarry Smith                         width,height,
647*5c6c1daeSBarry Smith                         NULL,
648*5c6c1daeSBarry Smith                         NULL,
649*5c6c1daeSBarry Smith                         hInst,
650*5c6c1daeSBarry Smith                         NULL);
651*5c6c1daeSBarry Smith   pop->x = 0;
652*5c6c1daeSBarry Smith   pop->y = 0;
653*5c6c1daeSBarry Smith   pop->w = width;
654*5c6c1daeSBarry Smith   pop->h = height;
655*5c6c1daeSBarry Smith 
656*5c6c1daeSBarry Smith   if (!hWnd) {
657*5c6c1daeSBarry Smith     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
658*5c6c1daeSBarry Smith     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
659*5c6c1daeSBarry Smith     LocalFree( lpMsgBuf );
660*5c6c1daeSBarry Smith     exit(0);
661*5c6c1daeSBarry Smith   }
662*5c6c1daeSBarry Smith   pop->hWnd = hWnd;
663*5c6c1daeSBarry Smith   /* display and update new popup window */
664*5c6c1daeSBarry Smith   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
665*5c6c1daeSBarry Smith   UpdateWindow(pop->hWnd);
666*5c6c1daeSBarry Smith   SetEvent(pop->hReadyEvent);
667*5c6c1daeSBarry Smith 
668*5c6c1daeSBarry Smith   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
669*5c6c1daeSBarry Smith     TranslateMessage(&msg);
670*5c6c1daeSBarry Smith     DispatchMessage(&msg);
671*5c6c1daeSBarry Smith   }
672*5c6c1daeSBarry Smith   PetscFunctionReturnVoid();
673*5c6c1daeSBarry Smith }
674*5c6c1daeSBarry Smith 
675*5c6c1daeSBarry Smith #undef __FUNCT__
676*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawDestroy_Win32"
677*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
678*5c6c1daeSBarry Smith {
679*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
680*5c6c1daeSBarry Smith 
681*5c6c1daeSBarry Smith   PetscFunctionBegin;
682*5c6c1daeSBarry Smith   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
683*5c6c1daeSBarry Smith   PetscFree(windraw);
684*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
685*5c6c1daeSBarry Smith }
686*5c6c1daeSBarry Smith 
687*5c6c1daeSBarry Smith #undef __FUNCT__
688*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawSynchronizedFlush_Win32"
689*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
690*5c6c1daeSBarry Smith {
691*5c6c1daeSBarry Smith   /* Multi Processor is not implemeted yet */
692*5c6c1daeSBarry Smith   PetscFunctionBegin;
693*5c6c1daeSBarry Smith   PetscDrawFlush_Win32(draw);
694*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
695*5c6c1daeSBarry Smith }
696*5c6c1daeSBarry Smith 
697*5c6c1daeSBarry Smith #undef __FUNCT__
698*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawSynchronizedClear_Win32"
699*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
700*5c6c1daeSBarry Smith {
701*5c6c1daeSBarry Smith   /* Multi Processor is not implemeted yet */
702*5c6c1daeSBarry Smith   PetscFunctionBegin;
703*5c6c1daeSBarry Smith   PetscDrawClear_Win32(draw);
704*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
705*5c6c1daeSBarry Smith }
706*5c6c1daeSBarry Smith 
707*5c6c1daeSBarry Smith #undef __FUNCT__
708*5c6c1daeSBarry Smith #define __FUNCT__ "MessageLoopThread_Win32"
709*5c6c1daeSBarry Smith void MessageLoopThread_Win32(PetscDraw draw)
710*5c6c1daeSBarry Smith {
711*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
712*5c6c1daeSBarry Smith   MSG             msg;
713*5c6c1daeSBarry Smith   HWND            hWnd = NULL;
714*5c6c1daeSBarry Smith   char            classname[MAX_LOADSTRING + 1];
715*5c6c1daeSBarry Smith   WNDCLASSEX      wclass;
716*5c6c1daeSBarry Smith   LPVOID          lpMsgBuf;
717*5c6c1daeSBarry Smith 
718*5c6c1daeSBarry Smith   PetscFunctionBegin;
719*5c6c1daeSBarry Smith   /* initialize window class parameters */
720*5c6c1daeSBarry Smith   wclass.cbSize         = sizeof(WNDCLASSEX);
721*5c6c1daeSBarry Smith   wclass.style          = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
722*5c6c1daeSBarry Smith   wclass.lpfnWndProc    = (WNDPROC)PetscWndProc;
723*5c6c1daeSBarry Smith   wclass.cbClsExtra     = 0;
724*5c6c1daeSBarry Smith   wclass.cbWndExtra     = 0;
725*5c6c1daeSBarry Smith   wclass.hInstance      = NULL;
726*5c6c1daeSBarry Smith   wclass.hIcon          = LoadIcon(NULL,IDI_APPLICATION);
727*5c6c1daeSBarry Smith   wclass.hCursor        = LoadCursor(NULL,IDC_ARROW);
728*5c6c1daeSBarry Smith   wclass.hbrBackground  = GetStockBrush(WHITE_BRUSH);
729*5c6c1daeSBarry Smith   wclass.lpszMenuName   = NULL;
730*5c6c1daeSBarry Smith   wclass.lpszClassName  = classname;
731*5c6c1daeSBarry Smith   wclass.hIconSm        = NULL;
732*5c6c1daeSBarry Smith 
733*5c6c1daeSBarry Smith   RegisterClassEx(&wclass);
734*5c6c1daeSBarry Smith 
735*5c6c1daeSBarry Smith 
736*5c6c1daeSBarry Smith   hWnd = CreateWindowEx(0,
737*5c6c1daeSBarry Smith                         classname,
738*5c6c1daeSBarry Smith                         NULL,
739*5c6c1daeSBarry Smith                         WS_OVERLAPPEDWINDOW,
740*5c6c1daeSBarry Smith                         draw->x,
741*5c6c1daeSBarry Smith                         draw->y,
742*5c6c1daeSBarry Smith                         draw->w,
743*5c6c1daeSBarry Smith                         draw->h,
744*5c6c1daeSBarry Smith                         NULL,
745*5c6c1daeSBarry Smith                         NULL,
746*5c6c1daeSBarry Smith                         hInst,
747*5c6c1daeSBarry Smith                         NULL);
748*5c6c1daeSBarry Smith 
749*5c6c1daeSBarry Smith   if (!hWnd) {
750*5c6c1daeSBarry Smith     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
751*5c6c1daeSBarry Smith     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
752*5c6c1daeSBarry Smith     LocalFree( lpMsgBuf );
753*5c6c1daeSBarry Smith     exit(0);
754*5c6c1daeSBarry Smith   }
755*5c6c1daeSBarry Smith   windraw->hWnd = hWnd;
756*5c6c1daeSBarry Smith   /* display and update new window */
757*5c6c1daeSBarry Smith   ShowWindow(hWnd,SW_SHOWNORMAL);
758*5c6c1daeSBarry Smith   UpdateWindow(hWnd);
759*5c6c1daeSBarry Smith   SetEvent(windraw->hReadyEvent);
760*5c6c1daeSBarry Smith 
761*5c6c1daeSBarry Smith   while (GetMessage(&msg,hWnd, 0, 0)) {
762*5c6c1daeSBarry Smith     TranslateMessage(&msg);
763*5c6c1daeSBarry Smith     DispatchMessage(&msg);
764*5c6c1daeSBarry Smith   }
765*5c6c1daeSBarry Smith   PetscFunctionReturnVoid();
766*5c6c1daeSBarry Smith }
767*5c6c1daeSBarry Smith 
768*5c6c1daeSBarry Smith 
769*5c6c1daeSBarry Smith static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
770*5c6c1daeSBarry Smith                                  PetscDrawFlush_Win32,
771*5c6c1daeSBarry Smith                                  PetscDrawLine_Win32,
772*5c6c1daeSBarry Smith                                  PetscDrawLineSetWidth_Win32,
773*5c6c1daeSBarry Smith                                  PetscDrawLineGetWidth_Win32,
774*5c6c1daeSBarry Smith                                  PetscDrawPoint_Win32,
775*5c6c1daeSBarry Smith                                  PetscDrawPointSetSize_Win32,
776*5c6c1daeSBarry Smith                                  PetscDrawString_Win32,
777*5c6c1daeSBarry Smith                                  PetscDrawStringVertical_Win32,
778*5c6c1daeSBarry Smith                                  PetscDrawStringSetSize_Win32,
779*5c6c1daeSBarry Smith                                  PetscDrawStringGetSize_Win32,
780*5c6c1daeSBarry Smith                                  0,
781*5c6c1daeSBarry Smith                                  PetscDrawClear_Win32,
782*5c6c1daeSBarry Smith                                  PetscDrawSynchronizedFlush_Win32,
783*5c6c1daeSBarry Smith                                  PetscDrawRectangle_Win32,
784*5c6c1daeSBarry Smith                                  PetscDrawTriangle_Win32,
785*5c6c1daeSBarry Smith                                  0,
786*5c6c1daeSBarry Smith                                  PetscDrawGetMouseButton_Win32,
787*5c6c1daeSBarry Smith                                  PetscDrawPause_Win32,
788*5c6c1daeSBarry Smith                                  PetscDrawSynchronizedClear_Win32,
789*5c6c1daeSBarry Smith                                  0,
790*5c6c1daeSBarry Smith                                  0,
791*5c6c1daeSBarry Smith                                  PetscDrawGetPopup_Win32,
792*5c6c1daeSBarry Smith                                  PetscDrawSetTitle_Win32,
793*5c6c1daeSBarry Smith                                  PetscDrawCheckResizedWindow_Win32,
794*5c6c1daeSBarry Smith                                  PetscDrawResizeWindow_Win32,
795*5c6c1daeSBarry Smith                                  PetscDrawDestroy_Win32,
796*5c6c1daeSBarry Smith                                  0,
797*5c6c1daeSBarry Smith                                  0,
798*5c6c1daeSBarry Smith                                  0,
799*5c6c1daeSBarry Smith                                  0};
800*5c6c1daeSBarry Smith 
801*5c6c1daeSBarry Smith #undef __FUNCT__
802*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawGetPopup_Win32"
803*5c6c1daeSBarry Smith static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
804*5c6c1daeSBarry Smith {
805*5c6c1daeSBarry Smith   PetscDraw_Win32 *pop;
806*5c6c1daeSBarry Smith   HANDLE          hThread = NULL;
807*5c6c1daeSBarry Smith   WindowNode      newnode;
808*5c6c1daeSBarry Smith   PetscErrorCode ierr;
809*5c6c1daeSBarry Smith 
810*5c6c1daeSBarry Smith   PetscFunctionBegin;
811*5c6c1daeSBarry Smith   ierr = PetscNew(PetscDraw_Win32,&pop);CHKERRQ(ierr);
812*5c6c1daeSBarry Smith   (*popdraw)->data = pop;
813*5c6c1daeSBarry Smith 
814*5c6c1daeSBarry Smith   /* the following is temporary fix for initializing a global datastructure */
815*5c6c1daeSBarry Smith   if (!g_hWindowListMutex) {
816*5c6c1daeSBarry Smith     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
817*5c6c1daeSBarry Smith   }
818*5c6c1daeSBarry Smith   ierr = PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
819*5c6c1daeSBarry Smith 
820*5c6c1daeSBarry Smith   pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
821*5c6c1daeSBarry Smith   CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
822*5c6c1daeSBarry Smith   CloseHandle(hThread);
823*5c6c1daeSBarry Smith   WaitForSingleObject(pop->hReadyEvent, INFINITE);
824*5c6c1daeSBarry Smith   CloseHandle(pop->hReadyEvent);
825*5c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
826*5c6c1daeSBarry Smith 
827*5c6c1daeSBarry Smith   draw->popup             = (*popdraw);
828*5c6c1daeSBarry Smith   ierr                    = PetscNew(struct _p_WindowNode,&newnode);CHKERRQ(ierr);
829*5c6c1daeSBarry Smith   newnode->MouseListHead  = NULL;
830*5c6c1daeSBarry Smith   newnode->MouseListTail  = NULL;
831*5c6c1daeSBarry Smith   newnode->wnext          = WindowListHead;
832*5c6c1daeSBarry Smith   newnode->wprev          = NULL;
833*5c6c1daeSBarry Smith   newnode->hWnd           = pop->hWnd;
834*5c6c1daeSBarry Smith   if (WindowListHead != NULL) {
835*5c6c1daeSBarry Smith     WindowListHead->wprev = newnode;
836*5c6c1daeSBarry Smith   }
837*5c6c1daeSBarry Smith   WindowListHead          = newnode;
838*5c6c1daeSBarry Smith   pop->hdc                = GetDC(pop->hWnd);
839*5c6c1daeSBarry Smith 
840*5c6c1daeSBarry Smith   pop->stringheight   = 10;
841*5c6c1daeSBarry Smith   pop->stringwidth    = 6;
842*5c6c1daeSBarry Smith   pop->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
843*5c6c1daeSBarry Smith   pop->pointdiameter  = 1;
844*5c6c1daeSBarry Smith   pop->node           = newnode;
845*5c6c1daeSBarry Smith 
846*5c6c1daeSBarry Smith   newnode->bitwidth  = pop->w;
847*5c6c1daeSBarry Smith   newnode->bitheight = pop->h;
848*5c6c1daeSBarry Smith 
849*5c6c1daeSBarry Smith   /* Create and initialize primary graphics buffer */
850*5c6c1daeSBarry Smith   newnode->Buffer = CreateCompatibleDC(pop->hdc);
851*5c6c1daeSBarry Smith   newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
852*5c6c1daeSBarry Smith   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
853*5c6c1daeSBarry Smith   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
854*5c6c1daeSBarry Smith 
855*5c6c1daeSBarry Smith 
856*5c6c1daeSBarry Smith   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
857*5c6c1daeSBarry Smith   newnode->DoubleBuffered = PETSC_FALSE;
858*5c6c1daeSBarry Smith 
859*5c6c1daeSBarry Smith   ReleaseDC(pop->hWnd,pop->hdc);
860*5c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
861*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
862*5c6c1daeSBarry Smith }
863*5c6c1daeSBarry Smith 
864*5c6c1daeSBarry Smith EXTERN_C_BEGIN
865*5c6c1daeSBarry Smith #undef __FUNCT__
866*5c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawCreate_Win32"
867*5c6c1daeSBarry Smith PetscErrorCode  PetscDrawCreate_Win32(PetscDraw draw)
868*5c6c1daeSBarry Smith {
869*5c6c1daeSBarry Smith   PetscDraw_Win32 *windraw;
870*5c6c1daeSBarry Smith   HANDLE          hThread = NULL;
871*5c6c1daeSBarry Smith   PetscErrorCode ierr;
872*5c6c1daeSBarry Smith   WindowNode      newnode;
873*5c6c1daeSBarry Smith 
874*5c6c1daeSBarry Smith   PetscFunctionBegin;
875*5c6c1daeSBarry Smith   ierr        = PetscNew(PetscDraw_Win32,&windraw);CHKERRQ(ierr);
876*5c6c1daeSBarry Smith   draw->data  = windraw;
877*5c6c1daeSBarry Smith 
878*5c6c1daeSBarry Smith   /* the following is temporary fix for initializing a global datastructure */
879*5c6c1daeSBarry Smith   if (!g_hWindowListMutex) {
880*5c6c1daeSBarry Smith     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
881*5c6c1daeSBarry Smith   }
882*5c6c1daeSBarry Smith   ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
883*5c6c1daeSBarry Smith 
884*5c6c1daeSBarry Smith   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
885*5c6c1daeSBarry Smith   /* makes call to MessageLoopThread to creat window and attach a thread */
886*5c6c1daeSBarry Smith   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
887*5c6c1daeSBarry Smith   CloseHandle(hThread);
888*5c6c1daeSBarry Smith   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
889*5c6c1daeSBarry Smith   CloseHandle(windraw->hReadyEvent);
890*5c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex,INFINITE);
891*5c6c1daeSBarry Smith 
892*5c6c1daeSBarry Smith   ierr                    = PetscNew(struct _p_WindowNode,&newnode);CHKERRQ(ierr);
893*5c6c1daeSBarry Smith   newnode->MouseListHead  = NULL;
894*5c6c1daeSBarry Smith   newnode->MouseListTail  = NULL;
895*5c6c1daeSBarry Smith   newnode->wnext          = WindowListHead;
896*5c6c1daeSBarry Smith   newnode->wprev          = NULL;
897*5c6c1daeSBarry Smith   newnode->hWnd           = windraw->hWnd;
898*5c6c1daeSBarry Smith   if (WindowListHead != NULL) {
899*5c6c1daeSBarry Smith     WindowListHead->wprev = newnode;
900*5c6c1daeSBarry Smith   }
901*5c6c1daeSBarry Smith   WindowListHead          = newnode;
902*5c6c1daeSBarry Smith   windraw->hdc            = GetDC(windraw->hWnd);
903*5c6c1daeSBarry Smith 
904*5c6c1daeSBarry Smith   windraw->stringheight   = 10;
905*5c6c1daeSBarry Smith   windraw->stringwidth    = 6;
906*5c6c1daeSBarry Smith   windraw->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
907*5c6c1daeSBarry Smith   windraw->pointdiameter  = 1;
908*5c6c1daeSBarry Smith   windraw->node           = newnode;
909*5c6c1daeSBarry Smith 
910*5c6c1daeSBarry Smith   windraw->x = draw->x;
911*5c6c1daeSBarry Smith   windraw->y = draw->y;
912*5c6c1daeSBarry Smith   windraw->w = newnode->bitwidth    = draw->w;
913*5c6c1daeSBarry Smith   windraw->h = newnode->bitheight   = draw->h;
914*5c6c1daeSBarry Smith 
915*5c6c1daeSBarry Smith   /* Create and initialize primary graphics buffer */
916*5c6c1daeSBarry Smith   newnode->Buffer = CreateCompatibleDC(windraw->hdc);
917*5c6c1daeSBarry Smith   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
918*5c6c1daeSBarry Smith   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
919*5c6c1daeSBarry Smith   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
920*5c6c1daeSBarry Smith 
921*5c6c1daeSBarry Smith   newnode->event          = CreateEvent(NULL,TRUE,FALSE,NULL);
922*5c6c1daeSBarry Smith   newnode->DoubleBuffered = PETSC_FALSE;
923*5c6c1daeSBarry Smith 
924*5c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd,windraw->hdc);
925*5c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
926*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
927*5c6c1daeSBarry Smith }
928*5c6c1daeSBarry Smith EXTERN_C_END
929*5c6c1daeSBarry Smith 
930*5c6c1daeSBarry Smith 
931*5c6c1daeSBarry Smith /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
932*5c6c1daeSBarry Smith    PURPOSE:  Processes messages for the main window.
933*5c6c1daeSBarry Smith    WM_COMMAND  - process the application menu
934*5c6c1daeSBarry Smith    WM_PAINT    - Paint the main window
935*5c6c1daeSBarry Smith    WM_DESTROY  - post a quit message and return */
936*5c6c1daeSBarry Smith 
937*5c6c1daeSBarry Smith #undef __FUNCT__
938*5c6c1daeSBarry Smith #define __FUNCT__ "PetscWndProc"
939*5c6c1daeSBarry Smith LRESULT  CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
940*5c6c1daeSBarry Smith {
941*5c6c1daeSBarry Smith   int         wmId, wmEvent;
942*5c6c1daeSBarry Smith 
943*5c6c1daeSBarry Smith   PetscFunctionBegin;
944*5c6c1daeSBarry Smith   switch (message) {
945*5c6c1daeSBarry Smith     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
946*5c6c1daeSBarry Smith     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
947*5c6c1daeSBarry Smith   case WM_COMMAND:
948*5c6c1daeSBarry Smith     wmId    = LOWORD(wParam);
949*5c6c1daeSBarry Smith     wmEvent = HIWORD(wParam);
950*5c6c1daeSBarry Smith     /* Parse the menu selections:*/
951*5c6c1daeSBarry Smith     switch (wmId) {
952*5c6c1daeSBarry Smith     case IDM_EXIT:
953*5c6c1daeSBarry Smith       DestroyWindow(hWnd);
954*5c6c1daeSBarry Smith       break;
955*5c6c1daeSBarry Smith     default:
956*5c6c1daeSBarry Smith       return DefWindowProc(hWnd, message, wParam, lParam);
957*5c6c1daeSBarry Smith     }
958*5c6c1daeSBarry Smith     break;
959*5c6c1daeSBarry Smith   case WM_LBUTTONUP:
960*5c6c1daeSBarry Smith     MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
961*5c6c1daeSBarry Smith     break;
962*5c6c1daeSBarry Smith   case WM_RBUTTONUP:
963*5c6c1daeSBarry Smith     MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
964*5c6c1daeSBarry Smith     break;
965*5c6c1daeSBarry Smith   case WM_MBUTTONUP:
966*5c6c1daeSBarry Smith     MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
967*5c6c1daeSBarry Smith     break;
968*5c6c1daeSBarry Smith   default:
969*5c6c1daeSBarry Smith     PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
970*5c6c1daeSBarry Smith   }
971*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
972*5c6c1daeSBarry Smith }
973*5c6c1daeSBarry Smith 
974*5c6c1daeSBarry Smith #undef __FUNCT__
975*5c6c1daeSBarry Smith #define __FUNCT__ "OnPaint_Win32"
976*5c6c1daeSBarry Smith static void OnPaint_Win32(HWND hWnd)
977*5c6c1daeSBarry Smith {
978*5c6c1daeSBarry Smith   PAINTSTRUCT ps;
979*5c6c1daeSBarry Smith   HDC         hdc;
980*5c6c1daeSBarry Smith   WindowNode  current = NULL;
981*5c6c1daeSBarry Smith 
982*5c6c1daeSBarry Smith   PetscFunctionBegin;
983*5c6c1daeSBarry Smith   InvalidateRect(hWnd,NULL,TRUE);
984*5c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
985*5c6c1daeSBarry Smith   current = WindowListHead;
986*5c6c1daeSBarry Smith   hdc     = BeginPaint(hWnd, &ps);
987*5c6c1daeSBarry Smith 
988*5c6c1daeSBarry Smith   while(current != NULL) {
989*5c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
990*5c6c1daeSBarry Smith       /* flushes primary buffer to window */
991*5c6c1daeSBarry Smith       BitBlt(hdc,
992*5c6c1daeSBarry Smith              0,0,
993*5c6c1daeSBarry Smith              GetDeviceCaps(hdc,HORZRES),
994*5c6c1daeSBarry Smith              GetDeviceCaps(hdc,VERTRES),
995*5c6c1daeSBarry Smith              current->Buffer,
996*5c6c1daeSBarry Smith              0,0,
997*5c6c1daeSBarry Smith              SRCCOPY);
998*5c6c1daeSBarry Smith 
999*5c6c1daeSBarry Smith       /* StretchBlt(hdc,
1000*5c6c1daeSBarry Smith         0,0,
1001*5c6c1daeSBarry Smith         w,h,
1002*5c6c1daeSBarry Smith         current->Buffer,
1003*5c6c1daeSBarry Smith         0,0,
1004*5c6c1daeSBarry Smith         current->bitwidth,
1005*5c6c1daeSBarry Smith         current->bitheight,
1006*5c6c1daeSBarry Smith         SRCCOPY); */
1007*5c6c1daeSBarry Smith       break;
1008*5c6c1daeSBarry Smith     }
1009*5c6c1daeSBarry Smith     current = current->wnext;
1010*5c6c1daeSBarry Smith   }
1011*5c6c1daeSBarry Smith   EndPaint(hWnd, &ps);
1012*5c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
1013*5c6c1daeSBarry Smith   PetscFunctionReturnVoid();
1014*5c6c1daeSBarry Smith }
1015*5c6c1daeSBarry Smith 
1016*5c6c1daeSBarry Smith #undef __FUNCT__
1017*5c6c1daeSBarry Smith #define __FUNCT__ "MouseRecord_Win32"
1018*5c6c1daeSBarry Smith static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
1019*5c6c1daeSBarry Smith {
1020*5c6c1daeSBarry Smith   /* Called by all three mouse button actions
1021*5c6c1daeSBarry Smith     Records needed mouse data in windows data structure */
1022*5c6c1daeSBarry Smith   WindowNode current = NULL;
1023*5c6c1daeSBarry Smith   MouseNode  newnode;
1024*5c6c1daeSBarry Smith   POINT      mousepos;
1025*5c6c1daeSBarry Smith   PetscErrorCode ierr;
1026*5c6c1daeSBarry Smith 
1027*5c6c1daeSBarry Smith   PetscFunctionBegin;
1028*5c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1029*5c6c1daeSBarry Smith   current = WindowListHead;
1030*5c6c1daeSBarry Smith   if (current->IsGetMouseOn == TRUE) {
1031*5c6c1daeSBarry Smith 
1032*5c6c1daeSBarry Smith     SetEvent(current->event);
1033*5c6c1daeSBarry Smith     while (current != NULL) {
1034*5c6c1daeSBarry Smith       if (current->hWnd == hWnd) {
1035*5c6c1daeSBarry Smith 
1036*5c6c1daeSBarry Smith         ierr            = PetscNew(struct _p_MouseNode,&newnode);CHKERRQ(ierr);
1037*5c6c1daeSBarry Smith         newnode->Button = button;
1038*5c6c1daeSBarry Smith         GetCursorPos(&mousepos);
1039*5c6c1daeSBarry Smith         newnode->user.x = mousepos.x;
1040*5c6c1daeSBarry Smith         newnode->user.y = mousepos.y;
1041*5c6c1daeSBarry Smith         ScreenToClient(hWnd,&mousepos);
1042*5c6c1daeSBarry Smith         newnode->phys.x = mousepos.x;
1043*5c6c1daeSBarry Smith         newnode->phys.y = mousepos.y;
1044*5c6c1daeSBarry Smith         if (!current->MouseListTail) {
1045*5c6c1daeSBarry Smith           current->MouseListHead = newnode;
1046*5c6c1daeSBarry Smith           current->MouseListTail = newnode;
1047*5c6c1daeSBarry Smith         } else {
1048*5c6c1daeSBarry Smith           current->MouseListTail->mnext = newnode;
1049*5c6c1daeSBarry Smith           current->MouseListTail = newnode;
1050*5c6c1daeSBarry Smith         }
1051*5c6c1daeSBarry Smith         newnode->mnext = NULL;
1052*5c6c1daeSBarry Smith 
1053*5c6c1daeSBarry Smith         break;
1054*5c6c1daeSBarry Smith       }
1055*5c6c1daeSBarry Smith       current = current->wnext;
1056*5c6c1daeSBarry Smith     }
1057*5c6c1daeSBarry Smith   }
1058*5c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
1059*5c6c1daeSBarry Smith   PetscFunctionReturn(0);
1060*5c6c1daeSBarry Smith }
1061*5c6c1daeSBarry Smith 
1062*5c6c1daeSBarry Smith #undef __FUNCT__
1063*5c6c1daeSBarry Smith #define __FUNCT__ "OnDestroy_Win32"
1064*5c6c1daeSBarry Smith static void OnDestroy_Win32(HWND hWnd)
1065*5c6c1daeSBarry Smith {
1066*5c6c1daeSBarry Smith   /* searches linked list of window data and frees corresponding memory */
1067*5c6c1daeSBarry Smith   WindowNode current;
1068*5c6c1daeSBarry Smith 
1069*5c6c1daeSBarry Smith   PetscFunctionBegin;
1070*5c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1071*5c6c1daeSBarry Smith   current = WindowListHead;
1072*5c6c1daeSBarry Smith 
1073*5c6c1daeSBarry Smith   SetEvent(current->event);
1074*5c6c1daeSBarry Smith   while (current != NULL) {
1075*5c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
1076*5c6c1daeSBarry Smith       if (current->wprev != NULL) {
1077*5c6c1daeSBarry Smith         current->wprev->wnext = current->wnext;
1078*5c6c1daeSBarry Smith       } else {
1079*5c6c1daeSBarry Smith         WindowListHead = current->wnext;
1080*5c6c1daeSBarry Smith       }
1081*5c6c1daeSBarry Smith       if (current->MouseListHead) {
1082*5c6c1daeSBarry Smith         deletemouselist_Win32(current);
1083*5c6c1daeSBarry Smith       } else {
1084*5c6c1daeSBarry Smith         PetscFree(current);
1085*5c6c1daeSBarry Smith       }
1086*5c6c1daeSBarry Smith       break;
1087*5c6c1daeSBarry Smith     }
1088*5c6c1daeSBarry Smith     current = current->wnext;
1089*5c6c1daeSBarry Smith   }
1090*5c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
1091*5c6c1daeSBarry Smith   PostQuitMessage(0);
1092*5c6c1daeSBarry Smith   PetscFunctionReturnVoid();
1093*5c6c1daeSBarry Smith }
1094