Actual source code: win32draw.c

  1: #include "petsc.h"
  2: #include "src/sys/src/draw/drawimpl.h"
  3: #include "win32draw.h"

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

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

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

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

 37: /* Hard coded color hue until hue.c works with this */
 38: 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};
 39: 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};
 40: 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};

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

 55: static PetscErrorCode PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
 56: {
 57:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 58:   HDC             hdc      = GetDC(windraw->hWnd);
 59: 
 61:   windraw->node->DoubleBuffer = CreateCompatibleDC(hdc);
 62:   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
 63:   windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
 64:   /* Fill background of second buffer */
 65:   ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
 66:   /* Copy current buffer into seconf buffer and set window data as double buffered */
 67:   BitBlt(windraw->node->DoubleBuffer,
 68:          0,0,
 69:          windraw->w,windraw->h,
 70:          windraw->node->Buffer,
 71:          0,0,
 72:          SRCCOPY);

 74:   windraw->node->DoubleBuffered = PETSC_TRUE;
 75:   ReleaseDC(windraw->hWnd,hdc);
 76:   return(0);
 77: }
 80: static PetscErrorCode PetscDrawFlush_Win32(PetscDraw draw)
 81: {
 82:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 83:   HDC             hdc = GetDC(windraw->hWnd);
 84: 
 86:   /* flush double buffer into primary buffer */
 87:   BitBlt(windraw->node->Buffer,
 88:          0,0,
 89:          windraw->w,windraw->h,
 90:          windraw->node->DoubleBuffer,
 91:          0,0,
 92:          SRCCOPY);
 93:   /* flush double buffer into window */
 94:   BitBlt(hdc,
 95:          0,0,
 96:          windraw->w,windraw->h,
 97:          windraw->node->DoubleBuffer,
 98:          0,0,
 99:          SRCCOPY);
100:   ReleaseDC(windraw->hWnd,hdc);
101:   return(0);
102: }

106: static PetscErrorCode deletemouselist_Win32(WindowNode deletelist)
107: {
108:   /* Called upon window close. Frees memory of linked list of stored mouse commands */
109:   MouseNode node;
110: 
111:   while(deletelist->MouseListHead != NULL) {
112:     node = deletelist->MouseListHead;
113:     if(deletelist->MouseListHead->mnext != NULL) {
114:       deletelist->MouseListHead = deletelist->MouseListHead->mnext;
115:     }
116:     PetscFree(node);
117:   }
118:   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
119:   if (deletelist->wprev != NULL) {
120:     deletelist->wprev->wnext = deletelist->wnext;
121:   }
122:   if (deletelist->wnext != NULL) {
123:     deletelist->wnext->wprev = deletelist->wprev;
124:   }
125:   PetscFree(deletelist);
126:   return 0;
127: }

