File:  [WindowsNT SDKs] / q_a / samples / scrnsave / fractal.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:29:55 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-nov-1993, ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993

/******************************Module*Header*******************************\
* Module Name: fractal.c
*
* Fractal generation Screen saver
*
* Created: 19-Dec-1992 20:43:00
* Author: Petrus Wong
*
* Copyright (c) 1992 Microsoft Corporation
*
* The screen saver generates the Mandelbrot picture...
*
* Dependencies:
*
*   (#defines)
*   (#includes)
*
\**************************************************************************/
#include            <windows.h>
#include            <scrnsave.h>
#include            <stdio.h>
#include            <math.h>
#include            <commdlg.h>
#include            "fractal.h"

LONG APIENTRY ScreenSaverProc(HWND, UINT, WPARAM, LPARAM);
BOOL APIENTRY ScreenSaverConfigureDialog(HWND, UINT, WPARAM, LPARAM);
BOOL WINAPI RegisterDialogClasses(HANDLE);
BOOL StartMandelbrot (PINFO);
INT  iCreatePenFrPal(HDC, PVOID *, INT, HPALETTE *);
BOOL bInitInfo(PINFO);
void vLoadStrings(VOID);
BOOL SaveBitmapFile(HDC, HBITMAP, PSTR);
void ErrorOut(char errstring[30]);
BOOL bGetPPStr(char szXFr[MAXDOUBLELEN], char szYFr[MAXDOUBLELEN],
               char szX2[MAXDOUBLELEN],  char szY2[MAXDOUBLELEN],
               char szSavef[MAXFILELEN], char szIter[MAXDOUBLELEN]);
