Actual source code: win32draw.c

petsc-3.5.4 2015-05-23
Report Typos and Errors
  2: #include <petscsys.h>
  3: #include <petsc-private/drawimpl.h>
  4: #include <../src/sys/classes/draw/impls/win32/win32draw.h>

  6: #define IDC_FOUR       109
  7: #define IDI_FOUR       107
  8: #define IDM_EXIT       105
  9: #define IDR_POPUP      103
 10: #define MAX_LOADSTRING 100

 12: #if !defined(SelectPen)
 13: #define SelectPen(hdc, hpen)      ((HPEN)SelectObject((hdc), (HGDIOBJ)(HPEN)(hpen)))
 14: #endif
 15: #if !defined(SelectFont)
 16: #define SelectFont(hdc,hfont)    ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
 17: #endif
 18: #if !defined(SelectBrush)
 19: #define SelectBrush(hdc,hbrush) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbrush)))
 20: #endif
 21: #if !defined(GetStockBrush)
 22: #define GetStockBrush(i)      ((HBRUSH)GetStockObject(i))
 23: #endif

 25: #define XTRANS(draw,win,x) \
 26:     (int)(((win)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)*         \
 27:                             ((draw)->port_xr - (draw)->port_xl))/        \
 28:                             ((draw)->coor_xr - (draw)->coor_xl))))
 29: #define YTRANS(draw,win,y) \
 30:     (int)(((win)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)*     \
 31:                                 ((draw)->port_yr - (draw)->port_yl))/    \
 32:                                 ((draw)->coor_yr - (draw)->coor_yl))))

 34: HINSTANCE  hInst;
 35: HANDLE     g_hWindowListMutex = NULL;
 36: WindowNode WindowListHead     = NULL;

 38: /* Hard coded color hue until hue.c works with this */
 39: unsigned char RedMap[]   = {255,0,255,0,0,0,255,127,34,255,238,165,255,255,190,255,255,238,0,255,105,154,135,0,0,244,152,176,220,216,50,255};
 40: unsigned char GreenMap[] = {255,0,0,255,255,0,0,255,139,165,130,42,182,127,190,255,215,162,197,246,105,205,206,100,0,164,245,224,17,191,205,240};
 41: 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};

 43: /* Foward declarations of functions included in this code module: */
 44: LRESULT CALLBACK PetscWndProc(HWND, UINT, WPARAM, LPARAM);
 45: static PetscErrorCode TranslateColor_Win32(PetscDraw,int);
 46: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw,int,int,int,int);
 47: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw,int,int,int);
 48: static PetscErrorCode deletemouselist_Win32(WindowNode);
 49: static void OnPaint_Win32(HWND);
 50: static void OnDestroy_Win32(HWND);
 51: static PetscErrorCode MouseRecord_Win32(HWND,PetscDrawButton);
 52: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw,PetscDraw*);

 56: static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
 57: {
 58:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 59:   HDC             hdc      = GetDC(windraw->hWnd);

 62:   windraw->node->DoubleBuffer    = CreateCompatibleDC(hdc);
 63:   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
 64:   windraw->node->dbstore         = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
 65:   /* Fill background of second buffer */
 66:   ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
 67:   /* Copy current buffer into seconf buffer and set window data as double buffered */
 68:   BitBlt(windraw->node->DoubleBuffer,0,0,windraw->w,windraw->h,
 69:          windraw->node->Buffer,0,0, SRCCOPY);

 71:   windraw->node->DoubleBuffered = PETSC_TRUE;
 72:   ReleaseDC(windraw->hWnd,hdc);
 73:   return(0);
 74: }

 78: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
 79: {
 80:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 81:   HDC             hdc      = GetDC(windraw->hWnd);

 84:   /* flush double buffer into primary buffer */
 85:   BitBlt(windraw->node->Buffer,0,0,windraw->w,windraw->h,
 86:          windraw->node->DoubleBuffer,0,0,SRCCOPY);
 87:   /* flush double buffer into window */
 88:   BitBlt(hdc,0,0,windraw->w,windraw->h,
 89:          windraw->node->DoubleBuffer, 0,0,SRCCOPY);
 90:   ReleaseDC(windraw->hWnd,hdc);
 91:   return(0);
 92: }

 96: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
 97: {
 98:   /* Called upon window close. Frees memory of linked list of stored mouse commands */
 99:   MouseNode node;

101:   while (deletelist->MouseListHead != NULL) {
102:     node = deletelist->MouseListHead;
103:     if (deletelist->MouseListHead->mnext != NULL) deletelist->MouseListHead = deletelist->MouseListHead->mnext;
104:     PetscFree(node);
105:   }
106:   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
107:   if (deletelist->wprev != NULL) deletelist->wprev->wnext = deletelist->wnext;
108:   if (deletelist->wnext != NULL) deletelist->wnext->wprev = deletelist->wprev;
109:   PetscFree(deletelist);
110:   return 0;
111: }