131: static PetscErrorCode PetscDrawGetMouseButton_Win32(PetscDraw draw, PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
132: {
133:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
134:   WindowNode      current;
135:   MouseNode       node=0;
136: 
138:   /* Make sure no other code is using the linked list at this moment */
139:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
140:   /* Look for the node that matches the window you are using */
141:   current = WindowListHead;
142:   while (current != NULL) {
143:     if(current->hWnd == windraw->hWnd) {
144:       current->IsGetMouseOn = TRUE;
145:       break;
146:     } else {
147:       current = current->wnext;
148:     }
149:   }
150:   /* If no actions have occured, wait for one */
151:   node = current->MouseListHead;
152:   if (!node) {
153:     ReleaseMutex(g_hWindowListMutex);
154:     WaitForSingleObject(current->event, INFINITE);
155:     WaitForSingleObject(g_hWindowListMutex, INFINITE);
156:   }
157:   /* once we have the information, assign the pointers to it */
158:   *button = current->MouseListHead->Button;
159:   *x_user = current->MouseListHead->user.x;
160:   *y_user = current->MouseListHead->user.y;
161:   /* optional arguments */
162:   if (x_phys) *x_phys = current->MouseListHead->phys.x;
163:   if (y_phys) *y_phys = current->MouseListHead->phys.y;
164:   /* remove set of information from sub linked-list, delete the node */
165:   current->MouseListHead = current->MouseListHead->mnext;
166:   if (!current->MouseListHead) {
167:     ResetEvent(current->event);
168:     current->MouseListTail = NULL;
169:   }
170:   if (node) PetscFree(node);

172:   /* Release mutex so that  other code can use
173:      the linked list now that we are done with it */
174:   ReleaseMutex(g_hWindowListMutex);
175:   return(0);
176: }

180: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
181: {
183:   PetscSleep(draw->pause);
184:   return(0);
185: }

189: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
190: {
191:   /* Maps single color value into the RGB colors in our tables */
192:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
193:   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
194:   return 0;
195: }
198: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
199: {
200:   /* Averages colors given at points of rectangle and sets color from color table
201:     will be changed once the color gradient problem is worked out */
202:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
203:   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
204:                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
205:                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
206:   return 0;
207: }
210: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
211: {
212:   /* Averages colors given at points of rectangle and sets color from color table
213:     will be changed once the color gradient problem is worked out */
214:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
215:   windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
216:                               (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
217:                               (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
218:   return 0;
219: }
222: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
223: {
224:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
225:   HBRUSH          hbrush;
226:   RECT            rect;
227:   int             x1,yone,x2,y2;
228:   HDC             hdc;
229: 
231:   x1 = XTRANS(draw,windraw,xl);
232:   x2 = XTRANS(draw,windraw,xr);
233:   yone = YTRANS(draw,windraw,yl);
234:   y2 = YTRANS(draw,windraw,yr);
235:   SetRect(&rect,x1,y2,x2,yone);
236:   if (c1==c2 && c2==c3 && c3==c4) {
237:     TranslateColor_Win32(draw,c1);
238:   } else {
239:     AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
240:   }
241:   hbrush = CreateSolidBrush(windraw->currentcolor);
242: 
243:   if(windraw->node->DoubleBuffered) {
244:     hdc = windraw->node->DoubleBuffer;
245:   } else {
246:     hdc = windraw->node->Buffer;
247:   }
248:   FillRect(hdc,&rect,hbrush);
249:   /* Forces a WM_PAINT message and erases background */
250:   InvalidateRect(windraw->hWnd,NULL,TRUE);
251:   UpdateWindow(windraw->hWnd);
252:   return(0);
253: }
256: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
257: {
258:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
259:   HPEN            hpen;
260:   int             x1,yone,x2,y2;
261:   HDC             hdc;
262: 
264:   TranslateColor_Win32(draw,color);
265:   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
266:   yone   = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
267:   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
268:   if(windraw->node->DoubleBuffered) {
269:     hdc = windraw->node->DoubleBuffer;
270:   } else {
271:     hdc = windraw->node->Buffer;
272:   }
273:   SelectPen(hdc,hpen);
274:   MoveToEx(hdc,x1,yone,NULL);
275:   LineTo(hdc,x2,y2);
276:   /* Forces a WM_PAINT message and erases background */
277:   InvalidateRect(windraw->hWnd,NULL,TRUE);
278:   UpdateWindow(windraw->hWnd);
279:   return(0);
280: }

284: static PetscErrorCode PetscDrawLineSetWidth_Win32(PetscDraw draw,PetscReal width)
285: {
286:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
287:   int             averagesize,finalwidth;
288:   RECT            rect;
289: 
291:   GetClientRect(windraw->hWnd,&rect);
292:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
293:   finalwidth  = (int)floor(averagesize*width);
294:   if (finalwidth < 1) {
295:     finalwidth = 1; /* minimum size PetscDrawLine can except */
296:   }
297:   windraw->linewidth = finalwidth;
298:   return(0);
299: }

303: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
304: {
305:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
306: 
308:   *width = (PetscReal)windraw->linewidth;
309:   return(0);
310: }
313: static PetscErrorCode PetscDrawPoint_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color)
314: {
315:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
316:   HBRUSH          hbrush;
317:   HRGN            hrgn;
318:   int             radius;
319:   int             x1,yone;
320:   HDC             hdc;
321: 
323:   TranslateColor_Win32(draw,color);
324:   x1     = XTRANS(draw,windraw,x);
325:   yone     = YTRANS(draw,windraw,y);
326:   hbrush = CreateSolidBrush(windraw->currentcolor);
327:   if(windraw->node->DoubleBuffered) {
328:     hdc = windraw->node->DoubleBuffer;
329:   } else {
330:     hdc = windraw->node->Buffer;
331:   }
332:   /* desired size is one logical pixel so just turn it on */
333:   if (windraw->pointdiameter == 1) {
334:     SetPixelV(hdc,x1,yone,windraw->currentcolor);
335:   } else {
336:     /* draw point around position determined */
337:     radius = windraw->pointdiameter/2; /* integer division */
338:     hrgn   = CreateEllipticRgn(x1-radius,yone-radius,x1+radius,yone+radius);
339:     FillRgn(hdc,hrgn,hbrush);
340:   }
341:   /* Forces a WM_PAINT and erases background */
342:   InvalidateRect(windraw->hWnd,NULL,TRUE);
343:   UpdateWindow(windraw->hWnd);
344:   return(0);
345: }

349: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
350: {
351:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
352:   int             averagesize,diameter;
353:   RECT            rect;
354: 
356:   GetClientRect(windraw->hWnd,&rect);
357:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
358:   diameter    = (int)floor(averagesize*width);
359:   if (diameter < 1) diameter = 1;
360:   windraw->pointdiameter     = diameter;
361:   return(0);
362: }
365: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
366: {
367:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
368:   RECT            r;
369:   HFONT           hfont;
370:   LOGFONT         logfont;
371:   int             x1,yone;
372:   HDC             hdc;
373: 
375:   x1              = XTRANS(draw,windraw,x);
376:   yone              = YTRANS(draw,windraw,y);
377:   r.bottom        = yone;
378:   r.left          = x1;
379:   r.right         = x1 + 1;
380:   r.top           = yone + 1;
381:   logfont.lfHeight         = windraw->stringheight;
382:   logfont.lfWidth          = windraw->stringwidth;
383:   logfont.lfEscapement     = 0;
384:   logfont.lfOrientation    = 0;
385:   logfont.lfCharSet        = 0;
386:   logfont.lfClipPrecision  = 0;
387:   logfont.lfItalic         = 0;
388:   logfont.lfOutPrecision   = 0;
389:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
390:   logfont.lfQuality        = DEFAULT_QUALITY;
391:   logfont.lfStrikeOut      = 0;
392:   logfont.lfUnderline      = 0;
393:   logfont.lfWeight         = FW_NORMAL;
394:   hfont = CreateFontIndirect(&logfont);
395:   TranslateColor_Win32(draw,color);
396:   if(windraw->node->DoubleBuffered) {
397:     hdc = windraw->node->DoubleBuffer;
398:   } else {
399:     hdc = windraw->node->Buffer;
400:   }
401:   SelectFont(hdc,hfont);
402:   SetTextColor(hdc,windraw->currentcolor);
403:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
404:   DeleteObject(hfont);
405:   /* Forces a WM_PAINT message and erases background */
406:   InvalidateRect(windraw->hWnd,NULL,TRUE);
407:   UpdateWindow(windraw->hWnd);
408:   return(0);
409: }
412: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
413: {
414:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
415:   RECT            r;
416:   HFONT           hfont;
417:   LOGFONT         logfont;
418:   int             x1,yone;
419:   HDC             hdc;
420: 
422:   x1           = XTRANS(draw,windraw,x);
423:   yone           = YTRANS(draw,windraw,y);
424:   r.left       = x1;
425:   r.bottom     = yone + 30;
426:   r.right      = x1 + 1;
427:   r.top        = yone - 30;
428:   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
429:   logfont.lfHeight         = windraw->stringheight;
430:   logfont.lfWidth          = windraw->stringwidth;
431:   logfont.lfOrientation    = 0;
432:   logfont.lfCharSet        = DEFAULT_CHARSET;
433:   logfont.lfClipPrecision  = 0;
434:   logfont.lfItalic         = 0;
435:   logfont.lfOutPrecision   = 0;
436:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
437:   logfont.lfQuality        = DEFAULT_QUALITY;
438:   logfont.lfStrikeOut      = 0;
439:   logfont.lfUnderline      = 0;
440:   logfont.lfWeight         = FW_NORMAL;
441:   hfont = CreateFontIndirect(&logfont);
442:   TranslateColor_Win32(draw,color);
443:   if(windraw->node->DoubleBuffered) {
444:     hdc = windraw->node->DoubleBuffer;
445:   } else {
446:     hdc = windraw->node->Buffer;
447:   }
448:   SelectFont(hdc,hfont);
449:   SetTextColor(hdc,windraw->currentcolor);
450:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE );
451:   DeleteObject(hfont);
452:   /* Forces a WM_PAINT message and erases background */
453:   InvalidateRect(windraw->hWnd,NULL,TRUE);
454:   UpdateWindow(windraw->hWnd);
455:   return(0);
456: }
459: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
460: {
461:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
462:   int             w,h;
463: 
465:   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
466:   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
467:   if (h < 1) h = 1;
468:   if (w < 1) w = 1;
469:   windraw->stringheight = h;
470:   windraw->stringwidth  = w;
471:   return(0);
472: }
475: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
476: {
477:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
478:   double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
479:   double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
480: 
482:   *height = (double)windraw->stringheight*scaleY;
483:   *width  = (double)windraw->stringwidth*scaleX;
484:   return(0);
485: }

489: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
490: {
491:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
492:   RECT            r;
493: 
495:   GetWindowRect(windraw->hWnd,&r);
496:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
497:   /* set all variable dealing with window dimensions */
498:   windraw->node->bitheight = windraw->h = draw->h = h;
499:   windraw->node->bitwidth  = windraw->w = draw->w = w;
500:   /* set up graphic buffers with the new size of window */
501:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
502:   if(windraw->node->DoubleBuffered) {
503:     SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
504:   }
505:   windraw->haveresized = PETSC_TRUE;
506:   return(0);
507: }

511: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
512: {
513:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
514: 
516:   if (windraw->haveresized == 1) {
517:     PetscFunctionReturn(1);
518:   } else {
519:     return(0);
520:   }
521: 
522: }

526: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
527: {
528:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
529: 
531:   SetWindowText(windraw->hWnd,title);
532:   return(0);
533: }

537: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
538: {
539:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
540: 
542:   /* clear primary buffer */
543:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
544:   /* if exists clear secondary buffer */
545:   if(windraw->node->DoubleBuffered) {
546:     ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
547:   }
548:   /* force WM_PAINT message so cleared buffer will show */
549:   InvalidateRect(windraw->hWnd,NULL,TRUE);
550:   UpdateWindow(windraw->hWnd);
551:   return(0);
552: }

556: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
557:                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
558: {
559:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
560:   HBRUSH          hbrush;
561:   HPEN            hpen;
562:   int             p1x,p1y,p2x,p2y,p3x,p3y;
563:   HDC             bit;
564: 
566:   AverageColorTriangle_Win32(draw,c1,c2,c3);
567:   hbrush = CreateSolidBrush(windraw->currentcolor);
568:   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
569:   p1x = XTRANS(draw,windraw,x1);
570:   p2x = XTRANS(draw,windraw,x2);
571:   p3x = XTRANS(draw,windraw,x3);
572:   p1y = YTRANS(draw,windraw,yone);
573:   p2y = YTRANS(draw,windraw,y2);
574:   p3y = YTRANS(draw,windraw,y3);
575: 
576:   if(windraw->node->DoubleBuffered) {
577:     bit = windraw->node->DoubleBuffer;
578:   } else {
579:     bit = windraw->node->Buffer;
580:   }
581:   BeginPath(bit);
582:   MoveToEx(bit,p1x,p1y,NULL);
583:   LineTo(bit,p2x,p2y);
584:   LineTo(bit,p3x,p3y);
585:   LineTo(bit,p1x,p1y);
586:   EndPath(bit);
587:   SelectPen(bit,hpen);
588:   SelectBrush(bit,hbrush);
589:   StrokeAndFillPath(bit);
590:   /* Forces a WM_PAINT message and erases background */
591:   InvalidateRect(windraw->hWnd,NULL,TRUE);
592:   UpdateWindow(windraw->hWnd);
593:   return(0);
594: }
597: void PopMessageLoopThread_Win32(PetscDraw popdraw)
598: {
599:   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
600:   MSG             msg;
601:   HWND            hWnd = NULL;
602:   char            PopClassName [MAX_LOADSTRING + 1];
603:   RECT            r;
604:   int             width,height;
605:   WNDCLASSEX      myclass;
606:   LPVOID          lpMsgBuf;
607: 
608:   /* initialize window class parameters */
609:   myclass.cbSize        = sizeof(WNDCLASSEX);
610:   myclass.style         = CS_OWNDC;
611:   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
612:   myclass.cbClsExtra    = 0;
613:   myclass.cbWndExtra    = 0;
614:   myclass.hInstance     = NULL;
615:   myclass.hIcon         = NULL;
616:   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
617:   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
618:   myclass.lpszMenuName  = NULL;
619:   myclass.lpszClassName = PopClassName;
620:   myclass.hIconSm       = NULL;
621: 
622:   RegisterClassEx(&myclass);
623: 
624:   SetRect(&r,0,0,450,450);
625: 
626:   width    = (r.right - r.left) / 3;
627:   height   = (r.bottom - r.top) / 3;
628: 
629:   hWnd = CreateWindowEx(0,
630:                         PopClassName,
631:                         NULL,
632:                         WS_POPUPWINDOW | WS_CAPTION,
633:                         0,0,
634:                         width,height,
635:                         NULL,
636:                         NULL,
637:                         hInst,
638:                         NULL);
639:   pop->x = 0;
640:   pop->y = 0;
641:   pop->w = width;
642:   pop->h = height;
643: 
644:   if(!hWnd) {
645:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
646:     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
647:     LocalFree( lpMsgBuf );
648:     exit(0);
649:   }
650:   pop->hWnd = hWnd;
651:   /* display and update new popup window */
652:   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
653:   UpdateWindow(pop->hWnd);
654:   SetEvent(pop->hReadyEvent);
655: 
656:   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
657:     TranslateMessage(&msg);
658:     DispatchMessage(&msg);
659:   }
660: }