BOOL bInitDlgItems(HWND);
BOOL bColorCycle(HDC, PINFO);
/******************************Public*Routine******************************\
*
* ScreenSaverProc
*
* Effects:  Creates a drawing thread.
*
* Warnings:
*
* History:
*  18-Dec-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

LONG APIENTRY
ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HBRUSH hBkBr;

    switch(message)
    {
        case WM_CREATE:
            hBkBr = GetStockObject(BLACK_BRUSH);
            hpnRed     = CreatePen(PS_SOLID, 0, RGB(0xFF, 0,    0));
            hpnGreen   = CreatePen(PS_SOLID, 0, RGB(0,    0xFF, 0));
            hpnBlack   = CreatePen(PS_SOLID, 0, RGB(0,    0,    0));

            vLoadStrings();
            bInitInfo(&gInfo);
            break;

        case WM_ERASEBKGND: {
            RECT    rc;

            GetClientRect(hWnd, &rc);
            FillRect((HDC)wParam, &rc, hBkBr);
            gInfo.bMandel = TRUE;
            gInfo.hwnd = hWnd;
            gInfo.hHTPal = CreateHalftonePalette((HDC)wParam);
            gInfo.hThrd = CreateThread(NULL, 0,
                                 (LPTHREAD_START_ROUTINE)StartMandelbrot,
                                 &gInfo,
                                 STANDARD_RIGHTS_REQUIRED,
                                 &gInfo.dwThreadId );

            if (gInfo.hThrd) {
                SetThreadPriority(gInfo.hThrd, THREAD_PRIORITY_BELOW_NORMAL);
            }


            return 0L;
        }
        case WM_DESTROY:
            DeleteObject(hBkBr);
            DeleteObject(hpnRed);
            DeleteObject(hpnGreen);
            DeleteObject(hpnBlack);
            TerminateThread(gInfo.hThrd, (DWORD)0L);
            break;
    }
    return (DefScreenSaverProc(hWnd,message,wParam,lParam));
}


/******************************Public*Routine******************************\
*
* ScreenSaverConfigureDialog
*
* Effects:
*
* Warnings:
*
* History:
*  19-Dec-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

BOOL APIENTRY
ScreenSaverConfigureDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_INITDIALOG: {
            vLoadStrings();
            bInitDlgItems(hDlg);
            return TRUE;
        }
        case WM_COMMAND:

            switch(LOWORD(wParam))
            {
                static char         szFile[MAXPATHLEN];
                static BOOL         bSave2DiffFile = FALSE;

                case ID_SAVEAS: {
                    OPENFILENAME ofn;
                    char         szDirName[MAXPATHLEN];
                    char         szFileTitle[256];
                    static char  *szFilter;

                    szFilter = "DIB files (*.bmp)\0\0";

                    GetSystemDirectory((LPSTR) szDirName, MAXPATHLEN);
                    strcpy(szFile, "*.bmp\0");
                    ofn.lStructSize = sizeof(OPENFILENAME);
                    ofn.hwndOwner = hDlg;
                    ofn.lpstrFilter = szFilter;
                    ofn.lpstrCustomFilter = (LPSTR) NULL;
                    ofn.nMaxCustFilter = 0L;
                    ofn.nFilterIndex = 0L;
                    ofn.lpstrFile = szFile;
                    ofn.nMaxFile = sizeof(szFile);
                    ofn.lpstrFileTitle = szFileTitle;
                    ofn.nMaxFileTitle = sizeof(szFileTitle);
                    ofn.lpstrInitialDir = szDirName;
                    ofn.lpstrTitle = "Save Bitmap As";
                    ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
                    ofn.nFileOffset = 0;
                    ofn.nFileExtension = 0;
                    ofn.lpstrDefExt = (LPSTR)NULL;

                    if (GetSaveFileName(&ofn))
                        bSave2DiffFile = TRUE;

                    break;
                }
                case IDOK: {
                    char    szXFr[MAXDOUBLELEN];
                    char    szYFr[MAXDOUBLELEN];
                    char    szX2[MAXDOUBLELEN];
                    char    szY2[MAXDOUBLELEN];
                    char    szIter[MAXDOUBLELEN];

                    if (bSave2DiffFile)
                        WritePrivateProfileString(szAppName, szSaveFile, szFile, szIniFile);

                    //
                    // Saves new configuartion...
                    //
                    GetDlgItemText(hDlg, ID_XFROM, szXFr, MAXDOUBLELEN);
                    GetDlgItemText(hDlg, ID_YFROM, szYFr, MAXDOUBLELEN);
                    GetDlgItemText(hDlg, ID_XTO,   szX2,  MAXDOUBLELEN);
                    GetDlgItemText(hDlg, ID_YTO,   szY2,  MAXDOUBLELEN);
                    GetDlgItemText(hDlg, ID_ITERATION, szIter, MAXDOUBLELEN);
                    WritePrivateProfileString(szAppName, szXFrom, szXFr, szIniFile);
                    WritePrivateProfileString(szAppName, szYFrom, szYFr, szIniFile);
                    WritePrivateProfileString(szAppName, szXTo,    szX2,  szIniFile);
                    WritePrivateProfileString(szAppName, szYTo,    szY2,  szIniFile);
                    WritePrivateProfileString(szAppName, szIteration, szIter,  szIniFile);
                }
                case IDCANCEL:
                    bSave2DiffFile = FALSE;
                    EndDialog(hDlg,LOWORD(wParam) == IDOK);
                    return TRUE;
                default:
                    break;
            }
        default:
            break;
    }
    return FALSE;
}

/******************************Public*Routine******************************\
*
* RegisterDialogClasses
*
* Effects: Register window classes used by the configuration dialog
*
* Warnings: Return TRUE even if no class needed to be registered.
*
* History:
*  18-Dec-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
    return TRUE;
}

/**************************************************************************\
*
* StartMandelbrot
*					     2
* Effects: Draw'g the Mandelbrot Set for Q (z) = z  + c, where z, c complex
*
* Warnings:
*
* History:
*  15-Jan-1993      Petrus Wong     Added color cycle and removed the red &
*                                   black for saving the screen
*  19-Dec-1992      Petrus Wong     Adapted from the Mandel SDK Sample
*  14-Dec-1992 -by- Petrus Wong     Enable shadow bitmap
*  14-Jun-1992 -by- Petrus Wong     Modified to use the pen array and LineTo
*  20-Nov-1991 -by- Petrus Wong
* Wrote it.
\**************************************************************************/
BOOL StartMandelbrot(PINFO pInfo)
{
   DWORD       dwTick1;
   HDC         hDC;
   RECT        rc;
   int	       m, n, i, iPrev;
   int         xCurr, yCurr;
   int         iPen;

#ifndef THRDONE
   INT      iNumClr;
   char     text[256];
#endif

   double c1, c2;
   double x1, y1, x, y, r;

   HDC          hDCMem;
   HBITMAP      hBitmap, hOldBitmap;

   pInfo->bMandel = TRUE;
   pInfo->bDrawing = TRUE;
   hDC = GetDC(pInfo->hwnd);

#ifndef THRDONE
    if ((iNumClr = iCreatePenFrPal(hDC, NULL, 0, &(pInfo->hPal))) != 0) {
        sprintf( gtext,"iNumClr = %d\n", iNumClr);
        OutputDebugString( gtext);

        if ((pInfo->prghPen = (PVOID*) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(HPEN)*iNumClr)) == NULL) {
            MessageBox(GetFocus(), "Failed in Memory Allocation for pInfo->prghPen!", "Error", MB_OK);
        } else {
            if ((pInfo->iPen = iCreatePenFrPal(hDC, pInfo->prghPen, 1, &(pInfo->hPal))) == 0)
                MessageBox(GetFocus(), "Failed in creating pen!", "Error", MB_OK);
        }
    }

   hDCMem = CreateCompatibleDC(hDC);

   if (pInfo->hPal) {
    SelectPalette(hDCMem, pInfo->hPal, FALSE);
    RealizePalette(hDCMem);
   }
   iPen = pInfo->iPen + 1;
   wsprintf(text, "iPen = %d\n", iPen);
   //MessageBox(GetFocus(), text, "Error", MB_OK);
