Path: utzoo!attcan!uunet!husc6!purdue!i.cc.purdue.edu!j.cc.purdue.edu!ain
From: ain@j.cc.purdue.edu (Patrick White)
Newsgroups: comp.sources.amiga
Subject: vscreen (sources 2 of 2)
Keywords: virtuial, screen, superbitmap, uncompiled
Message-ID: <7278@j.cc.purdue.edu>
Date: 23 Jun 88 23:00:23 GMT
Organization: PUCC Land, USA
Lines: 1478
Approved: ain@j.cc.purdue.edu	(Patrick White)

Submitted by:	dpvc@tut.cc.rochester.edu  (David P. Cervone)
Summary:	Make virtual screens lager than will fit on monitor.
Poster Boy:	Patrick White	(ain@j.cc.purdue.edu)
Archive Name:	sources/amiga/volume5/vscreen.s.sh.2of2.Z
tested but not compiled.
 
NOTES:
   The source is for Lattice -- I didn't even try compiling it.
   It is a bit messy when resizing in that it dosen't seem to send window
resize messages when you change the size of a window, or when you exit vscreen,
but it works otherwise.. I feel it might be useful despite these bugs so I'm
posting it anyway.
.
 
 
-- Pat White   (co-moderator comp.sources/binaries.amiga)
ARPA/UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM  PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906
 
========================================
 
#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	vScreen.c
#	vScreenSetup.c
#	wList.c
#	wMax.c
#	wMove.c
#	wSize.c
# This archive created: Wed Jun 22 11:35:24 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting vScreen.c '(14176 characters)'
cat << \SHAR_EOF > vScreen.c
/*
 *  VSCREEN.C       Creates virtual screens that can be larger than
 *                  the actual display area of your monitor.  The virtual
 *                  screen scrolls when the mouse moves off the edge of
 *                  the display.
 *
 *                  Copyright 1988 by Davide P. Cervone, all rights reserved.
 *
 *                  You may may distibute this code as is, for non-commercial
 *                  purposes, provided that this notice remains intact and the
 *                  documentation file is distributed with it.
 *
 *                  You may not modify this code or incorporate it into your
 *                  own programs without the permission of the author.
 */

/*
 *  WARNING:  This code uses and even modifies the INTUITIONPRIVATE
 *  area of the IntuitionBase structure.  Use it at your own risk.  It is
 *  likely to break under a future release of Intuition.
 */

#include "vScreen.h"

static char *program = "vScreen";           /* the program name */
static char *author  = COPYRIGHT;           /* the copyright notice */
#define LOADVERS        1                   /* this program's version */

static char *handler = "L:vScreen-Handler"; /* the name of the handler */
#define HANDLER         &(handler[2])       /* same but in the current dir */


extern struct LayersBase *LayersBase;       /* the Layers library */
 
struct vScreenInfo *vScreenData;            /* data needed by the handler */
struct Screen *VScreen = NULL;              /* the virtual screen */
static long Segment = NULL;                 /* the loaded handler */
SHORT ScreenWidth,ScreenHeight;             /* the new screen sizes */

static struct MsgPort *NamedPort = NULL;    /* used to find the handler later */
static struct MsgPort *InputPort = NULL;    /* to talk to Input.Device */
static struct IOStdReq *InputBlock = NULL;  /* IO block for Input.Device */
static short  InputDevice = FALSE;          /* is Input.Device open? */
static int    Enlarged = FALSE;             /* is screen changed? */


/*
 *  These routines are in vScreenSetup.c
 */

extern struct Screen *FindScreen();
extern void SetVariables();
extern void GetVariables();
extern int  EnlargeScreen();
extern void RestoreScreen();

 
#ifndef PROTO
extern long SetFunction();
#endif

/*
 *  We trap these routines via SetFunction in order to make vSscreen work.
 */

#ifndef PROTO
extern void MoveSprite();
extern void LoadView();
extern void AutoRequest();
extern void BuildSysRequest();
extern void CloseScreen();
#endif

extern long LVOMoveSprite;
extern long LVOLoadView;
extern long LVOAutoRequest;
extern long LVOBuildSysRequest;
extern long LVOCloseScreen;


/*
 *  CreateNonSigPort()
 *
 *  Creates a message port with signal type PA_IGNORE.  Based on
 *  CreatePort() from the exec support functions documented in the RKM.
 */

struct MsgPort *CreateNonSigPort(name,pri)
char *name;
BYTE pri;
{
   struct MsgPort *thePort;
   
   thePort = (struct MsgPort *)AllocMem((ULONG)sizeof(struct MsgPort),
                                         MEMF_PUBLIC | MEMF_CLEAR);
   if (thePort)
   {
      thePort->mp_Node.ln_Name = name;
      thePort->mp_Node.ln_Pri  = pri;
      thePort->mp_Node.ln_Type = NT_MSGPORT;
      
      thePort->mp_Flags = PA_IGNORE;
      thePort->mp_SigBit = 0;
      thePort->mp_SigTask = NULL;
      
      if (name)
         AddPort(thePort);
        else
         NewList(&(thePort->mp_MsgList));
   }
   return(thePort);
}


/*
 *  DeleteNonSigPort()
 *
 *  Deletes a message port with signal type PA_IGNORE.  Based on
 *  DeletePort() from the exec support functions documented in the RKM
 */

void DeleteNonSigPort(thePort)
struct MsgPort *thePort;
{
   if (thePort->mp_Node.ln_Name) RemPort(thePort);
   thePort->mp_Node.ln_Type = 0xFF;
   thePort->mp_MsgList.lh_Head = (struct Node *) -1;
   FreeMem(thePort,(ULONG)sizeof(struct MsgPort));
}


/*
 *  DoExit()
 *
 *  Exit with error status.  Print a message with up to three parameters
 *  and then clean up everything (restore the screen if it is enlarged,
 *  unload the handler if it is loaded, close the Input.Device and free
 *  its IO blocks and ports, and close any open libraries).  Return the
 *  error status.
 */