664: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
665: {
666:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
667: 
669:   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
670:   PetscFree(windraw);
671:   return(0);
672: }
675: static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
676: {
677:   /* Multi Processor is not implemeted yet */
679:   PetscDrawFlush_Win32(draw);
680:   return(0);
681: }
684: static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
685: {
686:   /* Multi Processor is not implemeted yet */
688:   PetscDrawClear_Win32(draw);
689:   return(0);
690: }
693: void MessageLoopThread_Win32(PetscDraw draw)
694: {
695:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
696:   MSG             msg;
697:   HWND            hWnd = NULL;
698:   char            classname[MAX_LOADSTRING + 1];
699:   WNDCLASSEX      wclass;
700:   LPVOID          lpMsgBuf;
701: 
702:   /* initialize window class parameters */
703:   wclass.cbSize         = sizeof(WNDCLASSEX);
704:   wclass.style          = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
705:   wclass.lpfnWndProc    = (WNDPROC)PetscWndProc;
706:   wclass.cbClsExtra     = 0;
707:   wclass.cbWndExtra     = 0;
708:   wclass.hInstance      = NULL;
709:   wclass.hIcon          = LoadIcon(NULL,IDI_APPLICATION);
710:   wclass.hCursor        = LoadCursor(NULL,IDC_ARROW);
711:   wclass.hbrBackground  = GetStockBrush(WHITE_BRUSH);
712:   wclass.lpszMenuName   = NULL;
713:   wclass.lpszClassName  = classname;
714:   wclass.hIconSm        = NULL;
715: 
716:   RegisterClassEx(&wclass);
717: 
718: 
719:   hWnd = CreateWindowEx(0,
720:                         classname,
721:                         NULL,
722:                         WS_OVERLAPPEDWINDOW,
723:                         draw->x,
724:                         draw->y,
725:                         draw->w,
726:                         draw->h,
727:                         NULL,
728:                         NULL,
729:                         hInst,
730:                         NULL);
731: 
732:   if (!hWnd) {
733:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
734:     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
735:     LocalFree( lpMsgBuf );
736:     exit(0);
737:   }
738:   windraw->hWnd = hWnd;
739:   /* display and update new window */
740:   ShowWindow(hWnd,SW_SHOWNORMAL);
741:   UpdateWindow(hWnd);
742:   SetEvent(windraw->hReadyEvent);
743: 
744:   while (GetMessage(&msg,hWnd, 0, 0)) {
745:     TranslateMessage(&msg);
746:     DispatchMessage(&msg);
747:   }
748: }


