home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d500 / wiconify.lha / wIconify / wIconSetter.lzh / wIconCutter / Frame.c next >
C/C++ Source or Header  |  1991-04-19  |  21KB  |  730 lines

  1. /*
  2.  *  FRAME.C     A general-purpose bitmap creating library.  It allows you
  3.  *              to select a portion of any screen by dragging a selection 
  4.  *              rectangle, and returns a bitmap structure that contains
  5.  *              a copy of the selected region.
  6.  *
  7.  *  Copyright 1990 by Davide P. Cervone, all rights reserved.
  8.  *  You may use this code, provided this copyright notice is kept intact.
  9.  */
  10.  
  11. #define INTUITIONPRIVATE  TRUE
  12. #include <intuition/intuitionbase.h>
  13. #include <exec/interrupts.h>
  14. #include <exec/memory.h>
  15. #include <devices/input.h>
  16. #include <devices/inputevent.h>
  17. #include <libraries/dos.h>
  18.  
  19. #include "Frame.h"
  20.  
  21. struct LayersBase *LayersBase;
  22.  
  23. struct Screen *theScreen;        /* the selected screen */
  24. UBYTE PlaneMask = 0xFF;          /* which bitplanes to use */
  25. UBYTE theDepth;                  /* the depth of the bitmap */
  26. WORD theWidth, theHeight;        /* its width and height */
  27. ULONG theModes;                  /* a copy of the screen's modes */
  28. struct ColorMap *theColorMap;    /* a copy of the screen's color map */
  29. struct RastPort *theRastPort;    /* the screen's RastPort */
  30. struct BitMap theBitMap;         /* the copied bitmap */
  31. WORD StartX, StartY;             /* position within the screen */
  32. WORD CurrentX, CurrentY;         /* current mouse position */
  33. WORD LeftX, TopY;                /* corner of selection rectangle */
  34.  
  35.  
  36. extern struct MsgPort *CreatePort();
  37. extern struct IOStdReq *CreateStdIO();
  38. extern LONG AllocSignal(), Wait(), SetSignal();
  39. extern APTR FindTask();
  40. extern PLANEPTR AllocRaster();
  41. extern struct ColorMap *GetColorMap();
  42. extern APTR AllocMem();
  43.  
  44. extern void FrameHandlerStub();
  45.  
  46.  
  47. #define INTUITION_REV   0L
  48. #define LAYERS_REV      0L
  49. #define GRAPHICS_REV    0L
  50.  
  51. #define EXIT_OK         0L
  52. #define EXIT_ERROR      10L
  53.  
  54. #define STARTQUAL       (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  55.  
  56. #define NewX(i)         (Frame->XY[i*2])
  57. #define NewY(i)         (Frame->XY[i*2+1])
  58. #define OldX(i)         (Frame->NextBorder->XY[i*2])
  59. #define OldY(i)         (Frame->NextBorder->XY[i*2+1])
  60. #define SCREENX(x)      (((x) >> Xshift) - theScreen->LeftEdge)
  61. #define SCREENY(y)      (((y) >> Yshift) - theScreen->TopEdge)
  62. #define INTUIX(x)       ((x) << Xshift)
  63. #define INTUIY(y)       ((y) << Yshift)
  64. #define SCREENTOP\
  65.    (theScreen->TopEdge << ((theScreen->ViewPort.Modes & LACE)? 0: 1))
  66. #define CTRL_C(e)\
  67.    ((e)->ie_Code == 0x33 && ((e)->ie_Qualifier & IEQUALIFIER_CONTROL))
  68.  
  69. #define SIGBREAKF_ANY\
  70.    (SIGBREAKF_CTRL_C| SIGBREAKF_CTRL_D| SIGBREAKF_CTRL_E| SIGBREAKF_CTRL_F)
  71.  
  72. #define WIDTH           ((long)theWidth)
  73. #define HEIGHT          ((long)theHeight)
  74. #define DEPTH           ((long)theDepth)
  75. #define BLT_COPY        0x000000C0
  76. #define BLT_ALLPLANES   0x000000FF
  77.  
  78. struct MsgPort *InputPort = NULL;     /* Port used to talk to Input.Device */
  79. struct IOStdReq *InputBlock = NULL;   /* request block used with Input.Device */
  80. static short InputOpen = FALSE;       /* flag for when input.Device is open */
  81. static APTR theTask;                  /* pointer to our task */
  82. static LONG OkSignal;                 /* signal when movement detected */
  83. static LONG EndSignal;                /* signal when frame is done */
  84. static LONG OkMask;                   /* 1 << OkSignal */
  85. static LONG EndMask;                  /* 1 << EndSignal */
  86.  
  87. static short OkToSignal = TRUE;       /* TRUE if not using shared memory */
  88. static short MouseMoved = FALSE;      /* TRUE when mouse moves buffered */
  89. static short RemoveEvent;             /* should an input event be removed? */
  90. static short Xshift, Yshift;          /* HIRES and LACE adjustments */
  91. static WORD Xs,Ys, Xc, Yc;            /* starting and current X,Y */
  92. static WORD Hmin,Hmax, Wmin, Wmax;    /* min and max movement values */
  93.  
  94. static SHORT NewBox[5][2];            /* current select frame */
  95. static SHORT OldBox[5][2];            /* previous select frame */
  96.  
  97. struct Border NewFrame = {0,0, 0x01,0, COMPLEMENT, 5, &NewBox[0][0], NULL};
  98. struct Border OldFrame = {0,0, 0x01,0, COMPLEMENT, 5, &OldBox[0][0], &NewFrame};
  99. struct Border *Frame = &OldFrame;
  100.  
  101. static struct Interrupt HandlerData =  /* used to add an input handler */
  102. {
  103.    {NULL, NULL, 0, 52, NULL},           /* Node structure (nl_Pri = 52) */
  104.    NULL,                                /* data pointer */
  105.    &FrameHandlerStub                    /* code pointer */
  106. };
  107.  
  108.  
  109. /*
  110.  *  GetMinMax()
  111.  *
  112.  *  If a screen is selected,
  113.  *    Get the min and max values from the screen
  114.  *  Otherwise get them from Intuition itself
  115.  */
  116.  
  117. static void GetMinMax()
  118. {
  119.    if (theScreen)
  120.    {
  121.       Hmin = INTUIY(theScreen->TopEdge);
  122.       Hmax = INTUIY(theScreen->Height + theScreen->TopEdge - 1);
  123.       if (Hmax > IntuitionBase->MaxYMouse) Hmax = IntuitionBase->MaxYMouse;
  124.       Wmin = INTUIX(theScreen->LeftEdge);
  125.       Wmax = INTUIX(theScreen->Width + theScreen->LeftEdge - 1);
  126.       if (Wmax > IntuitionBase->MaxXMouse) Wmax = IntuitionBase->MaxXMouse;
  127.    } else {
  128.       Hmin = IntuitionBase->MinYMouse;
  129.       Hmax = IntuitionBase->MaxYMouse;
  130.       Wmin = IntuitionBase->MinXMouse;
  131.       Wmax = IntuitionBase->MaxXMouse;
  132.    }
  133. }
  134.  
  135.  
  136. /*
  137.  *  DoSelectDown()
  138.  *
  139.  *  Remove the event.
  140.  *  Starting at the first screen find the first one higher than the mouse
  141.  *  If none, choose the active screen, otherwise bring the screen to the front.
  142.  *  Get the shift values from the screen's modes, and save the current X,Y
  143.  */
  144.  
  145. static void DoSelectDown()
  146. {
  147.    RemoveEvent = TRUE;
  148.    theScreen = IntuitionBase->FirstScreen;
  149.    while (theScreen && IntuitionBase->MouseY < SCREENTOP)
  150.       theScreen = theScreen->NextScreen;
  151.    if (theScreen == NULL)
  152.       theScreen = IntuitionBase->ActiveScreen;
  153.      else
  154.       ScreenToFront(theScreen);
  155.    Xshift = (theScreen->ViewPort.Modes & HIRES)? 0: 1;
  156.    Yshift = (theScreen->ViewPort.Modes & LACE)? 0: 1;
  157.    Xs = Xc;
  158.    Ys = Yc;
  159. }
  160.  
  161.  
  162. /*
  163.  *  DoMouseMove()
  164.  *
  165.  *  Get the mouse's movement and clip it to the movement rectangle.
  166.  *  If right button is presseed and the select rectangle is started,
  167.  *    Adjust the mouse movement, if necessary
  168.  *    Move the starting position by this amount (ie, move the frame)
  169.  *  If there was some movement,
  170.  *    Don't remove the event,
  171.  *    Pass on the modified mouse movements
  172.  *    Adjust the mouse's current position
  173.  *    If the select rectangle is already started, indicate that it has changed.
  174.  */
  175.  
  176. static void DoMouseMove(theEvent)
  177. struct InputEvent *theEvent;
  178. {
  179.    register WORD dx,dy;
  180.  
  181.    dx = theEvent->ie_X;
  182.    dy = theEvent->ie_Y;
  183.    if (dx < Wmin - Xc) dx = Wmin - Xc;
  184.    if (dy < Hmin - Yc) dy = Hmin - Yc;
  185.    if (dx > Wmax - Xc) dx = Wmax - Xc;
  186.    if (dy > Hmax - Yc) dy = Hmax - Yc;
  187.    if ((theEvent->ie_Qualifier & IEQUALIFIER_RBUTTON) && theScreen)
  188.    {
  189.       if (dx < Wmin - Xs) dx = Wmin - Xs;
  190.       if (dy < Hmin - Ys) dy = Hmin - Ys;
  191.       if (dx > Wmax - Xs) dx = Wmax - Xs;
  192.       if (dy > Hmax - Ys) dy = Hmax - Ys;
  193.       Xs += dx; Ys += dy;
  194.    }
  195.    if (dx != 0 || dy != 0)
  196.    {
  197.       RemoveEvent = FALSE;
  198.       theEvent->ie_X = dx;
  199.       theEvent->ie_Y = dy;
  200.       Xc += dx;
  201.       Yc += dy;
  202.       if (theScreen) MouseMoved = TRUE;
  203.    }
  204. }
  205.  
  206.  
  207. /*
  208.  *  SignalMove()
  209.  *
  210.  *  Mark that the shared memory is in use
  211.  *  Save the start and current X,Y in the shared memory
  212.  *  Signal the main task to draw the select rectangle
  213.  *
  214.  *  (This stuff should all be replaced by message passing - I wrote this
  215.  *   a long time ago before I had much experience)
  216.  */
  217.  
  218. static void SignalMove()
  219. {
  220.    OkToSignal = FALSE;
  221.    MouseMoved = FALSE;
  222.    StartX   = SCREENX(Xs);
  223.    StartY   = SCREENY(Ys);
  224.    CurrentX = SCREENX(Xc); 
  225.    CurrentY = SCREENY(Yc);
  226.    Signal(theTask,OkMask);
  227. }
  228.  
  229.  
  230. /*
  231.  *  FrameHandler()
  232.  *
  233.  *  Get the current mouse position, and get the mouse movement rectangle.
  234.  *  While there are more events to look at,
  235.  *    Keep the event unless we say otherwise,
  236.  *    Check the type of event:
  237.  *      RAWMOUSE:
  238.  *        Remove the event if the select box is up
  239.  *        Check the button type:
  240.  *          SELECTDOWN:
  241.  *            If the select box is not already going, and the right qualifiers
  242.  *              are present, then start the box
  243.  *          SELECTUP:
  244.  *            If the select box is going, signal that it's done
  245.  *          MENU:
  246.  *            Ignore these
  247.  *          Anything else (i.e., MOUSEMOVE):
  248.  *            Do a mouse move
  249.  *      RAWKEY:
  250.  *        If it is a CTRL-C, signal the task to stop.
  251.  *    If we are removing the event, do so, otherwise go on to the next one.
  252.  *  If mouse moves took placem and the memory is not in use, signal the move.
  253.  *  Return the (modified) event list.
  254.  */
  255.  
  256. struct InputEvent *FrameHandler(EventList,data)
  257. struct InputEvent *EventList;
  258. APTR data;
  259. {
  260.    register struct InputEvent **EventPtr = &EventList;
  261.    register struct InputEvent *theEvent;
  262.  
  263.    Xc = IntuitionBase->MouseX;
  264.    Yc = IntuitionBase->MouseY;
  265.    GetMinMax();
  266.  
  267.    Forbid();
  268.    while ((theEvent = *EventPtr) != NULL)
  269.    {
  270.       RemoveEvent = FALSE;
  271.       switch(theEvent->ie_Class)
  272.       {
  273.          case IECLASS_RAWMOUSE:
  274.             RemoveEvent = (theScreen != NULL);
  275.             switch(theEvent->ie_Code)
  276.             {
  277.                case SELECTDOWN:
  278.                   if (theScreen == NULL &&
  279.                      (theEvent->ie_Qualifier & STARTQUAL))
  280.                         DoSelectDown();
  281.                   break;
  282.  
  283.                case SELECTUP:
  284.                   if (theScreen) Signal(theTask,EndMask);
  285.                   break;
  286.  
  287.                case MENUDOWN:
  288.                case MENUUP:
  289.                   break;
  290.  
  291.                default:
  292.                   DoMouseMove(theEvent);
  293.                   break;
  294.             }
  295.             break;
  296.  
  297.          case IECLASS_RAWKEY:
  298.             if (CTRL_C(theEvent)) Signal(theTask,SIGBREAKF_CTRL_C);
  299.             break;
  300.       }
  301.       if (RemoveEvent)
  302.          *EventPtr = theEvent->ie_NextEvent;
  303.         else
  304.          EventPtr = &(theEvent->ie_NextEvent);
  305.    }
  306.    Permit();
  307.    if (OkToSignal && MouseMoved) SignalMove();
  308.    return(EventList);
  309. }
  310.  
  311.  
  312. /*
  313.  *  Ctrl_C()
  314.  *
  315.  *  Dummy routine to disable Lattice-C CTRL-C trapping.
  316.  */
  317.  
  318. #ifndef MANX
  319. static int Ctrl_C()
  320. {
  321.    return(0);
  322. }
  323. #endif
  324.  
  325.  
  326. /*
  327.  *  DoExit()
  328.  *
  329.  *  General purpose exit routine.  If 's' is not NULL, then print an
  330.  *  error message with up to three parameters.  Free any memory, close
  331.  *  any open files, delete any ports, free any used signals, etc.
  332.  */
  333.  
  334. void DoExit(s,x1,x2,x3)
  335. char *s, *x1, *x2, *x3;
  336. {
  337.    long status = EXIT_OK;
  338.    short i;
  339.    extern void DoUseExit();
  340.    
  341.    if (theRastPort) UnlockLayers(&theScreen->LayerInfo);
  342.    if (s != NULL)
  343.    {
  344.       printf(s,x1,x2,x3);
  345.       printf("\n");
  346.       status = EXIT_ERROR;
  347.    }
  348.    DoUseExit();
  349.    for (i=0; i<theDepth; i++)
  350.    {
  351.       if (theBitMap.Planes[i])
  352.          FreeRaster(theBitMap.Planes[i],theWidth,theHeight);
  353.    }
  354.    if (InputOpen)     CloseDevice(InputBlock);
  355.    if (InputBlock)    DeleteStdIO(InputBlock);
  356.    if (InputPort)     DeletePort(InputPort);
  357.    if (theColorMap)   FreeColorMap(theColorMap);
  358.    if (OkSignal)      FreeSignal(OkSignal);
  359.    if (EndSignal)     FreeSignal(EndSignal);
  360.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  361.    if (LayersBase)    CloseLibrary(LayersBase);
  362.    if (GfxBase)       CloseLibrary(GfxBase);
  363.    exit(status);
  364. }
  365.  
  366.  
  367. /*
  368.  *  New()
  369.  *
  370.  *  Get a chunk of memory and check that it has been allocated OK.
  371.  *  If not, exit with an error message.
  372.  */
  373.  
  374. APTR New(name,size)
  375. char *name;
  376. int size;
  377. {
  378.    APTR ptr;
  379.    
  380.    if ((ptr = AllocMem(size,MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
  381.       DoExit("Can't Allocate Memory for %s",name);
  382.    return(ptr);
  383. }
  384.  
  385.  
  386. /*
  387.  *  CheckLibOpen()
  388.  *
  389.  *  General library open routine.  It opens a library and sets a pointer
  390.  *  to it.  It checks that the library was openned successfully.
  391.  */
  392.  
  393. void CheckLibOpen(lib,name,rev)
  394. APTR *lib;
  395. char *name;
  396. int rev;
  397. {
  398.    extern APTR OpenLibrary();
  399.  
  400.    if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
  401.       DoExit("Can't open %s",name);
  402. }
  403.  
  404.  
  405. /*
  406.  *  GetSignal()
  407.  *
  408.  *  Allocate a signal (error if none available) and set the mask to
  409.  *  the proper value.
  410.  */
  411.  
  412. static void GetSignal(theSignal,theMask)
  413. LONG *theSignal, *theMask;
  414. {
  415.    LONG signal;
  416.  
  417.    if ((signal = AllocSignal(-ONE)) == -ONE) DoExit("Can't Get Signal");
  418.    *theSignal = signal;
  419.    *theMask = (ONE << signal);
  420. }
  421.  
  422.  
  423. /*
  424.  *  SetupTask()
  425.  *
  426.  *  Find the task pointer for the main task (so the input handler can 
  427.  *  signal it).  Clear the CTRL signal flags (so we don't get any left
  428.  *  over from before JOURNAL was run) and allocate some signals for 
  429.  *  new events and errors (so the input handler can signal them).
  430.  */
  431.  
  432. static void SetupTask()
  433. {
  434.    theTask = FindTask(NULL);
  435.    SetSignal(0L,SIGBREAKF_ANY);
  436.    GetSignal(&OkSignal,&OkMask);
  437.    GetSignal(&EndSignal,&EndMask);
  438.    #ifndef MANX
  439.       onbreak(&Ctrl_C);
  440.    #endif
  441. }
  442.  
  443.  
  444. /*
  445.  *  TellInputDevice()
  446.  *
  447.  *  Create a port and a standard IO block for talking to the input device.
  448.  *  Open the input device and tell it to add or remove the input handler.
  449.  *  The handler is at priority 51, so it will be ahead of Intuition.
  450.  *  Once the handler is added or removed, close the device and delete the
  451.  *  request block and port.
  452.  */
  453.  
  454. static void TellInputDevice(function)
  455. long function;
  456. {
  457.    long status;
  458.  
  459.    if ((InputPort = CreatePort(0,0)) == NULL)
  460.       DoExit("Can't Create Port for Input Device");
  461.    if ((InputBlock = CreateStdIO(InputPort)) == NULL)
  462.       DoExit("Can't Create IO Block for Input Device");
  463.    if (OpenDevice("input.device",0,InputBlock,0) != 0)
  464.       DoExit("Can't Open Input Device");
  465.    InputOpen = TRUE;
  466.    
  467.    InputBlock->io_Command = function;
  468.    InputBlock->io_Data    = (APTR) &HandlerData;
  469.    if (status = DoIO(InputBlock)) DoExit("Error from DoIO:  %ld",status);
  470.    
  471.    CloseDevice(InputBlock); InputOpen  = FALSE;
  472.    DeleteStdIO(InputBlock); InputBlock = NULL;
  473.    DeletePort(InputPort);   InputPort  = NULL;
  474. }
  475.  
  476.  
  477. /*
  478.  *  DrawFrame()
  479.  *
  480.  *  Set the corners of the border to their new positions.
  481.  *  If the select frame has been moved,
  482.  *    Get the old X,Y and calculate the new X,Y for the intermediate
  483.  *      part of the border (the border is not square so as to avoid
  484.  *      unnecessary flickering when it is sized)
  485.  *    Update the intermediate border positions
  486.  *  Otherwise
  487.  *    Update the intermediate positions
  488.  &  Draw the borders
  489.  *  Switch which one is the current one, and link them properly
  490.  */
  491.  
  492. static void DrawFrame()
  493. {
  494.    WORD Xo,Yo, Xn,Yn;
  495.  
  496.    NewX(3) = NewX(4) = StartX;  NewX(1) = NewX(2) = CurrentX;
  497.    NewY(0) = NewY(1) = StartY;  NewY(2) = NewY(3) = CurrentY;
  498.    if (StartX == OldX(4) && StartY == OldY(0))
  499.    {
  500.       Xo = OldX(2); Yo = OldY(2);
  501.       if ((CurrentX > StartX && StartX >= Xo) ||
  502.           (CurrentX < StartX && StartX <= Xo))
  503.       {
  504.          Xn = StartX;
  505.       } else {
  506.          if ((CurrentX > Xo && Xo > StartX) ||
  507.              (CurrentX < Xo && Xo < StartX))
  508.             Xn = Xo;
  509.            else
  510.             Xn = CurrentX;
  511.       }
  512.       if ((CurrentY > StartY && StartY >= Yo) ||
  513.           (CurrentY < StartY && StartY <= Yo))
  514.       {
  515.          Yn = StartY;
  516.       } else {
  517.          if ((CurrentY > Yo && Yo > StartY) ||
  518.              (CurrentY < Yo && Yo < StartY))
  519.             Yn = Yo;
  520.            else
  521.             Yn = CurrentY;
  522.       }
  523.       OldX(0) = NewX(0) = Xn;
  524.       OldY(4) = NewY(4) = Yn;
  525.    } else {
  526.       OldX(0) = OldX(4); OldY(4) = OldY(0);
  527.       NewX(0) = StartX;  NewY(4) = StartY;
  528.    }
  529.    DrawBorder(theRastPort,Frame,0L,0L);
  530.    Frame->NextBorder->NextBorder = Frame;
  531.    Frame = Frame->NextBorder;
  532.    Frame->NextBorder->NextBorder = NULL;
  533. }
  534.  
  535.  
  536. /*
  537.  *  CopyFrame()
  538.  *
  539.  *  Get the mask for the planes actually needed
  540.  *  Count the number of planes involved
  541.  *  If none, give an error
  542.  *  Get the widthm height, and upper-left-hand corner of the rectangle.
  543.  *  Get a color map of the required depth and copy the screen's
  544.  *    color map into it, skipping unneeded colors
  545.  *  Get the screen's modes
  546.  *  Initialize the BitMap, and a temporary one (to be used for blitting)
  547.  *  For each plane selected
  548.  *    Allocate a raster area for it (error if it not possible)
  549.  *    Use it as the bitplane for both the TempBitMap and the BitMap
  550.  *      (BitMap has them sequentially, TempBitMap has them in the positions
  551.  *       corresponding to their positions in the screen bitmap)
  552.  *    Clear the last two bytes of each bitplane (to make sure they are 0)
  553.  *  Copy the screen data to the TempBitMap (and hence the to BitMap, since
  554.  *    they share bitplanes)
  555.  */
  556.  
  557. void CopyFrame()
  558. {
  559.    short i,j,b;
  560.    UWORD *OldC,*NewC;
  561.    PLANEPTR thePlane;
  562.    UBYTE TempMask, NotPlaneMask;
  563.    struct BitMap TempBitMap;
  564.    long TempDepth = theScreen->BitMap.Depth;
  565.  
  566.    PlaneMask &= (1 << TempDepth) - 1;
  567.    NotPlaneMask = ~PlaneMask;
  568.    for (TempMask = PlaneMask, theDepth = 0; TempMask; TempMask >>= 1)
  569.       theDepth += (TempMask & 1);
  570.    if (theDepth == 0) DoExit("No Bit Planes Selected By Mask");
  571.  
  572.    if (CurrentX > StartX)
  573.    {
  574.       theWidth = CurrentX - StartX + 1;
  575.       LeftX = StartX;
  576.    } else {
  577.       theWidth = StartX - CurrentX + 1;
  578.       LeftX = CurrentX;
  579.    }
  580.    if (CurrentY > StartY)
  581.    {
  582.       theHeight = CurrentY - StartY + 1;
  583.       TopY = StartY;
  584.    } else {
  585.       theHeight = StartY - CurrentY + 1;
  586.       TopY = CurrentY;
  587.    }
  588.  
  589.    theColorMap = GetColorMap((long)(1 << theDepth));
  590.    if (theColorMap == 0) DoExit("Can't Get Color Map");
  591.    OldC = (UWORD *)(theScreen->ViewPort.ColorMap->ColorTable);
  592.    NewC = (UWORD *)(theColorMap->ColorTable);
  593.    for (i=0; i<theScreen->ViewPort.ColorMap->Count; i++, OldC++)
  594.       if ((i & NotPlaneMask) == 0) *NewC++ = *OldC;
  595.  
  596.    theModes = theScreen->ViewPort.Modes;
  597.  
  598.    InitBitMap(&theBitMap,DEPTH,WIDTH,HEIGHT);
  599.    InitBitMap(&TempBitMap,TempDepth,WIDTH,HEIGHT);
  600.    for (TempMask=PlaneMask, i=j=0; TempMask; TempMask >>= 1,j++)
  601.    {
  602.       if (TempMask & 1)
  603.       {
  604.          thePlane = AllocRaster(WIDTH,HEIGHT);
  605.          if (thePlane == NULL) DoExit("Can't Get BitPlane %d",i);
  606.          TempBitMap.Planes[j] = theBitMap.Planes[i++] = thePlane;
  607.          for (b=RASSIZE(theWidth,theHeight)-1; b>0; b -= theBitMap.BytesPerRow)
  608.             thePlane[b] = thePlane[b-1] = 0;
  609.       }
  610.    }
  611.    BltBitMap(&theScreen->BitMap,(long)LeftX,(long)TopY,&TempBitMap,0L,0L,
  612.       WIDTH,HEIGHT,BLT_COPY,(long)PlaneMask,NULL);
  613. }
  614.  
  615.  
  616. /*
  617.  *  TrackFrame()
  618.  *
  619.  *  Setup the task, and get the signal mask
  620.  *  Add the input handler and give the installation message
  621.  *  Tell the user how to get the select rectangle
  622.  *  While there is more to do,
  623.  *    Wait for something to happen
  624.  *    If we have gotten a new mouse position,
  625.  *      If the screen is already chosen,
  626.  *        Update and draw the new frame
  627.  *      Otherwise,
  628.  *        Get the rastport of the selected screen,
  629.  *        Lock its layers so nothing happens while we're selecting
  630.  *        Initialize the frames and draw them on the screen
  631.  *      Indicate that we are done with the shared memory.
  632.  *    If some other signal is present,
  633.  *      End the loop
  634.  *      Check if the loop was cancelled by the user
  635.  *      If the select box was drawn,
  636.  *        Finish the frame and remove it
  637.  *        If not cancelled, get a copy of the frame
  638.  *        Unlock the screen layers so things can happen again
  639.  *        Forget the rastport
  640.  *  Remove the handler
  641.  *  return the status
  642.  */
  643.  
  644. static int TrackFrame()
  645. {
  646.    LONG signals;
  647.    LONG SigMask;
  648.    short NotDone = TRUE;
  649.    int NotCancelled = TRUE;
  650.    
  651.    SetupTask();
  652.    SigMask = OkMask | EndMask | SIGBREAKF_CTRL_C;
  653.  
  654.    TellInputDevice(IND_ADDHANDLER);
  655.    printf("%s %s Installed\n",program,version);
  656.    printf("Drag a selection rectangle while holding the SHIFT key.  To change\n");
  657.    printf("the position of the box, press the right mouse button while dragging.\n");
  658.    printf("Press CTRL-C to cancel at any time.\n");
  659.    while (NotDone)
  660.    {
  661.       signals = Wait(SigMask);
  662.       if (signals & OkMask)
  663.       {
  664.          if (theRastPort)
  665.          {
  666.             DrawFrame();
  667.          } else {
  668.             theRastPort = &theScreen->RastPort; 
  669.             LockLayers(&theScreen->LayerInfo);
  670.             OldX(0) = OldX(3) = OldX(4) = StartX; OldX(1) = OldX(2) = CurrentX;
  671.             OldY(0) = OldY(1) = OldY(4) = StartY; OldY(2) = OldY(3) = CurrentY;
  672.             DrawBorder(theRastPort,Frame->NextBorder,0L,0L);
  673.          }
  674.          OkToSignal = TRUE;
  675.       }
  676.       if (signals & ~OkMask)
  677.       {
  678.          NotDone = FALSE;
  679.          NotCancelled = ((signals & SIGBREAKF_CTRL_C) == 0);
  680.          if (theRastPort)
  681.          {
  682.             OldX(0) = OldX(4);
  683.             OldY(4) = OldY(0);
  684.             DrawBorder(theRastPort,Frame->NextBorder,0L,0L);
  685.             if (NotCancelled) CopyFrame();
  686.             UnlockLayers(&theScreen->LayerInfo);
  687.             theRastPort = NULL;
  688.          }
  689.       }
  690.    }
  691.    TellInputDevice(IND_REMHANDLER);
  692.    return(NotCancelled);
  693. }
  694.  
  695.  
  696. /*
  697.  *  main()
  698.  *
  699.  *  Parse the command-line arguments and perform the proper function
  700.  *  (either show the usage, exit, or get a section of bitmap and use it).
  701.  */
  702.  
  703. void main(argc,argv)
  704. int argc;
  705. char **argv;
  706. {
  707.    int function;
  708.    extern int ParseArguments();
  709.    extern void UseFrame();
  710.  
  711.    function = ParseArguments(argc,argv);
  712.    switch(function)
  713.    {
  714.       case SHOW_USAGE:
  715.          printf("Usage:  %s\n",usage);
  716.          break;
  717.  
  718.       case JUST_EXIT:
  719.          break;
  720.  
  721.       default:
  722.          CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  723.          CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
  724.          CheckLibOpen(&GfxBase,"graphics.library",GRAPHICS_REV);
  725.          if (TrackFrame()) UseFrame(function);
  726.          break;
  727.    }
  728.    DoExit(NULL);
  729. }
  730.