void DoExit(s,x1,x2,x3)
char *s, *x1,*x2,*x3;
{
   int status = OK_EXIT;

   if (s)
   {
      printf(s,x1,x2,x3);
      printf("\n");
      status = ERROR_EXIT;
   }
   if (Enlarged)        RestoreScreen();
   if (NamedPort)       DeleteNonSigPort(NamedPort);
   if (Segment)         UnLoadSeg(Segment);
   if (InputDevice)     CloseDevice(InputBlock);
   if (InputBlock)      DeleteStdIO(InputBlock);
   if (InputPort)       DeletePort(InputPort);
   if (IntuitionBase)   CloseLibrary(IntuitionBase);
   if (GfxBase)         CloseLibrary(GfxBase);
   if (LayersBase)      CloseLibrary(LayersBase);
   exit(status);
}


/*
 *  CheckLibOpen()
 *
 *  Call OpenLibrary() for the specified library, and check that the 
 *  open succeeded.
 */

void CheckLibOpen(lib,name,rev)
APTR *lib;
char *name;
int rev;
{
   #ifndef PROTO
   extern APTR OpenLibrary();
   #endif
   
   if ((*lib = OpenLibrary(name,(ULONG)rev)) == NULL)
      DoExit("Can't open '%s'",name);
}


/*
 *  GetInt()
 *
 *  Read the first integer from the given string variable (used to parse
 *  the command-line arguments).  If no integer can be read, exit and
 *  show the usage string.
 */

static long GetInt(s)
char *s;
{
   long i;

   if (sscanf(s,"%ld",&i) != 1) DoExit("Usage:  %s",USAGE);
   return(i);
}


/*
 *  ParseArguments()
 *
 *  Parse the command-line arguments.  If there are too many or too few
 *  arguments, exit with an error message, otherwise get the width and height
 *  agruments.  If there was a screen name specified, record that.
 *  Find the specified screen.
 */

static void ParseArguments(argc,argv)
int argc;
char *argv[];
{
   char *ScreenName = NULL;

   if (argc < 3) DoExit("Width and Height are required\nUsage:  %s",USAGE);
   if (argc > 4) DoExit("Too many arguments");
   ScreenWidth  = GetInt(argv[1]);
   ScreenHeight = GetInt(argv[2]);
   if (ScreenWidth <= 0 || ScreenHeight <= 0)
      DoExit("Screen height and width must be positive");
   if (ScreenWidth > 1024 || ScreenHeight > 1024)
      printf("Warning:  sizes greater than 1024 may cause Blitter problems\n");
   if (argc > 3 && argv[3] && argv[3][0] != '\0') ScreenName = argv[3];
   VScreen = FindScreen(ScreenName);
}


/*
 *  LoadHandler()
 *
 *  Try to LoadSeg the handler from the current directory, and if it is not
 *  found, try the L: directory.  If neither can be loaded, exit with a 
 *  message.  Once the handler is loaded, call its Setup routine passing it
 *  our version number.  The handler will check the versions for compatability,
 *  and return NULL for version mismatch, or a pointer to its data structure
 *  with pointers to the variables that vScreen will initialize for it.
 *  LoadHandler() sets the pointer to the handlers SegList, and sets the
 *  loader version number
 */

static void LoadHandler()
{
   struct vScreenInfo *(*Setup)();

   if ((Segment = LoadSeg(HANDLER)) == NULL)
      if ((Segment = LoadSeg(handler)) == NULL)
         DoExit("Can't Load '%s'",handler);
   Setup = (struct vScreenInfo *(*)()) ((Segment << 2) + 4);
   
   vScreenData   = (*Setup)(LOADVERS);
   if (vScreenData)
   {
      if (var(MajVers) > 1) DoExit("version mismatch with '%s'",HANDLER);
   } else {
      DoExit("'%s' reports a version mismatch",HANDLER);
   }

   var(Segment)  = Segment;
   var(LoadVers) = LOADVERS;
}


/*
 *  TellInputDevice()
 *
 *  Create a port and I/O block, then open the input device.  Set up the
 *  I/O block to add or remove the input handler, and send the request
 *  to the input device.  Finally, close the device and delete the
 *  I/O block and port.
 */
 
void TellInputDevice(function)
int function;
{
   long status;

   if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
   if ((InputBlock = CreateStdIO(InputPort)) == NULL)
      DoExit("Can't Create Standard IO Block");
   InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
   if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
   
   InputBlock->io_Command = (long) function;
   InputBlock->io_Data    = (APTR) vScreenData->HandlerInfo;
   if (status = DoIO(InputBlock)) DoExit("Error from DoIO:  %ld",status);

   CloseDevice(InputBlock); InputDevice = FALSE;
   DeleteStdIO(InputBlock); InputBlock = NULL;
   DeletePort(InputPort);   InputPort = NULL;
}


/*
 *  SetVectors()
 *
 *  Call SetFunction() to replace the library vectores for the routines that
 *  we need to trap.  Use the routines that the handler has supplied (they
 *  were passed to us in the vScreenData structure).  Save the old vectors
 *  in the vScreenData strucutre so we can replace them later.  Set the 
 *  jump addresses so that the stub routines can call the old vectors.
 *  I Know this is a kludge, and is a form of self-modifying code, but I
 *  can't figure out a better method.  The JSR (Ax) is only good when there
 *  is a free A register, which is not always the case.
 */

void SetVectors()
{
   var(OldCloseScreen) =
       SetFunction(IntuitionBase,&LVOCloseScreen,var(aCloseScreen));
   var(CloseScreenJmpTarget)[-1] = (long) var(OldCloseScreen);

   var(OldBuildSysRequest) =
       SetFunction(IntuitionBase,&LVOBuildSysRequest,var(aBuildSysRequest));
   var(BuildSysRequestJmpTarget)[-1] = (long) var(OldBuildSysRequest);

   var(OldAutoRequest) =
      SetFunction(IntuitionBase,&LVOAutoRequest,var(aAutoRequest));
   var(AutoRequestJmpTarget)[-1] = (long) var(OldAutoRequest);

   var(OldLoadView) = SetFunction(GfxBase,&LVOLoadView,var(aLoadView));
   var(LoadViewJmpTarget)[-1] = (long) var(OldLoadView);

   var(OldMoveSprite) = SetFunction(GfxBase,&LVOMoveSprite,var(aMoveSprite));
   var(MoveSpriteJmpTarget)[-1] = (long) var(OldMoveSprite);
}


