Actual source code: win32draw.c

      1: #define PETSC_DLL
      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: #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 PETSC_DLLEXPORT 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);
     60:
     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,
     69:          0,0,
     70:          windraw->w,windraw->h,
     71:          windraw->node->Buffer,
     72:          0,0,
     73:          SRCCOPY);

     75:   windraw->node->DoubleBuffered = PETSC_TRUE;
     76:   ReleaseDC(windraw->hWnd,hdc);
     77:   return(0);
     78: }

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

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

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

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

    182: static PetscErrorCode PetscDrawPause_Win32(PetscDraw draw)
    183: {
    185:   PetscSleep(draw->pause);
    186:   return(0);
    187: }

    191: static PetscErrorCode TranslateColor_Win32(PetscDraw draw,int color)
    192: {
    193:   /* Maps single color value into the RGB colors in our tables */
    194:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
    195:   windraw->currentcolor = RGB(RedMap[color],GreenMap[color],BlueMap[color]);
    196:   return 0;
    197: }

    201: static PetscErrorCode AverageColorRectangle_Win32(PetscDraw draw,int c1,int c2, int c3, int c4)
    202: {
    203:   /* Averages colors given at points of rectangle and sets color from color table
    204:     will be changed once the color gradient problem is worked out */
    205:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
    206:   windraw->currentcolor = RGB(((RedMap[c1]+RedMap[c2]+RedMap[c3]+RedMap[c4])/4),
    207:                               ((GreenMap[c1]+GreenMap[c2]+GreenMap[c3]+GreenMap[c4])/4),
    208:                               ((BlueMap[c1]+BlueMap[c2]+BlueMap[c3]+BlueMap[c4])/4));
    209:   return 0;
    210: }

    214: static PetscErrorCode AverageColorTriangle_Win32(PetscDraw draw,int c1,int c2,int c3)
    215: {
    216:   /* Averages colors given at points of rectangle and sets color from color table
    217:     will be changed once the color gradient problem is worked out */
    218:   PetscDraw_Win32 *windraw   = (PetscDraw_Win32*)draw->data;
    219:   windraw->currentcolor = RGB((RedMap[c1]+RedMap[c2]+RedMap[c3])/3,
    220:                               (GreenMap[c1]+GreenMap[c2]+GreenMap[c3])/3,
    221:                               (BlueMap[c1]+BlueMap[c2]+BlueMap[c3])/3);
    222:   return 0;
    223: }

    227: static PetscErrorCode PetscDrawRectangle_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
    228: {
    229:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    230:   HBRUSH          hbrush;
    231:   RECT            rect;
    232:   int             x1,yone,x2,y2;
    233:   HDC             hdc;
    234:
    236:   x1 = XTRANS(draw,windraw,xl);
    237:   x2 = XTRANS(draw,windraw,xr);
    238:   yone = YTRANS(draw,windraw,yl);
    239:   y2 = YTRANS(draw,windraw,yr);
    240:   SetRect(&rect,x1,y2,x2,yone);
    241:   if (c1==c2 && c2==c3 && c3==c4) {
    242:     TranslateColor_Win32(draw,c1);
    243:   } else {
    244:     AverageColorRectangle_Win32(draw,c1,c2,c3,c4);
    245:   }
    246:   hbrush = CreateSolidBrush(windraw->currentcolor);
    247:
    248:   if(windraw->node->DoubleBuffered) {
    249:     hdc = windraw->node->DoubleBuffer;
    250:   } else {
    251:     hdc = windraw->node->Buffer;
    252:   }
    253:   FillRect(hdc,&rect,hbrush);
    254:   /* Forces a WM_PAINT message and erases background */
    255:   InvalidateRect(windraw->hWnd,NULL,TRUE);
    256:   UpdateWindow(windraw->hWnd);
    257:   return(0);
    258: }

    262: static PetscErrorCode PetscDrawLine_Win32(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int color)
    263: {
    264:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    265:   HPEN            hpen;
    266:   int             x1,yone,x2,y2;
    267:   HDC             hdc;
    268:
    270:   TranslateColor_Win32(draw,color);
    271:   x1   = XTRANS(draw,windraw,xl);x2  = XTRANS(draw,windraw,xr);
    272:   yone   = YTRANS(draw,windraw,yl);y2  = YTRANS(draw,windraw,yr);
    273:   hpen = CreatePen (PS_SOLID, windraw->linewidth, windraw->currentcolor);
    274:   if(windraw->node->DoubleBuffered) {
    275:     hdc = windraw->node->DoubleBuffer;
    276:   } else {
    277:     hdc = windraw->node->Buffer;
    278:   }
    279:   SelectPen(hdc,hpen);
    280:   MoveToEx(hdc,x1,yone,NULL);
    281:   LineTo(hdc,x2,y2);
    282:   /* Forces a WM_PAINT message and erases background */
    283:   InvalidateRect(windraw->hWnd,NULL,TRUE);
    284:   UpdateWindow(windraw->hWnd);
    285:   return(0);
    286: }

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

    309: static PetscErrorCode PetscDrawLineGetWidth_Win32(PetscDraw draw,PetscReal *width)
    310: {
    311:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    312:
    314:   *width = (PetscReal)windraw->linewidth;
    315:   return(0);
    316: }

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

    356: static PetscErrorCode PetscDrawPointSetSize_Win32(PetscDraw draw,PetscReal width)
    357: {
    358:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    359:   int             averagesize,diameter;
    360:   RECT            rect;
    361:
    363:   GetClientRect(windraw->hWnd,&rect);
    364:   averagesize = ((rect.right - rect.left)+(rect.bottom - rect.top))/2;
    365:   diameter    = (int)floor(averagesize*width);
    366:   if (diameter < 1) diameter = 1;
    367:   windraw->pointdiameter     = diameter;
    368:   return(0);
    369: }

    373: static PetscErrorCode PetscDrawString_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
    374: {
    375:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    376:   RECT            r;
    377:   HFONT           hfont;
    378:   LOGFONT         logfont;
    379:   int             x1,yone;
    380:   HDC             hdc;
    381:
    383:   x1              = XTRANS(draw,windraw,x);
    384:   yone              = YTRANS(draw,windraw,y);
    385:   r.bottom        = yone;
    386:   r.left          = x1;
    387:   r.right         = x1 + 1;
    388:   r.top           = yone + 1;
    389:   logfont.lfHeight         = windraw->stringheight;
    390:   logfont.lfWidth          = windraw->stringwidth;
    391:   logfont.lfEscapement     = 0;
    392:   logfont.lfOrientation    = 0;
    393:   logfont.lfCharSet        = 0;
    394:   logfont.lfClipPrecision  = 0;
    395:   logfont.lfItalic         = 0;
    396:   logfont.lfOutPrecision   = 0;
    397:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
    398:   logfont.lfQuality        = DEFAULT_QUALITY;
    399:   logfont.lfStrikeOut      = 0;
    400:   logfont.lfUnderline      = 0;
    401:   logfont.lfWeight         = FW_NORMAL;
    402:   hfont = CreateFontIndirect(&logfont);
    403:   TranslateColor_Win32(draw,color);
    404:   if(windraw->node->DoubleBuffered) {
    405:     hdc = windraw->node->DoubleBuffer;
    406:   } else {
    407:     hdc = windraw->node->Buffer;
    408:   }
    409:   SelectFont(hdc,hfont);
    410:   SetTextColor(hdc,windraw->currentcolor);
    411:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP);
    412:   DeleteObject(hfont);
    413:   /* Forces a WM_PAINT message and erases background */
    414:   InvalidateRect(windraw->hWnd,NULL,TRUE);
    415:   UpdateWindow(windraw->hWnd);
    416:   return(0);
    417: }

    421: static PetscErrorCode PetscDrawStringVertical_Win32(PetscDraw draw,PetscReal x,PetscReal y,int color,const char *text)
    422: {
    423:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    424:   RECT            r;
    425:   HFONT           hfont;
    426:   LOGFONT         logfont;
    427:   int             x1,yone;
    428:   HDC             hdc;
    429:
    431:   x1           = XTRANS(draw,windraw,x);
    432:   yone           = YTRANS(draw,windraw,y);
    433:   r.left       = x1;
    434:   r.bottom     = yone + 30;
    435:   r.right      = x1 + 1;
    436:   r.top        = yone - 30;
    437:   logfont.lfEscapement     = 2700; /* Causes verticle text drawing */
    438:   logfont.lfHeight         = windraw->stringheight;
    439:   logfont.lfWidth          = windraw->stringwidth;
    440:   logfont.lfOrientation    = 0;
    441:   logfont.lfCharSet        = DEFAULT_CHARSET;
    442:   logfont.lfClipPrecision  = 0;
    443:   logfont.lfItalic         = 0;
    444:   logfont.lfOutPrecision   = 0;
    445:   logfont.lfPitchAndFamily = DEFAULT_PITCH;
    446:   logfont.lfQuality        = DEFAULT_QUALITY;
    447:   logfont.lfStrikeOut      = 0;
    448:   logfont.lfUnderline      = 0;
    449:   logfont.lfWeight         = FW_NORMAL;
    450:   hfont = CreateFontIndirect(&logfont);
    451:   TranslateColor_Win32(draw,color);
    452:   if(windraw->node->DoubleBuffered) {
    453:     hdc = windraw->node->DoubleBuffer;
    454:   } else {
    455:     hdc = windraw->node->Buffer;
    456:   }
    457:   SelectFont(hdc,hfont);
    458:   SetTextColor(hdc,windraw->currentcolor);
    459:   DrawText(hdc,text,lstrlen(text),&r,DT_NOCLIP | DT_SINGLELINE );
    460:   DeleteObject(hfont);
    461:   /* Forces a WM_PAINT message and erases background */
    462:   InvalidateRect(windraw->hWnd,NULL,TRUE);
    463:   UpdateWindow(windraw->hWnd);
    464:   return(0);
    465: }

    469: static PetscErrorCode PetscDrawStringSetSize_Win32(PetscDraw draw,PetscReal width,PetscReal height)
    470: {
    471:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    472:   int             w,h;
    473:
    475:   w = (int)((windraw->w)*width *(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
    476:   h = (int)((windraw->h)*height*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
    477:   if (h < 1) h = 1;
    478:   if (w < 1) w = 1;
    479:   windraw->stringheight = h;
    480:   windraw->stringwidth  = w;
    481:   return(0);
    482: }
    485: static PetscErrorCode PetscDrawStringGetSize_Win32(PetscDraw draw,PetscReal *width,PetscReal *height)
    486: {
    487:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    488:   double scaleX = (draw->coor_xr - draw->coor_xl)/(draw->w)*(draw->port_xr - draw->port_xl);
    489:   double scaleY = (draw->coor_yr - draw->coor_yl)/(draw->h)*(draw->port_yr - draw->port_yl);
    490:
    492:   *height = (double)windraw->stringheight*scaleY;
    493:   *width  = (double)windraw->stringwidth*scaleX;
    494:   return(0);
    495: }

    499: static PetscErrorCode PetscDrawResizeWindow_Win32(PetscDraw draw,int w,int h)
    500: {
    501:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    502:   RECT            r;
    503:
    505:   GetWindowRect(windraw->hWnd,&r);
    506:   MoveWindow(windraw->hWnd,r.left,r.top,(int)w,(int)h,TRUE);
    507:   /* set all variable dealing with window dimensions */
    508:   windraw->node->bitheight = windraw->h = draw->h = h;
    509:   windraw->node->bitwidth  = windraw->w = draw->w = w;
    510:   /* set up graphic buffers with the new size of window */
    511:   SetBitmapDimensionEx(windraw->node->BufferBit,w,h,NULL);
    512:   if(windraw->node->DoubleBuffered) {
    513:     SetBitmapDimensionEx(windraw->node->DoubleBufferBit,w,h,NULL);
    514:   }
    515:   windraw->haveresized = PETSC_TRUE;
    516:   return(0);
    517: }

    521: static PetscErrorCode PetscDrawCheckResizedWindow_Win32(PetscDraw draw)
    522: {
    523:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    524:
    526:   if (windraw->haveresized == 1) {
    527:     PetscFunctionReturn(1);
    528:   } else {
    529:     return(0);
    530:   }
    531:
    532: }

    536: static PetscErrorCode PetscDrawSetTitle_Win32(PetscDraw draw, const char title[])
    537: {
    538:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    539:
    541:   SetWindowText(windraw->hWnd,title);
    542:   return(0);
    543: }

    547: static PetscErrorCode PetscDrawClear_Win32(PetscDraw draw)
    548: {
    549:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    550:
    552:   /* clear primary buffer */
    553:   ExtFloodFill(windraw->node->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
    554:   /* if exists clear secondary buffer */
    555:   if(windraw->node->DoubleBuffered) {
    556:     ExtFloodFill(windraw->node->DoubleBuffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
    557:   }
    558:   /* force WM_PAINT message so cleared buffer will show */
    559:   InvalidateRect(windraw->hWnd,NULL,TRUE);
    560:   UpdateWindow(windraw->hWnd);
    561:   return(0);
    562: }

    566: static PetscErrorCode PetscDrawTriangle_Win32(PetscDraw draw,PetscReal x1,PetscReal yone,PetscReal x2,PetscReal y2,
    567:                               PetscReal x3,PetscReal y3,int c1,int c2,int c3)
    568: {
    569:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    570:   HBRUSH          hbrush;
    571:   HPEN            hpen;
    572:   int             p1x,p1y,p2x,p2y,p3x,p3y;
    573:   HDC             bit;
    574:
    576:   AverageColorTriangle_Win32(draw,c1,c2,c3);
    577:   hbrush = CreateSolidBrush(windraw->currentcolor);
    578:   hpen   = CreatePen(PS_SOLID,0,windraw->currentcolor);
    579:   p1x = XTRANS(draw,windraw,x1);
    580:   p2x = XTRANS(draw,windraw,x2);
    581:   p3x = XTRANS(draw,windraw,x3);
    582:   p1y = YTRANS(draw,windraw,yone);
    583:   p2y = YTRANS(draw,windraw,y2);
    584:   p3y = YTRANS(draw,windraw,y3);
    585:
    586:   if(windraw->node->DoubleBuffered) {
    587:     bit = windraw->node->DoubleBuffer;
    588:   } else {
    589:     bit = windraw->node->Buffer;
    590:   }
    591:   BeginPath(bit);
    592:   MoveToEx(bit,p1x,p1y,NULL);
    593:   LineTo(bit,p2x,p2y);
    594:   LineTo(bit,p3x,p3y);
    595:   LineTo(bit,p1x,p1y);
    596:   EndPath(bit);
    597:   SelectPen(bit,hpen);
    598:   SelectBrush(bit,hbrush);
    599:   StrokeAndFillPath(bit);
    600:   /* Forces a WM_PAINT message and erases background */
    601:   InvalidateRect(windraw->hWnd,NULL,TRUE);
    602:   UpdateWindow(windraw->hWnd);
    603:   return(0);
    604: }

    608: void PopMessageLoopThread_Win32(PetscDraw popdraw)
    609: {
    610:   PetscDraw_Win32 *pop = (PetscDraw_Win32*)popdraw->data;
    611:   MSG             msg;
    612:   HWND            hWnd = NULL;
    613:   char            PopClassName [MAX_LOADSTRING + 1];
    614:   RECT            r;
    615:   int             width,height;
    616:   WNDCLASSEX      myclass;
    617:   LPVOID          lpMsgBuf;
    618:
    620:   /* initialize window class parameters */
    621:   myclass.cbSize        = sizeof(WNDCLASSEX);
    622:   myclass.style         = CS_OWNDC;
    623:   myclass.lpfnWndProc   = (WNDPROC)PetscWndProc;
    624:   myclass.cbClsExtra    = 0;
    625:   myclass.cbWndExtra    = 0;
    626:   myclass.hInstance     = NULL;
    627:   myclass.hIcon         = NULL;
    628:   myclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    629:   myclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    630:   myclass.lpszMenuName  = NULL;
    631:   myclass.lpszClassName = PopClassName;
    632:   myclass.hIconSm       = NULL;
    633:
    634:   RegisterClassEx(&myclass);
    635:
    636:   SetRect(&r,0,0,450,450);
    637:
    638:   width    = (r.right - r.left) / 3;
    639:   height   = (r.bottom - r.top) / 3;
    640:
    641:   hWnd = CreateWindowEx(0,
    642:                         PopClassName,
    643:                         NULL,
    644:                         WS_POPUPWINDOW | WS_CAPTION,
    645:                         0,0,
    646:                         width,height,
    647:                         NULL,
    648:                         NULL,
    649:                         hInst,
    650:                         NULL);
    651:   pop->x = 0;
    652:   pop->y = 0;
    653:   pop->w = width;
    654:   pop->h = height;
    655:
    656:   if(!hWnd) {
    657:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
    658:     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
    659:     LocalFree( lpMsgBuf );
    660:     exit(0);
    661:   }
    662:   pop->hWnd = hWnd;
    663:   /* display and update new popup window */
    664:   ShowWindow(pop->hWnd, SW_SHOWNORMAL);
    665:   UpdateWindow(pop->hWnd);
    666:   SetEvent(pop->hReadyEvent);
    667:
    668:   while (GetMessage(&msg, pop->hWnd, 0, 0)) {
    669:     TranslateMessage(&msg);
    670:     DispatchMessage(&msg);
    671:   }
    672:   PetscFunctionReturnVoid();
    673: }

    677: static PetscErrorCode PetscDrawDestroy_Win32(PetscDraw draw)
    678: {
    679:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    680:
    682:   SendMessage(windraw->hWnd,WM_DESTROY,0,0);
    683:   PetscFree(windraw);
    684:   return(0);
    685: }

    689: static PetscErrorCode PetscDrawSynchronizedFlush_Win32(PetscDraw draw)
    690: {
    691:   /* Multi Processor is not implemeted yet */
    693:   PetscDrawFlush_Win32(draw);
    694:   return(0);
    695: }

    699: static PetscErrorCode PetscDrawSynchronizedClear_Win32(PetscDraw draw)
    700: {
    701:   /* Multi Processor is not implemeted yet */
    703:   PetscDrawClear_Win32(draw);
    704:   return(0);
    705: }

    709: void MessageLoopThread_Win32(PetscDraw draw)
    710: {
    711:   PetscDraw_Win32 *windraw = (PetscDraw_Win32*)draw->data;
    712:   MSG             msg;
    713:   HWND            hWnd = NULL;
    714:   char            classname[MAX_LOADSTRING + 1];
    715:   WNDCLASSEX      wclass;
    716:   LPVOID          lpMsgBuf;
    717:
    719:   /* initialize window class parameters */
    720:   wclass.cbSize         = sizeof(WNDCLASSEX);
    721:   wclass.style          = CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
    722:   wclass.lpfnWndProc    = (WNDPROC)PetscWndProc;
    723:   wclass.cbClsExtra     = 0;
    724:   wclass.cbWndExtra     = 0;
    725:   wclass.hInstance      = NULL;
    726:   wclass.hIcon          = LoadIcon(NULL,IDI_APPLICATION);
    727:   wclass.hCursor        = LoadCursor(NULL,IDC_ARROW);
    728:   wclass.hbrBackground  = GetStockBrush(WHITE_BRUSH);
    729:   wclass.lpszMenuName   = NULL;
    730:   wclass.lpszClassName  = classname;
    731:   wclass.hIconSm        = NULL;
    732:
    733:   RegisterClassEx(&wclass);
    734:
    735:
    736:   hWnd = CreateWindowEx(0,
    737:                         classname,
    738:                         NULL,
    739:                         WS_OVERLAPPEDWINDOW,
    740:                         draw->x,
    741:                         draw->y,
    742:                         draw->w,
    743:                         draw->h,
    744:                         NULL,
    745:                         NULL,
    746:                         hInst,
    747:                         NULL);
    748:
    749:   if (!hWnd) {
    750:     lpMsgBuf = (LPVOID)"Window Not Succesfully Created";
    751:     MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
    752:     LocalFree( lpMsgBuf );
    753:     exit(0);
    754:   }
    755:   windraw->hWnd = hWnd;
    756:   /* display and update new window */
    757:   ShowWindow(hWnd,SW_SHOWNORMAL);
    758:   UpdateWindow(hWnd);
    759:   SetEvent(windraw->hReadyEvent);
    760:
    761:   while (GetMessage(&msg,hWnd, 0, 0)) {
    762:     TranslateMessage(&msg);
    763:     DispatchMessage(&msg);
    764:   }
    765:   PetscFunctionReturnVoid();
    766: }

    769: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_Win32,
    770:                                  PetscDrawFlush_Win32,
    771:                                  PetscDrawLine_Win32,
    772:                                  PetscDrawLineSetWidth_Win32,
    773:                                  PetscDrawLineGetWidth_Win32,
    774:                                  PetscDrawPoint_Win32,
    775:                                  PetscDrawPointSetSize_Win32,
    776:                                  PetscDrawString_Win32,
    777:                                  PetscDrawStringVertical_Win32,
    778:                                  PetscDrawStringSetSize_Win32,
    779:                                  PetscDrawStringGetSize_Win32,
    780:                                  0,
    781:                                  PetscDrawClear_Win32,
    782:                                  PetscDrawSynchronizedFlush_Win32,
    783:                                  PetscDrawRectangle_Win32,
    784:                                  PetscDrawTriangle_Win32,
    785:                                  0,
    786:                                  PetscDrawGetMouseButton_Win32,
    787:                                  PetscDrawPause_Win32,
    788:                                  PetscDrawSynchronizedClear_Win32,
    789:                                  0,
    790:                                  0,
    791:                                  PetscDrawGetPopup_Win32,
    792:                                  PetscDrawSetTitle_Win32,
    793:                                  PetscDrawCheckResizedWindow_Win32,
    794:                                  PetscDrawResizeWindow_Win32,
    795:                                  PetscDrawDestroy_Win32,
    796:                                  0,
    797:                                  0,
    798:                                  0,
    799:                                  0};

    803: static PetscErrorCode PetscDrawGetPopup_Win32(PetscDraw draw,PetscDraw *popdraw)
    804: {
    805:   PetscDraw_Win32 *pop;
    806:   HANDLE          hThread = NULL;
    807:   WindowNode      newnode;
    809:
    811:   PetscNew(PetscDraw_Win32,&pop);
    812:   (*popdraw)->data = pop;
    813:
    814:   /* the following is temporary fix for initializing a global datastructure */
    815:   if(!g_hWindowListMutex) {
    816:     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
    817:   }
    818:   PetscMemcpy((*popdraw)->ops,&DvOps,sizeof(DvOps));
    819:
    820:   pop->hReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    821:   CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)PopMessageLoopThread_Win32,*popdraw,0,(unsigned long*)hThread);
    822:   CloseHandle(hThread);
    823:   WaitForSingleObject(pop->hReadyEvent, INFINITE);
    824:   CloseHandle(pop->hReadyEvent);
    825:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    826:
    827:   draw->popup             = (*popdraw);
    828:   PetscNew(struct _p_WindowNode,&newnode);
    829:   newnode->MouseListHead  = NULL;
    830:   newnode->MouseListTail  = NULL;
    831:   newnode->wnext          = WindowListHead;
    832:   newnode->wprev          = NULL;
    833:   newnode->hWnd           = pop->hWnd;
    834:   if(WindowListHead != NULL) {
    835:     WindowListHead->wprev = newnode;
    836:   }
    837:   WindowListHead          = newnode;
    838:   pop->hdc                = GetDC(pop->hWnd);
    839:
    840:   pop->stringheight   = 10;
    841:   pop->stringwidth    = 6;
    842:   pop->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
    843:   pop->pointdiameter  = 1;
    844:   pop->node           = newnode;
    845:
    846:   newnode->bitwidth  = pop->w;
    847:   newnode->bitheight = pop->h;
    848:
    849:   /* Create and initialize primary graphics buffer */
    850:   newnode->Buffer = CreateCompatibleDC(pop->hdc);
    851:   newnode->BufferBit = CreateCompatibleBitmap(pop->hdc,pop->w,pop->h);
    852:   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
    853:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
    854:
    855:
    856:   newnode->event          = CreateEvent(NULL, TRUE, FALSE, NULL);
    857:   newnode->DoubleBuffered = PETSC_FALSE;
    858:
    859:   ReleaseDC(pop->hWnd,pop->hdc);
    860:   ReleaseMutex(g_hWindowListMutex);
    861:   return(0);
    862: }

    867: PetscErrorCode PETSC_DLLEXPORT PetscDrawCreate_Win32(PetscDraw draw)
    868: {
    869:   PetscDraw_Win32 *windraw;
    870:   HANDLE          hThread = NULL;
    872:   WindowNode      newnode;
    873:
    875:   PetscNew(PetscDraw_Win32,&windraw);
    876:   draw->data  = windraw;
    877:
    878:   /* the following is temporary fix for initializing a global datastructure */
    879:   if(!g_hWindowListMutex) {
    880:     g_hWindowListMutex = CreateMutex(NULL,FALSE,NULL);
    881:   }
    882:   PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
    883:
    884:   windraw->hReadyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
    885:   /* makes call to MessageLoopThread to creat window and attach a thread */
    886:   CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MessageLoopThread_Win32,draw,0,(unsigned long*)hThread);
    887:   CloseHandle(hThread);
    888:   WaitForSingleObject(windraw->hReadyEvent,INFINITE);
    889:   CloseHandle(windraw->hReadyEvent);
    890:   WaitForSingleObject(g_hWindowListMutex,INFINITE);
    891:
    892:   PetscNew(struct _p_WindowNode,&newnode);
    893:   newnode->MouseListHead  = NULL;
    894:   newnode->MouseListTail  = NULL;
    895:   newnode->wnext          = WindowListHead;
    896:   newnode->wprev          = NULL;
    897:   newnode->hWnd           = windraw->hWnd;
    898:   if(WindowListHead != NULL) {
    899:     WindowListHead->wprev = newnode;
    900:   }
    901:   WindowListHead          = newnode;
    902:   windraw->hdc            = GetDC(windraw->hWnd);
    903:
    904:   windraw->stringheight   = 10;
    905:   windraw->stringwidth    = 6;
    906:   windraw->linewidth      = 1;   /* default pixel sizes of graphics until user changes them */
    907:   windraw->pointdiameter  = 1;
    908:   windraw->node           = newnode;
    909:
    910:   windraw->x = draw->x;
    911:   windraw->y = draw->y;
    912:   windraw->w = newnode->bitwidth    = draw->w;
    913:   windraw->h = newnode->bitheight   = draw->h;
    914:
    915:   /* Create and initialize primary graphics buffer */
    916:   newnode->Buffer = CreateCompatibleDC(windraw->hdc);
    917:   newnode->BufferBit = CreateCompatibleBitmap(windraw->hdc,windraw->w,windraw->h);
    918:   newnode->store = SelectObject(newnode->Buffer,newnode->BufferBit);
    919:   ExtFloodFill(newnode->Buffer,0,0,COLOR_WINDOW,FLOODFILLBORDER);
    920:
    921:   newnode->event          = CreateEvent(NULL,TRUE,FALSE,NULL);
    922:   newnode->DoubleBuffered = PETSC_FALSE;
    923:
    924:   ReleaseDC(windraw->hWnd,windraw->hdc);
    925:   ReleaseMutex(g_hWindowListMutex);
    926:   return(0);
    927: }

    931: /* FUNCTION: PetscWndProc(HWND, unsigned, WORD, LONG)
    932:    PURPOSE:  Processes messages for the main window.
    933:    WM_COMMAND  - process the application menu
    934:    WM_PAINT    - Paint the main window
    935:    WM_DESTROY  - post a quit message and return */

    939: LRESULT PETSC_DLLEXPORT CALLBACK PetscWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    940: {
    941:   int         wmId, wmEvent;
    942:
    944:   switch (message) {
    945:     HANDLE_MSG(hWnd,WM_PAINT,OnPaint_Win32);
    946:     HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy_Win32);
    947:   case WM_COMMAND:
    948:     wmId    = LOWORD(wParam);
    949:     wmEvent = HIWORD(wParam);
    950:     /* Parse the menu selections:*/
    951:     switch (wmId) {
    952:     case IDM_EXIT:
    953:       DestroyWindow(hWnd);
    954:       break;
    955:     default:
    956:       return DefWindowProc(hWnd, message, wParam, lParam);
    957:     }
    958:     break;
    959:   case WM_LBUTTONUP:
    960:     MouseRecord_Win32(hWnd,BUTTON_LEFT);
    961:     break;
    962:   case WM_RBUTTONUP:
    963:     MouseRecord_Win32(hWnd,BUTTON_RIGHT);
    964:     break;
    965:   case WM_MBUTTONUP:
    966:     MouseRecord_Win32(hWnd,BUTTON_CENTER);
    967:     break;
    968:   default:
    969:     PetscFunctionReturn(DefWindowProc(hWnd, message, wParam, lParam));
    970:   }
    971:   return(0);
    972: }

    976: static void OnPaint_Win32(HWND hWnd)
    977: {
    978:   PAINTSTRUCT ps;
    979:   HDC         hdc;
    980:   WindowNode  current = NULL;

    983:   InvalidateRect(hWnd,NULL,TRUE);
    984:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    985:   current = WindowListHead;
    986:   hdc     = BeginPaint(hWnd, &ps);
    987:
    988:   while(current != NULL) {
    989:     if (current->hWnd == hWnd) {
    990:       /* flushes primary buffer to window */
    991:       BitBlt(hdc,
    992:              0,0,
    993:              GetDeviceCaps(hdc,HORZRES),
    994:              GetDeviceCaps(hdc,VERTRES),
    995:              current->Buffer,
    996:              0,0,
    997:              SRCCOPY);
    998:
    999:       /* StretchBlt(hdc,
    1000:         0,0,
    1001:         w,h,
    1002:         current->Buffer,
    1003:         0,0,
    1004:         current->bitwidth,
    1005:         current->bitheight,
    1006:         SRCCOPY); */
    1007:       break;
    1008:     }
    1009:     current = current->wnext;
    1010:   }
    1011:   EndPaint(hWnd, &ps);
    1012:   ReleaseMutex(g_hWindowListMutex);
    1013:   PetscFunctionReturnVoid();
    1014: }

    1018: static PetscErrorCode MouseRecord_Win32(HWND hWnd,PetscDrawButton button)
    1019: {
    1020:   /* Called by all three mouse button actions
    1021:     Records needed mouse data in windows data structure */
    1022:   WindowNode current = NULL;
    1023:   MouseNode  newnode;
    1024:   POINT      mousepos;
    1026:
    1028:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    1029:   current = WindowListHead;
    1030:   if(current->IsGetMouseOn == TRUE) {
    1031:
    1032:     SetEvent(current->event);
    1033:     while (current != NULL) {
    1034:       if(current->hWnd == hWnd) {
    1035:
    1036:         PetscNew(struct _p_MouseNode,&newnode);
    1037:         newnode->Button = button;
    1038:         GetCursorPos(&mousepos);
    1039:         newnode->user.x = mousepos.x;
    1040:         newnode->user.y = mousepos.y;
    1041:         ScreenToClient(hWnd,&mousepos);
    1042:         newnode->phys.x = mousepos.x;
    1043:         newnode->phys.y = mousepos.y;
    1044:         if (!current->MouseListTail) {
    1045:           current->MouseListHead = newnode;
    1046:           current->MouseListTail = newnode;
    1047:         } else {
    1048:           current->MouseListTail->mnext = newnode;
    1049:           current->MouseListTail = newnode;
    1050:         }
    1051:         newnode->mnext = NULL;
    1052:
    1053:         break;
    1054:       }
    1055:       current = current->wnext;
    1056:     }
    1057:   }
    1058:   ReleaseMutex(g_hWindowListMutex);
    1059:   return(0);
    1060: }

    1064: static void OnDestroy_Win32(HWND hWnd)
    1065: {
    1066:   /* searches linked list of window data and frees corresponding memory */
    1067:   WindowNode current;
    1068:
    1070:   WaitForSingleObject(g_hWindowListMutex, INFINITE);
    1071:   current = WindowListHead;
    1072:
    1073:   SetEvent(current->event);
    1074:   while (current != NULL) {
    1075:     if(current->hWnd == hWnd) {
    1076:       if(current->wprev != NULL) {
    1077:         current->wprev->wnext = current->wnext;
    1078:       } else {
    1079:         WindowListHead = current->wnext;
    1080:       }
    1081:       if(current->MouseListHead) {
    1082:         deletemouselist_Win32(current);
    1083:       } else {
    1084:         PetscFree(current);
    1085:       }
    1086:       break;
    1087:     }
    1088:     current = current->wnext;
    1089:   }
    1090:   ReleaseMutex(g_hWindowListMutex);
    1091:   PostQuitMessage(0);
    1092:   PetscFunctionReturnVoid();
    1093: }