xref: /petsc/src/sys/classes/draw/impls/win32/win32draw.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 
25*9371c9d4SSatish 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))))
26*9371c9d4SSatish 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 
375c6c1daeSBarry Smith /* Foward 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 
48*9371c9d4SSatish Balay static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw) {
495c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
505c6c1daeSBarry Smith   HDC              hdc     = GetDC(windraw->hWnd);
515c6c1daeSBarry Smith 
525c6c1daeSBarry Smith   PetscFunctionBegin;
535c6c1daeSBarry Smith   windraw->node->DoubleBuffer    = CreateCompatibleDC(hdc);
545c6c1daeSBarry Smith   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc, windraw->w, windraw->h);
555c6c1daeSBarry Smith   windraw->node->dbstore         = SelectObject(windraw->node->DoubleBuffer, windraw->node->DoubleBufferBit);
565c6c1daeSBarry Smith   /* Fill background of second buffer */
575c6c1daeSBarry Smith   ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
585c6c1daeSBarry Smith   /* Copy current buffer into seconf buffer and set window data as double buffered */
59*9371c9d4SSatish Balay   BitBlt(windraw->node->DoubleBuffer, 0, 0, windraw->w, windraw->h, windraw->node->Buffer, 0, 0, SRCCOPY);
605c6c1daeSBarry Smith 
615c6c1daeSBarry Smith   windraw->node->DoubleBuffered = PETSC_TRUE;
625c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, hdc);
635c6c1daeSBarry Smith   PetscFunctionReturn(0);
645c6c1daeSBarry Smith }
655c6c1daeSBarry Smith 
66*9371c9d4SSatish Balay static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw) {
675c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
685c6c1daeSBarry Smith   HDC              hdc     = GetDC(windraw->hWnd);
695c6c1daeSBarry Smith 
705c6c1daeSBarry Smith   PetscFunctionBegin;
715c6c1daeSBarry Smith   /* flush double buffer into primary buffer */
72*9371c9d4SSatish Balay   BitBlt(windraw->node->Buffer, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
735c6c1daeSBarry Smith   /* flush double buffer into window */
74*9371c9d4SSatish Balay   BitBlt(hdc, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
755c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, hdc);
765c6c1daeSBarry Smith   PetscFunctionReturn(0);
775c6c1daeSBarry Smith }
785c6c1daeSBarry Smith 
79*9371c9d4SSatish Balay static PetscErrorCode deletemouselist_Win32(WindowNode deletelist) {
805c6c1daeSBarry Smith   /* Called upon window close. Frees memory of linked list of stored mouse commands */
815c6c1daeSBarry Smith   MouseNode node;
825c6c1daeSBarry Smith 
836c4ed002SBarry Smith   while (deletelist->MouseListHead) {
845c6c1daeSBarry Smith     node = deletelist->MouseListHead;
856c4ed002SBarry Smith     if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
865c6c1daeSBarry Smith     PetscFree(node);
875c6c1daeSBarry Smith   }
885c6c1daeSBarry Smith   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
896c4ed002SBarry Smith   if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
906c4ed002SBarry Smith   if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
915c6c1daeSBarry Smith   PetscFree(deletelist);
925c6c1daeSBarry Smith   return 0;
935c6c1daeSBarry Smith }
945c6c1daeSBarry Smith 
95*9371c9d4SSatish Balay static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button, PetscReal *x_user, PetscReal *y_user, PetscReal *x_phys, PetscReal *y_phys) {
965c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
975c6c1daeSBarry Smith   WindowNode       current;
985c6c1daeSBarry Smith   MouseNode        node = 0;
995c6c1daeSBarry Smith 
1005c6c1daeSBarry Smith   PetscFunctionBegin;
1015c6c1daeSBarry Smith   /* Make sure no other code is using the linked list at this moment */
1025c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1035c6c1daeSBarry Smith   /* Look for the node that matches the window you are using */
1045c6c1daeSBarry Smith   current = WindowListHead;
1056c4ed002SBarry Smith   while (current) {
1065c6c1daeSBarry Smith     if (current->hWnd == windraw->hWnd) {
1075c6c1daeSBarry Smith       current->IsGetMouseOn = TRUE;
1085c6c1daeSBarry Smith       break;
109a297a907SKarl Rupp     } else current = current->wnext;
1105c6c1daeSBarry Smith   }
111a5b23f4aSJose E. Roman   /* If no actions have occurred, wait for one */
1125c6c1daeSBarry Smith   node = current->MouseListHead;
1135c6c1daeSBarry Smith   if (!node) {
1145c6c1daeSBarry Smith     ReleaseMutex(g_hWindowListMutex);
1155c6c1daeSBarry Smith     WaitForSingleObject(current->event, INFINITE);
1165c6c1daeSBarry Smith     WaitForSingleObject(g_hWindowListMutex, INFINITE);
1175c6c1daeSBarry Smith   }
1185c6c1daeSBarry Smith   /* once we have the information, assign the pointers to it */
1195c6c1daeSBarry Smith   *button = current->MouseListHead->Button;
1205c6c1daeSBarry Smith   *x_user = current->MouseListHead->user.x;
1215c6c1daeSBarry Smith   *y_user = current->MouseListHead->user.y;
1225c6c1daeSBarry Smith   /* optional arguments */
1235c6c1daeSBarry Smith   if (x_phys) *x_phys = current->MouseListHead->phys.x;
1245c6c1daeSBarry Smith   if (y_phys) *y_phys = current->MouseListHead->phys.y;
1255c6c1daeSBarry Smith   /* remove set of information from sub linked-list, delete the node */
1265c6c1daeSBarry Smith   current->MouseListHead = current->MouseListHead->mnext;
1275c6c1daeSBarry Smith   if (!current->MouseListHead) {
1285c6c1daeSBarry Smith     ResetEvent(current->event);
1295c6c1daeSBarry Smith     current->MouseListTail = NULL;
1305c6c1daeSBarry Smith   }
1315c6c1daeSBarry Smith   if (node) PetscFree(node);
1325c6c1daeSBarry Smith 
1335c6c1daeSBarry Smith   /* Release mutex so that  other code can use
1345c6c1daeSBarry Smith      the linked list now that we are done with it */
1355c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
1365c6c1daeSBarry Smith   PetscFunctionReturn(0);
1375c6c1daeSBarry Smith }
1385c6c1daeSBarry Smith 
139*9371c9d4SSatish Balay static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw) {
1405c6c1daeSBarry Smith   PetscFunctionBegin;
1415c6c1daeSBarry Smith   PetscSleep(draw->pause);
1425c6c1daeSBarry Smith   PetscFunctionReturn(0);
1435c6c1daeSBarry Smith }
1445c6c1daeSBarry Smith 
145*9371c9d4SSatish Balay static PetscErrorCode TranslateColor_Win32(PetscDraw draw, int color) {
1465c6c1daeSBarry Smith   /* Maps single color value into the RGB colors in our tables */
1475c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1485c6c1daeSBarry Smith   windraw->currentcolor    = RGB(RedMap[color], GreenMap[color], BlueMap[color]);
1495c6c1daeSBarry Smith   return 0;
1505c6c1daeSBarry Smith }
1515c6c1daeSBarry Smith 
152*9371c9d4SSatish Balay static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw, int c1, int c2, int c3, int c4) {
1535c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
1545c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
1555c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
156*9371c9d4SSatish 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));
1575c6c1daeSBarry Smith   return 0;
1585c6c1daeSBarry Smith }
1595c6c1daeSBarry Smith 
160*9371c9d4SSatish Balay static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw, int c1, int c2, int c3) {
1615c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
1625c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
1635c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
164*9371c9d4SSatish 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);
1655c6c1daeSBarry Smith   return 0;
1665c6c1daeSBarry Smith }
1675c6c1daeSBarry Smith 
168*9371c9d4SSatish Balay static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4) {
1695c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1705c6c1daeSBarry Smith   HBRUSH           hbrush;
1715c6c1daeSBarry Smith   RECT             rect;
1725c6c1daeSBarry Smith   int              x1, yone, x2, y2;
1735c6c1daeSBarry Smith   HDC              hdc;
1745c6c1daeSBarry Smith 
1755c6c1daeSBarry Smith   PetscFunctionBegin;
1765c6c1daeSBarry Smith   x1   = XTRANS(draw, windraw, xl);
1775c6c1daeSBarry Smith   x2   = XTRANS(draw, windraw, xr);
1785c6c1daeSBarry Smith   yone = YTRANS(draw, windraw, yl);
1795c6c1daeSBarry Smith   y2   = YTRANS(draw, windraw, yr);
1805c6c1daeSBarry Smith   SetRect(&rect, x1, y2, x2, yone);
181a297a907SKarl Rupp   if (c1 == c2 && c2 == c3 && c3 == c4) TranslateColor_Win32(draw, c1);
182a297a907SKarl Rupp   else AverageColorRectangle_Win32(draw, c1, c2, c3, c4);
1835c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
1845c6c1daeSBarry Smith 
185a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
186a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
187a297a907SKarl Rupp 
1885c6c1daeSBarry Smith   FillRect(hdc, &rect, hbrush);
1895c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
1905c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
1915c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
1925c6c1daeSBarry Smith   PetscFunctionReturn(0);
1935c6c1daeSBarry Smith }
1945c6c1daeSBarry Smith 
195*9371c9d4SSatish Balay static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int color) {
1965c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1975c6c1daeSBarry Smith   HPEN             hpen;
1985c6c1daeSBarry Smith   int              x1, yone, x2, y2;
1995c6c1daeSBarry Smith   HDC              hdc;
2005c6c1daeSBarry Smith 
2015c6c1daeSBarry Smith   PetscFunctionBegin;
2025c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
203*9371c9d4SSatish Balay   x1   = XTRANS(draw, windraw, xl);
204*9371c9d4SSatish Balay   x2   = XTRANS(draw, windraw, xr);
205*9371c9d4SSatish Balay   yone = YTRANS(draw, windraw, yl);
206*9371c9d4SSatish Balay   y2   = YTRANS(draw, windraw, yr);
2075c6c1daeSBarry Smith   hpen = CreatePen(PS_SOLID, windraw->linewidth, windraw->currentcolor);
208a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
209a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
210a297a907SKarl Rupp 
2115c6c1daeSBarry Smith   SelectPen(hdc, hpen);
2125c6c1daeSBarry Smith   MoveToEx(hdc, x1, yone, NULL);
2135c6c1daeSBarry Smith   LineTo(hdc, x2, y2);
2145c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
2155c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
2165c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2175c6c1daeSBarry Smith   PetscFunctionReturn(0);
2185c6c1daeSBarry Smith }
2195c6c1daeSBarry Smith 
220*9371c9d4SSatish Balay static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw, PetscReal width) {
2215c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2225c6c1daeSBarry Smith   int              averagesize, finalwidth;
2235c6c1daeSBarry Smith   RECT             rect;
2245c6c1daeSBarry Smith 
2255c6c1daeSBarry Smith   PetscFunctionBegin;
2265c6c1daeSBarry Smith   GetClientRect(windraw->hWnd, &rect);
2275c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
22877b4d14cSPeter Brune   finalwidth  = (int)PetscFloorReal(averagesize * width);
229a297a907SKarl Rupp   if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */
230a297a907SKarl Rupp 
2315c6c1daeSBarry Smith   windraw->linewidth = finalwidth;
2325c6c1daeSBarry Smith   PetscFunctionReturn(0);
2335c6c1daeSBarry Smith }
2345c6c1daeSBarry Smith 
235*9371c9d4SSatish Balay static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw, PetscReal *width) {
2365c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2375c6c1daeSBarry Smith 
2385c6c1daeSBarry Smith   PetscFunctionBegin;
2395c6c1daeSBarry Smith   *width = (PetscReal)windraw->linewidth;
2405c6c1daeSBarry Smith   PetscFunctionReturn(0);
2415c6c1daeSBarry Smith }
2425c6c1daeSBarry Smith 
243*9371c9d4SSatish Balay static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color) {
2445c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2455c6c1daeSBarry Smith   HBRUSH           hbrush;
2465c6c1daeSBarry Smith   HRGN             hrgn;
2475c6c1daeSBarry Smith   int              radius;
2485c6c1daeSBarry Smith   int              x1, yone;
2495c6c1daeSBarry Smith   HDC              hdc;
2505c6c1daeSBarry Smith 
2515c6c1daeSBarry Smith   PetscFunctionBegin;
2525c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
2535c6c1daeSBarry Smith   x1     = XTRANS(draw, windraw, x);
2545c6c1daeSBarry Smith   yone   = YTRANS(draw, windraw, y);
2555c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
256a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
257a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
258a297a907SKarl Rupp 
2595c6c1daeSBarry Smith   /* desired size is one logical pixel so just turn it on */
260a297a907SKarl Rupp   if (windraw->pointdiameter == 1) SetPixelV(hdc, x1, yone, windraw->currentcolor);
261a297a907SKarl Rupp   else {
2625c6c1daeSBarry Smith     /* draw point around position determined */
2635c6c1daeSBarry Smith     radius = windraw->pointdiameter / 2; /* integer division */
2645c6c1daeSBarry Smith     hrgn   = CreateEllipticRgn(x1 - radius, yone - radius, x1 + radius, yone + radius);
2655c6c1daeSBarry Smith     FillRgn(hdc, hrgn, hbrush);
2665c6c1daeSBarry Smith   }
2675c6c1daeSBarry Smith   /* Forces a WM_PAINT and erases background */
2685c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
2695c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2705c6c1daeSBarry Smith   PetscFunctionReturn(0);
2715c6c1daeSBarry Smith }
2725c6c1daeSBarry Smith 
273*9371c9d4SSatish Balay static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw, PetscReal width) {
2745c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2755c6c1daeSBarry Smith   int              averagesize, diameter;
2765c6c1daeSBarry Smith   RECT             rect;
2775c6c1daeSBarry Smith 
2785c6c1daeSBarry Smith   PetscFunctionBegin;
2795c6c1daeSBarry Smith   GetClientRect(windraw->hWnd, &rect);
2805c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
28177b4d14cSPeter Brune   diameter    = (int)PetscFloorReal(averagesize * width);
2825c6c1daeSBarry Smith   if (diameter < 1) diameter = 1;
2835c6c1daeSBarry Smith   windraw->pointdiameter = diameter;
2845c6c1daeSBarry Smith   PetscFunctionReturn(0);
2855c6c1daeSBarry Smith }
2865c6c1daeSBarry Smith 
287*9371c9d4SSatish Balay static PetscErrorCode PetscDrawString_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text) {
2885c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2895c6c1daeSBarry Smith   RECT             r;
2905c6c1daeSBarry Smith   HFONT            hfont;
2915c6c1daeSBarry Smith   LOGFONT          logfont;
2925c6c1daeSBarry Smith   int              x1, yone;
2935c6c1daeSBarry Smith   HDC              hdc;
2945c6c1daeSBarry Smith 
2955c6c1daeSBarry Smith   PetscFunctionBegin;
2965c6c1daeSBarry Smith   x1       = XTRANS(draw, windraw, x);
2975c6c1daeSBarry Smith   yone     = YTRANS(draw, windraw, y);
2985c6c1daeSBarry Smith   r.bottom = yone;
2995c6c1daeSBarry Smith   r.left   = x1;
3005c6c1daeSBarry Smith   r.right  = x1 + 1;
3015c6c1daeSBarry Smith   r.top    = yone + 1;
302a297a907SKarl Rupp 
3035c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3045c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3055c6c1daeSBarry Smith   logfont.lfEscapement     = 0;
3065c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3075c6c1daeSBarry Smith   logfont.lfCharSet        = 0;
3085c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3095c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3105c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3115c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3125c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3135c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3145c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3155c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
316a297a907SKarl Rupp 
3175c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3185c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
319a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
320a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
321a297a907SKarl Rupp 
3225c6c1daeSBarry Smith   SelectFont(hdc, hfont);
3235c6c1daeSBarry Smith   SetTextColor(hdc, windraw->currentcolor);
3245c6c1daeSBarry Smith   DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP);
3255c6c1daeSBarry Smith   DeleteObject(hfont);
3265c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3275c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
3285c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
3295c6c1daeSBarry Smith   PetscFunctionReturn(0);
3305c6c1daeSBarry Smith }
3315c6c1daeSBarry Smith 
332*9371c9d4SSatish Balay static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text) {
3335c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3345c6c1daeSBarry Smith   RECT             r;
3355c6c1daeSBarry Smith   HFONT            hfont;
3365c6c1daeSBarry Smith   LOGFONT          logfont;
3375c6c1daeSBarry Smith   int              x1, yone;
3385c6c1daeSBarry Smith   HDC              hdc;
3395c6c1daeSBarry Smith 
3405c6c1daeSBarry Smith   PetscFunctionBegin;
3415c6c1daeSBarry Smith   x1       = XTRANS(draw, windraw, x);
3425c6c1daeSBarry Smith   yone     = YTRANS(draw, windraw, y);
3435c6c1daeSBarry Smith   r.left   = x1;
3445c6c1daeSBarry Smith   r.bottom = yone + 30;
3455c6c1daeSBarry Smith   r.right  = x1 + 1;
3465c6c1daeSBarry Smith   r.top    = yone - 30;
347a297a907SKarl Rupp 
3485c6c1daeSBarry Smith   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
3495c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3505c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3515c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3525c6c1daeSBarry Smith   logfont.lfCharSet        = DEFAULT_CHARSET;
3535c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3545c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3555c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3565c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3575c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3585c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3595c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3605c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
361a297a907SKarl Rupp 
3625c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3635c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
364a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
365a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
366a297a907SKarl Rupp 
3675c6c1daeSBarry Smith   SelectFont(hdc, hfont);
3685c6c1daeSBarry Smith   SetTextColor(hdc, windraw->currentcolor);
3695c6c1daeSBarry Smith   DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP | DT_SINGLELINE);
3705c6c1daeSBarry Smith   DeleteObject(hfont);
3715c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3725c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
3735c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
3745c6c1daeSBarry Smith   PetscFunctionReturn(0);
3755c6c1daeSBarry Smith }
3765c6c1daeSBarry Smith 
377*9371c9d4SSatish Balay static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw, PetscReal width, PetscReal height) {
3785c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3795c6c1daeSBarry Smith   int              w, h;
3805c6c1daeSBarry Smith 
3815c6c1daeSBarry Smith   PetscFunctionBegin;
3825c6c1daeSBarry Smith   w = (int)((windraw->w) * width * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl));
3835c6c1daeSBarry Smith   h = (int)((windraw->h) * height * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl));
3845c6c1daeSBarry Smith   if (h < 1) h = 1;
3855c6c1daeSBarry Smith   if (w < 1) w = 1;
3865c6c1daeSBarry Smith   windraw->stringheight = h;
3875c6c1daeSBarry Smith   windraw->stringwidth  = w;
3885c6c1daeSBarry Smith   PetscFunctionReturn(0);
3895c6c1daeSBarry Smith }
390*9371c9d4SSatish Balay static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw, PetscReal *width, PetscReal *height) {
3915c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3925c6c1daeSBarry Smith   double           scaleX  = (draw->coor_xr - draw->coor_xl) / (draw->w) * (draw->port_xr - draw->port_xl);
3935c6c1daeSBarry Smith   double           scaleY  = (draw->coor_yr - draw->coor_yl) / (draw->h) * (draw->port_yr - draw->port_yl);
3945c6c1daeSBarry Smith 
3955c6c1daeSBarry Smith   PetscFunctionBegin;
3964a5237bfSSatish Balay   if (height) *height = (double)windraw->stringheight * scaleY;
3974a5237bfSSatish Balay   if (width) *width = (double)windraw->stringwidth * scaleX;
3985c6c1daeSBarry Smith   PetscFunctionReturn(0);
3995c6c1daeSBarry Smith }
4005c6c1daeSBarry Smith 
401*9371c9d4SSatish Balay static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw, int w, int h) {
4025c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4035c6c1daeSBarry Smith   RECT             r;
4045c6c1daeSBarry Smith 
4055c6c1daeSBarry Smith   PetscFunctionBegin;
4065c6c1daeSBarry Smith   GetWindowRect(windraw->hWnd, &r);
4075c6c1daeSBarry Smith   MoveWindow(windraw->hWnd, r.left, r.top, (int)w, (int)h, TRUE);
4085c6c1daeSBarry Smith   /* set all variable dealing with window dimensions */
4095c6c1daeSBarry Smith   windraw->node->bitheight = windraw->h = draw->h = h;
4105c6c1daeSBarry Smith   windraw->node->bitwidth = windraw->w = draw->w = w;
4115c6c1daeSBarry Smith   /* set up graphic buffers with the new size of window */
4125c6c1daeSBarry Smith   SetBitmapDimensionEx(windraw->node->BufferBit, w, h, NULL);
413a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit, w, h, NULL);
4145c6c1daeSBarry Smith   windraw->haveresized = PETSC_TRUE;
4155c6c1daeSBarry Smith   PetscFunctionReturn(0);
4165c6c1daeSBarry Smith }
4175c6c1daeSBarry Smith 
418*9371c9d4SSatish Balay static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw) {
4195c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4205c6c1daeSBarry Smith 
4215c6c1daeSBarry Smith   PetscFunctionBegin;
422a297a907SKarl Rupp   if (windraw->haveresized == 1) PetscFunctionReturn(1);
423a297a907SKarl Rupp   else PetscFunctionReturn(0);
4245c6c1daeSBarry Smith }
4255c6c1daeSBarry Smith 
426*9371c9d4SSatish Balay static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[]) {
4275c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4285c6c1daeSBarry Smith 
4295c6c1daeSBarry Smith   PetscFunctionBegin;
4305c6c1daeSBarry Smith   SetWindowText(windraw->hWnd, title);
4315c6c1daeSBarry Smith   PetscFunctionReturn(0);
4325c6c1daeSBarry Smith }
4335c6c1daeSBarry Smith 
434*9371c9d4SSatish Balay static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw) {
4355c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4365c6c1daeSBarry Smith 
4375c6c1daeSBarry Smith   PetscFunctionBegin;
4385c6c1daeSBarry Smith   /* clear primary buffer */
4395c6c1daeSBarry Smith   ExtFloodFill(windraw->node->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
4405c6c1daeSBarry Smith   /* if exists clear secondary buffer */
441a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
442a297a907SKarl Rupp 
4435c6c1daeSBarry Smith   /* force WM_PAINT message so cleared buffer will show */
4445c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
4455c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
4465c6c1daeSBarry Smith   PetscFunctionReturn(0);
4475c6c1daeSBarry Smith }
4485c6c1daeSBarry Smith 
449*9371c9d4SSatish Balay static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw, PetscReal x1, PetscReal yone, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3) {
4505c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4515c6c1daeSBarry Smith   HBRUSH           hbrush;
4525c6c1daeSBarry Smith   HPEN             hpen;
4535c6c1daeSBarry Smith   int              p1x, p1y, p2x, p2y, p3x, p3y;
4545c6c1daeSBarry Smith   HDC              bit;
4555c6c1daeSBarry Smith 
4565c6c1daeSBarry Smith   PetscFunctionBegin;
4575c6c1daeSBarry Smith   AverageColorTriangle_Win32(draw, c1, c2, c3);
4585c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
4595c6c1daeSBarry Smith   hpen   = CreatePen(PS_SOLID, 0, windraw->currentcolor);
4605c6c1daeSBarry Smith   p1x    = XTRANS(draw, windraw, x1);
4615c6c1daeSBarry Smith   p2x    = XTRANS(draw, windraw, x2);
4625c6c1daeSBarry Smith   p3x    = XTRANS(draw, windraw, x3);
4635c6c1daeSBarry Smith   p1y    = YTRANS(draw, windraw, yone);
4645c6c1daeSBarry Smith   p2y    = YTRANS(draw, windraw, y2);
4655c6c1daeSBarry Smith   p3y    = YTRANS(draw, windraw, y3);
4665c6c1daeSBarry Smith 
467a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
468a297a907SKarl Rupp   else bit = windraw->node->Buffer;
469a297a907SKarl Rupp 
4705c6c1daeSBarry Smith   BeginPath(bit);
4715c6c1daeSBarry Smith   MoveToEx(bit, p1x, p1y, NULL);
4725c6c1daeSBarry Smith   LineTo(bit, p2x, p2y);
4735c6c1daeSBarry Smith   LineTo(bit, p3x, p3y);
4745c6c1daeSBarry Smith   LineTo(bit, p1x, p1y);
4755c6c1daeSBarry Smith   EndPath(bit);
4765c6c1daeSBarry Smith   SelectPen(bit, hpen);
4775c6c1daeSBarry Smith   SelectBrush(bit, hbrush);
4785c6c1daeSBarry Smith   StrokeAndFillPath(bit);
4795c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
4805c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
4815c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
4825c6c1daeSBarry Smith   PetscFunctionReturn(0);
4835c6c1daeSBarry Smith }
4845c6c1daeSBarry Smith 
485*9371c9d4SSatish Balay void PopMessageLoopThread_Win32(PetscDraw popdraw) {
4865c6c1daeSBarry Smith   PetscDraw_Win32 *pop = (PetscDraw_Win32 *)popdraw->data;
4875c6c1daeSBarry Smith   MSG              msg;
4885c6c1daeSBarry Smith   HWND             hWnd           = NULL;
489fad2a674SVolker   const char       PopClassName[] = "PETSc Window Pop Class";
4905c6c1daeSBarry Smith   RECT             r;
4915c6c1daeSBarry Smith   int              width, height;
4925c6c1daeSBarry Smith   WNDCLASSEX       myclass;
4935c6c1daeSBarry Smith   LPVOID           lpMsgBuf;
4945c6c1daeSBarry Smith 
4955c6c1daeSBarry Smith   PetscFunctionBegin;
4965c6c1daeSBarry Smith   /* initialize window class parameters */
4975c6c1daeSBarry Smith   myclass.cbSize        = sizeof(WNDCLASSEX);
4985c6c1daeSBarry Smith   myclass.style         = CS_OWNDC;
4995c6c1daeSBarry Smith   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
5005c6c1daeSBarry Smith   myclass.cbClsExtra    = 0;
5015c6c1daeSBarry Smith   myclass.cbWndExtra    = 0;
5025c6c1daeSBarry Smith   myclass.hInstance     = NULL;
5035c6c1daeSBarry Smith   myclass.hIcon         = NULL;
5045c6c1daeSBarry Smith   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
5055c6c1daeSBarry Smith   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
5065c6c1daeSBarry Smith   myclass.lpszMenuName  = NULL;
5075c6c1daeSBarry Smith   myclass.lpszClassName = PopClassName;
5085c6c1daeSBarry Smith   myclass.hIconSm       = NULL;
5095c6c1daeSBarry Smith 
5105c6c1daeSBarry Smith   RegisterClassEx(&myclass);
5115c6c1daeSBarry Smith 
5125c6c1daeSBarry Smith   SetRect(&r, 0, 0, 450, 450);
5135c6c1daeSBarry Smith 
5145c6c1daeSBarry Smith   width  = (r.right - r.left) / 3;
5155c6c1daeSBarry Smith   height = (r.bottom - r.top) / 3;
5165c6c1daeSBarry Smith 
517*9371c9d4SSatish Balay   hWnd   = CreateWindowEx(0, PopClassName, NULL, WS_POPUPWINDOW | WS_CAPTION, 0, 0, width, height, NULL, NULL, hInst, NULL);
5185c6c1daeSBarry Smith   pop->x = 0;
5195c6c1daeSBarry Smith   pop->y = 0;
5205c6c1daeSBarry Smith   pop->w = width;
5215c6c1daeSBarry Smith   pop->h = height;
5225c6c1daeSBarry Smith 
5235c6c1daeSBarry Smith   if (!hWnd) {
524fad2a674SVolker     lpMsgBuf = (LPVOID) "Window Not Successfully Created";
5255c6c1daeSBarry Smith     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
5265c6c1daeSBarry Smith     LocalFree(lpMsgBuf);
5275c6c1daeSBarry Smith     exit(0);
5285c6c1daeSBarry Smith   }
5295c6c1daeSBarry Smith   pop->hWnd = hWnd;
5305c6c1daeSBarry Smith   /* display and update new popup window */
5315c6c1daeSBarry Smith   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
5325c6c1daeSBarry Smith   UpdateWindow(pop->hWnd);
5335c6c1daeSBarry Smith   SetEvent(pop->hReadyEvent);
5345c6c1daeSBarry Smith 
5355c6c1daeSBarry Smith   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
5365c6c1daeSBarry Smith     TranslateMessage(&msg);
5375c6c1daeSBarry Smith     DispatchMessage(&msg);
5385c6c1daeSBarry Smith   }
5395c6c1daeSBarry Smith   PetscFunctionReturnVoid();
5405c6c1daeSBarry Smith }
5415c6c1daeSBarry Smith 
542*9371c9d4SSatish Balay static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw) {
5435c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
5445c6c1daeSBarry Smith 
5455c6c1daeSBarry Smith   PetscFunctionBegin;
5465c6c1daeSBarry Smith   SendMessage(windraw->hWnd, WM_DESTROY, 0, 0);
54750c74209SLisandro Dalcin   PetscFree(draw->data);
5485c6c1daeSBarry Smith   PetscFunctionReturn(0);
5495c6c1daeSBarry Smith }
5505c6c1daeSBarry Smith 
551*9371c9d4SSatish Balay void MessageLoopThread_Win32(PetscDraw draw) {
5525c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
5535c6c1daeSBarry Smith   MSG              msg;
5545c6c1daeSBarry Smith   HWND             hWnd        = NULL;
555fad2a674SVolker   const char       classname[] = "PETSc Window Class";
5565c6c1daeSBarry Smith   WNDCLASSEX       wclass;
5575c6c1daeSBarry Smith   LPVOID           lpMsgBuf;
5585c6c1daeSBarry Smith 
5595c6c1daeSBarry Smith   /* initialize window class parameters */
5605c6c1daeSBarry Smith   wclass.cbSize        = sizeof(WNDCLASSEX);
5615c6c1daeSBarry Smith   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
5625c6c1daeSBarry Smith   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
5635c6c1daeSBarry Smith   wclass.cbClsExtra    = 0;
5645c6c1daeSBarry Smith   wclass.cbWndExtra    = 0;
5655c6c1daeSBarry Smith   wclass.hInstance     = NULL;
5665c6c1daeSBarry Smith   wclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
5675c6c1daeSBarry Smith   wclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
5685c6c1daeSBarry Smith   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
5695c6c1daeSBarry Smith   wclass.lpszMenuName  = NULL;
5705c6c1daeSBarry Smith   wclass.lpszClassName = classname;
5715c6c1daeSBarry Smith   wclass.hIconSm       = NULL;
5725c6c1daeSBarry Smith 
5735c6c1daeSBarry Smith   RegisterClassEx(&wclass);
5745c6c1daeSBarry Smith 
575*9371c9d4SSatish Balay   hWnd = CreateWindowEx(0, classname, NULL, WS_OVERLAPPEDWINDOW, draw->x, draw->y, draw->w, draw->h, NULL, NULL, hInst, NULL);
5765c6c1daeSBarry Smith 
5775c6c1daeSBarry Smith   if (!hWnd) {
578fad2a674SVolker     lpMsgBuf = (LPVOID) "Window Not Successfully Created";
5795c6c1daeSBarry Smith     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
5805c6c1daeSBarry Smith     LocalFree(lpMsgBuf);
5815c6c1daeSBarry Smith     exit(0);
5825c6c1daeSBarry Smith   }
5835c6c1daeSBarry Smith   windraw->hWnd = hWnd;
5845c6c1daeSBarry Smith   /* display and update new window */
5855c6c1daeSBarry Smith   ShowWindow(hWnd, SW_SHOWNORMAL);
5865c6c1daeSBarry Smith   UpdateWindow(hWnd);
5875c6c1daeSBarry Smith   SetEvent(windraw->hReadyEvent);
5885c6c1daeSBarry Smith 
5895c6c1daeSBarry Smith   while (GetMessage(&msg, hWnd, 0, 0)) {
5905c6c1daeSBarry Smith     TranslateMessage(&msg);
5915c6c1daeSBarry Smith     DispatchMessage(&msg);
5925c6c1daeSBarry Smith   }
593f9baa8adSSatish Balay   return;
5945c6c1daeSBarry Smith }
5955c6c1daeSBarry Smith 
596*9371c9d4SSatish Balay 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};
5975c6c1daeSBarry Smith 
598*9371c9d4SSatish Balay static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw, PetscDraw *popup) {
5994a5237bfSSatish Balay   PetscDraw_Win32 *win = (PetscDraw_Win32 *)draw->data;
6004a5237bfSSatish Balay   PetscBool        flg = PETSC_TRUE;
6015c6c1daeSBarry Smith 
6025c6c1daeSBarry Smith   PetscFunctionBegin;
6039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, ((PetscObject)draw)->prefix, "-draw_popup", &flg, NULL));
6044a5237bfSSatish Balay   if (flg) {
6059566063dSJacob Faibussowitsch     PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)draw), NULL, NULL, win->x, win->y + win->h + 36, 220, 220, popup));
6069566063dSJacob Faibussowitsch     PetscCall(PetscDrawSetType(*popup, PETSC_DRAW_WIN32));
6074a5237bfSSatish Balay     draw->popup = *popup;
6084a5237bfSSatish Balay   } else {
6094a5237bfSSatish Balay     *popup = NULL;
6104a5237bfSSatish Balay   }
6115c6c1daeSBarry Smith   PetscFunctionReturn(0);
6125c6c1daeSBarry Smith }
613*9371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw) {
6145c6c1daeSBarry Smith   PetscDraw_Win32 *windraw;
6155c6c1daeSBarry Smith   HANDLE           hThread = NULL;
6165c6c1daeSBarry Smith   WindowNode       newnode;
6175c6c1daeSBarry Smith 
6185c6c1daeSBarry Smith   PetscFunctionBegin;
6199566063dSJacob Faibussowitsch   PetscCall(PetscNew(&windraw));
6205c6c1daeSBarry Smith   draw->data = windraw;
6215c6c1daeSBarry Smith 
6225c6c1daeSBarry Smith   /* the following is temporary fix for initializing a global datastructure */
623a297a907SKarl Rupp   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL, FALSE, NULL);
6249566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(draw->ops, &DvOps, sizeof(DvOps)));
6255c6c1daeSBarry Smith 
6265c6c1daeSBarry Smith   windraw->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
6275c6c1daeSBarry Smith   /* makes call to MessageLoopThread to creat window and attach a thread */
62813d99558SMatthew G. Knepley   CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLoopThread_Win32, draw, 0, (LPDWORD)hThread);
6295c6c1daeSBarry Smith   CloseHandle(hThread);
6305c6c1daeSBarry Smith   WaitForSingleObject(windraw->hReadyEvent, INFINITE);
6315c6c1daeSBarry Smith   CloseHandle(windraw->hReadyEvent);
6325c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
6335c6c1daeSBarry Smith 
6349566063dSJacob Faibussowitsch   PetscCall(PetscNew(&newnode));
6355c6c1daeSBarry Smith   newnode->MouseListHead = NULL;
6365c6c1daeSBarry Smith   newnode->MouseListTail = NULL;
6375c6c1daeSBarry Smith   newnode->wnext         = WindowListHead;
6385c6c1daeSBarry Smith   newnode->wprev         = NULL;
6395c6c1daeSBarry Smith   newnode->hWnd          = windraw->hWnd;
6406c4ed002SBarry Smith   if (WindowListHead) WindowListHead->wprev = newnode;
6415c6c1daeSBarry Smith   WindowListHead = newnode;
6425c6c1daeSBarry Smith   windraw->hdc   = GetDC(windraw->hWnd);
6435c6c1daeSBarry Smith 
6445c6c1daeSBarry Smith   windraw->stringheight  = 10;
6455c6c1daeSBarry Smith   windraw->stringwidth   = 6;
6465c6c1daeSBarry Smith   windraw->linewidth     = 1; /* default pixel sizes of graphics until user changes them */
6475c6c1daeSBarry Smith   windraw->pointdiameter = 1;
6485c6c1daeSBarry Smith   windraw->node          = newnode;
6495c6c1daeSBarry Smith 
6505c6c1daeSBarry Smith   windraw->x = draw->x;
6515c6c1daeSBarry Smith   windraw->y = draw->y;
6525c6c1daeSBarry Smith   windraw->w = newnode->bitwidth = draw->w;
6535c6c1daeSBarry Smith   windraw->h = newnode->bitheight = draw->h;
6545c6c1daeSBarry Smith 
6555c6c1daeSBarry Smith   /* Create and initialize primary graphics buffer */
6565c6c1daeSBarry Smith   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
6575c6c1daeSBarry Smith   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc, windraw->w, windraw->h);
6585c6c1daeSBarry Smith   newnode->store     = SelectObject(newnode->Buffer, newnode->BufferBit);
6595c6c1daeSBarry Smith   ExtFloodFill(newnode->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
6605c6c1daeSBarry Smith 
6615c6c1daeSBarry Smith   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
6625c6c1daeSBarry Smith   newnode->DoubleBuffered = PETSC_FALSE;
6635c6c1daeSBarry Smith 
6645c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, windraw->hdc);
6655c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
6665c6c1daeSBarry Smith   PetscFunctionReturn(0);
6675c6c1daeSBarry Smith }
6685c6c1daeSBarry Smith 
6695c6c1daeSBarry Smith /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
6705c6c1daeSBarry Smith    PURPOSE:  Processes messages for the main window.
6715c6c1daeSBarry Smith    WM_COMMAND  - process the application menu
6725c6c1daeSBarry Smith    WM_PAINT    - Paint the main window
6735c6c1daeSBarry Smith    WM_DESTROY  - post a quit message and return */
6745c6c1daeSBarry Smith 
675*9371c9d4SSatish Balay LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
6767ae38d14SSatish Balay   int wmId;
6775c6c1daeSBarry Smith 
6785c6c1daeSBarry Smith   switch (message) {
6795c6c1daeSBarry Smith     HANDLE_MSG(hWnd, WM_PAINT, OnPaint_Win32);
6805c6c1daeSBarry Smith     HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy_Win32);
6815c6c1daeSBarry Smith   case WM_COMMAND:
6825c6c1daeSBarry Smith     wmId = LOWORD(wParam);
6835c6c1daeSBarry Smith     /* Parse the menu selections:*/
6845c6c1daeSBarry Smith     switch (wmId) {
685*9371c9d4SSatish Balay     case IDM_EXIT: DestroyWindow(hWnd); break;
686*9371c9d4SSatish Balay     default: return DefWindowProc(hWnd, message, wParam, lParam);
6875c6c1daeSBarry Smith     }
6885c6c1daeSBarry Smith     break;
689*9371c9d4SSatish Balay   case WM_LBUTTONUP: MouseRecord_Win32(hWnd, PETSC_BUTTON_LEFT); break;
690*9371c9d4SSatish Balay   case WM_RBUTTONUP: MouseRecord_Win32(hWnd, PETSC_BUTTON_RIGHT); break;
691*9371c9d4SSatish Balay   case WM_MBUTTONUP: MouseRecord_Win32(hWnd, PETSC_BUTTON_CENTER); break;
692*9371c9d4SSatish Balay   default: return DefWindowProc(hWnd, message, wParam, lParam);
6935c6c1daeSBarry Smith   }
694f9baa8adSSatish Balay   return 0;
6955c6c1daeSBarry Smith }
6965c6c1daeSBarry Smith 
697*9371c9d4SSatish Balay static void OnPaint_Win32(HWND hWnd) {
6985c6c1daeSBarry Smith   PAINTSTRUCT ps;
6995c6c1daeSBarry Smith   HDC         hdc;
7005c6c1daeSBarry Smith   WindowNode  current = NULL;
7015c6c1daeSBarry Smith 
7025c6c1daeSBarry Smith   InvalidateRect(hWnd, NULL, TRUE);
7035c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
7045c6c1daeSBarry Smith   current = WindowListHead;
7055c6c1daeSBarry Smith   hdc     = BeginPaint(hWnd, &ps);
7065c6c1daeSBarry Smith 
7076c4ed002SBarry Smith   while (current) {
7085c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
7095c6c1daeSBarry Smith       /* flushes primary buffer to window */
710*9371c9d4SSatish Balay       BitBlt(hdc, 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), current->Buffer, 0, 0, SRCCOPY);
7115c6c1daeSBarry Smith 
712be332245SKarl Rupp       /* StretchBlt(hdc,0,0,w,h,
713be332245SKarl Rupp         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
7145c6c1daeSBarry Smith       break;
7155c6c1daeSBarry Smith     }
7165c6c1daeSBarry Smith     current = current->wnext;
7175c6c1daeSBarry Smith   }
7185c6c1daeSBarry Smith   EndPaint(hWnd, &ps);
7195c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
720f9baa8adSSatish Balay   return;
7215c6c1daeSBarry Smith }
7225c6c1daeSBarry Smith 
723*9371c9d4SSatish Balay static PetscErrorCode MouseRecord_Win32(HWND hWnd, PetscDrawButton button) {
7245c6c1daeSBarry Smith   /* Called by all three mouse button actions
7255c6c1daeSBarry Smith     Records needed mouse data in windows data structure */
7265c6c1daeSBarry Smith   WindowNode current = NULL;
7275c6c1daeSBarry Smith   MouseNode  newnode;
7285c6c1daeSBarry Smith   POINT      mousepos;
7295c6c1daeSBarry Smith 
7305c6c1daeSBarry Smith   PetscFunctionBegin;
7315c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
7325c6c1daeSBarry Smith   current = WindowListHead;
7335c6c1daeSBarry Smith   if (current->IsGetMouseOn == TRUE) {
7345c6c1daeSBarry Smith     SetEvent(current->event);
7356c4ed002SBarry Smith     while (current) {
7365c6c1daeSBarry Smith       if (current->hWnd == hWnd) {
7379566063dSJacob Faibussowitsch         PetscCall(PetscNew(&newnode));
7385c6c1daeSBarry Smith         newnode->Button = button;
7395c6c1daeSBarry Smith         GetCursorPos(&mousepos);
7405c6c1daeSBarry Smith         newnode->user.x = mousepos.x;
7415c6c1daeSBarry Smith         newnode->user.y = mousepos.y;
7425c6c1daeSBarry Smith         ScreenToClient(hWnd, &mousepos);
7435c6c1daeSBarry Smith         newnode->phys.x = mousepos.x;
7445c6c1daeSBarry Smith         newnode->phys.y = mousepos.y;
7455c6c1daeSBarry Smith         if (!current->MouseListTail) {
7465c6c1daeSBarry Smith           current->MouseListHead = newnode;
7475c6c1daeSBarry Smith           current->MouseListTail = newnode;
7485c6c1daeSBarry Smith         } else {
7495c6c1daeSBarry Smith           current->MouseListTail->mnext = newnode;
7505c6c1daeSBarry Smith           current->MouseListTail        = newnode;
7515c6c1daeSBarry Smith         }
7525c6c1daeSBarry Smith         newnode->mnext = NULL;
7535c6c1daeSBarry Smith 
7545c6c1daeSBarry Smith         break;
7555c6c1daeSBarry Smith       }
7565c6c1daeSBarry Smith       current = current->wnext;
7575c6c1daeSBarry Smith     }
7585c6c1daeSBarry Smith   }
7595c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
7605c6c1daeSBarry Smith   PetscFunctionReturn(0);
7615c6c1daeSBarry Smith }
7625c6c1daeSBarry Smith 
763*9371c9d4SSatish Balay static void OnDestroy_Win32(HWND hWnd) {
7645c6c1daeSBarry Smith   /* searches linked list of window data and frees corresponding memory */
7655c6c1daeSBarry Smith   WindowNode current;
7665c6c1daeSBarry Smith 
7675c6c1daeSBarry Smith   PetscFunctionBegin;
7685c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
7695c6c1daeSBarry Smith   current = WindowListHead;
7705c6c1daeSBarry Smith 
7715c6c1daeSBarry Smith   SetEvent(current->event);
7726c4ed002SBarry Smith   while (current) {
7735c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
7746c4ed002SBarry Smith       if (current->wprev) current->wprev->wnext = current->wnext;
775a297a907SKarl Rupp       else WindowListHead = current->wnext;
776a297a907SKarl Rupp       if (current->MouseListHead) deletemouselist_Win32(current);
777a297a907SKarl Rupp       else PetscFree(current);
7785c6c1daeSBarry Smith       break;
7795c6c1daeSBarry Smith     }
7805c6c1daeSBarry Smith     current = current->wnext;
7815c6c1daeSBarry Smith   }
7825c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
7835c6c1daeSBarry Smith   PostQuitMessage(0);
7845c6c1daeSBarry Smith   PetscFunctionReturnVoid();
7855c6c1daeSBarry Smith }
786