/*
 *  UnSetVectors()
 *
 *  Put back the old jump vectors for the routines that we replaced.
 *  Make sure that no one else has replced them behind our backs, however.
 *  If they are not the same way we left them, return an error status.
 */

int UnSetVectors()
{
   long NewCloseScreen,NewBuildSysRequest,NewAutoRequest,
        NewLoadView,NewMoveSprite;
   int status = TRUE;

   NewCloseScreen =
      SetFunction(IntuitionBase,&LVOCloseScreen,var(OldCloseScreen));
   NewBuildSysRequest =
      SetFunction(IntuitionBase,&LVOBuildSysRequest,var(OldBuildSysRequest));
   NewAutoRequest =
      SetFunction(IntuitionBase,&LVOAutoRequest,var(OldAutoRequest));
   NewLoadView   = SetFunction(GfxBase,&LVOLoadView,var(OldLoadView));
   NewMoveSprite = SetFunction(GfxBase,&LVOMoveSprite,var(OldMoveSprite));

   if (NewCloseScreen     != (long) var(aCloseScreen) ||
       NewBuildSysRequest != (long) var(aBuildSysRequest) ||
       NewAutoRequest     != (long) var(aAutoRequest) ||
       NewLoadView        != (long) var(aLoadView) ||
       NewMoveSprite      != (long) var(aMoveSprite))
   {
      SetFunction(IntuitionBase,&LVOCloseScreen,NewCloseScreen);
      SetFunction(IntuitionBase,&LVOBuildSysRequest,NewBuildSysRequest);
      SetFunction(IntuitionBase,&LVOAutoRequest,NewAutoRequest);
      SetFunction(GfxBase,&LVOLoadView,NewLoadView);
      SetFunction(GfxBase,&LVOMoveSprite,NewMoveSprite);
      status = FALSE;
   }
   return(status);
}


/*
 *  main()
 *
 *  Look for the vScreen port.
 *  If one does not exist then vScreen is not currently active, so
 *    open the intuition and graphics libraries.
 *    Parse the command-line arguments to get the width, height, and screen.
 *    Load the handler code, and check its version.
 *    Create the named port used to store information about the handler.
 *    Setup some of the variables needed by the handler, and save a pointer
 *      to the handler data in the named port.
 *    Try to enlarge the size of the screen bitmap, and set more variables.
 *    Add the input handler into the input chain.
 *    SetFunction the neede vectors.  At this point vScreen is active.
 *    Print a message that reports the version numbers.
 *  Otherwise (the port already exists, so vScreen already is active)
 *    Get the pointer to the vScreenData structure from the port.
 *    If they user had supplied arguments, tell him vScreen already is running.
 *    Try to unset the routines we replaced earlier.
 *    If the vectors we removed successfully then
 *      Remove the input handler.
 *      Restore the screen to its original size.
 *      Delete the (no-longer-needed) named port.
 *      Unload the handler code.
 *      Tell the user that the code is removed.
 *      Close the libraries (note that these remained open between calls 
 *        to vScreen, while the handler was active).
 *    Otherwise (we could not replce the function vectors)
 *      Report the problem, and leave the handler running.
 */

void main(argc,argv)
int argc;
char *argv[];
{
   NamedPort = FindPort(PORTNAME);
   if (NamedPort == NULL)
   {
      CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
      CheckLibOpen(&GfxBase,"graphics.library",GRAPHICS_REV);

      ParseArguments(argc,argv);
      LoadHandler();
      if ((NamedPort = CreateNonSigPort(var(PortName),0L)) == NULL)
         DoExit("Can't Create Message Port '%s'",var(PortName));

      SetVariables(NamedPort);
      Enlarged = EnlargeScreen();
      TellInputDevice(IND_ADDHANDLER);
      SetVectors();

      printf("%s v%d.%d.%d Installed\n",program,
         var(MajVers),var(MinVers),var(LoadVers));
   } else {
      GetVariables(NamedPort);
      if (argc > 1)
      {
         printf("%s already active on screen '%s'\n",program,VScreen->Title);
      } else {
         if (UnSetVectors())
         {
            TellInputDevice(IND_REMHANDLER);
            RestoreScreen();
            DeleteNonSigPort(NamedPort);
            UnLoadSeg(var(Segment));
            printf("%s Removed\n",program);
            CloseLibrary(IntuitionBase);
            CloseLibrary(GfxBase);
         } else {
            printf("SetFunction vectors have been changed!\n");
            printf("%s Not Removed\n",program);
         }
      }
   }
}
SHAR_EOF
if test 14176 -ne "`wc -c vScreen.c`"
then
echo shar: error transmitting vScreen.c '(should have been 14176 characters)'
fi
echo shar: extracting vScreenSetup.c '(14356 characters)'
cat << \SHAR_EOF > vScreenSetup.c
/*
 *  VSCREENSETUP.C  Creates virtual screens that can be larger than
 *                  the actual display area of your monitor.  The virtual
 *                  screen scrolls when the mouse moves off the edge of
 *                  the display.
 *
 *                  Copyright 1988 by Davide P. Cervone, all rights reserved.
 *
 *                  You may may distibute this code as is for non-commercial
 *                  purposes, provided that this notice remains intact and the
 *                  documentation file is distributed with it.
 *
 *                  You may not modify this code or incorporate it into your
 *                  own programs without the permission of the author.
 */

