[comp.sys.amiga] So Close, Yet So Far Away...

ewhac@well.UUCP (03/11/87)

[ I've been released from the NSA mental health ward. ]

Hello again,

	I had hoped that I might be able to give you all an actual utility.
As it turns out, I can't.

	Once upon a time, I saw a program for the Macintrash computer that
loaded a picture into the Desktop's background, so that you would have a
pretty picture to look at behind all your windows instead of just a boring
pattern.

	I thought I'd try writing this for the Amiga.  It shouldn't be too
hard, I thought.  Just change the WorkBench's backdrop window from
SIMPLE_REFRESH to SMART_REFRESH, without mashing anything.

	Well, I got that far.  But after modifying the backdrop window, I
discovered a "feature" of the WorkBench.

	The disk icons are attached to the WorkBench backdrop window
(obviously), and are therefore rendered in its RastPort.  I had anticipated
problems with this (disk icons might permanently mark a loaded image), but
didn't know exactly how WorkBench dealt with it.

	I found out.  Whenever you move a disk icon, or remove a volume from
a drive, the WorkBench program *clears the screen* and redraws all the disk
icons.  Thus, if you render anything into the WorkBench window, it will get
erased the moment you fiddle with the disk icons.

	This pretty much blew my idea out of the water.  I can see no way
around this, apart from replacing the SetRast() call in the graphics library
(to check for to see if they're trying to clear the WorkBench and prevent
it), or by rewriting the WorkBench (no, thanks).

	I also tried setting the RastPort's Mask value to 0.  I thought this
would prevent any subsequent rendering into the window.  It was here I
encountered what appears to be at first sight a bug in the graphics library.
After rendering into the window, I set the Mask to 0.  Everything appeared
to be fixed on the screen.  Then I moved my CLI window around.  Everything
underneath it was erased.  "Hmmm," I thought.  "Could it be that, when
returning backup bitmaps to the visible screen, it's wrongly observing the
Mask value?"  As an experiment, I changed the mask value to 1 and tried
moving the CLI window around again.  After uncovering something, anything
that was in the masked bitplane disappeared.  I can only assume that the
graphics library is trying to restore the visible bitmap while observing the
Mask value, which strikes me as wrong.  Dale Luck, you out there?  Can you
comment on this? (KS 1.2R, 512K CHIP, 2M FAST, 2 drives, MANX, written while
listening to 1812 Overture (Guru alerts take on a whole new meaning :-) ))

	In any event, I did end up with some code that does, in fact, change
the WorkBench window from SIMPLE_ to SMART_REFRESH.  I thought you people
might find it instuctive.  And who knows; someone else may actually get my
original idea working.

	The following program changes the identity of the WorkBench backdrop
window, then draws a couple of lines in it to "prove" that it's really SMART
now.  You can move windows around, and the background will be preserved.
However, the moment you fiddle with the disk icons, the window will be
cleared, and the only thing you'll have to show for all this is a major loss
of chip RAM.

	By the way, this is a MANX program.
	cc fixwb.c
	ln fixwb.o -lc -o fixwb

	Maybe you people can do something constructive with this.  Thanks
for your time and disk space.

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 ________		 ___			Leo L. Schwab
	   \		/___--__		The Guy in The Cape
  ___  ___ /\		    ---##\		ihnp4!ptsfa!well!ewhac
      /   X  \_____    |  __ _---))			..or..
     /   /_\--    -----+==____\ // \  _		well ---\