115: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
116: {
117:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
118:   WindowNode      current;
119:   MouseNode       node=0;

122:   /* Make sure no other code is using the linked list at this moment */
123:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
124:   /* Look for the node that matches the window you are using */
125:   current = WindowListHead;
126:   while (current != NULL) {
127:     if (current->hWnd == windraw->hWnd) {
128:       current->IsGetMouseOn = TRUE;
129:       break;
130:     } else current = current->wnext;
131:   }
132:   /* If no actions have occured, wait for one */
133:   node = current->MouseListHead;
134:   if (!node) {
135:     ReleaseMutex(g_hWindowListMutex);
136:     WaitForSingleObject(current->event, INFINITE);
137:     WaitForSingleObject(g_hWindowListMutex, INFINITE);
138:   }
139:   /* once we have the information, assign the pointers to it */
140:   *button = current->MouseListHead->Button;
141:   *x_user = current->MouseListHead->user.x;
142:   *y_user = current->MouseListHead->user.y;
143:   /* optional arguments */
144:   if (x_phys) *x_phys = current->MouseListHead->phys.x;
145:   if (y_phys) *y_phys = current->MouseListHead->phys.y;
146:   /* remove set of information from sub linked-list, delete the node */
147:   current->MouseListHead = current->MouseListHead->mnext;
148:   if (!current->MouseListHead) {
149:     ResetEvent(current->event);
150:     current->MouseListTail = NULL;
151:   }
152:   if (node) PetscFree(node);

154:   /* Release mutex so that  other code can use
155:      the linked list now that we are done with it */
156:   ReleaseMutex(g_hWindowListMutex);
157:   return(0);
158: }

162: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
163: {
165:   PetscSleep(draw->pause);
166:   return(0);
167: }

171: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
172: {
173:   /* Maps single color value into the RGB colors in our tables */
174:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
175:   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
176:   return 0;
177: }

181: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
182: {
183:   /* Averages colors given at points of rectangle and sets color from color table
184:     will be changed once the color gradient problem is worked out */
185:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
186:   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
187:                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
188:                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
189:   return 0;
190: }

