home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mandelc.zip / apfel.cpp next >
C/C++ Source or Header  |  1993-08-01  |  28KB  |  1,012 lines

  1. #include "apfel.h"
  2. #ifdef INCLUDESOURCE
  3. #include "pmprocess.cc"
  4. #endif
  5.  
  6.  
  7. #define WinSelectLboxItem(hwndLbox, index, fSelect) \
  8.     ((USHORT)WinSendMsg((hwndLbox), LM_SELECTITEM, \
  9.          (MPARAM) (index), (MPARAM) (fSelect)))
  10.  
  11. // The calculation thread if there are no servers
  12. // The priority is for both foreground and background of class idle -
  13. // caused of that this thread is not interactive
  14. calcThread::calcThread(menuWindowTree *pWindowNew)
  15.     :pmWindowThread(pWindowNew)
  16. {    pWindow = pWindowNew;
  17.     iClassF = PRTYC_IDLETIME;
  18.     iValueF = 31;
  19.     iClassB = PRTYC_IDLETIME;
  20.     iValueB = 0;
  21. }
  22.  
  23.  
  24. void menuWindowTree::winInvalidate(unsigned int yi)
  25. {    RECTL rcl;
  26.  
  27.     rcl.xLeft = 0;
  28.     rcl.yTop = yi + 1;
  29.     rcl.yBottom = yi;
  30.     rcl.xRight = iSizeX;
  31.     WinInvalidateRect(hwndClient, &rcl, FALSE);
  32. }
  33.  
  34.  
  35. // calculates a image
  36. void calcThread::doSomething(void)
  37. {    unsigned int yi;
  38.     //menuPmThread *pMsgThread = (menuPmThread*)pParent;
  39.     double xl = pWindow->xa, yl = pWindow->ya;
  40.     BITMAPINFO2 *pBitmapInfo;
  41.     unsigned char *pData;
  42.     unsigned char *pDataCompare;
  43.     unsigned int iBitmapSize;
  44.  
  45.     pData = (unsigned char *)alloca(iBitmapSize = pWindow->iSizeX * sizeof*pData);
  46.     pDataCompare = (unsigned char *)alloca(iBitmapSize);
  47.     assert(!((unsigned long)pData & 3));
  48.     pBitmapInfo = (BITMAPINFO2 *)alloca(256*sizeof(RGB2)
  49.        + (unsigned int)((char*)&pBitmapInfo->ulCompression
  50.       - (char*)&pBitmapInfo->cbFix));
  51.     memset(pBitmapInfo, 0, 256*sizeof(RGB2));
  52.     {    RGB2 *pScan;
  53.         unsigned short iColor;
  54.  
  55.         for (pScan = (RGB2*)&pBitmapInfo->ulCompression,
  56.            iColor = 0;
  57.            iColor < 256;
  58.            pScan++, iColor++)
  59.         {    pScan->fcOptions = PC_EXPLICIT;
  60.             pScan->bBlue = iColor;
  61.         }
  62.     }
  63.     pBitmapInfo->cbFix = (unsigned int)((char*)&pBitmapInfo->ulCompression
  64.        - (char*)&pBitmapInfo->cbFix);
  65.     assert(pBitmapInfo->cbFix > 0);
  66.     pBitmapInfo->cx = pWindow->iSizeX;
  67.     pBitmapInfo->cy = 1;
  68.     pBitmapInfo->cPlanes = 1;
  69.     pBitmapInfo->cBitCount = 8*sizeof*pData;
  70.     /*
  71.     pBitmapInfo->ulCompression = BCA_UNCOMP;
  72.     pBitmapInfo->cbImage = 0;
  73.     pBitmapInfo->cxResolution = 0;
  74.     pBitmapInfo->cyResolution = 0;
  75.     pBitmapInfo->cclrUsed = 0;
  76.     pBitmapInfo->cclrImportant = 0;
  77.     pBitmapInfo->usUnits = 0;
  78.     pBitmapInfo->usReserved = 0;
  79.     pBitmapInfo->usRecording = BRA_BOTTOMUP;
  80.     pBitmapInfo->usRendering = BRH_NOTHALFTONED;
  81.     pBitmapInfo->ulColorEncoding = BCE_RGB;
  82.     */
  83.     for (yi = 0;
  84.        yi < pWindow->iSizeY;
  85.        xl -= pWindow->ydx, yl += pWindow->xdx,
  86.        GpiSetBitmapBits(
  87.         (unsigned long)pWindow->hpsBitmap,
  88.         (LONG)yi,
  89.         (LONG)1,
  90.         (unsigned char*)pData,
  91.         pBitmapInfo),
  92.         // After some hours without any picture,
  93.         // I wanted to have a look, wethere the bitmap will be changed
  94.         // or not.
  95.         // Thats why I read from the bitmap using the next function call
  96.         // and I got a picture on the screen.
  97.         // If I take this function call away - no more drawing action
  98.         // will occure.
  99.         // Is there anyone how can explain this?
  100.        GpiQueryBitmapBits(
  101.         (unsigned long)pWindow->hpsBitmap,
  102.         (LONG)yi,
  103.         (LONG)1,
  104.         (unsigned char*)pDataCompare,
  105.         pBitmapInfo),
  106.        pWindow->winInvalidate(yi),
  107.        yi++)
  108.         (*pWindow->pFctCalculate)(
  109.             pWindow->iSizeX,
  110.             pWindow->iMaxColors,
  111.             pWindow->iMaxIterations,
  112.             pData,
  113.             pWindow->dLimit,
  114.             pWindow->xdx,
  115.             pWindow->ydx,
  116.             xl,
  117.             yl);
  118. }
  119.  
  120. // If there are some pipe names start in server-client mode
  121. // if not start the calculation thread  of class calcThread
  122. Boolean menuWindowTree::startCalculation(void)
  123. {       iLine = 0;
  124.     if (pabCalculated)
  125.         memset(pabCalculated, 0, iSizeY*sizeof*pabCalculated);
  126.     chainThreads.getMutualExclusiveAccess();
  127.     if (pProcess->chainPipes.iNumberOfElements)
  128.         if (pProcess->chainPipes.foreach(idForeachPipeNameMakeThread,
  129.             this))
  130.         {    chainThreads.freeMutualExclusiveAccess();
  131.             return FALSE;
  132.         }
  133.         else
  134.         {    chainThreads.freeMutualExclusiveAccess();
  135.             return TRUE;
  136.         }
  137.     else
  138.     {    calcThread *pThread;
  139.  
  140.         pThread = new calcThread(this);
  141.         if (pThread)
  142.             if (pThread->isSuccessfull())
  143.             {    pThread->startThread();
  144.                 chainThreads.freeMutualExclusiveAccess();
  145.                 return TRUE;
  146.             }
  147.             else
  148.                 delete pThread;
  149.         chainThreads.freeMutualExclusiveAccess();
  150.         return FALSE;
  151.     }
  152. }
  153.  
  154.  
  155. // Kills all running threads
  156. void menuWindowTree::stopCalculation(void)
  157. {    chainThreads.getMutualExclusiveAccess();
  158.     chainThreads.foreach(idForeachChainElementDestruct, (void*)0);
  159.     chainThreads.freeMutualExclusiveAccess();
  160. }
  161.  
  162.  
  163. // The windowproc of this class
  164. // some other message will be treated in the base classes
  165. MRESULT menuWindowTree::windowProc(ULONG msg, MPARAM mp1, MPARAM mp2)
  166. {    switch (msg)
  167.     {    default:
  168.             return processWindow::windowProc(msg, mp1, mp2);
  169.         case WM_BUTTON2DOWN:
  170.         {    WinPopupMenu(hwndClient,
  171.                 hwndClient,
  172.                 hwndMenu,
  173.                 MOUSEMSG(&msg)->x,
  174.                 MOUSEMSG(&msg)->y,
  175.                 0,
  176.                 PU_HCONSTRAIN
  177.                 | PU_VCONSTRAIN
  178.                 //| PU_MOUSEBUTTON2DOWN
  179.                 | PU_KEYBOARD
  180.                 | PU_MOUSEBUTTON1
  181.                 | PU_MOUSEBUTTON2);
  182.             return (MRESULT)TRUE;
  183.         }
  184.         case WM_BUTTON1DOWN:
  185.         {    if (eZoomState == 3)
  186.             {    drawZoomRectangle();
  187.                 WinEnableMenuItem(hwndMenu,
  188.                     idResourceMenuItemZoomOld, FALSE);
  189.                 WinEnableMenuItem(hwndMenu,
  190.                     idResourceMenuItemZoomNew, FALSE);
  191.             }
  192.             iZoomXE = iZoomXA = MOUSEMSG(&msg)->x;
  193.             iZoomYE = iZoomYA = MOUSEMSG(&msg)->y;
  194.             WinSetCapture(HWND_DESKTOP, hwndClient);
  195.             eZoomState = 1;
  196.             return (MRESULT)FALSE;
  197.         }
  198.         case WM_MOUSEMOVE:
  199.         {    if (eZoomState == 0 || eZoomState == 3)
  200.                 return (MRESULT)FALSE;
  201.             if (eZoomState == 2)
  202.                 drawZoomRectangle();
  203.             iZoomXE = MOUSEMSG(&msg)->x;
  204.             iZoomYE = MOUSEMSG(&msg)->y;
  205.             if (iZoomXE == iZoomXA && iZoomYE == iZoomYA)
  206.             {    eZoomState = 1;
  207.                 return (MRESULT)FALSE;
  208.             }
  209.             drawZoomRectangle();
  210.             eZoomState = 2;
  211.             return (MRESULT)FALSE;
  212.         }
  213.         case WM_BUTTON1UP:
  214.         {    if (eZoomState != 2)
  215.             {    if (eZoomState == 1)
  216.                 {    eZoomState = 0;
  217.                     WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  218.                 }
  219.                 return (MRESULT)FALSE;
  220.             }
  221.             WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  222.             drawZoomRectangle();
  223.             iZoomXE = MOUSEMSG(&msg)->x;
  224.             iZoomYE = MOUSEMSG(&msg)->y;
  225.             drawZoomRectangle();
  226.             eZoomState = 3;
  227.             WinEnableMenuItem(hwndMenu, idResourceMenuItemZoomOld,
  228.                 TRUE);
  229.             WinEnableMenuItem(hwndMenu, idResourceMenuItemZoomNew,
  230.                 TRUE);
  231.             return (MRESULT)FALSE;
  232.         }
  233. #ifdef undefined
  234.     unsigned int eZoomState;    // Are the following Values valid
  235.     //    0 means no valid zoom
  236.     //    1 means first point selected
  237.     //    2 has already moved, still moving
  238.     //    3 means second point selected,
  239.     int iZoomXA, iZoomYA, iZoomXE, iZoomYE;
  240. #endif
  241.         case WM_COMMAND:
  242.             switch ((USHORT)mp1)
  243.             {       default:
  244.                     return processWindow
  245.                         ::windowProc(msg, mp1, mp2);/*
  246.                     if ((USHORT)mp1
  247.                         <= idResourceMenuItemLast
  248.                         + pProcess->chainDLLNames.iNumberOfElements
  249.                         && (USHORT)mp1 > idResourceMenuItemLast)
  250.                     {       unsigned int iMenuId = (USHORT)mp1;
  251.  
  252.                         if (!pProcess->chainDLLNames.foreach(
  253.                             idForeachDLLNameGetProcAddrByIndex,
  254.                             &iMenuId))
  255.                             return (MRESULT)FALSE;
  256.                         stopCalculation();
  257.                         iMenuIdSelected = (USHORT)mp1;
  258.                         pFctCalculate = (pFctCalculateFractal)iMenuId;
  259.                         WinEnableMenuItem(hwndMenu,
  260.                             idResourceMenuItemZoomOld,
  261.                             FALSE);
  262.                         WinEnableMenuItem(hwndMenu,
  263.                             idResourceMenuItemZoomNew,
  264.                             FALSE);
  265.                         eZoomState = 0;
  266.                         startCalculation();                        return (MRESULT)FALSE;
  267.                     }
  268.                     else
  269.                         return processWindow
  270.                             ::windowProc(msg, mp1, mp2);
  271. */                case idResourceMenuItemSettings:
  272.                 {    settingsDlg *pWindow
  273.                         = new settingsDlg(this);
  274.                     if (pWindow)
  275.                         if (pWindow->isSuccessfull())
  276.                             if (pWindow->init())
  277.                                 return (MRESULT)FALSE;
  278.                             else
  279.                                 delete pWindow;
  280.                         else
  281.                             delete pWindow;
  282.                     return (MRESULT)FALSE;
  283.                 }                case idResourceMenuItemZoomOld:
  284.                     if (eZoomState != 3)
  285.                         return (MRESULT)FALSE;
  286.                     stopCalculation();
  287.                     WinEnableMenuItem(hwndMenu,
  288.                         idResourceMenuItemZoomOld,
  289.                         FALSE);
  290.                     WinEnableMenuItem(hwndMenu,
  291.                         idResourceMenuItemZoomNew,
  292.                         FALSE);
  293.                     eZoomState = 0;
  294.                     calcZoomCoordinates();
  295.                     startCalculation();
  296.                     return (MRESULT)FALSE;                case idResourceMenuItemZoomNew:
  297.                 {    menuWindowTree *pWindowTree;
  298.  
  299.                     if (eZoomState != 3)
  300.                         return (MRESULT)FALSE;
  301.                     if (!(pWindowTree
  302.                         = new menuWindowTree(
  303.                         (menuPmThread*)pMsgThread
  304.                         ->getChainElementMember(
  305.                         idGetChainElementMenuMsgThreadTreeThis)
  306.                         ,
  307.                         0,
  308.                         "Apfel")))
  309.                         return (MRESULT)FALSE;
  310.                     else
  311.                         if (!pWindowTree->isSuccessfull())
  312.                         {    delete pWindowTree;
  313.                             return (MRESULT)FALSE;
  314.                         }
  315.                     pWindowTree->bCoordiantesValid = TRUE;
  316.                     pWindowTree->xa = xa;
  317.                     pWindowTree->xdx = xdx;
  318.                     pWindowTree->ya = ya;
  319.                     pWindowTree->ydx = ydx;
  320.                     pWindowTree->iMaxIterations = iMaxIterations;
  321.                     pWindowTree->dLimit = dLimit;
  322.                     pWindowTree->iZoomXA = iZoomXA;
  323.                     pWindowTree->iZoomYA = iZoomYA;
  324.                     pWindowTree->iZoomXE = iZoomXE;
  325.                     pWindowTree->iZoomYE = iZoomYE;
  326.                     pWindowTree->iIdSelected = iIdSelected;
  327.                     pWindowTree->pFctCalculate = pFctCalculate;
  328.                     //pWindowTree->eZoomState = eZoomState;
  329.                     if (!pWindowTree->init())
  330.                         delete pWindowTree;
  331.                     return (MRESULT)FALSE;
  332.                 }
  333.             }
  334.     }
  335. }
  336.  
  337.  
  338. void menuWindowTree::doPaint(HPS hps, RECTL *pStructRectl)
  339. {    POINTL aPoint[4];
  340.  
  341.     aPoint[0].x = pStructRectl->xLeft;
  342.     aPoint[0].y = pStructRectl->yBottom;
  343.     aPoint[1].x = pStructRectl->xRight;
  344.     aPoint[1].y = pStructRectl->yTop;
  345.     aPoint[2].x = pStructRectl->xLeft;
  346.     aPoint[2].y = pStructRectl->yBottom;
  347.     aPoint[3].x = pStructRectl->xRight;
  348.     aPoint[3].y = pStructRectl->yTop;
  349.     if (eZoomState >= 2)
  350.         drawZoomRectangle();
  351.     GpiBitBlt(hps, hpsBitmap, 4, aPoint, ROP_SRCCOPY, BBO_OR);
  352.     if (eZoomState >= 2)
  353.         drawZoomRectangle();
  354. }
  355.  
  356.  
  357. Boolean menuWindowTree::initPost(void)
  358. {       if (!processWindow::initPost())
  359.         return FALSE;
  360.     {    SIZEL structSize;
  361.  
  362.         structSize.cx = structSize.cy = 0;
  363.         hZoomRectanglePS = GpiCreatePS(pMsgThread->hab,
  364.             hWindowDC,
  365.             &structSize,
  366.             PU_PELS | GPIA_ASSOC);
  367.     }
  368.     GpiSetMix(hZoomRectanglePS, FM_INVERT);
  369.     hdcBitmap = DevOpenDC(pMsgThread->hab, OD_MEMORY, (unsigned char*)"*", 0, 0, 0);
  370.     {    SIZEL size;
  371.  
  372.         size.cx = size.cy = 0;
  373.         hpsBitmap = GpiCreatePS(pMsgThread->hab, hdcBitmap, &size,
  374.            PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
  375.     }
  376.     iSizeX = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
  377.     iSizeY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
  378.     {    long alBmpFormats[2];
  379.         BITMAPINFOHEADER2 structBmpInfoHeader;
  380.  
  381.         GpiQueryDeviceBitmapFormats(hpsBitmap, 2, alBmpFormats);
  382.         memset(&structBmpInfoHeader, 0, sizeof(structBmpInfoHeader));
  383.         structBmpInfoHeader.cbFix = sizeof(structBmpInfoHeader);
  384.         structBmpInfoHeader.cx = iSizeX;
  385.         structBmpInfoHeader.cy = iSizeY;
  386.         structBmpInfoHeader.cPlanes = (USHORT)alBmpFormats[0];
  387.         structBmpInfoHeader.cBitCount = (USHORT)alBmpFormats[1];
  388.         hbm = GpiCreateBitmap(hpsBitmap,
  389.             &structBmpInfoHeader,
  390.             0,
  391.             (BYTE*)0,
  392.             (BITMAPINFO2*)0);
  393.     }
  394.     GpiSetBitmap(hpsBitmap, hbm);
  395.     {    POINTL aPoint[4];
  396.  
  397.         aPoint[0].x = 0;
  398.         aPoint[0].y = iSizeY;
  399.         aPoint[1].x = iSizeX;
  400.         aPoint[1].y = 0;
  401.         aPoint[2].x = 0;
  402.         aPoint[2].y = iSizeY;
  403.         aPoint[3].x = iSizeX;
  404.         aPoint[3].y = 0;
  405.         GpiBitBlt(hpsBitmap, hpsBitmap, 4, aPoint, ROP_ZERO, BBO_OR);
  406.     }
  407.     // Wether the window is the first started or not
  408.     // the values need initialization or not
  409.     if (!bCoordiantesValid)
  410.     {    xa = -2.0;
  411.         xdx = 3.0 / (iSizeX - 1);
  412.         ya = -xdx*(iSizeY - 1)*0.5;
  413.         ydx = 0.0;
  414.         iMaxIterations = 255;
  415.         dLimit = 100.0;
  416.     }
  417.     else
  418.         calcZoomCoordinates();
  419.     {    HDC hdc;
  420.         hdc = WinOpenWindowDC(HWND_DESKTOP);
  421.         DevQueryCaps((HDC)hdc, (LONG)CAPS_COLORS, (LONG)1,
  422.             (LONG*)&iMaxColors);
  423.         DevCloseDC(hdc);
  424.     }
  425.     //hwndMenu = WinWindowFromID(hwndFrame, FID_MENU);
  426.     hwndMenu = WinLoadMenu(hwndClient, (HMODULE)0, idResourceMenu);
  427.     if (pProcess->chainPipes.iNumberOfElements)
  428.     {    pabCalculated = new unsigned char[iSizeY];
  429.         memset(pabCalculated, 0, iSizeY*sizeof*pabCalculated);
  430.     }
  431.     else
  432.         pabCalculated = (unsigned char*)0;
  433.     // start the calculation thread(s)
  434. #ifdef undefined
  435.     pProcess->chainDLLNames.foreach(idForeachDLLNameAddMenuEntry,
  436.         (void*)hwndMenu);
  437. #endif
  438.     if (!bCoordiantesValid)
  439.     {       dLLName *pDLLName = (dLLName*)(iIdSelected = 0);
  440.  
  441.         if (!pProcess->chainDLLNames.foreach(
  442.             idForeachDLLNameGetThisByIndex,
  443.             (void*)&pDLLName))
  444.             return FALSE;
  445.         pFctCalculate = pDLLName->pFctCalculate;
  446. #ifdef undefined
  447.         WinCheckMenuItem(hwndMenu, idResourceMenuItemLast + 1,
  448.             TRUE);
  449. #endif undefined
  450.     }
  451.     return startCalculation();
  452. }
  453.  
  454.  
  455. // the matching counterpart for initPost()
  456. void menuWindowTree::destructPre(void)
  457. {       stopCalculation();
  458.     if (pabCalculated)
  459.         delete pabCalculated;
  460.     GpiDeleteBitmap(hbm);
  461.     DevCloseDC(hdcBitmap);
  462.     GpiDestroyPS(hZoomRectanglePS);
  463.     processWindow::destructPre();
  464. }
  465.  
  466.  
  467. // I think there is still a bug releated to the milestone problem
  468. void menuWindowTree::drawZoomRectangle(void)
  469. {    int iXa, iYa, iXe = iZoomXE,
  470.         iYe = iZoomYE, iXdx, iYdx, iXdy, iYdy;
  471.     POINTL aStructPoint[5];
  472.  
  473.     iXa = 2*iZoomXA - iXe;
  474.     iYa = 2*iZoomYA - iYe;
  475.     iXdx = iXe - iXa;
  476.     iYdx = iYe - iYa;
  477.     iYdy = iXdx*(iSizeY - 1)/(iSizeX - 1)/2;
  478.     iXdy = -iYdx*(iSizeY - 1)/(iSizeX - 1)/2;
  479.     aStructPoint[0].x = iXa - iXdy; aStructPoint[0].y = iYa - iYdy;
  480.     aStructPoint[1].x = iXe - iXdy; aStructPoint[1].y = iYe - iYdy;
  481.     aStructPoint[2].x = iXe + iXdy; aStructPoint[2].y = iYe + iYdy;
  482.     aStructPoint[3].x = iXa + iXdy; aStructPoint[3].y = iYa + iYdy;
  483.     aStructPoint[4].x = iXa - iXdy; aStructPoint[4].y = iYa - iYdy;
  484.     GpiMove(hZoomRectanglePS, aStructPoint);
  485.     GpiPolyLine(hZoomRectanglePS, 5, aStructPoint);
  486. }
  487.  
  488.  
  489. Boolean menuWindowTree::initPre(void)
  490. {    if (!processWindow::initPre())
  491.         return FALSE;
  492.     //frameFlags |= FCF_MENU;
  493.     pWindowClassName = "menuWindowTree";
  494.     return TRUE;
  495. }
  496.  
  497.  
  498. menuWindowTree::menuWindowTree(menuPmThread *pMsgThreadNew, int idResource,
  499.     char *pTitle):processWindow(pMsgThreadNew, idResource, pTitle), oMtx()
  500. {    pMsgThread = pMsgThreadNew;
  501.     pProcess = pMsgThread->pProcess;
  502. }
  503.  
  504.  
  505. menuWindowTree::~menuWindowTree(void)
  506. {
  507. }
  508.  
  509.  
  510. // I think there is still a bug releated to a milestone problem
  511. void menuWindowTree::calcZoomCoordinates(void)
  512. {    int iXa, iYa, iXe = iZoomXE, iYe = iZoomYE, iXdx, iYdx, iXdy, iYdy;
  513.     double dXaNew, dYaNew, dxdxNew, dydxNew;
  514.  
  515.     iXa = 2*iZoomXA - iXe;
  516.     iYa = 2*iZoomYA - iYe;
  517.     iXdx = iXe - iXa;
  518.     iYdx = iYe - iYa;
  519.     iYdy = iXdx*iSizeY/(iSizeX - 1)/2;
  520.     iXdy = -iYdx*iSizeY/(iSizeX - 1)/2;
  521.     iXa -= iXdy; iYa -= iYdy;
  522.     iXe -= iXdy; iYe -= iYdy;
  523.     dXaNew = xa + iXa*xdx - iYa*ydx;
  524.     dYaNew = ya + iXa*ydx + iYa*xdx;
  525.     dxdxNew = (xa + iXe*xdx - iYe*ydx - dXaNew)/(iSizeX - 1);
  526.     dydxNew = (ya + iXe*ydx + iYe*xdx - dYaNew)/(iSizeX - 1);
  527.     xa = dXaNew;
  528.     ya = dYaNew;
  529.     xdx = dxdxNew;
  530.     ydx = dydxNew;
  531. }
  532.  
  533.  
  534. menuPmThread::menuPmThread(menuPmProcess *pProcessNew)
  535.     :pmMsgThread(pProcessNew)
  536. {    pProcess = pProcessNew;
  537. }
  538.  
  539.  
  540. Boolean menuPmThread::create(void)
  541. {    menuWindowTree *pWindowTree;
  542.  
  543.     if (!(pWindowTree
  544.        = new menuWindowTree(this, 0, "Apfel")))
  545.         return FALSE;
  546.     else
  547.         if (!pWindowTree->isSuccessfull())
  548.         {    delete pWindowTree;
  549.             return FALSE;
  550.         }
  551.     return TRUE;
  552. }
  553.  
  554.  
  555. Boolean menuPmProcess::create(void)
  556. {    if (argc > 1)
  557.     {    FILE *pFile;
  558.         char acLine[1024];
  559.         unsigned int iId = 0;
  560.  
  561.         if (!(pFile = fopen(argv[1], "r")))
  562.         {    fprintf(stderr, "Cannot open %s!\n", argv[1]);
  563.             return FALSE;
  564.         }
  565.         acLine[sizeof acLine - 1] = 0;
  566.         while (fgets(acLine, sizeof acLine - 1, pFile))
  567.         {    dLLName *p;
  568.             char *pPos;
  569.  
  570.             if (pPos = strchr(acLine, '\n'))
  571.                 *pPos = 0;
  572.             if (p = new dLLName(acLine, &chainDLLNames, iId++))
  573.                 if (p->isSuccessfull())
  574.                     continue;
  575.                 else
  576.                     delete p;
  577.             fprintf(stderr, "Error loading DLL %s!\n", acLine);
  578.             return FALSE;
  579.         }
  580.         fclose(pFile);
  581.     }
  582.     if (argc > 2)
  583.     {    FILE *pFile;
  584.         char acLine[1024];
  585.  
  586.         if (!(pFile = fopen(argv[2], "r")))
  587.         {    fprintf(stderr, "Cannot open %s!\n", argv[1]);
  588.             return FALSE;
  589.         }
  590.         acLine[sizeof acLine - 1] = 0;
  591.         // reading of the file
  592.         // create a object of class pipeName for every line in the file
  593.         while (fgets(acLine, sizeof acLine - 1, pFile))
  594.         {    pipeName *p;
  595.             char *pPos;
  596.  
  597.             if (pPos = strchr(acLine, '\n'))
  598.                 *pPos = 0;
  599.             if (p = new pipeName(acLine, &chainPipes))
  600.                 if (p->isSuccessfull())
  601.                     continue;
  602.                 else
  603.                     delete p;
  604.             fprintf(stderr, "Not enough memory!\n");
  605.             return FALSE;
  606.         }
  607.         fclose(pFile);
  608.     }
  609.     if (!new menuPmThread(this))
  610.         return FALSE;
  611.     else
  612.         if (!pProcessThread->isSuccessfull())
  613.         {    delete pProcessThread;
  614.             return FALSE;
  615.         }
  616.         else
  617.             return TRUE;
  618. }
  619.  
  620.  
  621. int pipeName::toBeCalledForeachElement(unsigned int iMsg, void *pData)
  622. {    switch (iMsg)
  623.     {    default:
  624.             return stringChainElement
  625.                 ::toBeCalledForeachElement(iMsg, pData);
  626.         case idForeachPipeNameMakeThread:
  627.         {       clientThread *pThread;
  628.  
  629.             if (!(pThread = new clientThread((menuWindowTree*)pData,
  630.                 pString)))
  631.                 return -1;
  632.             else
  633.                 if (!pThread->isSuccessfull())
  634.                 {    delete pThread;
  635.                     return -1;
  636.                 }
  637.             pThread->startThread();
  638.             return 0;
  639.         }
  640.     }
  641. }
  642.  
  643.  
  644. clientThread::clientThread(menuWindowTree *pWindowNew, char *pPipeNameNew)
  645.     :pmWindowThread(pWindowNew)
  646. {    pWindow = pWindowNew;
  647.     if (!(pPipeName = strdup(pPipeNameNew)))
  648.     {    setNoSuccess();
  649.         return;
  650.     }
  651. }
  652.  
  653. clientThread::~clientThread(void)
  654. {    if (hPipe)
  655.         DosClose(hPipe);
  656.     if (pPipeName)
  657.         free(pPipeName);
  658. }
  659.  
  660.  
  661. void clientThread::doSomething(void)
  662. {    BITMAPINFO2 *pBitmapInfo;
  663.     unsigned char *pData;
  664.     unsigned char *pDataCompare;
  665.     unsigned int iBitmapSize;
  666.  
  667.     //wait for a listening pipe available
  668.     {    unsigned long iAction;
  669.  
  670.         if (DosWaitNPipe((unsigned char*)pPipeName, -1)
  671.             || DosOpen(pPipeName, &hPipe, &iAction, 0, 0,
  672.             OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
  673.             OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
  674.             (EAOP2*)0))
  675.         {       hPipe = (HPIPE)0;
  676.             return;
  677.         }
  678.     }
  679.     {    unsigned long iBytes, iSize;
  680.         dLLName *pDLLName = (dLLName*)pWindow->iIdSelected;
  681.  
  682.         pWindow->pProcess->chainDLLNames.foreach(
  683.             idForeachDLLNameGetThisByIndex,
  684.             &pDLLName);
  685.         iSize = strlen(pDLLName->pDescription) + 1;
  686.         if (DosWrite(hPipe, pDLLName->pDescription, iSize, &iBytes)
  687.             || iBytes != iSize)
  688.             return;
  689.     }    pData = (unsigned char *)alloca(iBitmapSize = pWindow->iSizeX * sizeof(*pData));
  690.     pDataCompare = (unsigned char *)alloca(iBitmapSize);
  691.     assert(!((unsigned long)pData & 3));
  692.     pBitmapInfo = (BITMAPINFO2 *)alloca(256*sizeof(RGB2)
  693.        + (unsigned int)((char*)&pBitmapInfo->ulCompression
  694.       - (char*)&pBitmapInfo->cbFix));
  695.     memset(pBitmapInfo, 0, 256*sizeof(RGB2));
  696.     {    RGB2 *pScan;
  697.         unsigned short iColor;
  698.  
  699.         for (pScan = (RGB2*)&pBitmapInfo->ulCompression,
  700.            iColor = 0;
  701.            iColor < 256;
  702.            pScan++, iColor++)
  703.         {    pScan->fcOptions = PC_EXPLICIT;
  704.             pScan->bBlue = iColor;
  705.         }
  706.     }
  707.     pBitmapInfo->cbFix = (unsigned int)((char*)&pBitmapInfo->ulCompression
  708.        - (char*)&pBitmapInfo->cbFix);
  709.     assert(pBitmapInfo->cbFix > 0);
  710.     pBitmapInfo->cx = pWindow->iSizeX;
  711.     pBitmapInfo->cy = 1;
  712.     pBitmapInfo->cPlanes = 1;
  713.     pBitmapInfo->cBitCount = sizeof(*pData)*8;
  714.  
  715.     // make sure that only one thread has access to pWindow->iLine
  716.     // and pWindow->pabCalculated
  717.     pWindow->oMtx.getMutualExclusiveAccess();
  718.     while (1)
  719.     {    unsigned int iLine;
  720.         structRequest structR;
  721.         unsigned long iBytes;
  722.  
  723.         if (pWindow->iLine < pWindow->iSizeY)
  724.             iLine = pWindow->iLine++;
  725.         else
  726.         {    unsigned char *pScan, *pMax;
  727.  
  728.             for (pScan = pWindow->pabCalculated,
  729.                 pMax = pScan + pWindow->iSizeY;
  730.                 pScan < pMax;
  731.                 pScan++)
  732.                 if (!*pScan)
  733.                 {    iLine = pScan - pWindow->pabCalculated;
  734.                     break;
  735.                 }
  736.             if (pScan == pMax)
  737.             {    pWindow->oMtx.freeMutualExclusiveAccess();
  738.                 return;
  739.             }
  740.         }
  741.         pWindow->oMtx.freeMutualExclusiveAccess();
  742.         structR.iSizeX = pWindow->iSizeX;
  743.         structR.iMaxIterations = pWindow->iMaxIterations;
  744.         structR.iMaxColors = pWindow->iMaxColors;
  745.         structR.dLimit = pWindow->dLimit;
  746.         structR.dXa = pWindow->xa - pWindow->ydx*iLine;
  747.         structR.dYa = pWindow->ya + pWindow->xdx*iLine;
  748.         structR.dXdx = pWindow->xdx;
  749.         structR.dYdx = pWindow->ydx;
  750.         if (DosWrite(hPipe, &structR, sizeof structR, &iBytes)
  751.             || iBytes != sizeof structR)
  752.             return;
  753.         if (DosRead(hPipe, pData, pWindow->iSizeX*sizeof*pData,
  754.             &iBytes)
  755.             || iBytes != pWindow->iSizeX*sizeof*pData)
  756.             return;
  757.         pWindow->oMtx.getMutualExclusiveAccess();
  758.         do
  759.         {    GpiSetBitmapBits(
  760.                 (unsigned long)pWindow->hpsBitmap,
  761.                 (LONG)iLine,
  762.                 (LONG)1,
  763.                 (unsigned char*)pData,
  764.                 pBitmapInfo);
  765.         // After some hours without any picture,
  766.         // I wanted to have a look, wethere the bitmap will be changed
  767.         // or not.
  768.         // Thats why I read from the bitmap using the next function call
  769.         // and I got a picture on the screen.
  770.         // If I take this function call away - no more drawing action
  771.         // will occure.
  772.         // Is there anyone how can explain this?
  773.             GpiQueryBitmapBits(
  774.                 (unsigned long)pWindow->hpsBitmap,
  775.                 (LONG)iLine,
  776.                 (LONG)1,
  777.                 (unsigned char*)pDataCompare,
  778.                 pBitmapInfo);
  779.         // I've included this, caused of that calling one time
  780.         // above two functions caused no change in the bitmap
  781.         // in the first one or two lines.
  782.         // I've checked this!
  783.         // May be the display.dll is a little bit buggy
  784.         } while (memcmp(pData,
  785.             pDataCompare,
  786.             pWindow->iSizeX*sizeof*pData));
  787.         pWindow->winInvalidate(iLine);
  788.         pWindow->pabCalculated[iLine] = TRUE;
  789.     }
  790. }
  791.  
  792.  
  793. int main(int argc, char **argv)
  794. {      menuPmProcess *p = new menuPmProcess(argc, argv);
  795.  
  796.     if (p)
  797.         if (p->isSuccessfull())
  798.         {    p->run();
  799.             delete p;
  800.         }
  801.         else
  802.             delete p;
  803.     DosExit(EXIT_PROCESS, 0);
  804.     return 0;
  805. }
  806.  
  807.  
  808. dLLName::dLLName(char *pString, chain *pParent, unsigned int iIdNew)
  809.     :stringChainElement(pString, pParent)
  810. {    char acBuffer[1024];
  811.     char *(*pFctGetName)(void);
  812.     APIRET iRet;
  813.  
  814.     iId = iIdNew;
  815.     if (iRet = DosLoadModule((unsigned char*)acBuffer, sizeof acBuffer,
  816.         (unsigned char*)pString, &hDLL))
  817.     {    hDLL = (HMODULE)0;
  818.         setNoSuccess();
  819.         fprintf(stderr, "Error returned from DosLoadModule() == %u\n",
  820.             iRet);
  821.         return;
  822.     }
  823. /*
  824. @getName$qv                    @1
  825. @calculateFractal$quiuiuipucddddd @2
  826. */
  827.     if (iRet = DosQueryProcAddr(hDLL, 0, (unsigned char*)"_getName",
  828.         (PFN*)&pFctGetName))
  829.     {    setNoSuccess();
  830.         fprintf(stderr, "Error returned from DosQueryProcAddr(%s) == %u\n",
  831.             "getName",
  832.             iRet);
  833.         return;
  834.     }
  835.     if (!(pDescription = (*pFctGetName)()))
  836.     {    setNoSuccess();
  837.         return;
  838.     }
  839.     if (iRet = DosQueryProcAddr(hDLL,
  840.         0,
  841.         (unsigned char*)"_calculateFractal",
  842.         (PFN*)&pFctCalculate))
  843.     {    setNoSuccess();
  844.         fprintf(stderr, "Error returned from DosQueryProcAddr(%s) == %u\n",
  845.             "calculateFractal",
  846.             iRet);
  847.         return;
  848.     }
  849. }
  850.  
  851.  
  852. dLLName::~dLLName(void)
  853. {    if (hDLL)
  854.         DosFreeModule(hDLL);
  855. }
  856.  
  857.  
  858. int dLLName::toBeCalledForeachElement(unsigned int iMsg, void *pDummy)
  859. {    switch (iMsg)
  860.     {    default:
  861.             return stringChainElement
  862.                 ::toBeCalledForeachElement(iMsg, pDummy);
  863.         case idForeachDLLNameAddMenuEntry:
  864.             if (WinInsertLboxItem((HWND)pDummy, iId, pDescription)
  865.                 == iId)
  866.                 return 0;
  867.             else
  868.                 return -1;
  869.         case idForeachDLLNameGetThisByIndex:
  870.             if (*(unsigned int*)pDummy == iId)
  871.             {    *(dLLName**)pDummy = this;
  872.                 return -1;
  873.             }
  874.             else
  875.                 return 0;
  876.     }
  877. }
  878.  
  879.  
  880. settingsDlg::settingsDlg(menuWindowTree *pParentNew)
  881.     :dlgWindow(pParentNew, (HMODULE)0, idResourceDLGSettings, "Settings")
  882. {    pParent = pParentNew;
  883.     pStrXa = pStrXe = pStrYa = pStrXe = pStrLimit = (char*)0;
  884. }
  885.  
  886.  
  887. settingsDlg::~settingsDlg(void)
  888. {    if (pStrXa)
  889.         free(pStrXa);
  890.     if (pStrXe)
  891.         free(pStrXe);
  892.     if (pStrYa)
  893.         free(pStrYa);
  894.     if (pStrYe)
  895.         free(pStrYe);
  896.     if (pStrLimit)
  897.         free(pStrLimit);
  898. }
  899.  
  900. BOOL WinSetDlgItemDouble(HWND hWndDlg, ULONG iItemID, double dValue,
  901.     char **ppStr)
  902. {       char acBuffer[1024];
  903.  
  904.     sprintf(acBuffer, "%e", dValue);
  905.     if (!(*ppStr = strdup(acBuffer)))
  906.         return FALSE;
  907.     return WinSetDlgItemText(hWndDlg, iItemID, acBuffer);
  908. }
  909.  
  910.  
  911. Boolean settingsDlg::initPost(void)
  912. {    HWND hwndLbox = WinWindowFromID(hwndClient,
  913.         idResourceDLGSettingsIterationMethod);
  914.  
  915.     if (!hwndLbox)
  916.         return FALSE;
  917.     if (pParent->pProcess->chainDLLNames.foreach(idForeachDLLNameAddMenuEntry,
  918.         (void*)hwndLbox))
  919.         return FALSE;
  920.     WinSelectLboxItem(hwndLbox, pParent->iIdSelected, TRUE);
  921.     WinSetDlgItemDouble(hwndClient, idResourceDLGSettingsBorder,
  922.         pParent->dLimit, &pStrLimit);
  923.     WinSetDlgItemShort(hwndClient, idResourceDLGSettingsIterations,
  924.         pParent->iMaxIterations & 0xFFFF, FALSE);
  925.     WinSetDlgItemDouble(hwndClient, idResourceDLGSettingsCoordinatesXA,
  926.         pParent->xa, &pStrXa);
  927.     WinSetDlgItemDouble(hwndClient, idResourceDLGSettingsCoordinatesYA,
  928.         pParent->ya, &pStrYa);
  929.     WinSetDlgItemDouble(hwndClient, idResourceDLGSettingsCoordinatesXE,
  930.         pParent->xa + (pParent->iSizeX - 1)*pParent->xdx, &pStrXe);
  931.     WinSetDlgItemDouble(hwndClient, idResourceDLGSettingsCoordinatesYE,
  932.         pParent->ya + (pParent->iSizeX - 1)*pParent->ydx, &pStrYe);
  933.     return TRUE;
  934. }
  935.  
  936.  
  937. #define iBufferStrLen 64
  938.  
  939.  
  940. BOOL WinQueryDlgItemDouble(HWND hwndDlg, ULONG iItemID, double *pd,
  941.     char *pBuffer)
  942. {    char *pPos;
  943.  
  944.     if (!WinQueryDlgItemText(hwndDlg, iItemID, iBufferStrLen - 1,
  945.         pBuffer))
  946.         return FALSE;
  947.     *pd = strtod(pBuffer, &pPos);
  948.     if (*pPos)
  949.         return FALSE;
  950.     return TRUE;
  951. }
  952.  
  953.  
  954. MRESULT settingsDlg::DIDOK(MPARAM mp2)
  955. {       unsigned int iId;
  956.     double dXa, dXe, dYa, dYe, dLimit;
  957.     unsigned short iMaxIterations;
  958.     char acXa[iBufferStrLen], acYa[iBufferStrLen],
  959.         acXe[iBufferStrLen], acYe[iBufferStrLen],
  960.         acLimit[iBufferStrLen];
  961.     HWND hwndLbox = WinWindowFromID(hwndClient,
  962.         idResourceDLGSettingsIterationMethod);
  963.  
  964.     iId = WinQueryLboxSelectedItem(hwndLbox);
  965.     if (!WinQueryDlgItemDouble(hwndClient,
  966.         idResourceDLGSettingsCoordinatesXA,
  967.         &dXa, acXa)
  968.         || !WinQueryDlgItemDouble(hwndClient,
  969.         idResourceDLGSettingsCoordinatesYA,
  970.         &dYa, acYa)
  971.         || !WinQueryDlgItemDouble(hwndClient,
  972.         idResourceDLGSettingsCoordinatesXE,
  973.         &dXe, acXe)
  974.         || !WinQueryDlgItemDouble(hwndClient,
  975.         idResourceDLGSettingsCoordinatesYE,
  976.         &dYe, acYe)
  977.         || !WinQueryDlgItemDouble(hwndClient,
  978.         idResourceDLGSettingsBorder,
  979.         &dLimit, acLimit)
  980.         || !WinQueryDlgItemShort(hwndClient,
  981.         idResourceDLGSettingsIterations,
  982.         (short*)&iMaxIterations, FALSE))
  983.         return (MRESULT)TRUE;
  984.     if (iId != pParent->iIdSelected
  985.         || dXa != pParent->xa && strcmp(acXa, pStrXa)
  986.         || dYa != pParent->ya && strcmp(acYa, pStrYa)
  987.         || dXe != pParent->xa + (pParent->iSizeX - 1)*pParent->xdx
  988.         && strcmp(acXe, pStrXe)
  989.         || dYe != pParent->ya + (pParent->iSizeX - 1)*pParent->ydx
  990.         && strcmp(acYe, pStrYe)
  991.         || dLimit != pParent->dLimit && strcmp(acLimit, pStrLimit)
  992.         || iMaxIterations != pParent->iMaxIterations
  993.         )
  994.     {    dLLName *pDLLName = (dLLName*)iId;
  995.  
  996.         pParent->stopCalculation();
  997.         pParent->iIdSelected = iId;
  998.         pParent->xa = dXa;
  999.         pParent->ya = dYa;
  1000.         pParent->xdx = (dXe - dXa)/(pParent->iSizeX - 1);
  1001.         pParent->ydx = (dYe - dYa)/(pParent->iSizeX - 1);
  1002.         pParent->dLimit = dLimit;
  1003.         pParent->iMaxIterations = iMaxIterations;
  1004.         pParent->pProcess->chainDLLNames.foreach(
  1005.             idForeachDLLNameGetThisByIndex,
  1006.             &pDLLName);
  1007.         pParent->pFctCalculate = pDLLName->pFctCalculate;
  1008.         pParent->startCalculation();
  1009.     }
  1010.     return dlgWindow::DIDOK(mp2);
  1011. }
  1012.