751: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
752:                                  PetscDrawFlush_Win32,
753:                                  PetscDrawLine_Win32,
754:                                  PetscDrawLineSetWidth_Win32,
755:                                  PetscDrawLineGetWidth_Win32,
756:                                  PetscDrawPoint_Win32,
757:                                  PetscDrawPointSetSize_Win32,
758:                                  PetscDrawString_Win32,
759:                                  PetscDrawStringVertical_Win32,
760:                                  PetscDrawStringSetSize_Win32,
761:                                  PetscDrawStringGetSize_Win32,
762:                                  0,
763:                                  PetscDrawClear_Win32,
764:                                  PetscDrawSynchronizedFlush_Win32,
765:                                  PetscDrawRectangle_Win32,
766:                                  PetscDrawTriangle_Win32,
767:                                  0,
768:                                  PetscDrawGetMouseButton_Win32,
769:                                  PetscDrawPause_Win32,
770:                                  PetscDrawSynchronizedClear_Win32,
771:                                  0,
772:                                  0,
773:                                  PetscDrawGetPopup_Win32,
774:                                  PetscDrawSetTitle_Win32,
775:                                  PetscDrawCheckResizedWindow_Win32,
776:                                  PetscDrawResizeWindow_Win32,
777:                                  PetscDrawDestroy_Win32,
778:                                  0,
779:                                  0,
780:                                  0,
781:                                  0};