194: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
195: {
196:   /* Averages colors given at points of rectangle and sets color from color table
197:     will be changed once the color gradient problem is worked out */
198:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
199:   windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
200:                               (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
201:                               (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
202:   return 0;
203: }

207: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
208: {
209:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
210:   HBRUSH          hbrush;
211:   RECT            rect;
212:   int             x1,yone,x2,y2;
213:   HDC             hdc;

216:   x1   = XTRANS(draw,windraw,xl);
217:   x2   = XTRANS(draw,windraw,xr);
218:   yone = YTRANS(draw,windraw,yl);
219:   y2   = YTRANS(draw,windraw,yr);
220:   SetRect(&rect,x1,y2,x2,yone);
221:   if (c1==c2 && c2==c3 && c3==c4) TranslateColor_Win32(draw,c1);
222:   else AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
223:   hbrush = CreateSolidBrush(windraw->currentcolor);

225:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
226:   else                               hdc = windraw->node->Buffer;

228:   FillRect(hdc,&rect,hbrush);
229:   /* Forces a WM_PAINT message and erases background */
230:   InvalidateRect(windraw->hWnd,NULL,TRUE);
231:   UpdateWindow(windraw->hWnd);
232:   return(0);
233: }

237: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
238: {
239:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
240:   HPEN            hpen;
241:   int             x1,yone,x2,y2;
242:   HDC             hdc;

245:   TranslateColor_Win32(draw,color);
246:   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
247:   yone = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
248:   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
249:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
250:   else                               hdc = windraw->node->Buffer;

252:   SelectPen(hdc,hpen);
253:   MoveToEx(hdc,x1,yone,NULL);
254:   LineTo(hdc,x2,y2);
255:   /* Forces a WM_PAINT message and erases background */
256:   InvalidateRect(windraw->hWnd,NULL,TRUE);
257:   UpdateWindow(windraw->hWnd);
258:   return(0);
259: }

263: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
264: {
265:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
266:   int             averagesize,finalwidth;
267:   RECT            rect;

270:   GetClientRect(windraw->hWnd,&rect);
271:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
272:   finalwidth  = (int)PetscFloorReal(averagesize*width);
273:   if (finalwidth < 1) finalwidth = 1; /* minimum size PetscDrawLine can except */

275:   windraw->linewidth = finalwidth;
276:   return(0);
277: }

281: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
282: {
283:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

286:   *width = (PetscReal)windraw->linewidth;
287:   return(0);
288: }

292: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
293: {
294:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
295:   HBRUSH          hbrush;
296:   HRGN            hrgn;
297:   int             radius;
298:   int             x1,yone;
299:   HDC             hdc;

302:   TranslateColor_Win32(draw,color);
303:   x1     = XTRANS(draw,windraw,x);
304:   yone   = YTRANS(draw,windraw,y);
305:   hbrush = CreateSolidBrush(windraw->currentcolor);
306:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
307:   else                               hdc = windraw->node->Buffer;

309:   /* desired size is one logical pixel so just turn it on */
310:   if (windraw->pointdiameter == 1) SetPixelV(hdc,x1,yone,windraw->currentcolor);
311:   else {
312:     /* draw point around position determined */
313:     radius = windraw->pointdiameter/2; /* integer division */
314:     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
315:     FillRgn(hdc,hrgn,hbrush);
316:   }
317:   /* Forces a WM_PAINT and erases background */
318:   InvalidateRect(windraw->hWnd,NULL,TRUE);
319:   UpdateWindow(windraw->hWnd);
320:   return(0);
321: }

325: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
326: {
327:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
328:   int             averagesize,diameter;
329:   RECT            rect;

332:   GetClientRect(windraw->hWnd,&rect);
333:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
334:   diameter    = (int)PetscFloorReal(averagesize*width);
335:   if (diameter < 1) diameter = 1;
336:   windraw->pointdiameter = diameter;
337:   return(0);
338: }

342: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
343: {
344:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
345:   RECT            r;
346:   HFONT           hfont;
347:   LOGFONT         logfont;
348:   int             x1,yone;
349:   HDC             hdc;

352:   x1       = XTRANS(draw,windraw,x);
353:   yone     = YTRANS(draw,windraw,y);
354:   r.bottom = yone;
355:   r.left   = x1;
356:   r.right  = x1 + 1;
357:   r.top    = yone + 1;

359:   logfont.lfHeight         = windraw->stringheight;
360:   logfont.lfWidth          = windraw->stringwidth;
361:   logfont.lfEscapement     = 0;
362:   logfont.lfOrientation    = 0;
363:   logfont.lfCharSet        = 0;
364:   logfont.lfClipPrecision  = 0;
365:   logfont.lfItalic         = 0;
366:   logfont.lfOutPrecision   = 0;
367:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
368:   logfont.lfQuality        = DEFAULT_QUALITY;
369:   logfont.lfStrikeOut      = 0;
370:   logfont.lfUnderline      = 0;
371:   logfont.lfWeight         = FW_NORMAL;

373:   hfont = CreateFontIndirect(&logfont);
374:   TranslateColor_Win32(draw,color);
375:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
376:   else                               hdc = windraw->node->Buffer;

378:   SelectFont(hdc,hfont);
379:   SetTextColor(hdc,windraw->currentcolor);
380:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
381:   DeleteObject(hfont);
382:   /* Forces a WM_PAINT message and erases background */
383:   InvalidateRect(windraw->hWnd,NULL,TRUE);
384:   UpdateWindow(windraw->hWnd);
385:   return(0);
386: }

390: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
391: {
392:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
393:   RECT            r;
394:   HFONT           hfont;
395:   LOGFONT         logfont;
396:   int             x1,yone;
397:   HDC             hdc;

400:   x1       = XTRANS(draw,windraw,x);
401:   yone     = YTRANS(draw,windraw,y);
402:   r.left   = x1;
403:   r.bottom = yone + 30;
404:   r.right  = x1 + 1;
405:   r.top    = yone - 30;

407:   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
408:   logfont.lfHeight         = windraw->stringheight;
409:   logfont.lfWidth          = windraw->stringwidth;
410:   logfont.lfOrientation    = 0;
411:   logfont.lfCharSet        = DEFAULT_CHARSET;
412:   logfont.lfClipPrecision  = 0;
413:   logfont.lfItalic         = 0;
414:   logfont.lfOutPrecision   = 0;
415:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
416:   logfont.lfQuality        = DEFAULT_QUALITY;
417:   logfont.lfStrikeOut      = 0;
418:   logfont.lfUnderline      = 0;
419:   logfont.lfWeight         = FW_NORMAL;

421:   hfont = CreateFontIndirect(&logfont);
422:   TranslateColor_Win32(draw,color);
423:   if (windraw->node->DoubleBuffered) hdc = windraw->node->DoubleBuffer;
424:   else                               hdc = windraw->node->Buffer;

426:   SelectFont(hdc,hfont);
427:   SetTextColor(hdc,windraw->currentcolor);
428:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE);
429:   DeleteObject(hfont);
430:   /* Forces a WM_PAINT message and erases background */
431:   InvalidateRect(windraw->hWnd,NULL,TRUE);
432:   UpdateWindow(windraw->hWnd);
433:   return(0);
434: }

438: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
439: {
440:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
441:   int             w,h;

444:   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
445:   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
446:   if (h < 1) h = 1;
447:   if (w < 1) w = 1;
448:   windraw->stringheight = h;
449:   windraw->stringwidth  = w;
450:   return(0);
451: }
454: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
455: {
456:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
457:   double          scaleX   = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
458:   double          scaleY   = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);

461:   *height = (double)windraw->stringheight*scaleY;
462:   *width  = (double)windraw->stringwidth*scaleX;
463:   return(0);
464: }