#endif

   GetClientRect(pInfo->hwnd, &rc);

   hBitmap = CreateCompatibleBitmap(hDC, (int)rc.right, (int)rc.bottom);
   hOldBitmap = SelectObject(hDCMem, hBitmap);

//#if 0
 {
   int iWidth, i, j;

   iWidth = (((iWidth = rc.right/iNumClr) == 0) ? 1 : iWidth);
   sprintf( gtext,"iWidth = %d\n", iWidth);
   OutputDebugString( gtext);

   for (i = 0; i < iNumClr; i++) {
   //for (i = 0; i < 256; i++) {
       //sprintf( gtext,"i mod iNumClr = %d\n", i % iNumClr);
       //OutputDebugString( gtext);
       if ((SelectObject(hDC, (HPEN)(pInfo->prghPen)[i % iNumClr])) == NULL) {
            sprintf( gtext,"Select Pen failed\n");
            OutputDebugString( gtext);
       }
       SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[i % iNumClr]);
       for (j = 0; j < iWidth; j++) {
            MoveToEx(hDC, i*iWidth+j, 0, NULL);
            LineTo(hDC, i*iWidth+j, rc.bottom);
            MoveToEx(hDCMem, i*iWidth+j, 0, NULL);
            LineTo(hDCMem, i*iWidth+j, rc.bottom);
       }

   }
 }
//#endif

   dwTick1 = GetTickCount();

   sprintf( gtext,"Start Drawing\n");
   OutputDebugString( gtext);
   yCurr = rc.top;
   for (n=rc.top; n<=rc.bottom; n+=pInfo->iStep, yCurr+=pInfo->iStep, iPrev = FIRST_PIXEL) {
       xCurr = rc.left;                   // since LineTo excludes last point
       MoveToEx(hDC, 0, yCurr, NULL);
       MoveToEx(hDCMem, 0, yCurr, NULL);
       c2 = Xform((double) n, 0.0, (double) rc.bottom, pInfo->yFrom, pInfo->yTo);

       for (m=rc.left; m<=rc.right; m++, xCurr++) {
           c1 = Xform((double) m, 0.0, (double) rc.right, pInfo->xFrom, pInfo->xTo);
	   x = c1;
	   y = c2;

	   for (i=1; i<=pInfo->iIteration; i++) {
               x1 = (x - y) * (x + y) + c1;
               y1 = 2 * x * y + c2;
	       r = x1 * x1 + y1 * y1;
	       x = x1;
	       y = y1;
	       if (r > 4.0) {
                   break;
               }
           }

           if (i != iPrev) {
               if (iPrev != FIRST_PIXEL) {
                 switch(iPrev) {
                   case 1: SelectObject(hDC, (HPEN)(pInfo->prghPen)[0]);
                           SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
                    break;
                   default:
                       if (iPrev >= pInfo->iIteration) {
                            SelectObject(hDC, (HPEN)(pInfo->prghPen)[iPen/3]);
                            SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[iPen/3]);
                            break;
                       }
                       SelectObject(hDC, (HPEN)(pInfo->prghPen)[iPrev % iPen]);
                       SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[iPrev % iPen]);
                       //SelectObject(hDC, (HPEN)(pInfo->prghPen)[iPrev % iNumClr]);
                       break;
                 }
                 iPrev = i;
                 LineTo(hDC, xCurr, yCurr);
                 LineTo(hDCMem, xCurr, yCurr);
               }
               else
		  iPrev = i;	// remember the color for the first pixel
           }
       }

            switch(i)
		{
                   case 1: SelectObject(hDC, (HPEN)(pInfo->prghPen)[0]);
                           SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
                    break;
                   default:
                       if (i >= pInfo->iIteration) {
                            SelectObject(hDC, (HPEN)(pInfo->prghPen)[iPen/3]);
                            SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[iPen/3]);
                            break;
                       }
                       SelectObject(hDC, (HPEN)(pInfo->prghPen)[i % iPen]);
                       SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[i % iPen]);
                       //SelectObject(hDC, (HPEN)(pInfo->prghPen)[i % iNumClr]);
                       break;
		}

		 LineTo(hDC,xCurr,yCurr);
                 LineTo(hDCMem,xCurr,yCurr);

   }



   pInfo->dwElapsed = GetTickCount() - dwTick1;

   if (pInfo->hBmpSaved)
       DeleteObject(pInfo->hBmpSaved);

   pInfo->hBmpSaved = SelectObject(hDCMem, hOldBitmap);
   pInfo->bDrawing = FALSE;
   SaveBitmapFile(hDC, pInfo->hBmpSaved, pInfo->szSavef);
   pInfo->bClrCycle = TRUE;
   if (pInfo->hPal)
      bColorCycle(hDC, pInfo);
   ReleaseDC(pInfo->hwnd, hDC);

#ifndef THRDONE
   if (pInfo->prghPen != NULL) {
       for (i = 0; i <= pInfo->iPen; i++) {
           DeleteObject((HPEN) (pInfo->prghPen)[i]);
       }
       GlobalFree(pInfo->prghPen);
   }