/*
 *  WARNING:  This code uses and even modifies the INTUITIONPRIVATE
 *  area of the IntuitionBase structure.  Use it at your own risk.  It is
 *  likely to break under a future release of Intuition.
 */

#include "vScreen.h"

struct LayersBase *LayersBase = NULL;       /* the Layers Library */

extern struct vScreenInfo *vScreenData;     /* the data from the Handler */
extern struct Screen *VScreen;              /* the virtual screen pointer */
extern SHORT ScreenWidth,ScreenHeight;      /* the new width and height */
static UBYTE OldDepth;                      /* the screen depth */

extern void CheckLibOpen();
extern void DoExit();


#define BLT_COPY    0xC0                    /* blitter copy function */
#define MIN(x,y)    (((x)<(y))?(x):(y))     /* MIN macro */


/*
 *  FindScreen()
 *
 *  If a screen name was specified, look through the Intuition screens
 *  for the first one that matches the specified name (case does not matter),
 *  otherwise, use the active screen.
 *  if the screen was not found, exit with an error message.
 */

struct Screen *FindScreen(ScreenName)
char *ScreenName;
{
   struct Screen *theScreen;

   Forbid();
   if (ScreenName && ScreenName[0])
   {
      theScreen = IntuitionBase->FirstScreen;
      while (theScreen && (theScreen->Title == NULL ||
             stricmp(theScreen->Title,ScreenName) != 0))
                theScreen = theScreen->NextScreen;
   } else {
      theScreen = IntuitionBase->ActiveScreen;
   }
   Permit();
   if (theScreen == NULL) DoExit("Can't find screen '%s'",ScreenName);
   return(theScreen);
}


/*
 *  CheckWindows()
 *
 *  Make sure that all the windows on the virtual screen will fit on the
 *  screen when we reduce it to its original size.
 *
 *  For each window on the screen,
 *    check that its right edge will be on the smaller-sized screen.
 *    if not, move it to the left so that it will be.
 *      if that would move the left egde off the screen, then
 *        shrink the window so that it fits.
 *    Check the the bottom edge will be on the smaller screen.
 *    if no, then move it up so that it will be.
 *      if that would move the top edge off the screen, then
 *         shrink the window so that it fits.
 *    If the window needs to change size or position, do so, and record
 *      the number of changes made.
 *
 *  if any windows were changed, delay long enough for Intuition to update
 *    the windows before we actually restore the screen size.  (This is a
 *    kludge, but I don't know a better method that this.  You may need to
 *    adjust the timing factore for busier screens).
 */

static void CheckWindows(theScreen,theWidth,theHeight)
struct Screen *theScreen;
SHORT theWidth,theHeight;
{
   struct Window *theWindow;
   SHORT x,y, w,h;
   SHORT Wx,Wy, Ww,Wh;
   short wChanged = 0;

   if (theScreen)
   {
      theWindow = theScreen->FirstWindow;
      while (theWindow)
      {
         Wx = x = theWindow->LeftEdge;
         Wy = y = theWindow->TopEdge;
         Ww = w = theWindow->Width;
         Wh = h = theWindow->Height;
         
         if (x+w > theWidth)
         {
            x = theWidth - w;
            if (x < 0)
            {
               x = 0;
               w = theWidth;
            }
         }

         if (y+h > theHeight)
         {
            y = theHeight - h;
            if (y < 0)
            {
               y = 0;
               h = theHeight;
            }
         }

         if (x != Wx || y != Wy)
         {
            MoveWindow(theWindow,x-Wx,y-Wy);
            wChanged++;
         }
         
         if (w != Ww || h != Wh)
         {
            SizeWindow(theWindow,w-Ww,h-Wh);
            wChanged++;
         }

         theWindow = theWindow->NextWindow;
      }
   }
   if (wChanged) Delay(wChanged * 30L);
}


/*
 *  GetPlane()
 *
 *  Allocate a bitplane and copy one of the VScren bitplanes into it, then 
 *  free the old bitplane and replace it with the new one.
 *
 *  Two temporary bitmaps are used so that we can call BltBitMap.  The
 *  new bitplane is cleared in case it is larger than the old one, then
 *  the old one is copied.  Since BltBitMap is asynchronous, we call BltClear
 *  on a dummy section of memory to synchronize with the BltBitMap.  That way
 *  we don't free the old raster until it is fully copied.
 *
 *  GetPlane() is used to get the larger bitmap as well as the smaller one 
 *  when we restore the original screen, so MIN() is used to determine
 *  the size of the BltBitMap() action.
 */

static int GetPlane(i,Map1,Map2,junk)
int i;
struct BitMap *Map1,*Map2;
UBYTE *junk;
{
   int error = TRUE;
   long w1 = (Map1->BytesPerRow) << 3;
   long h1 = Map1->Rows;
   long w2 = (Map2->BytesPerRow) << 3;
   long h2 = Map2->Rows;

   Map2->Planes[0] = VScreen->BitMap.Planes[i];
   Map1->Planes[0] = AllocRaster(w1,h1);
   if (Map1->Planes[0])
   {
      BltClear(Map1->Planes[0],RASSIZE(w1,h1),0L);
      BltBitMap(Map2,0L,0L,Map1,0L,0L,MIN(w1,w2),MIN(h1,h2),BLT_COPY,0xFF,NULL);
      BltClear(junk,8L,0L);  /* synchronize with BltBitMap */
      VScreen->BitMap.Planes[i] = Map1->Planes[0];
      FreeRaster(Map2->Planes[0],w2,h2);
      error = FALSE;
   }
   return(error);
}


/*
 *  GetBitMap()
 *
 *  GetBitMap allocates and copies a new, larger bitmap for the virtual
 *  screen.  It does so one plane at a time, however, in order avoid having
 *  the complete old screen and the complete new screen in memory at the
 *  same time.  Two temporary bitmaps are used to perform the single-plane
 *  copies.  The junk memory is used to synchronize the BltBitMap calls (see
 *  GetPlane() above).
 *
 *  For each bitplane in the screen, get a new plane of the proper
 *  size.  If the allocation fails, try to clean up (it's usually too
 *  late, however).
 *
 *  Modify the screen's bitmap to reflect the changed size.
 *  Free the junk space.
 */