468: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
469: {
470:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
471:   RECT            r;

474:   GetWindowRect(windraw->hWnd,&r);
475:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
476:   /* set all variable dealing with window dimensions */
477:   windraw->node->bitheight = windraw->h = draw->h = h;
478:   windraw->node->bitwidth  = windraw->w = draw->w = w;
479:   /* set up graphic buffers with the new size of window */
480:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
481:   if (windraw->node->DoubleBuffered) SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
482:   windraw->haveresized = PETSC_TRUE;
483:   return(0);
484: }

488: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
489: {
490:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

493:   if (windraw->haveresized == 1) PetscFunctionReturn(1);
494:   else return(0);
495: }

499: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
500: {
501:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

504:   SetWindowText(windraw->hWnd,title);
505:   return(0);
506: }

510: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
511: {
512:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

515:   /* clear primary buffer */
516:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
517:   /* if exists clear secondary buffer */
518:   if (windraw->node->DoubleBuffered) ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

520:   /* force WM_PAINT message so cleared buffer will show */
521:   InvalidateRect(windraw->hWnd,NULL,TRUE);
522:   UpdateWindow(windraw->hWnd);
523:   return(0);
524: }

528: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
529:                                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
530: {
531:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
532:   HBRUSH          hbrush;
533:   HPEN            hpen;
534:   int             p1x,p1y,p2x,p2y,p3x,p3y;
535:   HDC             bit;

538:   AverageColorTriangle_Win32(draw,c1,c2,c3);
539:   hbrush = CreateSolidBrush(windraw->currentcolor);
540:   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
541:   p1x    = XTRANS(draw,windraw,x1);
542:   p2x    = XTRANS(draw,windraw,x2);
543:   p3x    = XTRANS(draw,windraw,x3);
544:   p1y    = YTRANS(draw,windraw,yone);
545:   p2y    = YTRANS(draw,windraw,y2);
546:   p3y    = YTRANS(draw,windraw,y3);

548:   if (windraw->node->DoubleBuffered) bit = windraw->node->DoubleBuffer;
549:   else                               bit = windraw->node->Buffer;

551:   BeginPath(bit);
552:   MoveToEx(bit,p1x,p1y,NULL);
553:   LineTo(bit,p2x,p2y);
554:   LineTo(bit,p3x,p3y);
555:   LineTo(bit,p1x,p1y);
556:   EndPath(bit);
557:   SelectPen(bit,hpen);
558:   SelectBrush(bit,hbrush);
559:   StrokeAndFillPath(bit);
560:   /* Forces a WM_PAINT message and erases background */
561:   InvalidateRect(windraw->hWnd,NULL,TRUE);
562:   UpdateWindow(windraw->hWnd);
563:   return(0);
564: }

