xref: /petsc/src/sys/classes/draw/impls/win32/win32draw.c (revision d0e6bf2ad94dcc89b258ce16c7987200a4714786)
15c6c1daeSBarry Smith #include <petscsys.h>
2af0996ceSBarry Smith #include <petsc/private/drawimpl.h>
378ac5f8bSSatish Balay #include <../src/sys/classes/draw/impls/win32/win32draw.h>
45c6c1daeSBarry Smith 
55c6c1daeSBarry Smith #define IDC_FOUR       109
65c6c1daeSBarry Smith #define IDI_FOUR       107
75c6c1daeSBarry Smith #define IDM_EXIT       105
85c6c1daeSBarry Smith #define IDR_POPUP      103
95c6c1daeSBarry Smith #define MAX_LOADSTRING 100
105c6c1daeSBarry Smith 
115c6c1daeSBarry Smith #if !defined(SelectPen)
125c6c1daeSBarry Smith   #define SelectPen(hdc, hpen) ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen)))
135c6c1daeSBarry Smith #endif
145c6c1daeSBarry Smith #if !defined(SelectFont)
155c6c1daeSBarry Smith   #define SelectFont(hdc, hfont) ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
165c6c1daeSBarry Smith #endif
175c6c1daeSBarry Smith #if !defined(SelectBrush)
185c6c1daeSBarry Smith   #define SelectBrush(hdc, hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush)))
195c6c1daeSBarry Smith #endif
205c6c1daeSBarry Smith #if !defined(GetStockBrush)
215c6c1daeSBarry Smith   #define GetStockBrush(i) ((HBRUSH)GetStockObject(i))
225c6c1daeSBarry Smith #endif
235c6c1daeSBarry Smith 
249371c9d4SSatish 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))))
259371c9d4SSatish 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))))
265c6c1daeSBarry Smith 
275c6c1daeSBarry Smith HINSTANCE  hInst;
285c6c1daeSBarry Smith HANDLE     g_hWindowListMutex = NULL;
295c6c1daeSBarry Smith WindowNode WindowListHead     = NULL;
305c6c1daeSBarry Smith 
315c6c1daeSBarry Smith /* Hard coded color hue until hue.c works with this */
325c6c1daeSBarry 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};
335c6c1daeSBarry 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};
345c6c1daeSBarry 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};
355c6c1daeSBarry Smith 
36da81f932SPierre Jolivet /* Forward declarations of functions included in this code module: */
375c6c1daeSBarry Smith LRESULT CALLBACK      PetscWndProc(HWND, UINT, WPARAM, LPARAM);
385c6c1daeSBarry Smith static PetscErrorCode TranslateColor_Win32(PetscDraw, int);
395c6c1daeSBarry Smith static PetscErrorCode AverageColorRectangle_Win32(PetscDraw, int, int, int, int);
405c6c1daeSBarry Smith static PetscErrorCode AverageColorTriangle_Win32(PetscDraw, int, int, int);
415c6c1daeSBarry Smith static PetscErrorCode deletemouselist_Win32(WindowNode);
425c6c1daeSBarry Smith static void           OnPaint_Win32(HWND);
435c6c1daeSBarry Smith static void           OnDestroy_Win32(HWND);
445c6c1daeSBarry Smith static PetscErrorCode MouseRecord_Win32(HWND, PetscDrawButton);
455c6c1daeSBarry Smith static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw, PetscDraw *);
465c6c1daeSBarry Smith 
PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)47d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
48d71ae5a4SJacob Faibussowitsch {
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);
58da81f932SPierre Jolivet   /* Copy current buffer into second buffer and set window data as double buffered */
599371c9d4SSatish 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);
633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
645c6c1daeSBarry Smith }
655c6c1daeSBarry Smith 
PetscDrawFlush_Win32(PetscDraw draw)66d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
67d71ae5a4SJacob Faibussowitsch {
685c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
695c6c1daeSBarry Smith   HDC              hdc     = GetDC(windraw->hWnd);
705c6c1daeSBarry Smith 
715c6c1daeSBarry Smith   PetscFunctionBegin;
725c6c1daeSBarry Smith   /* flush double buffer into primary buffer */
739371c9d4SSatish Balay   BitBlt(windraw->node->Buffer, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
745c6c1daeSBarry Smith   /* flush double buffer into window */
759371c9d4SSatish Balay   BitBlt(hdc, 0, 0, windraw->w, windraw->h, windraw->node->DoubleBuffer, 0, 0, SRCCOPY);
765c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, hdc);
773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
785c6c1daeSBarry Smith }
795c6c1daeSBarry Smith 
deletemouselist_Win32(WindowNode deletelist)80d71ae5a4SJacob Faibussowitsch static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
81d71ae5a4SJacob Faibussowitsch {
825c6c1daeSBarry Smith   /* Called upon window close. Frees memory of linked list of stored mouse commands */
835c6c1daeSBarry Smith   MouseNode node;
845c6c1daeSBarry Smith 
856c4ed002SBarry Smith   while (deletelist->MouseListHead) {
865c6c1daeSBarry Smith     node = deletelist->MouseListHead;
876c4ed002SBarry Smith     if (deletelist->MouseListHead->mnext) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
885c6c1daeSBarry Smith     PetscFree(node);
895c6c1daeSBarry Smith   }
905c6c1daeSBarry Smith   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
916c4ed002SBarry Smith   if (deletelist->wprev) deletelist->wprev->wnext = deletelist->wnext;
926c4ed002SBarry Smith   if (deletelist->wnext) deletelist->wnext->wprev = deletelist->wprev;
935c6c1daeSBarry Smith   PetscFree(deletelist);
943ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
955c6c1daeSBarry Smith }
965c6c1daeSBarry Smith 
PetscDrawGetMouseButton_Win32(PetscDraw draw,PetscDrawButton * button,PetscReal * x_user,PetscReal * y_user,PetscReal * x_phys,PetscReal * y_phys)97d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button, PetscReal *x_user, PetscReal *y_user, PetscReal *x_phys, PetscReal *y_phys)
98d71ae5a4SJacob Faibussowitsch {
995c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1005c6c1daeSBarry Smith   WindowNode       current;
1015c6c1daeSBarry Smith   MouseNode        node = 0;
1025c6c1daeSBarry Smith 
1035c6c1daeSBarry Smith   PetscFunctionBegin;
1045c6c1daeSBarry Smith   /* Make sure no other code is using the linked list at this moment */
1055c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1065c6c1daeSBarry Smith   /* Look for the node that matches the window you are using */
1075c6c1daeSBarry Smith   current = WindowListHead;
1086c4ed002SBarry Smith   while (current) {
1095c6c1daeSBarry Smith     if (current->hWnd == windraw->hWnd) {
1105c6c1daeSBarry Smith       current->IsGetMouseOn = TRUE;
1115c6c1daeSBarry Smith       break;
112a297a907SKarl Rupp     } else current = current->wnext;
1135c6c1daeSBarry Smith   }
114a5b23f4aSJose E. Roman   /* If no actions have occurred, wait for one */
1155c6c1daeSBarry Smith   node = current->MouseListHead;
1165c6c1daeSBarry Smith   if (!node) {
1175c6c1daeSBarry Smith     ReleaseMutex(g_hWindowListMutex);
1185c6c1daeSBarry Smith     WaitForSingleObject(current->event, INFINITE);
1195c6c1daeSBarry Smith     WaitForSingleObject(g_hWindowListMutex, INFINITE);
1205c6c1daeSBarry Smith   }
1215c6c1daeSBarry Smith   /* once we have the information, assign the pointers to it */
1225c6c1daeSBarry Smith   *button = current->MouseListHead->Button;
1235c6c1daeSBarry Smith   *x_user = current->MouseListHead->user.x;
1245c6c1daeSBarry Smith   *y_user = current->MouseListHead->user.y;
1255c6c1daeSBarry Smith   /* optional arguments */
1265c6c1daeSBarry Smith   if (x_phys) *x_phys = current->MouseListHead->phys.x;
1275c6c1daeSBarry Smith   if (y_phys) *y_phys = current->MouseListHead->phys.y;
1285c6c1daeSBarry Smith   /* remove set of information from sub linked-list, delete the node */
1295c6c1daeSBarry Smith   current->MouseListHead = current->MouseListHead->mnext;
1305c6c1daeSBarry Smith   if (!current->MouseListHead) {
1315c6c1daeSBarry Smith     ResetEvent(current->event);
1325c6c1daeSBarry Smith     current->MouseListTail = NULL;
1335c6c1daeSBarry Smith   }
1345c6c1daeSBarry Smith   if (node) PetscFree(node);
1355c6c1daeSBarry Smith 
1365c6c1daeSBarry Smith   /* Release mutex so that  other code can use
1375c6c1daeSBarry Smith      the linked list now that we are done with it */
1385c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
1393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1405c6c1daeSBarry Smith }
1415c6c1daeSBarry Smith 
PetscDrawPause_Win32(PetscDraw draw)142d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
143d71ae5a4SJacob Faibussowitsch {
1445c6c1daeSBarry Smith   PetscFunctionBegin;
1455c6c1daeSBarry Smith   PetscSleep(draw->pause);
1463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1475c6c1daeSBarry Smith }
1485c6c1daeSBarry Smith 
TranslateColor_Win32(PetscDraw draw,int color)149d71ae5a4SJacob Faibussowitsch static PetscErrorCode TranslateColor_Win32(PetscDraw draw, int color)
150d71ae5a4SJacob Faibussowitsch {
1515c6c1daeSBarry Smith   /* Maps single color value into the RGB colors in our tables */
1525c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1535c6c1daeSBarry Smith   windraw->currentcolor    = RGB(RedMap[color], GreenMap[color], BlueMap[color]);
1543ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1555c6c1daeSBarry Smith }
1565c6c1daeSBarry Smith 
AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2,int c3,int c4)157d71ae5a4SJacob Faibussowitsch static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw, int c1, int c2, int c3, int c4)
158d71ae5a4SJacob Faibussowitsch {
1595c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
1605c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
1615c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
162*57508eceSPierre Jolivet   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);
1633ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1645c6c1daeSBarry Smith }
1655c6c1daeSBarry Smith 
AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)166d71ae5a4SJacob Faibussowitsch static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw, int c1, int c2, int c3)
167d71ae5a4SJacob Faibussowitsch {
1685c6c1daeSBarry Smith   /* Averages colors given at points of rectangle and sets color from color table
1695c6c1daeSBarry Smith     will be changed once the color gradient problem is worked out */
1705c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1719371c9d4SSatish 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);
1723ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
1735c6c1daeSBarry Smith }
1745c6c1daeSBarry Smith 
PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)175d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int c1, int c2, int c3, int c4)
176d71ae5a4SJacob Faibussowitsch {
1775c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
1785c6c1daeSBarry Smith   HBRUSH           hbrush;
1795c6c1daeSBarry Smith   RECT             rect;
1805c6c1daeSBarry Smith   int              x1, yone, x2, y2;
1815c6c1daeSBarry Smith   HDC              hdc;
1825c6c1daeSBarry Smith 
1835c6c1daeSBarry Smith   PetscFunctionBegin;
1845c6c1daeSBarry Smith   x1   = XTRANS(draw, windraw, xl);
1855c6c1daeSBarry Smith   x2   = XTRANS(draw, windraw, xr);
1865c6c1daeSBarry Smith   yone = YTRANS(draw, windraw, yl);
1875c6c1daeSBarry Smith   y2   = YTRANS(draw, windraw, yr);
1885c6c1daeSBarry Smith   SetRect(&rect, x1, y2, x2, yone);
189a297a907SKarl Rupp   if (c1 == c2 && c2 == c3 && c3 == c4) TranslateColor_Win32(draw, c1);
190a297a907SKarl Rupp   else AverageColorRectangle_Win32(draw, c1, c2, c3, c4);
1915c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
1925c6c1daeSBarry Smith 
193a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
194a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
195a297a907SKarl Rupp 
1965c6c1daeSBarry Smith   FillRect(hdc, &rect, hbrush);
1975c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
1985c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
1995c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2015c6c1daeSBarry Smith }
2025c6c1daeSBarry Smith 
PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)203d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr, int color)
204d71ae5a4SJacob Faibussowitsch {
2055c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2065c6c1daeSBarry Smith   HPEN             hpen;
2075c6c1daeSBarry Smith   int              x1, yone, x2, y2;
2085c6c1daeSBarry Smith   HDC              hdc;
2095c6c1daeSBarry Smith 
2105c6c1daeSBarry Smith   PetscFunctionBegin;
2115c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
2129371c9d4SSatish Balay   x1   = XTRANS(draw, windraw, xl);
2139371c9d4SSatish Balay   x2   = XTRANS(draw, windraw, xr);
2149371c9d4SSatish Balay   yone = YTRANS(draw, windraw, yl);
2159371c9d4SSatish Balay   y2   = YTRANS(draw, windraw, yr);
2165c6c1daeSBarry Smith   hpen = CreatePen(PS_SOLID, windraw->linewidth, windraw->currentcolor);
217a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
218a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
219a297a907SKarl Rupp 
2205c6c1daeSBarry Smith   SelectPen(hdc, hpen);
2215c6c1daeSBarry Smith   MoveToEx(hdc, x1, yone, NULL);
2225c6c1daeSBarry Smith   LineTo(hdc, x2, y2);
2235c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
2245c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
2255c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2275c6c1daeSBarry Smith }
2285c6c1daeSBarry Smith 
PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)229d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw, PetscReal width)
230d71ae5a4SJacob Faibussowitsch {
2315c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2325c6c1daeSBarry Smith   int              averagesize, finalwidth;
2335c6c1daeSBarry Smith   RECT             rect;
2345c6c1daeSBarry Smith 
2355c6c1daeSBarry Smith   PetscFunctionBegin;
2365c6c1daeSBarry Smith   GetClientRect(windraw->hWnd, &rect);
2375c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
23877b4d14cSPeter Brune   finalwidth  = (int)PetscFloorReal(averagesize * width);
239a297a907SKarl Rupp   if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */
240a297a907SKarl Rupp 
2415c6c1daeSBarry Smith   windraw->linewidth = finalwidth;
2423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2435c6c1daeSBarry Smith }
2445c6c1daeSBarry Smith 
PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal * width)245d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw, PetscReal *width)
246d71ae5a4SJacob Faibussowitsch {
2475c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2485c6c1daeSBarry Smith 
2495c6c1daeSBarry Smith   PetscFunctionBegin;
2505c6c1daeSBarry Smith   *width = (PetscReal)windraw->linewidth;
2513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2525c6c1daeSBarry Smith }
2535c6c1daeSBarry Smith 
PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)254d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color)
255d71ae5a4SJacob Faibussowitsch {
2565c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2575c6c1daeSBarry Smith   HBRUSH           hbrush;
2585c6c1daeSBarry Smith   HRGN             hrgn;
2595c6c1daeSBarry Smith   int              radius;
2605c6c1daeSBarry Smith   int              x1, yone;
2615c6c1daeSBarry Smith   HDC              hdc;
2625c6c1daeSBarry Smith 
2635c6c1daeSBarry Smith   PetscFunctionBegin;
2645c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
2655c6c1daeSBarry Smith   x1     = XTRANS(draw, windraw, x);
2665c6c1daeSBarry Smith   yone   = YTRANS(draw, windraw, y);
2675c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
268a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
269a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
270a297a907SKarl Rupp 
2715c6c1daeSBarry Smith   /* desired size is one logical pixel so just turn it on */
272a297a907SKarl Rupp   if (windraw->pointdiameter == 1) SetPixelV(hdc, x1, yone, windraw->currentcolor);
273a297a907SKarl Rupp   else {
2745c6c1daeSBarry Smith     /* draw point around position determined */
2755c6c1daeSBarry Smith     radius = windraw->pointdiameter / 2; /* integer division */
2765c6c1daeSBarry Smith     hrgn   = CreateEllipticRgn(x1 - radius, yone - radius, x1 + radius, yone + radius);
2775c6c1daeSBarry Smith     FillRgn(hdc, hrgn, hbrush);
2785c6c1daeSBarry Smith   }
2795c6c1daeSBarry Smith   /* Forces a WM_PAINT and erases background */
2805c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
2815c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2835c6c1daeSBarry Smith }
2845c6c1daeSBarry Smith 
PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)285d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw, PetscReal width)
286d71ae5a4SJacob Faibussowitsch {
2875c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
2885c6c1daeSBarry Smith   int              averagesize, diameter;
2895c6c1daeSBarry Smith   RECT             rect;
2905c6c1daeSBarry Smith 
2915c6c1daeSBarry Smith   PetscFunctionBegin;
2925c6c1daeSBarry Smith   GetClientRect(windraw->hWnd, &rect);
2935c6c1daeSBarry Smith   averagesize = ((rect.right - rect.left) + (rect.bottom - rect.top)) / 2;
29477b4d14cSPeter Brune   diameter    = (int)PetscFloorReal(averagesize * width);
2955c6c1daeSBarry Smith   if (diameter < 1) diameter = 1;
2965c6c1daeSBarry Smith   windraw->pointdiameter = diameter;
2973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2985c6c1daeSBarry Smith }
2995c6c1daeSBarry Smith 
PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char * text)300d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawString_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text)
301d71ae5a4SJacob Faibussowitsch {
3025c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3035c6c1daeSBarry Smith   RECT             r;
3045c6c1daeSBarry Smith   HFONT            hfont;
3055c6c1daeSBarry Smith   LOGFONT          logfont;
3065c6c1daeSBarry Smith   int              x1, yone;
3075c6c1daeSBarry Smith   HDC              hdc;
3085c6c1daeSBarry Smith 
3095c6c1daeSBarry Smith   PetscFunctionBegin;
3105c6c1daeSBarry Smith   x1       = XTRANS(draw, windraw, x);
3115c6c1daeSBarry Smith   yone     = YTRANS(draw, windraw, y);
3125c6c1daeSBarry Smith   r.bottom = yone;
3135c6c1daeSBarry Smith   r.left   = x1;
3145c6c1daeSBarry Smith   r.right  = x1 + 1;
3155c6c1daeSBarry Smith   r.top    = yone + 1;
316a297a907SKarl Rupp 
3175c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3185c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3195c6c1daeSBarry Smith   logfont.lfEscapement     = 0;
3205c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3215c6c1daeSBarry Smith   logfont.lfCharSet        = 0;
3225c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3235c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3245c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3255c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3265c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3275c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3285c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3295c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
330a297a907SKarl Rupp 
3315c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3325c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
333a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
334a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
335a297a907SKarl Rupp 
3365c6c1daeSBarry Smith   SelectFont(hdc, hfont);
3375c6c1daeSBarry Smith   SetTextColor(hdc, windraw->currentcolor);
3385c6c1daeSBarry Smith   DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP);
3395c6c1daeSBarry Smith   DeleteObject(hfont);
3405c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3415c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
3425c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
3433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3445c6c1daeSBarry Smith }
3455c6c1daeSBarry Smith 
PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char * text)346d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw, PetscReal x, PetscReal y, int color, const char *text)
347d71ae5a4SJacob Faibussowitsch {
3485c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3495c6c1daeSBarry Smith   RECT             r;
3505c6c1daeSBarry Smith   HFONT            hfont;
3515c6c1daeSBarry Smith   LOGFONT          logfont;
3525c6c1daeSBarry Smith   int              x1, yone;
3535c6c1daeSBarry Smith   HDC              hdc;
3545c6c1daeSBarry Smith 
3555c6c1daeSBarry Smith   PetscFunctionBegin;
3565c6c1daeSBarry Smith   x1       = XTRANS(draw, windraw, x);
3575c6c1daeSBarry Smith   yone     = YTRANS(draw, windraw, y);
3585c6c1daeSBarry Smith   r.left   = x1;
3595c6c1daeSBarry Smith   r.bottom = yone + 30;
3605c6c1daeSBarry Smith   r.right  = x1 + 1;
3615c6c1daeSBarry Smith   r.top    = yone - 30;
362a297a907SKarl Rupp 
3639c89aa79SPierre Jolivet   logfont.lfEscapement     = 2700; /* Causes vertical text drawing */
3645c6c1daeSBarry Smith   logfont.lfHeight         = windraw->stringheight;
3655c6c1daeSBarry Smith   logfont.lfWidth          = windraw->stringwidth;
3665c6c1daeSBarry Smith   logfont.lfOrientation    = 0;
3675c6c1daeSBarry Smith   logfont.lfCharSet        = DEFAULT_CHARSET;
3685c6c1daeSBarry Smith   logfont.lfClipPrecision  = 0;
3695c6c1daeSBarry Smith   logfont.lfItalic         = 0;
3705c6c1daeSBarry Smith   logfont.lfOutPrecision   = 0;
3715c6c1daeSBarry Smith   logfont.lfPitchAndFamily = DEFAULT_PITCH;
3725c6c1daeSBarry Smith   logfont.lfQuality        = DEFAULT_QUALITY;
3735c6c1daeSBarry Smith   logfont.lfStrikeOut      = 0;
3745c6c1daeSBarry Smith   logfont.lfUnderline      = 0;
3755c6c1daeSBarry Smith   logfont.lfWeight         = FW_NORMAL;
376a297a907SKarl Rupp 
3775c6c1daeSBarry Smith   hfont = CreateFontIndirect(&logfont);
3785c6c1daeSBarry Smith   TranslateColor_Win32(draw, color);
379a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
380a297a907SKarl Rupp   else hdc = windraw->node->Buffer;
381a297a907SKarl Rupp 
3825c6c1daeSBarry Smith   SelectFont(hdc, hfont);
3835c6c1daeSBarry Smith   SetTextColor(hdc, windraw->currentcolor);
3845c6c1daeSBarry Smith   DrawText(hdc, text, lstrlen(text), &r, DT_NOCLIP | DT_SINGLELINE);
3855c6c1daeSBarry Smith   DeleteObject(hfont);
3865c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
3875c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
3885c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
3893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3905c6c1daeSBarry Smith }
3915c6c1daeSBarry Smith 
PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)392d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw, PetscReal width, PetscReal height)
393d71ae5a4SJacob Faibussowitsch {
3945c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
3955c6c1daeSBarry Smith   int              w, h;
3965c6c1daeSBarry Smith 
3975c6c1daeSBarry Smith   PetscFunctionBegin;
398f4f49eeaSPierre Jolivet   w = (int)(windraw->w * width * (draw->port_xr - draw->port_xl) / (draw->coor_xr - draw->coor_xl));
399f4f49eeaSPierre Jolivet   h = (int)(windraw->h * height * (draw->port_yr - draw->port_yl) / (draw->coor_yr - draw->coor_yl));
4005c6c1daeSBarry Smith   if (h < 1) h = 1;
4015c6c1daeSBarry Smith   if (w < 1) w = 1;
4025c6c1daeSBarry Smith   windraw->stringheight = h;
4035c6c1daeSBarry Smith   windraw->stringwidth  = w;
4043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4055c6c1daeSBarry Smith }
PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal * width,PetscReal * height)406d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw, PetscReal *width, PetscReal *height)
407d71ae5a4SJacob Faibussowitsch {
4085c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4095c6c1daeSBarry Smith   double           scaleX  = (draw->coor_xr - draw->coor_xl) / (draw->w) * (draw->port_xr - draw->port_xl);
4105c6c1daeSBarry Smith   double           scaleY  = (draw->coor_yr - draw->coor_yl) / (draw->h) * (draw->port_yr - draw->port_yl);
4115c6c1daeSBarry Smith 
4125c6c1daeSBarry Smith   PetscFunctionBegin;
4134a5237bfSSatish Balay   if (height) *height = (double)windraw->stringheight * scaleY;
4144a5237bfSSatish Balay   if (width) *width = (double)windraw->stringwidth * scaleX;
4153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4165c6c1daeSBarry Smith }
4175c6c1daeSBarry Smith 
PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)418d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw, int w, int h)
419d71ae5a4SJacob Faibussowitsch {
4205c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4215c6c1daeSBarry Smith   RECT             r;
4225c6c1daeSBarry Smith 
4235c6c1daeSBarry Smith   PetscFunctionBegin;
4245c6c1daeSBarry Smith   GetWindowRect(windraw->hWnd, &r);
4255c6c1daeSBarry Smith   MoveWindow(windraw->hWnd, r.left, r.top, (int)w, (int)h, TRUE);
4265c6c1daeSBarry Smith   /* set all variable dealing with window dimensions */
4275c6c1daeSBarry Smith   windraw->node->bitheight = windraw->h = draw->h = h;
4285c6c1daeSBarry Smith   windraw->node->bitwidth = windraw->w = draw->w = w;
4295c6c1daeSBarry Smith   /* set up graphic buffers with the new size of window */
4305c6c1daeSBarry Smith   SetBitmapDimensionEx(windraw->node->BufferBit, w, h, NULL);
431a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit, w, h, NULL);
4325c6c1daeSBarry Smith   windraw->haveresized = PETSC_TRUE;
4333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4345c6c1daeSBarry Smith }
4355c6c1daeSBarry Smith 
PetscDrawCheckResizedWindow_Win32(PetscDraw draw)436d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
437d71ae5a4SJacob Faibussowitsch {
4385c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4395c6c1daeSBarry Smith 
4405c6c1daeSBarry Smith   PetscFunctionBegin;
44111cc89d2SBarry Smith   PetscCheck(windraw->haveresized != 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for resizing windows on Microsoft Windows");
4423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4435c6c1daeSBarry Smith }
4445c6c1daeSBarry Smith 
PetscDrawSetTitle_Win32(PetscDraw draw,const char title[])445d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
446d71ae5a4SJacob Faibussowitsch {
4475c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4485c6c1daeSBarry Smith 
4495c6c1daeSBarry Smith   PetscFunctionBegin;
4505c6c1daeSBarry Smith   SetWindowText(windraw->hWnd, title);
4513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4525c6c1daeSBarry Smith }
4535c6c1daeSBarry Smith 
PetscDrawClear_Win32(PetscDraw draw)454d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
455d71ae5a4SJacob Faibussowitsch {
4565c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4575c6c1daeSBarry Smith 
4585c6c1daeSBarry Smith   PetscFunctionBegin;
4595c6c1daeSBarry Smith   /* clear primary buffer */
4605c6c1daeSBarry Smith   ExtFloodFill(windraw->node->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
4615c6c1daeSBarry Smith   /* if exists clear secondary buffer */
462a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
463a297a907SKarl Rupp 
4645c6c1daeSBarry Smith   /* force WM_PAINT message so cleared buffer will show */
4655c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
4665c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
4673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4685c6c1daeSBarry Smith }
4695c6c1daeSBarry Smith 
PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,PetscReal x3,PetscReal y3,int c1,int c2,int c3)470d71ae5a4SJacob 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)
471d71ae5a4SJacob Faibussowitsch {
4725c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
4735c6c1daeSBarry Smith   HBRUSH           hbrush;
4745c6c1daeSBarry Smith   HPEN             hpen;
4755c6c1daeSBarry Smith   int              p1x, p1y, p2x, p2y, p3x, p3y;
4765c6c1daeSBarry Smith   HDC              bit;
4775c6c1daeSBarry Smith 
4785c6c1daeSBarry Smith   PetscFunctionBegin;
4795c6c1daeSBarry Smith   AverageColorTriangle_Win32(draw, c1, c2, c3);
4805c6c1daeSBarry Smith   hbrush = CreateSolidBrush(windraw->currentcolor);
4815c6c1daeSBarry Smith   hpen   = CreatePen(PS_SOLID, 0, windraw->currentcolor);
4825c6c1daeSBarry Smith   p1x    = XTRANS(draw, windraw, x1);
4835c6c1daeSBarry Smith   p2x    = XTRANS(draw, windraw, x2);
4845c6c1daeSBarry Smith   p3x    = XTRANS(draw, windraw, x3);
4855c6c1daeSBarry Smith   p1y    = YTRANS(draw, windraw, yone);
4865c6c1daeSBarry Smith   p2y    = YTRANS(draw, windraw, y2);
4875c6c1daeSBarry Smith   p3y    = YTRANS(draw, windraw, y3);
4885c6c1daeSBarry Smith 
489a297a907SKarl Rupp   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
490a297a907SKarl Rupp   else bit = windraw->node->Buffer;
491a297a907SKarl Rupp 
4925c6c1daeSBarry Smith   BeginPath(bit);
4935c6c1daeSBarry Smith   MoveToEx(bit, p1x, p1y, NULL);
4945c6c1daeSBarry Smith   LineTo(bit, p2x, p2y);
4955c6c1daeSBarry Smith   LineTo(bit, p3x, p3y);
4965c6c1daeSBarry Smith   LineTo(bit, p1x, p1y);
4975c6c1daeSBarry Smith   EndPath(bit);
4985c6c1daeSBarry Smith   SelectPen(bit, hpen);
4995c6c1daeSBarry Smith   SelectBrush(bit, hbrush);
5005c6c1daeSBarry Smith   StrokeAndFillPath(bit);
5015c6c1daeSBarry Smith   /* Forces a WM_PAINT message and erases background */
5025c6c1daeSBarry Smith   InvalidateRect(windraw->hWnd, NULL, TRUE);
5035c6c1daeSBarry Smith   UpdateWindow(windraw->hWnd);
5043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5055c6c1daeSBarry Smith }
5065c6c1daeSBarry Smith 
PetscDrawSetVisible_Win32(PetscDraw draw,PetscBool visible)507bb09dc67SDuncan Campbell static PetscErrorCode PetscDrawSetVisible_Win32(PetscDraw draw, PetscBool visible)
508bb09dc67SDuncan Campbell {
509bb09dc67SDuncan Campbell   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
510bb09dc67SDuncan Campbell 
511bb09dc67SDuncan Campbell   PetscFunctionBegin;
512bb09dc67SDuncan Campbell   ShowWindow(windraw->hWnd, visible ? SW_SHOWNA : SW_HIDE);
513bb09dc67SDuncan Campbell   PetscFunctionReturn(PETSC_SUCCESS);
514bb09dc67SDuncan Campbell }
515bb09dc67SDuncan Campbell 
PetscDrawDestroy_Win32(PetscDraw draw)516d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
517d71ae5a4SJacob Faibussowitsch {
5185c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
5195c6c1daeSBarry Smith 
5205c6c1daeSBarry Smith   PetscFunctionBegin;
5215c6c1daeSBarry Smith   SendMessage(windraw->hWnd, WM_DESTROY, 0, 0);
52250c74209SLisandro Dalcin   PetscFree(draw->data);
5233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5245c6c1daeSBarry Smith }
5255c6c1daeSBarry Smith 
MessageLoopThread_Win32(PetscDraw draw)526ba38deedSJacob Faibussowitsch static void MessageLoopThread_Win32(PetscDraw draw)
527d71ae5a4SJacob Faibussowitsch {
5285c6c1daeSBarry Smith   PetscDraw_Win32 *windraw = (PetscDraw_Win32 *)draw->data;
5295c6c1daeSBarry Smith   MSG              msg;
5305c6c1daeSBarry Smith   HWND             hWnd        = NULL;
531fad2a674SVolker   const char       classname[] = "PETSc Window Class";
5325c6c1daeSBarry Smith   WNDCLASSEX       wclass;
5335c6c1daeSBarry Smith   LPVOID           lpMsgBuf;
5345c6c1daeSBarry Smith 
5355c6c1daeSBarry Smith   /* initialize window class parameters */
5365c6c1daeSBarry Smith   wclass.cbSize        = sizeof(WNDCLASSEX);
5375c6c1daeSBarry Smith   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
5385c6c1daeSBarry Smith   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
5395c6c1daeSBarry Smith   wclass.cbClsExtra    = 0;
5405c6c1daeSBarry Smith   wclass.cbWndExtra    = 0;
5415c6c1daeSBarry Smith   wclass.hInstance     = NULL;
5425c6c1daeSBarry Smith   wclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
5435c6c1daeSBarry Smith   wclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
5445c6c1daeSBarry Smith   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
5455c6c1daeSBarry Smith   wclass.lpszMenuName  = NULL;
5465c6c1daeSBarry Smith   wclass.lpszClassName = classname;
5475c6c1daeSBarry Smith   wclass.hIconSm       = NULL;
5485c6c1daeSBarry Smith 
5495c6c1daeSBarry Smith   RegisterClassEx(&wclass);
5505c6c1daeSBarry Smith 
5519371c9d4SSatish Balay   hWnd = CreateWindowEx(0, classname, NULL, WS_OVERLAPPEDWINDOW, draw->x, draw->y, draw->w, draw->h, NULL, NULL, hInst, NULL);
5525c6c1daeSBarry Smith 
5535c6c1daeSBarry Smith   if (!hWnd) {
554fad2a674SVolker     lpMsgBuf = (LPVOID) "Window Not Successfully Created";
5555c6c1daeSBarry Smith     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
5565c6c1daeSBarry Smith     LocalFree(lpMsgBuf);
5575c6c1daeSBarry Smith     exit(0);
5585c6c1daeSBarry Smith   }
5595c6c1daeSBarry Smith   windraw->hWnd = hWnd;
5605c6c1daeSBarry Smith   /* display and update new window */
5615c6c1daeSBarry Smith   ShowWindow(hWnd, SW_SHOWNORMAL);
5625c6c1daeSBarry Smith   UpdateWindow(hWnd);
5635c6c1daeSBarry Smith   SetEvent(windraw->hReadyEvent);
5645c6c1daeSBarry Smith 
5655c6c1daeSBarry Smith   while (GetMessage(&msg, hWnd, 0, 0)) {
5665c6c1daeSBarry Smith     TranslateMessage(&msg);
5675c6c1daeSBarry Smith     DispatchMessage(&msg);
5685c6c1daeSBarry Smith   }
569f9baa8adSSatish Balay   return;
5705c6c1daeSBarry Smith }
5715c6c1daeSBarry Smith 
572bb09dc67SDuncan 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};
5735c6c1daeSBarry Smith 
PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw * popup)574d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw, PetscDraw *popup)
575d71ae5a4SJacob Faibussowitsch {
5764a5237bfSSatish Balay   PetscDraw_Win32 *win = (PetscDraw_Win32 *)draw->data;
5774a5237bfSSatish Balay   PetscBool        flg = PETSC_TRUE;
5785c6c1daeSBarry Smith 
5795c6c1daeSBarry Smith   PetscFunctionBegin;
5809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, ((PetscObject)draw)->prefix, "-draw_popup", &flg, NULL));
5814a5237bfSSatish Balay   if (flg) {
5829566063dSJacob Faibussowitsch     PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)draw), NULL, NULL, win->x, win->y + win->h + 36, 220, 220, popup));
5839566063dSJacob Faibussowitsch     PetscCall(PetscDrawSetType(*popup, PETSC_DRAW_WIN32));
5844a5237bfSSatish Balay     draw->popup = *popup;
5854a5237bfSSatish Balay   } else {
5864a5237bfSSatish Balay     *popup = NULL;
5874a5237bfSSatish Balay   }
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5895c6c1daeSBarry Smith }
PetscDrawCreate_Win32(PetscDraw draw)590d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
591d71ae5a4SJacob Faibussowitsch {
5925c6c1daeSBarry Smith   PetscDraw_Win32 *windraw;
5935c6c1daeSBarry Smith   HANDLE           hThread = NULL;
5945c6c1daeSBarry Smith   WindowNode       newnode;
5955c6c1daeSBarry Smith 
5965c6c1daeSBarry Smith   PetscFunctionBegin;
5979566063dSJacob Faibussowitsch   PetscCall(PetscNew(&windraw));
5985c6c1daeSBarry Smith   draw->data = windraw;
5995c6c1daeSBarry Smith 
6005c6c1daeSBarry Smith   /* the following is temporary fix for initializing a global datastructure */
601a297a907SKarl Rupp   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL, FALSE, NULL);
602aea10558SJacob Faibussowitsch   draw->ops[0] = DvOps;
6035c6c1daeSBarry Smith 
6045c6c1daeSBarry Smith   windraw->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
6055c6c1daeSBarry Smith   /* makes call to MessageLoopThread to creat window and attach a thread */
60613d99558SMatthew G. Knepley   CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MessageLoopThread_Win32, draw, 0, (LPDWORD)hThread);
6075c6c1daeSBarry Smith   CloseHandle(hThread);
6085c6c1daeSBarry Smith   WaitForSingleObject(windraw->hReadyEvent, INFINITE);
6095c6c1daeSBarry Smith   CloseHandle(windraw->hReadyEvent);
6105c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
6115c6c1daeSBarry Smith 
6129566063dSJacob Faibussowitsch   PetscCall(PetscNew(&newnode));
6135c6c1daeSBarry Smith   newnode->MouseListHead = NULL;
6145c6c1daeSBarry Smith   newnode->MouseListTail = NULL;
6155c6c1daeSBarry Smith   newnode->wnext         = WindowListHead;
6165c6c1daeSBarry Smith   newnode->wprev         = NULL;
6175c6c1daeSBarry Smith   newnode->hWnd          = windraw->hWnd;
6186c4ed002SBarry Smith   if (WindowListHead) WindowListHead->wprev = newnode;
6195c6c1daeSBarry Smith   WindowListHead = newnode;
6205c6c1daeSBarry Smith   windraw->hdc   = GetDC(windraw->hWnd);
6215c6c1daeSBarry Smith 
6225c6c1daeSBarry Smith   windraw->stringheight  = 10;
6235c6c1daeSBarry Smith   windraw->stringwidth   = 6;
6245c6c1daeSBarry Smith   windraw->linewidth     = 1; /* default pixel sizes of graphics until user changes them */
6255c6c1daeSBarry Smith   windraw->pointdiameter = 1;
6265c6c1daeSBarry Smith   windraw->node          = newnode;
6275c6c1daeSBarry Smith 
6285c6c1daeSBarry Smith   windraw->x = draw->x;
6295c6c1daeSBarry Smith   windraw->y = draw->y;
6305c6c1daeSBarry Smith   windraw->w = newnode->bitwidth = draw->w;
6315c6c1daeSBarry Smith   windraw->h = newnode->bitheight = draw->h;
6325c6c1daeSBarry Smith 
6335c6c1daeSBarry Smith   /* Create and initialize primary graphics buffer */
6345c6c1daeSBarry Smith   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
6355c6c1daeSBarry Smith   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc, windraw->w, windraw->h);
6365c6c1daeSBarry Smith   newnode->store     = SelectObject(newnode->Buffer, newnode->BufferBit);
6375c6c1daeSBarry Smith   ExtFloodFill(newnode->Buffer, 0, 0, COLOR_WINDOW, FLOODFILLBORDER);
6385c6c1daeSBarry Smith 
6395c6c1daeSBarry Smith   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
6405c6c1daeSBarry Smith   newnode->DoubleBuffered = PETSC_FALSE;
6415c6c1daeSBarry Smith 
6425c6c1daeSBarry Smith   ReleaseDC(windraw->hWnd, windraw->hdc);
6435c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
6443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6455c6c1daeSBarry Smith }
6465c6c1daeSBarry Smith 
6475c6c1daeSBarry Smith /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
6485c6c1daeSBarry Smith    PURPOSE:  Processes messages for the main window.
6495c6c1daeSBarry Smith    WM_COMMAND  - process the application menu
6505c6c1daeSBarry Smith    WM_PAINT    - Paint the main window
6515c6c1daeSBarry Smith    WM_DESTROY  - post a quit message and return */
6525c6c1daeSBarry Smith 
PetscWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)653d71ae5a4SJacob Faibussowitsch LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
654d71ae5a4SJacob Faibussowitsch {
6557ae38d14SSatish Balay   int wmId;
6565c6c1daeSBarry Smith 
6575c6c1daeSBarry Smith   switch (message) {
6585c6c1daeSBarry Smith     HANDLE_MSG(hWnd, WM_PAINT, OnPaint_Win32);
6595c6c1daeSBarry Smith     HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy_Win32);
6605c6c1daeSBarry Smith   case WM_COMMAND:
6615c6c1daeSBarry Smith     wmId = LOWORD(wParam);
6625c6c1daeSBarry Smith     /* Parse the menu selections:*/
6635c6c1daeSBarry Smith     switch (wmId) {
664d71ae5a4SJacob Faibussowitsch     case IDM_EXIT:
665d71ae5a4SJacob Faibussowitsch       DestroyWindow(hWnd);
666d71ae5a4SJacob Faibussowitsch       break;
667d71ae5a4SJacob Faibussowitsch     default:
668d71ae5a4SJacob Faibussowitsch       return DefWindowProc(hWnd, message, wParam, lParam);
6695c6c1daeSBarry Smith     }
6705c6c1daeSBarry Smith     break;
671d71ae5a4SJacob Faibussowitsch   case WM_LBUTTONUP:
672d71ae5a4SJacob Faibussowitsch     MouseRecord_Win32(hWnd, PETSC_BUTTON_LEFT);
673d71ae5a4SJacob Faibussowitsch     break;
674d71ae5a4SJacob Faibussowitsch   case WM_RBUTTONUP:
675d71ae5a4SJacob Faibussowitsch     MouseRecord_Win32(hWnd, PETSC_BUTTON_RIGHT);
676d71ae5a4SJacob Faibussowitsch     break;
677d71ae5a4SJacob Faibussowitsch   case WM_MBUTTONUP:
678d71ae5a4SJacob Faibussowitsch     MouseRecord_Win32(hWnd, PETSC_BUTTON_CENTER);
679d71ae5a4SJacob Faibussowitsch     break;
680d71ae5a4SJacob Faibussowitsch   default:
681d71ae5a4SJacob Faibussowitsch     return DefWindowProc(hWnd, message, wParam, lParam);
6825c6c1daeSBarry Smith   }
683f9baa8adSSatish Balay   return 0;
6845c6c1daeSBarry Smith }
6855c6c1daeSBarry Smith 
OnPaint_Win32(HWND hWnd)686d71ae5a4SJacob Faibussowitsch static void OnPaint_Win32(HWND hWnd)
687d71ae5a4SJacob Faibussowitsch {
6885c6c1daeSBarry Smith   PAINTSTRUCT ps;
6895c6c1daeSBarry Smith   HDC         hdc;
6905c6c1daeSBarry Smith   WindowNode  current = NULL;
6915c6c1daeSBarry Smith 
6925c6c1daeSBarry Smith   InvalidateRect(hWnd, NULL, TRUE);
6935c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
6945c6c1daeSBarry Smith   current = WindowListHead;
6955c6c1daeSBarry Smith   hdc     = BeginPaint(hWnd, &ps);
6965c6c1daeSBarry Smith 
6976c4ed002SBarry Smith   while (current) {
6985c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
6995c6c1daeSBarry Smith       /* flushes primary buffer to window */
7009371c9d4SSatish Balay       BitBlt(hdc, 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), current->Buffer, 0, 0, SRCCOPY);
7015c6c1daeSBarry Smith 
702be332245SKarl Rupp       /* StretchBlt(hdc,0,0,w,h,
703be332245SKarl Rupp         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
7045c6c1daeSBarry Smith       break;
7055c6c1daeSBarry Smith     }
7065c6c1daeSBarry Smith     current = current->wnext;
7075c6c1daeSBarry Smith   }
7085c6c1daeSBarry Smith   EndPaint(hWnd, &ps);
7095c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
710f9baa8adSSatish Balay   return;
7115c6c1daeSBarry Smith }
7125c6c1daeSBarry Smith 
MouseRecord_Win32(HWND hWnd,PetscDrawButton button)713d71ae5a4SJacob Faibussowitsch static PetscErrorCode MouseRecord_Win32(HWND hWnd, PetscDrawButton button)
714d71ae5a4SJacob Faibussowitsch {
7155c6c1daeSBarry Smith   /* Called by all three mouse button actions
7165c6c1daeSBarry Smith     Records needed mouse data in windows data structure */
7175c6c1daeSBarry Smith   WindowNode current = NULL;
7185c6c1daeSBarry Smith   MouseNode  newnode;
7195c6c1daeSBarry Smith   POINT      mousepos;
7205c6c1daeSBarry Smith 
7215c6c1daeSBarry Smith   PetscFunctionBegin;
7225c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
7235c6c1daeSBarry Smith   current = WindowListHead;
7245c6c1daeSBarry Smith   if (current->IsGetMouseOn == TRUE) {
7255c6c1daeSBarry Smith     SetEvent(current->event);
7266c4ed002SBarry Smith     while (current) {
7275c6c1daeSBarry Smith       if (current->hWnd == hWnd) {
7289566063dSJacob Faibussowitsch         PetscCall(PetscNew(&newnode));
7295c6c1daeSBarry Smith         newnode->Button = button;
7305c6c1daeSBarry Smith         GetCursorPos(&mousepos);
7315c6c1daeSBarry Smith         newnode->user.x = mousepos.x;
7325c6c1daeSBarry Smith         newnode->user.y = mousepos.y;
7335c6c1daeSBarry Smith         ScreenToClient(hWnd, &mousepos);
7345c6c1daeSBarry Smith         newnode->phys.x = mousepos.x;
7355c6c1daeSBarry Smith         newnode->phys.y = mousepos.y;
7365c6c1daeSBarry Smith         if (!current->MouseListTail) {
7375c6c1daeSBarry Smith           current->MouseListHead = newnode;
7385c6c1daeSBarry Smith           current->MouseListTail = newnode;
7395c6c1daeSBarry Smith         } else {
7405c6c1daeSBarry Smith           current->MouseListTail->mnext = newnode;
7415c6c1daeSBarry Smith           current->MouseListTail        = newnode;
7425c6c1daeSBarry Smith         }
7435c6c1daeSBarry Smith         newnode->mnext = NULL;
7445c6c1daeSBarry Smith 
7455c6c1daeSBarry Smith         break;
7465c6c1daeSBarry Smith       }
7475c6c1daeSBarry Smith       current = current->wnext;
7485c6c1daeSBarry Smith     }
7495c6c1daeSBarry Smith   }
7505c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
7513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7525c6c1daeSBarry Smith }
7535c6c1daeSBarry Smith 
OnDestroy_Win32(HWND hWnd)754d71ae5a4SJacob Faibussowitsch static void OnDestroy_Win32(HWND hWnd)
755d71ae5a4SJacob Faibussowitsch {
7565c6c1daeSBarry Smith   /* searches linked list of window data and frees corresponding memory */
7575c6c1daeSBarry Smith   WindowNode current;
7585c6c1daeSBarry Smith 
7595c6c1daeSBarry Smith   PetscFunctionBegin;
7605c6c1daeSBarry Smith   WaitForSingleObject(g_hWindowListMutex, INFINITE);
7615c6c1daeSBarry Smith   current = WindowListHead;
7625c6c1daeSBarry Smith 
7635c6c1daeSBarry Smith   SetEvent(current->event);
7646c4ed002SBarry Smith   while (current) {
7655c6c1daeSBarry Smith     if (current->hWnd == hWnd) {
7666c4ed002SBarry Smith       if (current->wprev) current->wprev->wnext = current->wnext;
767a297a907SKarl Rupp       else WindowListHead = current->wnext;
768a297a907SKarl Rupp       if (current->MouseListHead) deletemouselist_Win32(current);
769a297a907SKarl Rupp       else PetscFree(current);
7705c6c1daeSBarry Smith       break;
7715c6c1daeSBarry Smith     }
7725c6c1daeSBarry Smith     current = current->wnext;
7735c6c1daeSBarry Smith   }
7745c6c1daeSBarry Smith   ReleaseMutex(g_hWindowListMutex);
7755c6c1daeSBarry Smith   PostQuitMessage(0);
7765c6c1daeSBarry Smith   PetscFunctionReturnVoid();
7775c6c1daeSBarry Smith }
778