home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / linefrac / linefrac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-09  |  15.6 KB  |  671 lines

  1. /************************************************************************
  2. *
  3. *   linefrac.c -- Main window procedure for LineFractal window class.
  4. *
  5. *   Created by Microsoft Corporation, 1989
  6. *
  7. ************************************************************************/
  8.  
  9. #define INCL_WIN
  10. #define INCL_GPI
  11. #define INCL_DOSSEMAPHORES
  12. #define INCL_DOSMEMMGR
  13. #define INCL_DOSPROCESS
  14. #include <os2.h>
  15.  
  16. #define _MT
  17. #include <process.h>
  18.  
  19. #include <stdlib.h>
  20.  
  21. #define INCL_GLOBALS
  22. #define INCL_THREADS
  23. #include "linefrac.h"
  24.  
  25. #define INCL_LFMAIN
  26. #define INCL_LFINIT
  27. #define INCL_LFTHREAD
  28. #define INCL_LFPS
  29. #define INCL_LFCMD
  30. #define INCL_LFDRAW
  31. #include "lffuncs.h"
  32.  
  33.  
  34.  
  35.  
  36. /************************************************************************
  37. *
  38. *   Global Variables
  39. *
  40. ************************************************************************/
  41.  
  42. GLOBALDATA global;
  43.  
  44.  
  45.  
  46.  
  47. /************************************************************************
  48. *
  49. *   main
  50. *
  51. *   WinInitialize resizes our ring 2 stack, among other things, so
  52. *   we won't GP fault trying to do graphics.  WinCreateMsgQueue defines
  53. *   us as a REAL PM app. (as does the WINDOWAPI in the .DEF file).
  54. *   Call a subroutine to register our window class and create a window.
  55. *   Loop over messages.  Exit cleanly.
  56. *
  57. ************************************************************************/
  58.  
  59. VOID cdecl
  60. main( VOID )
  61. {
  62.     QMSG qMsg;
  63.     int iRet = 0;
  64.  
  65.     global.hab     = WinInitialize(0);
  66.     global.hMsgQ = WinCreateMsgQueue(global.hab, 0);
  67.  
  68.     if (LfInitApp())
  69.     while (WinGetMsg( global.hab, (PQMSG)&qMsg, (HWND)NULL, 0, 0 ))
  70.         WinDispatchMsg( global.hab, (PQMSG)&qMsg );
  71.     else
  72.     iRet = -1;
  73.  
  74.     WinDestroyWindow( global.hwndFrame );
  75.     WinDestroyMsgQueue( global.hMsgQ );
  76.     WinTerminate( global.hab );
  77.     DosExit(EXIT_PROCESS, iRet);
  78. }
  79.  
  80.  
  81.  
  82.  
  83. /************************************************************************
  84. *
  85. *   LineFracWndProc
  86. *
  87. *   Process messages for the LineFractal window class.
  88. *
  89. ************************************************************************/
  90.  
  91. ULONG CALLBACK
  92. LineFracWndProc( hwnd, usMsg, mp1, mp2 )
  93. HWND   hwnd;
  94. USHORT usMsg;
  95. MPARAM  mp1;
  96. MPARAM  mp2;
  97. {
  98.     HPS     hps;
  99.     USHORT  iNewTop;
  100.     USHORT  i;
  101.     PTHR pthr;
  102.     RECTL rcl;
  103.     BOOL  fIsTimerUsed;
  104.  
  105.     switch (usMsg)
  106.     {
  107.     case WM_CREATE:
  108.     if ((global.hptr)[global.usCurPtr])
  109.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  110.     break;
  111.  
  112.     case WM_CLOSE:
  113.     LfClose(hwnd);
  114.     break;
  115.  
  116.     case WM_COMMAND:
  117.     LfCommand(hwnd, LOUSHORT(mp1));
  118.     break;
  119.  
  120.     case WM_TIMER:
  121.     if (LOUSHORT(mp1) == IDT_AUTOSTARTREDRAW)
  122.     {
  123.         fIsTimerUsed = FALSE;
  124.         for (i = 0; i < global.cThr; ++i)
  125.         if (global.aThr[i]->fAutoStartRedraw)
  126.         {
  127.             DosSemClear(&(global.aThr[i])->lSemRedraw);
  128.             fIsTimerUsed = TRUE;
  129.         }
  130.         if (!fIsTimerUsed)
  131.         LfStopRedrawTimer();
  132.         else
  133.         {
  134.         LfStopRedrawTimer();
  135.         LfStartRedrawTimer();
  136.         }
  137.     }
  138.     else if (LOUSHORT(mp1) == IDT_AUTOSWITCH)
  139.     {
  140.         DosEnterCritSec();
  141.         iNewTop = (global.iThrTop + 1) % global.cThr;
  142.         DosExitCritSec();
  143.         LfBringThreadToTop(global.aThr[iNewTop]);
  144.     }
  145.     else
  146.         goto pass_it_on;
  147.     break;
  148.  
  149.     case WM_ERASEBACKGROUND:
  150.     LfEraseBackground(hwnd, NULL, NULL, NULL);
  151.     return FALSE;
  152.     break;
  153.  
  154.     case WM_PAINT:
  155.     if (!global.pThrTop)
  156.         WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_DCMEMORY, 0);
  157.  
  158.     hps = WinBeginPaint(global.hwnd, NULL, &rcl);
  159.     if (global.pThrTop)   /* only try to paint if we have a drawing */
  160.         LfPaint(hps, &rcl);
  161.     WinEndPaint(hps);
  162.     break;
  163.  
  164.     case WM_CHAR:
  165.     if (LOUSHORT(mp1) & KC_CHAR) 
  166.    {
  167.      LfChar(hwnd, (CHAR)(USHORT)(ULONG)(mp2));
  168.     }
  169.     break;
  170.  
  171.     case WM_BUTTON1DOWN:
  172.     case WM_BUTTON2DOWN:
  173.     LfButtonDown(hwnd, mp1);
  174.     WinSetFocus(HWND_DESKTOP, hwnd);
  175.     break;
  176.  
  177.     case WM_BUTTON1UP:
  178.     case WM_BUTTON2UP:
  179.     LfButtonUp(usMsg);
  180.     break;
  181.  
  182.     case WM_MOUSEMOVE:
  183.     LfMouseMove();
  184.     break;
  185.  
  186.     case WM_SIZE:
  187.     /* Resize each PS that has fAutoSizePS set to TRUE. */
  188.  
  189.     WinQueryWindowRect(global.hwnd, &global.rcl);
  190.     global.bm.cx = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
  191.     global.bm.cy = (USHORT) (global.rcl.yTop   - global.rcl.yBottom);
  192.  
  193.     for (i = 0; i < global.cThr; ++i)
  194.         if (pthr = global.aThr[i])
  195.         if (pthr->hps)
  196.             if (pthr->fAutoSizePS)
  197.             {
  198.             global.bm.cPlanes   = pthr->cPlanes;
  199.             global.bm.cBitCount = pthr->cBitCount;
  200.  
  201.             if (LfResizePS(pthr))
  202.                 DosSemClear(&pthr->lSemRedraw);
  203.             }
  204.  
  205.     /* fall through -- we might want to restart point accumulation,
  206.        but don't want to process the resize message */
  207.  
  208.     default:
  209. pass_it_on:
  210.     return( (ULONG)WinDefWindowProc(hwnd, usMsg, mp1, mp2));
  211.     break;
  212.     }
  213.  
  214.     return FALSE;
  215. }
  216.  
  217.  
  218.  
  219.  
  220. /************************************************************************
  221. *
  222. *   LfClose
  223. *
  224. *   Kill all the threads still running and delete all our fancy pointers.
  225. *   In general, prepare to terminate the program.
  226. *
  227. ************************************************************************/
  228.  
  229. VOID
  230. LfClose(hwnd)
  231. HWND hwnd;
  232. {
  233.     int i;
  234.  
  235.     WinSendMsg(hwnd, WM_COMMAND, (MPARAM)IDM_KILLALLTHREADS, 0);
  236.     WinSetPointer(HWND_DESKTOP,
  237.           WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,FALSE));
  238.     for (i = 0; i < NUM_PTR_SHAPES; ++i)
  239.     if ((global.hptr)[i])
  240.         WinDestroyPointer((global.hptr)[i]);
  241.     if (global.hptrTrack)
  242.     WinDestroyPointer(global.hptrTrack);
  243.     if (global.hptrPaste)
  244.     WinDestroyPointer(global.hptrPaste);
  245.     WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
  246. }
  247.  
  248.  
  249.  
  250.  
  251. /************************************************************************
  252. *
  253. *   LfEraseBackground
  254. *
  255. *   Erase the window background to a hatch pattern.  This enables the
  256. *   user to see where the bitmap's edges are in case it's smaller
  257. *   than the window.
  258. *
  259. ************************************************************************/
  260.  
  261. VOID
  262. LfEraseBackground(hwnd, hpsCaller, prclUpdate, prclX)
  263. HWND hwnd;
  264. HPS hpsCaller;
  265. PRECTL prclUpdate;
  266. PRECTL prclX;    /* excluded rectangle */
  267. {
  268.     HPS hps;
  269.     RECTL rcl;
  270.     RECTL rclT;
  271.     AREABUNDLE ab;
  272.     HRGN hrgnClipOld;
  273.     HRGN hrgn;
  274.     HRGN hrgnT;
  275.  
  276.  
  277.     if (hpsCaller)
  278.     hps = hpsCaller;
  279.     else
  280.     hps = WinGetPS(hwnd);
  281.  
  282.     if (prclUpdate)
  283.     rcl = *prclUpdate;
  284.     else
  285.     WinQueryUpdateRect(hwnd, (PRECTL)&rcl);
  286.  
  287.     ab.lColor      = CLR_BLACK;
  288.     ab.lBackColor = CLR_WHITE;
  289.     ab.usSymbol   = PATSYM_DIAG1;
  290.     GpiSetAttrs(hps, PRIM_AREA, ABB_COLOR|ABB_BACK_COLOR|ABB_SYMBOL,
  291.         0L, (PBUNDLE)&ab);
  292.  
  293.  
  294.     /* Make a region out of the nearest rectangle, then copy the real
  295.      * region data into it.  Set this as our clip rectangle.
  296.      */
  297.     if ((hrgn = GpiCreateRegion(hps, 1L, &rcl)) != HRGN_ERROR)
  298.     {
  299.     WinQueryUpdateRegion(hwnd, hrgn);
  300.     GpiSetClipRegion(hps, hrgn, &hrgnClipOld);
  301.     }
  302.  
  303.     if (!prclX)
  304.     GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rcl, ROP_PATCOPY, 0L);
  305.     else
  306.     {
  307.     if (prclX->yTop < rcl.yTop)
  308.     {
  309.         rclT.xLeft     = rcl.xLeft;
  310.         rclT.yBottom = prclX->yBottom;
  311.         rclT.xRight  = rcl.xRight;
  312.         rclT.yTop     = rcl.yTop;
  313.         GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rclT, ROP_PATCOPY, 0L);
  314.     }
  315.  
  316.     if (prclX->xRight < rcl.xRight)
  317.     {
  318.         rclT.xLeft     = prclX->xRight;
  319.         rclT.yBottom = rcl.yBottom;
  320.         rclT.xRight  = rcl.xRight;
  321.         rclT.yTop     = prclX->yTop;
  322.         GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rclT, ROP_PATCOPY, 0L);
  323.     }
  324.     }
  325.  
  326.     if (hrgnClipOld != HRGN_ERROR)
  327.     GpiSetClipRegion(hps, hrgnClipOld, &hrgnT);
  328.     if (hrgn != HRGN_ERROR)
  329.     GpiDestroyRegion(hps, hrgn);
  330.  
  331.     if (!hpsCaller)
  332.     WinReleasePS(hps);
  333. }
  334.  
  335.  
  336.  
  337.  
  338. /************************************************************************
  339. *
  340. *   LfPaint
  341. *
  342. *   If we have a bitmap, blt it to the screen, no matter what state
  343. *   it's in.  If the selection rectangle is still alive, then display
  344. *   it, too.  Note that it goes directly to the screen, so we have to
  345. *   redraw it each time the bitmap is thrown back up.
  346. *
  347. ************************************************************************/
  348.  
  349. VOID
  350. LfPaint(hps, prcl)
  351. HPS  hps;
  352. PRECTL prcl;
  353. {
  354.     POINTL  aptl[4];
  355.  
  356.     if (global.pThrTop)
  357.     {
  358.     switch (global.pThrTop->dcType)
  359.     {
  360.     case IDM_DCDIRECT:    /* all drawing is already on the screen */
  361.         break;
  362.  
  363.     case IDM_DCPOSTSCRIPT:
  364.     case IDM_DCPROPRINTER:
  365.         break;
  366.  
  367.     case IDM_DCMEMORY:
  368.  
  369.         GpiSetAttrs(hps, PRIM_IMAGE, IBB_COLOR|IBB_BACK_COLOR, 0L, &global.pThrTop->ib);
  370.  
  371.         aptl[0].x = 0L;
  372.         aptl[0].y = 0L;
  373.         aptl[1].x = (global.pThrTop->rcl).xRight;
  374.         aptl[1].y = (global.pThrTop->rcl).yTop;
  375.         aptl[2].x = 0L;
  376.         aptl[2].y = 0L;
  377.  
  378.         GpiBitBlt(hps, global.pThrTop->hps, 3L, aptl, ROP_SRCCOPY, (LONG)NULL);
  379.         LfEraseBackground(global.hwnd, hps, prcl, &(global.pThrTop->rcl));
  380.         break;
  381.  
  382.     default:
  383.         break;
  384.     }
  385.     if (global.fShowSelectRc)
  386.         LfShowSelectRc(hps, global.fTempSelect ? &global.rclSelect : &global.rclCutCopy);
  387.     }
  388. }
  389.  
  390.  
  391.  
  392.  
  393. /************************************************************************
  394. *
  395. *   LfShowSelectRc
  396. *
  397. *   Draw the selection rectangle in the given presentation space.  The
  398. *   rectangle is drawn in xor-mode so this can be called to remove it
  399. *   as well as show it.
  400. *
  401. ************************************************************************/
  402.  
  403. VOID
  404. LfShowSelectRc(hps, lprc)
  405. HPS hps;
  406. PRECTL lprc;
  407. {
  408.     LINEBUNDLE lb;
  409.  
  410.  
  411.     lb.lColor     = CLR_TRUE;
  412.     lb.usMixMode = FM_XOR;
  413.     lb.usType     = LINETYPE_ALTERNATE;
  414.     GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR|LBB_MIX_MODE|LBB_TYPE,
  415.         0L, (PBUNDLE)&lb);
  416.     GpiSetCurrentPosition(hps, (POINTL *)&(lprc->xLeft));
  417.     GpiBox(hps, DRO_OUTLINE, (POINTL *)&(lprc->xRight), 0L, 0L);
  418. }
  419.  
  420.  
  421.  
  422.  
  423. /************************************************************************
  424. *
  425. *   LfChar
  426. *
  427. *   Handle LineFractal's keyboard interface.  This consists of:
  428. *
  429. *   <space>    Cancels the selection rectangle.
  430. *   0-9     Brings thread i to the top, if it exists.
  431. *
  432. ************************************************************************/
  433.  
  434. VOID
  435. LfChar(hwnd, ch)
  436. HWND hwnd;
  437. char ch;
  438. {
  439.     HPS hps;
  440.     PRECTL lprc;
  441.     USHORT i;
  442.  
  443.     if (ch == ' ')
  444.     {
  445.     if (global.fShowSelectRc)
  446.     {
  447.         global.fShowSelectRc = FALSE;
  448.         hps = WinGetPS(hwnd);
  449.         if (global.fTempSelect)
  450.         {
  451.         lprc = &global.rclSelect;
  452.         global.fTempSelect = FALSE;
  453.         }
  454.         else
  455.         lprc = &global.rclCutCopy;
  456.         LfShowSelectRc(hps, lprc);
  457.         WinReleasePS(hps);
  458.     }
  459.     }
  460.     else if (ch >= '0' && ch <= '9')
  461.     {
  462.     i = ch - '0';
  463.     if (i < global.cThr)
  464.         LfBringThreadToTop(global.aThr[i]);
  465.     }
  466. }
  467.  
  468.  
  469.  
  470.  
  471. /************************************************************************
  472. *
  473. *   LfMouseMove
  474. *
  475. *   Handle actions necessary upon each move of the mouse pointer.
  476. *   This consists of resetting the mouse pointer -- if we pass
  477. *   this on to WinDefWindowProc, it will reset it to the arrow.
  478. *   As long as we're setting the pointer so often, we can do a
  479. *   little animation.
  480. *
  481. ************************************************************************/
  482.  
  483. VOID
  484. LfMouseMove()
  485. {
  486.     /* Do this so that if in tracking mode, the correct pointer
  487.        shape appears immediately. */
  488.     if (global.fTracking || global.fSelecting)
  489.     {
  490.     if (global.hptrTrack)
  491.         WinSetPointer(HWND_DESKTOP,global.hptrTrack);
  492.     return;
  493.     }
  494.     if (global.fPasting)
  495.     {
  496.     if (global.hptrPaste)
  497.         WinSetPointer(HWND_DESKTOP,global.hptrPaste);
  498.     return;
  499.     }
  500.     if (global.pThrTop)
  501.     {
  502.      if (global.pThrTop->fBusy)
  503.      {
  504.         if (global.hptrWait)
  505.         WinSetPointer(HWND_DESKTOP,global.hptrWait);
  506.         return;
  507.      }
  508.     }
  509.     global.usPtrCounter = (global.usPtrCounter+1) % global.usPtrThreshold;
  510.     if (global.usPtrCounter == 0)
  511.     {
  512.     global.usCurPtr += global.usPtrIncr;
  513.     if (global.usCurPtr <= 0)
  514.         global.usCurPtr = 0;
  515.     else
  516.         global.usCurPtr %= NUM_PTR_SHAPES;
  517.     if ((global.usCurPtr == NUM_PTR_SHAPES - 1) ||
  518.         (global.usCurPtr == 0))
  519.         global.usPtrIncr *= -1;
  520.     }
  521.     if ((global.hptr)[global.usCurPtr])
  522.     WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  523. }
  524.  
  525.  
  526.  
  527.  
  528. /************************************************************************
  529. *
  530. *   LfButtonUp
  531. *
  532. *   Handle up clicks of the mouse buttons.  This consists of:
  533. *
  534. *   left button up    increase the depth of recursion
  535. *   right button up    decrease the depth of recursion
  536. *
  537. *            In both cases, clear the semaphore so the
  538. *            drawing can restart at the new level of
  539. *            recursion.
  540. *
  541. ************************************************************************/
  542.  
  543. VOID
  544. LfButtonUp(usMsg)
  545. USHORT usMsg;
  546. {
  547.     if (global.fMouseChangesRecursion)
  548.     {
  549.     if (usMsg == WM_BUTTON1UP)
  550.         global.pThrTop->usRecursion = ++global.pThrTop->usRecursion;
  551.     else if (global.pThrTop->usRecursion > 0)
  552.         global.pThrTop->usRecursion = --global.pThrTop->usRecursion;
  553.  
  554.     global.pThrTop->flMiscAttrs |= LFA_RECURSION;
  555.     global.pThrTop->fUpdateAttrs = TRUE;
  556.     global.fUpdateAttrs = TRUE;
  557.  
  558.     if (global.pThrTop->hps)
  559.     {
  560.         global.pThrTop->fInterrupted = TRUE;
  561.         DosSemClear(&(global.pThrTop)->lSemRedraw);
  562.     }
  563.     }
  564. }
  565.  
  566.  
  567.  
  568.  
  569. /************************************************************************
  570. *
  571. *   LfButtonDown
  572. *
  573. *   Handle down clicks of the mouse buttons.  This consists of
  574. *   changing the mouse pointer depending upon which mode we're in
  575. *   and calling off to the subroutine to do the real work given
  576. *   the position at which the mouse button was clicked.  The modes
  577. *   are "tracking", "selecting", and "pasting".  Tracking means the
  578. *   user is defining the new dimensions of the fractal.  Selecting
  579. *   means the user is dragging a rectangle to cut or copy.  Pasting
  580. *   means the user is positioning the cut or copied rectangle in
  581. *   the window.
  582. *
  583. ************************************************************************/
  584.  
  585. VOID
  586. LfButtonDown(hwnd, mp1)
  587. HWND hwnd;
  588. MPARAM mp1;
  589. {
  590.     POINTS pt;
  591.  
  592.     if (global.fTracking)
  593.     {
  594.     if (global.hptrTrack)
  595.         WinSetPointer(HWND_DESKTOP,global.hptrTrack);
  596.     pt.x = LOUSHORT(mp1);
  597.     pt.y = HIUSHORT(mp1);
  598.     LfSelectDimension(hwnd, pt);
  599.     global.fTracking = FALSE;
  600.     if ((global.hptr)[global.usCurPtr])
  601.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  602.     if (global.pThrTop->fAttrRedraw)
  603.     {
  604.         global.pThrTop->fInterrupted = TRUE;
  605.         DosSemClear(&(global.pThrTop)->lSemRedraw);
  606.     }
  607.     }
  608.     else if (global.fSelecting)
  609.     {
  610.     if (global.hptrTrack)
  611.         WinSetPointer(HWND_DESKTOP,global.hptrTrack);
  612.     pt.x = LOUSHORT(mp1);
  613.     pt.y = HIUSHORT(mp1);
  614.     LfSelect(hwnd, pt);
  615.     global.fSelecting = FALSE;
  616.     if ((global.hptr)[global.usCurPtr])
  617.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  618.     }
  619.     else if (global.fPasting)
  620.     {
  621.     if (global.hptrPaste)
  622.         WinSetPointer(HWND_DESKTOP,global.hptrPaste);
  623.     pt.x = LOUSHORT(mp1);
  624.     pt.y = HIUSHORT(mp1);
  625.     LfPaste(hwnd);
  626.     global.fPasting = FALSE;
  627.     if ((global.hptr)[global.usCurPtr])
  628.         WinSetPointer(HWND_DESKTOP,(global.hptr)[global.usCurPtr]);
  629.     }
  630. }
  631.  
  632.  
  633.  
  634.  
  635. /************************************************************************
  636. *
  637. *   LfStartRedrawTimer
  638. *
  639. ************************************************************************/
  640.  
  641. VOID
  642. LfStartRedrawTimer()
  643. {
  644.     USHORT timeout;
  645.  
  646.     if (!global.fTimerOn)
  647.     {
  648.     timeout = (USHORT) ((rand()/32767.0) *
  649.           (global.usMaxTimerDelay  - global.usMinTimerDelay) +
  650.            global.usMinTimerDelay);
  651.     WinStartTimer(global.hab, global.hwnd, IDT_AUTOSTARTREDRAW, timeout);
  652.     global.fTimerOn = TRUE;
  653.     }
  654. }
  655.  
  656.  
  657.  
  658.  
  659. /************************************************************************
  660. *
  661. *   LfStopRedrawTimer
  662. *
  663. ************************************************************************/
  664.  
  665. VOID
  666. LfStopRedrawTimer()
  667. {
  668.     WinStopTimer(global.hab, global.hwnd, IDT_AUTOSTARTREDRAW);
  669.     global.fTimerOn = FALSE;
  670. }
  671.