568: void PopMessageLoopThread_Win32(PetscDraw popdraw)
569: {
570:   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
571:   MSG             msg;
572:   HWND            hWnd = NULL;
573:   char            PopClassName [MAX_LOADSTRING + 1];
574:   RECT            r;
575:   int             width,height;
576:   WNDCLASSEX      myclass;
577:   LPVOID          lpMsgBuf;

580:   /* initialize window class parameters */
581:   myclass.cbSize        = sizeof(WNDCLASSEX);
582:   myclass.style         = CS_OWNDC;
583:   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
584:   myclass.cbClsExtra    = 0;
585:   myclass.cbWndExtra    = 0;
586:   myclass.hInstance     = NULL;
587:   myclass.hIcon         = NULL;
588:   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
589:   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
590:   myclass.lpszMenuName  = NULL;
591:   myclass.lpszClassName = PopClassName;
592:   myclass.hIconSm       = NULL;

594:   RegisterClassEx(&myclass);

596:   SetRect(&r,0,0,450,450);

598:   width  = (r.right - r.left) / 3;
599:   height = (r.bottom - r.top) / 3;

601:   hWnd = CreateWindowEx(0,
602:                         PopClassName,
603:                         NULL,
604:                         WS_POPUPWINDOW | WS_CAPTION,
605:                         0,0,
606:                         width,height,
607:                         NULL,
608:                         NULL,
609:                         hInst,
610:                         NULL);
611:   pop->x = 0;
612:   pop->y = 0;
613:   pop->w = width;
614:   pop->h = height;

616:   if (!hWnd) {
617:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
618:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
619:     LocalFree(lpMsgBuf);
620:     exit(0);
621:   }
622:   pop->hWnd = hWnd;
623:   /* display and update new popup window */
624:   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
625:   UpdateWindow(pop->hWnd);
626:   SetEvent(pop->hReadyEvent);

628:   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
629:     TranslateMessage(&msg);
630:     DispatchMessage(&msg);
631:   }
632:   PetscFunctionReturnVoid();
633: }

637: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
638: {
639:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;

642:   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
643:   PetscFree(windraw);
644:   return(0);
645: }

649: static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
650: {
651:   /* Multi Processor is not implemeted yet */
653:   PetscDrawFlush_Win32(draw);
654:   return(0);
655: }

