Actual source code: win32draw.c

  1: /* $Id: win32draw.c,v 1.15 2001/09/07 20:08:10 bsmith Exp $ */
  2: #include "petsc.h"
  3: #include "src/sys/src/draw/drawimpl.h"
  4: #include "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: #define SelectPen(hdc, hpen)  ((HPEN)SelectObject((hdc),  (HGDIOBJ)(HPEN)(hpen)))
 13: #define SelectFont(hdc,hfont) ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
 14: #define GetStockBrush(i)      ((HBRUSH)GetStockObject(i))

 16: #define XTRANS(draw,win,x) 
 17:    (int)(((win)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)*
 18:                                    ((draw)->port_xr - (draw)->port_xl))/
 19:                                    ((draw)->coor_xr - (draw)->coor_xl))))
 20: #define YTRANS(draw,win,y) 
 21:    (int)(((win)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)*
 22:                                    ((draw)->port_yr - (draw)->port_yl))/
 23:                                    ((draw)->coor_yr - (draw)->coor_yl))))

 25: HINSTANCE     hInst;
 26: HANDLE        g_hWindowListMutex = NULL;
 27: WindowNode    WindowListHead     = NULL;

 29: /* Hard coded color hue until hue.c works with this */
 30: 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};
 31: 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};
 32: 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};

 34: /* Foward declarations of functions included in this code module: */
 35: LRESULT CALLBACK  WndProc(HWND, UINT, WPARAM, LPARAM);
 36: extern int  TranslateColor_Win32(PetscDraw,int);
 37: extern int  AverageColorRectangle_Win32(PetscDraw,int,int,int,int);
 38: extern int  AverageColorTriangle_Win32(PetscDraw,int,int,int);
 39: extern void MessageLoopThread(PetscDraw_Win32 *);
 40: extern int  deletemouselist_Win32(WindowNode);
 41: extern void OnPaint_Win32(HWND);
 42: extern void OnDestroy_Win32(HWND);
 43: extern void OnSize_Win32(HWND,UINT,int,int);
 44: extern int  MouseRecord_Win32(HWND,PetscDrawButton);
 45: extern int  PetscDrawGetPopup_Win32(PetscDraw,PetscDraw *);

 47: #undef __FUNCT__  
 49: static int PetscDrawSetDoubleBuffer_Win32(PetscDraw draw)
 50: {
 51:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 52:   HDC             hdc      = GetDC(windraw->hWnd);
 53: 
 55:   windraw->node->DoubleBuffer = CreateCompatibleDC(hdc);
 56:   windraw->node->DoubleBufferBit = CreateCompatibleBitmap(hdc,windraw->w,windraw->h);
 57:   windraw->node->dbstore = SelectObject(windraw->node->DoubleBuffer,windraw->node->DoubleBufferBit);
 58:   /* Fill background of second buffer */
 59:   ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
 60:   /* Copy current buffer into seconf buffer and set window data as double buffered */
 61:   BitBlt(windraw->node->DoubleBuffer,
 62:          0,0,
 63:          windraw->w,windraw->h,
 64:          windraw->node->Buffer,
 65:          0,0,
 66:          SRCCOPY);

 68:   windraw->node->DoubleBuffered = PETSC_TRUE;
 69:   ReleaseDC(windraw->hWnd,hdc);
 70:   return(0);
 71: }
 72: #undef __FUNCT__  
 74: static int PetscDrawFlush_Win32(PetscDraw draw)
 75: {
 76:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
 77:   HDC             hdc = GetDC(windraw->hWnd);
 78: 
 80:   /* flush double buffer into primary buffer */
 81:   BitBlt(windraw->node->Buffer,
 82:          0,0,
 83:          windraw->w,windraw->h,
 84:          windraw->node->DoubleBuffer,
 85:          0,0,
 86:          SRCCOPY);
 87:   /* flush double buffer into window */
 88:   BitBlt(hdc,
 89:          0,0,
 90:          windraw->w,windraw->h,
 91:          windraw->node->DoubleBuffer,
 92:          0,0,
 93:          SRCCOPY);
 94:   ReleaseDC(windraw->hWnd,hdc);
 95:   return(0);
 96: }

 98: #undef __FUNCT__  
100: static int deletemouselist_Win32(WindowNode deletelist)
101: {
102:   /* Called upon window close. Frees memory of linked list of stored mouse commands */
103:   MouseNode node;
104: 
105:   while(deletelist->MouseListHead != NULL) {
106:     node = deletelist->MouseListHead;
107:     if(deletelist->MouseListHead->mnext != NULL) {
108:       deletelist->MouseListHead = deletelist->MouseListHead->mnext;
109:     }
110:     PetscFree(node);
111:   }
112:   deletelist->MouseListHead = deletelist->MouseListTail = NULL;
113:   if (deletelist->wprev != NULL) {
114:     deletelist->wprev->wnext = deletelist->wnext;
115:   }
116:   if (deletelist->wnext != NULL) {
117:     deletelist->wnext->wprev = deletelist->wprev;
118:   }
119:   PetscFree(deletelist);
120:   return 0;
121: }

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