#endif

   DeleteDC(hDCMem);

   ExitThread(0);
   if (!CloseHandle(pInfo->hThrd))
       MessageBox(GetFocus(), "Failed in CloseHandle!", "Error", MB_OK);

   return TRUE;
}


/******************************Public*Routine******************************\
*
* iCreatePenFrPal
*
* Effects: Create an array of pens from palette.
*          If device supports palette, then first creates a logical palette
*          with a good spread of color. Then select the logical palette into
*          the DC. Create pen that corresponds to each palette entry.
*          If system does not support palette, then use the system palette.
*
*          prghPen pointer to an array of hPen
*                  If this is NULL, the required size of the array is
*                  returned. If this is not NULL, the array will be filled
*                  with hPens.
*
*          returns the number of hPens created.
*
* Warnings:
*
* History:
*  13-Jun-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

INT iCreatePenFrPal(HDC hDC, PVOID *prghPen, INT iWidth, HPALETTE *phPal)
{
    INT             iNumClr, iResult, i, iEntry;
    PLOGPALETTE     plogPat;
    ULONG           ulSize;

    iResult = 0;

    if (!((GetDeviceCaps(hDC, RASTERCAPS)) & RC_PALETTE)) {

        if (iNumClr = GetSystemPaletteEntries(hDC, 0, 0, NULL)) {
            if (prghPen == NULL) {
                return (iNumClr);
            }

            if (iWidth < 0) {
                MessageBox(GetFocus(), "Invalid pen width!", "Error", MB_OK);
                return 0L;
            }

            for (i = 0; i < iNumClr; i++) {
                prghPen[i] =
                     (PVOID) CreatePen(PS_SOLID, iWidth, PALETTEINDEX(i));
                iResult = i;
#if 0
                SelectObject(hDC, (HPEN)prghPen[i]);
                MoveToEx(hDC, i*iWidth, 0, NULL);
                LineTo(hDC, i*iWidth, 300);
#endif
            }
            return iResult;
        }

        // GetPaletteEntries returns 0
        iNumClr = 1 << GetDeviceCaps(hDC, BITSPIXEL);

        if (iNumClr <= 16) {
            sprintf( gtext,"Assertion failed: iCreatePenFrPal() \n");
            OutputDebugString( gtext);
            sprintf( gtext,"iNumClr <= 16! iNumClr = %d\n", iNumClr);
            OutputDebugString( gtext);
            return (iNumClr);
        }

        // Assuming at least 16 bit device
        //
        iNumClr = 768;      // COLORREF format: 0x00bbggrr r,g,b=[0,255]

        if (prghPen == NULL) {
            return (iNumClr);
        }

        if (iWidth < 0) {
            MessageBox(GetFocus(), "Invalid pen width!", "Error", MB_OK);
            return 0L;
        }

        for (i = 0; i < iNumClr; i++) {
            if (i < 256) {
                prghPen[i] =
                    (PVOID) CreatePen(PS_SOLID, iWidth, RGB(i,0,255-i));
                iResult = i;
#if 0
                SelectObject(hDC, (HPEN)prghPen[i]);
                MoveToEx(hDC, i*iWidth, 0, NULL);
                LineTo(hDC, i*iWidth, 300);
#endif
                continue;
            }

            if (i < 512) {
                prghPen[i] =
                    (PVOID) CreatePen(PS_SOLID, iWidth, RGB(511-i,i-256,0));
                iResult = i;
#if 0
                SelectObject(hDC, (HPEN)prghPen[i]);
                MoveToEx(hDC, i*iWidth, 0, NULL);
                LineTo(hDC, i*iWidth, 300);
#endif
                continue;
            }


            prghPen[i] =
                (PVOID) CreatePen(PS_SOLID, iWidth, RGB(0,767-i,i-512));
            iResult = i;
#if 0
            SelectObject(hDC, (HPEN)prghPen[i]);
            MoveToEx(hDC, i*iWidth, 0, NULL);
            LineTo(hDC, i*iWidth, 300);
#endif
        }

        return iResult;
    }

    //
    // Palette managed device
    //
    iEntry = iNumClr = 1 << GetDeviceCaps(hDC, BITSPIXEL);

    if (iNumClr > 256) {
        sprintf( gtext,"Assertion failed: iCreatePenFrPal() \n");
        OutputDebugString( gtext);
        sprintf( gtext,"iNumClr > 256! iNumClr = %d\n", iNumClr);
        OutputDebugString( gtext);
        iEntry=iNumClr = 256;
    }

    ulSize = sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*iNumClr;

    iNumClr -= GetDeviceCaps(hDC, NUMRESERVED);

    if (prghPen == NULL)
        return iNumClr;

    if ((plogPat = (PLOGPALETTE) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, ulSize)) == NULL) {
        MessageBox(GetFocus(), "Failed in Memory Allocation for plogPat!", "Error", MB_OK);
        goto ErrExit1;
    }

    plogPat->palVersion = 0x300;
    plogPat->palNumEntries = (WORD) iEntry;

    {
    int     iFirst, iSecond, iInc;

        iFirst = iNumClr/3;
        iSecond = iFirst * 2;
        iInc = (iNumClr <= 256) ? 3 : 1;


        for (i = 0; i < iNumClr; i++) {
            if (i < iFirst) {
                plogPat->palPalEntry[i+10].peBlue   = 255-(i+1)*iInc;
                plogPat->palPalEntry[i+10].peGreen  = 0;
                plogPat->palPalEntry[i+10].peRed    = (i+1)*iInc;
                plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
                continue;
            }
            if (i < iSecond) {
                plogPat->palPalEntry[i+10].peBlue   = 0;
                plogPat->palPalEntry[i+10].peGreen  = (i+1-iFirst)*iInc;
                plogPat->palPalEntry[i+10].peRed    = 255-(i+1-iFirst)*iInc;
                plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
                continue;
            }
            plogPat->palPalEntry[i+10].peBlue   = (i+1-iSecond)*iInc;
            plogPat->palPalEntry[i+10].peGreen  = 255-(i+1-iSecond)*iInc;
            plogPat->palPalEntry[i+10].peRed    = 0;
            plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
        }
    }

    DeleteObject(*phPal);

    if ((*phPal = CreatePalette(plogPat)) == (HPALETTE) NULL) {
        MessageBox(GetFocus(), "Failed in creating palette!", "Error", MB_OK);
        goto ErrExit2;
    }
    if (*phPal) {
       SelectPalette(hDC, *phPal, FALSE);
       RealizePalette(hDC);
    }

    for (i = 0; i < iNumClr; i++) {
        HPEN    hPen;

        hPen = CreatePen(PS_SOLID, iWidth, PALETTEINDEX(i+10));
        prghPen[i] = (PVOID) hPen;
        iResult = i;
#if 0
        SelectObject(hDC, hPen);
        MoveToEx(hDC, i*iWidth, 0, NULL);
        LineTo(hDC, i*iWidth, 300);
#endif
    }

ErrExit2:
    GlobalFree(plogPat);
ErrExit1:
    return iResult;

}

/******************************Public*Routine******************************\
*
* bInitInfo
*
* Effects: Initialize the Info data structure
*
* Warnings:
*
* History:
*  19-Dec-1992      Petrus Wong         Retrieve setup info fr control.ini
*  14-Dec-1992 -by- Petrus Wong         Added Rle and pens stuff
*  28-Jan-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

BOOL bInitInfo(PINFO pInfo)
{
    char    szXFr[MAXDOUBLELEN], szYFr[MAXDOUBLELEN], szX2[MAXDOUBLELEN],
            szY2[MAXDOUBLELEN], szSavef[MAXPATHLEN], szIter[MAXDOUBLELEN];

    bGetPPStr(szXFr, szYFr, szX2, szY2, szSavef, szIter);
    pInfo->xFrom        = atof(szXFr);
    pInfo->xTo          = atof(szX2);
    pInfo->yFrom        = atof(szYFr);
    pInfo->yTo          = atof(szY2);
    pInfo->lxFrom       = -4096;                // 20.11 fix point
    pInfo->lxTo         = 4096;                 // representation of
    pInfo->lyFrom       = 4096;                 // -2, 2, 2, and -2
    pInfo->lyTo         = -4096;                //
    pInfo->iIteration   = (INT) atof(szIter);
    pInfo->iStep        = gStep;
    pInfo->bStretch     = gbStretch;
    pInfo->iStretchMode = giStretchMode;
    pInfo->hwnd         = NULL;
    pInfo->hThrd        = NULL;
    pInfo->bDrawing     = FALSE;
    pInfo->dwThreadId   = 0;
    pInfo->dwElapsed    = 0L;
    pInfo->c1           = 0.0;
    pInfo->c2           = 0.0;
    pInfo->lc1          = 0L;
    pInfo->lc2          = 0L;
    pInfo->hBmpSaved    = NULL;
    pInfo->bMandel      = TRUE;
    pInfo->bSetDIBsToDevice = FALSE;
    pInfo->hPal         = NULL;
    pInfo->prghPen      = NULL;
    pInfo->iPen         = 0;
    pInfo->bClrCycle    = FALSE;
    wsprintf((LPSTR) &(pInfo->szSavef), szSavef);
    return TRUE;
}




/******************************Public*Routine******************************\
*
* vLoadStrings
*
* Effects: Load strings from resource
*
* Warnings:
*
* History:
*  19-Dec-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

void vLoadStrings(VOID)
{
    LoadString(hMainInstance, idsAppName, szAppName, APPNAMEBUFFERLEN);
    LoadString(hMainInstance, idsName, szName, TITLEBARNAMELEN);
    LoadString(hMainInstance, idsIniFile, szIniFile, MAXFILELEN);
    LoadString(hMainInstance, idsScreenSaver, szScreenSaver, 22);
    LoadString(hMainInstance, idsHelpFile, szHelpFile, MAXFILELEN);
    LoadString(hMainInstance, idsNoHelpMemory, szNoHelpMemory, BUFFLEN);
    LoadString(hMainInstance, idsXFrom, szXFrom, MAXDOUBLELEN);
    LoadString(hMainInstance, idsYFrom, szYFrom, MAXDOUBLELEN);
    LoadString(hMainInstance, idsXTo, szXTo, MAXDOUBLELEN);
    LoadString(hMainInstance, idsYTo, szYTo, MAXDOUBLELEN);
    LoadString(hMainInstance, idsSaveAs, szSaveFile, MAXPATHLEN);
    LoadString(hMainInstance, idsIteration, szIteration, MAXDOUBLELEN);
}



/******************************Public*Routine******************************\
* SaveBitmapFile
*
*
* Effects: Save pInfo->hBmpSaved into disk specified by pszFileName
*
* Warnings: assumes hBmpSaved is not selected into window's DC other than
*           pInfo->hwnd's DC
*
* History:
*  14-Jan-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

BOOL SaveBitmapFile(HDC hDC, HBITMAP hBmp, PSTR pszFileName)
{
    int         hFile;
    OFSTRUCT    ofReOpenBuff;
    HBITMAP     hTmpBmp, hBmpOld;
    BOOL        bSuccess;
    BITMAPFILEHEADER    bfh;
    PBITMAPINFO pbmi;
    PBYTE       pBits;
    BITMAPINFO  bmi;
    PBYTE pjTmp, pjTmpBmi;
    ULONG sizBMI;


    bSuccess = TRUE;
    if (!hBmp) {
        MessageBox(GetFocus(), "There's no Bitmap to save!", "Error", MB_OK);
        return FALSE;
    }

    //
    // Let the graphics engine to retrieve the dimension of the bitmap for us
    // GetDIBits uses the size to determine if it's BITMAPCOREINFO or BITMAPINFO
    // if BitCount != 0, color table will be retrieved
    //
    bmi.bmiHeader.biSize = 0x28;              // GDI need this to work
    bmi.bmiHeader.biBitCount = 0;             // don't get the color table
    if ((GetDIBits(hDC, hBmp, 0, 0, (LPSTR)NULL, &bmi, DIB_RGB_COLORS)) == 0) {
        MessageBox(GetFocus(), "GetDIBits failed!", "Error", MB_OK);
        return FALSE;
    }

    //
    // Now that we know the size of the image, alloc enough memory to retrieve
    // the actual bits
    //
    if ((pBits = (PBYTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
                bmi.bmiHeader.biSizeImage)) == NULL) {
        MessageBox(GetFocus(), "Failed in Memory Allocation for pBits!", "Error", MB_OK);
        return FALSE;
    }

    //
    // Note: 24 bits per pixel has no color table.  So, we don't have to
    // allocate memory for retrieving that.  Otherwise, we do.
    //
    pbmi = &bmi;                                      // assume no color table
    if (bmi.bmiHeader.biBitCount != 24) {             // has color table
        sizBMI = sizeof(BITMAPINFO)+sizeof(RGBQUAD)*(1<<bmi.bmiHeader.biBitCount);
        //
        // I need more memory for the color table
        //
        if ((pbmi = (PBITMAPINFO)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizBMI )) == NULL) {
            MessageBox(GetFocus(), "Failed in Memory Allocation for pbmi!", "Error", MB_OK);
            bSuccess = FALSE;
            goto ErrExit1;
        }
        //
        // Now that we've a bigger chunk of memory, let's copy the Bitmap
        // info header data over
        //
        pjTmp = (PBYTE)pbmi;
        pjTmpBmi = (PBYTE)&bmi;
        sizBMI = sizeof(BITMAPINFOHEADER);

        while(sizBMI--)
        {
            *(((PBYTE)pjTmp)++) = *((pjTmpBmi)++);
        }

    }

    //
    // Let's open the file and get ready for writing
    //
    if ((hFile = OpenFile(pszFileName, (LPOFSTRUCT)&ofReOpenBuff,
                 OF_CREATE | OF_WRITE)) == -1) {
        MessageBox(GetFocus(), "Failed in OpenFile!", "Error", MB_OK);
        ErrorOut("OpenFile");
        goto ErrExit2;
    }

    //
    // But first, fill in the info for the BitmapFileHeader
    //
    bfh.bfType = 0x4D42;                            // 'BM'
    bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*
        ((pbmi->bmiHeader.biBitCount == 24) ? 0 : (1<<pbmi->bmiHeader.biBitCount))+
        pbmi->bmiHeader.biSizeImage;
    bfh.bfReserved1 =
    bfh.bfReserved2 = 0;
    bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
        sizeof(RGBQUAD)*((pbmi->bmiHeader.biBitCount == 24) ? 0 : (1<<pbmi->bmiHeader.biBitCount));

    //
    // Write out the file header now
    //
    if (_lwrite(hFile, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER)) == -1) {
        MessageBox(GetFocus(), "Failed in WriteFile!", "Error", MB_OK);
        bSuccess = FALSE;
        goto ErrExit3;
    }

    //
    // Bitmap can't be selected into a DC when calling GetDIBits
    // Assume that the hDC is the DC where the bitmap would have been selected
    // if indeed it has been selected
    //
    if (hTmpBmp = CreateCompatibleBitmap(hDC, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight)) {
        hBmpOld = SelectObject(hDC, hTmpBmp);
        if ((GetDIBits(hDC, hBmp, 0, pbmi->bmiHeader.biHeight, (LPSTR)pBits, pbmi, DIB_RGB_COLORS))==0){
            MessageBox(GetFocus(), "Failed in GetDIBits!", "Error", MB_OK);
            bSuccess = FALSE;
            goto ErrExit4;
        }
    } else {
        MessageBox(GetFocus(), "Failed in creating bitmap!", "Error", MB_OK);
        bSuccess = FALSE;
        goto ErrExit3;
    }

    //
    // Now write out the BitmapInfoHeader and color table, if any
    //
    if (_lwrite(hFile, (LPSTR)pbmi, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) *
        ((pbmi->bmiHeader.biBitCount == 24) ? 0 : (1 << pbmi->bmiHeader.biBitCount))) == -1) {
        MessageBox(GetFocus(), "Failed in WriteFile!", "Error", MB_OK);
        bSuccess = FALSE;
        goto ErrExit4;
    }

    //
    // write the bits also
    //
    if (_lwrite(hFile, (LPSTR)pBits, pbmi->bmiHeader.biSizeImage) == -1) {
        MessageBox(GetFocus(), "Failed in WriteFile!", "Error", MB_OK);
        bSuccess = FALSE;
        goto ErrExit4;
    }


ErrExit4:
    SelectObject(hDC, hBmpOld);
    DeleteObject(hTmpBmp);
ErrExit3:
    _lclose(hFile);
ErrExit2:
    GlobalFree(pbmi);
ErrExit1:
    GlobalFree(pBits);
    return bSuccess;
}

/************************************************************************
 * void ErrorOut(char errstring[30])
 *
 * Purpose: Print out an meainful error code by means of
 *	  GetLastError and printf
 *
 * Inputs:  errstring - the action that failed, passed by the
 *		      calling proc.
 *
 * Returns: none
 *
 * Calls:   GetLastError
 *
 * History:
 *
\************************************************************************/