659: static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
660: {
661:   /* Multi Processor is not implemeted yet */
663:   PetscDrawClear_Win32(draw);
664:   return(0);
665: }

669: void MessageLoopThread_Win32(PetscDraw draw)
670: {
671:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
672:   MSG             msg;
673:   HWND            hWnd = NULL;
674:   char            classname[MAX_LOADSTRING + 1];
675:   WNDCLASSEX      wclass;
676:   LPVOID          lpMsgBuf;

679:   /* initialize window class parameters */
680:   wclass.cbSize        = sizeof(WNDCLASSEX);
681:   wclass.style         = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
682:   wclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
683:   wclass.cbClsExtra    = 0;
684:   wclass.cbWndExtra    = 0;
685:   wclass.hInstance     = NULL;
686:   wclass.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
687:   wclass.hCursor       = LoadCursor(NULL,IDC_ARROW);
688:   wclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
689:   wclass.lpszMenuName  = NULL;
690:   wclass.lpszClassName = classname;
691:   wclass.hIconSm       = NULL;

693:   RegisterClassEx(&wclass);


696:   hWnd = CreateWindowEx(0,
697:                         classname,
698:                         NULL,
699:                         WS_OVERLAPPEDWINDOW,
700:                         draw->x,
701:                         draw->y,
702:                         draw->w,
703:                         draw->h,
704:                         NULL,
705:                         NULL,
706:                         hInst,
707:                         NULL);

709:   if (!hWnd) {
710:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
711:     MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
712:     LocalFree(lpMsgBuf);
713:     exit(0);
714:   }
715:   windraw->hWnd = hWnd;
716:   /* display and update new window */
717:   ShowWindow(hWnd,SW_SHOWNORMAL);
718:   UpdateWindow(hWnd);
719:   SetEvent(windraw->hReadyEvent);

721:   while (GetMessage(&msg,hWnd, 0, 0)) {
722:     TranslateMessage(&msg);
723:     DispatchMessage(&msg);
724:   }
725:   PetscFunctionReturnVoid();
726: }


729: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
730:                                       PetscDrawFlush_Win32,
731:                                       PetscDrawLine_Win32,
732:                                       PetscDrawLineSetWidth_Win32,
733:                                       PetscDrawLineGetWidth_Win32,
734:                                       PetscDrawPoint_Win32,
735:                                       PetscDrawPointSetSize_Win32,
736:                                       PetscDrawString_Win32,
737:                                       PetscDrawStringVertical_Win32,
738:                                       PetscDrawStringSetSize_Win32,
739:                                       PetscDrawStringGetSize_Win32,
740:                                       0,
741:                                       PetscDrawClear_Win32,
742:                                       PetscDrawSynchronizedFlush_Win32,
743:                                       PetscDrawRectangle_Win32,
744:                                       PetscDrawTriangle_Win32,
745:                                       0,
746:                                       PetscDrawGetMouseButton_Win32,
747:                                       PetscDrawPause_Win32,
748:                                       PetscDrawSynchronizedClear_Win32,
749:                                       0,
750:                                       0,
751:                                       PetscDrawGetPopup_Win32,
752:                                       PetscDrawSetTitle_Win32,
753:                                       PetscDrawCheckResizedWindow_Win32,
754:                                       PetscDrawResizeWindow_Win32,
755:                                       PetscDrawDestroy_Win32,
756:                                       0,
757:                                       0,
758:                                       0,
759:                                       0};

763: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
764: {
765:   PetscDraw_Win32 *pop;
766:   HANDLE          hThread = NULL;
767:   WindowNode      newnode;
768:   PetscErrorCode  ierr;

771:   PetscNew(&pop);

773:   (*popdraw)->data = pop;

775:   /* the following is temporary fix for initializing a global datastructure */
776:   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
777:   PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));

779:   pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
780:   CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
781:   CloseHandle(hThread);
782:   WaitForSingleObject(pop->hReadyEvent, INFINITE);
783:   CloseHandle(pop->hReadyEvent);
784:   WaitForSingleObject(g_hWindowListMutex, INFINITE);

