/* Auto: make */ IMPORT struct SnapRsrc *SnapRsrc; IMPORT struct Image DiskImage; IMPORT struct Gadget DiskGad; IMPORT struct Gadget VProp, HProp; IMPORT struct PropInfo VInfo, HInfo; IMPORT struct Image VImage, HImage; IMPORT struct NewWindow Nw; IMPORT UBYTE *WindowTitle; #define MINWIDTH (24 + SnapRsrc->GadOffset + 16) #define MINHEIGHT 15 LONG xl; /* leftmost x position */ LONG xr; /* rightmost x position */ LONG yt; /* topmost y position */ LONG yb; /* bottommost y position */ LONG mx, my; /* Mouse position in pixels */ #define GfxFrame 4L IMPORT Point OldFrame[]; IMPORT Point NewFrame[]; IMPORT LONG OFType; /* Old frame type: ShortFrame/LongFrame */ IMPORT UWORD Ptrn; IMPORT WORD Pattern[]; IMPORT struct RastPort MyRP; IMPORT struct BitMap MyBM; IMPORT struct Screen *theScreen; struct Layer_Info *LockedLayerInfo; IMPORT struct RastPort rp; IMPORT LONGBITS cancelsignal, donesignal, movesignal, clicksignal, timersignal; IMPORT WORD action; LONG TitleBarHeight; LONG ContentsFontHeight; VOID FixHeights() { struct Screen WBScreen; if (GetScreenData((char *)&WBScreen, (LONG)sizeof(struct Screen), WBENCHSCREEN, NULL)) { /* Now this is a good practice */ TitleBarHeight = WBScreen.RastPort.TxHeight+2; ContentsFontHeight = WBScreen.Font->ta_YSize; } else { /* Sorry, but I don't realise how this could fail. Well, if we're snapping on another screen and WB is closed and it can't be opened by GetScreenData()... Anyway, IF this should happen -- Use Topaz 8 */ TitleBarHeight = 10; ContentsFontHeight = 8; } } /* SnapGfx is the actual graphics snapper. ** It steals the bitmap data from the given rastport ** and puts it in a separate bitmap. ** It also prepares the NewWindow structure according ** to the snapped bitmap. ** The coordinates are assumed to be valid. */ struct GfxSnap *SnapGfx(rp) struct RastPort *rp; { struct GfxSnap *GS; LONG i; GS = Create(GfxSnap); if (!GS) { return NULL; } GS->x = xl; GS->y = yt; GS->width = xr - xl + 1; GS->height = yb - yt + 1; GS->depth = rp->BitMap->Depth; GS->viewmode = theScreen->ViewPort.Modes; GS->pagew = theScreen->Width; GS->pageh = theScreen->Height; i = (GS->viewmode & HAM ? 16 : 1L << GS->depth); /* Copy the color map in case we should need it later */ while (i--) { ULONG col = GetRGB4(theScreen->ViewPort.ColorMap, i); GS->rgb[i][0] = ((col >> 8) & 0x0f) << 4; GS->rgb[i][1] = ((col >> 4) & 0x0f) << 4; GS->rgb[i][2] = ((col >> 0) & 0x0f) << 4; } /* Set up a nice bitmap */ InitBitMap(&GS->BM, GS->depth, GS->width, GS->height); /* Get a handle on the bitmap */ InitRastPort(&MyRP); MyRP.BitMap = &GS->BM; if (!AllocPlanes(&GS->BM, GS->width, GS->height)) { FreePlanes(&GS->BM, GS->width, GS->height); Kill(GS); return NULL; } /* Copy the selected part of the screen */ ClipBlit(rp, xl, yt, &MyRP, 0L, 0L, GS->width, GS->height, 0xC0L); Nw.LeftEdge = xl; Nw.TopEdge = yt; Nw.Width = GS->width + 18; /* Two pixels on each side */ Nw.Height = GS->height + TitleBarHeight + 9; /* Bar & scroll bar */ Nw.Title = WindowTitle; Nw.MaxWidth = Nw.Width; Nw.MaxHeight = Nw.Height; CopyMem((char *)&DiskGad, (char *)&GS->DiskGad, (LONG)sizeof(DiskGad) + sizeof(VProp) + sizeof(HProp) + sizeof(VInfo) + sizeof(HInfo) + sizeof(VImage) + sizeof(HImage)); GS->DiskGad.NextGadget = &GS->VProp; GS->DiskGad.LeftEdge = -(SnapRsrc->GadOffset+16); GS->DiskGad.Height = TitleBarHeight - 2; DiskImage.Height = TitleBarHeight; GS->VProp.NextGadget = &GS->HProp; GS->VProp.TopEdge = TitleBarHeight; GS->VProp.Height = -8 - TitleBarHeight; GS->VProp.GadgetRender = (APTR)&GS->VImage; GS->VProp.SpecialInfo = (APTR)&GS->VInfo; GS->HProp.NextGadget = NULL; GS->HProp.GadgetRender = (APTR)&GS->HImage; GS->HProp.SpecialInfo = (APTR)&GS->HInfo; return GS; } VOID ExtendGfx() { /* Fix which row we're talking about */ if (my-yt < yb-my) { /* Find closest row */ yt = my; /* change top row */ } else { yb = my; /* change bottom row */ } if (mx-xl < xr-mx) { xl = mx; } else { xr = mx; } } VOID gfx_frame() { NewFrame[0].x = xl; NewFrame[0].y = yt; NewFrame[1].x = xr; NewFrame[1].y = yt; NewFrame[2].x = xr; NewFrame[2].y = yb; NewFrame[3].x = xl; NewFrame[3].y = yb; NewFrame[4].x = xl; NewFrame[4].y = yt; draw_frame(GfxFrame); } WORD HandleGfx() { theScreen = WhichScreen(); /* Find out where we are */ if (!theScreen) { /* Don't know? Forget it. */ action = noaction; return 0; } /* Lock everything - find out what happens */ LockedLayerInfo = &theScreen->LayerInfo; LockLayers(LockedLayerInfo); /* Get a copy. Don't mess with somebody else's RP. */ CopyMem((char *)&theScreen->RastPort, (char *)&rp, (long)sizeof(struct RastPort)); SetDrMd(&rp, COMPLEMENT); xl = theScreen->MouseX + theScreen->ViewPort.RasInfo->RxOffset; if (xl < 0) { xl = 0; } if (xl >= theScreen->Width) { /* Check those corners. Check those corners. */ xl = theScreen->Width - 1; } yt = theScreen->MouseY + theScreen->ViewPort.RasInfo->RyOffset; if (yt < 0) { yt = 0; } if (yt >= theScreen->Height) { yt = theScreen->Height - 1; } xr = xl; yb = yt; Ptrn = (SnapRsrc->CrawlPtrn ? SnapRsrc->CrawlPtrn : Pattern[UNIT_FRAME]); OFType = 0L; gfx_frame(); FOREVER { REGISTER LONGBITS sig = Wait(movesignal|clicksignal|cancelsignal|donesignal|timersignal); if ((sig & timersignal) && (SnapRsrc->CrawlPtrn != 0xffff)) { crawl_frame(1L); } if (sig & movesignal || sig & clicksignal) { mx = theScreen->MouseX + theScreen->ViewPort.RasInfo->RxOffset; if (mx < 0) { mx = 0; } if (mx>=theScreen->Width) { mx = theScreen->Width - 1; } my = theScreen->MouseY + theScreen->ViewPort.RasInfo->RyOffset; if (my < 0) { my = 0; } if (my>=theScreen->Height) { my = theScreen->Height - 1; } ExtendGfx(); gfx_frame(); } if (sig & cancelsignal) { /* Cancelled? */ erase_frame(); UnlockLayers(LockedLayerInfo); return 0; } if (sig & donesignal) { /* Finished. Copy gfx. */ struct GfxSnap *GS; erase_frame(); if (xr < xl + MINWIDTH) { /* Can't have too small windows */ xr = xl + MINWIDTH; } if (xr >= theScreen->Width) { xl -= xr - theScreen->Width - 1; xr = theScreen->Width - 1; } if (yb < yt + MINHEIGHT) { yb = yt + MINHEIGHT; } if (yb >= theScreen->Height) { yt -= yb - theScreen->Height - 1; yb = theScreen->Height - 1; } FixHeights(); GS = SnapGfx(&rp); /* Snap! */ UnlockLayers(LockedLayerInfo); if (GS) { if (GS->window = opensharedwindow(&Nw)) { GS->window->UserData = (BYTE *)GS; /* Put gfx in our new window */ (VOID)AddGList(GS->window, &GS->DiskGad, 0L, 3L, NULL); RefreshGList(&GS->DiskGad, GS->window, NULL, 3L); AdjustSize(GS); } else { FreePlanes(&GS->BM, GS->width, GS->height); Kill(GS); } } else { /* Good question */ } action = noaction; return 0; } } }