166:   /* Release mutex so that  other code can use
167:      the linked list now that we are done with it */
168:   ReleaseMutex(g_hWindowListMutex);
169:   return(0);
170: }

172: #undef __FUNCT__  
174: static int PetscDrawPause_Win32(PetscDraw draw)
175: {
177:   PetscSleep(draw->pause);
178:   return(0);
179: }

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

276: #undef __FUNCT__  
278: static int PetscDrawLineSetWidth_Win32(PetscDraw draw,double width)
279: {
280:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
281:   int             averagesize,finalwidth;
282:   RECT            rect;
283: 
285:   GetClientRect(windraw->hWnd,&rect);
286:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
287:   finalwidth  = (int)floor(averagesize*width);
288:   if (finalwidth < 1) {
289:     finalwidth = 1; /* minimum size PetscDrawLine can except */
290:   }
291:   windraw->linewidth = finalwidth;
292:   return(0);
293: }

295: #undef __FUNCT__  
297: static int PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
298: {
299:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
300: 
302:   *width = (PetscReal)windraw->linewidth;
303:   return(0);
304: }
305: #undef __FUNCT__  
307: static int PetscDrawPoint_Win32(PetscDraw draw,double x,double y,int color)
308: {
309:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
310:   HBRUSH          hbrush;
311:   HRGN            hrgn;
312:   int             radius;
313:   int             x1,y1,left,right,top,bottom;
314:   HDC             hdc;
315: 
317:   TranslateColor_Win32(draw,color);
318:   x1     = XTRANS(draw,windraw,x);
319:   y1     = YTRANS(draw,windraw,y);
320:   hbrush = CreateSolidBrush(windraw->currentcolor);
321:   if(windraw->node->DoubleBuffered) {
322:     hdc = windraw->node->DoubleBuffer;
323:   } else {
324:     hdc = windraw->node->Buffer;
325:   }
326:   /* desired size is one logical pixel so just turn it on */
327:   if (windraw->pointdiameter == 1) {
328:     SetPixelV(hdc,x1,y1,windraw->currentcolor);
329:   } else {
330:     /* draw point around position determined */
331:     radius = (int)floor(windraw->pointdiameter/2);
332:     hrgn   = CreateEllipticRgn(x1-radius,y1-radius,x1+radius,y1+radius);
333:     FillRgn(hdc,hrgn,hbrush);
334:   }
335:   /* Forces a WM_PAINT and erases background */
336:   InvalidateRect(windraw->hWnd,NULL,TRUE);
337:   UpdateWindow(windraw->hWnd);
338:   return(0);
339: }

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

479: #undef __FUNCT__  
481: static int PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
482: {
483:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
484:   RECT            r;
485: 
487:   GetWindowRect(windraw->hWnd,&r);
488:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
489:   /* set all variable dealing with window dimensions */
490:   windraw->node->bitheight = windraw->h = draw->h = h;
491:   windraw->node->bitwidth  = windraw->w = draw->w = w;
492:   /* set up graphic buffers with the new size of window */
493:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
494:   if(windraw->node->DoubleBuffered) {
495:     SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
496:   }
497:   windraw->haveresized = PETSC_TRUE;
498:   return(0);
499: }

501: #undef __FUNCT__  
503: static int PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
504: {
505:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
506: 
508:   if (windraw->haveresized == 1) {
509:     PetscFunctionReturn(1);
510:   } else {
511:     return(0);
512:   }
513: 
514: }

516: #undef __FUNCT__  
518: static int PetscDrawSetTitle_Win32(PetscDraw draw, char *title)
519: {
520:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
521: 
523:   draw->title = title;
524:   SetWindowText(windraw->hWnd,title);
525:   return(0);
526: }

528: #undef __FUNCT__  
530: static int PetscDrawClear_Win32(PetscDraw draw)
531: {
532:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
533: 
535:   /* clear primary buffer */
536:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
537:   /* if exists clear secondary buffer */
538:   if(windraw->node->DoubleBuffered) {
539:     ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
540:   }
541:   /* force WM_PAINT message so cleared buffer will show */
542:   InvalidateRect(windraw->hWnd,NULL,TRUE);
543:   UpdateWindow(windraw->hWnd);
544:   return(0);
545: }

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

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


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


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


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


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

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

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

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