786:   draw->popup            = (*popdraw);
787:   PetscNew(&newnode);
788:   newnode->MouseListHead = NULL;
789:   newnode->MouseListTail = NULL;
790:   newnode->wnext         = WindowListHead;
791:   newnode->wprev         = NULL;
792:   newnode->hWnd          = pop->hWnd;
793:   if (WindowListHead != NULL) WindowListHead->wprev = newnode;
794:   WindowListHead         = newnode;
795:   pop->hdc               = GetDC(pop->hWnd);

797:   pop->stringheight  = 10;
798:   pop->stringwidth   = 6;
799:   pop->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
800:   pop->pointdiameter = 1;
801:   pop->node          = newnode;

803:   newnode->bitwidth  = pop->w;
804:   newnode->bitheight = pop->h;

806:   /* Create and initialize primary graphics buffer */
807:   newnode->Buffer    = CreateCompatibleDC(pop->hdc);
808:   newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
809:   newnode->store     = SelectObject(newnode->Buffer,newnode->BufferBit);
810:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);


813:   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
814:   newnode->DoubleBuffered = PETSC_FALSE;

816:   ReleaseDC(pop->hWnd,pop->hdc);
817:   ReleaseMutex(g_hWindowListMutex);
818:   return(0);
819: }

821: EXTERN_C_BEGIN
824: PetscErrorCode  PetscDrawCreate_Win32(PetscDraw draw)
825: {
826:   PetscDraw_Win32 *windraw;
827:   HANDLE          hThread = NULL;
828:   PetscErrorCode  ierr;
829:   WindowNode      newnode;

832:   PetscNew(&windraw);
833:   draw->data = windraw;

835:   /* the following is temporary fix for initializing a global datastructure */
836:   if (!g_hWindowListMutex) g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
837:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));

839:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
840:   /* makes call to MessageLoopThread to creat window and attach a thread */
841:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
842:   CloseHandle(hThread);
843:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
844:   CloseHandle(windraw->hReadyEvent);
845:   WaitForSingleObject(g_hWindowListMutex,INFINITE);

847:   PetscNew(&newnode);
848:   newnode->MouseListHead = NULL;
849:   newnode->MouseListTail = NULL;
850:   newnode->wnext         = WindowListHead;
851:   newnode->wprev         = NULL;
852:   newnode->hWnd          = windraw->hWnd;
853:   if (WindowListHead != NULL) WindowListHead->wprev = newnode;
854:   WindowListHead         = newnode;
855:   windraw->hdc           = GetDC(windraw->hWnd);

857:   windraw->stringheight  = 10;
858:   windraw->stringwidth   = 6;
859:   windraw->linewidth     = 1;    /* default pixel sizes of graphics until user changes them */
860:   windraw->pointdiameter = 1;
861:   windraw->node          = newnode;

863:   windraw->x = draw->x;
864:   windraw->y = draw->y;
865:   windraw->w = newnode->bitwidth    = draw->w;
866:   windraw->h = newnode->bitheight   = draw->h;

868:   /* Create and initialize primary graphics buffer */
869:   newnode->Buffer    = CreateCompatibleDC(windraw->hdc);
870:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
871:   newnode->store     = SelectObject(newnode->Buffer,newnode->BufferBit);
872:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);

874:   newnode->event          = CreateEvent(NULL,TRUE,FALSE,NULL);
875:   newnode->DoubleBuffered = PETSC_FALSE;

877:   ReleaseDC(windraw->hWnd,windraw->hdc);
878:   ReleaseMutex(g_hWindowListMutex);
879:   return(0);
880: }
881: EXTERN_C_END


884: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
885:    PURPOSE:  Processes messages for the main window.
886:    WM_COMMAND  - process the application menu
887:    WM_PAINT    - Paint the main window
888:    WM_DESTROY  - post a quit message and return */