784: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
785: {
786:   PetscDraw_Win32 *pop;
787:   HANDLE          hThread = NULL;
788:   WindowNode      newnode;
790: 
792:   PetscNew(PetscDraw_Win32,&pop);
793:   (*popdraw)->data = pop;
794: 
795:   /* the following is temporary fix for initializing a global datastructure */
796:   if(!g_hWindowListMutex) {
797:     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
798:   }
799:   PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));
800: 
801:   pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
802:   CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
803:   CloseHandle(hThread);
804:   WaitForSingleObject(pop->hReadyEvent, INFINITE);
805:   CloseHandle(pop->hReadyEvent);
806:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
807: 
808:   draw->popup             = (*popdraw);
809:   PetscNew(struct _p_WindowNode,&newnode);
810:   newnode->MouseListHead  = NULL;
811:   newnode->MouseListTail  = NULL;
812:   newnode->wnext          = WindowListHead;
813:   newnode->wprev          = NULL;
814:   newnode->hWnd           = pop->hWnd;
815:   if(WindowListHead != NULL) {
816:     WindowListHead->wprev = newnode;
817:   }
818:   WindowListHead          = newnode;
819:   pop->hdc                = GetDC(pop->hWnd);
820: 
821:   pop->stringheight   = 10;
822:   pop->stringwidth    = 6;
823:   pop->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
824:   pop->pointdiameter  = 1;
825:   pop->node           = newnode;
826: 
827:   newnode->bitwidth  = pop->w;
828:   newnode->bitheight = pop->h;
829: 
830:   /* Create and initialize primary graphics buffer */
831:   newnode->Buffer = CreateCompatibleDC(pop->hdc);
832:   newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
833:   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
834:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
835: 
836: 
837:   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
838:   newnode->DoubleBuffered = PETSC_FALSE;
839: 
840:   ReleaseDC(pop->hWnd,pop->hdc);
841:   ReleaseMutex(g_hWindowListMutex);
842:   return(0);
843: }


