home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mandlcpp.zip / apfel.cpp next >
C/C++ Source or Header  |  1993-06-27  |  20KB  |  735 lines

  1. #include "apfel.h"
  2. #include "apfel.resource.h"
  3. #include "communication.h"
  4. #ifdef INCLUDESOURCE
  5. #include "pmprocess.cc"
  6. #endif
  7.  
  8.  
  9. // The calculation thread if there are no servers
  10. // The priority is for both foreground and background of class idle -
  11. // caused of that this thread is not interactive
  12. calcThread::calcThread(menuWindowTree *pWindowNew)
  13.     :pmWindowThread(pWindowNew)
  14. {    pWindow = pWindowNew;
  15.     iClassF = PRTYC_IDLETIME;
  16.     iValueF = 31;
  17.     iClassB = PRTYC_IDLETIME;
  18.     iValueB = 0;
  19. }
  20.  
  21.  
  22. void menuWindowTree::winInvalidate(unsigned int yi)
  23. {    RECTL rcl;
  24.  
  25.     rcl.xLeft = 0;
  26.     rcl.yTop = yi + 1;
  27.     rcl.yBottom = yi;
  28.     rcl.xRight = iSizeX;
  29.     WinInvalidateRect(hwndClient, &rcl, FALSE);
  30. }
  31.  
  32.  
  33. // calculates a image
  34. void calcThread::doSomething(void)
  35. {    unsigned int xi, yi, it;
  36.     //menuPmThread *pMsgThread = (menuPmThread*)pParent;
  37.     double xl = pWindow->xa, yl = pWindow->ya, x, y;
  38.     BITMAPINFO2 *pBitmapInfo;
  39.     unsigned char *pData;
  40.     unsigned char *pDataCompare;
  41.     unsigned int iBitmapSize;
  42.  
  43.     pData = (unsigned char *)alloca(iBitmapSize = pWindow->iSizeX * sizeof(*pData));
  44.     pDataCompare = (unsigned char *)alloca(iBitmapSize);
  45.     assert(!((unsigned long)pData & 3));
  46.     pBitmapInfo = (BITMAPINFO2 *)alloca(256*sizeof(RGB2)
  47.        + (unsigned int)((char*)&pBitmapInfo->ulCompression
  48.       - (char*)&pBitmapInfo->cbFix));
  49.     memset(pBitmapInfo, 0, 256*sizeof(RGB2));
  50.     {    RGB2 *pScan;
  51.         unsigned short iColor;
  52.  
  53.         for (pScan = (RGB2*)&pBitmapInfo->ulCompression,
  54.            iColor = 0;
  55.            iColor < 256;
  56.            pScan++, iColor++)
  57.         {    pScan->fcOptions = PC_EXPLICIT;
  58.             pScan->bBlue = iColor;
  59.         }
  60.     }
  61.     pBitmapInfo->cbFix = (unsigned int)((char*)&pBitmapInfo->ulCompression
  62.        - (char*)&pBitmapInfo->cbFix);
  63.     assert(pBitmapInfo->cbFix > 0);
  64.     pBitmapInfo->cx = pWindow->iSizeX;
  65.     pBitmapInfo->cy = 1;
  66.     pBitmapInfo->cPlanes = 1;
  67.     pBitmapInfo->cBitCount = sizeof(*pData)*8;
  68.     /*
  69.     pBitmapInfo->ulCompression = BCA_UNCOMP;
  70.     pBitmapInfo->cbImage = 0;
  71.     pBitmapInfo->cxResolution = 0;
  72.     pBitmapInfo->cyResolution = 0;
  73.     pBitmapInfo->cclrUsed = 0;
  74.     pBitmapInfo->cclrImportant = 0;
  75.     pBitmapInfo->usUnits = 0;
  76.     pBitmapInfo->usReserved = 0;
  77.     pBitmapInfo->usRecording = BRA_BOTTOMUP;
  78.     pBitmapInfo->usRendering = BRH_NOTHALFTONED;
  79.     pBitmapInfo->ulColorEncoding = BCE_RGB;
  80.     */
  81.     for (yi = 0, x = xl, y = yl;
  82.        yi < pWindow->iSizeY;
  83.        x = (xl -= pWindow->ydx), y = (yl += pWindow->xdx),
  84.        GpiSetBitmapBits(
  85.         (unsigned long)pWindow->hpsBitmap,
  86.         (LONG)yi,
  87.         (LONG)1,
  88.         (unsigned char*)pData,
  89.         pBitmapInfo),
  90.         // After some hours without any picture,
  91.         // I wanted to have a look, wethere the bitmap will be changed
  92.         // or not.
  93.         // Thats why I read from the bitmap using the next function call
  94.         // and I got a picture on the screen.
  95.         // If I take this function call away - no more drawing action
  96.         // will occure.
  97.         // Is there anyone how can explain this?
  98.        GpiQueryBitmapBits(
  99.         (unsigned long)pWindow->hpsBitmap,
  100.         (LONG)yi,
  101.         (LONG)1,
  102.         (unsigned char*)pDataCompare,
  103.         pBitmapInfo),
  104.        pWindow->winInvalidate(yi),
  105.        yi++)
  106.     {    unsigned int iMaxColors_1 = pWindow->iMaxColors - 1;
  107.         double dLimit = pWindow->dLimit;
  108.         unsigned int iMaxIterations
  109.             = pWindow->iMaxIterations;
  110.         // You don't need to write the following stuff in assembler!
  111.         // Use a good compiler like EMX for OS/2!
  112.         for (xi = 0,
  113.            memset(pData, 0, iBitmapSize);
  114.            xi < pWindow->iSizeX;
  115.            xi++,
  116.            y += pWindow->ydx, x += pWindow->xdx
  117.            )
  118.         {    double y2 = y*y;
  119.             double x_1_2 = x + 1.0;
  120.  
  121.             x_1_2 *= x_1_2;
  122.             if (y2 + x_1_2 > 1.0/16.0)
  123.             {    double r = x*x + y2;
  124.                 double s = r - x*0.5 + 1.0/16.0;
  125.                 if ((r*16 - 5.0)*s + 4*x > 1)
  126.                 {    double xit = x, yit = y;
  127.  
  128.                     for (it = 0;
  129.                         it < iMaxIterations;
  130.                         it++)
  131.                     {    double x2 = xit*xit;
  132.                         double y2 = yit*yit;
  133.                         double r = y2 + x2;
  134.                         if (r > dLimit)
  135.                         {    pData[xi] = it
  136.                                 % iMaxColors_1 + 1;
  137.                             break;
  138.                         }
  139.                         r = 2*xit*yit + y;
  140.                         xit = x2 - y2 + x;
  141.                         yit = r;
  142.                     }
  143.                 }
  144.             }
  145.         }
  146.     }
  147. }
  148.  
  149.  
  150. // If there are some pipe names start in server-client mode
  151. // if not start the calculation thread  of class calcThread
  152. Boolean menuWindowTree::startCalculation(void)
  153. {       chainThreads.getMutualExclusiveAccess();
  154.     if (pProcess->chainPipes.iNumberOfElements)
  155.         if (pProcess->chainPipes.foreach(idForeachPipeNameMakeThread,
  156.             this))
  157.         {    chainThreads.freeMutualExclusiveAccess();
  158.             return FALSE;
  159.         }
  160.         else
  161.         {    chainThreads.freeMutualExclusiveAccess();
  162.             return TRUE;
  163.         }
  164.     else
  165.     {    calcThread *pThread;
  166.  
  167.         pThread = new calcThread(this);
  168.         if (pThread)
  169.             if (pThread->isSuccessfull())
  170.             {    pThread->startThread();
  171.                 chainThreads.freeMutualExclusiveAccess();
  172.                 return TRUE;
  173.             }
  174.             else
  175.                 delete pThread;
  176.         chainThreads.freeMutualExclusiveAccess();
  177.         return FALSE;
  178.     }
  179. }
  180.  
  181.  
  182. // Kills all running threads
  183. void menuWindowTree::stopCalculation(void)
  184. {    chainThreads.getMutualExclusiveAccess();
  185.     chainThreads.foreach(idForeachChainElementDestruct, (void*)0);
  186.     chainThreads.freeMutualExclusiveAccess();
  187. }
  188.  
  189.  
  190. // The windowproc of this class
  191. // some other message will be treated in the base classes
  192. MRESULT menuWindowTree::windowProc(ULONG msg, MPARAM mp1, MPARAM mp2)
  193. {    switch (msg)
  194.     {    default:
  195.             return processWindow::windowProc(msg, mp1, mp2);
  196.         case WM_BUTTON2DOWN:
  197.         {    WinPopupMenu(hwndClient,
  198.                 hwndClient,
  199.                 hwndMenu,
  200.                 MOUSEMSG(&msg)->x,
  201.                 MOUSEMSG(&msg)->y,
  202.                 0,
  203.                 PU_HCONSTRAIN
  204.                 | PU_VCONSTRAIN
  205.                 //| PU_MOUSEBUTTON2DOWN
  206.                 | PU_KEYBOARD
  207.                 | PU_MOUSEBUTTON1
  208.                 | PU_MOUSEBUTTON2);
  209.             return (MRESULT)TRUE;
  210.         }
  211.         case WM_BUTTON1DOWN:
  212.         {    if (eZoomState == 3)
  213.             {    drawZoomRectangle();
  214.                 WinEnableMenuItem(hwndMenu,
  215.                     idResourceMenuItemZoomOld, FALSE);
  216.                 WinEnableMenuItem(hwndMenu,
  217.                     idResourceMenuItemZoomNew, FALSE);
  218.             }
  219.             iZoomXE = iZoomXA = MOUSEMSG(&msg)->x;
  220.             iZoomYE = iZoomYA = MOUSEMSG(&msg)->y;
  221.             WinSetCapture(HWND_DESKTOP, hwndClient);
  222.             eZoomState = 1;
  223.             return (MRESULT)FALSE;
  224.         }
  225.         case WM_MOUSEMOVE:
  226.         {    if (eZoomState == 0 || eZoomState == 3)
  227.                 return (MRESULT)FALSE;
  228.             if (eZoomState == 2)
  229.                 drawZoomRectangle();
  230.             iZoomXE = MOUSEMSG(&msg)->x;
  231.             iZoomYE = MOUSEMSG(&msg)->y;
  232.             if (iZoomXE == iZoomXA || iZoomYE == iZoomYA)
  233.             {    eZoomState = 1;
  234.                 return (MRESULT)FALSE;
  235.             }
  236.             drawZoomRectangle();
  237.             eZoomState = 2;
  238.             return (MRESULT)FALSE;
  239.         }
  240.         case WM_BUTTON1UP:
  241.         {    if (eZoomState != 2)
  242.             {    if (eZoomState == 1)
  243.                 {    eZoomState = 0;
  244.                     WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  245.                 }
  246.                 return (MRESULT)FALSE;
  247.             }
  248.             WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  249.             drawZoomRectangle();
  250.             iZoomXE = MOUSEMSG(&msg)->x;
  251.             iZoomYE = MOUSEMSG(&msg)->y;
  252.             drawZoomRectangle();
  253.             eZoomState = 3;
  254.             WinEnableMenuItem(hwndMenu, idResourceMenuItemZoomOld,
  255.                 TRUE);
  256.             WinEnableMenuItem(hwndMenu, idResourceMenuItemZoomNew,
  257.                 TRUE);
  258.             return (MRESULT)FALSE;
  259.         }
  260. #ifdef undefined
  261.     unsigned int eZoomState;    // Are the following Values valid
  262.     //    0 means no valid zoom
  263.     //    1 means first point selected
  264.     //    2 has already moved, still moving
  265.     //    3 means second point selected,
  266.     int iZoomXA, iZoomYA, iZoomXE, iZoomYE;
  267. #endif
  268.         case WM_COMMAND:
  269.             switch ((USHORT)mp1)
  270.             {       default:
  271.                     return processWindow
  272.                         ::windowProc(msg, mp1, mp2);
  273.                 case idResourceMenuItemZoomOld:
  274.                     if (eZoomState != 3)
  275.                         return (MRESULT)FALSE;
  276.                     stopCalculation();
  277.                     WinEnableMenuItem(hwndMenu,
  278.                         idResourceMenuItemZoomOld,
  279.                         FALSE);
  280.                     WinEnableMenuItem(hwndMenu,
  281.                         idResourceMenuItemZoomNew,
  282.                         FALSE);
  283.                     eZoomState = 0;
  284.                     calcZoomCoordinates();
  285.                     startCalculation();
  286.                     return (MRESULT)FALSE;                case idResourceMenuItemZoomNew:
  287.                 {    menuWindowTree *pWindowTree;
  288.  
  289.                     if (eZoomState != 3)
  290.                         return (MRESULT)FALSE;
  291.                     if (!(pWindowTree
  292.                         = new menuWindowTree(
  293.                         (menuPmThread*)pMsgThread
  294.                         ->getChainElementMember(
  295.                         idGetChainElementMenuMsgThreadTreeThis)
  296.                         ,
  297.                         0,
  298.                         "Apfel")))
  299.                         return (MRESULT)FALSE;
  300.                     else
  301.                         if (!pWindowTree->isSuccessfull())
  302.                         {    delete pWindowTree;
  303.                             return (MRESULT)FALSE;
  304.                         }
  305.                     pWindowTree->bCoordiantesValid = TRUE;
  306.                     pWindowTree->xa = xa;
  307.                     pWindowTree->xdx = xdx;
  308.                     pWindowTree->ya = ya;
  309.                     pWindowTree->ydx = ydx;
  310.                     pWindowTree->iMaxIterations = iMaxIterations;
  311.                     pWindowTree->dLimit = dLimit;
  312.                     pWindowTree->iZoomXA = iZoomXA;
  313.                     pWindowTree->iZoomYA = iZoomYA;
  314.                     pWindowTree->iZoomXE = iZoomXE;
  315.                     pWindowTree->iZoomYE = iZoomYE;
  316.                     //pWindowTree->eZoomState = eZoomState;
  317.                     if (!pWindowTree->init())
  318.                         delete pWindowTree;
  319.                     return (MRESULT)FALSE;
  320.                 }
  321.             }
  322.     }
  323. }
  324.  
  325.  
  326. void menuWindowTree::doPaint(HPS hps, RECTL *pStructRectl)
  327. {    POINTL aPoint[4];
  328.  
  329.     aPoint[0].x = pStructRectl->xLeft;
  330.     aPoint[0].y = pStructRectl->yBottom;
  331.     aPoint[1].x = pStructRectl->xRight;
  332.     aPoint[1].y = pStructRectl->yTop;
  333.     aPoint[2].x = pStructRectl->xLeft;
  334.     aPoint[2].y = pStructRectl->yBottom;
  335.     aPoint[3].x = pStructRectl->xRight;
  336.     aPoint[3].y = pStructRectl->yTop;
  337.     if (eZoomState >= 2)
  338.         drawZoomRectangle();
  339.     GpiBitBlt(hps, hpsBitmap, 4, aPoint, ROP_SRCCOPY, BBO_OR);
  340.     if (eZoomState >= 2)
  341.         drawZoomRectangle();
  342. }
  343.  
  344.  
  345. Boolean menuWindowTree::initPost(void)
  346. {       if (!processWindow::initPost())
  347.         return FALSE;
  348.     {    SIZEL structSize;
  349.  
  350.         structSize.cx = structSize.cy = 0;
  351.         hZoomRectanglePS = GpiCreatePS(pMsgThread->hab,
  352.             hWindowDC,
  353.             &structSize,
  354.             PU_PELS | GPIA_ASSOC);
  355.     }
  356.     GpiSetMix(hZoomRectanglePS, FM_INVERT);
  357.     hdcBitmap = DevOpenDC(pMsgThread->hab, OD_MEMORY, (unsigned char*)"*", 0, 0, 0);
  358.     {    SIZEL size;
  359.  
  360.         size.cx = size.cy = 0;
  361.         hpsBitmap = GpiCreatePS(pMsgThread->hab, hdcBitmap, &size,
  362.            PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
  363.     }
  364.     iSizeX = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
  365.     iSizeY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
  366.     {    long alBmpFormats[2];
  367.         BITMAPINFOHEADER2 structBmpInfoHeader;
  368.  
  369.         GpiQueryDeviceBitmapFormats(hpsBitmap, 2, alBmpFormats);
  370.         memset(&structBmpInfoHeader, 0, sizeof(structBmpInfoHeader));
  371.         structBmpInfoHeader.cbFix = sizeof(structBmpInfoHeader);
  372.         structBmpInfoHeader.cx = iSizeX;
  373.         structBmpInfoHeader.cy = iSizeY;
  374.         structBmpInfoHeader.cPlanes = (USHORT)alBmpFormats[0];
  375.         structBmpInfoHeader.cBitCount = (USHORT)alBmpFormats[1];
  376.         hbm = GpiCreateBitmap(hpsBitmap,
  377.             &structBmpInfoHeader,
  378.             0,
  379.             (BYTE*)0,
  380.             (BITMAPINFO2*)0);
  381.     }
  382.     GpiSetBitmap(hpsBitmap, hbm);
  383.     {    POINTL aPoint[4];
  384.  
  385.         aPoint[0].x = 0;
  386.         aPoint[0].y = iSizeY;
  387.         aPoint[1].x = iSizeX;
  388.         aPoint[1].y = 0;
  389.         aPoint[2].x = 0;
  390.         aPoint[2].y = iSizeY;
  391.         aPoint[3].x = iSizeX;
  392.         aPoint[3].y = 0;
  393.         GpiBitBlt(hpsBitmap, hpsBitmap, 4, aPoint, ROP_ZERO, BBO_OR);
  394.     }
  395.     // Wether the window is the first started or not
  396.     // the values need initialization or not
  397.     if (!bCoordiantesValid)
  398.     {    xa = -2.0;
  399.         xdx = 3.0 / (iSizeX - 1);
  400.         ya = -xdx*(iSizeY - 1)*0.5;
  401.         ydx = 0.0;
  402.         iMaxIterations = 255;
  403.         dLimit = 100.0;
  404.     }
  405.     else
  406.         calcZoomCoordinates();
  407.     {    HDC hdc;
  408.         hdc = WinOpenWindowDC(HWND_DESKTOP);
  409.         DevQueryCaps((HDC)hdc, (LONG)CAPS_COLORS, (LONG)1,
  410.             (LONG*)&iMaxColors);
  411.         DevCloseDC(hdc);
  412.     }
  413.     //hwndMenu = WinWindowFromID(hwndFrame, FID_MENU);
  414.     hwndMenu = WinLoadMenu(hwndClient, (HMODULE)0, idResourceMenu);
  415.     if (pProcess->chainPipes.iNumberOfElements)
  416.     {    pabCalculated = new unsigned char[iSizeY];
  417.         memset(pabCalculated, 0, iSizeY*sizeof*pabCalculated);
  418.     }
  419.     else
  420.         pabCalculated = (unsigned char*)0;
  421.     // start the calculation thread(s)
  422.     return startCalculation();
  423. }
  424.  
  425.  
  426. // the matching counterpart for initPost()
  427. void menuWindowTree::destructPre(void)
  428. {       stopCalculation();
  429.     if (pabCalculated)
  430.         delete pabCalculated;
  431.     GpiDeleteBitmap(hbm);
  432.     DevCloseDC(hdcBitmap);
  433.     GpiDestroyPS(hZoomRectanglePS);
  434.     processWindow::destructPre();
  435. }
  436.  
  437.  
  438. // I think there is still a bug releated to the milestone problem
  439. void menuWindowTree::drawZoomRectangle(void)
  440. {    int iXa, iYa, iXe = iZoomXE,
  441.         iYe = iZoomYE, iXdx, iYdx, iXdy, iYdy;
  442.     POINTL aStructPoint[5];
  443.  
  444.     iXa = 2*iZoomXA - iXe;
  445.     iYa = 2*iZoomYA - iYe;
  446.     iXdx = iXe - iXa;
  447.     iYdx = iYe - iYa;
  448.     iYdy = iXdx*(iSizeY - 1)/(iSizeX - 1)/2;
  449.     iXdy = -iYdx*(iSizeY - 1)/(iSizeX - 1)/2;
  450.     aStructPoint[0].x = iXa - iXdy; aStructPoint[0].y = iYa - iYdy;
  451.     aStructPoint[1].x = iXe - iXdy; aStructPoint[1].y = iYe - iYdy;
  452.     aStructPoint[2].x = iXe + iXdy; aStructPoint[2].y = iYe + iYdy;
  453.     aStructPoint[3].x = iXa + iXdy; aStructPoint[3].y = iYa + iYdy;
  454.     aStructPoint[4].x = iXa - iXdy; aStructPoint[4].y = iYa - iYdy;
  455.     GpiMove(hZoomRectanglePS, aStructPoint);
  456.     GpiPolyLine(hZoomRectanglePS, 5, aStructPoint);
  457. }
  458.  
  459.  
  460. Boolean menuWindowTree::initPre(void)
  461. {    if (!processWindow::initPre())
  462.         return FALSE;
  463.     //frameFlags |= FCF_MENU;
  464.     pWindowClassName = "menuWindowTree";
  465.     return TRUE;
  466. }
  467.  
  468.  
  469. menuWindowTree::menuWindowTree(menuPmThread *pMsgThreadNew, int idResource,
  470.     char *pTitle):processWindow(pMsgThreadNew, idResource, pTitle), oMtx()
  471. {    pMsgThread = pMsgThreadNew;
  472.     pProcess = pMsgThread->pProcess;
  473. }
  474.  
  475.  
  476. menuWindowTree::~menuWindowTree(void)
  477. {
  478. }
  479.  
  480.  
  481. // I think there is still a bug releated to a milestone problem
  482. void menuWindowTree::calcZoomCoordinates(void)
  483. {    int iXa, iYa, iXe = iZoomXE, iYe = iZoomYE, iXdx, iYdx, iXdy, iYdy;
  484.     double dXaNew, dYaNew, dxdxNew, dydxNew;
  485.  
  486.     iXa = 2*iZoomXA - iXe;
  487.     iYa = 2*iZoomYA - iYe;
  488.     iXdx = iXe - iXa;
  489.     iYdx = iYe - iYa;
  490.     iYdy = iXdx*iSizeY/(iSizeX - 1)/2;
  491.     iXdy = -iYdx*iSizeY/(iSizeX - 1)/2;
  492.     iXa -= iXdy; iYa -= iYdy;
  493.     iXe -= iXdy; iYe -= iYdy;
  494.     dXaNew = xa + iXa*xdx - iYa*ydx;
  495.     dYaNew = ya + iXa*ydx + iYa*xdx;
  496.     dxdxNew = (xa + iXe*xdx - iYe*ydx - dXaNew)/(iSizeX - 1);
  497.     dydxNew = (ya + iXe*ydx + iYe*xdx - dYaNew)/(iSizeX - 1);
  498.     xa = dXaNew;
  499.     ya = dYaNew;
  500.     xdx = dxdxNew;
  501.     ydx = dydxNew;
  502. }
  503.  
  504.  
  505. menuPmThread::menuPmThread(menuPmProcess *pProcessNew)
  506.     :pmMsgThread(pProcessNew)
  507. {    pProcess = pProcessNew;
  508. }
  509.  
  510.  
  511. Boolean menuPmThread::create(void)
  512. {    menuWindowTree *pWindowTree;
  513.  
  514.     if (!(pWindowTree
  515.        = new menuWindowTree(this, 0, "Apfel")))
  516.         return FALSE;
  517.     else
  518.         if (!pWindowTree->isSuccessfull())
  519.         {    delete pWindowTree;
  520.             return FALSE;
  521.         }
  522.     return TRUE;
  523. }
  524.  
  525.  
  526. Boolean menuPmProcess::create(void)
  527. {    if (argc > 1)
  528.     {    FILE *pFile;
  529.         char acLine[1024];
  530.  
  531.         if (!(pFile = fopen(argv[1], "r")))
  532.         {    fprintf(stderr, "Cannot open %s!\n", argv[1]);
  533.             return FALSE;
  534.         }
  535.         acLine[sizeof acLine - 1] = 0;
  536.         // reading of the file
  537.         // create a object of class pipeName for every line in the file
  538.         while (fgets(acLine, sizeof acLine - 1, pFile))
  539.         {    pipeName *p;
  540.             char *pPos;
  541.  
  542.             if (pPos = strchr(acLine, '\n'))
  543.                 *pPos = 0;
  544.             if (p = new pipeName(acLine, &chainPipes))
  545.                 if (p->isSuccessfull())
  546.                     continue;
  547.                 else
  548.                     delete p;
  549.             fprintf(stderr, "Not enough memory!\n");
  550.             return FALSE;
  551.         }
  552.         fclose(pFile);
  553.     }
  554.     if (!new menuPmThread(this))
  555.         return FALSE;
  556.     else
  557.         if (!pProcessThread->isSuccessfull())
  558.         {    delete pProcessThread;
  559.             return FALSE;
  560.         }
  561.         else
  562.             return TRUE;
  563. }
  564.  
  565.  
  566. int pipeName::toBeCalledForeachElement(unsigned int iMsg, void *pData)
  567. {    switch (iMsg)
  568.     {    default:
  569.             return stringChainElement
  570.                 ::toBeCalledForeachElement(iMsg, pData);
  571.         case idForeachPipeNameMakeThread:
  572.         {       clientThread *pThread;
  573.  
  574.             if (!(pThread = new clientThread((menuWindowTree*)pData,
  575.                 pString)))
  576.                 return -1;
  577.             else
  578.                 if (!pThread->isSuccessfull())
  579.                 {    delete pThread;
  580.                     return -1;
  581.                 }
  582.             pThread->startThread();
  583.             return 0;
  584.         }
  585.     }
  586. }
  587.  
  588.  
  589. clientThread::clientThread(menuWindowTree *pWindowNew, char *pPipeName)
  590.     :pmWindowThread(pWindowNew)
  591. {    unsigned long iAction;
  592.  
  593.     pWindow = pWindowNew;
  594.     //wait for a listening pipe available
  595.     if (DosWaitNPipe((unsigned char*)pPipeName, -1)
  596.         || DosOpen(pPipeName, &hPipe, &iAction, 0, 0,
  597.         OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
  598.         OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
  599.         (EAOP2*)0))
  600.     {    setNoSuccess();
  601.         hPipe = (HPIPE)0;
  602.         return;
  603.     }
  604. }
  605.  
  606. clientThread::~clientThread(void)
  607. {    if (hPipe)
  608.         DosClose(hPipe);
  609. }
  610.  
  611.  
  612. void clientThread::doSomething(void)
  613. {    BITMAPINFO2 *pBitmapInfo;
  614.     unsigned char *pData;
  615.     unsigned char *pDataCompare;
  616.     unsigned int iBitmapSize;
  617.  
  618.     pData = (unsigned char *)alloca(iBitmapSize = pWindow->iSizeX * sizeof(*pData));
  619.     pDataCompare = (unsigned char *)alloca(iBitmapSize);
  620.     assert(!((unsigned long)pData & 3));
  621.     pBitmapInfo = (BITMAPINFO2 *)alloca(256*sizeof(RGB2)
  622.        + (unsigned int)((char*)&pBitmapInfo->ulCompression
  623.       - (char*)&pBitmapInfo->cbFix));
  624.     memset(pBitmapInfo, 0, 256*sizeof(RGB2));
  625.     {    RGB2 *pScan;
  626.         unsigned short iColor;
  627.  
  628.         for (pScan = (RGB2*)&pBitmapInfo->ulCompression,
  629.            iColor = 0;
  630.            iColor < 256;
  631.            pScan++, iColor++)
  632.         {    pScan->fcOptions = PC_EXPLICIT;
  633.             pScan->bBlue = iColor;
  634.         }
  635.     }
  636.     pBitmapInfo->cbFix = (unsigned int)((char*)&pBitmapInfo->ulCompression
  637.        - (char*)&pBitmapInfo->cbFix);
  638.     assert(pBitmapInfo->cbFix > 0);
  639.     pBitmapInfo->cx = pWindow->iSizeX;
  640.     pBitmapInfo->cy = 1;
  641.     pBitmapInfo->cPlanes = 1;
  642.     pBitmapInfo->cBitCount = sizeof(*pData)*8;
  643.  
  644.     // make sure that only one thread has access to pWindow->iLine
  645.     // and pWindow->pabCalculated
  646.     pWindow->oMtx.getMutualExclusiveAccess();
  647.     while (1)
  648.     {    unsigned int iLine;
  649.         structRequest structR;
  650.         unsigned long iBytes;
  651.  
  652.         if (pWindow->iLine < pWindow->iSizeY)
  653.             iLine = pWindow->iLine++;
  654.         else
  655.         {    unsigned char *pScan, *pMax;
  656.  
  657.             for (pScan = pWindow->pabCalculated,
  658.                 pMax = pScan + pWindow->iSizeY;
  659.                 pScan < pMax;
  660.                 pScan++)
  661.                 if (!*pScan)
  662.                 {    iLine = pScan - pWindow->pabCalculated;
  663.                     break;
  664.                 }
  665.             if (pScan == pMax)
  666.             {    pWindow->oMtx.freeMutualExclusiveAccess();
  667.                 return;
  668.             }
  669.         }
  670.         pWindow->oMtx.freeMutualExclusiveAccess();
  671.         structR.iSizeX = pWindow->iSizeX;
  672.         structR.iMaxIterations = pWindow->iMaxIterations;
  673.         structR.iMaxColors = pWindow->iMaxColors;
  674.         structR.dLimit = pWindow->dLimit;
  675.         structR.dXa = pWindow->xa - pWindow->ydx*iLine;
  676.         structR.dYa = pWindow->ya + pWindow->xdx*iLine;
  677.         structR.dXdx = pWindow->xdx;
  678.         structR.dYdx = pWindow->ydx;
  679.         if (DosWrite(hPipe, &structR, sizeof structR, &iBytes)
  680.             || iBytes != sizeof structR)
  681.             return;
  682.         if (DosRead(hPipe, pData, pWindow->iSizeX*sizeof*pData,
  683.             &iBytes)
  684.             || iBytes != pWindow->iSizeX*sizeof*pData)
  685.             return;
  686.         pWindow->oMtx.getMutualExclusiveAccess();
  687.         do
  688.         {    GpiSetBitmapBits(
  689.                 (unsigned long)pWindow->hpsBitmap,
  690.                 (LONG)iLine,
  691.                 (LONG)1,
  692.                 (unsigned char*)pData,
  693.                 pBitmapInfo);
  694.         // After some hours without any picture,
  695.         // I wanted to have a look, wethere the bitmap will be changed
  696.         // or not.
  697.         // Thats why I read from the bitmap using the next function call
  698.         // and I got a picture on the screen.
  699.         // If I take this function call away - no more drawing action
  700.         // will occure.
  701.         // Is there anyone how can explain this?
  702.             GpiQueryBitmapBits(
  703.                 (unsigned long)pWindow->hpsBitmap,
  704.                 (LONG)iLine,
  705.                 (LONG)1,
  706.                 (unsigned char*)pDataCompare,
  707.                 pBitmapInfo);
  708.         // I've included this, caused of that calling one time
  709.         // above two functions caused no change in the bitmap
  710.         // in the first one or two lines.
  711.         // I've checked this!
  712.         // May be the display.dll is a little bit buggy
  713.         } while (memcmp(pData,
  714.             pDataCompare,
  715.             pWindow->iSizeX*sizeof*pData));
  716.         pWindow->winInvalidate(iLine);
  717.         pWindow->pabCalculated[iLine] = TRUE;
  718.     }
  719. }
  720.  
  721.  
  722. int main(int argc, char **argv)
  723. {      menuPmProcess *p = new menuPmProcess(argc, argv);
  724.  
  725.     if (p)
  726.         if (p->isSuccessfull())
  727.         {    p->run();
  728.             delete p;
  729.         }
  730.         else
  731.             delete p;
  732.     DosExit(EXIT_PROCESS, 0);
  733.     return 0;
  734. }
  735.