home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / mandel / julia.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  149KB  |  5,738 lines

  1. /******************************Module*Header*******************************\
  2. * Module Name: julia.c
  3. *
  4. * Main module for the Mandelbrot Dream
  5. *       contains almost everything; windows procedure + misc stuff
  6. *
  7. * Created: 24-Oct-1991 18:34:08
  8. *
  9. * Copyright (C) 1993-1997 Microsoft Corporation
  10. *
  11. * The Mandelbrot Dream serves to demonstrate the GDI and USER
  12. * functionalities in the setting of fractals.
  13. *
  14. * The Mandelbrot Dream provides the following functions:
  15. *       1.  Drawing the Mandelbrot set and the corresponding julia set
  16. *       2.  Zooming into any of the set
  17. *       3.  MDI fractal drawing windows
  18. *       4.  Floating Point Math/Fix Point Math
  19. *       5.  Shifting color table entries
  20. *       6.  Changing palette entries and animating palatte aka color cycling
  21. *       7.  Loading/Saving bitmap created with special effect
  22. *       8.  Changing bitmap color with flood fill
  23. *       9.  Boundary tracing and creating a clip region out of it for
  24. *           creating special effect
  25. *      10.  Enumerate printers for printing
  26. *      11.  Load RLE (or convert .bmp files to RLE) for playing in viewer
  27. *      12.  Save the RLE in memory to disk.
  28. *
  29. * Note: Users can now draw and saves the julia sets on disk as bmps in
  30. *       the Julia windows.  These bitmaps can then be read into the memory
  31. *       (and converted to RLE format) one by one for displaying in sequence
  32. *       in the viewer window.  Eg Load the julia.rle in the viewer window
  33. *       and select the play or play continuously menu item.     02-Jan-1993
  34. *
  35. * Note2: The fix point math in this sample makes use of the LargeInteger
  36. *        64 bit math library.
  37. *
  38. * Dependencies:
  39. *
  40. *       none
  41. *
  42. \**************************************************************************/
  43. #include <windows.h>
  44. #include <stdlib.h>
  45. #include <commdlg.h>
  46. #include <stdarg.h>
  47. #include <math.h>
  48. #include <stdio.h>
  49. #include <shellapi.h>
  50. #include "julia.h"
  51.  
  52. //
  53. // For T1 to create all pens in advance.  This is not a good approach
  54. // because pens are per thread basis.  The drawing threads won't be able
  55. // to use them if they are not created in their threads.    18-Sep-1992
  56. //
  57. //#define THRDONE
  58.  
  59. #define CYCLETHRD
  60.  
  61. #define PRTTHRD
  62. #define NEWPRTAPI
  63.  
  64. #ifndef DEBUG
  65.    #undef OutputDebugString
  66.    #define OutputDebugString(LPCSTR)
  67. #endif
  68.  
  69. //
  70. // Forward declarations.
  71. //
  72. BOOL InitializeApp            (INT*);
  73. LONG APIENTRY MainWndProc     (HWND, UINT, DWORD, LONG);
  74. LONG APIENTRY ChildWndProc    (HWND, UINT, DWORD, LONG);
  75. BOOL CALLBACK About           (HWND, UINT, DWORD, LONG);
  76. LONG APIENTRY TextWndProc     (HWND, UINT, DWORD, LONG);
  77. LONG APIENTRY JuliaWndProc    (HWND, UINT, DWORD, LONG);
  78. LONG APIENTRY ViewerWndProc   (HWND, UINT, DWORD, LONG);
  79. LONG APIENTRY ViewSurfWndProc (HWND, UINT, DWORD, LONG);
  80. BOOL APIENTRY SuspendDrawThrd (HWND, LONG);
  81. BOOL APIENTRY ResumeDrawThrd  (HWND, LONG);
  82. BOOL StartDraw       (PINFO);
  83. BOOL StartDrawFix    (PINFO);
  84. BOOL StartDraw2      (PINFO);
  85. BOOL StartMandelbrot (PINFO);
  86. BOOL StartMandelbrotFix (PINFO);
  87. HBITMAP SaveBitmap   (HWND, HPALETTE);
  88. void DrawBitmap      (HDC, PINFO, int, int, int, int);
  89. BOOL bDrawDIB        (HDC, PINFO, int, int, int, int);
  90. LONG lMul(LONG, LONG);
  91. LONG lDiv(LONG, LONG);
  92. PINFO pGetInfoData(HWND);
  93. BOOL bReleaseInfoData(HWND);
  94. BOOL bCheckMutexMenuItem(PINFO, HMENU, UINT);
  95. VOID vChkMenuItem(PINFO, HMENU, UINT);
  96. BOOL bInitInfo(PINFO);
  97. BOOL bResetGlobal(VOID);
  98. HBRUSH hBrCreateBrush(HDC, DWORD);
  99. BOOL bPrintBmp(PPRTDATA);
  100. BOOL bStoreRleFile(HDC, PINFO, PSTR);
  101. BOOL bFreeRleFile(PINFO);
  102. BOOL bPlayRle(PINFO);
  103. BOOL bSaveRleFile(HDC, PINFO, PSTR);
  104. BOOL bPlayRleCont2(PINFO);
  105. BOOL bSelectDIBPal(HDC, PINFO, LPBITMAPINFO, BOOL);
  106. HBITMAP DIBfromDDB(HDC, HBITMAP, PINFO);
  107.  
  108.  
  109. //
  110. // Global variable declarations.
  111. //
  112.  
  113. HPEN   hpnRed;
  114. HPEN   hpnBlack;
  115. HPEN   hpnGreen;
  116. INT    giPen = 0;
  117.  
  118. HANDLE ghModule;
  119. HWND   ghwndMain = NULL;
  120. HWND   ghwndClient = NULL;
  121. HANDLE ghAccel;
  122.  
  123. HMENU  hMenu, hChildMenu, hViewMenu;
  124. HMENU  hViewSubOne, hSubMenuOne, hSubMenuThree;
  125. HMENU  hPrinterMenu;
  126.  
  127. CHAR   gszFile[20];
  128. CHAR   gszMapName[20];
  129. char   gtext[256];
  130.  
  131. BOOL   gFloat = TRUE;
  132. LONG   gStep = 1;
  133. LONG   gIteration = 500;
  134. BOOL   gbStretch = TRUE;
  135. INT    giStretchMode = COLORONCOLOR;
  136. INT    giDmOrient = DMORIENT_PORTRAIT;
  137. INT    giNPrinters = 0;
  138.  
  139. HPALETTE        ghPal, ghPalOld;
  140.  
  141. double xFrom, xTo, yFrom, yTo, c1, c2;
  142. LONG   lxFrom, lxTo, lyFrom, lyTo, lc1, lc2;
  143.  
  144.  
  145.  
  146.  
  147. /******************************Public*Routine******************************\
  148. *
  149. * WinMain
  150. *
  151. \**************************************************************************/
  152.  
  153. int WINAPI WinMain(
  154.     HINSTANCE hInstance,
  155.     HINSTANCE hPrevInstance,
  156.     LPSTR lpCmdLine,
  157.     int nShowCmd)
  158. {
  159.     MSG    msg;
  160.  
  161.     ghModule = GetModuleHandle(NULL);
  162.     if (!InitializeApp(&giPen)) 
  163.     {
  164.         OutputDebugString("memory: InitializeApp failure!");
  165.         return 0;
  166.     }
  167.  
  168.     if (!(ghAccel = LoadAccelerators (ghModule, MAKEINTRESOURCE(ACCEL_ID))))
  169.         OutputDebugString("memory: Load Accel failure!");
  170.  
  171.  
  172.     while (GetMessage(&msg, NULL, 0, 0)) 
  173.     {
  174.         if (!TranslateAccelerator( ghwndMain, ghAccel, &msg) &&
  175.             !TranslateMDISysAccel( ghwndClient, &msg)) 
  176.         {
  177.             TranslateMessage(&msg);
  178.             DispatchMessage(&msg);
  179.         }
  180.     }
  181.  
  182.  
  183.     DeleteObject(ghPal);
  184.  
  185.     return 1;
  186.  
  187.     UNREFERENCED_PARAMETER(lpCmdLine);
  188.     UNREFERENCED_PARAMETER(nShowCmd);
  189.     UNREFERENCED_PARAMETER(hInstance);
  190.     UNREFERENCED_PARAMETER(hPrevInstance);
  191. }
  192.  
  193.  
  194. /***************************************************************************\
  195. * InitializeApp
  196. *
  197. \***************************************************************************/
  198.  
  199. BOOL InitializeApp(INT *piPen)
  200. {
  201.     WNDCLASS wc;
  202.     HDC      hDC;
  203.  
  204. #ifdef THRDONE
  205.     INT      iNumClr;
  206. #endif
  207.  
  208.     wc.style            = CS_OWNDC;
  209.     wc.lpfnWndProc      = (WNDPROC)MainWndProc;
  210.     wc.cbClsExtra       = 0;
  211.     wc.cbWndExtra       = sizeof(LONG);
  212.     wc.hInstance        = ghModule;
  213.     wc.hIcon            = LoadIcon(ghModule, MAKEINTRESOURCE(APPICON));
  214.     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  215.     wc.hbrBackground    = (HBRUSH)(COLOR_APPWORKSPACE);
  216.     wc.lpszMenuName     = "MainMenu";
  217.     wc.lpszClassName    = "MandelClass";
  218.  
  219.     if (!RegisterClass(&wc))
  220.     return FALSE;
  221.  
  222.     wc.lpfnWndProc      = (WNDPROC)ChildWndProc;
  223.     wc.hIcon            = LoadIcon(ghModule, MAKEINTRESOURCE(APPICON));
  224.     wc.lpszMenuName     = NULL;
  225.     wc.lpszClassName    = "ChildClass";
  226.  
  227.     if (!RegisterClass(&wc))
  228.     return FALSE;
  229.  
  230.     wc.lpfnWndProc      = (WNDPROC)ViewerWndProc;
  231.     wc.hIcon            = LoadIcon(ghModule, MAKEINTRESOURCE(VIEWICON));
  232.     wc.lpszMenuName     = NULL;
  233.     wc.lpszClassName    = "ViewerClass";
  234.  
  235.     if (!RegisterClass(&wc))
  236.     return FALSE;
  237.  
  238.     wc.style            = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  239.     wc.lpfnWndProc      = (WNDPROC)TextWndProc;
  240.     wc.hIcon            = NULL;
  241.     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  242.     wc.hbrBackground    = (HBRUSH)(COLOR_BTNSHADOW);
  243.     wc.lpszMenuName     = NULL;
  244.     wc.lpszClassName    = "Text";
  245.  
  246.     if (!RegisterClass(&wc))
  247.         return FALSE;
  248.  
  249.     wc.style            = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  250.     wc.lpfnWndProc      = (WNDPROC)JuliaWndProc;
  251.     wc.hIcon            = NULL;
  252.  
  253.     //
  254.     // Nope.  Can't have this, screw up my Paint Can cursor
  255.     //
  256.     //wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  257.  
  258.     wc.hCursor          = NULL;
  259.     wc.hbrBackground    = (HBRUSH)(COLOR_BACKGROUND);
  260.     wc.lpszMenuName     = NULL;
  261.     wc.lpszClassName    = "Julia";
  262.  
  263.     if (!RegisterClass(&wc))
  264.         return FALSE;
  265.  
  266.     wc.style            = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  267.     wc.lpfnWndProc      = (WNDPROC)ViewSurfWndProc;
  268.     wc.hIcon            = NULL;
  269.     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
  270.     wc.hbrBackground    = (HBRUSH)(COLOR_BACKGROUND);
  271.     wc.lpszMenuName     = NULL;
  272.     wc.lpszClassName    = "View";
  273.  
  274.     if (!RegisterClass(&wc))
  275.         return FALSE;
  276.  
  277.  
  278.     //
  279.     // Notice, submenu is zero-based
  280.     //
  281.     hMenu       = LoadMenu(ghModule, "MainMenu");
  282.     hChildMenu  = LoadMenu(ghModule, "ChildMenu");
  283.     hViewMenu   = LoadMenu(ghModule, "ViewMenu");
  284.     hViewSubOne = GetSubMenu(hViewMenu, 1);
  285.     hSubMenuOne = GetSubMenu(hMenu, 1);
  286.     hSubMenuThree = GetSubMenu(hChildMenu, 8);
  287.     hPrinterMenu = GetSubMenu(hChildMenu, 7);
  288.  
  289.     //
  290.     // Disable color-cycling for display devices that does not support
  291.     // palette like the VGA.  As as 29-May-1992, the MIPS display driver
  292.     // is the only one that supports palette
  293.     //
  294.     hDC = GetDC(NULL);
  295.     if (!((GetDeviceCaps(hDC, RASTERCAPS)) & RC_PALETTE)) {
  296.     EnableMenuItem(hChildMenu, MM_CYCLE, MF_GRAYED);
  297.     }
  298.  
  299. #ifdef THRDONE
  300.  
  301.     if ((iNumClr = iCreatePenFrPal(hDC, NULL, 0, &ghPal)) != 0) 
  302.     {
  303.         sprintf( gtext,"iNumClr = %d\n", iNumClr);
  304.         OutputDebugString( gtext);
  305.  
  306.         if ((pInfo->prghPen = (PVOID*) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(HPEN)*iNumClr)) == NULL) 
  307.             OutputDebugString ("Failed in Memory Allocation for pInfo->prghPen!");
  308.         else 
  309.             if ((*piPen = iCreatePenFrPal(hDC, pInfo->prghPen, 0, &ghPal)) == 0)
  310.                 OutputDebugString("Failed in creating pen!");
  311.     }
  312.  
  313. #endif
  314.     ReleaseDC(NULL, hDC);
  315.  
  316.     ghwndMain = CreateWindowEx(0L, "MandelClass", 
  317.                                GetStringRes (IDS_MANDEL_DREAM),
  318.  
  319.         WS_OVERLAPPED   | WS_CAPTION     | WS_BORDER       |
  320.         WS_THICKFRAME   | WS_MAXIMIZEBOX | WS_MINIMIZEBOX  |
  321.         WS_CLIPCHILDREN | WS_VISIBLE     | WS_SYSMENU,
  322.         80, 70, 550, 400 /* 550 */,
  323.         NULL, hMenu, ghModule, NULL);
  324.  
  325.     if (ghwndMain == NULL)
  326.     return FALSE;
  327.  
  328.     bInitPrinter(ghwndMain);
  329.  
  330.     SetWindowLong(ghwndMain, GWL_USERDATA, 0L);
  331.  
  332.     SetFocus(ghwndMain);    /* set initial focus */
  333.  
  334.     PostMessage(ghwndMain, WM_COMMAND, MM_MANDEL, 0L);
  335.     PostMessage(ghwndMain, WM_COMMAND, MM_CREATE_MANDEL_THREAD, 0L);
  336.  
  337.     return TRUE;
  338. }
  339.  
  340.  
  341. /******************************Public*Routine******************************\
  342. *
  343. * MainWndProc
  344. *
  345. \**************************************************************************/
  346.  
  347. long APIENTRY MainWndProc(
  348.     HWND hwnd,
  349.     UINT message,
  350.     DWORD wParam,
  351.     LONG lParam)
  352. {
  353.     static int         iJuliaCount=1;
  354.     static int         iMandelCount=1;
  355.     static int         iViewerCount=1;
  356.     CLIENTCREATESTRUCT clientcreate;
  357.     HWND               hwndChildWindow;
  358.     static FARPROC     lpfnSuspendThrd, lpfnResumeThrd;
  359.  
  360.  
  361.     switch (message) {
  362.  
  363.       case WM_CREATE:
  364.     SetWindowLong(hwnd, 0, (LONG)NULL);
  365.  
  366.     clientcreate.hWindowMenu  = hSubMenuOne;
  367.     clientcreate.idFirstChild = 1;
  368.  
  369.     ghwndClient = CreateWindow("MDICLIENT", NULL,
  370.                     WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
  371.                     0,0,0,0,
  372.                     hwnd, NULL, ghModule, (LPVOID)&clientcreate);
  373.     lpfnSuspendThrd = (FARPROC)MakeProcInstance (SuspendDrawThrd, ghModule);
  374.     lpfnResumeThrd  = (FARPROC)MakeProcInstance (ResumeDrawThrd, ghModule);
  375.  
  376.     return 0L;
  377.  
  378.       case WM_DESTROY: {
  379.     bCleanupPrinter();
  380.     PostQuitMessage(0);
  381.     return 0L;
  382.       }
  383.  
  384.       //
  385.       // Wait! User is going to zero out our app's visible region.  This
  386.       // is going to mess up our drawing (we are not keeping any shadow
  387.       // bitmap in this version yet.) So, let's suspend our drawing thread
  388.       // first before user does that.  We will resume after user is done.
  389.       //
  390.       case WM_SYSCOMMAND: {
  391.     LONG        lResult;
  392.  
  393.     //
  394.     // We'll enumerate our children and suspend their drawing thread.
  395.     //
  396.     EnumChildWindows(ghwndClient, (WNDENUMPROC)lpfnSuspendThrd, lParam);
  397.  
  398.     //
  399.     // Now, let user does it supposed to do
  400.     //
  401.     lResult = DefFrameProc(hwnd,  ghwndClient, message, wParam, lParam);
  402.  
  403.     //
  404.     // User's done, we'll resume the suspended threads in our children
  405.     //
  406.     EnumChildWindows(ghwndClient, (WNDENUMPROC)lpfnResumeThrd, lParam);
  407.  
  408.     return lResult;
  409.     break;
  410.       }
  411. #if 0
  412.       //
  413.       // Our window's size is going to change, we'll make sure the new
  414.       // window is a square.
  415.       //
  416.       case WM_WINDOWPOSCHANGING: {
  417.         PWINDOWPOS pWndPos;
  418.         RECT       rect;
  419.         LONG       lcx, lcy;
  420.  
  421.         GetWindowRect(hwnd, &rect);
  422.         lcx = rect.right-rect.left;
  423.         lcy = rect.bottom-rect.top;
  424.         pWndPos = (PWINDOWPOS)lParam;
  425.         if ((pWndPos->cy > lcy) || (pWndPos->cx > lcx))
  426.         pWndPos->cx =  pWndPos->cy =
  427.            ((pWndPos->cx > pWndPos->cy) ? pWndPos->cy : pWndPos->cx);
  428.         else if ((pWndPos->cy < lcy) || (pWndPos->cx < lcx))
  429.              pWndPos->cx =  pWndPos->cy =
  430.             ((pWndPos->cx > pWndPos->cy) ? pWndPos->cy : pWndPos->cx);
  431.         break;
  432.       }
  433. #endif
  434.  
  435.       case WM_COMMAND:
  436.  
  437.     switch (LOWORD(wParam)) {
  438.         case IDM_TILE:
  439.         SendMessage(ghwndClient, WM_MDITILE, 0L, 0L);
  440.         return 0L;
  441.         case IDM_CASCADE:
  442.         SendMessage(ghwndClient, WM_MDICASCADE, 0L, 0L);
  443.         return 0L;
  444.         case IDM_ARRANGE:
  445.         SendMessage(ghwndClient, WM_MDIICONARRANGE, 0L, 0L);
  446.         return 0L;
  447.  
  448.         //
  449.         // Create Julia or Mandelbrot set
  450.         //
  451.         case MM_JULIA:
  452.         case MM_MANDEL: {
  453.         HANDLE hInfo;
  454.         PINFO  pInfo;
  455.         MDICREATESTRUCT mdicreate;
  456.  
  457.         hInfo = LocalAlloc(LHND, (WORD) sizeof(INFO));
  458.         if (hInfo == NULL) 
  459.         {
  460.             OutputDebugString("Failed to Allocate Info!");
  461.             return 0L;
  462.         }
  463.         if ((pInfo = (PINFO)LocalLock(hInfo)) == NULL) 
  464.         {
  465.             OutputDebugString("Failed in LocalLock, hInfo");
  466.             return 0L;
  467.         }
  468.  
  469.         bInitInfo(pInfo);
  470.         wsprintf((LPSTR) &(pInfo->CaptionBarText),
  471.              (LOWORD(wParam) == MM_JULIA) ? 
  472.              GetStringRes (IDS_JULIA): 
  473.              GetStringRes (IDS_MANDELBROT),
  474.              (LOWORD(wParam) == MM_JULIA) ? iJuliaCount : iMandelCount);
  475.         if (LOWORD(wParam) == MM_JULIA) {
  476.             c1 = 0.360284;
  477.             c2 = 0.100376;
  478.             lc1 = 738;          //.3603515
  479.             lc2 = 206;          //.1005859
  480.             pInfo->bMandel = FALSE;
  481.         } else {
  482.             pInfo->bMandel = TRUE;
  483.         }
  484.  
  485.         //
  486.         // Fill in the MDICREATE structure for MDI child creation
  487.         //
  488.         mdicreate.szClass = "ChildClass";
  489.         mdicreate.szTitle = (LPTSTR)&(pInfo->CaptionBarText);
  490.         mdicreate.hOwner  = ghModule;
  491.         mdicreate.x       =
  492.         mdicreate.y       = CW_USEDEFAULT;
  493.         mdicreate.cx      = 300;
  494.         mdicreate.cy      = 300;
  495.         mdicreate.style   = 0L;
  496.         mdicreate.lParam  = (LONG) hInfo;
  497.  
  498.         /*Create Child Window*/
  499.         hwndChildWindow =
  500.             (HANDLE) SendMessage(ghwndClient, WM_MDICREATE,
  501.                 0L,
  502.                 (LONG)(LPMDICREATESTRUCT)&mdicreate);
  503.  
  504.         if (hwndChildWindow == NULL) 
  505.         {
  506.             OutputDebugString ("Failed in Creating Child Window");
  507.             return 0L;
  508.         }
  509.  
  510.         (LOWORD(wParam) == MM_JULIA) ? iJuliaCount++ : iMandelCount++ ;
  511.         LocalUnlock(hInfo);
  512.         return ((LONG)hwndChildWindow);
  513.         }
  514.  
  515.         case MM_RLEVIEWER: {
  516.         HANDLE hInfo;
  517.         PINFO  pInfo;
  518.         MDICREATESTRUCT mdicreate;
  519.  
  520.         hInfo = LocalAlloc(LHND, (WORD) sizeof(INFO));
  521.         if (hInfo == NULL) 
  522.         {
  523.             OutputDebugString ("Failed to Allocate Info!");
  524.             return 0L;
  525.         }
  526.         if ((pInfo = (PINFO)LocalLock(hInfo)) == NULL) 
  527.         {
  528.             OutputDebugString ("Failed in LocalLock, hInfo");
  529.             return 0L;
  530.         }
  531.  
  532.         bInitInfo(pInfo);
  533.         wsprintf((LPSTR) &(pInfo->CaptionBarText), GetStringRes (IDS_VIEWER), iViewerCount );
  534.  
  535.         //
  536.         // Fill in the MDICREATE structure for MDI child creation
  537.         //
  538.         mdicreate.szClass = "ViewerClass";
  539.         mdicreate.szTitle = (LPTSTR)&(pInfo->CaptionBarText);
  540.         mdicreate.hOwner  = ghModule;
  541.         mdicreate.x       =
  542.         mdicreate.y       = CW_USEDEFAULT;
  543.         mdicreate.cx      = 300;
  544.         mdicreate.cy      = 300;
  545.         mdicreate.style   = 0L;
  546.         mdicreate.lParam  = (LONG) hInfo;
  547.  
  548.         /*Create Child Window*/
  549.         hwndChildWindow =
  550.             (HANDLE) SendMessage(ghwndClient, WM_MDICREATE,
  551.                 0L,
  552.                 (LONG)(LPMDICREATESTRUCT)&mdicreate);
  553.  
  554.         if (hwndChildWindow == NULL) 
  555.         {
  556.             OutputDebugString ("Failed in Creating Child Window");
  557.             return 0L;
  558.         }
  559.  
  560.         iViewerCount++ ;
  561.         LocalUnlock(hInfo);
  562.         return ((LONG)hwndChildWindow);
  563.  
  564.         }
  565.  
  566.         case MM_ABOUT:
  567.         if (DialogBox(ghModule, "AboutBox", ghwndMain, (DLGPROC)About) == -1)
  568.            OutputDebugString ("DEMO: About Dialog Creation Error!");
  569.         return 0L;
  570.  
  571.         //
  572.         // Only my children know how to deal with these messages, so
  573.         // pass these to children for processing
  574.         //
  575.         case MM_CREATE_JULIA_THREAD:
  576.         case MM_SET_XFORM_ATTR:
  577.         case MM_CREATE_MANDEL_THREAD:
  578.         case MM_OPT_4:              // currently not used
  579.         case MM_DRAW_SET:
  580.         case MM_SETDIB2DEVICE:
  581.         case MM_BW:
  582.         case MM_SHIFT:
  583.         case MM_CUSTOM:
  584.         case MM_CYCLE:
  585.         case MM_TP_IDLE:
  586.         case MM_TP_LOW:
  587.         case MM_TP_BELOW_NORMAL:
  588.         case MM_TP_NORMAL:
  589.         case MM_TP_ABOVE_NORMAL:
  590.         case MM_TP_HIGH:
  591.         case MM_TP_TIME_CRITICAL:
  592.         case MM_FLOAT:
  593.         case MM_FIX:
  594.         case MM_ITERATION_100:
  595.         case MM_ITERATION_500:
  596.         case MM_ITERATION_1000:
  597.         case MM_ITERATION_5000:
  598.         case MM_ITERATION_DOUBLE:
  599.         case MM_STEP_ONE:
  600.         case MM_STEP_TWO:
  601.         case MM_STEP_THREE:
  602.         case MM_SAVE:
  603.         case MM_SAVE_MONO:
  604.         case MM_LOAD:
  605.         case MM_STRETCHBLT:
  606.         case MM_BITBLT:
  607.         case MM_BLACKONWHITE:
  608.         case MM_COLORONCOLOR:
  609.         case MM_WHITEONBLACK:
  610.         case MM_HALFTONE:
  611.         case MM_CLIP:
  612.         case MM_RM_CLIP:
  613.         case MM_SELCLIPRGN:
  614.         case MM_ERASE:
  615.         case MM_PORTRAIT:
  616.         case MM_LANDSCAPE:
  617.         case MM_PRINTER:
  618.         case MM_PRINTER + 1:
  619.         case MM_PRINTER + 2:
  620.         case MM_PRINTER + 3:
  621.         case MM_PRINTER + 4:
  622.         case MM_PRINTER + 5:
  623.         case MM_PRINTER + 6:
  624.         case MM_PRINTER + 7:
  625.         case MM_PRINTER + 8:
  626.         case MM_PRINTER + 9:
  627.         case MM_RLELOAD_DEMO:
  628.         case MM_RLEPLAYCONT:
  629.         case MM_RLELOAD:
  630.         case MM_RLESAVE:
  631.         case MM_CLEAR:
  632.         case MM_RLEPLAY:
  633.         {
  634.         HWND hActiveChild;
  635.  
  636.         hActiveChild = (HANDLE) SendMessage(ghwndClient, WM_MDIGETACTIVE, 0L, 0L);
  637.         if (hActiveChild)
  638.             SendMessage(hActiveChild, WM_COMMAND, wParam, lParam);
  639.         return 0L;
  640.         }
  641.  
  642.         default:
  643.         return DefFrameProc(hwnd,  ghwndClient, message, wParam, lParam);
  644.     }
  645.     default:
  646.  
  647.     return DefFrameProc(hwnd,  ghwndClient, message, wParam, lParam);
  648.     }
  649. }
  650.  
  651. /***************************************************************************\
  652. * ChildWndProc
  653. *
  654. \***************************************************************************/
  655.  
  656. long APIENTRY ChildWndProc(
  657.     HWND hwnd,
  658.     UINT message,
  659.     DWORD wParam,
  660.     LONG lParam)
  661. {
  662.     static FARPROC     lpfnSuspendThrd, lpfnResumeThrd;
  663.     static BOOL        bDIB2Device = FALSE;
  664.  
  665.     sprintf( gtext,"message = %lx\n", message);
  666.     OutputDebugString( gtext);
  667.  
  668.     switch (message) {
  669.     case WM_COMMAND: {
  670.       PINFO       pInfo;
  671.       HWND        hTextWnd;
  672.  
  673.       switch (LOWORD(wParam)) {
  674.         //
  675.         // Create a Julia drawing thread
  676.         //
  677.         case MM_CREATE_JULIA_THREAD: {
  678.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  679.             return 0L;
  680.         }
  681.  
  682.         hTextWnd = pInfo->hTextWnd;
  683.         sprintf( gtext,"(%g, %g) <-> (%g, %g)", pInfo->xFrom, pInfo->yFrom, pInfo->xTo, pInfo->yTo);
  684.         SetWindowText(hTextWnd, gtext);
  685.         sprintf( gtext,"(c1 = %g, c2 = %g)\n\n", pInfo->c1, pInfo->c2);
  686.         OutputDebugString( gtext );
  687.  
  688.         if (pInfo->hThrd)
  689.             CloseHandle(pInfo->hThrd);
  690.  
  691.         pInfo->hThrd = CreateThread(NULL, 0,
  692.                  (gFloat ? (LPTHREAD_START_ROUTINE)StartDraw : (LPTHREAD_START_ROUTINE)StartDrawFix),
  693.                  pInfo,
  694.                  STANDARD_RIGHTS_REQUIRED,
  695.                  &pInfo->dwThreadId );
  696.  
  697.            if (pInfo->hThrd && pInfo->bDrawing) 
  698.            {
  699.                if (!SetThreadPriority(pInfo->hThrd, pInfo->iPriority))
  700.                  OutputDebugString ("Can't set Priority!");
  701.            }
  702.  
  703.            bReleaseInfoData(hwnd);
  704.            return 0L;
  705.         }
  706.  
  707.         //
  708.         // Reset pInfo reflecting new transformation
  709.         //
  710.         case MM_SET_XFORM_ATTR: {
  711.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  712.             return 0L;
  713.         }
  714.  
  715.         hTextWnd = pInfo->hTextWnd;
  716.         SetWindowText(hTextWnd, GetStringRes (IDS_CLICK_HERE_VIEW));
  717.  
  718.         pInfo->xFrom      = xFrom;
  719.         pInfo->xTo        = xTo;
  720.         pInfo->yFrom      = yFrom;
  721.         pInfo->yTo        = yTo;
  722.         pInfo->c1         = c1;
  723.         pInfo->c2         = c2;
  724.         pInfo->lxFrom      = lxFrom;
  725.         pInfo->lxTo        = lxTo;
  726.         pInfo->lyFrom      = lyFrom;
  727.         pInfo->lyTo        = lyTo;
  728.         pInfo->lc1         = lc1;
  729.         pInfo->lc2         = lc2;
  730.  
  731.            bReleaseInfoData(hwnd);
  732.            return 0L;
  733.         }
  734.  
  735.         //
  736.         // Create a Mandelbrot drawing thread
  737.         //
  738.         case MM_CREATE_MANDEL_THREAD: {
  739.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  740.             return 0L;
  741.         }
  742.  
  743.         hTextWnd = pInfo->hTextWnd;
  744.         sprintf( gtext,"(%g, %g) <-> (%g, %g)", pInfo->xFrom, pInfo->yFrom, pInfo->xTo, pInfo->yTo);
  745.         SetWindowText(hTextWnd, gtext);
  746.         sprintf( gtext,"(c1 = %g, c2 = %g)\n\n", pInfo->c1, pInfo->c2);
  747.         OutputDebugString( gtext );
  748.  
  749.         if (pInfo->hThrd)
  750.             CloseHandle(pInfo->hThrd);
  751.  
  752.         pInfo->hThrd = CreateThread(NULL, 0,
  753.                  (gFloat ? (LPTHREAD_START_ROUTINE)StartMandelbrot : (LPTHREAD_START_ROUTINE)StartMandelbrotFix),
  754.                  pInfo,
  755.                  STANDARD_RIGHTS_REQUIRED,
  756.                  &pInfo->dwThreadId );
  757.  
  758.            if (pInfo->hThrd && pInfo->bDrawing) 
  759.            {
  760.               if (!SetThreadPriority(pInfo->hThrd, pInfo->iPriority))
  761.                  OutputDebugString ("Can't set Priority!");
  762.            }
  763.  
  764.  
  765.            bReleaseInfoData(hwnd);
  766.            return 0L;
  767.         }
  768.  
  769.         //
  770.         // Create a Julia drawing thread using algorithm StartDraw2
  771.         // Currently not used
  772.         //
  773.         case MM_OPT_4: {
  774.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  775.             return 0L;
  776.         }
  777.  
  778.         hTextWnd = pInfo->hTextWnd;
  779.         SetWindowText(hTextWnd, "MM_OPT_4");
  780.  
  781.         sprintf( gtext,"xFrom = %g, xTo = %g, yFrom = %g, yTo = %g\n", pInfo->xFrom, pInfo->xTo, pInfo->yFrom, pInfo->yTo);
  782.         OutputDebugString( gtext );
  783.  
  784.         if (pInfo->hThrd)
  785.             CloseHandle(pInfo->hThrd);
  786.  
  787.         pInfo->hThrd = CreateThread(NULL, 0,
  788.                  (LPTHREAD_START_ROUTINE)StartDraw2,
  789.                  pInfo,
  790.                  STANDARD_RIGHTS_REQUIRED,
  791.                  &pInfo->dwThreadId );
  792.  
  793.            if (pInfo->hThrd && pInfo->bDrawing) 
  794.            {
  795.               if (!SetThreadPriority(pInfo->hThrd, pInfo->iPriority))
  796.                  OutputDebugString ("Can't set Priority!");
  797.            }
  798.  
  799.            bReleaseInfoData(hwnd);
  800.            return 0L;
  801.         }
  802.  
  803.         case MM_DRAW_SET: {
  804.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  805.             return 0L;
  806.         }
  807.  
  808.         PostMessage(hwnd, WM_COMMAND,
  809.             pInfo->bMandel ? (DWORD)((WORD)MM_CREATE_MANDEL_THREAD) : (DWORD)((WORD)MM_CREATE_JULIA_THREAD),
  810.             (LONG)0L);
  811.  
  812.            bReleaseInfoData(hwnd);
  813.            return 0L;
  814.         }
  815.  
  816.         {
  817.         int     iPriority;
  818.  
  819.         case MM_TP_IDLE:
  820.             if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  821.             return 0L;
  822.             }
  823.  
  824.             iPriority = THREAD_PRIORITY_IDLE;
  825.             bCheckMutexMenuItem(pInfo, hChildMenu, MM_TP_IDLE);
  826.             DrawMenuBar(GetParent(GetParent(hwnd))) ;
  827.             goto CWP_SET_PRIORITY;
  828.  
  829.         case MM_TP_LOW:
  830.             if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  831.             return 0L;
  832.             }
  833.  
  834.             iPriority = THREAD_PRIORITY_LOWEST;
  835.             bCheckMutexMenuItem(pInfo, hChildMenu, MM_TP_LOW);
  836.             DrawMenuBar(GetParent(GetParent(hwnd))) ;
  837.             goto CWP_SET_PRIORITY;
  838.  
  839.         case MM_TP_BELOW_NORMAL:
  840.             if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  841.             return 0L;
  842.             }
  843.  
  844.             iPriority = THREAD_PRIORITY_BELOW_NORMAL;
  845.             bCheckMutexMenuItem(pInfo, hChildMenu, MM_TP_BELOW_NORMAL);
  846.             DrawMenuBar(GetParent(GetParent(hwnd))) ;
  847.             goto CWP_SET_PRIORITY;
  848.  
  849.         case MM_TP_NORMAL:
  850.             if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  851.             return 0L;
  852.             }
  853.  
  854.             iPriority = THREAD_PRIORITY_NORMAL;
  855.             bCheckMutexMenuItem(pInfo, hChildMenu, MM_TP_NORMAL);
  856.             DrawMenuBar(GetParent(GetParent(hwnd))) ;
  857.             goto CWP_SET_PRIORITY;
  858.  
  859.         case MM_TP_ABOVE_NORMAL:
  860.             if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  861.             return 0L;
  862.             }
  863.  
  864.             iPriority = THREAD_PRIORITY_ABOVE_NORMAL;
  865.             bCheckMutexMenuItem(pInfo, hChildMenu, MM_TP_ABOVE_NORMAL);
  866.             DrawMenuBar(GetParent(GetParent(hwnd))) ;
  867.             goto CWP_SET_PRIORITY;
  868.  
  869.         case MM_TP_HIGH:
  870.             if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  871.             return 0L;
  872.             }
  873.  
  874.             iPriority = THREAD_PRIORITY_HIGHEST;
  875.             bCheckMutexMenuItem(pInfo, hChildMenu, MM_TP_HIGH);
  876.             DrawMenuBar(GetParent(GetParent(hwnd))) ;
  877.             goto CWP_SET_PRIORITY;
  878.  
  879.         case MM_TP_TIME_CRITICAL:
  880.             if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  881.             return 0L;
  882.             }
  883.  
  884.             iPriority = THREAD_PRIORITY_TIME_CRITICAL;
  885.             bCheckMutexMenuItem(pInfo, hChildMenu, MM_TP_TIME_CRITICAL);
  886.             DrawMenuBar(GetParent(GetParent(hwnd))) ;
  887.  
  888. CWP_SET_PRIORITY:
  889.             {
  890.                HANDLE       hThrd;
  891.  
  892.                hThrd = pInfo->hThrd;
  893.                pInfo->iPriority = iPriority;
  894.  
  895.                if (hThrd && pInfo->bDrawing) 
  896.                {
  897.                   if (!SetThreadPriority(hThrd, iPriority))
  898.                      OutputDebugString ("Can't set Priority!");
  899.                }
  900.  
  901.             }
  902.             bReleaseInfoData(hwnd);
  903.             return 0L;
  904.  
  905.         }
  906.  
  907.         case MM_FLOAT: {
  908.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  909.             return 0L;
  910.         }
  911.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_FLOAT);
  912.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  913.         gFloat = TRUE;
  914.         bReleaseInfoData(hwnd);
  915.         return 0L;
  916.         }
  917.         case MM_FIX: {
  918.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  919.             return 0L;
  920.         }
  921.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_FIX);
  922.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  923.         gFloat = FALSE;
  924.         bReleaseInfoData(hwnd);
  925.         return 0L;
  926.         }
  927.         case MM_ITERATION_100: {
  928.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  929.             return 0L;
  930.         }
  931.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_ITERATION_100);
  932.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  933.         gIteration = 100;
  934.         pInfo->iIteration = 100;
  935.         SetWindowText(pInfo->hTextWnd, GetStringRes (IDS_ITER_100));
  936.         bReleaseInfoData(hwnd);
  937.         return 0L;
  938.         }
  939.         case MM_ITERATION_500: {
  940.         if ((pInfo = pGetInfoData(hwnd)) == NULL){
  941.             return 0L;
  942.         }
  943.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_ITERATION_500);
  944.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  945.         gIteration = 500;
  946.  
  947.         pInfo->iIteration = 500;
  948.         SetWindowText(pInfo->hTextWnd, GetStringRes (IDS_ITER_500));
  949.         bReleaseInfoData(hwnd);
  950.         return 0L;
  951.         }
  952.         case MM_ITERATION_1000: {
  953.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  954.             return 0L;
  955.         }
  956.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_ITERATION_1000);
  957.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  958.         gIteration = 1000;
  959.         pInfo->iIteration = 1000;
  960.         SetWindowText(pInfo->hTextWnd, GetStringRes (IDS_ITER_1000));
  961.         bReleaseInfoData(hwnd);
  962.         return 0L;
  963.         }
  964.         case MM_ITERATION_5000: {
  965.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  966.             return 0L;
  967.         }
  968.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_ITERATION_5000);
  969.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  970.         gIteration = 5000;
  971.         pInfo->iIteration = 5000;
  972.         SetWindowText(pInfo->hTextWnd, GetStringRes (IDS_ITER_5000));
  973.         bReleaseInfoData(hwnd);
  974.         return 0L;
  975.         }
  976.         case MM_ITERATION_DOUBLE: {
  977.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  978.             return 0L;
  979.         }
  980.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_ITERATION_DOUBLE);
  981.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  982.         gIteration *= 2;
  983.         pInfo->iIteration = gIteration;
  984.         sprintf( gtext, GetStringRes (IDS_ITERATION), pInfo->iIteration);
  985.         SetWindowText(pInfo->hTextWnd, gtext);
  986.         bReleaseInfoData(hwnd);
  987.         return 0L;
  988.         }
  989.         case MM_STEP_ONE: {
  990.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  991.             return 0L;
  992.         }
  993.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_STEP_ONE);
  994.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  995.         gStep = 1;
  996.         pInfo->iStep = 1;
  997.  
  998.         bReleaseInfoData(hwnd);
  999.         return 0L;
  1000.         }
  1001.         case MM_STEP_TWO:  {
  1002.         if ((pInfo = pGetInfoData(hwnd)) == NULL){
  1003.             return 0L;
  1004.         }
  1005.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_STEP_TWO);
  1006.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1007.         gStep = 2;
  1008.         pInfo->iStep = 2;
  1009.  
  1010.         bReleaseInfoData(hwnd);
  1011.         return 0L;
  1012.         }
  1013.         case MM_STEP_THREE: {
  1014.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1015.             return 0L;
  1016.         }
  1017.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_STEP_THREE);
  1018.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1019.         gStep = 3;
  1020.         pInfo->iStep = 3;
  1021.  
  1022.         bReleaseInfoData(hwnd);
  1023.         return 0L;
  1024.         }
  1025.  
  1026.         case MM_LOAD: {
  1027.         HDC hDC;
  1028.         OPENFILENAME ofn;
  1029.         char szDirName[256];
  1030.         char szFile[256], szFileTitle[256];
  1031.         static char *szFilter;
  1032.         RECT    rc;
  1033.  
  1034.         if ((pInfo = pGetInfoData(hwnd)) == NULL){
  1035.             return 0L;
  1036.         }
  1037.  
  1038.         szFilter = GetStringRes (IDS_FILE_LIST1);
  1039.  
  1040.         GetSystemDirectory((LPSTR) szDirName, 256);
  1041.         strcpy(szFile, "*.bmp\0");
  1042.         ofn.lStructSize = sizeof(OPENFILENAME);
  1043.         ofn.hwndOwner = pInfo->hwnd;
  1044.         ofn.lpstrFilter = szFilter;
  1045.         ofn.lpstrCustomFilter = (LPSTR) NULL;
  1046.         ofn.nMaxCustFilter = 0L;
  1047.         ofn.nFilterIndex = 1;
  1048.         ofn.lpstrFile = szFile;
  1049.         ofn.nMaxFile = sizeof(szFile);
  1050.         ofn.lpstrFileTitle = szFileTitle;
  1051.         ofn.nMaxFileTitle = sizeof(szFileTitle);
  1052.         ofn.lpstrInitialDir = szDirName;
  1053.         ofn.lpstrTitle = (LPSTR) NULL;
  1054.         ofn.Flags = 0L;
  1055.         ofn.nFileOffset = 0;
  1056.         ofn.nFileExtension = 0;
  1057.         ofn.lpstrDefExt = "BMP";
  1058.  
  1059.         if (!GetOpenFileName(&ofn))
  1060.             return 0L;
  1061.  
  1062.         GetClientRect(pInfo->hwnd, &rc);
  1063.         hDC = GetDC(pInfo->hwnd);
  1064.         if (LoadBitmapFile(hDC, pInfo, szFile))
  1065.           bDrawDIB(hDC, pInfo, 0, 0, rc.right, rc.bottom);
  1066.         ReleaseDC(hwnd, hDC);
  1067.  
  1068.         bReleaseInfoData(hwnd);
  1069.  
  1070.         return 0L;
  1071.         }
  1072.  
  1073.         case MM_SAVE: {
  1074.         HDC hDC;
  1075.         OPENFILENAME ofn;
  1076.         char szDirName[256];
  1077.         char szFile[256], szFileTitle[256];
  1078.         static char *szFilter;
  1079.  
  1080.         szFilter = GetStringRes (IDS_FILE_LIST2);
  1081.  
  1082.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1083.             return 0L;
  1084.         }
  1085.         hDC = GetDC(pInfo->hwnd);
  1086. #if 0
  1087.         {
  1088.         HPALETTE hPalTmp;
  1089.  
  1090.         hPalTmp = CopyPalette(pInfo->hPal);
  1091.         DeleteObject(pInfo->hPal);
  1092.         pInfo->hPal = hPalTmp;
  1093.         }
  1094. #endif
  1095.         //
  1096.         // saving special effects user might have created in window
  1097.         //
  1098.         if (pInfo->hBmpSaved)
  1099.             DeleteObject(pInfo->hBmpSaved);
  1100.         pInfo->hBmpSaved = SaveBitmap(pInfo->hwnd, pInfo->hPal);
  1101.         pInfo->bUseDIB = FALSE;
  1102.  
  1103.         GetSystemDirectory((LPSTR) szDirName, 256);
  1104.         strcpy(szFile, "*.bmp\0");
  1105.         ofn.lStructSize = sizeof(OPENFILENAME);
  1106.         ofn.hwndOwner = pInfo->hwnd;
  1107.         ofn.lpstrFilter = szFilter;
  1108.         ofn.lpstrCustomFilter = (LPSTR) NULL;
  1109.         ofn.nMaxCustFilter = 0L;
  1110.         ofn.nFilterIndex = 0L;
  1111.         ofn.lpstrFile = szFile;
  1112.         ofn.nMaxFile = sizeof(szFile);
  1113.         ofn.lpstrFileTitle = szFileTitle;
  1114.         ofn.nMaxFileTitle = sizeof(szFileTitle);
  1115.         ofn.lpstrInitialDir = szDirName;
  1116.         ofn.lpstrTitle = (LPSTR) NULL;
  1117.         ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
  1118.         ofn.nFileOffset = 0;
  1119.         ofn.nFileExtension = 0;
  1120.         ofn.lpstrDefExt = (LPSTR)NULL;
  1121.  
  1122.         if (!GetSaveFileName(&ofn)) {
  1123.             ReleaseDC(pInfo->hwnd, hDC);
  1124.             bReleaseInfoData(hwnd);
  1125.             return 0L;
  1126.         }
  1127.  
  1128.         SelectPalette(hDC,
  1129.            ((pInfo->iStretchMode == HALFTONE) ? pInfo->hHTPal : pInfo->hPal),
  1130.            FALSE);
  1131.         RealizePalette(hDC);
  1132.         UpdateColors(hDC);
  1133.  
  1134.         //
  1135.         // test
  1136.         //
  1137.         ghPal = pInfo->hPal;
  1138.  
  1139.         SaveBitmapFile(hDC, pInfo->hBmpSaved, szFile);
  1140.  
  1141.         ReleaseDC(pInfo->hwnd, hDC);
  1142.  
  1143.         bReleaseInfoData(hwnd);
  1144.         return 0L;
  1145.         }
  1146.         case MM_SAVE_MONO: {
  1147.         HDC hDC;
  1148.         OPENFILENAME ofn;
  1149.         char szDirName[256];
  1150.         char szFile[256], szFileTitle[256];
  1151.         static char *szFilter;
  1152.  
  1153.         if ((pInfo = pGetInfoData(hwnd)) == NULL){
  1154.             return 0L;
  1155.         }
  1156.  
  1157.         szFilter = GetStringRes (IDS_FILE_LIST2);
  1158.  
  1159.         GetSystemDirectory((LPSTR) szDirName, 256);
  1160.         strcpy(szFile, "*.bmp\0");
  1161.         ofn.lStructSize = sizeof(OPENFILENAME);
  1162.         ofn.hwndOwner = pInfo->hwnd;
  1163.         ofn.lpstrFilter = szFilter;
  1164.         ofn.lpstrCustomFilter = (LPSTR) NULL;
  1165.         ofn.nMaxCustFilter = 0L;
  1166.         ofn.nFilterIndex = 0L;
  1167.         ofn.lpstrFile = szFile;
  1168.         ofn.nMaxFile = sizeof(szFile);
  1169.         ofn.lpstrFileTitle = szFileTitle;
  1170.         ofn.nMaxFileTitle = sizeof(szFileTitle);
  1171.         ofn.lpstrInitialDir = szDirName;
  1172.         ofn.lpstrTitle = GetStringRes (IDS_SAVING_MONO_BITMAP);
  1173.         ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
  1174.         ofn.nFileOffset = 0;
  1175.         ofn.nFileExtension = 0;
  1176.         ofn.lpstrDefExt = (LPSTR)NULL;
  1177.  
  1178.         if (!GetSaveFileName(&ofn))
  1179.             return 0L;
  1180.  
  1181.         hDC = GetDC(pInfo->hwnd);
  1182.  
  1183.         SaveBitmapFile(hDC, pInfo->hBmpMono, szFile);
  1184.         ReleaseDC(pInfo->hwnd, hDC);
  1185.  
  1186.         bReleaseInfoData(hwnd);
  1187.         return 0L;
  1188.         }
  1189.         case MM_STRETCHBLT: {
  1190.         if ((pInfo = pGetInfoData(hwnd)) == NULL){
  1191.             return 0L;
  1192.         }
  1193.         gbStretch = TRUE;
  1194.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_STRETCHBLT);
  1195.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1196.         pInfo->bStretch = gbStretch;
  1197.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  1198.  
  1199.         bReleaseInfoData(hwnd);
  1200.         return 0L;
  1201.  
  1202.         }
  1203.         case MM_BITBLT: {
  1204.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1205.             return 0L;
  1206.         }
  1207.         gbStretch = FALSE;
  1208.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_BITBLT);
  1209.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1210.         pInfo->bStretch = gbStretch;
  1211.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  1212.  
  1213.         bReleaseInfoData(hwnd);
  1214.         return 0L;
  1215.  
  1216.         }
  1217.         case MM_BLACKONWHITE: {
  1218.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1219.             return 0L;
  1220.         }
  1221.         giStretchMode = BLACKONWHITE;
  1222.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_BLACKONWHITE);
  1223.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1224.         pInfo->iStretchMode = giStretchMode;
  1225.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  1226.  
  1227.         bReleaseInfoData(hwnd);
  1228.         return 0L;
  1229.  
  1230.         }
  1231.         case MM_COLORONCOLOR: {
  1232.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1233.             return 0L;
  1234.         }
  1235.         giStretchMode = COLORONCOLOR;
  1236.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_COLORONCOLOR);
  1237.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1238.         pInfo->iStretchMode = giStretchMode;
  1239.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  1240.  
  1241.         bReleaseInfoData(hwnd);
  1242.         return 0L;
  1243.  
  1244.         }
  1245.         case MM_WHITEONBLACK: {
  1246.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1247.             return 0L;
  1248.         }
  1249.         giStretchMode = WHITEONBLACK;
  1250.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_WHITEONBLACK);
  1251.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1252.         pInfo->iStretchMode = giStretchMode;
  1253.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  1254.  
  1255.         bReleaseInfoData(hwnd);
  1256.         return 0L;
  1257.  
  1258.         }
  1259.         case MM_HALFTONE: {
  1260.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1261.             return 0L;
  1262.         }
  1263.         giStretchMode = HALFTONE;
  1264.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_HALFTONE);
  1265.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1266.         pInfo->iStretchMode = giStretchMode;
  1267.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  1268.  
  1269.         bReleaseInfoData(hwnd);
  1270.         return 0L;
  1271.         }
  1272.         case MM_SETDIB2DEVICE: {
  1273.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1274.             return 0L;
  1275.         }
  1276.         bDIB2Device = (bDIB2Device ? FALSE : TRUE);
  1277.         pInfo->bSetDIBsToDevice = bDIB2Device;
  1278.         CheckMenuItem(hChildMenu, MM_SETDIB2DEVICE, (bDIB2Device ? MF_CHECKED : MF_UNCHECKED));
  1279.         bReleaseInfoData(hwnd);
  1280.         return 0L;
  1281.         }
  1282.         case MM_BW: {
  1283.         HDC hDC;
  1284.  
  1285.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1286.             return 0L;
  1287.         }
  1288.         hDC = GetDC(pInfo->hwnd);
  1289.         bChangeDIBColor(hDC, pInfo, MM_BW);
  1290.         ReleaseDC(hwnd, hDC);
  1291.         bReleaseInfoData(hwnd);
  1292.         return 0L;
  1293.         }
  1294.         case MM_SHIFT: {
  1295.         HDC hDC;
  1296.  
  1297.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1298.             return 0L;
  1299.         }
  1300.         hDC = GetDC(pInfo->hwnd);
  1301.         bChangeDIBColor(hDC, pInfo, MM_SHIFT);
  1302.         ReleaseDC(hwnd, hDC);
  1303.         bReleaseInfoData(hwnd);
  1304.         return 0L;
  1305.         }
  1306.         case MM_CUSTOM: {
  1307.         static DWORD argbCust[16] = {
  1308.             RGB(255, 255, 255), RGB(255, 255, 255),
  1309.             RGB(255, 255, 255), RGB(255, 255, 255),
  1310.             RGB(255, 255, 255), RGB(255, 255, 255),
  1311.             RGB(255, 255, 255), RGB(255, 255, 255),
  1312.             RGB(255, 255, 255), RGB(255, 255, 255),
  1313.             RGB(255, 255, 255), RGB(255, 255, 255),
  1314.             RGB(255, 255, 255), RGB(255, 255, 255),
  1315.             RGB(255, 255, 255), RGB(255, 255, 255)
  1316.         };
  1317.         CHOOSECOLOR cc;
  1318.         BOOL bResult;
  1319.         DWORD rgbOld;
  1320.         HBRUSH hBrush;
  1321.         HDC hDC;
  1322.  
  1323.         rgbOld = RGB(255, 255, 255);
  1324.         cc.lStructSize = sizeof(CHOOSECOLOR);
  1325.         cc.hwndOwner = ghwndMain;
  1326.         cc.hInstance = ghModule;
  1327.         cc.rgbResult = rgbOld;
  1328.         cc.lpCustColors = argbCust;
  1329.         cc.Flags = CC_RGBINIT | CC_SHOWHELP;
  1330.         cc.lCustData = 0;
  1331.         cc.lpfnHook = NULL;
  1332.         cc.lpTemplateName = NULL;
  1333.  
  1334.         bResult = ChooseColor(&cc);
  1335.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1336.             return 0L;
  1337.         }
  1338.         if (bResult) {
  1339.             hDC = GetDC(pInfo->hwnd);
  1340.             hBrush = hBrCreateBrush(hDC, cc.rgbResult);
  1341.             ReleaseDC(pInfo->hwnd, hDC);
  1342.             if (pInfo->hBrush)
  1343.             DeleteObject(pInfo->hBrush);
  1344.             pInfo->hBrush = hBrush;
  1345.             pInfo->bFill = TRUE;
  1346.         }
  1347.         bReleaseInfoData(hwnd);
  1348.         return 0L;
  1349.         }
  1350.  
  1351. #ifndef CYCLETHRD
  1352.         case MM_CYCLE: {
  1353.         HDC hDC;
  1354.  
  1355.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1356.             return 0L;
  1357.         }
  1358.         hDC = GetDC(pInfo->hwnd);
  1359.  
  1360.         if (pInfo->bClrCycle) {
  1361.             CheckMenuItem(hChildMenu, MM_CYCLE, MF_UNCHECKED);
  1362.             pInfo->bClrCycle = FALSE;
  1363.         } else {
  1364.             CheckMenuItem(hChildMenu, MM_CYCLE, MF_CHECKED);
  1365.             pInfo->bClrCycle = TRUE;
  1366.             bChangeDIBColor(hDC, pInfo, MM_CYCLE);
  1367.         }
  1368.  
  1369.         ReleaseDC(hwnd, hDC);
  1370.         bReleaseInfoData(hwnd);
  1371.         return 0L;
  1372.         }
  1373. #else
  1374.  
  1375.         case MM_CYCLE: {
  1376.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1377.             return 0L;
  1378.         }
  1379.  
  1380.         if (pInfo->bFirstTime) 
  1381.         {
  1382.             if (!SetEvent(pInfo->hQuitEvent)) 
  1383.             {
  1384.                 OutputDebugString ("Can't set Quit Event!");
  1385.                 return 0L;
  1386.             }
  1387.  
  1388.             if (pInfo->hCycleThrd)
  1389.             CloseHandle(pInfo->hCycleThrd);
  1390.  
  1391.             pInfo->hCycleThrd = CreateThread(NULL, 0,
  1392.                      (LPTHREAD_START_ROUTINE)bCycle,
  1393.                      (LPVOID)hwnd,
  1394.                      STANDARD_RIGHTS_REQUIRED,
  1395.                      &pInfo->dwCycleThrdID );
  1396.             pInfo->bClrCycle = TRUE;
  1397.             pInfo->bFirstTime = FALSE;
  1398.             CheckMenuItem(hChildMenu, MM_CYCLE, MF_CHECKED);
  1399.         } else {
  1400.             if (pInfo->bClrCycle) {
  1401.             CheckMenuItem(hChildMenu, MM_CYCLE, MF_UNCHECKED);
  1402.             pInfo->bClrCycle = FALSE;
  1403.             pInfo->dwSuspend = SuspendThread(pInfo->hCycleThrd);
  1404.             } else {
  1405.             CheckMenuItem(hChildMenu, MM_CYCLE, MF_CHECKED);
  1406.             pInfo->bClrCycle = TRUE;
  1407.             pInfo->dwSuspend = ResumeThread(pInfo->hCycleThrd);
  1408.             }
  1409.             if (pInfo->dwSuspend == -1) {
  1410.             (pInfo->bClrCycle ?
  1411.              sprintf( gtext,"Error in resuming thread\n") :
  1412.              sprintf( gtext,"Error in suspending thread\n")  );
  1413.             OutputDebugString( gtext );
  1414.             }
  1415.         }
  1416.  
  1417.         bReleaseInfoData(hwnd);
  1418.         return 0L;
  1419.         }
  1420. #endif
  1421.         case MM_CLIP: {
  1422.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1423.             return 0L;
  1424.         }
  1425.  
  1426.         hTextWnd = pInfo->hTextWnd;
  1427.         sprintf( gtext,"(%g, %g) <-> (%g, %g)", pInfo->xFrom, pInfo->yFrom, pInfo->xTo, pInfo->yTo);
  1428.         SetWindowText(hTextWnd, gtext);
  1429.         sprintf( gtext,"(c1 = %g, c2 = %g)\n\n", pInfo->c1, pInfo->c2);
  1430.         OutputDebugString( gtext );
  1431.         if (!pInfo->bMandel) 
  1432.         {
  1433.             MessageBox(ghwndMain, 
  1434.                        GetStringRes (IDS_BOUNDARY),
  1435.                        NULL, MB_OK);
  1436.             return 0L;
  1437.         }
  1438.  
  1439.         if (pInfo->hThrd)
  1440.             CloseHandle(pInfo->hThrd);
  1441.  
  1442.         pInfo->hThrd = CreateThread(NULL, 0,
  1443.                  (gFloat ? (LPTHREAD_START_ROUTINE)bBoundaryScanFix : (LPTHREAD_START_ROUTINE)bBoundaryScanFix),
  1444.                  pInfo,
  1445.                  STANDARD_RIGHTS_REQUIRED,
  1446.                  &pInfo->dwThreadId );
  1447.  
  1448.            bReleaseInfoData(hwnd);
  1449.            return 0L;
  1450.         }
  1451.         case MM_RM_CLIP: {
  1452.         HDC     hDC;
  1453.  
  1454.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1455.             return 0L;
  1456.         }
  1457.  
  1458.         hDC = GetDC(pInfo->hwnd);
  1459.         SelectClipRgn(hDC, (HRGN) NULL);
  1460.         ReleaseDC(pInfo->hwnd, hDC);
  1461.         bReleaseInfoData(hwnd);
  1462.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  1463.         return 0L;
  1464.  
  1465.         }
  1466.         case MM_SELCLIPRGN: {
  1467.         HDC     hDC;
  1468.  
  1469.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1470.             return 0L;
  1471.         }
  1472.         hDC = GetDC(pInfo->hwnd);
  1473.  
  1474.         if (pInfo->hRgnPath != (HRGN) NULL) {
  1475.             SelectClipRgn(hDC, pInfo->hRgnPath);
  1476.         }
  1477.  
  1478.         ReleaseDC(pInfo->hwnd, hDC);
  1479.         bReleaseInfoData(hwnd);
  1480.         return 0L;
  1481.         }
  1482.         case MM_ERASE: {
  1483.         HDC     hDC;
  1484.         RECT    rc;
  1485.  
  1486.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1487.             return 0L;
  1488.         }
  1489.         hDC = GetDC(pInfo->hwnd);
  1490.         if (pInfo->hRgnPath != (HRGN) NULL) {
  1491.             SelectClipRgn(hDC, pInfo->hRgnPath);
  1492.         }
  1493.         SelectObject(hDC, GetStockObject(WHITE_BRUSH));
  1494.         GetClientRect(pInfo->hwnd, &rc);
  1495.         PatBlt(hDC, 0, 0, rc.right, rc.bottom, PATCOPY);
  1496.         ReleaseDC(pInfo->hwnd, hDC);
  1497.         bReleaseInfoData(hwnd);
  1498.         return 0L;
  1499.         }
  1500.         case MM_PORTRAIT: {
  1501.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1502.             return 0L;
  1503.         }
  1504.  
  1505.         giDmOrient = DMORIENT_PORTRAIT;
  1506.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_PORTRAIT);
  1507.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1508.         bReleaseInfoData(hwnd);
  1509.         return 0L;
  1510.         }
  1511.         case MM_LANDSCAPE: {
  1512.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1513.             return 0L;
  1514.         }
  1515.  
  1516.         giDmOrient = DMORIENT_LANDSCAPE;
  1517.         bCheckMutexMenuItem(pInfo, hChildMenu, MM_LANDSCAPE);
  1518.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1519.         bReleaseInfoData(hwnd);
  1520.         return 0L;
  1521.         }
  1522.         case MM_PRINTER:
  1523.         case MM_PRINTER + 1:
  1524.         case MM_PRINTER + 2:
  1525.         case MM_PRINTER + 3:
  1526.         case MM_PRINTER + 4:
  1527.         case MM_PRINTER + 5:
  1528.         case MM_PRINTER + 6:
  1529.         case MM_PRINTER + 7:
  1530.         case MM_PRINTER + 8:
  1531.  
  1532. #ifdef PRTTHRD
  1533.         case MM_PRINTER + 9: {
  1534.         PINFO       pInfo;
  1535.         PRTDATA     PrtData, *pPrtData;
  1536.         ULONG       sizINFO;
  1537.         PBYTE       pjTmpInfo, pjTmp;
  1538.  
  1539.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1540.             return 0L;
  1541.         }
  1542.  
  1543.         if (pInfo->hBmpSaved == NULL) 
  1544.         {
  1545.             MessageBox(ghwndMain, 
  1546.                        GetStringRes (IDS_NO_SAVED_BITMAP),
  1547.                        NULL, MB_OK);
  1548.             return 0L;
  1549.         }
  1550.  
  1551.         //
  1552.         // Copy the info structure to PrtData
  1553.         //
  1554.         pPrtData = &PrtData;
  1555.         pjTmp    = (PBYTE)&(pPrtData->info);
  1556.         pjTmpInfo = (PBYTE)pInfo;
  1557.         sizINFO = sizeof(INFO);
  1558.  
  1559.         while(sizINFO--)
  1560.         {
  1561.             *(((PBYTE)pjTmp)++) = *((pjTmpInfo)++);
  1562.         }
  1563.  
  1564.         PrtData.index = LOWORD(wParam) - MM_PRINTER;
  1565.  
  1566.         if (giDmOrient == DMORIENT_PORTRAIT) {
  1567.             PrtData.bUseDefault = TRUE;
  1568.         } else {
  1569.             PrtData.bUseDefault = FALSE;
  1570.             PrtData.DevMode.dmSize = sizeof(DEVMODE);
  1571.             PrtData.DevMode.dmDriverExtra = 0;
  1572.             PrtData.DevMode.dmOrientation = DMORIENT_LANDSCAPE;
  1573.             PrtData.DevMode.dmFields = DM_ORIENTATION;
  1574.         }
  1575.  
  1576.         if (pInfo->hPrtThrd)
  1577.             CloseHandle(pInfo->hPrtThrd);
  1578.  
  1579.         pInfo->hPrtThrd = CreateThread(NULL, 0,
  1580.                  (LPTHREAD_START_ROUTINE)bPrintBmp,
  1581.                  &PrtData,
  1582.                  STANDARD_RIGHTS_REQUIRED,
  1583.                  &pInfo->dwPrtThrdID );
  1584.  
  1585.         bReleaseInfoData(hwnd);
  1586.         return 0L;
  1587.         }
  1588.  
  1589. #else
  1590.         case MM_PRINTER + 9: {
  1591.         HDC         hdcPrinter, hDC;
  1592.         int         index;
  1593.         DEVMODE     devmode;
  1594.         DEVMODE     *pdevmode;
  1595.         PINFO       pInfo;
  1596.         int         iWidth, iHeight;
  1597.  
  1598.  
  1599.         index = LOWORD(wParam) - MM_PRINTER;
  1600.  
  1601.         if (giDmOrient == DMORIENT_PORTRAIT)
  1602.             pdevmode = NULL;
  1603.         else {
  1604.             pdevmode = &devmode;
  1605.             devmode.dmSize = sizeof(DEVMODE);
  1606.             devmode.dmDriverExtra = 0;
  1607.             devmode.dmOrientation = DMORIENT_LANDSCAPE;
  1608.             devmode.dmFields = DM_ORIENTATION;
  1609.         }
  1610.  
  1611.         if (!(hdcPrinter = CreateDC( "", gpszPrinterNames[index],
  1612.                          "", pdevmode)))
  1613.         {
  1614.             return(0L);
  1615.         }
  1616.  
  1617.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1618.             return 0L;
  1619.         }
  1620.  
  1621.         iWidth = GetDeviceCaps(hdcPrinter, HORZRES);
  1622.         iHeight = GetDeviceCaps(hdcPrinter, VERTRES);
  1623.  
  1624. // !!! Why is it necessary to save the image over again?  May not want to
  1625. //     do this because user may want to print the nice HT bitmap. So,
  1626. //     use the DIB src.
  1627. #if 0
  1628.         if (pInfo->hBmpSaved)
  1629.             DeleteObject(pInfo->hBmpSaved);
  1630.  
  1631.         pInfo->hBmpSaved = SaveBitmap(pInfo->hwnd, pInfo->hPal);
  1632. #endif
  1633.         Escape(hdcPrinter, STARTDOC, 20, "Mandelbrot", NULL);
  1634.         bDrawDIB(hdcPrinter, pInfo, 0, 0, iWidth, iHeight);
  1635.         Escape(hdcPrinter, NEWFRAME, 0, NULL, NULL);
  1636.         Escape(hdcPrinter, ENDDOC, 0, NULL, NULL);
  1637.         ReleaseDC(pInfo->hwnd, hDC);
  1638.         bReleaseInfoData(hwnd);
  1639.         DeleteDC(hdcPrinter);
  1640.         return 0L;
  1641.         }
  1642. #endif
  1643.         default:
  1644.            return 0L;
  1645.  
  1646.       }
  1647.  
  1648.     }
  1649.     case WM_SETFOCUS:
  1650.         break;
  1651.  
  1652.     case WM_MDIACTIVATE: {
  1653.         PINFO       pInfo;
  1654.  
  1655.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1656.         return 0L;
  1657.         }
  1658.  
  1659.         if ((HWND) lParam == hwnd) {                // being activated
  1660.         SendMessage(GetParent(hwnd), WM_MDISETMENU,
  1661.                 (DWORD)  hChildMenu,
  1662.                 (LONG)   hSubMenuThree) ;
  1663.  
  1664.         (pInfo->bClrCycle ?
  1665.             CheckMenuItem(hChildMenu, MM_CYCLE, MF_CHECKED) :
  1666.             CheckMenuItem(hChildMenu, MM_CYCLE, MF_UNCHECKED) );
  1667.  
  1668.         vChkMenuItem(pInfo, hChildMenu, MF_CHECKED);
  1669.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1670.         goto MDI_ACT_EXIT;
  1671.         }
  1672.  
  1673.         if ((HWND) wParam == hwnd) {                // being deactivated
  1674.  
  1675.         vChkMenuItem(pInfo, hChildMenu, MF_UNCHECKED);
  1676.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1677.         }
  1678. MDI_ACT_EXIT:
  1679.         bReleaseInfoData(hwnd);
  1680.         return 0L;
  1681.     }
  1682.  
  1683.     case WM_QUERYNEWPALETTE:
  1684.     case WM_PALETTECHANGED: {
  1685.         PINFO       pInfo;
  1686.  
  1687.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1688.         return 0L;
  1689.         }
  1690.  
  1691.         SendMessage(pInfo->hwnd, message, wParam, lParam);
  1692.         bReleaseInfoData(hwnd);
  1693.         return 0L;
  1694.     }
  1695.  
  1696. #if 0
  1697.     case WM_WINDOWPOSCHANGING: {
  1698.         PWINDOWPOS  pWndPos;
  1699.         PINFO       pInfo;
  1700.         HWND        hTextWnd;
  1701.         int         iCyText, iCxBorder, iCyBorder, iCyCaption;
  1702.         RECT        rect, rcl;
  1703.         LONG        lcx, lcy;
  1704.  
  1705.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1706.         break;
  1707.         }
  1708.  
  1709.         hTextWnd = pInfo->hTextWnd;
  1710.  
  1711.         bReleaseInfoData(hwnd);
  1712.  
  1713.         iCyText = GetWindowLong(hTextWnd, GWL_USERDATA);
  1714.         iCxBorder = GetSystemMetrics(SM_CXBORDER);
  1715.         iCyBorder = GetSystemMetrics(SM_CYBORDER);
  1716.         iCyCaption = GetSystemMetrics(SM_CYCAPTION) - iCyBorder;
  1717.         GetClientRect(GetParent(hwnd), &rcl);
  1718.         GetWindowRect(hwnd, &rect);
  1719.         lcx = rect.right-rect.left;
  1720.         lcy = rect.bottom-rect.top;
  1721.         pWndPos = (PWINDOWPOS)lParam;
  1722.         if ((pWndPos->cy > lcy) || (pWndPos->cx > lcx)) {
  1723.         pWndPos->cx =
  1724.            ((pWndPos->cx > pWndPos->cy) ? pWndPos->cy-iCyText : pWndPos->cx);
  1725.         pWndPos->cy = pWndPos->cx + iCyText;
  1726.         } else { if ((pWndPos->cy < lcy) || (pWndPos->cx < lcx)) {
  1727.              pWndPos->cx =
  1728.             ((pWndPos->cx > pWndPos->cy) ? pWndPos->cy-iCyText : pWndPos->cx);
  1729.              pWndPos->cy = pWndPos->cx + iCyText;
  1730.            }
  1731.         }
  1732.         break;
  1733.     }
  1734. #endif
  1735.     case WM_SIZE: {
  1736.         HANDLE      hThrd;
  1737.         PINFO       pInfo;
  1738.         HWND        hTextWnd, hJulia;
  1739.         BOOL        bMandel;
  1740.         WORD        wCx;
  1741.         int         iCyText;
  1742.  
  1743.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1744.         break;
  1745.         }
  1746.  
  1747.         hTextWnd = pInfo->hTextWnd;
  1748.         hJulia   = pInfo->hwnd;
  1749.         hThrd    = pInfo->hThrd;
  1750.         bMandel  = pInfo->bMandel;
  1751.         bReleaseInfoData(hwnd);
  1752.         iCyText = GetWindowLong(hTextWnd, GWL_USERDATA);
  1753.         wCx = (WORD) (HIWORD(lParam) - iCyText);
  1754.  
  1755.         MoveWindow(hJulia, 0, 0,
  1756.                LOWORD(lParam),
  1757.                wCx,
  1758.                TRUE);
  1759.  
  1760.         MoveWindow(hTextWnd,
  1761.                0,
  1762.                wCx,
  1763.                LOWORD(lParam),
  1764.                iCyText,
  1765.                TRUE);
  1766.  
  1767.         if (hThrd) {
  1768.         TerminateThread(hThrd, (DWORD)0L);
  1769.         /*
  1770.         PostMessage(hwnd, WM_COMMAND,
  1771.             bMandel ? (DWORD)((WORD)MM_CREATE_MANDEL_THREAD) : (DWORD)((WORD)MM_CREATE_JULIA_THREAD),
  1772.             (LONG)0L);
  1773.           */
  1774.         }
  1775.  
  1776.         break;
  1777.     }
  1778.  
  1779.     //
  1780.     // display info in the status window
  1781.     //
  1782.     case WM_USER+0xa: {
  1783.         PINFO       pInfo;
  1784.         static ULONG ulClick = 0;
  1785.         HWND        hTextWnd;
  1786.  
  1787.         ulClick++;
  1788.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1789.         return 0L;
  1790.         }
  1791.  
  1792.         hTextWnd = pInfo->hTextWnd;
  1793.         switch (ulClick % 6) {
  1794.         case 0: sprintf( gtext,"%g <= x <= %g, %g <= y <= %g", pInfo->xFrom, pInfo->xTo, pInfo->yTo, pInfo->yFrom);
  1795.             break;
  1796.         case 1: sprintf( gtext,"c1 = %g, c2 = %g", pInfo->c1, pInfo->c2);
  1797.             break;
  1798.         case 2: sprintf( gtext,
  1799.                          GetStringRes (IDS_ELAPSED_TIME),
  1800.                          (ULONG) pInfo->dwElapsed);
  1801.             break;
  1802.         case 3: sprintf( gtext,
  1803.                          GetStringRes (IDS_ITERATION),
  1804.                          pInfo->iIteration);
  1805.             break;
  1806.         case 4:    sprintf( gtext,
  1807.                          GetStringRes (IDS_STEP),
  1808.                          pInfo->iStep);
  1809.             break;
  1810.         case 5: 
  1811.                 (gFloat ? sprintf( gtext, GetStringRes (IDS_FLOATING_PT))
  1812.                         : sprintf( gtext, GetStringRes (IDS_FIXED_PT))) ;
  1813.             break;
  1814.  
  1815.         default: break;
  1816.         }
  1817.         SetWindowText(hTextWnd, gtext);
  1818.         bReleaseInfoData(hwnd);
  1819.         return 0L;
  1820.     }
  1821.  
  1822.     case WM_SYSCOMMAND: {
  1823.         LONG        lResult;
  1824.  
  1825.         EnumChildWindows(ghwndClient, (WNDENUMPROC)lpfnSuspendThrd, lParam);
  1826.  
  1827.         lResult = DefMDIChildProc(hwnd, message, wParam, lParam);
  1828.  
  1829.         EnumChildWindows(ghwndClient, (WNDENUMPROC)lpfnResumeThrd, lParam);
  1830.  
  1831.         return lResult;
  1832.         break;
  1833.     }
  1834.  
  1835.     case WM_CREATE: {
  1836.         PINFO           pInfo;
  1837.         HANDLE          hInfo;
  1838.         HWND            hTextWnd, hJulia;
  1839.         RECT            rcl;
  1840.  
  1841.         //
  1842.         // CR! MakeProcInstance is noop!
  1843.         //
  1844.         lpfnSuspendThrd = (FARPROC)MakeProcInstance (SuspendDrawThrd, ghModule);
  1845.         lpfnResumeThrd  = (FARPROC)MakeProcInstance (ResumeDrawThrd, ghModule);
  1846.  
  1847.         hTextWnd = CreateWindow("Text", NULL,
  1848.                     WS_BORDER | SS_LEFT | WS_CHILD | WS_VISIBLE,
  1849.                     0, 0, 0, 0,
  1850.                     hwnd,
  1851.                     (HMENU) 2,
  1852.                     ghModule,
  1853.                     NULL);
  1854.  
  1855.         GetClientRect(hwnd, &rcl);
  1856.         hJulia = CreateWindow("Julia", (LPSTR) NULL,
  1857.               WS_CHILD      | WS_VISIBLE     |
  1858.               WS_BORDER,
  1859.               0,0, rcl.right-rcl.left,
  1860.               rcl.bottom-rcl.top-GetWindowLong(hTextWnd, GWL_USERDATA),
  1861.               hwnd, (HMENU)1, ghModule, (LPVOID)NULL);
  1862.  
  1863.         SetWindowText(hTextWnd, GetStringRes (IDS_SELECT_DRAW_SET));
  1864.  
  1865.         hInfo = (HANDLE) ((LPMDICREATESTRUCT) ((LPCREATESTRUCT) lParam)->lpCreateParams)->lParam ;
  1866.         if (hInfo) {
  1867.         if ((pInfo = (PINFO)LocalLock(hInfo)) == NULL) 
  1868.         {
  1869.             OutputDebugString ("Failed in LocalLock, hNode");
  1870.             break;
  1871.         } 
  1872.         else 
  1873.         {
  1874.             HDC hDC;
  1875.  
  1876.             if (!GetClientRect(hwnd, &pInfo->rcClient))
  1877.                 OutputDebugString ("Failed in GetClientRect!");
  1878.  
  1879.             pInfo->hTextWnd = hTextWnd;
  1880.             pInfo->hwnd = hJulia;
  1881.             hDC = GetDC(hJulia);
  1882.             pInfo->hHTPal = CreateHalftonePalette(hDC);
  1883.             ReleaseDC(hJulia, hDC);
  1884. #ifdef CYCLETHRD
  1885.             //
  1886.             // Creating a signal quit color cycling event
  1887.             //
  1888.             if ((pInfo->hQuitEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) == NULL)
  1889.                 OutputDebugString ("Failed in creating Quit Event!");
  1890. #endif
  1891.             SetWindowLong(hwnd, 0, (LONG) hInfo);
  1892.             LocalUnlock(hInfo);
  1893.         }
  1894.         } 
  1895.         else 
  1896.         {
  1897.             OutputDebugString ("Can't allocate hInfo!");
  1898.         }
  1899.  
  1900. #if 0
  1901.         //
  1902.         // Initialize printers here will detect printers availiability
  1903.         // more often, but kind of overkill.
  1904.         //
  1905.         bInitPrinter(hwnd);
  1906. #endif
  1907.         break;
  1908.     }
  1909.  
  1910.     case WM_CLOSE: {
  1911.         SendMessage(GetParent(hwnd), WM_MDISETMENU,
  1912.                 (DWORD) hMenu,
  1913.                 (LONG)  hSubMenuOne) ;
  1914.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  1915.         break;
  1916.     }
  1917.  
  1918.     case WM_DESTROY: {
  1919.         PINFO            pInfo;
  1920.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1921.         break;
  1922.         }
  1923.  
  1924.         if (pInfo->hThrd) {
  1925.         TerminateThread(pInfo->hThrd, (DWORD)0L);
  1926.         CloseHandle(pInfo->hThrd);
  1927.         }
  1928.         if (pInfo->hPrtThrd) {
  1929.         TerminateThread(pInfo->hPrtThrd, (DWORD)0L);
  1930.         CloseHandle(pInfo->hPrtThrd);
  1931.         }
  1932.         if (pInfo->hCycleThrd) {
  1933.         TerminateThread(pInfo->hCycleThrd, (DWORD)0L);
  1934.         CloseHandle(pInfo->hCycleThrd);
  1935.         }
  1936.  
  1937.  
  1938. #ifdef CYCLETHRD
  1939.         //
  1940.         // Cleanup color cycling
  1941.         //
  1942.         if (!ResetEvent(pInfo->hQuitEvent))
  1943.             OutputDebugString ("Failed in reseting quit event!");
  1944. #endif
  1945.         if (pInfo->hBmpMono)
  1946.         DeleteObject(pInfo->hBmpMono);
  1947.  
  1948.         if (pInfo->hBmpSaved)
  1949.         DeleteObject(pInfo->hBmpSaved);
  1950.  
  1951.         if (pInfo->hBrush)
  1952.         DeleteObject(pInfo->hBrush);
  1953.  
  1954.         bReleaseInfoData(hwnd);
  1955.         LocalFree((HANDLE) GetWindowLong(hwnd, 0));
  1956.         break;
  1957.     }
  1958.  
  1959.     default:
  1960.         return DefMDIChildProc(hwnd, message, wParam, lParam);
  1961.  
  1962.     } //switch
  1963.     return DefMDIChildProc(hwnd, message, wParam, lParam);
  1964. }
  1965.  
  1966. /******************************Public*Routine******************************\
  1967. *
  1968. * ViewerWndProc
  1969. *
  1970. * Effects:
  1971. *
  1972. * Warnings:
  1973. *
  1974. \**************************************************************************/
  1975.  
  1976. LONG APIENTRY ViewerWndProc(
  1977.     HWND hwnd,
  1978.     UINT message,
  1979.     DWORD wParam,
  1980.     LONG lParam)
  1981. {
  1982.     static FARPROC     lpfnSuspendThrd, lpfnResumeThrd;
  1983.  
  1984.     switch (message) {
  1985.     case WM_COMMAND: {
  1986.       PINFO       pInfo;
  1987.       HWND        hTextWnd;
  1988.  
  1989.       switch (LOWORD(wParam)) {
  1990.         case MM_RLELOAD_DEMO: {
  1991.         HDC             hDC;
  1992.         char            szDirName[256];
  1993.         char            szFile[400];
  1994.         HWND            hViewSurf;
  1995.  
  1996.         GetCurrentDirectory(256, (LPTSTR) szDirName);
  1997.  
  1998.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  1999.             return 0L;
  2000.         }
  2001.  
  2002.         if ((hViewSurf = pInfo->hwnd) == NULL)
  2003.             return 0L;
  2004.  
  2005.         hTextWnd = pInfo->hTextWnd;
  2006.         sprintf( gtext,"Loading bitmap(s) into memory");
  2007.         SetWindowText(hTextWnd, gtext);
  2008.  
  2009.         hDC = GetDC(hViewSurf);
  2010.         strcpy(szFile, szDirName);
  2011.         strcat(szFile, "\\rsc\\julia.rle");
  2012.  
  2013.         if (bStoreRleFile(hDC, pInfo, szFile)) {
  2014.             pInfo->RleData.ulFiles++;
  2015.             PostMessage(ghwndMain, WM_COMMAND, MM_RLEPLAYCONT, 0L);
  2016.         }
  2017.  
  2018.         ReleaseDC(hViewSurf, hDC);
  2019.  
  2020.         bReleaseInfoData(hwnd);
  2021.         return 0L;
  2022.  
  2023.         }
  2024.  
  2025.  
  2026.         case MM_RLELOAD: {
  2027.         HDC             hDC;
  2028.         OPENFILENAME    ofn;
  2029.         char            szDirName[256];
  2030.         char            szFile[256], szFileTitle[256];
  2031.         static char     *szFilter;
  2032.         RECT            rc;
  2033.         HWND            hViewSurf;
  2034.  
  2035.         szFilter = GetStringRes (IDS_FILE_LIST1);
  2036.  
  2037.         GetSystemDirectory((LPSTR) szDirName, 256);
  2038.         strcpy(szFile, "*.bmp\0");
  2039.         ofn.lStructSize = sizeof(OPENFILENAME);
  2040.         ofn.hwndOwner = hwnd;
  2041.         ofn.lpstrFilter = szFilter;
  2042.         ofn.lpstrCustomFilter = (LPSTR) NULL;
  2043.         ofn.nMaxCustFilter = 0L;
  2044.         ofn.nFilterIndex = 1;
  2045.         ofn.lpstrFile = szFile;
  2046.         ofn.nMaxFile = sizeof(szFile);
  2047.         ofn.lpstrFileTitle = szFileTitle;
  2048.         ofn.nMaxFileTitle = sizeof(szFileTitle);
  2049.         ofn.lpstrInitialDir = szDirName;
  2050.         ofn.lpstrTitle = (LPSTR) NULL;
  2051.         ofn.Flags = 0L;
  2052.         ofn.nFileOffset = 0;
  2053.         ofn.nFileExtension = 0;
  2054.         ofn.lpstrDefExt = "BMP";
  2055.  
  2056.         if (!GetOpenFileName(&ofn))
  2057.             return 0L;
  2058.  
  2059.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2060.             return 0L;
  2061.         }
  2062.  
  2063.         if ((hViewSurf = pInfo->hwnd) == NULL)
  2064.             return 0L;
  2065.  
  2066.         hTextWnd = pInfo->hTextWnd;
  2067.         sprintf( gtext, GetStringRes (IDS_LOADING_BITMAPS));
  2068.         SetWindowText(hTextWnd, gtext);
  2069.  
  2070.         GetClientRect(hwnd, &rc);
  2071.         hDC = GetDC(hViewSurf);
  2072.         if (bStoreRleFile(hDC, pInfo, szFile))
  2073.             pInfo->RleData.ulFiles++;
  2074.         ReleaseDC(hViewSurf, hDC);
  2075.  
  2076.         bReleaseInfoData(hwnd);
  2077.         return 0L;
  2078.  
  2079.         }
  2080.  
  2081.         case MM_RLESAVE: {
  2082.         HDC             hDC;
  2083.         OPENFILENAME    ofn;
  2084.         char            szDirName[256];
  2085.         char            szFile[256], szFileTitle[256];
  2086.         static char     *szFilter;
  2087.         HWND            hViewSurf;
  2088.  
  2089.         szFilter = GetStringRes (IDS_FILE_LIST3);
  2090.  
  2091.         GetSystemDirectory((LPSTR) szDirName, 256);
  2092.         strcpy(szFile, "*.rle\0");
  2093.         ofn.lStructSize = sizeof(OPENFILENAME);
  2094.         ofn.hwndOwner = hwnd;
  2095.         ofn.lpstrFilter = szFilter;
  2096.         ofn.lpstrCustomFilter = (LPSTR) NULL;
  2097.         ofn.nMaxCustFilter = 0L;
  2098.         ofn.nFilterIndex = 0L;
  2099.         ofn.lpstrFile = szFile;
  2100.         ofn.nMaxFile = sizeof(szFile);
  2101.         ofn.lpstrFileTitle = szFileTitle;
  2102.         ofn.nMaxFileTitle = sizeof(szFileTitle);
  2103.         ofn.lpstrInitialDir = szDirName;
  2104.         ofn.lpstrTitle = GetStringRes(IDS_SAVING_MEMORY_RLE); 
  2105.         ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
  2106.         ofn.nFileOffset = 0;
  2107.         ofn.nFileExtension = 0;
  2108.         ofn.lpstrDefExt = (LPSTR)NULL;
  2109.  
  2110.         if (!GetSaveFileName(&ofn))
  2111.             return 0L;
  2112.  
  2113.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2114.             return 0L;
  2115.         }
  2116.  
  2117.         if ((hViewSurf = pInfo->hwnd) == NULL)
  2118.             return 0L;
  2119.  
  2120.         hTextWnd = pInfo->hTextWnd;
  2121.         sprintf( gtext, GetStringRes (IDS_SAVING_LOADED_BMP)); 
  2122.         SetWindowText(hTextWnd, gtext);
  2123.  
  2124.         hDC = GetDC(hViewSurf);
  2125.         bSaveRleFile(hDC, pInfo, szFile);
  2126.         ReleaseDC(hViewSurf, hDC);
  2127.  
  2128.         bReleaseInfoData(hwnd);
  2129.         return 0L;
  2130.         }
  2131.  
  2132.         case MM_CLEAR: {
  2133.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2134.             return 0L;
  2135.         }
  2136.  
  2137.         hTextWnd = pInfo->hTextWnd;
  2138.         sprintf( gtext,GetStringRes (IDS_DISCARD_LOADED_BMP));
  2139.         SetWindowText(hTextWnd, gtext);
  2140.  
  2141.         bFreeRleFile(pInfo);
  2142.  
  2143.         bReleaseInfoData(hwnd);
  2144.         return 0L;
  2145.         }
  2146.  
  2147.         case MM_RLEPLAY: {
  2148.         HDC     hDC;
  2149.         HWND    hViewSurf;
  2150.  
  2151.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2152.             return 0L;
  2153.         }
  2154.  
  2155.         if ((hViewSurf = pInfo->hwnd) == NULL)
  2156.             return 0L;
  2157.  
  2158.         hTextWnd = pInfo->hTextWnd;
  2159.         sprintf( gtext, GetStringRes (IDS_PLAY_LOADED_BMP)); 
  2160.         SetWindowText(hTextWnd, gtext);
  2161.  
  2162.         hDC = GetDC(hViewSurf);
  2163.         EnableMenuItem(hViewSubOne, MM_CLEAR, MF_GRAYED);
  2164.  
  2165.         if (pInfo->hThrd0)
  2166.             CloseHandle(pInfo->hThrd0);
  2167.  
  2168.         pInfo->hThrd0 = CreateThread(NULL, 0,
  2169.                  (LPTHREAD_START_ROUTINE)bPlayRle,
  2170.                  pInfo,
  2171.                  STANDARD_RIGHTS_REQUIRED,
  2172.                  &pInfo->dwThreadId );
  2173.  
  2174.         if (pInfo->hThrd0) 
  2175.         {
  2176.             if (!SetThreadPriority(pInfo->hThrd0, THREAD_PRIORITY_BELOW_NORMAL))
  2177.                OutputDebugString ("Can't set Priority!");
  2178.         }
  2179.  
  2180.         //bPlayRle(hDC, pInfo);
  2181.         EnableMenuItem(hViewSubOne, MM_CLEAR, MF_ENABLED);
  2182.         ReleaseDC(hViewSurf, hDC);
  2183.  
  2184.         bReleaseInfoData(hwnd);
  2185.         return 0L;
  2186.         }
  2187.  
  2188.         case MM_RLEPLAYCONT: {
  2189.         HWND    hViewSurf;
  2190.  
  2191.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2192.             return 0L;
  2193.         }
  2194.  
  2195.         if ((hViewSurf = pInfo->hwnd) == NULL)
  2196.             return 0L;
  2197.  
  2198.         hTextWnd = pInfo->hTextWnd;
  2199.         sprintf( gtext, GetStringRes (IDS_PLAY_BMP_CONT));
  2200.         SetWindowText(hTextWnd, gtext);
  2201.  
  2202.         if (pInfo->bFirstTime) 
  2203.         {
  2204.             if (!SetEvent(pInfo->hQuitEvent)) 
  2205.             {
  2206.                 OutputDebugString ("Can't set Quit Event!");
  2207.                 return 0L;
  2208.             }
  2209.  
  2210.             EnableMenuItem(hViewSubOne, MM_CLEAR, MF_GRAYED);
  2211.  
  2212.             if (pInfo->hThrd)
  2213.             CloseHandle(pInfo->hThrd);
  2214.  
  2215.             pInfo->hThrd = CreateThread(NULL, 0,
  2216.                  (LPTHREAD_START_ROUTINE)bPlayRleCont2,
  2217.                  pInfo,
  2218.                  STANDARD_RIGHTS_REQUIRED,
  2219.                  &pInfo->dwThreadId );
  2220.  
  2221.             if (pInfo->hThrd) {
  2222.             if (!SetThreadPriority(pInfo->hThrd, THREAD_PRIORITY_BELOW_NORMAL))
  2223.                  OutputDebugString ("Can't set Priority!");
  2224.             }
  2225.  
  2226.             pInfo->bPlayRleCont = TRUE;
  2227.             pInfo->bFirstTime = FALSE;
  2228.             CheckMenuItem(hViewMenu, MM_RLEPLAYCONT, MF_CHECKED);
  2229.         } 
  2230.         else 
  2231.         {
  2232.             if (pInfo->bPlayRleCont) {
  2233.             EnableMenuItem(hViewSubOne, MM_CLEAR, MF_ENABLED);
  2234.             CheckMenuItem(hViewMenu, MM_RLEPLAYCONT, MF_UNCHECKED);
  2235.             pInfo->bPlayRleCont = FALSE;
  2236.             pInfo->dwSuspend = SuspendThread(pInfo->hThrd);
  2237.             } else {
  2238.             EnableMenuItem(hViewSubOne, MM_CLEAR, MF_GRAYED);
  2239.             CheckMenuItem(hViewMenu, MM_RLEPLAYCONT, MF_CHECKED);
  2240.             pInfo->bPlayRleCont = TRUE;
  2241.             pInfo->dwSuspend = ResumeThread(pInfo->hThrd);
  2242.             }
  2243.             if (pInfo->dwSuspend == -1) {
  2244.             (pInfo->bPlayRleCont ?
  2245.              sprintf( gtext,"Error in resuming thread\n") :
  2246.              sprintf( gtext,"Error in suspending thread\n")  );
  2247.             OutputDebugString( gtext );
  2248.             }
  2249.         }
  2250.  
  2251.         bReleaseInfoData(hwnd);
  2252.         return 0L;
  2253.         }
  2254.  
  2255.         default:
  2256.            return 0L;
  2257.  
  2258.       } //switch
  2259.  
  2260.     } // WM_COMMAND
  2261.     case WM_SETFOCUS:
  2262.         break;
  2263.  
  2264.     case WM_MDIACTIVATE: {
  2265.         PINFO       pInfo;
  2266.  
  2267.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2268.         return 0L;
  2269.         }
  2270.  
  2271.         if ((HWND) lParam == hwnd) {
  2272.         SendMessage(GetParent(hwnd), WM_MDISETMENU,
  2273.                 (WPARAM)  hViewMenu,
  2274.                 (LPARAM)  NULL) ;
  2275.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  2276.         }
  2277.  
  2278.         bReleaseInfoData(hwnd);
  2279.         return 0L;
  2280.     }
  2281.     case WM_QUERYNEWPALETTE:
  2282.     case WM_PALETTECHANGED: {
  2283.         PINFO       pInfo;
  2284.  
  2285.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2286.         return 0L;
  2287.         }
  2288.  
  2289.         SendMessage(pInfo->hwnd, message, wParam, lParam);
  2290.         bReleaseInfoData(hwnd);
  2291.         return 0L;
  2292.     }
  2293.  
  2294.     case WM_SIZE: {
  2295.         PINFO       pInfo;
  2296.         HWND        hTextWnd, hView;
  2297.         WORD        wCx;
  2298.         int         iCyText;
  2299.  
  2300.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2301.         break;
  2302.         }
  2303.  
  2304.         hTextWnd = pInfo->hTextWnd;
  2305.         hView    = pInfo->hwnd;
  2306.         bReleaseInfoData(hwnd);
  2307.         iCyText = GetWindowLong(hTextWnd, GWL_USERDATA);
  2308.         wCx = (WORD) (HIWORD(lParam) - iCyText);
  2309.  
  2310.         MoveWindow(hView, 0, 0,
  2311.                LOWORD(lParam),
  2312.                wCx,
  2313.                TRUE);
  2314.  
  2315.         MoveWindow(hTextWnd,
  2316.                0,
  2317.                wCx,
  2318.                LOWORD(lParam),
  2319.                iCyText,
  2320.                TRUE);
  2321.  
  2322.         break;
  2323.     }
  2324.  
  2325.     //
  2326.     // display info in the status window
  2327.     //
  2328.     case WM_USER+0xa: {
  2329.         PINFO       pInfo;
  2330.         static ULONG ulClick = 0;
  2331.         HWND        hTextWnd;
  2332.  
  2333.         ulClick++;
  2334.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2335.         return 0L;
  2336.         }
  2337.  
  2338.         hTextWnd = pInfo->hTextWnd;
  2339.         switch (ulClick % 4) {
  2340.         case 0: 
  2341.                 sprintf( gtext, GetStringRes (IDS_FRAMES)); 
  2342.             break;
  2343.         case 1: 
  2344.                 sprintf( gtext, GetStringRes (IDS_FRAMES));
  2345.             break;
  2346.         case 2: sprintf( gtext, (pInfo->bPlayRleCont ? 
  2347.                                    GetStringRes (IDS_CONT_PLAY) :
  2348.                                    GetStringRes (IDS_SINGLE_PLAY)));
  2349.             break;
  2350.         case 3: sprintf( gtext,"");
  2351.             break;
  2352.         default: break;
  2353.         }
  2354.         SetWindowText(hTextWnd, gtext);
  2355.         bReleaseInfoData(hwnd);
  2356.         return 0L;
  2357.     }
  2358.  
  2359.     case WM_SYSCOMMAND: {
  2360.         LONG        lResult;
  2361.  
  2362.         EnumChildWindows(ghwndClient, (WNDENUMPROC)lpfnSuspendThrd, lParam);
  2363.  
  2364.         lResult = DefMDIChildProc(hwnd, message, wParam, lParam);
  2365.  
  2366.         EnumChildWindows(ghwndClient, (WNDENUMPROC)lpfnResumeThrd, lParam);
  2367.  
  2368.         return lResult;
  2369.         break;
  2370.     }
  2371.  
  2372.     case WM_CREATE: {
  2373.         PINFO           pInfo;
  2374.         HANDLE          hInfo;
  2375.         HWND            hTextWnd, hView;
  2376.         RECT            rcl;
  2377.  
  2378.         //
  2379.         // CR! MakeProcInstance is noop!
  2380.         //
  2381.         lpfnSuspendThrd = (FARPROC)MakeProcInstance (SuspendDrawThrd, ghModule);
  2382.         lpfnResumeThrd  = (FARPROC)MakeProcInstance (ResumeDrawThrd, ghModule);
  2383.  
  2384.         hTextWnd = CreateWindow("Text", NULL,
  2385.                     WS_BORDER | SS_LEFT | WS_CHILD | WS_VISIBLE,
  2386.                     0, 0, 0, 0,
  2387.                     hwnd,
  2388.                     (HMENU) 2,
  2389.                     ghModule,
  2390.                     NULL);
  2391.  
  2392.         GetClientRect(hwnd, &rcl);
  2393.         hView = CreateWindow("View", (LPSTR) NULL,
  2394.               WS_CHILD      | WS_VISIBLE     |
  2395.               WS_BORDER,
  2396.               0,0, rcl.right-rcl.left,
  2397.               rcl.bottom-rcl.top-GetWindowLong(hTextWnd, GWL_USERDATA),
  2398.               hwnd, (HMENU)1, ghModule, (LPVOID)NULL);
  2399.  
  2400.         SetWindowText(hTextWnd, GetStringRes (IDS_SELECT_DRAW_SET));
  2401.         hInfo = (HANDLE) ((LPMDICREATESTRUCT) ((LPCREATESTRUCT) lParam)->lpCreateParams)->lParam ;
  2402.         if (hInfo) {
  2403.         if ((pInfo = (PINFO)LocalLock(hInfo)) == NULL) 
  2404.         {
  2405.             OutputDebugString ("Failed in LocalLock, hNode");
  2406.             break;
  2407.         } 
  2408.         else 
  2409.         {
  2410.             HDC hDC;
  2411.  
  2412.             if (!GetClientRect(hwnd, &pInfo->rcClient))
  2413.                 OutputDebugString ("Failed in GetClientRect!");
  2414.  
  2415.             pInfo->hTextWnd = hTextWnd;
  2416.             pInfo->hwnd = hView;
  2417.  
  2418.             hDC = GetDC(hView);
  2419.             pInfo->hHTPal = CreateHalftonePalette(hDC);
  2420.             ReleaseDC(hView, hDC);
  2421.  
  2422.             //
  2423.             // Creating a signal quit play continuous event
  2424.             //
  2425.             if ((pInfo->hQuitEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) == NULL)
  2426.                 OutputDebugString ("Failed in creating Quit Event!");
  2427.  
  2428.             SetWindowLong(hwnd, 0, (LONG) hInfo);
  2429.             LocalUnlock(hInfo);
  2430.         }
  2431.         } 
  2432.         else 
  2433.         {
  2434.             OutputDebugString ("Can't allocate hInfo!");
  2435.         }
  2436.  
  2437.         break;
  2438.     }
  2439.  
  2440.     case WM_CLOSE: {
  2441.         SendMessage(GetParent(hwnd), WM_MDISETMENU,
  2442.                 (DWORD) hMenu,
  2443.                 (LONG)  hSubMenuOne) ;
  2444.         DrawMenuBar(GetParent(GetParent(hwnd))) ;
  2445.         break;
  2446.     }
  2447.  
  2448.     case WM_DESTROY: {
  2449.         PINFO            pInfo;
  2450.         if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  2451.         break;
  2452.         }
  2453.  
  2454.         TerminateThread(pInfo->hThrd, (DWORD)0L);
  2455.         CloseHandle(pInfo->hThrd);
  2456.  
  2457.         //
  2458.         // Cleanup continuous play
  2459.         //
  2460.         if (!ResetEvent(pInfo->hQuitEvent))
  2461.             OutputDebugString ("Failed in reseting quit event!");
  2462.  
  2463.         bFreeRleFile(pInfo);
  2464.         bReleaseInfoData(hwnd);
  2465.         LocalFree((HANDLE) GetWindowLong(hwnd, 0));
  2466.         break;
  2467.     }
  2468.  
  2469.     default:
  2470.         return DefMDIChildProc(hwnd, message, wParam, lParam);
  2471.  
  2472.     } //switch
  2473.     return DefMDIChildProc(hwnd, message, wParam, lParam);
  2474. }
  2475.  
  2476. /******************************Public*Routine******************************\
  2477. *
  2478. * ViewSurfWndProc
  2479. *
  2480. * Effects:
  2481. *
  2482. * Warnings:
  2483. *
  2484. \**************************************************************************/
  2485.  
  2486. LONG APIENTRY ViewSurfWndProc (HWND hwnd, UINT message, DWORD wParam, LONG lParam)
  2487. {
  2488.     switch (message)
  2489.     {
  2490.        case WM_CREATE: {
  2491.         break;
  2492.        }
  2493.  
  2494.        case WM_DESTROY: {
  2495.         break;
  2496.        }
  2497.  
  2498.        case WM_QUERYNEWPALETTE: {
  2499.          HWND        hParent;
  2500.          PINFO       pInfo;
  2501.          HDC         hDC;
  2502.          UINT        i;
  2503.          HPALETTE    hOldPal;
  2504.  
  2505.          if ((hParent=GetParent(hwnd)) == NULL) 
  2506.          {
  2507.             OutputDebugString ("Can't get hParent!");
  2508.             return 0L;
  2509.          }
  2510.          if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2511.           return 0L;
  2512.          }
  2513.  
  2514.          // If palette realization causes a palette change,
  2515.          // we need to do a full redraw.
  2516.  
  2517.          hDC = GetDC (hwnd);
  2518.  
  2519.          hOldPal = SelectPalette (hDC,
  2520.                pInfo->RleData.hPal,
  2521.                0);
  2522.  
  2523.          i = RealizePalette(hDC);
  2524.  
  2525.          SelectPalette (hDC, hOldPal, 0);
  2526.          ReleaseDC (hwnd, hDC);
  2527.          bReleaseInfoData(hParent);
  2528.  
  2529.          if (i) {
  2530.          InvalidateRect (hwnd, (LPRECT) (NULL), TRUE);
  2531.          return TRUE;
  2532.          } else
  2533.          return FALSE;
  2534.  
  2535.        }
  2536.        case WM_PALETTECHANGED: {
  2537.          HWND        hParent;
  2538.          PINFO       pInfo;
  2539.          HDC         hDC;
  2540.          UINT        i;
  2541.          HPALETTE    hOldPal;
  2542.  
  2543.          if ((hParent=GetParent(hwnd)) == NULL) {
  2544.          MessageBox(ghwndMain, "Can't get hParent!", "Error", MB_OK);
  2545.          return 0L;
  2546.          }
  2547.          if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2548.           return 0L;
  2549.          }
  2550.  
  2551.          // if we were not responsible for palette change and if
  2552.          // palette realization causes a palette change, do a redraw.
  2553.  
  2554.          if ((HWND)wParam != hwnd){
  2555.         hDC = GetDC (hwnd);
  2556.  
  2557.         hOldPal = SelectPalette (hDC,
  2558.             pInfo->RleData.hPal,
  2559.             0);
  2560.  
  2561.         i = RealizePalette (hDC);
  2562.  
  2563.         if (i){
  2564.             UpdateColors (hDC);
  2565.         }
  2566.         SelectPalette (hDC, hOldPal, 0);
  2567.         ReleaseDC (hwnd, hDC);
  2568.         }
  2569.         bReleaseInfoData(hParent);
  2570.         break;
  2571.        }
  2572.  
  2573.        case WM_PAINT:
  2574.      {
  2575.          PAINTSTRUCT ps;
  2576.          HDC         hDC;
  2577.          RECT        rc;
  2578.  
  2579.          GetClientRect(hwnd,&rc);
  2580.          hDC = BeginPaint(hwnd, &ps);
  2581.          EndPaint(hwnd, &ps);
  2582.          return 0L;
  2583.      }
  2584.  
  2585.     } // switch
  2586.     return DefWindowProc(hwnd, message, wParam, lParam);
  2587. }
  2588.  
  2589. /***************************************************************************\
  2590. * About
  2591. *
  2592. * About dialog proc.
  2593. *
  2594. \***************************************************************************/
  2595.  
  2596. BOOL CALLBACK About(
  2597.     HWND hDlg,
  2598.     UINT message,
  2599.     DWORD wParam,
  2600.     LONG lParam)
  2601. {
  2602.     switch (message) {
  2603.     case WM_INITDIALOG:
  2604.     return TRUE;
  2605.  
  2606.     case WM_COMMAND:
  2607.     if (wParam == IDOK)
  2608.         EndDialog(hDlg, wParam);
  2609.     break;
  2610.     }
  2611.  
  2612.     return FALSE;
  2613.  
  2614.     UNREFERENCED_PARAMETER(lParam);
  2615.     UNREFERENCED_PARAMETER(hDlg);
  2616. }
  2617.  
  2618. /*************************************************************************
  2619. *
  2620. * TextWndProc
  2621. *
  2622. * Text Window proc.
  2623. *
  2624. \***************************************************************************/
  2625.  
  2626. LONG APIENTRY TextWndProc (HWND hwnd, UINT message, DWORD wParam, LONG lParam)
  2627. {
  2628.     static HFONT hFont = (HFONT) NULL;
  2629.  
  2630.     switch (message)
  2631.     {
  2632.     case WM_CREATE:
  2633.     {
  2634.         LOGFONT    lf;
  2635.         HDC        hDC;
  2636.         HFONT      hOldFont;
  2637.         TEXTMETRIC tm;
  2638.         RECT       rect;
  2639.         LONG       lHeight;
  2640.  
  2641.         SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (PVOID) &lf, FALSE);
  2642.  
  2643.         hDC = GetDC(hwnd);
  2644.         // this is the height for 8 point size font in pixels
  2645.         lf.lfHeight = 8 * GetDeviceCaps(hDC, LOGPIXELSY) / 72;
  2646.  
  2647.         hFont = CreateFontIndirect(&lf);
  2648.         hOldFont = SelectObject(hDC, hFont);
  2649.         GetTextMetrics(hDC, &tm);
  2650.         GetClientRect(GetParent(hwnd), &rect);
  2651.  
  2652.         // base the height of the window on size of text
  2653.         lHeight = tm.tmHeight+6*GetSystemMetrics(SM_CYBORDER)+2;
  2654.         // saved the height for later reference
  2655.         SetWindowLong(hwnd, GWL_USERDATA, lHeight);
  2656.         SetWindowPos(hwnd, NULL,
  2657.             0,
  2658.             rect.bottom-lHeight,
  2659.             rect.right-rect.left,
  2660.             lHeight,
  2661.             SWP_NOZORDER | SWP_NOMOVE);
  2662.  
  2663.         ReleaseDC(hwnd, hDC);
  2664.         break;
  2665.     }
  2666.  
  2667.     case WM_LBUTTONDOWN: {
  2668.     PostMessage(GetParent(hwnd), WM_USER+0xa, (DWORD)0L, (LONG)0L);
  2669.     break;
  2670.     }
  2671.  
  2672.     case WM_DESTROY:
  2673.         if (hFont)
  2674.         DeleteObject(hFont);
  2675.         break;
  2676.  
  2677.     case WM_SETTEXT:
  2678.         DefWindowProc(hwnd, message, wParam, lParam);
  2679.         InvalidateRect(hwnd,NULL,TRUE);
  2680.         UpdateWindow(hwnd);
  2681.         return 0L;
  2682.  
  2683.     case WM_PAINT:
  2684.     {
  2685.         PAINTSTRUCT ps;
  2686.         RECT   rc;
  2687.         char   ach[128];
  2688.         int    len, nxBorder, nyBorder;
  2689.         HFONT  hOldFont = NULL;
  2690.  
  2691.         BeginPaint(hwnd, &ps);
  2692.  
  2693.         GetClientRect(hwnd,&rc);
  2694.  
  2695.         nxBorder = GetSystemMetrics(SM_CXBORDER);
  2696.         rc.left  += 9*nxBorder;
  2697.         rc.right -= 9*nxBorder;
  2698.  
  2699.         nyBorder = GetSystemMetrics(SM_CYBORDER);
  2700.         rc.top    += 3*nyBorder;
  2701.         rc.bottom -= 3*nyBorder;
  2702.  
  2703.         // 3D Text
  2704.         len = GetWindowText(hwnd, ach, sizeof(ach));
  2705.         SetBkColor(ps.hdc, GetSysColor(COLOR_BTNFACE));
  2706.  
  2707.         SetBkMode(ps.hdc, TRANSPARENT);
  2708.         SetTextColor(ps.hdc, RGB(64,96,96));
  2709.         if (hFont)
  2710.         hOldFont = SelectObject(ps.hdc, hFont);
  2711.         ExtTextOut(ps.hdc, rc.left+2*nxBorder+2, rc.top+2, ETO_OPAQUE | ETO_CLIPPED,
  2712.             &rc, ach, len, NULL);
  2713.  
  2714.         SetTextColor(ps.hdc, RGB(128,128,128));
  2715.         if (hFont)
  2716.         hOldFont = SelectObject(ps.hdc, hFont);
  2717.         ExtTextOut(ps.hdc, rc.left+2*nxBorder+1, rc.top+1, ETO_CLIPPED,
  2718.             &rc, ach, len, NULL);
  2719.  
  2720.         SetTextColor(ps.hdc, RGB(255,255,255));
  2721.         if (hFont)
  2722.         hOldFont = SelectObject(ps.hdc, hFont);
  2723.         ExtTextOut(ps.hdc, rc.left+2*nxBorder, rc.top, ETO_CLIPPED,
  2724.             &rc, ach, len, NULL);
  2725.  
  2726.         SetBkMode(ps.hdc, OPAQUE);
  2727.  
  2728.         if (hOldFont)
  2729.         SelectObject(ps.hdc, hOldFont);
  2730.  
  2731.         EndPaint(hwnd, &ps);
  2732.         return 0L;
  2733.     }
  2734.     }
  2735.     return DefWindowProc(hwnd, message, wParam, lParam);
  2736. }
  2737.  
  2738.  
  2739. /**************************************************************************\
  2740. *
  2741. * JuliaWndProc
  2742. *
  2743. \**************************************************************************/
  2744.  
  2745. LONG APIENTRY JuliaWndProc (HWND hwnd, UINT message, DWORD wParam, LONG lParam)
  2746. {
  2747.     //
  2748.     // These statics are shared by all the Julia windows.  But, this is
  2749.     // fine because only one Julia window is tracking at any one time.
  2750.     // Ideally, we should place this in the per-window INFO data structure.
  2751.     // But, this is not necessary.
  2752.     //
  2753.     static BOOL    bTrack = FALSE;
  2754.     static int     OrgX, OrgY;
  2755.     static int     PrevX, PrevY;
  2756.     static HDC     hDC;
  2757.     static HCURSOR hCurArrow, hCurPaintCan;
  2758.  
  2759.     switch (message)
  2760.     {
  2761.        case WM_CREATE: {
  2762.  
  2763.         hpnRed     = CreatePen(PS_SOLID, 0, RGB(0xFF, 0,    0));
  2764.         hpnGreen   = CreatePen(PS_SOLID, 0, RGB(0,    0xFF, 0));
  2765.         hpnBlack   = CreatePen(PS_SOLID, 0, RGB(0,    0,    0));
  2766.  
  2767.         hCurPaintCan = LoadCursor(ghModule, MAKEINTRESOURCE(PAINTCURSOR));
  2768.         hCurArrow = LoadCursor(NULL, IDC_ARROW);
  2769.         break;
  2770.        }
  2771.  
  2772.        case WM_DESTROY: {
  2773.         HWND        hParent;
  2774.         PINFO       pInfo;
  2775.  
  2776.         DeleteObject(hpnRed);
  2777.         DeleteObject(hpnGreen);
  2778.         DeleteObject(hpnBlack);
  2779.  
  2780.         if ((hParent=GetParent(hwnd)) == NULL) 
  2781.         {
  2782.             OutputDebugString ("Can't get hParent!");
  2783.             break;
  2784.         }
  2785.         if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2786.         break;
  2787.         }
  2788.  
  2789.         // we might have open resource if we ever load bitmap in this wnd.
  2790.         bFreeRleFile(pInfo);
  2791.         bReleaseInfoData(hParent);
  2792.         break;
  2793.        }
  2794.  
  2795.        case WM_QUERYNEWPALETTE: {
  2796.          HWND        hParent;
  2797.          PINFO       pInfo;
  2798.          HDC         hDC;
  2799.          UINT        i;
  2800.          HPALETTE    hOldPal;
  2801.  
  2802.          if ((hParent=GetParent(hwnd)) == NULL) 
  2803.          {
  2804.             OutputDebugString ("Can't get hParent!");
  2805.             return 0L;
  2806.          }
  2807.          if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2808.           return 0L;
  2809.          }
  2810.  
  2811.          // If palette realization causes a palette change,
  2812.          // we need to do a full redraw.
  2813.  
  2814.          hDC = GetDC (hwnd);
  2815.  
  2816.          hOldPal = SelectPalette (hDC,
  2817.                ((pInfo->iStretchMode == HALFTONE) ? pInfo->hHTPal : pInfo->hPal),
  2818.                0);
  2819.  
  2820.          i = RealizePalette(hDC);
  2821.          SelectPalette (hDC, hOldPal, 0);
  2822.          ReleaseDC (hwnd, hDC);
  2823.          bReleaseInfoData(hParent);
  2824.  
  2825.          if (i) {
  2826.          InvalidateRect (hwnd, (LPRECT) (NULL), TRUE);
  2827.          return TRUE;
  2828.          } else
  2829.          return FALSE;
  2830.  
  2831.        }
  2832.        case WM_PALETTECHANGED: {
  2833.          HWND        hParent;
  2834.          PINFO       pInfo;
  2835.          HDC         hDC;
  2836.          UINT        i;
  2837.          HPALETTE    hOldPal;
  2838.  
  2839.          if ((hParent=GetParent(hwnd)) == NULL) {
  2840.             OutputDebugString ("Can't get hParent!");
  2841.             return 0L;
  2842.          }
  2843.          if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2844.           return 0L;
  2845.          }
  2846.  
  2847.          // if we were not responsible for palette change and if
  2848.          // palette realization causes a palette change, do a redraw.
  2849.  
  2850.          if ((HWND)wParam != hwnd){
  2851.         hDC = GetDC (hwnd);
  2852.  
  2853.         hOldPal = SelectPalette (hDC,
  2854.                ((pInfo->iStretchMode == HALFTONE) ? pInfo->hHTPal : pInfo->hPal),
  2855.             0);
  2856.  
  2857.         i = RealizePalette (hDC);
  2858.  
  2859.         if (i){
  2860.             UpdateColors (hDC);
  2861.         }
  2862.         SelectPalette (hDC, hOldPal, 0);
  2863.         ReleaseDC (hwnd, hDC);
  2864.         }
  2865.         bReleaseInfoData(hParent);
  2866.         break;
  2867.        }
  2868.  
  2869.        case WM_PAINT:
  2870.      {
  2871.          PAINTSTRUCT ps;
  2872.          HWND        hParent;
  2873.          PINFO       pInfo;
  2874.          HDC         hDC;
  2875.          RECT        rc;
  2876.  
  2877.          GetClientRect(hwnd,&rc);
  2878.          hDC = BeginPaint(hwnd, &ps);
  2879.          EndPaint(hwnd, &ps);
  2880.          if ((hParent=GetParent(hwnd)) == NULL) {
  2881.             OutputDebugString ("Can't get hParent!");
  2882.             return 0L;
  2883.          }
  2884.          if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2885.           return 0L;
  2886.         }
  2887.  
  2888.          if (pInfo->hBmpSaved) {
  2889.         hDC = GetDC(hwnd);
  2890.         bDrawDIB(hDC, pInfo, 0, 0, rc.right, rc.bottom);
  2891.         ReleaseDC(hwnd, hDC);
  2892.          }
  2893.          bReleaseInfoData(hParent);
  2894.  
  2895.          //EndPaint(hwnd, &ps);
  2896.          return 0L;
  2897.      }
  2898.  
  2899.        case WM_RBUTTONDOWN: {
  2900.      RECT   rc;
  2901.      HANDLE hParent;
  2902.      PINFO  pInfo;
  2903.      int    x, y;
  2904.      HWND   hJulia;
  2905.      HANDLE hTextWnd;
  2906.  
  2907.      x = (int) LOWORD(lParam);
  2908.      y = (int) HIWORD(lParam);
  2909.      if ((hParent=GetParent(hwnd)) == NULL) {
  2910.          OutputDebugString ("Can't get hParent!");
  2911.          break;
  2912.      }
  2913.  
  2914.      if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2915.          break;
  2916.      }
  2917.  
  2918.      hTextWnd = pInfo->hTextWnd;
  2919.  
  2920.      if (GetWindowLong(GetParent(hwnd), GWL_STYLE) & WS_MAXIMIZE) {
  2921.          GetClientRect(ghwndMain, &rc);
  2922.          rc.bottom -= GetWindowLong(hTextWnd,GWL_USERDATA);
  2923.      } else {
  2924.          GetClientRect(hwnd, &rc);
  2925.      }
  2926.  
  2927.      if (pInfo->bMandel) {
  2928.  
  2929.          hJulia = (HWND) SendMessage(ghwndMain, WM_COMMAND,
  2930.                      (DWORD)((WORD)MM_JULIA), 0L);
  2931.          if (hJulia) {
  2932.          //GetClientRect(hwnd, &rc);
  2933.          //
  2934.          // calculate the c value corresponding to the point
  2935.          //
  2936.          c1 = Xform((double) x, 0.0, (double) rc.right, pInfo->xFrom, pInfo->xTo);
  2937.          c2 = Xform((double) y, 0.0, (double) rc.bottom, pInfo->yFrom, pInfo->yTo);
  2938.          lc1 = XformFix(x, 0, rc.right, pInfo->lxFrom, pInfo->lxTo);
  2939.          lc2 = XformFix(y, 0, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
  2940.  
  2941.         sprintf( gtext,"(c1 = %g, c2 = %g)\n", c1, c2);
  2942.         OutputDebugString( gtext );
  2943.  
  2944.          //
  2945.          // Reset globals to default values for creating Julia set
  2946.          // (Entire set, not zoom in)
  2947.          //
  2948.          bResetGlobal();
  2949.          PostMessage(hJulia, WM_COMMAND, (DWORD)((WORD) MM_SET_XFORM_ATTR), 0L);
  2950.          } else {
  2951.          OutputDebugString ("Can't create hJulia!");
  2952.          }
  2953.      }
  2954.      bReleaseInfoData(hParent);
  2955.      break;
  2956.        }
  2957.        case WM_LBUTTONDOWN: {
  2958.      HANDLE hParent;
  2959.      PINFO  pInfo;
  2960.      int    x, y;
  2961.      DWORD  dwRGB;
  2962.      HBRUSH hBrOld;
  2963.  
  2964.      x = (int) LOWORD(lParam);
  2965.      y = (int) HIWORD(lParam);
  2966.      if ((hParent=GetParent(hwnd)) == NULL) {
  2967.          OutputDebugString ("Can't get hParent!");
  2968.          break;
  2969.      }
  2970.  
  2971.      if ((pInfo = pGetInfoData(hParent)) == NULL) {
  2972.          break;
  2973.      }
  2974.  
  2975.      if (pInfo->bFill) {
  2976.         hDC = GetDC(hwnd);
  2977.         hBrOld = SelectObject(hDC, pInfo->hBrush);
  2978.  
  2979.         dwRGB = GetPixel(hDC, x, y);
  2980.  
  2981.         ExtFloodFill(hDC, x, y, (COLORREF)dwRGB, FLOODFILLSURFACE);
  2982.         SelectObject(hDC, hBrOld);
  2983.         ReleaseDC(hwnd, hDC);
  2984.         pInfo->bFill = FALSE;
  2985.  
  2986.         if (pInfo->hBmpSaved)
  2987.         DeleteObject(pInfo->hBmpSaved);
  2988.  
  2989.         pInfo->hBmpSaved = SaveBitmap(hwnd, pInfo->hPal);
  2990.         pInfo->bUseDIB = FALSE;
  2991.  
  2992.  
  2993.         SetCursor(hCurArrow);
  2994.      } else {
  2995.         bTrack = TRUE;
  2996.         OrgX = PrevX = x = LOWORD(lParam);
  2997.         OrgY = PrevY = y = HIWORD(lParam);
  2998.  
  2999.         hDC = GetDC(hwnd);
  3000.         SetCapture(hwnd);
  3001.      }
  3002.      bReleaseInfoData(hParent);
  3003.      break;
  3004.        }
  3005.        case WM_MOUSEMOVE: {
  3006.      RECT rectClient;
  3007.      int NextX;
  3008.      int NextY;
  3009.      HANDLE hParent;
  3010.      PINFO  pInfo;
  3011.  
  3012.      if ((hParent=GetParent(hwnd)) == NULL) {
  3013.          OutputDebugString ("Can't get hParent!");
  3014.          break;
  3015.      }
  3016.  
  3017.      if ((pInfo = pGetInfoData(hParent)) == NULL) {
  3018.          break;
  3019.      }
  3020.  
  3021.      if (pInfo->bFill) {
  3022.          SetCursor(hCurPaintCan);
  3023.      } else {
  3024.          SetCursor(hCurArrow);
  3025.      }
  3026.  
  3027.      bReleaseInfoData(hParent);
  3028.  
  3029.      // Update the selection region
  3030.      if (bTrack) {
  3031.          NextX = (SHORT) LOWORD(lParam);
  3032.          NextY = (SHORT) HIWORD(lParam);
  3033.  
  3034.          // Do not draw outside the window's client area
  3035.  
  3036.          GetClientRect (hwnd, &rectClient);
  3037.          if (NextX < rectClient.left) {
  3038.          NextX = rectClient.left;
  3039.          } else if (NextX >= rectClient.right) {
  3040.          NextX = rectClient.right - 1;
  3041.          }
  3042.          if (NextY < rectClient.top) {
  3043.          NextY = rectClient.top;
  3044.          } else if (NextY >= rectClient.bottom) {
  3045.          NextY = rectClient.bottom - 1;
  3046.          }
  3047.          if ((NextX != PrevX) || (NextY != PrevY)) {
  3048.         SetROP2(hDC, R2_NOT);           // Erases the previous box
  3049.  
  3050.         MoveToEx(hDC, OrgX, OrgY, NULL);
  3051.         LineTo(hDC, OrgX, PrevY);
  3052.         LineTo(hDC, PrevX, PrevY);
  3053.         LineTo(hDC, PrevX, OrgY);
  3054.         LineTo(hDC, OrgX, OrgY);
  3055.          // Get the current mouse position
  3056.  
  3057.         PrevX = NextX;
  3058.         PrevY = NextY;
  3059.         MoveToEx(hDC, OrgX, OrgY, NULL);   // Draws the new box
  3060.         LineTo(hDC, OrgX, PrevY);
  3061.         LineTo(hDC, PrevX, PrevY);
  3062.         LineTo(hDC, PrevX, OrgY);
  3063.         LineTo(hDC, OrgX, OrgY);
  3064.          }
  3065.      }
  3066.      break;
  3067.  
  3068.        }
  3069.  
  3070.        case WM_LBUTTONUP: {
  3071.      RECT rc;
  3072.      HANDLE hParent;
  3073.      PINFO  pInfo;
  3074.      int NextX;
  3075.      int NextY;
  3076.      int iDistX, iDistY, iAbsDstX, iAbsDstY;
  3077.      HWND hZoom;
  3078.      HANDLE hTextWnd;
  3079.  
  3080.      if (!bTrack)
  3081.         break;
  3082.  
  3083.      // End the selection
  3084.         ReleaseCapture();
  3085.         bTrack = FALSE;
  3086.  
  3087.         MoveToEx(hDC, OrgX, OrgY, NULL);   // Erases the box
  3088.         LineTo(hDC, OrgX, PrevY);
  3089.         LineTo(hDC, PrevX, PrevY);
  3090.         LineTo(hDC, PrevX, OrgY);
  3091.         LineTo(hDC, OrgX, OrgY);
  3092.  
  3093.         NextX = LOWORD(lParam);
  3094.         NextY = HIWORD(lParam);
  3095.  
  3096.         iDistX = NextX - OrgX;
  3097.         iDistY = NextY - OrgY;
  3098.         iAbsDstX = (iDistX > 0 ? iDistX : -iDistX);
  3099.         iAbsDstY = (iDistY > 0 ? iDistY : -iDistY);
  3100.         if (iAbsDstX > iAbsDstY) {
  3101.         NextY = OrgY + (iDistY > 0 ? iAbsDstX : -iAbsDstX);
  3102.         } else if (iAbsDstX < iAbsDstY) {
  3103.             NextX = OrgX + (iDistX > 0 ? iAbsDstY : -iAbsDstY);
  3104.         }
  3105.  
  3106.         MoveToEx(hDC, OrgX, OrgY, NULL);   // Draws the new box
  3107.         LineTo(hDC, OrgX, NextY);
  3108.         LineTo(hDC, NextX, NextY);
  3109.         LineTo(hDC, NextX, OrgY);
  3110.         LineTo(hDC, OrgX, OrgY);
  3111.  
  3112.         SetROP2(hDC, R2_COPYPEN);
  3113.  
  3114.         ReleaseDC(hwnd, hDC);
  3115.         if ((hParent=GetParent(hwnd)) == NULL) {
  3116.         OutputDebugString ("Can't get hParent!");
  3117.         break;
  3118.         }
  3119.  
  3120.         if ((pInfo = pGetInfoData(hParent)) == NULL) {
  3121.         break;
  3122.         }
  3123.  
  3124.         hTextWnd = pInfo->hTextWnd;
  3125.         sprintf(gtext, GetStringRes (IDS_MOUSE), OrgX, OrgY, NextX, NextY);
  3126.  
  3127.         //SetWindowText(hTextWnd, gtext);
  3128.         OutputDebugString(gtext);
  3129.  
  3130.  
  3131.         if (GetWindowLong(GetParent(hwnd), GWL_STYLE) & WS_MAXIMIZE) {
  3132.  
  3133.         GetClientRect(ghwndMain, &rc);
  3134.         rc.bottom -= GetWindowLong(hTextWnd,GWL_USERDATA);
  3135.         sprintf(gtext, "(%d, %d), (%d, %d)\n", rc.left, rc.top, rc.right, rc.bottom);
  3136.         //SetWindowText(hTextWnd, gtext);
  3137.         OutputDebugString(gtext);
  3138.  
  3139.         } else {
  3140.         GetClientRect(hwnd, &rc);
  3141.         }
  3142.  
  3143.         if ((OrgX == NextX) && (OrgY == NextY)) {
  3144.         bReleaseInfoData(hParent);
  3145.         break;
  3146.         }
  3147.  
  3148.         hZoom = (HWND) SendMessage(ghwndMain, WM_COMMAND,
  3149.                pInfo->bMandel ? (DWORD)((WORD)MM_MANDEL) : (DWORD)((WORD)MM_JULIA),
  3150.                0L);
  3151.         if (hZoom) {
  3152.         //GetClientRect(hwnd, &rc);
  3153.         xFrom = Xform((double) OrgX, 0.0, (double) rc.right, pInfo->xFrom, pInfo->xTo);
  3154.         xTo   = Xform((double) NextX, 0.0, (double) rc.right, pInfo->xFrom, pInfo->xTo);
  3155.         yFrom = Xform((double) OrgY, 0.0, (double) rc.bottom, pInfo->yFrom, pInfo->yTo);
  3156.         yTo   = Xform((double) NextY, 0.0, (double) rc.bottom, pInfo->yFrom, pInfo->yTo);
  3157.         lxFrom = XformFix(OrgX, 0, rc.right, pInfo->lxFrom, pInfo->lxTo);
  3158.         lxTo   = XformFix(NextX, 0, rc.right, pInfo->lxFrom, pInfo->lxTo);
  3159.         lyFrom = XformFix(OrgY, 0, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
  3160.         lyTo   = XformFix(NextY, 0, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
  3161.         if (!pInfo->bMandel) {
  3162.             c1 = pInfo->c1;
  3163.             c2 = pInfo->c2;
  3164.             lc1 = pInfo->lc1;
  3165.             lc2 = pInfo->lc2;
  3166.         }
  3167.         PostMessage(hZoom, WM_COMMAND, (DWORD)((WORD) MM_SET_XFORM_ATTR), 0L);
  3168.         } else {
  3169.         OutputDebugString ("Can't create hZoom!");
  3170.         }
  3171.      bReleaseInfoData(hParent);
  3172.      break;
  3173.        } // case WM_LBUTTONUP
  3174.     } // switch
  3175.     return DefWindowProc(hwnd, message, wParam, lParam);
  3176. }
  3177.  
  3178.  
  3179. /******************************Public*Routine******************************\
  3180. *
  3181. * SuspendDrawThrd
  3182. *
  3183. * Effects: Enumerates all the MDI children.  Suspending the drawing thread
  3184. *          in those windows, if any.
  3185. *
  3186. * Warnings: assumes the MDI children has class name "ChildClass."
  3187. *
  3188. \**************************************************************************/
  3189.  
  3190.  
  3191. BOOL APIENTRY SuspendDrawThrd (HWND hwnd, LONG lParam) {
  3192.    HANDLE      hThrd;
  3193.    PINFO       pInfo;
  3194.    DWORD       dwSuspend;
  3195.    BOOL        bDrawing;
  3196.    char        sz[30];
  3197.  
  3198.    GetClassName(hwnd, sz, 15);
  3199.    if (strcmp(sz, "ChildClass") != 0)
  3200.     return 1L;
  3201.        if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  3202.        return 1L;
  3203.        }
  3204.  
  3205.        bDrawing = pInfo->bDrawing;
  3206.        hThrd    = pInfo->hThrd;
  3207.        bReleaseInfoData(hwnd);
  3208.  
  3209.        if (hThrd && bDrawing) {
  3210.        dwSuspend = SuspendThread(hThrd);
  3211.        sprintf( gtext,"\nSuspend: dwSuspend = %d, dwSuspend = %g\n", dwSuspend, dwSuspend);
  3212.        OutputDebugString( gtext );
  3213.  
  3214.        if (dwSuspend == -1) {
  3215.            sprintf( gtext,"Error in suspending thread\n");
  3216.            OutputDebugString( gtext );
  3217.        }
  3218.        }
  3219.    return 1L;
  3220.    UNREFERENCED_PARAMETER(lParam);
  3221. }
  3222.  
  3223.  
  3224. /******************************Public*Routine******************************\
  3225. *
  3226. * ResumeDrawThrd
  3227. *
  3228. * Effects: Enumerates all the MDI children.  Resuming the drawing thread
  3229. *          in those windows, if any.
  3230. *
  3231. * Warnings: Assumes the MDI children has class name "ChildClass." Also,
  3232. *           assumes the drawing has been suspended by SuspendDrawThrd.
  3233. *
  3234. \**************************************************************************/
  3235.  
  3236.  
  3237. BOOL APIENTRY ResumeDrawThrd  (HWND hwnd, LONG lParam) {
  3238.    HANDLE      hThrd;
  3239.    PINFO       pInfo;
  3240.    DWORD       dwSuspend;
  3241.    BOOL        bDrawing;
  3242.    char        sz[30];
  3243.  
  3244.    GetClassName(hwnd, sz, 15);
  3245.    if (strcmp(sz, "ChildClass") != 0)
  3246.     return 1L;
  3247.       if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  3248.       return 1L;
  3249.       }
  3250.  
  3251.       bDrawing = pInfo->bDrawing;
  3252.       hThrd    = pInfo->hThrd;
  3253.       bReleaseInfoData(hwnd);
  3254.  
  3255.       if (hThrd && bDrawing) {
  3256.       dwSuspend = ResumeThread(hThrd);
  3257.       sprintf( gtext,"Resume: dwSuspend = %d, dwSuspend = %g\n", dwSuspend, dwSuspend);
  3258.       OutputDebugString( gtext );
  3259.  
  3260.       if (dwSuspend == -1) {
  3261.           sprintf( gtext,"Error in resuming thread\n");
  3262.           OutputDebugString( gtext );
  3263.       }
  3264.       }
  3265.    return 1L;
  3266.    UNREFERENCED_PARAMETER(lParam);
  3267. }
  3268.  
  3269.  
  3270. /******************************Public*Routine******************************\
  3271. *
  3272. * lMul
  3273. *
  3274. * Effects: Fix point multiplication
  3275. *
  3276. * Warnings: 9.23 fix point representation used. This is only good for
  3277. *           multiplication in a limited range.  Will overflow.
  3278. *           CR! Will be implemented as macros in the future
  3279. *
  3280. \**************************************************************************/
  3281.  
  3282. LONG lMul(LONG l1, LONG l2)
  3283. {
  3284.     LONGLONG   lliTmp;
  3285.     LONG       lReturn;
  3286.  
  3287.     lliTmp = l1;
  3288.     lliTmp *= l2;
  3289.     lReturn = (LONG)(lliTmp >> 23);
  3290.  
  3291.     return(lReturn);
  3292. }
  3293.  
  3294. /******************************Public*Routine******************************\
  3295. *
  3296. * lDiv
  3297. *
  3298. * Effects: fix point division
  3299. *
  3300. * Warnings: 9.23 fix point representation used. This is only good for
  3301. *           division in a limited range.  Will overflow.
  3302. *           CR! Will be implemented as macros in the future
  3303. *
  3304. \**************************************************************************/
  3305.  
  3306. LONG lDiv(long l1, long l2)
  3307. {
  3308.     LONGLONG   lliTmp;
  3309.     LONG       lReturn;
  3310.  
  3311.  
  3312.  
  3313.     lliTmp  = (LONGLONG)l1;
  3314.     lliTmp  <<= 23;
  3315.  
  3316.     lReturn = (LONG)(lliTmp / (LONGLONG)l2);
  3317.     return (lReturn);
  3318. }
  3319.  
  3320.  
  3321. /**************************************************************************\
  3322. *
  3323. * StartDrawFix
  3324. *                                            2
  3325. * Effects: Draw'g the Julia Set for Q (z) = z  + c, where z, c are complex
  3326. *                                    c
  3327. *          Fact:   |Q (0)| = |c| > 2, the orbit of 0 escapes immediately
  3328. *                    c
  3329. *          claim:  |z| >= |c| = 2 + l, l > 0 escapes under Q
  3330. *                                                           c
  3331. *          The Julia Set: Basin Boundaries algorithm.
  3332. *
  3333. * Warnings:
  3334. *
  3335. \**************************************************************************/
  3336. BOOL StartDrawFix(PINFO pInfo)
  3337. {
  3338.    DWORD       dwTick1;
  3339.    HDC         hDC;
  3340.    RECT        rc;
  3341.  
  3342.    int m, n, i, iPrev;
  3343.    int xCurr, yCurr;
  3344.    int iPen;
  3345.  
  3346.    LONG c1, c2;
  3347.    LONG x0, y0, x1, y1, x, y, z;
  3348.  
  3349.    int  iBand=1;
  3350.    int  iScan=0;
  3351.    int  iDiff=0;
  3352.  
  3353. #ifndef THRDONE
  3354.    INT      iNumClr;
  3355. #endif
  3356.  
  3357.    HDC          hDCMem;
  3358.    HBITMAP      hBitmap, hOldBitmap;
  3359.  
  3360.    iPen = pInfo->iPen + 1;
  3361.    iPrev = FIRST_PIXEL;    // a big value to signal the first pixel
  3362.    //iPrev = pInfo->iIteration + FIRST_PIXEL;
  3363.    c1 = pInfo->lc1;
  3364.    c2 = pInfo->lc2;
  3365.  
  3366.    pInfo->bMandel = FALSE;
  3367.    pInfo->bDrawing = TRUE;
  3368.    hDC = GetDC(pInfo->hwnd);
  3369.  
  3370. #ifndef THRDONE
  3371.     if ((iNumClr = iCreatePenFrPal(hDC, NULL, 0, &(pInfo->hPal))) != 0) {
  3372.     sprintf( gtext,"iNumClr = %d\n", iNumClr);
  3373.     OutputDebugString( gtext);
  3374.  
  3375.     if ((pInfo->prghPen = (PVOID*) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(HPEN)*iNumClr)) == NULL) {
  3376.         OutputDebugString ("Failed in Memory Allocation for pInfo->prghPen!");
  3377.     } else {
  3378.         if ((pInfo->iPen = iCreatePenFrPal(hDC, pInfo->prghPen, 0, &(pInfo->hPal))) == 0)
  3379.         OutputDebugString ("Failed in creating pen!");
  3380.     }
  3381.     }
  3382.  
  3383.    hDCMem = CreateCompatibleDC(hDC);
  3384.  
  3385.    SelectPalette(hDCMem, pInfo->hPal, FALSE);
  3386.    SelectPalette(hDC,    pInfo->hPal, FALSE);
  3387.    RealizePalette(hDC);
  3388.    iPen = pInfo->iPen + 1;
  3389. #endif
  3390.  
  3391.    GetClientRect(pInfo->hwnd, &rc);
  3392.    hBitmap = CreateCompatibleBitmap(hDC, (int)rc.right, (int)rc.bottom);
  3393.    hOldBitmap = SelectObject(hDCMem, hBitmap);
  3394.    yCurr = rc.top;
  3395.  
  3396.    dwTick1 = GetTickCount();
  3397.    iScan = (((iScan = BATCH / rc.right) == 0) ? 1 : iScan);
  3398.  
  3399.    for (n=rc.top; n<=rc.bottom; n+=pInfo->iStep, yCurr+=pInfo->iStep, iPrev = FIRST_PIXEL) {
  3400.        xCurr = rc.left;               // since LineTo excludes last point
  3401.        MoveToEx(hDCMem, 0, yCurr, NULL);
  3402.        y0 = XformFix(n, rc.top, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
  3403.  
  3404.        for (m=rc.left; m<=rc.right; m++, xCurr++) {
  3405.        x0 = XformFix(m, rc.left, rc.right, pInfo->lxFrom, pInfo->lxTo);
  3406.        x = x0;
  3407.        y = y0;
  3408.  
  3409.        for (i=1; i<=pInfo->iIteration; i++) {
  3410.            x1 = lMul(x - y, x + y) + c1;    // Z = x1 + i x2
  3411.  
  3412.            y1 = (lMul(x, y) * 2) + c2;
  3413.            x = x1;
  3414.            y = y1;                          //    2       2     2 1/2     2
  3415.            z = lMul(x, x) + lMul(y, y);     // |Z|  = ((x1  + x2 )   ) > 2
  3416.  
  3417.            if (z > 33554432)
  3418.             break;
  3419.        }
  3420.  
  3421.        if (i != iPrev)
  3422.        {
  3423.           if (iPrev != FIRST_PIXEL)
  3424.           {
  3425.         switch(iPrev)
  3426.         {
  3427.            case 1:
  3428.                if (pInfo->prghPen)
  3429.                   SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
  3430.                break;
  3431.            default:
  3432.  
  3433.                if (iPrev >= pInfo->iIteration) 
  3434.                {
  3435.                    SelectObject(hDCMem, hpnBlack);
  3436.                    break;
  3437.                }
  3438.                if (pInfo->prghPen)
  3439.                    SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[iPrev % iPen]);
  3440.                break;
  3441.         }
  3442.         iPrev = i;
  3443.         LineTo(hDCMem,xCurr,yCurr);
  3444.           }
  3445.           else
  3446.          iPrev = i;     // remember the color for the first pixel
  3447.        }
  3448.        }
  3449.        switch(i) {
  3450.        case 1:
  3451.           if (pInfo->prghPen)
  3452.               SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
  3453.           break;
  3454.        default:
  3455.           if (iPrev >= pInfo->iIteration) {
  3456.               SelectObject(hDCMem, hpnBlack);
  3457.               break;
  3458.           }
  3459.           if (pInfo->prghPen)
  3460.              SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[i % iPen]);
  3461.           break;
  3462.        }
  3463.  
  3464.        LineTo(hDCMem,xCurr,yCurr);
  3465.  
  3466.        sprintf(gtext, GetStringRes (IDS_DRAWING), ((FLOAT)n/(FLOAT)rc.bottom)*100);
  3467.  
  3468.        SetWindowText(pInfo->hTextWnd, gtext);
  3469.  
  3470.        if (n >= iScan * iBand) {
  3471.         BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  3472.         iBand++;
  3473.        }
  3474.    }
  3475.  
  3476.    if ((iDiff = iScan * iBand - rc.bottom) != 0) {
  3477.     BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan-iDiff, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  3478.    }
  3479.  
  3480.    sprintf(gtext, GetStringRes (IDS_DRAWING_DONE));
  3481.  
  3482.    SetWindowText(pInfo->hTextWnd, gtext);
  3483.  
  3484.    ReleaseDC(pInfo->hwnd, hDC);
  3485.  
  3486.    pInfo->dwElapsed = GetTickCount() - dwTick1;
  3487.  
  3488.    if (pInfo->hBmpSaved)
  3489.        DeleteObject(pInfo->hBmpSaved);
  3490.  
  3491.    pInfo->hBmpSaved = SelectObject(hDCMem, hOldBitmap);
  3492.    pInfo->bDrawing = FALSE;
  3493. #ifndef THRDONE
  3494.    if (pInfo->prghPen != NULL) {
  3495.        for (i = 0; i <= pInfo->iPen; i++) {
  3496.        DeleteObject((HPEN) (pInfo->prghPen)[i]);
  3497.        }
  3498.        GlobalFree(pInfo->prghPen);
  3499.    }
  3500. #endif
  3501.    DeleteDC(hDCMem);
  3502.    ExitThread(0);
  3503.    return TRUE;
  3504. }
  3505.  
  3506. /**************************************************************************\
  3507. *
  3508. * StartDraw
  3509. *                                            2
  3510. * Effects: Draw'g the Julia Set for Q (z) = z  + c, where z, c are complex
  3511. *                                    c
  3512. *          Fact:   |Q (0)| = |c| > 2, the orbit of 0 escapes immediately
  3513. *                    c
  3514. *          claim:  |z| >= |c| = 2 + l, l > 0 escapes under Q
  3515. *                                                           c
  3516. *          The Julia Set: Basin Boundaries algorithm.
  3517. *
  3518. * Warnings:
  3519. *
  3520. \**************************************************************************/
  3521. BOOL StartDraw(PINFO pInfo)
  3522. {
  3523.    DWORD       dwTick1;
  3524.    HDC         hDC;
  3525.    RECT        rc;
  3526.  
  3527.    int m, n, i, iPrev;
  3528.    int xCurr, yCurr;
  3529.    int iPen;
  3530.  
  3531.    double c1, c2;
  3532.    double x0, y0, x1, y1, x, y, z;
  3533.  
  3534.    int  iBand=1;
  3535.    int  iScan=0;
  3536.    int  iDiff=0;
  3537.  
  3538.  
  3539.    HDC          hDCMem;
  3540.    HBITMAP      hBitmap, hOldBitmap;
  3541.  
  3542. #ifndef THRDONE
  3543.    INT      iNumClr;
  3544. #endif
  3545.  
  3546.    iPen = pInfo->iPen + 1;
  3547.    iPrev = FIRST_PIXEL;    // a big value to signal the first pixel
  3548.    //iPrev = pInfo->iIteration + FIRST_PIXEL;
  3549.    c1 = pInfo->c1;
  3550.    c2 = pInfo->c2;
  3551.  
  3552.    pInfo->bMandel = FALSE;
  3553.    pInfo->bDrawing = TRUE;
  3554.    hDC = GetDC(pInfo->hwnd);
  3555.  
  3556. #ifndef THRDONE
  3557.     if ((iNumClr = iCreatePenFrPal(hDC, NULL, 0, &(pInfo->hPal))) != 0) {
  3558.     sprintf( gtext,"iNumClr = %d\n", iNumClr);
  3559.     OutputDebugString( gtext);
  3560.  
  3561.     if ((pInfo->prghPen = (PVOID*) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(HPEN)*iNumClr)) == NULL) {
  3562.         OutputDebugString ("Failed in Memory Allocation for pInfo->prghPen!");
  3563.     } else {
  3564.         if ((pInfo->iPen = iCreatePenFrPal(hDC, pInfo->prghPen, 0, &(pInfo->hPal))) == 0)
  3565.            OutputDebugString ("Failed in creating pen!");
  3566.     }
  3567.     }
  3568.  
  3569.    hDCMem = CreateCompatibleDC(hDC);
  3570.  
  3571.    SelectPalette(hDCMem, pInfo->hPal, FALSE);
  3572.    SelectPalette(hDC,    pInfo->hPal, FALSE);
  3573.    RealizePalette(hDC);
  3574.    iPen = pInfo->iPen + 1;
  3575. #endif
  3576.  
  3577.    GetClientRect(pInfo->hwnd, &rc);
  3578.    hBitmap = CreateCompatibleBitmap(hDC, (int)rc.right, (int)rc.bottom);
  3579.    hOldBitmap = SelectObject(hDCMem, hBitmap);
  3580.    yCurr = rc.top;
  3581.  
  3582.    dwTick1 = GetTickCount();
  3583.  
  3584.    iScan = (((iScan = BATCH / rc.right) == 0) ? 1 : iScan);
  3585.  
  3586.    for (n=rc.top; n<=rc.bottom; n+=pInfo->iStep, yCurr+=pInfo->iStep, iPrev = FIRST_PIXEL) {
  3587.        xCurr = rc.left;               // since LineTo excludes last point
  3588.        MoveToEx(hDCMem, 0, yCurr, NULL);
  3589.        y0 = Xform((double) n, 0.0, (double) rc.bottom, pInfo->yFrom, pInfo->yTo);
  3590.  
  3591.        for (m=rc.left; m<=rc.right; m++, xCurr++) {
  3592.        x0 = Xform((double) m, 0.0, (double) rc.right, pInfo->xFrom, pInfo->xTo);
  3593.        x = x0;
  3594.        y = y0;
  3595.  
  3596.        for (i=1; i<=pInfo->iIteration; i++) {
  3597.            x1 = (x - y) * (x + y) + c1;     // Z = x1 + i x2
  3598.  
  3599.            y1 = 2 * x * y + c2;
  3600.            x = x1;
  3601.            y = y1;                          //    2       2     2 1/2     2
  3602.            z = x * x + y * y;               // |Z|  = ((x1  + x2 )   ) > 2
  3603.  
  3604.            if (z > 4.0)
  3605.             break;
  3606.        }
  3607.  
  3608.        if (i != iPrev)
  3609.        {
  3610.           if (iPrev != FIRST_PIXEL)
  3611.           {
  3612.         switch(iPrev)
  3613.         {
  3614.            case 1:
  3615.                if (pInfo->prghPen)
  3616.                   SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
  3617.                break;
  3618.            default:
  3619.  
  3620.                if (iPrev >= pInfo->iIteration) {
  3621.                    SelectObject(hDCMem, hpnBlack);
  3622.                    break;
  3623.                }
  3624.                if(pInfo->prghPen)
  3625.                    SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[iPrev % iPen]);
  3626.                break;
  3627.         }
  3628.         iPrev = i;
  3629.         LineTo(hDCMem,xCurr,yCurr);
  3630.           }
  3631.           else
  3632.          iPrev = i;     // remember the color for the first pixel
  3633.        }
  3634.        }
  3635.        switch(i) {
  3636.       case 1:
  3637.           SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
  3638.           break;
  3639.       default:
  3640.           if (iPrev >= pInfo->iIteration) {
  3641.              SelectObject(hDCMem, hpnBlack);
  3642.              break;
  3643.           }
  3644.           if (pInfo->prghPen)
  3645.               SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[i % iPen]);
  3646.           break;
  3647.        }
  3648.  
  3649.        LineTo(hDCMem,xCurr,yCurr);
  3650.  
  3651.        sprintf(gtext, GetStringRes (IDS_DRAWING), ((FLOAT)n/(FLOAT)rc.bottom)*100);
  3652.        SetWindowText(pInfo->hTextWnd, gtext);
  3653.  
  3654.        if (n >= iScan * iBand) {
  3655.         BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  3656.         iBand++;
  3657.        }
  3658.    }
  3659.  
  3660.    if ((iDiff = iScan * iBand - rc.bottom) != 0) {
  3661.     BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan-iDiff, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  3662.    }
  3663.  
  3664.    sprintf(gtext, GetStringRes(IDS_DRAWING_DONE));
  3665.  
  3666.    SetWindowText(pInfo->hTextWnd, gtext);
  3667.  
  3668.    ReleaseDC(pInfo->hwnd, hDC);
  3669.  
  3670.    pInfo->dwElapsed = GetTickCount() - dwTick1;
  3671.  
  3672.    if (pInfo->hBmpSaved)
  3673.        DeleteObject(pInfo->hBmpSaved);
  3674.  
  3675.    pInfo->hBmpSaved = SelectObject(hDCMem, hOldBitmap);
  3676.    pInfo->bDrawing = FALSE;
  3677. #ifndef THRDONE
  3678.    if (pInfo->prghPen != NULL) {
  3679.        for (i = 0; i <= pInfo->iPen; i++) {
  3680.        DeleteObject((HPEN) (pInfo->prghPen)[i]);
  3681.        }
  3682.        GlobalFree(pInfo->prghPen);
  3683.    }
  3684. #endif
  3685.    DeleteDC(hDCMem);
  3686.  
  3687.    ExitThread(0);
  3688.    return TRUE;
  3689. }
  3690.  
  3691. /**************************************************************************\
  3692. *
  3693. * StartDraw2
  3694. *                                            2
  3695. * Effects: Draw'g the Julia Set for Q (z) = z  + c, where z, c are complex
  3696. *
  3697. *          The Julia Set: Backward iteration algorithm.
  3698. *
  3699. * Warnings:
  3700. *
  3701. \**************************************************************************/
  3702.  
  3703. BOOL StartDraw2(PINFO pInfo)
  3704. {
  3705.    HDC         hDC;
  3706.    RECT        rc;
  3707.    int         m, n, i;
  3708.    double      c1, c2;
  3709.    double      x0, y0, w0, w1, pi, theta, r;
  3710.  
  3711.    pi = 22.0/7.0;
  3712.    c1 = 0.360284;
  3713.    c2 = 0.100376;
  3714.    x0 = 1.5;
  3715.    y0 = 1.5;
  3716.  
  3717.    hDC = GetDC(pInfo->hwnd);
  3718.  
  3719.    GetClientRect(pInfo->hwnd, &rc);
  3720.    for (i=0; i<=15000; i++) {
  3721.     w0 = x0 - c1;
  3722.     w1 = y0 - c2;
  3723.     sprintf( gtext,"w(%g, %g) xy(%g, %g)\n", w0, w1, x0, y0);
  3724.     OutputDebugString( gtext );
  3725.  
  3726.     if (w0 == 0.0) {
  3727.     theta = pi/2;
  3728.     sprintf( gtext,"(w0 == 0.0) theta = %g\n\n", theta);
  3729.     OutputDebugString( gtext );
  3730.  
  3731.     } else {
  3732.     if (w0 > 0.0) {
  3733.         theta = atan(w1/w0);
  3734.         sprintf( gtext,"(w0 > 0.0) theta = %g\n\n", theta);
  3735.         OutputDebugString( gtext );
  3736.  
  3737.     } else { // w0 < 0.0
  3738.         theta = pi + atan(w1/w0);
  3739.         sprintf( gtext,"(w0 < 0.0) theta = %g\n\n", theta);
  3740.         OutputDebugString( gtext );
  3741.     }
  3742.     }
  3743.     r = sqrt(w0 * w0 + w1 + w1);
  3744.     //theta = theta/2.0 + ((int) ((2.0*rand()/(RAND_MAX+1.0)))*pi);
  3745.     //theta = theta/2.0 + ((2.0*rand()/((double)RAND_MAX+1.0))*pi);
  3746.     r = sqrt(r);
  3747.     x0 = r*cos(theta);
  3748.     y0 = r*sin(theta);
  3749.     if (i > 50) {
  3750.     m = Xform2(x0, pInfo->xFrom, pInfo->xTo, 0.0, (double) rc.right);
  3751.     n = Xform2(y0, pInfo->yFrom, pInfo->yTo, 0.0, (double) rc.bottom);
  3752.     SetPixel(hDC, m, n, 0x000000ff);
  3753.     }
  3754.    }
  3755.  
  3756.    ReleaseDC(pInfo->hwnd, hDC);
  3757.  
  3758.    ExitThread(0);
  3759.    return TRUE;
  3760. }
  3761.  
  3762. /**************************************************************************\
  3763. *
  3764. * StartMandelbrotFix
  3765. *                                            2
  3766. * Effects: Draw'g the Mandelbrot Set for Q (z) = z  + c, where z, c complex
  3767. *
  3768. * Warnings:
  3769. \**************************************************************************/
  3770. BOOL StartMandelbrotFix(PINFO pInfo)
  3771. {
  3772.    DWORD       dwTick1;
  3773.    HDC         hDC;
  3774.    RECT        rc;
  3775.    int         m, n, i, iPrev;
  3776.    int         xCurr, yCurr;
  3777.    int         iPen;
  3778.  
  3779.    LONG c1, c2;
  3780.    LONG x1, y1, x, y, r;
  3781. #ifndef THRDONE
  3782.    INT      iNumClr;
  3783. #endif
  3784.  
  3785.    HDC          hDCMem;
  3786.    HBITMAP      hBitmap, hOldBitmap;
  3787.  
  3788.    int  iBand=1;
  3789.    int  iScan=0;
  3790.    int  iDiff=0;
  3791.  
  3792.    iPen = pInfo->iPen + 1;
  3793.    pInfo->bMandel = TRUE;
  3794.    pInfo->bDrawing = TRUE;
  3795.    hDC = GetDC(pInfo->hwnd);
  3796.  
  3797. #ifndef THRDONE
  3798.     if ((iNumClr = iCreatePenFrPal(hDC, NULL, 0, &(pInfo->hPal))) != 0) {
  3799.     sprintf( gtext,"iNumClr = %d\n", iNumClr);
  3800.     OutputDebugString( gtext);
  3801.  
  3802.     if ((pInfo->prghPen = (PVOID*) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(HPEN)*iNumClr)) == NULL) {
  3803.         OutputDebugString ("Failed in Memory Allocation for pInfo->prghPen!");
  3804.     } else {
  3805.         if ((pInfo->iPen = iCreatePenFrPal(hDC, pInfo->prghPen, 0, &(pInfo->hPal))) == 0)
  3806.         OutputDebugString ("Failed in creating pen!");
  3807.     }
  3808.     }
  3809.  
  3810.    hDCMem = CreateCompatibleDC(hDC);
  3811.  
  3812.    SelectPalette(hDCMem, pInfo->hPal, FALSE);
  3813.    SelectPalette(hDC,    pInfo->hPal, FALSE);
  3814.    RealizePalette(hDC);
  3815.    iPen = pInfo->iPen + 1;
  3816. #endif
  3817.  
  3818.    GetClientRect(pInfo->hwnd, &rc);
  3819.  
  3820.    hBitmap = CreateCompatibleBitmap(hDC, (int)rc.right, (int)rc.bottom);
  3821.    hOldBitmap = SelectObject(hDCMem, hBitmap);
  3822.  
  3823.    dwTick1 = GetTickCount();
  3824.    yCurr = rc.top;
  3825.  
  3826.    iScan = (((iScan = BATCH / rc.right) == 0) ? 1 : iScan);
  3827.  
  3828.    for (n=rc.top; n<=rc.bottom; n+=pInfo->iStep, yCurr+=pInfo->iStep, iPrev = FIRST_PIXEL) {
  3829.        xCurr = rc.left;                   // since LineTo excludes last point
  3830.        MoveToEx(hDCMem, 0, yCurr, NULL);
  3831.        c2 = XformFix(n, rc.top, rc.bottom, pInfo->lyFrom, pInfo->lyTo);
  3832.  
  3833.        for (m=rc.left; m<=rc.right; m++, xCurr++) {
  3834.        c1 = XformFix(m, rc.left, rc.right, pInfo->lxFrom, pInfo->lxTo);
  3835.        x = c1;
  3836.        y = c2;
  3837.  
  3838.        for (i=1; i<=pInfo->iIteration; i++) {
  3839.            x1 = lMul(x - y, x + y) + c1;
  3840.            y1 = (lMul(x, y) * 2) + c2;
  3841.            r = lMul(x1, x1) + lMul(y1, y1);
  3842.            x = x1;
  3843.            y = y1;
  3844.            if (r > 33554432) {
  3845.            break;
  3846.            }
  3847.        }
  3848.  
  3849.        if (i != iPrev) {
  3850.            if (iPrev != FIRST_PIXEL) {
  3851.          switch(iPrev) {
  3852.            case 1:
  3853.                SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]); break;
  3854.            default:
  3855.                if (iPrev >= pInfo->iIteration) {
  3856.                 SelectObject(hDCMem, hpnBlack);
  3857.                 break;
  3858.                }
  3859.                SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[iPrev % iPen]);
  3860.                break;
  3861.          }
  3862.          iPrev = i;
  3863.          LineTo(hDCMem, xCurr, yCurr);
  3864.            }
  3865.            else
  3866.           iPrev = i;    // remember the color for the first pixel
  3867.        }
  3868.        }
  3869.  
  3870.        switch(i) {
  3871.        case 1:
  3872.            SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
  3873.            break;
  3874.        default:
  3875.            if (i >= pInfo->iIteration) {
  3876.             SelectObject(hDCMem, hpnBlack);
  3877.             break;
  3878.            }
  3879.            SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[i % iPen]);
  3880.            break;
  3881.        }
  3882.        LineTo(hDCMem,xCurr,yCurr);
  3883.  
  3884.        sprintf(gtext, GetStringRes (IDS_DRAWING), ((FLOAT)n/(FLOAT)rc.bottom)*100);
  3885.  
  3886.        SetWindowText(pInfo->hTextWnd, gtext);
  3887.  
  3888.        if (n >= iScan * iBand) {
  3889.         BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  3890.         iBand++;
  3891.        }
  3892.  
  3893.    }
  3894.  
  3895.    if ((iDiff = iScan * iBand - rc.bottom) != 0) {
  3896.     BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan-iDiff, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  3897.    }
  3898.  
  3899.    sprintf(gtext, GetStringRes (IDS_DRAWING_DONE));
  3900.  
  3901.    SetWindowText(pInfo->hTextWnd, gtext);
  3902.  
  3903.    ReleaseDC(pInfo->hwnd, hDC);
  3904.  
  3905.    pInfo->dwElapsed = GetTickCount() - dwTick1;
  3906.  
  3907.    if (pInfo->hBmpSaved)
  3908.        DeleteObject(pInfo->hBmpSaved);
  3909.  
  3910.    pInfo->hBmpSaved = SelectObject(hDCMem, hOldBitmap);
  3911.    pInfo->bDrawing = FALSE;
  3912.  
  3913. #ifndef THRDONE
  3914.    if (pInfo->prghPen != NULL) {
  3915.        for (i = 0; i <= pInfo->iPen; i++) {
  3916.        DeleteObject((HPEN) (pInfo->prghPen)[i]);
  3917.        }
  3918.        GlobalFree(pInfo->prghPen);
  3919.    }
  3920. #endif
  3921.  
  3922.    DeleteDC(hDCMem);
  3923.  
  3924.    ExitThread(0);
  3925.    return TRUE;
  3926. }
  3927.  
  3928. /**************************************************************************\
  3929. *
  3930. * StartMandelbrot
  3931. *                                            2
  3932. * Effects: Draw'g the Mandelbrot Set for Q (z) = z  + c, where z, c complex
  3933. *
  3934. * Warnings:
  3935. *
  3936. \**************************************************************************/
  3937. BOOL StartMandelbrot(PINFO pInfo)
  3938. {
  3939.    DWORD       dwTick1;
  3940.    HDC         hDC;
  3941.    RECT        rc;
  3942.    int         m, n, i, iPrev;
  3943.    int         xCurr, yCurr;
  3944.    int         iPen;
  3945.  
  3946. #ifndef THRDONE
  3947.    INT      iNumClr;
  3948.    char     text[256];
  3949. #endif
  3950.  
  3951.    double c1, c2;
  3952.    double x1, y1, x, y, r;
  3953.  
  3954.    HDC          hDCMem;
  3955.    HBITMAP      hBitmap, hOldBitmap;
  3956.  
  3957.    int  iBand=1;
  3958.    int  iScan=0;
  3959.    int  iDiff=0;
  3960.  
  3961.    iPrev = 0;
  3962.    iPen = pInfo->iPen + 1;
  3963.    pInfo->bMandel = TRUE;
  3964.    pInfo->bDrawing = TRUE;
  3965.    hDC = GetDC(pInfo->hwnd);
  3966.  
  3967. #ifndef THRDONE
  3968.     if ((iNumClr = iCreatePenFrPal(hDC, NULL, 0, &(pInfo->hPal))) != 0) {
  3969.     sprintf( gtext,"iNumClr = %d\n", iNumClr);
  3970.     OutputDebugString( gtext);
  3971.  
  3972.     if ((pInfo->prghPen = (PVOID*) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(HPEN)*iNumClr)) == NULL) {
  3973.         OutputDebugString ("Failed in Memory Allocation for pInfo->prghPen!");
  3974.     } else {
  3975.         if ((pInfo->iPen = iCreatePenFrPal(hDC, pInfo->prghPen, 1, &(pInfo->hPal))) == 0)
  3976.         OutputDebugString ("Failed in creating pen!");
  3977.     }
  3978.     }
  3979.  
  3980.    hDCMem = CreateCompatibleDC(hDC);
  3981.  
  3982.    SelectPalette(hDCMem, pInfo->hPal, FALSE);
  3983.    SelectPalette(hDC,    pInfo->hPal, FALSE);
  3984.    RealizePalette(hDC);
  3985.    iPen = pInfo->iPen + 1;
  3986.    wsprintf(text, "iPen = %d\n", iPen);
  3987.    //MessageBox(ghwndMain, text, "Error", MB_OK);
  3988. #endif
  3989.  
  3990.    GetClientRect(pInfo->hwnd, &rc);
  3991.  
  3992.    hBitmap = CreateCompatibleBitmap(hDC, (int)rc.right, (int)rc.bottom);
  3993.    hOldBitmap = SelectObject(hDCMem, hBitmap);
  3994.  
  3995. #if 0
  3996.  {
  3997.    int iWidth, i, j;
  3998.  
  3999.    iWidth = rc.right/iNumClr;
  4000.  
  4001.    for (i = 0; i < iNumClr; i++) {
  4002.        SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[i % iNumClr]);
  4003.        for (j = 0; j < iWidth; j++) {
  4004.         MoveToEx(hDCMem, i*iWidth+j, 0, NULL);
  4005.         LineTo(hDCMem, i*iWidth+j, rc.bottom);
  4006.        }
  4007.  
  4008.    }
  4009.  }
  4010. #endif
  4011.  
  4012.    dwTick1 = GetTickCount();
  4013.  
  4014.    iScan = (((iScan = BATCH / rc.right) == 0) ? 1 : iScan);
  4015.  
  4016.    yCurr = rc.top;
  4017.    for (n=rc.top; n<=rc.bottom; n+=pInfo->iStep, yCurr+=pInfo->iStep, iPrev = FIRST_PIXEL) {
  4018.        xCurr = rc.left;                   // since LineTo excludes last point
  4019.        MoveToEx(hDCMem, 0, yCurr, NULL);
  4020.        c2 = Xform((double) n, 0.0, (double) rc.bottom, pInfo->yFrom, pInfo->yTo);
  4021.  
  4022.        for (m=rc.left; m<=rc.right; m++, xCurr++) {
  4023.        c1 = Xform((double) m, 0.0, (double) rc.right, pInfo->xFrom, pInfo->xTo);
  4024.        x = c1;
  4025.        y = c2;
  4026.  
  4027.        for (i=1; i<=pInfo->iIteration; i++) {
  4028.            x1 = (x - y) * (x + y) + c1;
  4029.            y1 = 2 * x * y + c2;
  4030.            r = x1 * x1 + y1 * y1;
  4031.            x = x1;
  4032.            y = y1;
  4033.            if (r > 4.0) {
  4034.            break;
  4035.            }
  4036.        }
  4037.  
  4038.        if (i != iPrev) {
  4039.            if (iPrev != FIRST_PIXEL) {
  4040.          switch(iPrev) {
  4041.            case 1:
  4042.                SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
  4043.             break;
  4044.            default:
  4045.                if (iPrev >= pInfo->iIteration) {
  4046.                 SelectObject(hDCMem, hpnBlack);
  4047.                 break;
  4048.                }
  4049.                SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[iPrev % iPen]);
  4050.                break;
  4051.          }
  4052.          iPrev = i;
  4053.          LineTo(hDCMem, xCurr, yCurr);
  4054.            }
  4055.            else
  4056.           iPrev = i;    // remember the color for the first pixel
  4057.        }
  4058.        }
  4059.  
  4060.        switch(i) {
  4061.           case 1:
  4062.               SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[0]);
  4063.            break;
  4064.           default:
  4065.           if (i >= pInfo->iIteration) {
  4066.                SelectObject(hDCMem, hpnBlack);
  4067.                break;
  4068.           }
  4069.           SelectObject(hDCMem, (HPEN)(pInfo->prghPen)[i % iPen]);
  4070.           break;
  4071.        }
  4072.  
  4073.        LineTo(hDCMem,xCurr,yCurr);
  4074.  
  4075.        sprintf(gtext, GetStringRes (IDS_DRAWING), ((FLOAT)n/(FLOAT)rc.bottom)*100);
  4076.  
  4077.        SetWindowText(pInfo->hTextWnd, gtext);
  4078.  
  4079.        if (n >= iScan * iBand) {
  4080.         BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  4081.         iBand++;
  4082.        }
  4083.    }
  4084.  
  4085.    if ((iDiff = iScan * iBand - rc.bottom) != 0) {
  4086.     BitBlt(hDC, 0, iScan * (iBand-1), rc.right, iScan-iDiff, hDCMem, 0, iScan * (iBand-1), SRCCOPY);
  4087.    }
  4088.  
  4089.    sprintf(gtext, GetStringRes (IDS_DRAWING_DONE));
  4090.  
  4091.    SetWindowText(pInfo->hTextWnd, gtext);
  4092.  
  4093.    ReleaseDC(pInfo->hwnd, hDC);
  4094.  
  4095.    pInfo->dwElapsed = GetTickCount() - dwTick1;
  4096.  
  4097.    if (pInfo->hBmpSaved)
  4098.        DeleteObject(pInfo->hBmpSaved);
  4099.  
  4100.    pInfo->hBmpSaved = SelectObject(hDCMem, hOldBitmap);
  4101.    pInfo->bDrawing = FALSE;
  4102. #ifndef THRDONE
  4103.    if (pInfo->prghPen != NULL) {
  4104.        for (i = 0; i <= pInfo->iPen; i++) {
  4105.        DeleteObject((HPEN) (pInfo->prghPen)[i]);
  4106.        }
  4107.        GlobalFree(pInfo->prghPen);
  4108.    }
  4109. #endif
  4110.  
  4111.    DeleteDC(hDCMem);
  4112.  
  4113.    ExitThread(0);
  4114.    return TRUE;
  4115. }
  4116.  
  4117.  
  4118. /******************************Public*Routine******************************\
  4119. *
  4120. * Xform
  4121. *
  4122. * Effects: Given m, find x.
  4123. *
  4124. *          Xform(Pt) : Src |--> Dest
  4125. * eg.
  4126. *          Src |----|--------|      |-->   Dest |----|--------|
  4127. *              -2   x        2                  0    m       320
  4128. *
  4129. *          x = (m - 0)/(320 - 0) * (2 - -2) + -2
  4130. *
  4131. * Warnings: 1. This will become a macro in the future for speed.  For now,
  4132. *              it is here for debugging purposes.
  4133. *
  4134. \**************************************************************************/
  4135. #if 0
  4136. double Xform(
  4137.    double Pt,
  4138.    double SrcFrom,
  4139.    double SrcTo,
  4140.    double DestFrom,
  4141.    double DestTo)
  4142. {
  4143.  //sprintf( gtext,"%g = Xform(%g, %g, %g, %g, %g)\n", ((Pt-SrcFrom)/(SrcTo-SrcFrom)*(DestTo-DestFrom))+DestFrom, Pt, SrcFrom, SrcTo, DestFrom, DestTo);
  4144.  //OutputDebugString( gtext );
  4145.  return(((Pt-SrcFrom)/(SrcTo-SrcFrom)*(DestTo-DestFrom))+DestFrom);
  4146. }
  4147. #endif
  4148.  
  4149. /******************************Public*Routine******************************\
  4150. *
  4151. * Xform2
  4152. *
  4153. * Effects: Given x, find m.
  4154. *
  4155. *          Xform(Pt) : Src |--> Dest
  4156. * eg.
  4157. *          Src |----|--------|      |-->   Dest |----|--------|
  4158. *              -2   x        2                  0    m       320
  4159. *
  4160. *          m = (x - -2)/(2 - -2) * 320
  4161. *
  4162. * Warnings: 1. This will become a macro in the future for speed.  For now,
  4163. *              it is here for debugging purposes.
  4164. *
  4165. \**************************************************************************/
  4166. #if 0
  4167. int Xform2(
  4168.    double Pt,
  4169.    double SrcFrom,
  4170.    double SrcTo,
  4171.    double DestFrom,
  4172.    double DestTo)
  4173. {
  4174.  //sprintf( gtext,"%g = Xform(%g, %g, %g, %g, %g)\n", ((Pt-SrcFrom)/(SrcTo-SrcFrom)*(DestTo-DestFrom))+DestFrom, Pt, SrcFrom, SrcTo, DestFrom, DestTo);
  4175.  //OutputDebugString( gtext );
  4176.  return((int) ((Pt-SrcFrom)/(SrcTo-SrcFrom)*(DestTo-DestFrom)+DestFrom));
  4177. }
  4178. #endif
  4179.  
  4180. /******************************Public*Routine******************************\
  4181. *
  4182. * SaveBitmap
  4183. *
  4184. * Effects:  Returns the handle of a bitmap corresponding to the window.
  4185. *           using utilizing BitBlt.
  4186. *
  4187. * Warnings:
  4188. *   // should we set the dirty flag here?
  4189. *
  4190. *
  4191. \**************************************************************************/
  4192.  
  4193. HBITMAP SaveBitmap(HWND hWnd, HPALETTE hPal) {
  4194.     HDC     hdcMem, hDC;
  4195.     HBITMAP hBitmap, hOldBitmap;
  4196.     RECT    rc;
  4197.     HPALETTE hPalOld, hPalMemOld;
  4198.     int     ii;
  4199.  
  4200.     hDC = GetDC(hWnd);
  4201.     GetClientRect(hWnd, &rc);
  4202.  
  4203.     if (hPal) {
  4204.  
  4205.     hPalOld = SelectPalette(hDC, hPal, FALSE);
  4206.     ii=RealizePalette(hDC);
  4207.     if (ii){
  4208.         UpdateColors (hDC);
  4209.     }
  4210.  
  4211.     }
  4212.  
  4213.     hdcMem = CreateCompatibleDC(hDC);
  4214.  
  4215.     if (hPal) {
  4216.  
  4217.     hPalMemOld = SelectPalette(hdcMem, hPal, FALSE);
  4218.     RealizePalette(hdcMem);
  4219.     }
  4220.  
  4221.     hBitmap = CreateCompatibleBitmap(hDC, (int)rc.right-rc.left, (int)rc.bottom-rc.top);
  4222.  
  4223.     hOldBitmap = SelectObject(hdcMem, hBitmap);
  4224.  
  4225.  
  4226.     BitBlt(hdcMem, 0, 0, (int)rc.right-rc.left, (int)rc.bottom-rc.top, hDC, 0, 0, SRCCOPY);
  4227.     hBitmap = SelectObject(hdcMem, hOldBitmap);
  4228.  
  4229.     DeleteDC(hdcMem);
  4230.     ReleaseDC(hWnd, hDC);
  4231.  
  4232.     return(hBitmap);
  4233.  
  4234. }
  4235.  
  4236. /******************************Public*Routine******************************\
  4237. *
  4238. * DrawBitmap
  4239. *
  4240. * Effects:
  4241. *
  4242. * Warnings:
  4243. *
  4244. \**************************************************************************/
  4245.  
  4246. void DrawBitmap(HDC hdc, PINFO pInfo, int xStart, int yStart, int cx, int cy) {
  4247.     BITMAP bm;
  4248.     HDC    hdcMem;
  4249.     POINT  ptSize, ptOrg;
  4250.     HPALETTE hPalOld, hPalMemOld;
  4251.     char    text[128];
  4252.  
  4253.     if ((pInfo->hPal) && !(pInfo->bUseMono)) {
  4254.  
  4255.     hPalOld = SelectPalette(hdc,
  4256.          ((pInfo->iStretchMode == HALFTONE) ? pInfo->hHTPal : pInfo->hPal),
  4257.          FALSE);
  4258.     //RealizePalette(hdc);
  4259.  
  4260.     wsprintf(text, "Realized Palette = %d", RealizePalette(hdc));
  4261.  
  4262.     OutputDebugString (text);
  4263.  
  4264.  
  4265.     UpdateColors (hdc);
  4266.     }
  4267.  
  4268.     hdcMem = CreateCompatibleDC(hdc);
  4269.  
  4270.     if ((pInfo->hPal) && !(pInfo->bUseMono)) {
  4271.  
  4272.     hPalMemOld = SelectPalette(hdcMem,
  4273.          ((pInfo->iStretchMode == HALFTONE) ? pInfo->hHTPal : pInfo->hPal),
  4274.           FALSE);
  4275.     //RealizePalette(hdcMem);
  4276.     wsprintf(text, "Realized Palette = %d", RealizePalette(hdcMem));
  4277.     OutputDebugString (text);
  4278.  
  4279.  
  4280.     UpdateColors (hdcMem);
  4281.  
  4282.  
  4283.  
  4284.     }
  4285.  
  4286.     SelectObject(hdcMem, (pInfo->bUseMono ? pInfo->hBmpMono : pInfo->hBmpSaved));
  4287.     SetMapMode(hdcMem, GetMapMode(hdc));
  4288.  
  4289.     GetObject((pInfo->bUseMono ? pInfo->hBmpMono : pInfo->hBmpSaved), sizeof(BITMAP), (LPSTR)&bm);
  4290.     ptSize.x = bm.bmWidth;
  4291.     ptSize.y = bm.bmHeight;
  4292.     DPtoLP(hdc, &ptSize, 1);
  4293.  
  4294.     ptOrg.x = 0;
  4295.     ptOrg.y = 0;
  4296.     DPtoLP(hdcMem, &ptOrg, 1);
  4297.  
  4298.     if (pInfo->bStretch) {
  4299.     SetStretchBltMode(hdc, pInfo->iStretchMode);
  4300.     // cx+1 and cy+1: temporary work around for a bug!
  4301.     StretchBlt(hdc, xStart, yStart, cx+1, cy+1,
  4302.            hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y,SRCCOPY);
  4303.     } else {
  4304.     BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y,
  4305.            hdcMem, xStart, yStart, SRCCOPY);
  4306.     }
  4307.  
  4308.     if (pInfo->bUseMono)
  4309.     pInfo->bUseMono = FALSE;
  4310.  
  4311.     DeleteDC(hdcMem);
  4312.     UNREFERENCED_PARAMETER(cx);
  4313.     UNREFERENCED_PARAMETER(cy);
  4314. }
  4315.  
  4316. /******************************Public*Routine******************************\
  4317. *
  4318. * bDrawDIB
  4319. *
  4320. * Effects:
  4321. *
  4322. * Warnings:
  4323. *
  4324. \**************************************************************************/
  4325.  
  4326. BOOL bDrawDIB(HDC hDC, PINFO pInfo, int xStart, int yStart, int cx, int cy)
  4327. {
  4328.     HBITMAP     hBmpOld, hBmp;
  4329.     BOOL        bSuccess;
  4330.     PBITMAPINFO pbmi;
  4331.     HDC         hdcMem;
  4332.     BITMAP      bm;
  4333.  
  4334.     bSuccess = TRUE;
  4335.     if (pInfo->bUseMono) {
  4336.     DrawBitmap(hDC, pInfo, xStart, yStart, cx, cy);
  4337.     return bSuccess;
  4338.     }
  4339.  
  4340.     if ((hBmp = pInfo->hBmpSaved) == NULL) {
  4341.  
  4342.         MessageBox(ghwndMain, GetStringRes (IDS_NO_BITMAP_TO_DRAW), 
  4343.                    NULL, MB_OK);
  4344.         return FALSE;
  4345.     }
  4346.  
  4347.     if (pInfo->bStretch) {
  4348.     SetStretchBltMode(hDC, pInfo->iStretchMode);
  4349.  
  4350.     if (pInfo->bUseDIB) { // this'll give a src for halftone...
  4351.         pbmi = (PBITMAPINFO) (pInfo->RleData.rgpbmi[0]);
  4352.  
  4353.         // Select and realize the appropriate palette to destination DC
  4354.         if ((pInfo->iStretchMode == HALFTONE) && (pInfo->hHTPal)) {
  4355.         SelectPalette(hDC, pInfo->hHTPal, FALSE);
  4356.         RealizePalette(hDC);
  4357.         } else {
  4358.         if ((pInfo->iStretchMode != HALFTONE) && (pInfo->hPal)) {
  4359.             SelectPalette(hDC, pInfo->hPal, FALSE);
  4360.             RealizePalette(hDC);
  4361.         }
  4362.         }
  4363.         if (pInfo->bCoreHdr) {
  4364.         StretchDIBits(hDC, xStart, yStart, cx, cy,
  4365.               0, 0, ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcWidth,
  4366.                 ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcHeight,
  4367.               (LPSTR)pInfo->RleData.rgpjFrame[0], pbmi, DIB_RGB_COLORS, SRCCOPY);
  4368.         } else {
  4369.         StretchDIBits(hDC, xStart, yStart, cx, cy,
  4370.               0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight,
  4371.               (LPSTR)pInfo->RleData.rgpjFrame[0], pbmi, DIB_RGB_COLORS, SRCCOPY);
  4372.         }
  4373.     } else { // image is dirty or created on this device
  4374.  
  4375.         HBITMAP     hDIB;
  4376.  
  4377.         //
  4378.         // Get the source DIB info from the DDB for halftoning
  4379.         //
  4380.         hDIB = DIBfromDDB(hDC, hBmp, pInfo);
  4381.  
  4382.         hdcMem = CreateCompatibleDC(hDC);
  4383.         hBmpOld = SelectObject(hdcMem, hDIB);
  4384.  
  4385.         if ((pInfo->iStretchMode == HALFTONE) && (pInfo->hHTPal)) {
  4386.         SelectPalette(hDC, pInfo->hHTPal, FALSE);
  4387.         RealizePalette(hDC);
  4388.         } else {
  4389.         if ((pInfo->iStretchMode != HALFTONE) && (pInfo->hPal)) {
  4390.             SelectPalette(hDC, pInfo->hPal, FALSE);
  4391.             RealizePalette(hDC);
  4392.         }
  4393.         }
  4394.  
  4395.         //
  4396.         // Use StretchBlt here instead of StretchDIBits just for
  4397.         // demonstrating using the API with halftone
  4398.         //
  4399.         GetObject(hDIB, sizeof(BITMAP), (LPSTR)&bm);
  4400.         StretchBlt(hDC, xStart, yStart, cx, cy, hdcMem,
  4401.               0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  4402.  
  4403.         DeleteDC(hdcMem);
  4404.  
  4405.     }
  4406.     return bSuccess;
  4407.     }
  4408.  
  4409.     //
  4410.     // Not stretching...No halftone
  4411.     //
  4412.  
  4413.     GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bm);
  4414.  
  4415.     // Select and realize the appropriate palette to destination DC
  4416.     if (pInfo->hPal) {
  4417.     SelectPalette(hDC, pInfo->hPal, FALSE);
  4418.     RealizePalette(hDC);
  4419.     }
  4420.  
  4421.     if (pInfo->bUseDIB) { // this'll give a src
  4422.     pbmi = (PBITMAPINFO) (pInfo->RleData.rgpbmi[0]);
  4423.  
  4424.     // default to use SetDIBitsToDevice
  4425.     SetDIBitsToDevice(hDC, xStart, yStart, bm.bmWidth, bm.bmHeight,
  4426.               0, 0, 0, bm.bmHeight, pInfo->RleData.rgpjFrame[0],
  4427.               pbmi, DIB_RGB_COLORS);
  4428.     } else { // image is dirty or created on this device
  4429.  
  4430.     hdcMem = CreateCompatibleDC(hDC);
  4431.     hBmpOld = SelectObject(hdcMem, hBmp);
  4432.  
  4433.     BitBlt(hDC, xStart, yStart, bm.bmWidth, bm.bmHeight,
  4434.            hdcMem, 0, 0, SRCCOPY);
  4435.  
  4436.     DeleteDC(hdcMem);
  4437.     }
  4438.  
  4439.     return bSuccess;
  4440. }
  4441.  
  4442. /******************************Public*Routine******************************\
  4443. *
  4444. * pGetInfoData(HWND hwnd)
  4445. *
  4446. * Effects:  calls LocalLock, returning pointer to Info structure.
  4447. *           assumes hwnd contains handle to Info structure at index 0.
  4448. *           should call bReleaseInfoData when done.
  4449. *           Global alert: ghwndMain used.
  4450. *
  4451. * Warnings:
  4452. *
  4453. \**************************************************************************/
  4454.  
  4455. PINFO pGetInfoData(HWND hwnd)
  4456. {
  4457.     HANDLE hInfo;
  4458.     PINFO  pInfo;
  4459.  
  4460.     hInfo = (HANDLE) GetWindowLong(hwnd, 0);
  4461.     if (hInfo == NULL) {
  4462.     OutputDebugString ("Null Info handle retrieved - GetInfo");
  4463.     return NULL;
  4464.     }
  4465.  
  4466.     if ((pInfo = (PINFO)LocalLock(hInfo)) == NULL) {
  4467.     return NULL;
  4468.     }
  4469.  
  4470.     return pInfo;
  4471. }
  4472.  
  4473. /******************************Public*Routine******************************\
  4474. *
  4475. * bReleaseInfoData(HWND hwnd)
  4476. *
  4477. * Effects: calls LocalUnlock.  Returns whatever LocalUnlock returns.
  4478. *
  4479. * Warnings: assumes LocalLock was called previously.
  4480. *           assumes hwnd contains handle to Info structure at index 0.
  4481. *           Global alert: ghwndMain used.
  4482. *
  4483. \**************************************************************************/
  4484.  
  4485. BOOL bReleaseInfoData(HWND hwnd)
  4486. {
  4487.     HANDLE hInfo;
  4488.  
  4489.     hInfo = (HANDLE) GetWindowLong(hwnd, 0);
  4490.     if (hInfo == NULL) {
  4491.     OutputDebugString ("Null Info handle retrieved - ReleaseInfo");
  4492.     return FALSE;
  4493.     }
  4494.  
  4495.     return (LocalUnlock(hInfo));
  4496. }
  4497.  
  4498.  
  4499. /******************************Public*Routine******************************\
  4500. *
  4501. * bCheckMutexMenuItem
  4502. *
  4503. * Effects: Put a check mark on uiCheckItem in the hMenu.  Remove previous
  4504. *          check mark, if any, on items in the same group.  Returns TRUE
  4505. *          if successful, FALSE otherwise (item not exists).
  4506. *
  4507. * Warnings:
  4508. *
  4509. \**************************************************************************/
  4510.  
  4511. BOOL bCheckMutexMenuItem(PINFO pInfo, HMENU hMenu, UINT uiCheckItem)
  4512. {
  4513.  
  4514.     switch(uiCheckItem) {
  4515.     case MM_TP_IDLE:
  4516.     case MM_TP_LOW:
  4517.     case MM_TP_BELOW_NORMAL:
  4518.     case MM_TP_NORMAL:
  4519.     case MM_TP_ABOVE_NORMAL:
  4520.     case MM_TP_HIGH:
  4521.     case MM_TP_TIME_CRITICAL:
  4522.         switch (pInfo->iPriority) {
  4523.         case THREAD_PRIORITY_IDLE:
  4524.             CheckMenuItem(hMenu, MM_TP_IDLE, MF_UNCHECKED);
  4525.             break;
  4526.         case THREAD_PRIORITY_LOWEST:
  4527.             CheckMenuItem(hMenu, MM_TP_LOW, MF_UNCHECKED);
  4528.             break;
  4529.         case THREAD_PRIORITY_BELOW_NORMAL:
  4530.             CheckMenuItem(hMenu, MM_TP_BELOW_NORMAL, MF_UNCHECKED);
  4531.             break;
  4532.         case THREAD_PRIORITY_NORMAL:
  4533.             CheckMenuItem(hMenu, MM_TP_NORMAL, MF_UNCHECKED);
  4534.             break;
  4535.         case THREAD_PRIORITY_ABOVE_NORMAL:
  4536.             CheckMenuItem(hMenu, MM_TP_ABOVE_NORMAL, MF_UNCHECKED);
  4537.             break;
  4538.         case THREAD_PRIORITY_HIGHEST:
  4539.             CheckMenuItem(hMenu, MM_TP_HIGH, MF_UNCHECKED);
  4540.             break;
  4541.         case THREAD_PRIORITY_TIME_CRITICAL:
  4542.             CheckMenuItem(hMenu, MM_TP_TIME_CRITICAL, MF_UNCHECKED);
  4543.             break;
  4544.         default:
  4545.             break;
  4546.         }
  4547.         break;
  4548.     case MM_FLOAT:
  4549.     case MM_FIX:
  4550.         CheckMenuItem(hMenu, MM_FLOAT, MF_UNCHECKED);
  4551.         CheckMenuItem(hMenu, MM_FIX,   MF_UNCHECKED);
  4552.         break;
  4553.     case MM_ITERATION_100:
  4554.     case MM_ITERATION_500:
  4555.     case MM_ITERATION_1000:
  4556.     case MM_ITERATION_5000:
  4557.     case MM_ITERATION_DOUBLE:
  4558.         switch (pInfo->iIteration) {
  4559.         case 100:
  4560.             CheckMenuItem(hMenu, MM_ITERATION_100, MF_UNCHECKED);
  4561.             break;
  4562.         case 500:
  4563.             CheckMenuItem(hMenu, MM_ITERATION_500, MF_UNCHECKED);
  4564.             break;
  4565.         case 1000:
  4566.             CheckMenuItem(hMenu, MM_ITERATION_1000, MF_UNCHECKED);
  4567.             break;
  4568.         case 5000:
  4569.             CheckMenuItem(hMenu, MM_ITERATION_5000, MF_UNCHECKED);
  4570.             break;
  4571.         default:
  4572.             CheckMenuItem(hMenu, MM_ITERATION_DOUBLE, MF_UNCHECKED);
  4573.             break;
  4574.         }
  4575.         break;
  4576.     case MM_STEP_ONE:
  4577.     case MM_STEP_TWO:
  4578.     case MM_STEP_THREE:
  4579.         switch (pInfo->iStep) {
  4580.         case 1:
  4581.             CheckMenuItem(hMenu, MM_STEP_ONE, MF_UNCHECKED);
  4582.             break;
  4583.         case 2:
  4584.             CheckMenuItem(hMenu, MM_STEP_TWO, MF_UNCHECKED);
  4585.             break;
  4586.         default:
  4587.             CheckMenuItem(hMenu, MM_STEP_THREE, MF_UNCHECKED);
  4588.             break;
  4589.         }
  4590.         break;
  4591.     case MM_STRETCHBLT:
  4592.     case MM_BITBLT:
  4593.         CheckMenuItem(hMenu, MM_STRETCHBLT,   MF_UNCHECKED);
  4594.         CheckMenuItem(hMenu, MM_BITBLT,       MF_UNCHECKED);
  4595.         break;
  4596.     case MM_BLACKONWHITE:
  4597.     case MM_COLORONCOLOR:
  4598.     case MM_WHITEONBLACK:
  4599.     case MM_HALFTONE:
  4600.         switch (pInfo->iStretchMode) {
  4601.         case BLACKONWHITE:
  4602.             CheckMenuItem(hMenu, MM_BLACKONWHITE, MF_UNCHECKED);
  4603.             break;
  4604.         case COLORONCOLOR:
  4605.             CheckMenuItem(hMenu, MM_COLORONCOLOR, MF_UNCHECKED);
  4606.             break;
  4607.         case WHITEONBLACK:
  4608.             CheckMenuItem(hMenu, MM_WHITEONBLACK, MF_UNCHECKED);
  4609.             break;
  4610.         case HALFTONE:
  4611.             CheckMenuItem(hMenu, MM_HALFTONE, MF_UNCHECKED);
  4612.             break;
  4613.         default:
  4614.             break;
  4615.         }
  4616.         break;
  4617.     case MM_PORTRAIT:
  4618.     case MM_LANDSCAPE:
  4619.         CheckMenuItem(hMenu, MM_PORTRAIT,   MF_UNCHECKED);
  4620.         CheckMenuItem(hMenu, MM_LANDSCAPE,  MF_UNCHECKED);
  4621.         break;
  4622.     default:
  4623.         return FALSE;
  4624.     }
  4625.     CheckMenuItem(hMenu, uiCheckItem, MF_CHECKED);
  4626.     return TRUE;
  4627. }
  4628.  
  4629.  
  4630. /******************************Public*Routine******************************\
  4631. *
  4632. * vChkMenuItem
  4633. *
  4634. * Effects:  Helper function for checking or unchecking menu items based on
  4635. *           values set in the pInfo.  Gets called when processing
  4636. *           WM_MDIACTIVATE
  4637. *
  4638. * Warnings:
  4639. *
  4640. \**************************************************************************/
  4641.  
  4642. VOID vChkMenuItem(PINFO pInfo, HMENU hMenu, UINT uiFlag)
  4643. {
  4644.     (pInfo->bStretch ?
  4645.     CheckMenuItem(hMenu, MM_STRETCHBLT, uiFlag) :
  4646.     CheckMenuItem(hMenu, MM_BITBLT, uiFlag) );
  4647.  
  4648.     switch (pInfo->iPriority) {
  4649.     case THREAD_PRIORITY_IDLE:
  4650.         CheckMenuItem(hMenu, MM_TP_IDLE, uiFlag);
  4651.         break;
  4652.     case THREAD_PRIORITY_LOWEST:
  4653.         CheckMenuItem(hMenu, MM_TP_LOW, uiFlag);
  4654.         break;
  4655.     case THREAD_PRIORITY_BELOW_NORMAL:
  4656.         CheckMenuItem(hMenu, MM_TP_BELOW_NORMAL, uiFlag);
  4657.         break;
  4658.     case THREAD_PRIORITY_NORMAL:
  4659.         CheckMenuItem(hMenu, MM_TP_NORMAL, uiFlag);
  4660.         break;
  4661.     case THREAD_PRIORITY_ABOVE_NORMAL:
  4662.         CheckMenuItem(hMenu, MM_TP_ABOVE_NORMAL, uiFlag);
  4663.         break;
  4664.     case THREAD_PRIORITY_HIGHEST:
  4665.         CheckMenuItem(hMenu, MM_TP_HIGH, uiFlag);
  4666.         break;
  4667.     case THREAD_PRIORITY_TIME_CRITICAL:
  4668.         CheckMenuItem(hMenu, MM_TP_TIME_CRITICAL, uiFlag);
  4669.         break;
  4670.     default:
  4671.         break;
  4672.     }
  4673.  
  4674.     switch (pInfo->iStretchMode) {
  4675.     case BLACKONWHITE:
  4676.         CheckMenuItem(hMenu, MM_BLACKONWHITE, uiFlag);
  4677.         break;
  4678.     case COLORONCOLOR:
  4679.         CheckMenuItem(hMenu, MM_COLORONCOLOR, uiFlag);
  4680.         break;
  4681.     case WHITEONBLACK:
  4682.         CheckMenuItem(hMenu, MM_WHITEONBLACK, uiFlag);
  4683.         break;
  4684.     case HALFTONE:
  4685.         CheckMenuItem(hMenu, MM_HALFTONE, uiFlag);
  4686.         break;
  4687.     default:
  4688.         break;
  4689.     }
  4690.  
  4691.     switch (pInfo->iStep) {
  4692.     case 1:
  4693.         CheckMenuItem(hMenu, MM_STEP_ONE, uiFlag);
  4694.         break;
  4695.     case 2:
  4696.         CheckMenuItem(hMenu, MM_STEP_TWO, uiFlag);
  4697.         break;
  4698.     default:
  4699.         CheckMenuItem(hMenu, MM_STEP_THREE, uiFlag);
  4700.         break;
  4701.     }
  4702.  
  4703.     switch (pInfo->iIteration) {
  4704.     case 100:
  4705.         CheckMenuItem(hMenu, MM_ITERATION_100, uiFlag);
  4706.         break;
  4707.     case 500:
  4708.         CheckMenuItem(hMenu, MM_ITERATION_500, uiFlag);
  4709.         break;
  4710.     case 1000:
  4711.         CheckMenuItem(hMenu, MM_ITERATION_1000, uiFlag);
  4712.         break;
  4713.     case 5000:
  4714.         CheckMenuItem(hMenu, MM_ITERATION_5000, uiFlag);
  4715.         break;
  4716.     default:
  4717.         CheckMenuItem(hMenu, MM_ITERATION_DOUBLE, uiFlag);
  4718.         break;
  4719.     }
  4720.     return;
  4721. }
  4722.  
  4723. /******************************Public*Routine******************************\
  4724. *
  4725. * bInitInfo
  4726. *
  4727. * Effects: Initialize the Info data structure
  4728. *
  4729. * Warnings:
  4730. *
  4731. \**************************************************************************/
  4732.  
  4733. BOOL bInitInfo(PINFO pInfo)
  4734. {
  4735.     pInfo->hParent      = ghwndClient;
  4736.     pInfo->xFrom        = -2.0;
  4737.     pInfo->xTo          = 1.0;
  4738.     pInfo->yFrom        = 1.5;
  4739.     pInfo->yTo          = -1.5;
  4740.     pInfo->lxFrom       = -16777216;                 // 9.23 fix point
  4741.     pInfo->lxTo         =  8388608;                  // representation of
  4742.     pInfo->lyFrom       =  12582912;                 // -2, 1.0, 1.5, and -1.5
  4743.     pInfo->lyTo         = -12582912;                 //
  4744.     pInfo->iIteration   = gIteration;
  4745.     pInfo->iStep        = gStep;
  4746.     pInfo->bStretch     = gbStretch;
  4747.     pInfo->iStretchMode = giStretchMode;
  4748.     wsprintf((LPSTR) &(pInfo->CaptionBarText), "");
  4749.     pInfo->hwnd         = NULL;
  4750.     pInfo->hTextWnd     = NULL;
  4751.     pInfo->rcClient.top    = 0;
  4752.     pInfo->rcClient.left   = 0;
  4753.     pInfo->rcClient.bottom = 0;
  4754.     pInfo->rcClient.right  = 0;
  4755.     pInfo->hdcClient    = NULL;
  4756.     pInfo->hRgnPath     = NULL;
  4757.     pInfo->hThrd0       = NULL;
  4758.     pInfo->hThrd        = NULL;
  4759.     pInfo->bDrawing     = FALSE;
  4760.     pInfo->dwThreadId   = 0;
  4761.     pInfo->dwElapsed    = 0L;
  4762.     pInfo->c1           = 0.0;
  4763.     pInfo->c2           = 0.0;
  4764.     pInfo->lc1          = 0L;
  4765.     pInfo->lc2          = 0L;
  4766.     pInfo->hBmpSaved    = NULL;
  4767.     pInfo->bSizeChng    = FALSE;
  4768.     pInfo->bMandel      = TRUE;
  4769.     pInfo->bSetDIBsToDevice = FALSE;
  4770.     pInfo->bFill        = FALSE;
  4771.     pInfo->hBrush       = NULL;
  4772.     pInfo->hQuitEvent   = NULL;
  4773.     pInfo->hCycleThrd   = NULL;
  4774.     pInfo->dwCycleThrdID = 0;
  4775.     pInfo->bClrCycle    = FALSE;
  4776.     pInfo->bFirstTime   = TRUE;
  4777.     pInfo->dwSuspend    = 0;
  4778.     pInfo->hBmpMono     = NULL;
  4779.     pInfo->bUseMono     = FALSE;
  4780.     pInfo->hPrtThrd     = NULL;
  4781.     pInfo->dwPrtThrdID  = 0;
  4782.     pInfo->hPal         = NULL;
  4783.     pInfo->hCyclePal    = NULL;
  4784.     pInfo->RleData.ulFiles  = 0;
  4785.     pInfo->RleData.ulFrames = 0;
  4786.     pInfo->bPlayRleCont = FALSE;
  4787.     pInfo->prghPen      = NULL;
  4788.     pInfo->iPen         = 0;
  4789.     pInfo->iPriority    = THREAD_PRIORITY_NORMAL;
  4790.     pInfo->bUseDIB      = FALSE;
  4791.     pInfo->bCoreHdr     = FALSE;
  4792.  
  4793.     return TRUE;
  4794. }
  4795.  
  4796. /******************************Public*Routine******************************\
  4797. *
  4798. * bResetGlobal
  4799. *
  4800. * Effects: Set (l) x/y From/To to their default values
  4801. *          Used for Julia set
  4802. *
  4803. * Warnings:
  4804. *
  4805. \**************************************************************************/
  4806.  
  4807. BOOL bResetGlobal(VOID)
  4808. {
  4809.     xFrom  =  -2.0;
  4810.     xTo    =   2.0;
  4811.     yFrom  =   2.0;
  4812.     yTo    =  -2.0;
  4813.     lxFrom =  -16777216;
  4814.     lxTo   =   16777216;
  4815.     lyFrom =   16777216;
  4816.     lyTo   =  -16777216;
  4817.     return TRUE;
  4818. }
  4819.  
  4820. /******************************Public*Routine******************************\
  4821. *
  4822. * hBrCreateBrush
  4823. *
  4824. * Effects: Creates a brush with the specified RGB
  4825. *
  4826. * Warnings:
  4827. *
  4828. \**************************************************************************/
  4829.  
  4830. HBRUSH hBrCreateBrush(HDC hDC, DWORD dwRGB)
  4831. {
  4832.     HDC hdcMem;
  4833.     HBRUSH hbr;
  4834.     HBRUSH hbrOld;
  4835.     HBITMAP hbmPat;
  4836.     HBITMAP hbmOld;
  4837.  
  4838.     hbr = CreateSolidBrush(dwRGB);
  4839.     hdcMem = CreateCompatibleDC(hDC);
  4840.  
  4841.     //
  4842.     // Minimum size for a bitmap to be used in a fill pattern is 8x8
  4843.     //
  4844.     hbmPat = CreateCompatibleBitmap(hDC, 8, 8);
  4845.  
  4846.     hbmOld = SelectObject(hdcMem, hbmPat);
  4847.     hbrOld = SelectObject(hdcMem, hbr);
  4848.     PatBlt(hdcMem, 0, 0, 8, 8, PATCOPY);
  4849.  
  4850.     //
  4851.     // Deselect hbmPat and hbr
  4852.     //
  4853.     SelectObject(hdcMem, hbmOld);
  4854.     SelectObject(hdcMem, hbrOld);
  4855.  
  4856.     DeleteDC(hdcMem);
  4857.     DeleteObject(hbr);
  4858.  
  4859.     hbr = CreatePatternBrush(hbmPat);
  4860.  
  4861.     DeleteObject(hbmPat);
  4862.  
  4863.     return hbr;
  4864. }
  4865.  
  4866.  
  4867. /******************************Public*Routine******************************\
  4868. *
  4869. * bPrintBmp
  4870. *
  4871. * Effects: A Thread routine for printing bitmap
  4872. *
  4873. * Warnings:
  4874. *
  4875. \**************************************************************************/
  4876.  
  4877. BOOL bPrintBmp(PPRTDATA pPrtData) {
  4878.     HDC         hdcPrinter;
  4879.     int         iWidth, iHeight;
  4880.  
  4881. #ifdef NEWPRTAPI
  4882.     DOCINFO     DocInfo;
  4883. #endif
  4884.  
  4885.     if (pPrtData->bUseDefault) {
  4886.       hdcPrinter = CreateDC( "", gpszPrinterNames[pPrtData->index],
  4887.                  "", NULL);
  4888.     } else {
  4889.       hdcPrinter = CreateDC( "", gpszPrinterNames[pPrtData->index],
  4890.                  "", &(pPrtData->DevMode));
  4891.     }
  4892.  
  4893.     if (!hdcPrinter)
  4894.     {
  4895.     ExitThread(0);
  4896.     return(FALSE);
  4897.     }
  4898.  
  4899.     iWidth = GetDeviceCaps(hdcPrinter, HORZRES);
  4900.     iHeight = GetDeviceCaps(hdcPrinter, VERTRES);
  4901.  
  4902. #ifdef NEWPRTAPI
  4903.  
  4904.     memset(&DocInfo, 0, sizeof(DOCINFO));
  4905.     DocInfo.cbSize      = sizeof(DOCINFO);
  4906.     DocInfo.lpszDocName = pPrtData->info.CaptionBarText;
  4907.     DocInfo.lpszOutput   = NULL;
  4908.     StartDoc(hdcPrinter, &DocInfo);
  4909.     StartPage(hdcPrinter);
  4910.     bDrawDIB(hdcPrinter, &(pPrtData->info), 0, 0, iWidth, iHeight);
  4911.     EndPage(hdcPrinter);
  4912.     EndDoc(hdcPrinter);
  4913.  
  4914. #else
  4915.  
  4916.     Escape(hdcPrinter, STARTDOC, 20, "Mandelbrot", NULL);
  4917.     bDrawDIB(hdcPrinter, &(pPrtData->info), 0, 0, iWidth, iHeight);
  4918.     Escape(hdcPrinter, NEWFRAME, 0, NULL, NULL);
  4919.     Escape(hdcPrinter, ENDDOC, 0, NULL, NULL);
  4920.  
  4921. #endif
  4922.  
  4923.     DeleteDC(hdcPrinter);
  4924.     ExitThread(0);
  4925.     return(TRUE);
  4926.  
  4927. }
  4928.  
  4929.  
  4930.  
  4931. /******************************Public*Routine******************************\
  4932. *
  4933. * StoreRleFile
  4934. *
  4935. * Effects:
  4936. *
  4937. * Warnings:
  4938. *
  4939. \**************************************************************************/
  4940.  
  4941. BOOL bStoreRleFile(HDC hDC, PINFO pInfo, PSTR pszFileName)
  4942. {
  4943.   BOOL                bSuccess;
  4944.   HANDLE              hFile, hMapFile;
  4945.   LPVOID              pMapFile;
  4946.   LPBITMAPINFOHEADER  pbmh;
  4947.   LPBITMAPINFO        pbmi;
  4948.   PBYTE               pjTmp, pjDIBits, pjRleBits;
  4949.   ULONG               sizBMI, sizImage, ulfSize;
  4950.   DWORD               dwOffBits;
  4951.   LONG                lScan;
  4952.   INT                 iNumClr;
  4953.   ULONG               ulFrames, ulFiles, ulOffset;
  4954.   PFILEINFO           pFileInfo;
  4955.   DWORD               dwFileSizeLow, dwFileSizeHigh;
  4956.   WORD                wBitCount;
  4957.   BOOL                bCoreHdr;
  4958.  
  4959.   bSuccess = TRUE;
  4960.  
  4961.   if ((hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  4962.       OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL)) == (HANDLE)-1) {
  4963.       bSuccess = FALSE;
  4964.       goto ErrExit1;
  4965.   }
  4966.  
  4967.   dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh);
  4968.   if ((dwFileSizeLow == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
  4969.       bSuccess = FALSE;
  4970.       goto ErrExit2;
  4971.   }
  4972.  
  4973.   //
  4974.   // Create a map file of the opened file
  4975.   //
  4976.   if ((hMapFile = CreateFileMapping(hFile, NULL,
  4977.                PAGE_READONLY, 0, 0, NULL)) == (HANDLE)-1) {
  4978.       bSuccess = FALSE;
  4979.       goto ErrExit2;
  4980.   }
  4981.  
  4982.   //
  4983.   // Map a view of the whole file
  4984.   //
  4985.   if ((pMapFile = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0)) == NULL) {
  4986.       bSuccess = FALSE;
  4987.       goto ErrExit3;
  4988.   }
  4989.  
  4990.   ulFiles = pInfo->RleData.ulFiles;
  4991.   pFileInfo = &(pInfo->RleData.rgFileInfo[ulFiles]);
  4992.   pFileInfo->hFile = hFile;
  4993.   pFileInfo->hMapFile = hMapFile;
  4994.   pFileInfo->lpvMapView = pMapFile;
  4995.  
  4996.   ulFrames = pInfo->RleData.ulFrames;
  4997.   ulOffset = 0;
  4998.  
  4999.   while (TRUE) {
  5000.     //
  5001.     // First check that it is a bitmap file
  5002.     //
  5003.     if (*((PWORD)pMapFile) != 0x4d42) {              // 'BM'
  5004.     OutputDebugString ("This is not a DIB bitmap file!");
  5005.     bSuccess = FALSE;
  5006.     goto ErrExit3;
  5007.     }
  5008. #ifdef DEBUG
  5009.     {
  5010.     static ULONG ulCnt=0;
  5011.     char buf[128];
  5012.  
  5013.     ulCnt++;
  5014.     wsprintf(buf, "ulCnt = %ld", ulCnt);
  5015.     OutputDebugString (buf);
  5016.     }
  5017. #endif
  5018.     //
  5019.     // Saving the bfSize field in the BITMAPFILEHEADER for incrementing to the
  5020.     // next frame.  bfSize does not start at DWORD boundary...
  5021.     //
  5022.     {
  5023.       PBYTE   pjTmp;
  5024.       FILEHDR fHdr, *pfHdr;
  5025.       ULONG   ulSiz;
  5026.  
  5027.       pjTmp = (PBYTE)pMapFile+2;
  5028.       pfHdr = &fHdr;
  5029.  
  5030.       ulSiz = sizeof(FILEHDR);
  5031.       while (ulSiz--) {
  5032.       *(((PBYTE)pfHdr)++) = *(((PBYTE)pjTmp)++);
  5033.       }
  5034.       ulfSize = fHdr.bfSize;
  5035.       dwOffBits = fHdr.bfOffbits;
  5036.     }
  5037.  
  5038.     //
  5039.     // advance pMapFile to point pass BITMAPFILEHEADER
  5040.     //
  5041.     //pMapFile = (PBYTE)pMapFile + sizeof(BITMAPFILEHEADER);
  5042.  
  5043.     //
  5044.     // Since the file header doesn't end on DWORD boundary...
  5045.     //
  5046.     pbmh = (LPBITMAPINFOHEADER)((PBYTE)pMapFile + sizeof(BITMAPFILEHEADER));
  5047.  
  5048.     {
  5049.     BITMAPCOREHEADER bmch, *pbmch;
  5050.     BITMAPINFOHEADER bmih, *pbmih;
  5051.     PBYTE            pjTmp;
  5052.     ULONG            ulSiz;
  5053.  
  5054.     pbmch = &bmch;
  5055.     pbmih = &bmih;
  5056.  
  5057.     pjTmp = (PBYTE)pbmh;
  5058.     ulSiz = sizeof(BITMAPCOREHEADER);
  5059.     while (ulSiz--) {
  5060.         *(((PBYTE)pbmch)++) = *(((PBYTE)pjTmp)++);
  5061.     }
  5062.  
  5063.     pjTmp = (PBYTE)pbmh;
  5064.     ulSiz = sizeof(BITMAPINFOHEADER);
  5065.     while (ulSiz--) {
  5066.         *(((PBYTE)pbmih)++) = *(((PBYTE)pjTmp)++);
  5067.     }
  5068.  
  5069.     //
  5070.     // Use the size to determine if it is a BitmapCoreHeader or
  5071.     // BitmapInfoHeader
  5072.     //
  5073.     if (bmch.bcSize == sizeof(BITMAPCOREHEADER))
  5074.     {
  5075.         wBitCount = bmch.bcBitCount;
  5076.         iNumClr = ((wBitCount == 24) ? 0 : (1 << wBitCount));
  5077.         sizBMI = sizeof(BITMAPCOREHEADER)+sizeof(RGBTRIPLE)*iNumClr;
  5078.         bCoreHdr = TRUE;
  5079.     }
  5080.     else            // BITMAPINFOHEADER
  5081.     {
  5082.         wBitCount = bmih.biBitCount;
  5083.         switch (wBitCount) {
  5084.         case 16:
  5085.         case 32:
  5086.             sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3;
  5087.             break;
  5088.         case 24:
  5089.             sizBMI = sizeof(BITMAPINFOHEADER);
  5090.             break;
  5091.         default:
  5092.             iNumClr = (1 << wBitCount);
  5093.             sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*iNumClr;
  5094.             break;
  5095.         }
  5096.         bCoreHdr = FALSE;
  5097.     }
  5098.     }
  5099.  
  5100.     if ((pbmi = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED,sizBMI)) == NULL) {
  5101.         bSuccess = FALSE;
  5102.         goto ErrExit3;
  5103.     }
  5104.  
  5105.     //
  5106.     // Make sure we pass in a DWORD aligned BitmapInfo to CreateDIBitmap
  5107.     // Otherwise, exception on the MIPS platform
  5108.     // CR!!!  Equivalent to memcpy
  5109.     //
  5110.     pjTmp = (PBYTE)pbmi;
  5111.  
  5112.     while(sizBMI--)
  5113.     {
  5114.     *(((PBYTE)pjTmp)++) = *(((PBYTE)pbmh)++);
  5115.     }
  5116.  
  5117.     //
  5118.     // assuming CreateDIBitmap() is doing a byte fetch...
  5119.     //
  5120.     pjDIBits = (PBYTE)pMapFile + dwOffBits;
  5121.  
  5122.     if (pbmi->bmiHeader.biCompression == BI_RGB)
  5123.     {
  5124.     //
  5125.     // Converting to RLE bits...
  5126.     //
  5127.  
  5128.     OutputDebugString ("Converting to RLE format!");
  5129.     lScan = pbmi->bmiHeader.biHeight;
  5130.     sizImage = pbmi->bmiHeader.biSizeImage;
  5131.  
  5132.     //
  5133.     // select the palette into the DC first...
  5134.     //
  5135.     bSelectDIBPal(hDC, pInfo, pbmi, bCoreHdr);
  5136.     if ((pInfo->hBmpSaved = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)pbmi,
  5137.                 CBM_INIT, pjDIBits, pbmi, DIB_RGB_COLORS)) == NULL) {
  5138.         bSuccess = FALSE;
  5139.         goto ErrExit4;
  5140.     }
  5141.  
  5142.     // We want to retrieve the RLE format...
  5143.     pbmi->bmiHeader.biCompression = ((wBitCount==4) ? BI_RLE4 : BI_RLE8);
  5144.  
  5145.     pbmi->bmiHeader.biSizeImage = 0;
  5146.     pbmi->bmiHeader.biXPelsPerMeter = 0;
  5147.     pbmi->bmiHeader.biYPelsPerMeter = 0;
  5148.     pbmi->bmiHeader.biClrUsed = 0;
  5149.     pbmi->bmiHeader.biClrImportant = 0;
  5150.  
  5151.     if (GetDIBits(hDC, pInfo->hBmpSaved, 0, lScan, NULL, pbmi,
  5152.         DIB_RGB_COLORS) == 0) {
  5153.          OutputDebugString ("Not all scans are converted!");
  5154.          bSuccess = FALSE;
  5155.          goto ErrExit4;
  5156.     }
  5157.  
  5158.     if (pbmi->bmiHeader.biSizeImage == 0) {
  5159.         if (sizImage == 0) {
  5160.         OutputDebugString ("biSizeImage == 0!");
  5161.         bSuccess = FALSE;
  5162.         goto ErrExit4;
  5163.         }
  5164.         OutputDebugString ("Engine returns zero image size, making one up!");
  5165.         sizImage = (sizImage *3)/2;
  5166.     } else {
  5167.         sizImage = pbmi->bmiHeader.biSizeImage;
  5168.     }
  5169.  
  5170.     if ((pjRleBits = (PBYTE) LocalAlloc(LMEM_FIXED, sizImage)) == NULL) {
  5171.          bSuccess = FALSE;
  5172.          goto ErrExit4;
  5173.     }
  5174.  
  5175.     pbmi->bmiHeader.biSizeImage = sizImage;
  5176.     if (GetDIBits(hDC, pInfo->hBmpSaved, 0, lScan, pjRleBits, pbmi,
  5177.         DIB_RGB_COLORS) < lScan) {
  5178.          bSuccess = FALSE;
  5179.          goto ErrExit5;
  5180.     }
  5181.  
  5182.     SetDIBitsToDevice(hDC, 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight,
  5183.               0, 0, 0, lScan, pjRleBits, pbmi, DIB_RGB_COLORS);
  5184.  
  5185.     pInfo->RleData.rgpjFrame[ulFrames] = pjRleBits;
  5186.     } else {
  5187.     bSelectDIBPal(hDC, pInfo, pbmi, bCoreHdr);
  5188.     lScan = pbmi->bmiHeader.biHeight;
  5189.     if (bCoreHdr) {
  5190.        lScan = ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcHeight;
  5191.        SetDIBitsToDevice(hDC, 0, 0, ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcWidth, ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcHeight,
  5192.               0, 0, 0, lScan, pjDIBits, pbmi, DIB_RGB_COLORS);
  5193.     } else {
  5194.        lScan = pbmi->bmiHeader.biHeight;
  5195.        SetDIBitsToDevice(hDC, 0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight,
  5196.               0, 0, 0, lScan, pjDIBits, pbmi, DIB_RGB_COLORS);
  5197.     }
  5198.     pInfo->RleData.rgpjFrame[ulFrames] = pjDIBits;
  5199.     }
  5200.  
  5201.     pInfo->RleData.ulSize[ulFrames] = sizImage;
  5202.     pInfo->RleData.rgpbmi[ulFrames] = pbmi;
  5203.  
  5204.     //
  5205.     // Go to next frame
  5206.     //
  5207.     pMapFile = (PBYTE)pMapFile + ulfSize;
  5208.     ulOffset += ulfSize;
  5209.     ulFrames++;
  5210.  
  5211.     //
  5212.     // end condition
  5213.     //
  5214.     if (ulOffset >= dwFileSizeLow) {
  5215.     break;
  5216.     }
  5217.  
  5218.   }
  5219.  
  5220.     //
  5221.     // set pbmi to the very first bmi
  5222.     //
  5223.     pInfo->RleData.pbmi = pInfo->RleData.rgpbmi[0];
  5224.  
  5225.     pInfo->RleData.hPal = pInfo->hPal;
  5226.     pInfo->RleData.ulFrames = ulFrames;
  5227.     return (bSuccess);
  5228.  
  5229. ErrExit5:
  5230.     LocalFree(pjRleBits);
  5231. ErrExit4:
  5232.     LocalFree(pbmi);
  5233. ErrExit3:
  5234.     CloseHandle(pFileInfo->hMapFile);
  5235. ErrExit2:
  5236.     CloseHandle(pFileInfo->hFile);
  5237. ErrExit1:
  5238.     return (bSuccess);
  5239.  
  5240. }
  5241.  
  5242. /******************************Public*Routine******************************\
  5243. *
  5244. * bSelectDIBPal
  5245. *
  5246. * Effects: Creates a logical palette from the DIB and select it into the DC
  5247. *          and realize the palette. Saving the hPal in the pInfo->hPal
  5248. *
  5249. * Warnings: Based on Windows NT DIB support.  If PM support 16,24,32 bpp
  5250. *           we need to modify this routine.
  5251. *
  5252. \**************************************************************************/
  5253.  
  5254. BOOL bSelectDIBPal(HDC hDC, PINFO pInfo, LPBITMAPINFO pbmi, BOOL bCoreHdr)
  5255. {
  5256.   LOGPALETTE    *plogPal;
  5257.   UINT          uiSizPal;
  5258.   INT           i, iNumClr;
  5259.   WORD          wBitCount;
  5260.  
  5261.   if (bCoreHdr) {
  5262.     wBitCount = ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcBitCount;
  5263.   } else {
  5264.     wBitCount = pbmi->bmiHeader.biBitCount;
  5265.   }
  5266.  
  5267.   switch (wBitCount) {
  5268.     case 16:
  5269.     case 24:
  5270.     case 32:                            // Does PM supports these?
  5271.     return FALSE;
  5272.     default:
  5273.     iNumClr = (1 << wBitCount);
  5274.     break;
  5275.   }
  5276.  
  5277.   uiSizPal = sizeof(WORD)*2 + sizeof(PALETTEENTRY)*iNumClr;
  5278.   if ((plogPal = (LOGPALETTE *) LocalAlloc(LMEM_FIXED,uiSizPal)) == NULL) {
  5279.       pInfo->hPal = NULL;
  5280.       return FALSE;
  5281.   }
  5282.  
  5283.   plogPal->palVersion = 0x300;
  5284.   plogPal->palNumEntries = (WORD) iNumClr;
  5285.  
  5286.   if (bCoreHdr) {
  5287.     for (i=0; i<iNumClr; i++) {
  5288.     plogPal->palPalEntry[i].peRed   = ((LPBITMAPCOREINFO)pbmi)->bmciColors[i].rgbtRed;
  5289.     plogPal->palPalEntry[i].peGreen = ((LPBITMAPCOREINFO)pbmi)->bmciColors[i].rgbtGreen;
  5290.     plogPal->palPalEntry[i].peBlue  = ((LPBITMAPCOREINFO)pbmi)->bmciColors[i].rgbtBlue;
  5291.     plogPal->palPalEntry[i].peFlags = PC_RESERVED;
  5292.     }
  5293.   } else {
  5294.     for (i=0; i<iNumClr; i++) {
  5295.     plogPal->palPalEntry[i].peRed   = pbmi->bmiColors[i].rgbRed;
  5296.     plogPal->palPalEntry[i].peGreen = pbmi->bmiColors[i].rgbGreen;
  5297.     plogPal->palPalEntry[i].peBlue  = pbmi->bmiColors[i].rgbBlue;
  5298.     plogPal->palPalEntry[i].peFlags = PC_RESERVED;
  5299.     }
  5300.   }
  5301.  
  5302.   DeleteObject(pInfo->hPal);
  5303.   pInfo->hPal = CreatePalette((LPLOGPALETTE)plogPal);
  5304.   if ((pInfo->hPal) == NULL) {
  5305.       return FALSE;
  5306.   }
  5307.  
  5308.   if ((GetDeviceCaps(hDC, RASTERCAPS)) & RC_PALETTE) {
  5309.     SelectPalette(hDC, pInfo->hPal, FALSE);
  5310.     RealizePalette(hDC);
  5311.   }
  5312.  
  5313.   GlobalFree(plogPal);
  5314.  
  5315.   return TRUE;
  5316. }
  5317.  
  5318. /******************************Public*Routine******************************\
  5319. *
  5320. * bFreeRleFile
  5321. *
  5322. * Effects:
  5323. *
  5324. * Warnings:
  5325. *
  5326. \**************************************************************************/
  5327.  
  5328. BOOL bFreeRleFile(PINFO pInfo)
  5329. {
  5330.     ULONG               ulFiles;
  5331.     ULONG               ulFrames;
  5332.     ULONG               i;
  5333.     PFILEINFO           pFileInfo;
  5334.  
  5335.     ulFiles = pInfo->RleData.ulFiles;
  5336.     ulFrames = pInfo->RleData.ulFrames;
  5337.  
  5338.     for (i = 0; i < ulFrames; i++) {
  5339.     LocalFree(pInfo->RleData.rgpjFrame[i]);
  5340.     LocalFree(pInfo->RleData.rgpbmi[i]);
  5341.     }
  5342.  
  5343.     for (i = 0; i < ulFiles; i++) {
  5344.     pFileInfo = &(pInfo->RleData.rgFileInfo[i]);
  5345.     CloseHandle(pFileInfo->hFile);
  5346.     CloseHandle(pFileInfo->hMapFile);
  5347.     UnmapViewOfFile(pFileInfo->lpvMapView);
  5348.     }
  5349.  
  5350.     pInfo->RleData.ulFiles = 0;
  5351.     pInfo->RleData.ulFrames = 0;
  5352.     return TRUE;
  5353. }
  5354.  
  5355. /******************************Public*Routine******************************\
  5356. *
  5357. * bPlayRle
  5358. *
  5359. * Effects:
  5360. *
  5361. * Warnings:
  5362. *
  5363. \**************************************************************************/
  5364.  
  5365. BOOL bPlayRle(PINFO pInfo)
  5366. {
  5367.     ULONG               ulFrames;
  5368.     ULONG               i;
  5369.     LPBITMAPINFO        pbmi;
  5370.     HDC                 hDC;
  5371.     HWND                hViewSurf;
  5372.     int                 ii;
  5373.  
  5374. //    RECT                rc;
  5375.  
  5376.     hDC = GetDC(hViewSurf=pInfo->hwnd);
  5377.  
  5378.     SelectPalette(hDC, pInfo->RleData.hPal, FALSE);
  5379.     ii=RealizePalette(hDC);
  5380.     if (ii){
  5381.     UpdateColors (hDC);
  5382.     }
  5383.  
  5384.     ulFrames = pInfo->RleData.ulFrames;
  5385.  
  5386.     for (i = 0; i < ulFrames; i++) {
  5387.     pbmi = pInfo->RleData.rgpbmi[i];
  5388.     SetDIBitsToDevice(hDC,
  5389.           0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight,
  5390.           0, 0, 0, pbmi->bmiHeader.biHeight,
  5391.           pInfo->RleData.rgpjFrame[i], pbmi, DIB_RGB_COLORS);
  5392.  
  5393. #if 0
  5394.     GetClientRect(pInfo->hwnd, &rc);
  5395.     StretchDIBits(hDC,
  5396.            0, 0, rc.right, rc.bottom,
  5397.            0, 0, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight,
  5398.            (LPSTR)pInfo->RleData.rgpjFrame[i], pbmi, DIB_RGB_COLORS,
  5399.            SRCCOPY);
  5400. #endif
  5401.     }
  5402.  
  5403.     ReleaseDC(hViewSurf, hDC);
  5404.  
  5405.     return TRUE;
  5406. }
  5407.  
  5408.  
  5409. /******************************Public*Routine******************************\
  5410. *
  5411. * bSaveRleFile
  5412. *
  5413. * Effects:
  5414. *
  5415. * Warnings:
  5416. *
  5417. \**************************************************************************/
  5418.  
  5419. BOOL bSaveRleFile(HDC hDC, PINFO pInfo, PSTR pszFileName)
  5420. {
  5421.     int                 hFile;
  5422.     OFSTRUCT            ofReOpenBuff;
  5423.     BOOL                bSuccess;
  5424.     BITMAPFILEHEADER    bfh;
  5425.     ULONG               ulFrames;
  5426.     ULONG               i;
  5427.     LPBITMAPINFO        pbmi;
  5428.     ULONG               ulNumClr;
  5429.     ULONG               ulSize;
  5430.  
  5431.     bSuccess = TRUE;
  5432.     ulFrames = pInfo->RleData.ulFrames;
  5433.  
  5434.     if (ulFrames == 0) {
  5435.     MessageBox(GetFocus(), GetStringRes (IDS_NO_RLE_TO_SAVE),
  5436.                NULL, MB_OK);
  5437.     return FALSE;
  5438.     }
  5439.  
  5440.     // Let's open the file and get ready for writing
  5441.     if ((hFile = OpenFile(pszFileName, (LPOFSTRUCT)&ofReOpenBuff,
  5442.          OF_CREATE | OF_WRITE)) == -1) {
  5443.     OutputDebugString ("Failed in OpenFile!");
  5444.     return FALSE;
  5445.     }
  5446.  
  5447.     for (i = 0; i < ulFrames; i++) {
  5448.  
  5449.     pbmi = pInfo->RleData.rgpbmi[i];
  5450.  
  5451.     switch(pbmi->bmiHeader.biBitCount) {
  5452.         case 24:
  5453.         ulSize = 0;
  5454.         break;
  5455.         case 16:
  5456.         case 32:
  5457.         ulSize = sizeof(DWORD)*3;
  5458.         break;
  5459.         default:
  5460.         ulNumClr = 1<<pbmi->bmiHeader.biBitCount;
  5461.         ulSize = sizeof(RGBQUAD)*ulNumClr;
  5462.         break;
  5463.     }
  5464. #if 0
  5465.     ulNumClr = ((pbmi->bmiHeader.biBitCount == 24)
  5466.                ? 0
  5467.                : (1<<pbmi->bmiHeader.biBitCount));
  5468. #endif
  5469.     // fill in the info for the BitmapFileHeader
  5470.     bfh.bfType    = 0x4D42;                            // 'BM'
  5471.     bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
  5472.             ulSize;
  5473.             //sizeof(RGBQUAD)*ulNumClr;
  5474.     bfh.bfSize    = bfh.bfOffBits + pbmi->bmiHeader.biSizeImage;
  5475.     bfh.bfReserved1 =
  5476.     bfh.bfReserved2 = 0;
  5477.  
  5478.     // Write out the file header now
  5479.     if (_lwrite(hFile, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER)) == -1) {
  5480.         bSuccess = FALSE;
  5481.         goto ErrExit1;
  5482.     }
  5483.  
  5484.     // Now write out the BitmapInfoHeader and color table, if any
  5485.     if (_lwrite(hFile, (LPSTR)pbmi, sizeof(BITMAPINFOHEADER) +
  5486.                     ulSize) == -1) {
  5487.                     //sizeof(RGBQUAD)*ulNumClr) == -1) {
  5488.         bSuccess = FALSE;
  5489.         goto ErrExit1;
  5490.     }
  5491.  
  5492.     // write the bits also
  5493.     if (_lwrite(hFile, (LPSTR)pInfo->RleData.rgpjFrame[i],
  5494.                pbmi->bmiHeader.biSizeImage) == -1) {
  5495.         bSuccess = FALSE;
  5496.         goto ErrExit1;
  5497.     }
  5498.  
  5499.     }
  5500.  
  5501. ErrExit1:
  5502.     _lclose(hFile);
  5503.     return bSuccess;
  5504. }
  5505.  
  5506.  
  5507. /******************************Public*Routine******************************\
  5508. *
  5509. * bPlayRleCont
  5510. *
  5511. * Effects:
  5512. *
  5513. * Warnings:
  5514. *
  5515. \**************************************************************************/
  5516.  
  5517. BOOL bPlayRleCont(HDC hDC, PINFO pInfo)
  5518. {
  5519.     BOOL    bQuit;
  5520.     MSG     msg;
  5521.     int     ii;
  5522.  
  5523.     bQuit = FALSE;
  5524.  
  5525.     SelectPalette(hDC, pInfo->RleData.hPal, FALSE);
  5526.     ii=RealizePalette(hDC);
  5527.     if (ii){
  5528.     UpdateColors (hDC);
  5529.     }
  5530.  
  5531.     while (TRUE && !bQuit) {
  5532.  
  5533.     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  5534.  
  5535.         if ((msg.message == WM_QUIT) || (msg.message == WM_CLOSE) ||
  5536.         ((msg.message == WM_SYSCOMMAND) && (msg.wParam == SC_CLOSE))) {
  5537.         bQuit = TRUE;
  5538.         PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
  5539.         } else {
  5540.         if (!TranslateAccelerator(msg.hwnd, ghAccel, &msg)) {
  5541.             TranslateMessage(&msg);
  5542.             DispatchMessage(&msg);
  5543.         }
  5544.        }
  5545.     }
  5546.  
  5547.     if (!pInfo->bPlayRleCont) {
  5548.         bQuit = TRUE;
  5549.     }
  5550.  
  5551.     if (!bQuit) {
  5552.         bPlayRle(pInfo);
  5553.     }
  5554.  
  5555.     }
  5556.     return TRUE;
  5557. }
  5558.  
  5559.  
  5560. /******************************Public*Routine******************************\
  5561. *
  5562. * bPlayRleCont2
  5563. *
  5564. * Effects:
  5565. *
  5566. * Warnings:
  5567. *
  5568. \**************************************************************************/
  5569.  
  5570. BOOL bPlayRleCont2(PINFO pInfo)
  5571. {
  5572.     HDC             hDC;
  5573.     HWND            hViewSurf;
  5574.     DWORD           dwWait;
  5575.     BOOL            bQuit;
  5576.     int             ii;
  5577.  
  5578.     hDC = GetDC(hViewSurf=pInfo->hwnd);
  5579.  
  5580.     SelectPalette(hDC, pInfo->RleData.hPal, FALSE);
  5581.     ii=RealizePalette(hDC);
  5582.     if (ii){
  5583.     UpdateColors (hDC);
  5584.     }
  5585.  
  5586.     bQuit = FALSE;
  5587.     while (TRUE) {
  5588.     //
  5589.     // If parent gets a WM_CLOSE, we will return
  5590.     //
  5591.     dwWait = WaitForSingleObject(pInfo->hQuitEvent, 0);
  5592.     if (dwWait == WAIT_TIMEOUT) {
  5593.         MessageBox(ghwndMain,
  5594.                    GetStringRes (IDS_PLAY_THREAD_END),
  5595.                    GetStringRes (IDS_PLAY_THREAD),
  5596.                    MB_OK);
  5597.         break;
  5598.     }
  5599.  
  5600.     if (!pInfo->bPlayRleCont) {
  5601.         bQuit = TRUE;
  5602.     }
  5603.  
  5604.     if (!bQuit)
  5605.         bPlayRle(pInfo);
  5606.     }
  5607.  
  5608.     ReleaseDC(hViewSurf, hDC);
  5609.  
  5610.     ExitThread(0);
  5611.     return TRUE;
  5612.  
  5613. }
  5614.  
  5615.  
  5616. /******************************Public*Routine******************************\
  5617. *
  5618. * DIBfromDDB
  5619. *
  5620. * Effects:  Call GetDIBits to retrieve the DIB info from DDB
  5621. *
  5622. * Warnings:
  5623. *
  5624. \**************************************************************************/
  5625.  
  5626. HBITMAP DIBfromDDB(HDC hDC, HBITMAP hBmp, PINFO pInfo)
  5627. {
  5628.     LPBITMAPINFO        pbmi;
  5629.     HBITMAP             hDIB;
  5630.     INT                 iBitCount, iNumClr;
  5631.     BITMAP              bm;
  5632.     DWORD               sizImage;
  5633.     PBYTE               pjBits;
  5634.     ULONG               sizBMI;
  5635.     LONG                lScan;
  5636.  
  5637.     iBitCount = GetDeviceCaps(hDC, BITSPIXEL);
  5638.     switch (iBitCount) {
  5639.     case 16:
  5640.     case 32:
  5641.         sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3;
  5642.         break;
  5643.     case 24:
  5644.         sizBMI = sizeof(BITMAPINFOHEADER);
  5645.         break;
  5646.     default:
  5647.         iNumClr = (1 << iBitCount);
  5648.         sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*iNumClr;
  5649.         break;
  5650.     }
  5651.  
  5652.     if ((pbmi = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED,sizBMI)) == NULL) {
  5653.     goto ErrExit1;
  5654.     }
  5655.  
  5656.     pbmi->bmiHeader.biSize = 0x28;              // GDI need this to work
  5657.     pbmi->bmiHeader.biBitCount = 0;             // don't get the color table
  5658.     pbmi->bmiHeader.biCompression = BI_RGB;
  5659.     pbmi->bmiHeader.biSizeImage = 0;
  5660.     pbmi->bmiHeader.biXPelsPerMeter = 0;
  5661.     pbmi->bmiHeader.biYPelsPerMeter = 0;
  5662.     pbmi->bmiHeader.biClrUsed = 0;
  5663.     pbmi->bmiHeader.biClrImportant = 0;
  5664.  
  5665.     GetObject(hBmp, sizeof(BITMAP), &bm);
  5666.  
  5667.     //
  5668.     // Important!  Select the correct palette corresponding to the DDB
  5669.     //
  5670.     SelectPalette(hDC, pInfo->hPal, FALSE);
  5671.     if (GetDIBits(hDC, hBmp, 0, bm.bmHeight, NULL, pbmi,
  5672.     DIB_RGB_COLORS) == 0) {
  5673.      goto ErrExit2;
  5674.     }
  5675.  
  5676.     sizImage = pbmi->bmiHeader.biSizeImage;
  5677.     if (sizImage == 0) {
  5678.     goto ErrExit2;
  5679.     }
  5680.  
  5681.     if ((pjBits = (PBYTE) LocalAlloc(LMEM_FIXED, sizImage)) == NULL) {
  5682.      goto ErrExit2;
  5683.     }
  5684.  
  5685.     lScan = pbmi->bmiHeader.biHeight;
  5686.  
  5687.     if (GetDIBits(hDC, pInfo->hBmpSaved, 0, lScan, pjBits, pbmi,
  5688.     DIB_RGB_COLORS) < lScan) {
  5689.      goto ErrExit3;
  5690.     }
  5691.  
  5692.     //
  5693.     // Saving the DIB...free memory when the windows is closed.
  5694.     //
  5695.     pInfo->RleData.rgpjFrame[0] = pjBits;
  5696.     pInfo->RleData.rgpbmi[0]    = pbmi;
  5697.     pInfo->RleData.pbmi         = (PBITMAPINFO) &(pInfo->RleData.rgpbmi[0]);
  5698.     pInfo->RleData.ulFrames     = 1;
  5699.     pInfo->RleData.ulFiles      = 1;
  5700.  
  5701.     // set flag to use original DIB as source for blting so HT can be done
  5702.     pInfo->bUseDIB = TRUE;
  5703.  
  5704.     pInfo->bCoreHdr = FALSE;
  5705.  
  5706.     // hDIB = CreateDIBitmap(hDC, NULL, CBM_INIT, pjBits, pbmi, DIB_RGB_COLORS);
  5707.     hDIB = CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, &pjBits, NULL, 0);
  5708.  
  5709.     return hDIB;
  5710.  
  5711. ErrExit3:
  5712.     LocalFree(pjBits);
  5713. ErrExit2:
  5714.     LocalFree(pbmi);
  5715. ErrExit1:
  5716.     return ((HBITMAP)NULL);
  5717. }
  5718.  
  5719.  
  5720. //---------------------------------------------------------------------------
  5721. //
  5722. // FUNCTION:    GetStringRes (int id INPUT ONLY)
  5723. //
  5724. // COMMENTS:    Load the resource string with the ID given, and return a
  5725. //              pointer to it.  Notice that the buffer is common memory so
  5726. //              the string must be used before this call is made a second time.
  5727. //
  5728. //---------------------------------------------------------------------------
  5729.  
  5730. LPTSTR GetStringRes (int id)
  5731. {
  5732.   static TCHAR buffer[MAX_PATH];
  5733.  
  5734.   buffer[0]=0;
  5735.   LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  5736.   return buffer;
  5737. }
  5738.