void ErrorOut(char errstring[30])
{
DWORD Error;
CHAR  str[80];

Error= GetLastError();
wsprintf((LPSTR) str, "Error on %s = %d\n", errstring, Error);
MessageBox(GetFocus(), (LPSTR)str, "Error", MB_OK);
}

BOOL bInitDlgItems(HWND hDlg)
{
    char    szXFr[MAXDOUBLELEN], szYFr[MAXDOUBLELEN], szX2[MAXDOUBLELEN],
            szY2[MAXDOUBLELEN], szSavef[MAXPATHLEN], szIter[MAXDOUBLELEN];
    BOOL    bSuccess;

    bSuccess = bGetPPStr(szXFr, szYFr, szX2, szY2, szSavef, szIter);
    SetDlgItemText(hDlg, ID_XFROM, szXFr);
    SetDlgItemText(hDlg, ID_YFROM, szYFr);
    SetDlgItemText(hDlg, ID_XTO, szX2);
    SetDlgItemText(hDlg, ID_YTO, szY2);
    SetDlgItemText(hDlg, ID_ITERATION, szIter);

    return bSuccess;
}


/******************************Public*Routine******************************\
*
* bGetPPStr
*
* Effects: GetPrivateProfileString from control.ini
*
* Warnings:
*
* History:
*  19-Dec-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

BOOL bGetPPStr(char szXFr[MAXDOUBLELEN], char szYFr[MAXDOUBLELEN],
               char szX2[MAXDOUBLELEN],  char szY2[MAXDOUBLELEN],
               char szSavef[MAXPATHLEN], char szIter[MAXDOUBLELEN])
{
    char    szDefXFr[MAXDOUBLELEN];
    char    szDefYFr[MAXDOUBLELEN];
    char    szDefX2[MAXDOUBLELEN];
    char    szDefY2[MAXDOUBLELEN];
    char    szDefSavef[MAXPATHLEN];
    char    szDefIter[MAXDOUBLELEN];

    sprintf(szDefXFr, "-2.00");
    sprintf(szDefYFr, "1.00");
    sprintf(szDefX2,  "1.00");
    sprintf(szDefY2,  "-1.00");
    sprintf(szDefSavef, "c:\\fractal.bmp");
    sprintf(szDefIter, "500");
    GetPrivateProfileString(szAppName, szXFrom, szDefXFr, szXFr, MAXDOUBLELEN, szIniFile);
    GetPrivateProfileString(szAppName, szYFrom, szDefYFr, szYFr, MAXDOUBLELEN, szIniFile);
    GetPrivateProfileString(szAppName, szXTo, szDefX2, szX2, MAXDOUBLELEN, szIniFile);
    GetPrivateProfileString(szAppName, szYTo, szDefY2, szY2, MAXDOUBLELEN, szIniFile);
    GetPrivateProfileString(szAppName, szSaveFile, szDefSavef, szSavef, MAXPATHLEN, szIniFile);
    GetPrivateProfileString(szAppName, szIteration, szDefIter, szIter, MAXDOUBLELEN, szIniFile);
    return TRUE;
}



/******************************Public*Routine******************************\
*
* bColorCycle
*
* Effects:  Create a logical palette with a good spread of color
*           Animate the palette, shift the palette entries and animate
*           again for 256 times altogether.
*           This creates the color cycling effect.
*
* Warnings: Only works in device that support palette.
*
* History:
*  15-Jan-1993      Petrus Wong     Adaped from the SDK Mandel sample
*  24-Apr-1992 -by- Petrus Wong
* Wrote it.
\**************************************************************************/