static void GetBitMap()
{
   struct BitMap MyBitMap;
   struct BitMap theBitMap;
   int i;
   UBYTE *junk;

   junk = AllocMem(8L,MEMF_CHIP);
   InitBitMap(&MyBitMap,1L,ScreenWidth,ScreenHeight);
   InitBitMap(&theBitMap,1L,VAR(OldWidth),VAR(OldHeight));
   for (i=0; iBitMap.BytesPerRow = MyBitMap.BytesPerRow;
   VScreen->BitMap.Rows = MyBitMap.Rows;
   FreeMem(junk,8L);
}


/*
 *  FreeBitMap()
 *
 *  Similar to GetBitMap, except that FreeBitMap trys to allocate a bitmap
 *  the size of the original screen.
 */

static void FreeBitMap()
{
   struct BitMap MyBitMap;
   struct BitMap theBitMap;
   short i;
   UBYTE *junk;

   junk = AllocMem(8L,MEMF_CHIP);
   InitBitMap(&MyBitMap,1L,ScreenWidth,ScreenHeight);
   InitBitMap(&theBitMap,1L,VAR(OldWidth),VAR(OldHeight));
   for (i=0; iBitMap.BytesPerRow = theBitMap.BytesPerRow;
   VScreen->BitMap.Rows = theBitMap.Rows;
   FreeMem(junk,8L);
}


/*
 *  SetClipRects()
 *
 *  Since the screen size is changing, we need to modify the ClipRects
 *  for the menubar's Layer.  This allows the layer to update itself
 *  properly.
 *
 *  Set the menubar bounds-rectangle size.
 *  For each ClipRect in the menubar layer,
 *    If the bounds-rectangle's right edge is at the edge of the old screen
 *      then set it to be the edge of the new screen.
 */

static void SetClipRects(OldX,NewX)
WORD OldX,NewX;
{
   struct ClipRect *theClipRect = VScreen->BarLayer->ClipRect;

   OldX--; NewX--;
   VScreen->BarLayer->bounds.MaxX = NewX;
   while (theClipRect)
   {
      if (theClipRect->bounds.MaxX == OldX)
         theClipRect->bounds.MaxX = NewX;
      theClipRect = theClipRect->Next; 
   }
}


/*
 *  EnlargeScreen()
 *
 *  Store the current state of the screen and change what needs to be 
 *  changed in order to make it bigger.
 *
 *  Open the Layers Library so that we can call LockLayers().
 *  Lock the Layers for the screen.  The Forbid() may not be necessary.
 *
 *  Get the HIRES and LACE flags for the screen.  Set up the Shift values
 *  needed to convert the screen's local coordinates to actual display
 *  coordinates (always considered 640 x 400 mode).
 *
 *  Get the pointers to the RxOffset and RyOffset variables of the RasInfo
 *  for the ViewPort of the virtual Screen.  These are what tell the
 *  graphics library which part of the bitmap to display.  These are what
 *  make it possible to scroll the screen quickly and easily.  Without them,
 *  vScreen would be impossible, but luckily, the graphics library knows how
 *  to use them.  Unfortunately, Intuition does not, so we have to bend
 *  over backwards to fool intuition.  See vScreen-Handler.c for details.
 *
 *  Get the old width and height of the screen, and the depth.
 *  Get the new, larger bitplanes for the screen.
 *
 *  Set the screen width and height, and repair the ClipRects in the
 *  menubar Layer.
 *
 *  Get the old MaxDisplay values.
 *
 *  Call the handler's SetVScreen() routine (it sets the MaxDisplay
 *  values, the Max and Min Mouse values, and some other stuff),
 *  and the FixView() routine, which calls MakeVPort() and MrgCop() to
 *  incorporate the screen changes into the Intuition View structure.
 *  Finally, load the new View so taht the larger screen will be displayed.
 *
 *  Unlock the layers and close the library.
 *
 *  Call ShowTitle, so that the menubar layer will be updated (so that
 *  it is as wide as the new screen).
 */

void EnlargeScreen()
{
   CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
   LockLayers(&(VScreen->LayerInfo));
   Forbid();

   VAR(HiResScreen) = (VScreen->ViewPort.Modes & HIRES);
   VAR(LaceScreen)  = (VScreen->ViewPort.Modes & LACE);
   VAR(HiResShift) = (VAR(HiResScreen))? 0: 1;
   VAR(LaceShift)  = (VAR(LaceScreen))? 0: 1;

   VAR(RxOffset) = &(VScreen->ViewPort.RasInfo->RxOffset);
   VAR(RyOffset) = &(VScreen->ViewPort.RasInfo->RyOffset);
   VAR(RxOffset2) = (*(VAR(RxOffset))) << VAR(HiResShift);
   VAR(RyOffset2) = (*(VAR(RyOffset))) << VAR(LaceShift);

   VAR(OldWidth)  = VScreen->Width;
   VAR(OldHeight) = VScreen->Height;
   OldDepth = VScreen->BitMap.Depth;
   GetBitMap();

   VScreen->Width  = ScreenWidth;
   VScreen->Height = ScreenHeight;
   SetClipRects(VAR(OldWidth),ScreenWidth);

   VAR(OldMaxDH) = IntuitionBase->MaxDisplayHeight;
   VAR(OldMaxDR) = IntuitionBase->MaxDisplayRow;
   VAR(OldMaxDW) = IntuitionBase->MaxDisplayWidth;

   VAR(SetVScreen)();
   VAR(FixView)(TRUE);
   LoadView(&(IntuitionBase->ViewLord));

   Permit();
   UnlockLayers(&(VScreen->LayerInfo));
   CloseLibrary(LayersBase); LayersBase = NULL;

   ShowTitle(VScreen,(VScreen->Flags & SHOWTITLE)? TRUE: FALSE);
}


/*
 *  RestoreScreen()
 *
 *  If the screen still exists (i.e.,it was not closed while vScreen was
 *  running), then check the windows to be sure that they all will fit on
 *  the original-sized screen.
 *  Open the Layers Library, and lock the screen layers.
 *  Reset the old screen size, and set the menubar ClipRects to the old size.
 *  Set the offsets to zero, and call the Handler's ResetVScreen() routine
 *  (which resets Intuitions MaxDisplay and Min and Max Mouse fields).
 *  Get the screen depth and restore the old bitmap.
 *  Finally, unlock the screen, and remake the Intuition display so that
 *  the new sized screen is displayed.
 *  update the title bar so that it is the right size.
 */

void RestoreScreen()
{
   if (VScreen)
   {
      CheckWindows(VScreen,VAR(OldWidth),VAR(OldHeight));

      CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
      LockLayers(&(VScreen->LayerInfo));
      Forbid();

      VScreen->Width  = VAR(OldWidth);
      VScreen->Height = VAR(OldHeight);
      SetClipRects(ScreenWidth,VAR(OldWidth));

      *(VAR(RxOffset)) = 0;
      *(VAR(RyOffset)) = 0;
      VAR(ResetVScreen)();

      OldDepth = VScreen->BitMap.Depth;
      FreeBitMap();

      Permit();
      UnlockLayers(&(VScreen->LayerInfo));
      CloseLibrary(LayersBase); LayersBase = NULL;

      RemakeDisplay();
      ShowTitle(VScreen,(VScreen->Flags & SHOWTITLE)? TRUE: FALSE);
   }
}


/*
 *  SetVariables()
 *
 *  Store that vScreenData pointer in the MsgPort structure so we can look
 *  it up later (in order to remove the handler).  Save the library pointers
 *  so that the handler can use them, and save the pointer to the virtual 
 *  screen abd its new width and height.
 */

void SetVariables(NamedPort)
struct MsgPort *NamedPort;
{
   NamedPort->mp_SigTask = (struct Task *) vScreenData;
   VAR(IntuitionBase) = IntuitionBase;
   VAR(GfxBase)       = GfxBase;
   VAR(VScreen)       = VScreen;
   VAR(ScreenWidth)   = ScreenWidth;
   VAR(ScreenHeight)  = ScreenHeight;
}


/*
 *  GetVariables()
 *
 *  Retrieve the vScreenData pointer from the MsgPort were we stored it
 *  earlier.  Get back the library pointers so that we can use them and close
 *  them.  Get back the pointer to the virtual screen and its new width
 *  and height.
 */

void GetVariables(NamedPort)
struct MsgPort *NamedPort;
{
   vScreenData   = (struct vScreenInfo *) (NamedPort->mp_SigTask);
   IntuitionBase = VAR(IntuitionBase);
   GfxBase       = VAR(GfxBase);
   VScreen       = VAR(VScreen);
   ScreenWidth   = VAR(ScreenWidth);
   ScreenHeight  = VAR(ScreenHeight);
}
SHAR_EOF
if test 14356 -ne "`wc -c vScreenSetup.c`"
then
echo shar: error transmitting vScreenSetup.c '(should have been 14356 characters)'
fi
echo shar: extracting wList.c '(2260 characters)'
cat << \SHAR_EOF > wList.c
#include 
#include 
#include 
#include 
#include 

#define INTUITION_REV   0L
extern struct IntuitionBase *IntuitionBase;
extern struct IntuitionBase *OpenLibrary();


static void ShowUsage()
{
   printf("Usage:  WLIST [screen]\n");
   exit(10L);
}


static struct Screen *FindScreen(ScreenName)
char *ScreenName;
{
   struct Screen *theScreen;

   if (ScreenName && ScreenName[0])
   {
      Forbid();
      theScreen = IntuitionBase->FirstScreen;
      while (theScreen && (theScreen->Title == NULL ||
             stricmp(theScreen->Title,ScreenName) != 0))
                theScreen = theScreen->NextScreen;
      Permit();
   } else {
      Forbid();
      theScreen = IntuitionBase->FirstScreen;
      Permit();
   }

   if (theScreen == NULL)
   {
      Permit();
      printf("Can't find screen '%s'\n",ScreenName);
      exit(10L);
   }
   return(theScreen);
}


static void PrintWindowTitle(theWindow)
struct Window *theWindow;
{
   if (theWindow && theWindow->Title)
      printf("   '%s'\n",theWindow->Title);
     else
      printf("   [No Title]\n");
}

static void PrintScreenTitle(theScreen)
struct Screen *theScreen;
{
   if (theScreen && theScreen->Title)
      printf("'%s'\n",theScreen->Title);
     else
      printf("[No Title]\n");
}


static void PrintScreenWindows(theScreen)
struct Screen *theScreen;
{
   struct Window *theWindow = theScreen->FirstWindow;
   
   while (theWindow)
   {
      PrintWindowTitle(theWindow);
      theWindow = theWindow->NextWindow;
   }
}


void main(argc,argv)
int argc;
char *argv[];
{
   char *ScreenName = NULL;
   struct Screen *theScreen;

   if (argc > 2) ShowUsage();
   if (argc > 1 && argv[1] && argv[1][0] != '\0') ScreenName = argv[1];
   
   IntuitionBase = OpenLibrary("intuition.library",INTUITION_REV);
   if (IntuitionBase)
   {
      theScreen = FindScreen(ScreenName);

      printf("\n");
      while (theScreen)
      {
         PrintScreenTitle(theScreen);
         PrintScreenWindows(theScreen);
         if (ScreenName)
            theScreen = NULL;
           else
            theScreen = theScreen->NextScreen;
      }
      printf("\n");
      CloseLibrary(IntuitionBase);
   }
}

SHAR_EOF
if test 2260 -ne "`wc -c wList.c`"
then
echo shar: error transmitting wList.c '(should have been 2260 characters)'
fi
echo shar: extracting wMax.c '(2831 characters)'
cat << \SHAR_EOF > wMax.c
#include 
#include 
#include 
#include 
#include 

#define INTUITION_REV   0L
extern struct IntuitionBase *IntuitionBase;
extern struct IntuitionBase *OpenLibrary();


static void ShowUsage()
{
   printf("Usage:  WMAX x y [window [screen]]\n");
   exit(10L);
}


static void GetInt(i,s)
long *i;
char *s;
{
   if (sscanf(s,"%ld",i) != 1) ShowUsage();
}

static struct Screen *FindScreen(ScreenName)
char *ScreenName;
{
   struct Screen *theScreen;

   if (ScreenName && ScreenName[0])
   {
      theScreen = IntuitionBase->FirstScreen;
      while (theScreen && (theScreen->Title == NULL ||
             stricmp(theScreen->Title,ScreenName) != 0))
                theScreen = theScreen->NextScreen;
   } else {
      theScreen = IntuitionBase->ActiveScreen;
   }

   if (theScreen == NULL)
   {
      Permit();
      printf("Can't find screen '%s'\n",ScreenName);
      exit(10L);
   }
   return(theScreen);
}


static struct Window *FindWindow(WindowName,theScreen)
char *WindowName;
struct Screen *theScreen;
{
   struct Window *theWindow;

   if (WindowName && WindowName[0])
   {
      theWindow = theScreen->FirstWindow;
      while (theWindow && (theWindow->Title == NULL ||
             stricmp(theWindow->Title,WindowName) != 0))
                theWindow = theWindow->NextWindow;
   } else {
      theWindow = IntuitionBase->ActiveWindow;
   }

   if (theWindow == NULL)
   {
      Permit();
      printf("Can't find window '%s' on screen '%s'\n",
         WindowName,theScreen->Title);
      exit(10L);
   }
   Permit();
   return(theWindow);
}


void main(argc,argv)
int argc;
char *argv[];
{
   char *WindowName = NULL;
   char *ScreenName = NULL;
   long x,y;
   struct Window *theWindow;
   struct Screen *theScreen;

   if (argc < 3 || argc > 5) ShowUsage();
   GetInt(&x,argv[1]);
   GetInt(&y,argv[2]);
   if (argc > 3 && argv[3] && argv[3][0] != '\0') WindowName = argv[3];
   if (argc > 4 && argv[4] && argv[4][0] != '\0') ScreenName = argv[4];
   
   IntuitionBase = OpenLibrary("intuition.library",INTUITION_REV);
   if (IntuitionBase)
   {
      Forbid();
      theScreen = FindScreen(ScreenName);
      theWindow = FindWindow(WindowName,theScreen);
      Permit();

      printf("\nWindow '%s' on Screen '%s'\n",
         theWindow->Title,theWindow->WScreen->Title);
      printf("   Old Max:  (%d,%d)    Old Min:  (%d,%d)\n",
         theWindow->MaxWidth,theWindow->MaxHeight,
         theWindow->MinWidth,theWindow->MinHeight);
      if (x || y)
      {
         Forbid();
         theWindow->MaxWidth  = x;
         theWindow->MaxHeight = y;
         Permit();
         printf("   New Max:  (%d,%d)\n\n",
            theWindow->MaxWidth,theWindow->MaxHeight);
      }
      CloseLibrary(IntuitionBase);
   }
}
SHAR_EOF
if test 2831 -ne "`wc -c wMax.c`"
then
echo shar: error transmitting wMax.c '(should have been 2831 characters)'
fi
echo shar: extracting wMove.c '(3182 characters)'
cat << \SHAR_EOF > wMove.c
#include 
#include 
#include 
#include 
#include 

#define INTUITION_REV   0L
extern struct IntuitionBase *IntuitionBase;
extern struct IntuitionBase *OpenLibrary();


static void ShowUsage()
{
   printf("Usage:  WMOVE dx dy [window [screen]]\n");
   exit(10L);
}


static void GetInt(i,s)
long *i;
char *s;
{
   if (sscanf(s,"%ld",i) != 1) ShowUsage();
}

static struct Screen *FindScreen(ScreenName)
char *ScreenName;
{
   struct Screen *theScreen;

   if (ScreenName && ScreenName[0])
   {
      theScreen = IntuitionBase->FirstScreen;
      while (theScreen && (theScreen->Title == NULL ||
             stricmp(theScreen->Title,ScreenName) != 0))
                theScreen = theScreen->NextScreen;
   } else {
      theScreen = IntuitionBase->ActiveScreen;
   }

   if (theScreen == NULL)
   {
      Permit();
      printf("Can't find screen '%s'\n",ScreenName);
      exit(10L);
   }
   return(theScreen);
}


static struct Window *FindWindow(WindowName,theScreen)
char *WindowName;
struct Screen *theScreen;
{
   struct Window *theWindow;

   if (WindowName && WindowName[0])
   {
      theWindow = theScreen->FirstWindow;
      while (theWindow && (theWindow->Title == NULL ||
             stricmp(theWindow->Title,WindowName) != 0))
                theWindow = theWindow->NextWindow;
   } else {
      theWindow = IntuitionBase->ActiveWindow;
   }

   if (theWindow == NULL)
   {
      Permit();
      printf("Can't find window '%s' on screen '%s'\n",
         WindowName,theScreen->Title);
      exit(10L);
   }
   Permit();
   return(theWindow);
}


void main(argc,argv)
int argc;
char *argv[];
{
   char *WindowName = NULL;
   char *ScreenName = NULL;
   long dx,dy;
   struct Window *theWindow;
   struct Screen *theScreen;

   if (argc < 3 || argc > 5) ShowUsage();
   GetInt(&dx,argv[1]);
   GetInt(&dy,argv[2]);
   if (argc > 3 && argv[3] && argv[3][0] != '\0') WindowName = argv[3];
   if (argc > 4 && argv[4] && argv[4][0] != '\0') ScreenName = argv[4];
   
   IntuitionBase = OpenLibrary("intuition.library",INTUITION_REV);
   if (IntuitionBase)
   {
      Forbid();
      theScreen = FindScreen(ScreenName);
      theWindow = FindWindow(WindowName,theScreen);
      Permit();

      if (dx < -(theWindow->LeftEdge)) dx = -(theWindow->LeftEdge);
      if (dy < -(theWindow->TopEdge))  dy = -(theWindow->TopEdge);
      
      if (theWindow->LeftEdge + dx + theWindow->Width > theScreen->Width)
         dx = theScreen->Width - theWindow->Width - theWindow->LeftEdge;
      if (theWindow->TopEdge + dy + theWindow->Height > theScreen->Height)
         dy = theScreen->Height - theWindow->Height - theWindow->TopEdge;

      printf("\nWindow '%s' on Screen '%s'\n",
         theWindow->Title,theWindow->WScreen->Title);
      printf("   Old position:  (%d,%d)\n",
         theWindow->LeftEdge,theWindow->TopEdge);
      if (dx || dy)
      {
         printf("   New position:  (%d,%d)\n   Changed:       (%d,%d)\n\n",
            theWindow->LeftEdge+dx,theWindow->TopEdge+dy,dx,dy);
         MoveWindow(theWindow,dx,dy);
      }
      CloseLibrary(IntuitionBase);
   }
}
SHAR_EOF
if test 3182 -ne "`wc -c wMove.c`"
then
echo shar: error transmitting wMove.c '(should have been 3182 characters)'
fi
echo shar: extracting wSize.c '(3542 characters)'
cat << \SHAR_EOF > wSize.c
#include 
#include 
#include 
#include 
#include 

#define INTUITION_REV   0L
extern struct IntuitionBase *IntuitionBase;
extern struct IntuitionBase *OpenLibrary();


static void ShowUsage()
{
   printf("Usage:  WSIZE dx dy [window [screen [IGNOREMAX]]\n");
   exit(10L);
}


static void GetInt(i,s)
long *i;
char *s;
{
   if (sscanf(s,"%ld",i) != 1) ShowUsage();
}

static struct Screen *FindScreen(ScreenName)
char *ScreenName;
{
   struct Screen *theScreen;

   if (ScreenName && ScreenName[0])
   {
      theScreen = IntuitionBase->FirstScreen;
      while (theScreen && (theScreen->Title == NULL ||
             stricmp(theScreen->Title,ScreenName) != 0))
                theScreen = theScreen->NextScreen;
   } else {
      theScreen = IntuitionBase->ActiveScreen;
   }

   if (theScreen == NULL)
   {
      Permit();
      printf("Can't find screen '%s'\n",ScreenName);
      exit(10L);
   }
   return(theScreen);
}


static struct Window *FindWindow(WindowName,theScreen)
char *WindowName;
struct Screen *theScreen;
{
   struct Window *theWindow;

   if (WindowName && WindowName[0])
   {
      theWindow = theScreen->FirstWindow;
      while (theWindow && (theWindow->Title == NULL ||
             stricmp(theWindow->Title,WindowName) != 0))
                theWindow = theWindow->NextWindow;
   } else {
      theWindow = IntuitionBase->ActiveWindow;
   }

   if (theWindow == NULL)
   {
      Permit();
      printf("Can't find window '%s' on screen '%s'\n",
         WindowName,theScreen->Title);
      exit(10L);
   }
   Permit();
   return(theWindow);
}


void main(argc,argv)
int argc;
char *argv[];
{
   char *WindowName = NULL;
   char *ScreenName = NULL;
   long dx,dy;
   struct Window *theWindow;
   struct Screen *theScreen;
   long UseMax = TRUE;

   if (argc < 3 || argc > 6) ShowUsage();
   GetInt(&dx,argv[1]);
   GetInt(&dy,argv[2]);
   if (argc > 3 && argv[3] && argv[3][0] != '\0') WindowName = argv[3];
   if (argc > 4 && argv[4] && argv[4][0] != '\0') ScreenName = argv[4];
   if (argc > 5) UseMax = FALSE;
   
   IntuitionBase = OpenLibrary("intuition.library",INTUITION_REV);
   if (IntuitionBase)
   {
      Forbid();
      theScreen = FindScreen(ScreenName);
      theWindow = FindWindow(WindowName,theScreen);
      Permit();

      if (theWindow->LeftEdge + theWindow->Width + dx > theScreen->Width)
         dx = theScreen->Width - theWindow->LeftEdge - theWindow->Width;
      if (theWindow->Width + dx < theWindow->MinWidth)
         dx = theWindow->MinWidth - theWindow->Width;
      if (theWindow->Width + dx > theWindow->MaxWidth && UseMax)
         dx = theWindow->MaxWidth - theWindow->Width;

      if (theWindow->TopEdge + theWindow->Height + dy > theScreen->Height)
         dy = theScreen->Height - theWindow->TopEdge - theWindow->Height;
      if (theWindow->Height + dy < theWindow->MinHeight)
         dy = theWindow->MinHeight - theWindow->Height;
      if (theWindow->Height + dy > theWindow->MaxHeight && UseMax)
         dy = theWindow->MaxHeight - theWindow->Height;

      printf("\nWindow '%s' on Screen '%s'\n",
         theWindow->Title,theWindow->WScreen->Title);
      printf("   Old size:  (%d,%d)\n",theWindow->Width,theWindow->Height);
      if (dx || dy)
      {
         printf("   New size:  (%d,%d)\n   Changed:   (%d,%d)\n\n",
            theWindow->Width+dx,theWindow->Height+dy,dx,dy);
         SizeWindow(theWindow,dx,dy);
      }
      CloseLibrary(IntuitionBase);
   }
}
SHAR_EOF
if test 3542 -ne "`wc -c wSize.c`"
then
echo shar: error transmitting wSize.c '(should have been 3542 characters)'
fi
#	End of shell archive
exit 0