847: PetscErrorCode PetscDrawCreate_Win32(PetscDraw draw)
848: {
849:   PetscDraw_Win32 *windraw;
850:   HANDLE          hThread = NULL;
852:   WindowNode      newnode;
853: 
854:   PetscNew(PetscDraw_Win32,&windraw);
855:   draw->data  = windraw;
856: 
857:   /* the following is temporary fix for initializing a global datastructure */
858:   if(!g_hWindowListMutex) {
859:     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
860:   }
861:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
862: 
863:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
864:   /* makes call to MessageLoopThread to creat window and attach a thread */
865:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
866:   CloseHandle(hThread);
867:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
868:   CloseHandle(windraw->hReadyEvent);
869:   WaitForSingleObject(g_hWindowListMutex,INFINITE);
870: 
871:   PetscNew(struct _p_WindowNode,&newnode);
872:   newnode->MouseListHead  = NULL;
873:   newnode->MouseListTail  = NULL;
874:   newnode->wnext          = WindowListHead;
875:   newnode->wprev          = NULL;
876:   newnode->hWnd           = windraw->hWnd;
877:   if(WindowListHead != NULL) {
878:     WindowListHead->wprev = newnode;
879:   }
880:   WindowListHead          = newnode;
881:   windraw->hdc            = GetDC(windraw->hWnd);
882: 
883:   windraw->stringheight   = 10;
884:   windraw->stringwidth    = 6;
885:   windraw->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
886:   windraw->pointdiameter  = 1;
887:   windraw->node           = newnode;
888: 
889:   windraw->x = draw->x;
890:   windraw->y = draw->y;
891:   windraw->w = newnode->bitwidth    = draw->w;
892:   windraw->h = newnode->bitheight   = draw->h;
893: 
894:   /* Create and initialize primary graphics buffer */
895:   newnode->Buffer = CreateCompatibleDC(windraw->hdc);
896:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
897:   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
898:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
899: 
900:   newnode->event          = CreateEvent(NULL,TRUE,FALSE,NULL);
901:   newnode->DoubleBuffered = PETSC_FALSE;
902: 
903:   ReleaseDC(windraw->hWnd,windraw->hdc);
904:   ReleaseMutex(g_hWindowListMutex);
905:   return 0;
906: }