892: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
893: {
894:   int wmId, wmEvent;

897:   switch (message) {
898:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
899:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
900:   case WM_COMMAND:
901:     wmId    = LOWORD(wParam);
902:     wmEvent = HIWORD(wParam);
903:     /* Parse the menu selections:*/
904:     switch (wmId) {
905:     case IDM_EXIT:
906:       DestroyWindow(hWnd);
907:       break;
908:     default:
909:       return DefWindowProc(hWnd, message, wParam, lParam);
910:     }
911:     break;
912:   case WM_LBUTTONUP:
913:     MouseRecord_Win32(hWnd,PETSC_BUTTON_LEFT);
914:     break;
915:   case WM_RBUTTONUP:
916:     MouseRecord_Win32(hWnd,PETSC_BUTTON_RIGHT);
917:     break;
918:   case WM_MBUTTONUP:
919:     MouseRecord_Win32(hWnd,PETSC_BUTTON_CENTER);
920:     break;
921:   default:
922:     PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
923:   }
924:   return(0);
925: }

929: static void OnPaint_Win32(HWND hWnd)
930: {
931:   PAINTSTRUCT ps;
932:   HDC         hdc;
933:   WindowNode  current = NULL;

936:   InvalidateRect(hWnd,NULL,TRUE);
937:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
938:   current = WindowListHead;
939:   hdc     = BeginPaint(hWnd, &ps);

941:   while (current != NULL) {
942:     if (current->hWnd == hWnd) {
943:       /* flushes primary buffer to window */
944:       BitBlt(hdc,0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES),
945:              current->Buffer,0,0,SRCCOPY);

947:       /* StretchBlt(hdc,0,0,w,h,
948:         current->Buffer,0,0,current->bitwidth,current->bitheight,SRCCOPY); */
949:       break;
950:     }
951:     current = current->wnext;
952:   }
953:   EndPaint(hWnd, &ps);
954:   ReleaseMutex(g_hWindowListMutex);
955:   PetscFunctionReturnVoid();
956: }

960: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
961: {
962:   /* Called by all three mouse button actions
963:     Records needed mouse data in windows data structure */
964:   WindowNode     current = NULL;
965:   MouseNode      newnode;
966:   POINT          mousepos;

970:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
971:   current = WindowListHead;
972:   if (current->IsGetMouseOn == TRUE) {

974:     SetEvent(current->event);
975:     while (current != NULL) {
976:       if (current->hWnd == hWnd) {

978:         PetscNew(&newnode);
979:         newnode->Button = button;
980:         GetCursorPos(&mousepos);
981:         newnode->user.x = mousepos.x;
982:         newnode->user.y = mousepos.y;
983:         ScreenToClient(hWnd,&mousepos);
984:         newnode->phys.x = mousepos.x;
985:         newnode->phys.y = mousepos.y;
986:         if (!current->MouseListTail) {
987:           current->MouseListHead = newnode;
988:           current->MouseListTail = newnode;
989:         } else {
990:           current->MouseListTail->mnext = newnode;
991:           current->MouseListTail        = newnode;
992:         }
993:         newnode->mnext = NULL;

995:         break;
996:       }
997:       current = current->wnext;
998:     }
999:   }
1000:   ReleaseMutex(g_hWindowListMutex);
1001:   return(0);
1002: }

1006: static void OnDestroy_Win32(HWND hWnd)
1007: {
1008:   /* searches linked list of window data and frees corresponding memory */
1009:   WindowNode current;

1012:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1013:   current = WindowListHead;

1015:   SetEvent(current->event);
1016:   while (current != NULL) {
1017:     if (current->hWnd == hWnd) {
1018:       if (current->wprev != NULL) current->wprev->wnext = current->wnext;
1019:       else WindowListHead = current->wnext;
1020:       if (current->MouseListHead) deletemouselist_Win32(current);
1021:       else PetscFree(current);
1022:       break;
1023:     }
1024:     current = current->wnext;
1025:   }
1026:   ReleaseMutex(g_hWindowListMutex);
1027:   PostQuitMessage(0);
1028:   PetscFunctionReturnVoid();
1029: }