xref: /petsc/src/sys/classes/draw/impls/win32/win32draw.c (revision bb09dc679343949bbd3a0d169d00d20c9bec7648)
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 
259371c9d4SSatish Balay #define XTRANS(draw, win, x) (int)(((win)->w) * ((draw)->port_xl + (((x - (draw)->coor_xl) * ((draw)->port_xr - (draw)->port_xl)) / ((draw)->coor_xr - (draw)->coor_xl))))
269371c9d4SSatish Balay #define YTRANS(draw, win, y) (int)(((win)->h) * (1.0 - (draw)->port_yl - (((y - (draw)->coor_yl) * ((draw)->port_yr - (draw)->port_yl)) / ((draw)->coor_yr - (draw)->coor_yl))))
275c6c1daeSBarry Smith 
285c6c1daeSBarry Smith HINSTANCE  hInst;
295c6c1daeSBarry Smith HANDLE     g_hWindowListMutex = NULL;
305c6c1daeSBarry Smith WindowNode WindowListHead     = NULL;
315c6c1daeSBarry Smith 
325c6c1daeSBarry Smith /* Hard coded color hue until hue.c works with this */
335c6c1daeSBarry 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};
345c6c1daeSBarry 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};
355c6c1daeSBarry 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};
365c6c1daeSBarry Smith 
37da81f932SPierre Jolivet /* Forward declarations of functions included in this code module: */
385c6c1daeSBarry Smith LRESULT CALLBACK      PetscWndProc(HWND, UINT, WPARAM, LPARAM);
395c6c1daeSBarry Smith static PetscErrorCode TranslateColor_Win32(PetscDraw, int);
405c6c1daeSBarry Smith static PetscErrorCode AverageColorRectangle_Win32(PetscDraw, int, int, int, int);
415c6c1daeSBarry Smith static PetscErrorCode AverageColorTriangle_Win32(PetscDraw, int, int, int);
425c6c1daeSBarry Smith static PetscErrorCode deletemouselist_Win32(WindowNode);
435c6c1daeSBarry Smith static void           OnPaint_Win32(HWND);
445c6c1daeSBarry Smith static void           OnDestroy_Win32(HWND);
455c6c1daeSBarry Smith static PetscErrorCode MouseRecord_Win32(HWND, PetscDrawButton);
465c6c1daeSBarry Smith static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw, PetscDraw *);
475c6c1daeSBarry Smith 
48d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
49d71ae5a4SJacob Faibussowitsch {
505c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
515c6c1daeSBarry Smith   HDC              hdc     = GetDC(windraw->hWnd);
525c6c1daeSBarry Smith 
535c6c1daeSBarry Smith   PetscFunctionBegin;
545c6c1daeSBarry Smith   windraw->node->DoubleBuffer    = CreateCompatibleDC(hdc);
555c6c1daeSBarry Smith   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc, windraw->w, windraw->h);
565c6c1daeSBarry Smith   windraw->node->dbstore         = SelectObject(windraw->node->DoubleBuffer, windraw->node->DoubleBufferBit);
575c6c1daeSBarry Smith   /* Fill background of second buffer */
585c6c1daeSBarry Smith   ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
59da81f932SPierre Jolivet   /* Copy current buffer into second buffer and set window data as double buffered */
609371c9d4SSatish Balay   BitBlt(windraw->node->DoubleBuffer, 0, 0, windraw->w, windraw->h, windraw->node->Buffer, 0, 0, SRCCOPY);
615c6c1daeSBarry Smith 
625c6c1daeSBarry Smith   windraw->node->DoubleBuffered = PETSC_TRUE;
635c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, hdc);
643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
655c6c1daeSBarry Smith }
665c6c1daeSBarry Smith 
67d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
68d71ae5a4SJacob Faibussowitsch {
695c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
705c6c1daeSBarry Smith   HDC              hdc     = GetDC(windraw->hWnd);
715c6c1daeSBarry Smith 
725c6c1daeSBarry Smith   PetscFunctionBegin;
735c6c1daeSBarry Smith   /* flush double buffer into primary buffer */
749371c9d4SSatish Balay   BitBlt(windraw->node->Buffer, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
755c6c1daeSBarry Smith   /* flush double buffer into window */
769371c9d4SSatish Balay   BitBlt(hdc, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
775c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, hdc);
783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
795c6c1daeSBarry Smith }
805c6c1daeSBarry Smith 
81d71ae5a4SJacob Faibussowitsch static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
82d71ae5a4SJacob Faibussowitsch {
835c6c1daeSBarry Smith   /* Called upon window close. Frees memory of linked list of stored mouse commands */
845c6c1daeSBarry Smith   MouseNode node;
855c6c1daeSBarry Smith 
866c4ed002SBarry Smith   while (deletelist->MouseListHead) {
875c6c1daeSBarry Smith     node = deletelist->MouseListHead;
886c4ed002SBarry Smith     if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
895c6c1daeSBarry Smith     PetscFree(node);
905c6c1daeSBarry Smith   }
915c6c1daeSBarry Smith   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
926c4ed002SBarry Smith   if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
936c4ed002SBarry Smith   if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
945c6c1daeSBarry Smith   PetscFree(deletelist);
953ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
965c6c1daeSBarry Smith }
975c6c1daeSBarry Smith 
98d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button, PetscReal *x_user, PetscReal *y_user, PetscReal *x_phys, PetscReal *y_phys)
99d71ae5a4SJacob Faibussowitsch {
1005c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1015c6c1daeSBarry Smith   WindowNode       current;
1025c6c1daeSBarry Smith   MouseNode        node = 0;
1035c6c1daeSBarry Smith 
1045c6c1daeSBarry Smith   PetscFunctionBegin;
1055c6c1daeSBarry Smith   /* Make sure no other code is using the linked list at this moment */
1065c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1075c6c1daeSBarry Smith   /* Look for the node that matches the window you are using */
1085c6c1daeSBarry Smith   current = WindowListHead;
1096c4ed002SBarry Smith   while (current) {
1105c6c1daeSBarry Smith     if (current->hWnd == windraw->hWnd) {
1115c6c1daeSBarry Smith       current->IsGetMouseOn = TRUE;
1125c6c1daeSBarry Smith       break;
113a297a907SKarl Rupp     } else current = current->wnext;
1145c6c1daeSBarry Smith   }
115a5b23f4aSJose E. Roman   /* If no actions have occurred, wait for one */
1165c6c1daeSBarry Smith   node = current->MouseListHead;
1175c6c1daeSBarry Smith   if (!node) {
1185c6c1daeSBarry Smith     ReleaseMutex(g_hWindowListMutex);
1195c6c1daeSBarry Smith     WaitForSingleObject(current->event, INFINITE);
1205c6c1daeSBarry Smith     WaitForSingleObject(g_hWindowListMutex, INFINITE);
1215c6c1daeSBarry Smith   }
1225c6c1daeSBarry Smith   /* once we have the information, assign the pointers to it */
1235c6c1daeSBarry Smith   *button = current->MouseListHead->Button;
1245c6c1daeSBarry Smith   *x_user = current->MouseListHead->user.x;
1255c6c1daeSBarry Smith   *y_user = current->MouseListHead->user.y;
1265c6c1daeSBarry Smith   /* optional arguments */
1275c6c1daeSBarry Smith   if (x_phys) *x_phys = current->MouseListHead->phys.x;
1285c6c1daeSBarry Smith   if (y_phys) *y_phys = current->MouseListHead->phys.y;
1295c6c1daeSBarry Smith   /* remove set of information from sub linked-list, delete the node */
1305c6c1daeSBarry Smith   current->MouseListHead = current->MouseListHead->mnext;
1315c6c1daeSBarry Smith   if (!current->MouseListHead) {
1325c6c1daeSBarry Smith     ResetEvent(current->event);
1335c6c1daeSBarry Smith     current->MouseListTail = NULL;
1345c6c1daeSBarry Smith   }
1355c6c1daeSBarry Smith   if (node) PetscFree(node);
1365c6c1daeSBarry Smith 
1375c6c1daeSBarry Smith   /* Release mutex so that  other code can use
1385c6c1daeSBarry Smith      the linked list now that we are done with it */
1395c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
1403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1415c6c1daeSBarry Smith }
1425c6c1daeSBarry Smith 
143d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
144d71ae5a4SJacob Faibussowitsch {
1455c6c1daeSBarry Smith   PetscFunctionBegin;
1465c6c1daeSBarry Smith   PetscSleep(draw->pause);
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1485c6c1daeSBarry Smith }
1495c6c1daeSBarry Smith 
150d71ae5a4SJacob Faibussowitsch static PetscErrorCode TranslateColor_Win32(PetscDraw draw, int color)
151d71ae5a4SJacob Faibussowitsch {
1525c6c1daeSBarry Smith   /* Maps single color value into the RGB colors in our tables */
1535c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1545c6c1daeSBarry Smith   windraw->currentcolor    = RGB(RedMap[color], GreenMap[color], BlueMap[color]);
1553ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1565c6c1daeSBarry Smith }
1575c6c1daeSBarry Smith 
158d71ae5a4SJacob Faibussowitsch static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw, int c1, int c2, int c3, int c4)
159d71ae5a4SJacob Faibussowitsch {
1605c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
1615c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
1625c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1639371c9d4SSatish Balay   windraw->currentcolor    = RGB(((RedMap[c1] + RedMap[c2] + RedMap[c3] + RedMap[c4]) / 4), ((GreenMap[c1] + GreenMap[c2] + GreenMap[c3] + GreenMap[c4]) / 4), ((BlueMap[c1] + BlueMap[c2] + BlueMap[c3] + BlueMap[c4]) / 4));
1643ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1655c6c1daeSBarry Smith }
1665c6c1daeSBarry Smith 
167d71ae5a4SJacob Faibussowitsch static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw, int c1, int c2, int c3)
168d71ae5a4SJacob Faibussowitsch {
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;
1729371c9d4SSatish Balay   windraw->currentcolor    = RGB((RedMap[c1] + RedMap[c2] + RedMap[c3]) / 3, (GreenMap[c1] + GreenMap[c2] + GreenMap[c3]) / 3, (BlueMap[c1] + BlueMap[c2] + BlueMap[c3]) / 3);
1733ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1745c6c1daeSBarry Smith }
1755c6c1daeSBarry Smith 
176d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4)
177d71ae5a4SJacob Faibussowitsch {
1785c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1795c6c1daeSBarry Smith   HBRUSH           hbrush;
1805c6c1daeSBarry Smith   RECT             rect;
1815c6c1daeSBarry Smith   int              x1, yone, x2, y2;
1825c6c1daeSBarry Smith   HDC              hdc;
1835c6c1daeSBarry Smith 
1845c6c1daeSBarry Smith   PetscFunctionBegin;
1855c6c1daeSBarry Smith   x1   = XTRANS(draw, windraw, xl);
1865c6c1daeSBarry Smith   x2   = XTRANS(draw, windraw, xr);
1875c6c1daeSBarry Smith   yone = YTRANS(draw, windraw, yl);
1885c6c1daeSBarry Smith   y2   = YTRANS(draw, windraw, yr);
1895c6c1daeSBarry Smith   SetRect(&rect, x1, y2, x2, yone);
190a297a907SKarl Rupp   if (c1 == c2 && c2 == c3 && c3 == c4) TranslateColor_Win32(draw, c1);
191a297a907SKarl Rupp   else AverageColorRectangle_Win32(draw, c1, c2, c3, c4);
1925c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
1935c6c1daeSBarry Smith 
194a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
195a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
196a297a907SKarl Rupp 
1975c6c1daeSBarry Smith   FillRect(hdc, &rect, hbrush);
1985c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
1995c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
2005c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2025c6c1daeSBarry Smith }
2035c6c1daeSBarry Smith 
204d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int color)
205d71ae5a4SJacob Faibussowitsch {
2065c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2075c6c1daeSBarry Smith   HPEN             hpen;
2085c6c1daeSBarry Smith   int              x1, yone, x2, y2;
2095c6c1daeSBarry Smith   HDC              hdc;
2105c6c1daeSBarry Smith 
2115c6c1daeSBarry Smith   PetscFunctionBegin;
2125c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
2139371c9d4SSatish Balay   x1   = XTRANS(draw, windraw, xl);
2149371c9d4SSatish Balay   x2   = XTRANS(draw, windraw, xr);
2159371c9d4SSatish Balay   yone = YTRANS(draw, windraw, yl);
2169371c9d4SSatish Balay   y2   = YTRANS(draw, windraw, yr);
2175c6c1daeSBarry Smith   hpen = CreatePen(PS_SOLID, windraw->linewidth, windraw->currentcolor);
218a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
219a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
220a297a907SKarl Rupp 
2215c6c1daeSBarry Smith   SelectPen(hdc, hpen);
2225c6c1daeSBarry Smith   MoveToEx(hdc, x1, yone, NULL);
2235c6c1daeSBarry Smith   LineTo(hdc, x2, y2);
2245c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
2255c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
2265c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2285c6c1daeSBarry Smith }
2295c6c1daeSBarry Smith 
230d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw, PetscReal width)
231d71ae5a4SJacob Faibussowitsch {
2325c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2335c6c1daeSBarry Smith   int              averagesize, finalwidth;
2345c6c1daeSBarry Smith   RECT             rect;
2355c6c1daeSBarry Smith 
2365c6c1daeSBarry Smith   PetscFunctionBegin;
2375c6c1daeSBarry Smith   GetClientRect(windraw->hWnd, &rect);
2385c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
23977b4d14cSPeter Brune   finalwidth  = (int)PetscFloorReal(averagesize * width);
240a297a907SKarl Rupp   if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */
241a297a907SKarl Rupp 
2425c6c1daeSBarry Smith   windraw->linewidth = finalwidth;
2433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2445c6c1daeSBarry Smith }
2455c6c1daeSBarry Smith 
246d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw, PetscReal *width)
247d71ae5a4SJacob Faibussowitsch {
2485c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2495c6c1daeSBarry Smith 
2505c6c1daeSBarry Smith   PetscFunctionBegin;
2515c6c1daeSBarry Smith   *width = (PetscReal)windraw->linewidth;
2523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2535c6c1daeSBarry Smith }
2545c6c1daeSBarry Smith 
255d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color)
256d71ae5a4SJacob Faibussowitsch {
2575c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2585c6c1daeSBarry Smith   HBRUSH           hbrush;
2595c6c1daeSBarry Smith   HRGN             hrgn;
2605c6c1daeSBarry Smith   int              radius;
2615c6c1daeSBarry Smith   int              x1, yone;
2625c6c1daeSBarry Smith   HDC              hdc;
2635c6c1daeSBarry Smith 
2645c6c1daeSBarry Smith   PetscFunctionBegin;
2655c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
2665c6c1daeSBarry Smith   x1     = XTRANS(draw, windraw, x);
2675c6c1daeSBarry Smith   yone   = YTRANS(draw, windraw, y);
2685c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
269a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
270a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
271a297a907SKarl Rupp 
2725c6c1daeSBarry Smith   /* desired size is one logical pixel so just turn it on */
273a297a907SKarl Rupp   if (windraw->pointdiameter == 1) SetPixelV(hdc, x1, yone, windraw->currentcolor);
274a297a907SKarl Rupp   else {
2755c6c1daeSBarry Smith     /* draw point around position determined */
2765c6c1daeSBarry Smith     radius = windraw->pointdiameter / 2; /* integer division */
2775c6c1daeSBarry Smith     hrgn   = CreateEllipticRgn(x1 - radius, yone - radius, x1 + radius, yone + radius);
2785c6c1daeSBarry Smith     FillRgn(hdc, hrgn, hbrush);
2795c6c1daeSBarry Smith   }
2805c6c1daeSBarry Smith   /* Forces a WM_PAINT and erases background */
2815c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
2825c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2845c6c1daeSBarry Smith }
2855c6c1daeSBarry Smith 
286d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw, PetscReal width)
287d71ae5a4SJacob Faibussowitsch {
2885c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2895c6c1daeSBarry Smith   int              averagesize, diameter;
2905c6c1daeSBarry Smith   RECT             rect;
2915c6c1daeSBarry Smith 
2925c6c1daeSBarry Smith   PetscFunctionBegin;
2935c6c1daeSBarry Smith   GetClientRect(windraw->hWnd, &rect);
2945c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
29577b4d14cSPeter Brune   diameter    = (int)PetscFloorReal(averagesize * width);
2965c6c1daeSBarry Smith   if (diameter < 1) diameter = 1;
2975c6c1daeSBarry Smith   windraw->pointdiameter = diameter;
2983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2995c6c1daeSBarry Smith }
3005c6c1daeSBarry Smith 
301d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawString_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text)
302d71ae5a4SJacob Faibussowitsch {
3035c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3045c6c1daeSBarry Smith   RECT             r;
3055c6c1daeSBarry Smith   HFONT            hfont;
3065c6c1daeSBarry Smith   LOGFONT          logfont;
3075c6c1daeSBarry Smith   int              x1, yone;
3085c6c1daeSBarry Smith   HDC              hdc;
3095c6c1daeSBarry Smith 
3105c6c1daeSBarry Smith   PetscFunctionBegin;
3115c6c1daeSBarry Smith   x1       = XTRANS(draw, windraw, x);
3125c6c1daeSBarry Smith   yone     = YTRANS(draw, windraw, y);
3135c6c1daeSBarry Smith   r.bottom = yone;
3145c6c1daeSBarry Smith   r.left   = x1;
3155c6c1daeSBarry Smith   r.right  = x1 + 1;
3165c6c1daeSBarry Smith   r.top    = yone + 1;
317a297a907SKarl Rupp 
3185c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3195c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3205c6c1daeSBarry Smith   logfont.lfEscapement     = 0;
3215c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3225c6c1daeSBarry Smith   logfont.lfCharSet        = 0;
3235c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3245c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3255c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3265c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3275c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3285c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3295c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3305c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
331a297a907SKarl Rupp 
3325c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3335c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
334a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
335a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
336a297a907SKarl Rupp 
3375c6c1daeSBarry Smith   SelectFont(hdc, hfont);
3385c6c1daeSBarry Smith   SetTextColor(hdc, windraw->currentcolor);
3395c6c1daeSBarry Smith   DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP);
3405c6c1daeSBarry Smith   DeleteObject(hfont);
3415c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3425c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
3435c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
3443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3455c6c1daeSBarry Smith }
3465c6c1daeSBarry Smith 
347d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text)
348d71ae5a4SJacob Faibussowitsch {
3495c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3505c6c1daeSBarry Smith   RECT             r;
3515c6c1daeSBarry Smith   HFONT            hfont;
3525c6c1daeSBarry Smith   LOGFONT          logfont;
3535c6c1daeSBarry Smith   int              x1, yone;
3545c6c1daeSBarry Smith   HDC              hdc;
3555c6c1daeSBarry Smith 
3565c6c1daeSBarry Smith   PetscFunctionBegin;
3575c6c1daeSBarry Smith   x1       = XTRANS(draw, windraw, x);
3585c6c1daeSBarry Smith   yone     = YTRANS(draw, windraw, y);
3595c6c1daeSBarry Smith   r.left   = x1;
3605c6c1daeSBarry Smith   r.bottom = yone + 30;
3615c6c1daeSBarry Smith   r.right  = x1 + 1;
3625c6c1daeSBarry Smith   r.top    = yone - 30;
363a297a907SKarl Rupp 
3645c6c1daeSBarry Smith   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
3655c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3665c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3675c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3685c6c1daeSBarry Smith   logfont.lfCharSet        = DEFAULT_CHARSET;
3695c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3705c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3715c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3725c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3735c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3745c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3755c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3765c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
377a297a907SKarl Rupp 
3785c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3795c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
380a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
381a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
382a297a907SKarl Rupp 
3835c6c1daeSBarry Smith   SelectFont(hdc, hfont);
3845c6c1daeSBarry Smith   SetTextColor(hdc, windraw->currentcolor);
3855c6c1daeSBarry Smith   DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP | DT_SINGLELINE);
3865c6c1daeSBarry Smith   DeleteObject(hfont);
3875c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3885c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
3895c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
3903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3915c6c1daeSBarry Smith }
3925c6c1daeSBarry Smith 
393d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw, PetscReal width, PetscReal height)
394d71ae5a4SJacob Faibussowitsch {
3955c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3965c6c1daeSBarry Smith   int              w, h;
3975c6c1daeSBarry Smith 
3985c6c1daeSBarry Smith   PetscFunctionBegin;
3995c6c1daeSBarry Smith   w = (int)((windraw->w) * width * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl));
4005c6c1daeSBarry Smith   h = (int)((windraw->h) * height * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl));
4015c6c1daeSBarry Smith   if (h < 1) h = 1;
4025c6c1daeSBarry Smith   if (w < 1) w = 1;
4035c6c1daeSBarry Smith   windraw->stringheight = h;
4045c6c1daeSBarry Smith   windraw->stringwidth  = w;
4053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4065c6c1daeSBarry Smith }
407d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw, PetscReal *width, PetscReal *height)
408d71ae5a4SJacob Faibussowitsch {
4095c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4105c6c1daeSBarry Smith   double           scaleX  = (draw->coor_xr - draw->coor_xl) / (draw->w) * (draw->port_xr - draw->port_xl);
4115c6c1daeSBarry Smith   double           scaleY  = (draw->coor_yr - draw->coor_yl) / (draw->h) * (draw->port_yr - draw->port_yl);
4125c6c1daeSBarry Smith 
4135c6c1daeSBarry Smith   PetscFunctionBegin;
4144a5237bfSSatish Balay   if (height) *height = (double)windraw->stringheight * scaleY;
4154a5237bfSSatish Balay   if (width) *width = (double)windraw->stringwidth * scaleX;
4163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4175c6c1daeSBarry Smith }
4185c6c1daeSBarry Smith 
419d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw, int w, int h)
420d71ae5a4SJacob Faibussowitsch {
4215c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4225c6c1daeSBarry Smith   RECT             r;
4235c6c1daeSBarry Smith 
4245c6c1daeSBarry Smith   PetscFunctionBegin;
4255c6c1daeSBarry Smith   GetWindowRect(windraw->hWnd, &r);
4265c6c1daeSBarry Smith   MoveWindow(windraw->hWnd, r.left, r.top, (int)w, (int)h, TRUE);
4275c6c1daeSBarry Smith   /* set all variable dealing with window dimensions */
4285c6c1daeSBarry Smith   windraw->node->bitheight = windraw->h = draw->h = h;
4295c6c1daeSBarry Smith   windraw->node->bitwidth = windraw->w = draw->w = w;
4305c6c1daeSBarry Smith   /* set up graphic buffers with the new size of window */
4315c6c1daeSBarry Smith   SetBitmapDimensionEx(windraw->node->BufferBit, w, h, NULL);
432a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit, w, h, NULL);
4335c6c1daeSBarry Smith   windraw->haveresized = PETSC_TRUE;
4343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4355c6c1daeSBarry Smith }
4365c6c1daeSBarry Smith 
437d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
438d71ae5a4SJacob Faibussowitsch {
4395c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4405c6c1daeSBarry Smith 
4415c6c1daeSBarry Smith   PetscFunctionBegin;
44211cc89d2SBarry Smith   PetscCheck(windraw->haveresized != 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for resizing windows on Microsoft Windows");
4433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4445c6c1daeSBarry Smith }
4455c6c1daeSBarry Smith 
446d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
447d71ae5a4SJacob Faibussowitsch {
4485c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4495c6c1daeSBarry Smith 
4505c6c1daeSBarry Smith   PetscFunctionBegin;
4515c6c1daeSBarry Smith   SetWindowText(windraw->hWnd, title);
4523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4535c6c1daeSBarry Smith }
4545c6c1daeSBarry Smith 
455d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
456d71ae5a4SJacob Faibussowitsch {
4575c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4585c6c1daeSBarry Smith 
4595c6c1daeSBarry Smith   PetscFunctionBegin;
4605c6c1daeSBarry Smith   /* clear primary buffer */
4615c6c1daeSBarry Smith   ExtFloodFill(windraw->node->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
4625c6c1daeSBarry Smith   /* if exists clear secondary buffer */
463a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
464a297a907SKarl Rupp 
4655c6c1daeSBarry Smith   /* force WM_PAINT message so cleared buffer will show */
4665c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
4675c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
4683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4695c6c1daeSBarry Smith }
4705c6c1daeSBarry Smith 
471d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw, PetscReal x1, PetscReal yone, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3)
472d71ae5a4SJacob Faibussowitsch {
4735c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4745c6c1daeSBarry Smith   HBRUSH           hbrush;
4755c6c1daeSBarry Smith   HPEN             hpen;
4765c6c1daeSBarry Smith   int              p1x, p1y, p2x, p2y, p3x, p3y;
4775c6c1daeSBarry Smith   HDC              bit;
4785c6c1daeSBarry Smith 
4795c6c1daeSBarry Smith   PetscFunctionBegin;
4805c6c1daeSBarry Smith   AverageColorTriangle_Win32(draw, c1, c2, c3);
4815c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
4825c6c1daeSBarry Smith   hpen   = CreatePen(PS_SOLID, 0, windraw->currentcolor);
4835c6c1daeSBarry Smith   p1x    = XTRANS(draw, windraw, x1);
4845c6c1daeSBarry Smith   p2x    = XTRANS(draw, windraw, x2);
4855c6c1daeSBarry Smith   p3x    = XTRANS(draw, windraw, x3);
4865c6c1daeSBarry Smith   p1y    = YTRANS(draw, windraw, yone);
4875c6c1daeSBarry Smith   p2y    = YTRANS(draw, windraw, y2);
4885c6c1daeSBarry Smith   p3y    = YTRANS(draw, windraw, y3);
4895c6c1daeSBarry Smith 
490a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
491a297a907SKarl Rupp   else bit = windraw->node->Buffer;
492a297a907SKarl Rupp 
4935c6c1daeSBarry Smith   BeginPath(bit);
4945c6c1daeSBarry Smith   MoveToEx(bit, p1x, p1y, NULL);
4955c6c1daeSBarry Smith   LineTo(bit, p2x, p2y);
4965c6c1daeSBarry Smith   LineTo(bit, p3x, p3y);
4975c6c1daeSBarry Smith   LineTo(bit, p1x, p1y);
4985c6c1daeSBarry Smith   EndPath(bit);
4995c6c1daeSBarry Smith   SelectPen(bit, hpen);
5005c6c1daeSBarry Smith   SelectBrush(bit, hbrush);
5015c6c1daeSBarry Smith   StrokeAndFillPath(bit);
5025c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
5035c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
5045c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
5053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5065c6c1daeSBarry Smith }
5075c6c1daeSBarry Smith 
508*bb09dc67SDuncan Campbell static PetscErrorCode PetscDrawSetVisible_Win32(PetscDraw draw, PetscBool visible)
509*bb09dc67SDuncan Campbell {
510*bb09dc67SDuncan Campbell   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
511*bb09dc67SDuncan Campbell 
512*bb09dc67SDuncan Campbell   PetscFunctionBegin;
513*bb09dc67SDuncan Campbell   ShowWindow(windraw->hWnd, visible ? SW_SHOWNA : SW_HIDE);
514*bb09dc67SDuncan Campbell   PetscFunctionReturn(PETSC_SUCCESS);
515*bb09dc67SDuncan Campbell }
516*bb09dc67SDuncan Campbell 
517d71ae5a4SJacob Faibussowitsch void PopMessageLoopThread_Win32(PetscDraw popdraw)
518d71ae5a4SJacob Faibussowitsch {
5195c6c1daeSBarry Smith   PetscDraw_Win32 *pop = (PetscDraw_Win32 *)popdraw->data;
5205c6c1daeSBarry Smith   MSG              msg;
5215c6c1daeSBarry Smith   HWND             hWnd           = NULL;
522fad2a674SVolker   const char       PopClassName[] = "PETSc Window Pop Class";
5235c6c1daeSBarry Smith   RECT             r;
5245c6c1daeSBarry Smith   int              width, height;
5255c6c1daeSBarry Smith   WNDCLASSEX       myclass;
5265c6c1daeSBarry Smith   LPVOID           lpMsgBuf;
5275c6c1daeSBarry Smith 
5285c6c1daeSBarry Smith   PetscFunctionBegin;
5295c6c1daeSBarry Smith   /* initialize window class parameters */
5305c6c1daeSBarry Smith   myclass.cbSize        = sizeof(WNDCLASSEX);
5315c6c1daeSBarry Smith   myclass.style         = CS_OWNDC;
5325c6c1daeSBarry Smith   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
5335c6c1daeSBarry Smith   myclass.cbClsExtra    = 0;
5345c6c1daeSBarry Smith   myclass.cbWndExtra    = 0;
5355c6c1daeSBarry Smith   myclass.hInstance     = NULL;
5365c6c1daeSBarry Smith   myclass.hIcon         = NULL;
5375c6c1daeSBarry Smith   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
5385c6c1daeSBarry Smith   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
5395c6c1daeSBarry Smith   myclass.lpszMenuName  = NULL;
5405c6c1daeSBarry Smith   myclass.lpszClassName = PopClassName;
5415c6c1daeSBarry Smith   myclass.hIconSm       = NULL;
5425c6c1daeSBarry Smith 
5435c6c1daeSBarry Smith   RegisterClassEx(&myclass);
5445c6c1daeSBarry Smith 
5455c6c1daeSBarry Smith   SetRect(&r, 0, 0, 450, 450);
5465c6c1daeSBarry Smith 
5475c6c1daeSBarry Smith   width  = (r.right - r.left) / 3;
5485c6c1daeSBarry Smith   height = (r.bottom - r.top) / 3;
5495c6c1daeSBarry Smith 
5509371c9d4SSatish Balay   hWnd   = CreateWindowEx(0, PopClassName, NULL, WS_POPUPWINDOW | WS_CAPTION, 0, 0, width, height, NULL, NULL, hInst, NULL);
5515c6c1daeSBarry Smith   pop->x = 0;
5525c6c1daeSBarry Smith   pop->y = 0;
5535c6c1daeSBarry Smith   pop->w = width;
5545c6c1daeSBarry Smith   pop->h = height;
5555c6c1daeSBarry Smith 
5565c6c1daeSBarry Smith   if (!hWnd) {
557fad2a674SVolker     lpMsgBuf = (LPVOID) "Window Not Successfully Created";
5585c6c1daeSBarry Smith     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
5595c6c1daeSBarry Smith     LocalFree(lpMsgBuf);
5605c6c1daeSBarry Smith     exit(0);
5615c6c1daeSBarry Smith   }
5625c6c1daeSBarry Smith   pop->hWnd = hWnd;
5635c6c1daeSBarry Smith   /* display and update new popup window */
5645c6c1daeSBarry Smith   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
5655c6c1daeSBarry Smith   UpdateWindow(pop->hWnd);
5665c6c1daeSBarry Smith   SetEvent(pop->hReadyEvent);
5675c6c1daeSBarry Smith 
5685c6c1daeSBarry Smith   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
5695c6c1daeSBarry Smith     TranslateMessage(&msg);
5705c6c1daeSBarry Smith     DispatchMessage(&msg);
5715c6c1daeSBarry Smith   }
5725c6c1daeSBarry Smith   PetscFunctionReturnVoid();
5735c6c1daeSBarry Smith }
5745c6c1daeSBarry Smith 
575d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
576d71ae5a4SJacob Faibussowitsch {
5775c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
5785c6c1daeSBarry Smith 
5795c6c1daeSBarry Smith   PetscFunctionBegin;
5805c6c1daeSBarry Smith   SendMessage(windraw->hWnd, WM_DESTROY, 0, 0);
58150c74209SLisandro Dalcin   PetscFree(draw->data);
5823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5835c6c1daeSBarry Smith }
5845c6c1daeSBarry Smith 
585d71ae5a4SJacob Faibussowitsch void MessageLoopThread_Win32(PetscDraw draw)
586d71ae5a4SJacob Faibussowitsch {
5875c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
5885c6c1daeSBarry Smith   MSG              msg;
5895c6c1daeSBarry Smith   HWND             hWnd        = NULL;
590fad2a674SVolker   const char       classname[] = "PETSc Window Class";
5915c6c1daeSBarry Smith   WNDCLASSEX       wclass;
5925c6c1daeSBarry Smith   LPVOID           lpMsgBuf;
5935c6c1daeSBarry Smith 
5945c6c1daeSBarry Smith   /* initialize window class parameters */
5955c6c1daeSBarry Smith   wclass.cbSize        = sizeof(WNDCLASSEX);
5965c6c1daeSBarry Smith   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
5975c6c1daeSBarry Smith   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
5985c6c1daeSBarry Smith   wclass.cbClsExtra    = 0;
5995c6c1daeSBarry Smith   wclass.cbWndExtra    = 0;
6005c6c1daeSBarry Smith   wclass.hInstance     = NULL;
6015c6c1daeSBarry Smith   wclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
6025c6c1daeSBarry Smith   wclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
6035c6c1daeSBarry Smith   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
6045c6c1daeSBarry Smith   wclass.lpszMenuName  = NULL;
6055c6c1daeSBarry Smith   wclass.lpszClassName = classname;
6065c6c1daeSBarry Smith   wclass.hIconSm       = NULL;
6075c6c1daeSBarry Smith 
6085c6c1daeSBarry Smith   RegisterClassEx(&wclass);
6095c6c1daeSBarry Smith 
6109371c9d4SSatish Balay   hWnd = CreateWindowEx(0, classname, NULL, WS_OVERLAPPEDWINDOW, draw->x, draw->y, draw->w, draw->h, NULL, NULL, hInst, NULL);
6115c6c1daeSBarry Smith 
6125c6c1daeSBarry Smith   if (!hWnd) {
613fad2a674SVolker     lpMsgBuf = (LPVOID) "Window Not Successfully Created";
6145c6c1daeSBarry Smith     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
6155c6c1daeSBarry Smith     LocalFree(lpMsgBuf);
6165c6c1daeSBarry Smith     exit(0);
6175c6c1daeSBarry Smith   }
6185c6c1daeSBarry Smith   windraw->hWnd = hWnd;
6195c6c1daeSBarry Smith   /* display and update new window */
6205c6c1daeSBarry Smith   ShowWindow(hWnd, SW_SHOWNORMAL);
6215c6c1daeSBarry Smith   UpdateWindow(hWnd);
6225c6c1daeSBarry Smith   SetEvent(windraw->hReadyEvent);
6235c6c1daeSBarry Smith 
6245c6c1daeSBarry Smith   while (GetMessage(&msg, hWnd, 0, 0)) {
6255c6c1daeSBarry Smith     TranslateMessage(&msg);
6265c6c1daeSBarry Smith     DispatchMessage(&msg);
6275c6c1daeSBarry Smith   }
628f9baa8adSSatish Balay   return;
6295c6c1daeSBarry Smith }
6305c6c1daeSBarry Smith 
631*bb09dc67SDuncan Campbell static struct _PetscDrawOps DvOps = {PetscDrawSetDoubleBuffer_Win32, PetscDrawFlush_Win32, PetscDrawLine_Win32, PetscDrawLineSetWidth_Win32, PetscDrawLineGetWidth_Win32, PetscDrawPoint_Win32, PetscDrawPointSetSize_Win32, PetscDrawString_Win32, PetscDrawStringVertical_Win32, PetscDrawStringSetSize_Win32, PetscDrawStringGetSize_Win32, 0, PetscDrawClear_Win32, PetscDrawRectangle_Win32, PetscDrawTriangle_Win32, 0, PetscDrawGetMouseButton_Win32, PetscDrawPause_Win32, 0, 0, PetscDrawGetPopup_Win32, PetscDrawSetTitle_Win32, PetscDrawCheckResizedWindow_Win32, PetscDrawResizeWindow_Win32, PetscDrawDestroy_Win32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PetscDrawSetVisible_Win32};
6325c6c1daeSBarry Smith 
633d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw, PetscDraw *popup)
634d71ae5a4SJacob Faibussowitsch {
6354a5237bfSSatish Balay   PetscDraw_Win32 *win = (PetscDraw_Win32 *)draw->data;
6364a5237bfSSatish Balay   PetscBool        flg = PETSC_TRUE;
6375c6c1daeSBarry Smith 
6385c6c1daeSBarry Smith   PetscFunctionBegin;
6399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, ((PetscObject)draw)->prefix, "-draw_popup", &flg, NULL));
6404a5237bfSSatish Balay   if (flg) {
6419566063dSJacob Faibussowitsch     PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)draw), NULL, NULL, win->x, win->y + win->h + 36, 220, 220, popup));
6429566063dSJacob Faibussowitsch     PetscCall(PetscDrawSetType(*popup, PETSC_DRAW_WIN32));
6434a5237bfSSatish Balay     draw->popup = *popup;
6444a5237bfSSatish Balay   } else {
6454a5237bfSSatish Balay     *popup = NULL;
6464a5237bfSSatish Balay   }
6473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6485c6c1daeSBarry Smith }
649d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
650d71ae5a4SJacob Faibussowitsch {
6515c6c1daeSBarry Smith   PetscDraw_Win32 *windraw;
6525c6c1daeSBarry Smith   HANDLE           hThread = NULL;
6535c6c1daeSBarry Smith   WindowNode       newnode;
6545c6c1daeSBarry Smith 
6555c6c1daeSBarry Smith   PetscFunctionBegin;
6569566063dSJacob Faibussowitsch   PetscCall(PetscNew(&windraw));
6575c6c1daeSBarry Smith   draw->data = windraw;
6585c6c1daeSBarry Smith 
6595c6c1daeSBarry Smith   /* the following is temporary fix for initializing a global datastructure */
660a297a907SKarl Rupp   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL, FALSE, NULL);
6619566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(draw->ops, &DvOps, sizeof(DvOps)));
6625c6c1daeSBarry Smith 
6635c6c1daeSBarry Smith   windraw->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
6645c6c1daeSBarry Smith   /* makes call to MessageLoopThread to creat window and attach a thread */
66513d99558SMatthew G. Knepley   CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLoopThread_Win32, draw, 0, (LPDWORD)hThread);
6665c6c1daeSBarry Smith   CloseHandle(hThread);
6675c6c1daeSBarry Smith   WaitForSingleObject(windraw->hReadyEvent, INFINITE);
6685c6c1daeSBarry Smith   CloseHandle(windraw->hReadyEvent);
6695c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
6705c6c1daeSBarry Smith 
6719566063dSJacob Faibussowitsch   PetscCall(PetscNew(&newnode));
6725c6c1daeSBarry Smith   newnode->MouseListHead = NULL;
6735c6c1daeSBarry Smith   newnode->MouseListTail = NULL;
6745c6c1daeSBarry Smith   newnode->wnext         = WindowListHead;
6755c6c1daeSBarry Smith   newnode->wprev         = NULL;
6765c6c1daeSBarry Smith   newnode->hWnd          = windraw->hWnd;
6776c4ed002SBarry Smith   if (WindowListHead) WindowListHead->wprev = newnode;
6785c6c1daeSBarry Smith   WindowListHead = newnode;
6795c6c1daeSBarry Smith   windraw->hdc   = GetDC(windraw->hWnd);
6805c6c1daeSBarry Smith 
6815c6c1daeSBarry Smith   windraw->stringheight  = 10;
6825c6c1daeSBarry Smith   windraw->stringwidth   = 6;
6835c6c1daeSBarry Smith   windraw->linewidth     = 1; /* default pixel sizes of graphics until user changes them */
6845c6c1daeSBarry Smith   windraw->pointdiameter = 1;
6855c6c1daeSBarry Smith   windraw->node          = newnode;
6865c6c1daeSBarry Smith 
6875c6c1daeSBarry Smith   windraw->x = draw->x;
6885c6c1daeSBarry Smith   windraw->y = draw->y;
6895c6c1daeSBarry Smith   windraw->w = newnode->bitwidth = draw->w;
6905c6c1daeSBarry Smith   windraw->h = newnode->bitheight = draw->h;
6915c6c1daeSBarry Smith 
6925c6c1daeSBarry Smith   /* Create and initialize primary graphics buffer */
6935c6c1daeSBarry Smith   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
6945c6c1daeSBarry Smith   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc, windraw->w, windraw->h);
6955c6c1daeSBarry Smith   newnode->store     = SelectObject(newnode->Buffer, newnode->BufferBit);
6965c6c1daeSBarry Smith   ExtFloodFill(newnode->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
6975c6c1daeSBarry Smith 
6985c6c1daeSBarry Smith   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
6995c6c1daeSBarry Smith   newnode->DoubleBuffered = PETSC_FALSE;
7005c6c1daeSBarry Smith 
7015c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, windraw->hdc);
7025c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
7033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7045c6c1daeSBarry Smith }
7055c6c1daeSBarry Smith 
7065c6c1daeSBarry Smith /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
7075c6c1daeSBarry Smith    PURPOSE:  Processes messages for the main window.
7085c6c1daeSBarry Smith    WM_COMMAND  - process the application menu
7095c6c1daeSBarry Smith    WM_PAINT    - Paint the main window
7105c6c1daeSBarry Smith    WM_DESTROY  - post a quit message and return */
7115c6c1daeSBarry Smith 
712d71ae5a4SJacob Faibussowitsch LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
713d71ae5a4SJacob Faibussowitsch {
7147ae38d14SSatish Balay   int wmId;
7155c6c1daeSBarry Smith 
7165c6c1daeSBarry Smith   switch (message) {
7175c6c1daeSBarry Smith     HANDLE_MSG(hWnd, WM_PAINT, OnPaint_Win32);
7185c6c1daeSBarry Smith     HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy_Win32);
7195c6c1daeSBarry Smith   case WM_COMMAND:
7205c6c1daeSBarry Smith     wmId = LOWORD(wParam);
7215c6c1daeSBarry Smith     /* Parse the menu selections:*/
7225c6c1daeSBarry Smith     switch (wmId) {
723d71ae5a4SJacob Faibussowitsch     case IDM_EXIT:
724d71ae5a4SJacob Faibussowitsch       DestroyWindow(hWnd);
725d71ae5a4SJacob Faibussowitsch       break;
726d71ae5a4SJacob Faibussowitsch     default:
727d71ae5a4SJacob Faibussowitsch       return DefWindowProc(hWnd, message, wParam, lParam);
7285c6c1daeSBarry Smith     }
7295c6c1daeSBarry Smith     break;
730d71ae5a4SJacob Faibussowitsch   case WM_LBUTTONUP:
731d71ae5a4SJacob Faibussowitsch     MouseRecord_Win32(hWnd, PETSC_BUTTON_LEFT);
732d71ae5a4SJacob Faibussowitsch     break;
733d71ae5a4SJacob Faibussowitsch   case WM_RBUTTONUP:
734d71ae5a4SJacob Faibussowitsch     MouseRecord_Win32(hWnd, PETSC_BUTTON_RIGHT);
735d71ae5a4SJacob Faibussowitsch     break;
736d71ae5a4SJacob Faibussowitsch   case WM_MBUTTONUP:
737d71ae5a4SJacob Faibussowitsch     MouseRecord_Win32(hWnd, PETSC_BUTTON_CENTER);
738d71ae5a4SJacob Faibussowitsch     break;
739d71ae5a4SJacob Faibussowitsch   default:
740d71ae5a4SJacob Faibussowitsch     return DefWindowProc(hWnd, message, wParam, lParam);
7415c6c1daeSBarry Smith   }
742f9baa8adSSatish Balay   return 0;
7435c6c1daeSBarry Smith }
7445c6c1daeSBarry Smith 
745d71ae5a4SJacob Faibussowitsch static void OnPaint_Win32(HWND hWnd)
746d71ae5a4SJacob Faibussowitsch {
7475c6c1daeSBarry Smith   PAINTSTRUCT ps;
7485c6c1daeSBarry Smith   HDC         hdc;
7495c6c1daeSBarry Smith   WindowNode  current = NULL;
7505c6c1daeSBarry Smith 
7515c6c1daeSBarry Smith   InvalidateRect(hWnd, NULL, TRUE);
7525c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
7535c6c1daeSBarry Smith   current = WindowListHead;
7545c6c1daeSBarry Smith   hdc     = BeginPaint(hWnd, &ps);
7555c6c1daeSBarry Smith 
7566c4ed002SBarry Smith   while (current) {
7575c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
7585c6c1daeSBarry Smith       /* flushes primary buffer to window */
7599371c9d4SSatish Balay       BitBlt(hdc, 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), current->Buffer, 0, 0, SRCCOPY);
7605c6c1daeSBarry Smith 
761be332245SKarl Rupp       /* StretchBlt(hdc,0,0,w,h,
762be332245SKarl Rupp         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
7635c6c1daeSBarry Smith       break;
7645c6c1daeSBarry Smith     }
7655c6c1daeSBarry Smith     current = current->wnext;
7665c6c1daeSBarry Smith   }
7675c6c1daeSBarry Smith   EndPaint(hWnd, &ps);
7685c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
769f9baa8adSSatish Balay   return;
7705c6c1daeSBarry Smith }
7715c6c1daeSBarry Smith 
772d71ae5a4SJacob Faibussowitsch static PetscErrorCode MouseRecord_Win32(HWND hWnd, PetscDrawButton button)
773d71ae5a4SJacob Faibussowitsch {
7745c6c1daeSBarry Smith   /* Called by all three mouse button actions
7755c6c1daeSBarry Smith     Records needed mouse data in windows data structure */
7765c6c1daeSBarry Smith   WindowNode current = NULL;
7775c6c1daeSBarry Smith   MouseNode  newnode;
7785c6c1daeSBarry Smith   POINT      mousepos;
7795c6c1daeSBarry Smith 
7805c6c1daeSBarry Smith   PetscFunctionBegin;
7815c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
7825c6c1daeSBarry Smith   current = WindowListHead;
7835c6c1daeSBarry Smith   if (current->IsGetMouseOn == TRUE) {
7845c6c1daeSBarry Smith     SetEvent(current->event);
7856c4ed002SBarry Smith     while (current) {
7865c6c1daeSBarry Smith       if (current->hWnd == hWnd) {
7879566063dSJacob Faibussowitsch         PetscCall(PetscNew(&newnode));
7885c6c1daeSBarry Smith         newnode->Button = button;
7895c6c1daeSBarry Smith         GetCursorPos(&mousepos);
7905c6c1daeSBarry Smith         newnode->user.x = mousepos.x;
7915c6c1daeSBarry Smith         newnode->user.y = mousepos.y;
7925c6c1daeSBarry Smith         ScreenToClient(hWnd, &mousepos);
7935c6c1daeSBarry Smith         newnode->phys.x = mousepos.x;
7945c6c1daeSBarry Smith         newnode->phys.y = mousepos.y;
7955c6c1daeSBarry Smith         if (!current->MouseListTail) {
7965c6c1daeSBarry Smith           current->MouseListHead = newnode;
7975c6c1daeSBarry Smith           current->MouseListTail = newnode;
7985c6c1daeSBarry Smith         } else {
7995c6c1daeSBarry Smith           current->MouseListTail->mnext = newnode;
8005c6c1daeSBarry Smith           current->MouseListTail        = newnode;
8015c6c1daeSBarry Smith         }
8025c6c1daeSBarry Smith         newnode->mnext = NULL;
8035c6c1daeSBarry Smith 
8045c6c1daeSBarry Smith         break;
8055c6c1daeSBarry Smith       }
8065c6c1daeSBarry Smith       current = current->wnext;
8075c6c1daeSBarry Smith     }
8085c6c1daeSBarry Smith   }
8095c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
8103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8115c6c1daeSBarry Smith }
8125c6c1daeSBarry Smith 
813d71ae5a4SJacob Faibussowitsch static void OnDestroy_Win32(HWND hWnd)
814d71ae5a4SJacob Faibussowitsch {
8155c6c1daeSBarry Smith   /* searches linked list of window data and frees corresponding memory */
8165c6c1daeSBarry Smith   WindowNode current;
8175c6c1daeSBarry Smith 
8185c6c1daeSBarry Smith   PetscFunctionBegin;
8195c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
8205c6c1daeSBarry Smith   current = WindowListHead;
8215c6c1daeSBarry Smith 
8225c6c1daeSBarry Smith   SetEvent(current->event);
8236c4ed002SBarry Smith   while (current) {
8245c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
8256c4ed002SBarry Smith       if (current->wprev) current->wprev->wnext = current->wnext;
826a297a907SKarl Rupp       else WindowListHead = current->wnext;
827a297a907SKarl Rupp       if (current->MouseListHead) deletemouselist_Win32(current);
828a297a907SKarl Rupp       else PetscFree(current);
8295c6c1daeSBarry Smith       break;
8305c6c1daeSBarry Smith     }
8315c6c1daeSBarry Smith     current = current->wnext;
8325c6c1daeSBarry Smith   }
8335c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
8345c6c1daeSBarry Smith   PostQuitMessage(0);
8355c6c1daeSBarry Smith   PetscFunctionReturnVoid();
8365c6c1daeSBarry Smith }
837