910: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
911:    PURPOSE:  Processes messages for the main window.
912:    WM_COMMAND  - process the application menu
913:    WM_PAINT    - Paint the main window
914:    WM_DESTROY  - post a quit message and return */
915: LRESULT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
916: {
917:   int         wmId, wmEvent;
918: 
919:   switch (message) {
920:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
921:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
922:   case WM_COMMAND:
923:     wmId    = LOWORD(wParam);
924:     wmEvent = HIWORD(wParam);
925:     /* Parse the menu selections:*/
926:     switch (wmId) {
927:     case IDM_EXIT:
928:       DestroyWindow(hWnd);
929:       break;
930:     default:
931:       return DefWindowProc(hWnd, message, wParam, lParam);
932:     }
933:     break;
934:   case WM_LBUTTONUP:
935:     MouseRecord_Win32(hWnd,BUTTON_LEFT);
936:     break;
937:   case WM_RBUTTONUP:
938:     MouseRecord_Win32(hWnd,BUTTON_RIGHT);
939:     break;
940:   case WM_MBUTTONUP:
941:     MouseRecord_Win32(hWnd,BUTTON_CENTER);
942:     break;
943:   default:
944:     return DefWindowProc(hWnd, message, wParam, lParam);
945:   }
946:   return 0;
947: }