___ (   o---+------------------O/   \/ \	dual ----> !unicom!ewhac
     \     /		    ___ \_  (`o )	hplabs -/       ("AE-wack")
 ____ \___/			     \_/
	      Recumbent Bikes:			"Work FOR?  I don't work FOR
	    The _O_n_l_y Way To Fly!		anybody!  I'm just having fun."

_-_-_-_-_-_-_-_-_-_-_ Apply Andy Finkel here. _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
/*  :ts=8 bk=0
 *
 * fixwb.c:	A program to fix the WorkBench backdrop window into place,
 *		by turning it into a SMART_REFRESH window.  Also will load
 *		an IFF image into the window, assuming I can figure out the
 *		IFF spec.
 *
 * Sigh.  As it turns out, the WorkBench program makes this effort
 * impossible since it clears the backdrop window everytime something new
 * happens with the disk icons.
 *
 * Leo L. Schwab		8703.10		(415)-456-6565
 */

#include <exec/types.h>
#include <intuition/intuition.h>

/*  Only the full-screen WorkBench window has these two flags set.  */
#define	WBACK		(WBENCHWINDOW | BACKDROP)

extern void	*OpenLibrary(), *OpenWindow(), *CreateBehindLayer();

struct NewWindow windef = {
	0, 30, 200, 10,
	-1, -1,
	NULL,
	WINDOWDRAG | WINDOWDEPTH | SMART_REFRESH | ACTIVATE,
	NULL, NULL,
	(UBYTE *) "Computing...",
	NULL, NULL,
	0, 0, 0, 0,
	WBENCHSCREEN
};

struct Window	*win;
void		*IntuitionBase, *GfxBase, *LayersBase;


main ()
{
	struct Screen *wbs;
	struct Layer_Info *li;
	struct Layer *wbl;
	struct Window *chk, *wbw = 0;
	long top, left, wide, high;
	long flags;

	openstuff ();
	wbs = win -> WScreen;	/*  Get pointer to WorkBench screen  */
	li = &wbs -> LayerInfo;

	for (chk = wbs -> FirstWindow; chk; chk = chk -> NextWindow) {
		flags = chk -> Flags;
		if ((flags & WBACK) == WBACK) {
			wbw = chk;
			break;
		}
	}
	if (!wbw)
		die ("WorkBench not loaded.");
	if ((flags & REFRESHBITS) == SMART_REFRESH)
		die ("WorkBench already fixed.");
	top	= wbw -> TopEdge;
	left	= wbw -> LeftEdge;
	wide	= wbw -> Width;
	high	= wbw -> Height;

	wbl = wbw -> RPort -> Layer;	/*  Get the layer pointer  */

	/*
	 * At this point, we are about to perform what is probably
	 * tantamount to rape to the system.  Therefore, I'm Forbid()ing
	 * anything else from running so as to prevent a major collapse.
	 *
	 * First, we stop everyone else.  Then, we un-backdrop the layer
	 * so we can depth-arrange it.  We then bring it to the front,
	 * forcing the layers library to save the state of everything else.
	 * Then we change the identity of the layer from SIMPLE to SMART.
	 * Then we depth-arrange it to the back again.  This will make all
	 * previous layers visible, and cause the library to create all the
	 * necssary ClipRects and backup bitmaps for us.  Then we re-set
	 * the backdrop bit, anchoring the window into place.
	 */

	Forbid ();
	wbl -> Flags &= ~LAYERBACKDROP;
	UpfrontLayer (li, wbl);
	wbl -> Flags = wbl -> Flags & ~LAYERSIMPLE | LAYERSMART;
	BehindLayer (li, wbl);
	wbl -> Flags |= LAYERBACKDROP;

	/*  Correct Intuition's ideas about the window.  */
	wbw -> Flags = flags & ~SIMPLE_REFRESH | SMART_REFRESH;

	Permit ();	/*  That should do it  */

	/*  Do things in the newly fixed WorkBench  */
	SetAPen (wbw -> RPort, 1L);
	Move (wbw -> RPort, 0L, 0L);
	Draw (wbw -> RPort, wide-1, high-1);
	Move (wbw -> RPort, 0L, high-1);
	Draw (wbw -> RPort, wide-1, 0L);
	/*
	 * If you want to watch the Mask "bug" at work, uncomment this next
	 * line of code.  Move window on and off disk icons and watch the
	 * results.
	 *
	 * wbw -> RPort -> Mask = 1;
	 */
	closestuff ();
}


openstuff ()
{
	if (!(IntuitionBase = OpenLibrary ("intuition.library", 0L)))
		die ("Intuition unavailable, use logic.");

	if (!(GfxBase = OpenLibrary ("graphics.library", 0L)))
		die ("Art shop closed.");

	if (!(LayersBase = OpenLibrary ("layers.library", 0L)))
		die ("Nothing laying around.");

	if (!(win = OpenWindow (&windef)))
		die ("Window painted shut.");
}

closestuff ()
{
	if (win)		CloseWindow (win);
	if (LayersBase)		CloseLibrary (LayersBase);
	if (GfxBase)		CloseLibrary (GfxBase);
	if (IntuitionBase)	CloseLibrary (IntuitionBase);
}

die (str)
char *str;
{
	puts (str);
	closestuff ();
	exit (10);
}