BOOL bColorCycle(HDC hDC, PINFO pInfo)
{
    INT             iEntry, i, iNumClr;
    PLOGPALETTE     plogPat;
    ULONG           ulSize;
    BOOL            bSuccess;
    HPALETTE        hPal, hPalOld;
    PALETTEENTRY    peTemp;
    BOOL            bQuit;


UINT uRC;

    bSuccess = TRUE;
    iEntry = 1<<GetDeviceCaps(hDC, BITSPIXEL);
    iNumClr = 236;          // 256 minus 20 reserved colors
    ulSize = sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*256;

    if ((plogPat = (PLOGPALETTE) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, ulSize)) == NULL) {
        MessageBox(hMainWindow, "Failed in Memory Allocation for plogPat!", "Error", MB_OK);
        bSuccess = FALSE;
        goto ErrExit1;
    }

    plogPat->palVersion = 0x300;
    plogPat->palNumEntries = (WORD) 256;
    {
    int     iFirst, iSecond, iInc;

        iFirst = iNumClr/3;
        iSecond = iFirst * 2;
        iInc = (iNumClr <= 256) ? 3 : 1;

        for (i = 0; i < iNumClr; i++) {
            if (i < iFirst) {
                plogPat->palPalEntry[i+10].peBlue   = 255-(i+1)*iInc;
                plogPat->palPalEntry[i+10].peGreen  = 0;
                plogPat->palPalEntry[i+10].peRed    = (i+1)*iInc;
                plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
                continue;
            }
            if (i < iSecond) {
                plogPat->palPalEntry[i+10].peBlue   = 0;
                plogPat->palPalEntry[i+10].peGreen  = (i+1-iFirst)*iInc;
                plogPat->palPalEntry[i+10].peRed    = 255-(i+1-iFirst)*iInc;
                plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
                continue;
            }
            plogPat->palPalEntry[i+10].peBlue   = (i+1-iSecond)*iInc;
            plogPat->palPalEntry[i+10].peGreen  = 255-(i+1-iSecond)*iInc;
            plogPat->palPalEntry[i+10].peRed    = 0;
            plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
        }
    }

    if ((hPal = CreatePalette(plogPat)) == (HPALETTE) NULL) {
        MessageBox(hMainWindow, "Failed in creating palette!", "Error", MB_OK);
        bSuccess = FALSE;
        goto ErrExit2;
    }

    hPalOld = SelectPalette(hDC, hPal, FALSE);
    RealizePalette(hDC);
    //SelectPalette(hDC, hPalOld, FALSE);

    bQuit = FALSE;
    while (TRUE && !bQuit) {
        if (!pInfo->bClrCycle) {
            //sprintf( gtext,"NOT to animate palette\n");
            //OutputDebugString( gtext );
            bQuit = TRUE;
        }

        if (!bQuit) {
            //sprintf( gtext,"About to animate palette\n");
            //OutputDebugString( gtext );


            peTemp = plogPat->palPalEntry[10];
            for (i = 0; i < iNumClr; i++) {
                plogPat->palPalEntry[i+10] = plogPat->palPalEntry[i+10+1];
            }
            plogPat->palPalEntry[i+10] = peTemp;

            Sleep(25);

            if (!AnimatePalette(hPal, 0, 256, plogPat->palPalEntry)) {
                sprintf( gtext,"Anmiate palette failed\n");
                OutputDebugString( gtext );
            }

            if ((uRC = RealizePalette(hDC)) == -1) {
                sprintf( gtext,"Realize palette failed\n");
                OutputDebugString( gtext );
            }

            if (!UpdateColors(hDC)) {
                sprintf( gtext,"Update Colors failed\n");
                OutputDebugString( gtext );
            }

        }

    }

    SelectPalette(hDC, hPalOld, 0);
    DeleteObject(hPal);
ErrExit2:
    GlobalFree(plogPat);
ErrExit1:
    return bSuccess;

}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.