xref: /petsc/src/sys/classes/draw/impls/win32/win32draw.c (revision f9baa8adbc10b227db3e6cd97ca29eb7b9f9837e)
15c6c1daeSBarry Smith 
25c6c1daeSBarry Smith #include <petscsys.h>
3af0996ceSBarry Smith #include <petsc/private/drawimpl.h>
478ac5f8bSSatish Balay #include <../src/sys/classes/draw/impls/win32/win32draw.h>
55c6c1daeSBarry Smith 
65c6c1daeSBarry Smith #define IDC_FOUR       109
75c6c1daeSBarry Smith #define IDI_FOUR       107
85c6c1daeSBarry Smith #define IDM_EXIT       105
95c6c1daeSBarry Smith #define IDR_POPUP      103
105c6c1daeSBarry Smith #define MAX_LOADSTRING 100
115c6c1daeSBarry Smith 
125c6c1daeSBarry Smith #if !defined(SelectPen)
135c6c1daeSBarry Smith #define SelectPen(hdc, hpen)      ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen)))
145c6c1daeSBarry Smith #endif
155c6c1daeSBarry Smith #if !defined(SelectFont)
165c6c1daeSBarry Smith #define SelectFont(hdc,hfont)    ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
175c6c1daeSBarry Smith #endif
185c6c1daeSBarry Smith #if !defined(SelectBrush)
195c6c1daeSBarry Smith #define SelectBrush(hdc,hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush)))
205c6c1daeSBarry Smith #endif
215c6c1daeSBarry Smith #if !defined(GetStockBrush)
225c6c1daeSBarry Smith #define GetStockBrush(i)      ((HBRUSH)GetStockObject(i))
235c6c1daeSBarry Smith #endif
245c6c1daeSBarry Smith 
255c6c1daeSBarry Smith #define XTRANS(draw,win,x) \
265c6c1daeSBarry Smith     (int)(((win)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)*         \
275c6c1daeSBarry Smith                             ((draw)->port_xr - (draw)->port_xl))/        \
285c6c1daeSBarry Smith                             ((draw)->coor_xr - (draw)->coor_xl))))
295c6c1daeSBarry Smith #define YTRANS(draw,win,y) \
305c6c1daeSBarry Smith     (int)(((win)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)*     \
315c6c1daeSBarry Smith                                 ((draw)->port_yr - (draw)->port_yl))/    \
325c6c1daeSBarry Smith                                 ((draw)->coor_yr - (draw)->coor_yl))))
335c6c1daeSBarry Smith 
345c6c1daeSBarry Smith HINSTANCE  hInst;
355c6c1daeSBarry Smith HANDLE     g_hWindowListMutex = NULL;
365c6c1daeSBarry Smith WindowNode WindowListHead     = NULL;
375c6c1daeSBarry Smith 
385c6c1daeSBarry Smith /* Hard coded color hue until hue.c works with this */
395c6c1daeSBarry 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};
405c6c1daeSBarry 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};
415c6c1daeSBarry 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};
425c6c1daeSBarry Smith 
435c6c1daeSBarry Smith /* Foward declarations of functions included in this code module: */
445c6c1daeSBarry Smith LRESULT CALLBACK PetscWndProc(HWND, UINT, WPARAM, LPARAM);
455c6c1daeSBarry Smith static PetscErrorCode TranslateColor_Win32(PetscDraw,int);
465c6c1daeSBarry Smith static PetscErrorCode AverageColorRectangle_Win32(PetscDraw,int,int,int,int);
475c6c1daeSBarry Smith static PetscErrorCode AverageColorTriangle_Win32(PetscDraw,int,int,int);
485c6c1daeSBarry Smith static PetscErrorCode deletemouselist_Win32(WindowNode);
495c6c1daeSBarry Smith static void OnPaint_Win32(HWND);
505c6c1daeSBarry Smith static void OnDestroy_Win32(HWND);
515c6c1daeSBarry Smith static PetscErrorCode MouseRecord_Win32(HWND,PetscDrawButton);
525c6c1daeSBarry Smith static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw,PetscDraw*);
535c6c1daeSBarry Smith 
545c6c1daeSBarry Smith static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
555c6c1daeSBarry Smith {
565c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
575c6c1daeSBarry Smith   HDC             hdc      = GetDC(windraw->hWnd);
585c6c1daeSBarry Smith 
595c6c1daeSBarry Smith   PetscFunctionBegin;
605c6c1daeSBarry Smith   windraw->node->DoubleBuffer    = CreateCompatibleDC(hdc);
615c6c1daeSBarry Smith   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
625c6c1daeSBarry Smith   windraw->node->dbstore         = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
635c6c1daeSBarry Smith   /* Fill background of second buffer */
645c6c1daeSBarry Smith   ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
655c6c1daeSBarry Smith   /* Copy current buffer into seconf buffer and set window data as double buffered */
66be332245SKarl Rupp   BitBlt(windraw->node->DoubleBuffer,0,0,windraw->w,windraw->h,
67be332245SKarl Rupp          windraw->node->Buffer,0,0, SRCCOPY);
685c6c1daeSBarry Smith 
695c6c1daeSBarry Smith   windraw->node->DoubleBuffered = PETSC_TRUE;
705c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd,hdc);
715c6c1daeSBarry Smith   PetscFunctionReturn(0);
725c6c1daeSBarry Smith }
735c6c1daeSBarry Smith 
745c6c1daeSBarry Smith static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
755c6c1daeSBarry Smith {
765c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
775c6c1daeSBarry Smith   HDC             hdc      = GetDC(windraw->hWnd);
785c6c1daeSBarry Smith 
795c6c1daeSBarry Smith   PetscFunctionBegin;
805c6c1daeSBarry Smith   /* flush double buffer into primary buffer */
81be332245SKarl Rupp   BitBlt(windraw->node->Buffer,0,0,windraw->w,windraw->h,
82be332245SKarl Rupp          windraw->node->DoubleBuffer,0,0,SRCCOPY);
835c6c1daeSBarry Smith   /* flush double buffer into window */
84be332245SKarl Rupp   BitBlt(hdc,0,0,windraw->w,windraw->h,
85be332245SKarl Rupp          windraw->node->DoubleBuffer, 0,0,SRCCOPY);
865c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd,hdc);
875c6c1daeSBarry Smith   PetscFunctionReturn(0);
885c6c1daeSBarry Smith }
895c6c1daeSBarry Smith 
905c6c1daeSBarry Smith static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
915c6c1daeSBarry Smith {
925c6c1daeSBarry Smith   /* Called upon window close. Frees memory of linked list of stored mouse commands */
935c6c1daeSBarry Smith   MouseNode node;
945c6c1daeSBarry Smith 
956c4ed002SBarry Smith   while (deletelist->MouseListHead) {
965c6c1daeSBarry Smith     node = deletelist->MouseListHead;
976c4ed002SBarry Smith     if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
985c6c1daeSBarry Smith     PetscFree(node);
995c6c1daeSBarry Smith   }
1005c6c1daeSBarry Smith   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
1016c4ed002SBarry Smith   if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
1026c4ed002SBarry Smith   if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
1035c6c1daeSBarry Smith   PetscFree(deletelist);
1045c6c1daeSBarry Smith   return 0;
1055c6c1daeSBarry Smith }
1065c6c1daeSBarry Smith 
1075c6c1daeSBarry Smith static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
1085c6c1daeSBarry Smith {
1095c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
1105c6c1daeSBarry Smith   WindowNode      current;
1115c6c1daeSBarry Smith   MouseNode       node=0;
1125c6c1daeSBarry Smith 
1135c6c1daeSBarry Smith   PetscFunctionBegin;
1145c6c1daeSBarry Smith   /* Make sure no other code is using the linked list at this moment */
1155c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1165c6c1daeSBarry Smith   /* Look for the node that matches the window you are using */
1175c6c1daeSBarry Smith   current = WindowListHead;
1186c4ed002SBarry Smith   while (current) {
1195c6c1daeSBarry Smith     if (current->hWnd == windraw->hWnd) {
1205c6c1daeSBarry Smith       current->IsGetMouseOn = TRUE;
1215c6c1daeSBarry Smith       break;
122a297a907SKarl Rupp     } else current = current->wnext;
1235c6c1daeSBarry Smith   }
124a5b23f4aSJose E. Roman   /* If no actions have occurred, wait for one */
1255c6c1daeSBarry Smith   node = current->MouseListHead;
1265c6c1daeSBarry Smith   if (!node) {
1275c6c1daeSBarry Smith     ReleaseMutex(g_hWindowListMutex);
1285c6c1daeSBarry Smith     WaitForSingleObject(current->event, INFINITE);
1295c6c1daeSBarry Smith     WaitForSingleObject(g_hWindowListMutex, INFINITE);
1305c6c1daeSBarry Smith   }
1315c6c1daeSBarry Smith   /* once we have the information, assign the pointers to it */
1325c6c1daeSBarry Smith   *button = current->MouseListHead->Button;
1335c6c1daeSBarry Smith   *x_user = current->MouseListHead->user.x;
1345c6c1daeSBarry Smith   *y_user = current->MouseListHead->user.y;
1355c6c1daeSBarry Smith   /* optional arguments */
1365c6c1daeSBarry Smith   if (x_phys) *x_phys = current->MouseListHead->phys.x;
1375c6c1daeSBarry Smith   if (y_phys) *y_phys = current->MouseListHead->phys.y;
1385c6c1daeSBarry Smith   /* remove set of information from sub linked-list, delete the node */
1395c6c1daeSBarry Smith   current->MouseListHead = current->MouseListHead->mnext;
1405c6c1daeSBarry Smith   if (!current->MouseListHead) {
1415c6c1daeSBarry Smith     ResetEvent(current->event);
1425c6c1daeSBarry Smith     current->MouseListTail = NULL;
1435c6c1daeSBarry Smith   }
1445c6c1daeSBarry Smith   if (node) PetscFree(node);
1455c6c1daeSBarry Smith 
1465c6c1daeSBarry Smith   /* Release mutex so that  other code can use
1475c6c1daeSBarry Smith      the linked list now that we are done with it */
1485c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
1495c6c1daeSBarry Smith   PetscFunctionReturn(0);
1505c6c1daeSBarry Smith }
1515c6c1daeSBarry Smith 
1525c6c1daeSBarry Smith static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
1535c6c1daeSBarry Smith {
1545c6c1daeSBarry Smith   PetscFunctionBegin;
1555c6c1daeSBarry Smith   PetscSleep(draw->pause);
1565c6c1daeSBarry Smith   PetscFunctionReturn(0);
1575c6c1daeSBarry Smith }
1585c6c1daeSBarry Smith 
1595c6c1daeSBarry Smith static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
1605c6c1daeSBarry Smith {
1615c6c1daeSBarry Smith   /* Maps single color value into the RGB colors in our tables */
1625c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
1635c6c1daeSBarry Smith   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
1645c6c1daeSBarry Smith   return 0;
1655c6c1daeSBarry Smith }
1665c6c1daeSBarry Smith 
1675c6c1daeSBarry Smith static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
1685c6c1daeSBarry Smith {
1695c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
1705c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
1715c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
1725c6c1daeSBarry Smith   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
1735c6c1daeSBarry Smith                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
1745c6c1daeSBarry Smith                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
1755c6c1daeSBarry Smith   return 0;
1765c6c1daeSBarry Smith }
1775c6c1daeSBarry Smith 
1785c6c1daeSBarry Smith static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
1795c6c1daeSBarry Smith {
1805c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
1815c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
1825c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
1835c6c1daeSBarry Smith   windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
1845c6c1daeSBarry Smith                               (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
1855c6c1daeSBarry Smith                               (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
1865c6c1daeSBarry Smith   return 0;
1875c6c1daeSBarry Smith }
1885c6c1daeSBarry Smith 
1895c6c1daeSBarry Smith static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
1905c6c1daeSBarry Smith {
1915c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
1925c6c1daeSBarry Smith   HBRUSH          hbrush;
1935c6c1daeSBarry Smith   RECT            rect;
1945c6c1daeSBarry Smith   int             x1,yone,x2,y2;
1955c6c1daeSBarry Smith   HDC             hdc;
1965c6c1daeSBarry Smith 
1975c6c1daeSBarry Smith   PetscFunctionBegin;
1985c6c1daeSBarry Smith   x1   = XTRANS(draw,windraw,xl);
1995c6c1daeSBarry Smith   x2   = XTRANS(draw,windraw,xr);
2005c6c1daeSBarry Smith   yone = YTRANS(draw,windraw,yl);
2015c6c1daeSBarry Smith   y2   = YTRANS(draw,windraw,yr);
2025c6c1daeSBarry Smith   SetRect(&rect,x1,y2,x2,yone);
203a297a907SKarl Rupp   if (c1==c2 && c2==c3 && c3==c4) TranslateColor_Win32(draw,c1);
204a297a907SKarl Rupp   else AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
2055c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
2065c6c1daeSBarry Smith 
207a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
208a297a907SKarl Rupp   else                               hdc = windraw->node->Buffer;
209a297a907SKarl Rupp 
2105c6c1daeSBarry Smith   FillRect(hdc,&rect,hbrush);
2115c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
2125c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
2135c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2145c6c1daeSBarry Smith   PetscFunctionReturn(0);
2155c6c1daeSBarry Smith }
2165c6c1daeSBarry Smith 
2175c6c1daeSBarry Smith static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
2185c6c1daeSBarry Smith {
2195c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
2205c6c1daeSBarry Smith   HPEN            hpen;
2215c6c1daeSBarry Smith   int             x1,yone,x2,y2;
2225c6c1daeSBarry Smith   HDC             hdc;
2235c6c1daeSBarry Smith 
2245c6c1daeSBarry Smith   PetscFunctionBegin;
2255c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
2265c6c1daeSBarry Smith   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
2275c6c1daeSBarry Smith   yone = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
2285c6c1daeSBarry Smith   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
229a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
230a297a907SKarl Rupp   else                               hdc = windraw->node->Buffer;
231a297a907SKarl Rupp 
2325c6c1daeSBarry Smith   SelectPen(hdc,hpen);
2335c6c1daeSBarry Smith   MoveToEx(hdc,x1,yone,NULL);
2345c6c1daeSBarry Smith   LineTo(hdc,x2,y2);
2355c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
2365c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
2375c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2385c6c1daeSBarry Smith   PetscFunctionReturn(0);
2395c6c1daeSBarry Smith }
2405c6c1daeSBarry Smith 
2415c6c1daeSBarry Smith static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
2425c6c1daeSBarry Smith {
2435c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
2445c6c1daeSBarry Smith   int             averagesize,finalwidth;
2455c6c1daeSBarry Smith   RECT            rect;
2465c6c1daeSBarry Smith 
2475c6c1daeSBarry Smith   PetscFunctionBegin;
2485c6c1daeSBarry Smith   GetClientRect(windraw->hWnd,&rect);
2495c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
25077b4d14cSPeter Brune   finalwidth  = (int)PetscFloorReal(averagesize*width);
251a297a907SKarl Rupp   if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */
252a297a907SKarl Rupp 
2535c6c1daeSBarry Smith   windraw->linewidth = finalwidth;
2545c6c1daeSBarry Smith   PetscFunctionReturn(0);
2555c6c1daeSBarry Smith }
2565c6c1daeSBarry Smith 
2575c6c1daeSBarry Smith static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
2585c6c1daeSBarry Smith {
2595c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
2605c6c1daeSBarry Smith 
2615c6c1daeSBarry Smith   PetscFunctionBegin;
2625c6c1daeSBarry Smith   *width = (PetscReal)windraw->linewidth;
2635c6c1daeSBarry Smith   PetscFunctionReturn(0);
2645c6c1daeSBarry Smith }
2655c6c1daeSBarry Smith 
2665c6c1daeSBarry Smith static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
2675c6c1daeSBarry Smith {
2685c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
2695c6c1daeSBarry Smith   HBRUSH          hbrush;
2705c6c1daeSBarry Smith   HRGN            hrgn;
2715c6c1daeSBarry Smith   int             radius;
2725c6c1daeSBarry Smith   int             x1,yone;
2735c6c1daeSBarry Smith   HDC             hdc;
2745c6c1daeSBarry Smith 
2755c6c1daeSBarry Smith   PetscFunctionBegin;
2765c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
2775c6c1daeSBarry Smith   x1     = XTRANS(draw,windraw,x);
2785c6c1daeSBarry Smith   yone   = YTRANS(draw,windraw,y);
2795c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
280a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
281a297a907SKarl Rupp   else                               hdc = windraw->node->Buffer;
282a297a907SKarl Rupp 
2835c6c1daeSBarry Smith   /* desired size is one logical pixel so just turn it on */
284a297a907SKarl Rupp   if (windraw->pointdiameter == 1) SetPixelV(hdc,x1,yone,windraw->currentcolor);
285a297a907SKarl Rupp   else {
2865c6c1daeSBarry Smith     /* draw point around position determined */
2875c6c1daeSBarry Smith     radius = windraw->pointdiameter/2; /* integer division */
2885c6c1daeSBarry Smith     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
2895c6c1daeSBarry Smith     FillRgn(hdc,hrgn,hbrush);
2905c6c1daeSBarry Smith   }
2915c6c1daeSBarry Smith   /* Forces a WM_PAINT and erases background */
2925c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
2935c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2945c6c1daeSBarry Smith   PetscFunctionReturn(0);
2955c6c1daeSBarry Smith }
2965c6c1daeSBarry Smith 
2975c6c1daeSBarry Smith static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
2985c6c1daeSBarry Smith {
2995c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
3005c6c1daeSBarry Smith   int             averagesize,diameter;
3015c6c1daeSBarry Smith   RECT            rect;
3025c6c1daeSBarry Smith 
3035c6c1daeSBarry Smith   PetscFunctionBegin;
3045c6c1daeSBarry Smith   GetClientRect(windraw->hWnd,&rect);
3055c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
30677b4d14cSPeter Brune   diameter    = (int)PetscFloorReal(averagesize*width);
3075c6c1daeSBarry Smith   if (diameter < 1) diameter = 1;
3085c6c1daeSBarry Smith   windraw->pointdiameter = diameter;
3095c6c1daeSBarry Smith   PetscFunctionReturn(0);
3105c6c1daeSBarry Smith }
3115c6c1daeSBarry Smith 
3125c6c1daeSBarry Smith static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
3135c6c1daeSBarry Smith {
3145c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
3155c6c1daeSBarry Smith   RECT            r;
3165c6c1daeSBarry Smith   HFONT           hfont;
3175c6c1daeSBarry Smith   LOGFONT         logfont;
3185c6c1daeSBarry Smith   int             x1,yone;
3195c6c1daeSBarry Smith   HDC             hdc;
3205c6c1daeSBarry Smith 
3215c6c1daeSBarry Smith   PetscFunctionBegin;
3225c6c1daeSBarry Smith   x1       = XTRANS(draw,windraw,x);
3235c6c1daeSBarry Smith   yone     = YTRANS(draw,windraw,y);
3245c6c1daeSBarry Smith   r.bottom = yone;
3255c6c1daeSBarry Smith   r.left   = x1;
3265c6c1daeSBarry Smith   r.right  = x1 + 1;
3275c6c1daeSBarry Smith   r.top    = yone + 1;
328a297a907SKarl Rupp 
3295c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3305c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3315c6c1daeSBarry Smith   logfont.lfEscapement     = 0;
3325c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3335c6c1daeSBarry Smith   logfont.lfCharSet        = 0;
3345c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3355c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3365c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3375c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3385c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3395c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3405c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3415c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
342a297a907SKarl Rupp 
3435c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3445c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
345a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
346a297a907SKarl Rupp   else                               hdc = windraw->node->Buffer;
347a297a907SKarl Rupp 
3485c6c1daeSBarry Smith   SelectFont(hdc,hfont);
3495c6c1daeSBarry Smith   SetTextColor(hdc,windraw->currentcolor);
3505c6c1daeSBarry Smith   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
3515c6c1daeSBarry Smith   DeleteObject(hfont);
3525c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3535c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
3545c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
3555c6c1daeSBarry Smith   PetscFunctionReturn(0);
3565c6c1daeSBarry Smith }
3575c6c1daeSBarry Smith 
3585c6c1daeSBarry Smith static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
3595c6c1daeSBarry Smith {
3605c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
3615c6c1daeSBarry Smith   RECT            r;
3625c6c1daeSBarry Smith   HFONT           hfont;
3635c6c1daeSBarry Smith   LOGFONT         logfont;
3645c6c1daeSBarry Smith   int             x1,yone;
3655c6c1daeSBarry Smith   HDC             hdc;
3665c6c1daeSBarry Smith 
3675c6c1daeSBarry Smith   PetscFunctionBegin;
3685c6c1daeSBarry Smith   x1       = XTRANS(draw,windraw,x);
3695c6c1daeSBarry Smith   yone     = YTRANS(draw,windraw,y);
3705c6c1daeSBarry Smith   r.left   = x1;
3715c6c1daeSBarry Smith   r.bottom = yone + 30;
3725c6c1daeSBarry Smith   r.right  = x1 + 1;
3735c6c1daeSBarry Smith   r.top    = yone - 30;
374a297a907SKarl Rupp 
3755c6c1daeSBarry Smith   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
3765c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3775c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3785c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3795c6c1daeSBarry Smith   logfont.lfCharSet        = DEFAULT_CHARSET;
3805c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3815c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3825c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3835c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3845c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3855c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3865c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3875c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
388a297a907SKarl Rupp 
3895c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3905c6c1daeSBarry Smith   TranslateColor_Win32(draw,color);
391a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
392a297a907SKarl Rupp   else                               hdc = windraw->node->Buffer;
393a297a907SKarl Rupp 
3945c6c1daeSBarry Smith   SelectFont(hdc,hfont);
3955c6c1daeSBarry Smith   SetTextColor(hdc,windraw->currentcolor);
3965c6c1daeSBarry Smith   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE);
3975c6c1daeSBarry Smith   DeleteObject(hfont);
3985c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3995c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
4005c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
4015c6c1daeSBarry Smith   PetscFunctionReturn(0);
4025c6c1daeSBarry Smith }
4035c6c1daeSBarry Smith 
4045c6c1daeSBarry Smith static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
4055c6c1daeSBarry Smith {
4065c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
4075c6c1daeSBarry Smith   int             w,h;
4085c6c1daeSBarry Smith 
4095c6c1daeSBarry Smith   PetscFunctionBegin;
4105c6c1daeSBarry Smith   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
4115c6c1daeSBarry Smith   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
4125c6c1daeSBarry Smith   if (h < 1) h = 1;
4135c6c1daeSBarry Smith   if (w < 1) w = 1;
4145c6c1daeSBarry Smith   windraw->stringheight = h;
4155c6c1daeSBarry Smith   windraw->stringwidth  = w;
4165c6c1daeSBarry Smith   PetscFunctionReturn(0);
4175c6c1daeSBarry Smith }
4185c6c1daeSBarry Smith static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
4195c6c1daeSBarry Smith {
4205c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
4215c6c1daeSBarry Smith   double          scaleX   = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
4225c6c1daeSBarry Smith   double          scaleY   = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
4235c6c1daeSBarry Smith 
4245c6c1daeSBarry Smith   PetscFunctionBegin;
4254a5237bfSSatish Balay   if (height) *height = (double)windraw->stringheight*scaleY;
4264a5237bfSSatish Balay   if (width)  *width  = (double)windraw->stringwidth*scaleX;
4275c6c1daeSBarry Smith   PetscFunctionReturn(0);
4285c6c1daeSBarry Smith }
4295c6c1daeSBarry Smith 
4305c6c1daeSBarry Smith static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
4315c6c1daeSBarry Smith {
4325c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
4335c6c1daeSBarry Smith   RECT            r;
4345c6c1daeSBarry Smith 
4355c6c1daeSBarry Smith   PetscFunctionBegin;
4365c6c1daeSBarry Smith   GetWindowRect(windraw->hWnd,&r);
4375c6c1daeSBarry Smith   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
4385c6c1daeSBarry Smith   /* set all variable dealing with window dimensions */
4395c6c1daeSBarry Smith   windraw->node->bitheight = windraw->h = draw->h = h;
4405c6c1daeSBarry Smith   windraw->node->bitwidth  = windraw->w = draw->w = w;
4415c6c1daeSBarry Smith   /* set up graphic buffers with the new size of window */
4425c6c1daeSBarry Smith   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
443a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
4445c6c1daeSBarry Smith   windraw->haveresized = PETSC_TRUE;
4455c6c1daeSBarry Smith   PetscFunctionReturn(0);
4465c6c1daeSBarry Smith }
4475c6c1daeSBarry Smith 
4485c6c1daeSBarry Smith static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
4495c6c1daeSBarry Smith {
4505c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
4515c6c1daeSBarry Smith 
4525c6c1daeSBarry Smith   PetscFunctionBegin;
453a297a907SKarl Rupp   if (windraw->haveresized == 1) PetscFunctionReturn(1);
454a297a907SKarl Rupp   else PetscFunctionReturn(0);
4555c6c1daeSBarry Smith }
4565c6c1daeSBarry Smith 
4575c6c1daeSBarry Smith static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
4585c6c1daeSBarry Smith {
4595c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
4605c6c1daeSBarry Smith 
4615c6c1daeSBarry Smith   PetscFunctionBegin;
4625c6c1daeSBarry Smith   SetWindowText(windraw->hWnd,title);
4635c6c1daeSBarry Smith   PetscFunctionReturn(0);
4645c6c1daeSBarry Smith }
4655c6c1daeSBarry Smith 
4665c6c1daeSBarry Smith static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
4675c6c1daeSBarry Smith {
4685c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
4695c6c1daeSBarry Smith 
4705c6c1daeSBarry Smith   PetscFunctionBegin;
4715c6c1daeSBarry Smith   /* clear primary buffer */
4725c6c1daeSBarry Smith   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
4735c6c1daeSBarry Smith   /* if exists clear secondary buffer */
474a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
475a297a907SKarl Rupp 
4765c6c1daeSBarry Smith   /* force WM_PAINT message so cleared buffer will show */
4775c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
4785c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
4795c6c1daeSBarry Smith   PetscFunctionReturn(0);
4805c6c1daeSBarry Smith }
4815c6c1daeSBarry Smith 
4825c6c1daeSBarry Smith static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
4835c6c1daeSBarry Smith                                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
4845c6c1daeSBarry Smith {
4855c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
4865c6c1daeSBarry Smith   HBRUSH          hbrush;
4875c6c1daeSBarry Smith   HPEN            hpen;
4885c6c1daeSBarry Smith   int             p1x,p1y,p2x,p2y,p3x,p3y;
4895c6c1daeSBarry Smith   HDC             bit;
4905c6c1daeSBarry Smith 
4915c6c1daeSBarry Smith   PetscFunctionBegin;
4925c6c1daeSBarry Smith   AverageColorTriangle_Win32(draw,c1,c2,c3);
4935c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
4945c6c1daeSBarry Smith   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
4955c6c1daeSBarry Smith   p1x    = XTRANS(draw,windraw,x1);
4965c6c1daeSBarry Smith   p2x    = XTRANS(draw,windraw,x2);
4975c6c1daeSBarry Smith   p3x    = XTRANS(draw,windraw,x3);
4985c6c1daeSBarry Smith   p1y    = YTRANS(draw,windraw,yone);
4995c6c1daeSBarry Smith   p2y    = YTRANS(draw,windraw,y2);
5005c6c1daeSBarry Smith   p3y    = YTRANS(draw,windraw,y3);
5015c6c1daeSBarry Smith 
502a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
503a297a907SKarl Rupp   else                               bit = windraw->node->Buffer;
504a297a907SKarl Rupp 
5055c6c1daeSBarry Smith   BeginPath(bit);
5065c6c1daeSBarry Smith   MoveToEx(bit,p1x,p1y,NULL);
5075c6c1daeSBarry Smith   LineTo(bit,p2x,p2y);
5085c6c1daeSBarry Smith   LineTo(bit,p3x,p3y);
5095c6c1daeSBarry Smith   LineTo(bit,p1x,p1y);
5105c6c1daeSBarry Smith   EndPath(bit);
5115c6c1daeSBarry Smith   SelectPen(bit,hpen);
5125c6c1daeSBarry Smith   SelectBrush(bit,hbrush);
5135c6c1daeSBarry Smith   StrokeAndFillPath(bit);
5145c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
5155c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd,NULL,TRUE);
5165c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
5175c6c1daeSBarry Smith   PetscFunctionReturn(0);
5185c6c1daeSBarry Smith }
5195c6c1daeSBarry Smith 
5205c6c1daeSBarry Smith void PopMessageLoopThread_Win32(PetscDraw popdraw)
5215c6c1daeSBarry Smith {
5225c6c1daeSBarry Smith   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
5235c6c1daeSBarry Smith   MSG             msg;
5245c6c1daeSBarry Smith   HWND            hWnd = NULL;
525fad2a674SVolker   const char      PopClassName[] = "PETSc Window Pop Class";
5265c6c1daeSBarry Smith   RECT            r;
5275c6c1daeSBarry Smith   int             width,height;
5285c6c1daeSBarry Smith   WNDCLASSEX      myclass;
5295c6c1daeSBarry Smith   LPVOID          lpMsgBuf;
5305c6c1daeSBarry Smith 
5315c6c1daeSBarry Smith   PetscFunctionBegin;
5325c6c1daeSBarry Smith   /* initialize window class parameters */
5335c6c1daeSBarry Smith   myclass.cbSize        = sizeof(WNDCLASSEX);
5345c6c1daeSBarry Smith   myclass.style         = CS_OWNDC;
5355c6c1daeSBarry Smith   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
5365c6c1daeSBarry Smith   myclass.cbClsExtra    = 0;
5375c6c1daeSBarry Smith   myclass.cbWndExtra    = 0;
5385c6c1daeSBarry Smith   myclass.hInstance     = NULL;
5395c6c1daeSBarry Smith   myclass.hIcon         = NULL;
5405c6c1daeSBarry Smith   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
5415c6c1daeSBarry Smith   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
5425c6c1daeSBarry Smith   myclass.lpszMenuName  = NULL;
5435c6c1daeSBarry Smith   myclass.lpszClassName = PopClassName;
5445c6c1daeSBarry Smith   myclass.hIconSm       = NULL;
5455c6c1daeSBarry Smith 
5465c6c1daeSBarry Smith   RegisterClassEx(&myclass);
5475c6c1daeSBarry Smith 
5485c6c1daeSBarry Smith   SetRect(&r,0,0,450,450);
5495c6c1daeSBarry Smith 
5505c6c1daeSBarry Smith   width  = (r.right - r.left) / 3;
5515c6c1daeSBarry Smith   height = (r.bottom - r.top) / 3;
5525c6c1daeSBarry Smith 
5535c6c1daeSBarry Smith   hWnd = CreateWindowEx(0,
5545c6c1daeSBarry Smith                         PopClassName,
5555c6c1daeSBarry Smith                         NULL,
5565c6c1daeSBarry Smith                         WS_POPUPWINDOW | WS_CAPTION,
5575c6c1daeSBarry Smith                         0,0,
5585c6c1daeSBarry Smith                         width,height,
5595c6c1daeSBarry Smith                         NULL,
5605c6c1daeSBarry Smith                         NULL,
5615c6c1daeSBarry Smith                         hInst,
5625c6c1daeSBarry Smith                         NULL);
5635c6c1daeSBarry Smith   pop->x = 0;
5645c6c1daeSBarry Smith   pop->y = 0;
5655c6c1daeSBarry Smith   pop->w = width;
5665c6c1daeSBarry Smith   pop->h = height;
5675c6c1daeSBarry Smith 
5685c6c1daeSBarry Smith   if (!hWnd) {
569fad2a674SVolker     lpMsgBuf = (LPVOID)"Window Not Successfully Created";
5705c6c1daeSBarry Smith     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
5715c6c1daeSBarry Smith     LocalFree(lpMsgBuf);
5725c6c1daeSBarry Smith     exit(0);
5735c6c1daeSBarry Smith   }
5745c6c1daeSBarry Smith   pop->hWnd = hWnd;
5755c6c1daeSBarry Smith   /* display and update new popup window */
5765c6c1daeSBarry Smith   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
5775c6c1daeSBarry Smith   UpdateWindow(pop->hWnd);
5785c6c1daeSBarry Smith   SetEvent(pop->hReadyEvent);
5795c6c1daeSBarry Smith 
5805c6c1daeSBarry Smith   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
5815c6c1daeSBarry Smith     TranslateMessage(&msg);
5825c6c1daeSBarry Smith     DispatchMessage(&msg);
5835c6c1daeSBarry Smith   }
5845c6c1daeSBarry Smith   PetscFunctionReturnVoid();
5855c6c1daeSBarry Smith }
5865c6c1daeSBarry Smith 
5875c6c1daeSBarry Smith static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
5885c6c1daeSBarry Smith {
5895c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
5905c6c1daeSBarry Smith 
5915c6c1daeSBarry Smith   PetscFunctionBegin;
5925c6c1daeSBarry Smith   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
59350c74209SLisandro Dalcin   PetscFree(draw->data);
5945c6c1daeSBarry Smith   PetscFunctionReturn(0);
5955c6c1daeSBarry Smith }
5965c6c1daeSBarry Smith 
5975c6c1daeSBarry Smith void MessageLoopThread_Win32(PetscDraw draw)
5985c6c1daeSBarry Smith {
5995c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
6005c6c1daeSBarry Smith   MSG             msg;
6015c6c1daeSBarry Smith   HWND            hWnd = NULL;
602fad2a674SVolker   const char      classname[] = "PETSc Window Class";
6035c6c1daeSBarry Smith   WNDCLASSEX      wclass;
6045c6c1daeSBarry Smith   LPVOID          lpMsgBuf;
6055c6c1daeSBarry Smith 
6065c6c1daeSBarry Smith   /* initialize window class parameters */
6075c6c1daeSBarry Smith   wclass.cbSize        = sizeof(WNDCLASSEX);
6085c6c1daeSBarry Smith   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
6095c6c1daeSBarry Smith   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
6105c6c1daeSBarry Smith   wclass.cbClsExtra    = 0;
6115c6c1daeSBarry Smith   wclass.cbWndExtra    = 0;
6125c6c1daeSBarry Smith   wclass.hInstance     = NULL;
6135c6c1daeSBarry Smith   wclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
6145c6c1daeSBarry Smith   wclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
6155c6c1daeSBarry Smith   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
6165c6c1daeSBarry Smith   wclass.lpszMenuName  = NULL;
6175c6c1daeSBarry Smith   wclass.lpszClassName = classname;
6185c6c1daeSBarry Smith   wclass.hIconSm       = NULL;
6195c6c1daeSBarry Smith 
6205c6c1daeSBarry Smith   RegisterClassEx(&wclass);
6215c6c1daeSBarry Smith 
6225c6c1daeSBarry Smith   hWnd = CreateWindowEx(0,
6235c6c1daeSBarry Smith                         classname,
6245c6c1daeSBarry Smith                         NULL,
6255c6c1daeSBarry Smith                         WS_OVERLAPPEDWINDOW,
6265c6c1daeSBarry Smith                         draw->x,
6275c6c1daeSBarry Smith                         draw->y,
6285c6c1daeSBarry Smith                         draw->w,
6295c6c1daeSBarry Smith                         draw->h,
6305c6c1daeSBarry Smith                         NULL,
6315c6c1daeSBarry Smith                         NULL,
6325c6c1daeSBarry Smith                         hInst,
6335c6c1daeSBarry Smith                         NULL);
6345c6c1daeSBarry Smith 
6355c6c1daeSBarry Smith   if (!hWnd) {
636fad2a674SVolker     lpMsgBuf = (LPVOID)"Window Not Successfully Created";
6375c6c1daeSBarry Smith     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
6385c6c1daeSBarry Smith     LocalFree(lpMsgBuf);
6395c6c1daeSBarry Smith     exit(0);
6405c6c1daeSBarry Smith   }
6415c6c1daeSBarry Smith   windraw->hWnd = hWnd;
6425c6c1daeSBarry Smith   /* display and update new window */
6435c6c1daeSBarry Smith   ShowWindow(hWnd,SW_SHOWNORMAL);
6445c6c1daeSBarry Smith   UpdateWindow(hWnd);
6455c6c1daeSBarry Smith   SetEvent(windraw->hReadyEvent);
6465c6c1daeSBarry Smith 
6475c6c1daeSBarry Smith   while (GetMessage(&msg,hWnd, 0, 0)) {
6485c6c1daeSBarry Smith     TranslateMessage(&msg);
6495c6c1daeSBarry Smith     DispatchMessage(&msg);
6505c6c1daeSBarry Smith   }
651*f9baa8adSSatish Balay   return;
6525c6c1daeSBarry Smith }
6535c6c1daeSBarry Smith 
6545c6c1daeSBarry Smith static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
6555c6c1daeSBarry Smith                                       PetscDrawFlush_Win32,
6565c6c1daeSBarry Smith                                       PetscDrawLine_Win32,
6575c6c1daeSBarry Smith                                       PetscDrawLineSetWidth_Win32,
6585c6c1daeSBarry Smith                                       PetscDrawLineGetWidth_Win32,
6595c6c1daeSBarry Smith                                       PetscDrawPoint_Win32,
6605c6c1daeSBarry Smith                                       PetscDrawPointSetSize_Win32,
6615c6c1daeSBarry Smith                                       PetscDrawString_Win32,
6625c6c1daeSBarry Smith                                       PetscDrawStringVertical_Win32,
6635c6c1daeSBarry Smith                                       PetscDrawStringSetSize_Win32,
6645c6c1daeSBarry Smith                                       PetscDrawStringGetSize_Win32,
6655c6c1daeSBarry Smith                                       0,
6665c6c1daeSBarry Smith                                       PetscDrawClear_Win32,
6675c6c1daeSBarry Smith                                       PetscDrawRectangle_Win32,
6685c6c1daeSBarry Smith                                       PetscDrawTriangle_Win32,
6695c6c1daeSBarry Smith                                       0,
6705c6c1daeSBarry Smith                                       PetscDrawGetMouseButton_Win32,
6715c6c1daeSBarry Smith                                       PetscDrawPause_Win32,
6725c6c1daeSBarry Smith                                       0,
6735c6c1daeSBarry Smith                                       0,
6745c6c1daeSBarry Smith                                       PetscDrawGetPopup_Win32,
6755c6c1daeSBarry Smith                                       PetscDrawSetTitle_Win32,
6765c6c1daeSBarry Smith                                       PetscDrawCheckResizedWindow_Win32,
6775c6c1daeSBarry Smith                                       PetscDrawResizeWindow_Win32,
6785c6c1daeSBarry Smith                                       PetscDrawDestroy_Win32,
6795c6c1daeSBarry Smith                                       0,
6805c6c1daeSBarry Smith                                       0,
6815c6c1daeSBarry Smith                                       0,
6825c6c1daeSBarry Smith                                       0};
6835c6c1daeSBarry Smith 
6844a5237bfSSatish Balay static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popup)
6855c6c1daeSBarry Smith {
6865c6c1daeSBarry Smith   PetscErrorCode  ierr;
6874a5237bfSSatish Balay   PetscDraw_Win32 *win = (PetscDraw_Win32*)draw->data;
6884a5237bfSSatish Balay   PetscBool       flg  = PETSC_TRUE;
6895c6c1daeSBarry Smith 
6905c6c1daeSBarry Smith   PetscFunctionBegin;
69176a34f28SBarry Smith   ierr = PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);CHKERRQ(ierr);
6924a5237bfSSatish Balay   if (flg) {
6934a5237bfSSatish Balay     ierr = PetscDrawCreate(PetscObjectComm((PetscObject)draw),NULL,NULL,win->x,win->y+win->h+36,220,220,popup);CHKERRQ(ierr);
6944a5237bfSSatish Balay     ierr = PetscDrawSetType(*popup,PETSC_DRAW_WIN32);CHKERRQ(ierr);
6954a5237bfSSatish Balay     draw->popup = *popup;
6964a5237bfSSatish Balay   } else {
6974a5237bfSSatish Balay     *popup = NULL;
6984a5237bfSSatish Balay   }
6995c6c1daeSBarry Smith   PetscFunctionReturn(0);
7005c6c1daeSBarry Smith }
701728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode  PetscDrawCreate_Win32(PetscDraw draw)
7025c6c1daeSBarry Smith {
7035c6c1daeSBarry Smith   PetscDraw_Win32 *windraw;
7045c6c1daeSBarry Smith   HANDLE          hThread = NULL;
7055c6c1daeSBarry Smith   PetscErrorCode  ierr;
7065c6c1daeSBarry Smith   WindowNode      newnode;
7075c6c1daeSBarry Smith 
7085c6c1daeSBarry Smith   PetscFunctionBegin;
709b00a9115SJed Brown   ierr       = PetscNew(&windraw);CHKERRQ(ierr);
7105c6c1daeSBarry Smith   draw->data = windraw;
7115c6c1daeSBarry Smith 
7125c6c1daeSBarry Smith   /* the following is temporary fix for initializing a global datastructure */
713a297a907SKarl Rupp   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
7145c6c1daeSBarry Smith   ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
7155c6c1daeSBarry Smith 
7165c6c1daeSBarry Smith   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
7175c6c1daeSBarry Smith   /* makes call to MessageLoopThread to creat window and attach a thread */
71813d99558SMatthew G. Knepley   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(LPDWORD)hThread);
7195c6c1daeSBarry Smith   CloseHandle(hThread);
7205c6c1daeSBarry Smith   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
7215c6c1daeSBarry Smith   CloseHandle(windraw->hReadyEvent);
7225c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex,INFINITE);
7235c6c1daeSBarry Smith 
724b00a9115SJed Brown   ierr                   = PetscNew(&newnode);CHKERRQ(ierr);
7255c6c1daeSBarry Smith   newnode->MouseListHead = NULL;
7265c6c1daeSBarry Smith   newnode->MouseListTail = NULL;
7275c6c1daeSBarry Smith   newnode->wnext         = WindowListHead;
7285c6c1daeSBarry Smith   newnode->wprev         = NULL;
7295c6c1daeSBarry Smith   newnode->hWnd          = windraw->hWnd;
7306c4ed002SBarry Smith   if (WindowListHead) WindowListHead->wprev = newnode;
7315c6c1daeSBarry Smith   WindowListHead         = newnode;
7325c6c1daeSBarry Smith   windraw->hdc           = GetDC(windraw->hWnd);
7335c6c1daeSBarry Smith 
7345c6c1daeSBarry Smith   windraw->stringheight  = 10;
7355c6c1daeSBarry Smith   windraw->stringwidth   = 6;
7365c6c1daeSBarry Smith   windraw->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
7375c6c1daeSBarry Smith   windraw->pointdiameter = 1;
7385c6c1daeSBarry Smith   windraw->node          = newnode;
7395c6c1daeSBarry Smith 
7405c6c1daeSBarry Smith   windraw->x = draw->x;
7415c6c1daeSBarry Smith   windraw->y = draw->y;
7425c6c1daeSBarry Smith   windraw->w = newnode->bitwidth    = draw->w;
7435c6c1daeSBarry Smith   windraw->h = newnode->bitheight   = draw->h;
7445c6c1daeSBarry Smith 
7455c6c1daeSBarry Smith   /* Create and initialize primary graphics buffer */
7465c6c1daeSBarry Smith   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
7475c6c1daeSBarry Smith   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
7485c6c1daeSBarry Smith   newnode->store     = SelectObject(newnode->Buffer,newnode->BufferBit);
7495c6c1daeSBarry Smith   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
7505c6c1daeSBarry Smith 
7515c6c1daeSBarry Smith   newnode->event          = CreateEvent(NULL,TRUE,FALSE,NULL);
7525c6c1daeSBarry Smith   newnode->DoubleBuffered = PETSC_FALSE;
7535c6c1daeSBarry Smith 
7545c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd,windraw->hdc);
7555c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
7565c6c1daeSBarry Smith   PetscFunctionReturn(0);
7575c6c1daeSBarry Smith }
7585c6c1daeSBarry Smith 
7595c6c1daeSBarry Smith /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
7605c6c1daeSBarry Smith    PURPOSE:  Processes messages for the main window.
7615c6c1daeSBarry Smith    WM_COMMAND  - process the application menu
7625c6c1daeSBarry Smith    WM_PAINT    - Paint the main window
7635c6c1daeSBarry Smith    WM_DESTROY  - post a quit message and return */
7645c6c1daeSBarry Smith 
7655c6c1daeSBarry Smith LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
7665c6c1daeSBarry Smith {
7677ae38d14SSatish Balay   int wmId;
7685c6c1daeSBarry Smith 
7695c6c1daeSBarry Smith   switch (message) {
7705c6c1daeSBarry Smith     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
7715c6c1daeSBarry Smith     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
7725c6c1daeSBarry Smith   case WM_COMMAND:
7735c6c1daeSBarry Smith     wmId    = LOWORD(wParam);
7745c6c1daeSBarry Smith     /* Parse the menu selections:*/
7755c6c1daeSBarry Smith     switch (wmId) {
7765c6c1daeSBarry Smith     case IDM_EXIT:
7775c6c1daeSBarry Smith       DestroyWindow(hWnd);
7785c6c1daeSBarry Smith       break;
7795c6c1daeSBarry Smith     default:
7805c6c1daeSBarry Smith       return DefWindowProc(hWnd, message, wParam, lParam);
7815c6c1daeSBarry Smith     }
7825c6c1daeSBarry Smith     break;
7835c6c1daeSBarry Smith   case WM_LBUTTONUP:
7845c6c1daeSBarry Smith     MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
7855c6c1daeSBarry Smith     break;
7865c6c1daeSBarry Smith   case WM_RBUTTONUP:
7875c6c1daeSBarry Smith     MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
7885c6c1daeSBarry Smith     break;
7895c6c1daeSBarry Smith   case WM_MBUTTONUP:
7905c6c1daeSBarry Smith     MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
7915c6c1daeSBarry Smith     break;
7925c6c1daeSBarry Smith   default:
793*f9baa8adSSatish Balay     return DefWindowProc(hWnd, message, wParam, lParam);
7945c6c1daeSBarry Smith   }
795*f9baa8adSSatish Balay   return 0;
7965c6c1daeSBarry Smith }
7975c6c1daeSBarry Smith 
7985c6c1daeSBarry Smith static void OnPaint_Win32(HWND hWnd)
7995c6c1daeSBarry Smith {
8005c6c1daeSBarry Smith   PAINTSTRUCT ps;
8015c6c1daeSBarry Smith   HDC         hdc;
8025c6c1daeSBarry Smith   WindowNode  current = NULL;
8035c6c1daeSBarry Smith 
8045c6c1daeSBarry Smith   InvalidateRect(hWnd,NULL,TRUE);
8055c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
8065c6c1daeSBarry Smith   current = WindowListHead;
8075c6c1daeSBarry Smith   hdc     = BeginPaint(hWnd, &ps);
8085c6c1daeSBarry Smith 
8096c4ed002SBarry Smith   while (current) {
8105c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
8115c6c1daeSBarry Smith       /* flushes primary buffer to window */
812be332245SKarl Rupp       BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
813be332245SKarl Rupp              current->Buffer,0,0,SRCCOPY);
8145c6c1daeSBarry Smith 
815be332245SKarl Rupp       /* StretchBlt(hdc,0,0,w,h,
816be332245SKarl Rupp         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
8175c6c1daeSBarry Smith       break;
8185c6c1daeSBarry Smith     }
8195c6c1daeSBarry Smith     current = current->wnext;
8205c6c1daeSBarry Smith   }
8215c6c1daeSBarry Smith   EndPaint(hWnd, &ps);
8225c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
823*f9baa8adSSatish Balay   return;
8245c6c1daeSBarry Smith }
8255c6c1daeSBarry Smith 
8265c6c1daeSBarry Smith static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
8275c6c1daeSBarry Smith {
8285c6c1daeSBarry Smith   /* Called by all three mouse button actions
8295c6c1daeSBarry Smith     Records needed mouse data in windows data structure */
8305c6c1daeSBarry Smith   WindowNode     current = NULL;
8315c6c1daeSBarry Smith   MouseNode      newnode;
8325c6c1daeSBarry Smith   POINT          mousepos;
8335c6c1daeSBarry Smith   PetscErrorCode ierr;
8345c6c1daeSBarry Smith 
8355c6c1daeSBarry Smith   PetscFunctionBegin;
8365c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
8375c6c1daeSBarry Smith   current = WindowListHead;
8385c6c1daeSBarry Smith   if (current->IsGetMouseOn == TRUE) {
8395c6c1daeSBarry Smith 
8405c6c1daeSBarry Smith     SetEvent(current->event);
8416c4ed002SBarry Smith     while (current) {
8425c6c1daeSBarry Smith       if (current->hWnd == hWnd) {
8435c6c1daeSBarry Smith 
844b00a9115SJed Brown         ierr            = PetscNew(&newnode);CHKERRQ(ierr);
8455c6c1daeSBarry Smith         newnode->Button = button;
8465c6c1daeSBarry Smith         GetCursorPos(&mousepos);
8475c6c1daeSBarry Smith         newnode->user.x = mousepos.x;
8485c6c1daeSBarry Smith         newnode->user.y = mousepos.y;
8495c6c1daeSBarry Smith         ScreenToClient(hWnd,&mousepos);
8505c6c1daeSBarry Smith         newnode->phys.x = mousepos.x;
8515c6c1daeSBarry Smith         newnode->phys.y = mousepos.y;
8525c6c1daeSBarry Smith         if (!current->MouseListTail) {
8535c6c1daeSBarry Smith           current->MouseListHead = newnode;
8545c6c1daeSBarry Smith           current->MouseListTail = newnode;
8555c6c1daeSBarry Smith         } else {
8565c6c1daeSBarry Smith           current->MouseListTail->mnext = newnode;
8575c6c1daeSBarry Smith           current->MouseListTail        = newnode;
8585c6c1daeSBarry Smith         }
8595c6c1daeSBarry Smith         newnode->mnext = NULL;
8605c6c1daeSBarry Smith 
8615c6c1daeSBarry Smith         break;
8625c6c1daeSBarry Smith       }
8635c6c1daeSBarry Smith       current = current->wnext;
8645c6c1daeSBarry Smith     }
8655c6c1daeSBarry Smith   }
8665c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
8675c6c1daeSBarry Smith   PetscFunctionReturn(0);
8685c6c1daeSBarry Smith }
8695c6c1daeSBarry Smith 
8705c6c1daeSBarry Smith static void OnDestroy_Win32(HWND hWnd)
8715c6c1daeSBarry Smith {
8725c6c1daeSBarry Smith   /* searches linked list of window data and frees corresponding memory */
8735c6c1daeSBarry Smith   WindowNode current;
8745c6c1daeSBarry Smith 
8755c6c1daeSBarry Smith   PetscFunctionBegin;
8765c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
8775c6c1daeSBarry Smith   current = WindowListHead;
8785c6c1daeSBarry Smith 
8795c6c1daeSBarry Smith   SetEvent(current->event);
8806c4ed002SBarry Smith   while (current) {
8815c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
8826c4ed002SBarry Smith       if (current->wprev) current->wprev->wnext = current->wnext;
883a297a907SKarl Rupp       else WindowListHead = current->wnext;
884a297a907SKarl Rupp       if (current->MouseListHead) deletemouselist_Win32(current);
885a297a907SKarl Rupp       else PetscFree(current);
8865c6c1daeSBarry Smith       break;
8875c6c1daeSBarry Smith     }
8885c6c1daeSBarry Smith     current = current->wnext;
8895c6c1daeSBarry Smith   }
8905c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
8915c6c1daeSBarry Smith   PostQuitMessage(0);
8925c6c1daeSBarry Smith   PetscFunctionReturnVoid();
8935c6c1daeSBarry Smith }
894