949: static void OnPaint_Win32(HWND hWnd)
950: {
951:   PAINTSTRUCT ps;
952:   HDC         hdc;
953:   WindowNode  current = NULL;
954:   InvalidateRect(hWnd,NULL,TRUE);
955:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
956:   current = WindowListHead;
957:   hdc     = BeginPaint(hWnd, &ps);
958: 
959:   while(current != NULL) {
960:     if (current->hWnd == hWnd) {
961:       /* flushes primary buffer to window */
962:       BitBlt(hdc,
963:              0,0,
964:              GetDeviceCaps(hdc,HORZRES),
965:              GetDeviceCaps(hdc,VERTRES),
966:              current->Buffer,
967:              0,0,
968:              SRCCOPY);
969: 
970:       /* StretchBlt(hdc,
971:         0,0,
972:         w,h,
973:         current->Buffer,
974:         0,0,
975:         current->bitwidth,
976:         current->bitheight,
977:         SRCCOPY); */
978:       break;
979:     }
980:     current = current->wnext;
981:   }
982:   EndPaint(hWnd, &ps);
983:   ReleaseMutex(g_hWindowListMutex);
984: }

986: static PetscErrorCode  MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
987: {
988: 
989:   /* Called by all three mouse button actions
990:     Records needed mouse data in windows data structure */
991:   WindowNode current = NULL;
992:   MouseNode  newnode;
993:   POINT      mousepos;
995: 
996:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
997:   current = WindowListHead;
998:   if(current->IsGetMouseOn == TRUE) {
999: 
1000:     SetEvent(current->event);
1001:     while (current != NULL) {
1002:       if(current->hWnd == hWnd) {
1003: 
1004:         PetscNew(struct _p_MouseNode,&newnode);
1005:         newnode->Button = button;
1006:         GetCursorPos(&mousepos);
1007:         newnode->user.x = mousepos.x;
1008:         newnode->user.y = mousepos.y;
1009:         ScreenToClient(hWnd,&mousepos);
1010:         newnode->phys.x = mousepos.x;
1011:         newnode->phys.y = mousepos.y;
1012:         if (!current->MouseListTail) {
1013:           current->MouseListHead = newnode;
1014:           current->MouseListTail = newnode;
1015:         } else {
1016:           current->MouseListTail->mnext = newnode;
1017:           current->MouseListTail = newnode;
1018:         }
1019:         newnode->mnext = NULL;
1020: 
1021:         break;
1022:       }
1023:       current = current->wnext;
1024:     }
1025:   }
1026:   ReleaseMutex(g_hWindowListMutex);
1027:   return 0;
1028: }

1030: static void OnDestroy_Win32(HWND hWnd)
1031: {
1032:   /* searches linked list of window data and frees corresponding memory */
1033:   WindowNode current;
1034: 
1035:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
1036:   current = WindowListHead;
1037: 
1038:   SetEvent(current->event);
1039:   while (current != NULL) {
1040:     if(current->hWnd == hWnd) {
1041:       if(current->wprev != NULL) {
1042:         current->wprev->wnext = current->wnext;
1043:       } else {
1044:         WindowListHead = current->wnext;
1045:       }
1046:       if(current->MouseListHead) {
1047:         deletemouselist_Win32(current);
1048:       } else {
1049:         PetscFree(current);
1050:       }
1051:       break;
1052:     }
1053:     current = current->wnext;
1054:   }
1055:   ReleaseMutex(g_hWindowListMutex);
1056:   PostQuitMessage(0);
1057: }