ain@j.cc.purdue.edu (Patrick White) (12/30/87)
Program Name: iconify
Submitted By: well!ewhac@lll-crg.llnl.gov (Leo 'Bols Ewhac' Schwab)
Summary: This code shows how to iconify a window.
Poster Boy: Pat White (ain@j.cc.purdue.edu)
Tested.
NOTES:
There is an executable version of the demo posted to comp.binaries.amiga.
"There are NO bugs in MY code."
To get it to compile under Manx 3.4a, you *must* add some preceeding
^
semicolons to the comments in the assembly code in the file demo.c.
-- Pat White (co-moderator comp.sources/binaries.amiga)
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
----------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# README
# iconify.doc
# Makefile
# iconify.h
# iconify.c
# demo.c
# This archive created: Fri Dec 18 16:14:20 1987
# By: Leo 'Bols Ewhac' Schwab (Hole Earth 'Lectronic Loss (or words to that effect))
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'README'
then
echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
At last! I wrote something useful! This package contains the
iconify() routine, and a demo program that demonstrates it.
MANUFACTURE:
This program is guaranteed to work with the Manx C compiler (version
3.4b). However, I did try to keep compiler independence in mind when
writing it, so it is hoped that the iconify() routine will compile cleanly
under Lattice (but I haven't tried it, so no promises). To create the demo,
you say:
1> make
SHAMELESS PLEADING:
Please do read the top comment in the iconify.c and/or iconify.h
file.
I hope you all like this new goodie.
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Leo L. Schwab -- The Guy in The Cape ihnp4!ptsfa -\
\_ -_ Recumbent Bikes: dual ---> !{well,unicom}!ewhac
O----^o The Only Way To Fly. hplabs / (pronounced "AE-wack")
"Work FOR? I don't work FOR anybody! I'm just having fun." -- The Doctor
SHAR_EOF
fi
if test -f 'iconify.doc'
then
echo shar: "will not over-write existing file 'iconify.doc'"
else
cat << \SHAR_EOF > 'iconify.doc'
iconify() Amiga Programmer's Manual iconify()
NAME
iconify -- Create an icon on the screen that can be dragged
around.
SYNOPSIS
#include "iconify.h"
int success;
success =
iconify (LeftEdge, TopEdge, Width, Height, Screen, ptr, Type);
UWORD *LeftEdge, *TopEdge;
UWORD Width, Height;
struct Screen *Screen;
APTR ptr;
int Type;
DESCRIPTION
Iconify() is a subroutine that creates an icon on the Amiga screen
that can be subsequently dragged around, and double-clicked on.
Iconify() creates an icon at screen location (*LeftEdge, *TopEdge)
and of size (Width, Height), in pixels. The icon is created on
the screen specified. If Screen is NULL, the icon will be created
on the WorkBench screen.
The Type variable tells iconify() how to make the icon. Based on
the value contained in Type, ptr may be interpreted in one of three
different ways:
ICON_IMAGE:
ptr points to an initialized structure of type Image
(intuition.h). The image contained in the structure will
be used as the icon image.
ICON_BORDER:
ptr points to an initialized structure of type Border
(intuition.h). The drawing instructions contained in the
border structure will be used to render the icon.
ICON_FUNCTION:
[This is by far the most interesting one.] ptr points to
a function that will be called by iconify() N times a
second (where N is a compile-time constant). The format
of the call is:
(* ((void (*)()) ptr)) (win, val);
struct Window *win;
WORD val;
When the icon is first created, your function will be
called with val equal to one (non-zero). This should be
used as a flag to your function to call any initialization
code it may need (such as caching the icon size, setting
draw modes, etc.). On every subsequent call, val will be
equal to zero.
win points to the window which is your icon (the icon is in
fact a window-sized drag gadget). This may be used for
rendering purposes (animated icons, for example).
After the icon is created, iconify() will wait until the icon has
been double-clicked on. If the icon is of type ICON_FUNCTION,
iconify() will also call the supplied function N times a second
while waiting for the double-click.
When the icon is double-clicked, iconify() will update the values
pointed to by LeftEdge and TopEdge. This is so that, in subsequent
invocations of iconify(), the icon will be where the user last left
it. Thus, it is the responsibility of the calling program to
maintain these values.
After updating these values, iconify() will remove the icon from
the screen, and return to the caller with a non-zero value. If any
of iconify()'s internal operations fail, a zero value will be
returned. It is strongly suggested that this be checked for by
the calling program.
VIEW TO OUTSIDE PROGRAMS
Icons created with iconify() will look like small windows (this is
largely due to the fact that they are small windows). Outside
programs may wish to differentiate between 'real' windows, and
objects created with iconify().
To this end, iconify() writes the 32-bit constant 0x49434f4e
(which just happens to be the word 'ICON' in ASCII) into the
window's UserData field. Outside programs that are manipulating
windows can check for this so they can avoid touching icons (or so
that they can specifically find icons if they want).
AUTHOR
Leo L. Schwab
61 Martens Blvd.
San Rafael, CA 94901-5028
{ihnp4!ptsfa,hplabs}!{well!unicom}!ewhac
SEE ALSO
Amiga Rom Kernel Manual
Intuition: The Amiga User Interface
BUGS
There are NO bugs in MY code. However, there may be any number
of undesireable features (but I doubt it).
SHAR_EOF
fi
if test -f 'Makefile'
then
echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# :ts=8 bk=0
#
# Makefile for iconify tester program.
OBJECTS = demo.o iconify.o
demo: $(OBJECTS)
ln $(OBJECTS) +cd -lc
SHAR_EOF
fi
if test -f 'iconify.h'
then
echo shar: "will not over-write existing file 'iconify.h'"
else
cat << \SHAR_EOF > 'iconify.h'
/* :ts=8 bk=0
*
* iconify.h: Should be used by all programs intending to use iconify.c.
*
* Copyright 1987 by Leo L. Schwab.
* Permission is hereby granted for use in any and all programs, both
* Public Domain and commercial in nature, provided this Copyright notice
* is left intact. Purveyors of programs, at their option, may wish observe
* the following conditions (in the spirit of hackerdom):
* 1: You send me a free, registered copy of the program that uses the
* iconify feature,
* 2: If you're feeling really nice, a mention in the program's
* documentation of my name would be neat.
*
* 8712.10 (415) 456-3960
*/
#define ICON_IMAGE 0
#define ICON_BORDER 1
#define ICON_FUNCTION 2
/* Suggested icon size for a standard (640 x 200) WorkBench screen. */
#define ICONWIDTH ((UWORD) 50)
#define ICONHEIGHT ((UWORD) 25)
SHAR_EOF
fi
if test -f 'iconify.c'
then
echo shar: "will not over-write existing file 'iconify.c'"
else
cat << \SHAR_EOF > 'iconify.c'
/* :ts=8 bk=0
*
* iconify.c: You asked for it, you got it.
*
* Copyright 1987 by Leo L. Schwab.
* Permission is hereby granted for use in any and all programs, both
* Public Domain and commercial in nature, provided this Copyright notice
* is left intact. Purveyors of programs, at their option, may wish observe
* the following conditions (in the spirit of hackerdom):
* 1: You send me a free, registered copy of the program that uses the
* iconify feature,
* 2: If you're feeling really nice, a mention in the program's
* documentation of my name would be neat.
*
* 8712.10 (415) 456-3960
*/
#include <exec/types.h>
#include <devices/timer.h>
#include <intuition/intuition.h>
#include "iconify.h"
/*
* It is recommended that the tick rate not be made too rapid to avoid
* bogging down the system.
*/
#define TICKS_PER_SECOND 10
/*
* Some programmers may not wish to have the added functionality of the
* ICON_FUNCTION feature. If you're such a programmer, you may comment out
* the following #define, which will eliminate the code to handle function
* calls, and make iconify() even smaller.
*/
#define USE_FUNCTIONS
/*
* Jim Mackraz suggested making icons easily identifiable by outside
* programs, so this constant gets stuffed into the UserData field.
*/
#define ICON 0x49434f4eL /* 'ICON' */
extern void *OpenWindow(), *GetMsg(), *CreatePort(), *CreateExtIO(),
*CheckIO();
extern long OpenDevice(), DoubleClick();
static struct Gadget gadget = {
NULL,
0, 0, 0, 0,
NULL, /* Set later */
GADGIMMEDIATE,
WDRAGGING, /* Observe the Magic! */
NULL, /* Set later */
NULL, NULL, NULL, NULL,
0, 0
};
static struct NewWindow windef = {
0, 0, 0, 0, /* Set later */
-1, -1,
GADGETDOWN,
BORDERLESS | SMART_REFRESH | NOCAREREFRESH,
&gadget,
NULL, NULL, NULL, NULL, /* Lotsa these */
0, 0, 0, 0,
WBENCHSCREEN
};
static struct Window *win;
#ifdef USE_FUNCTIONS
static struct timerequest *tr;
static struct MsgPort *reply;
#endif
iconify (left, top, width, height, screen, ptr, type)
UWORD *left, *top, width, height;
struct Screen *screen;
APTR ptr;
int type;
{
register struct IntuiMessage *msg;
long secs = 0, mics = 0,
cs, cm,
class,
sigmask;
windef.LeftEdge = *left;
windef.TopEdge = *top;
windef.Width = width;
windef.Height = height;
windef.Type = (windef.Screen = screen) ? CUSTOMSCREEN : WBENCHSCREEN;
gadget.Flags = GADGHCOMP | GRELWIDTH | GRELHEIGHT;
switch (type & 3) {
case ICON_IMAGE:
gadget.Flags |= GADGIMAGE;
case ICON_BORDER:
gadget.GadgetRender = ptr;
break;
case ICON_FUNCTION:
#ifdef USE_FUNCTIONS
gadget.GadgetRender = NULL;
#else
return (0);
#endif
break;
default:
return (0);
}
if (!openstuff ())
return (0);
sigmask = 1L << win -> UserPort -> mp_SigBit;
#ifdef USE_FUNCTIONS
if (type == ICON_FUNCTION) {
sigmask |= 1L << reply -> mp_SigBit;
tr -> tr_node.io_Command= TR_ADDREQUEST;
tr -> tr_time.tv_secs = 0;
tr -> tr_time.tv_micro = (1000000L / TICKS_PER_SECOND);
SendIO (tr);
/*
* Make initialization call to user's function.
* Isn't typecasting wonderful? :-|
*/
(* ((void (*)()) ptr)) (win, (WORD) 1);
}
#endif
while (1) {
Wait (sigmask);
#ifdef USE_FUNCTIONS
if (GetMsg (reply)) {
/*
* Call user's function to do something to the icon.
*/
(* ((void (*)()) ptr)) (win, (WORD) 0);
tr -> tr_time.tv_secs = 0;
tr -> tr_time.tv_micro =
(1000000L / TICKS_PER_SECOND);
SendIO (tr);
}
#endif
if (msg = GetMsg (win -> UserPort)) {
class = msg -> Class;
cs = msg -> Seconds;
cm = msg -> Micros;
ReplyMsg (msg);
if (class == GADGETDOWN) {
if (DoubleClick (secs, mics, cs, cm))
break;
secs = cs; mics = cm;
}
}
}
#ifdef USE_FUNCTIONS
if (type == ICON_FUNCTION) {
AbortIO (tr);
WaitIO (tr);
}
#endif
*left = win -> LeftEdge;
*top = win -> TopEdge;
closestuff ();
return (1);
}
static
openstuff ()
{
if (!(win = OpenWindow (&windef)))
return (0);
win -> UserData = (BYTE *) ICON;
#ifdef USE_FUNCTIONS
if (!(reply = CreatePort (NULL, NULL)) ||
!(tr = CreateExtIO (reply, (long) sizeof (*tr))) ||
OpenDevice (TIMERNAME, UNIT_VBLANK, tr, 0L)) {
closestuff ();
return (0);
}
#endif
return (1);
}
static
closestuff ()
{
#ifdef USE_FUNCTIONS
if (tr) {
if (tr -> tr_node.io_Device)
CloseDevice (tr);
DeleteExtIO (tr, (long) sizeof (*tr));
}
if (reply) DeletePort (reply);
#endif
if (win) CloseWindow (win);
}
SHAR_EOF
fi
if test -f 'demo.c'
then
echo shar: "will not over-write existing file 'demo.c'"
else
cat << \SHAR_EOF > 'demo.c'
/* :ts=8 bk=0
*
* demo.c: Demonstrates The Incredible New Iconification Program!!!!!!
*
* Leo L. Schwab 8712.10
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include "iconify.h"
#define LENGTH 20
extern void *OpenLibrary(), *OpenWindow(), *GetMsg();
extern long VBeamPos();
/* The Boing icon image */
UWORD icon[] = {
0xFFFF, 0xFFFF, 0xFFFF, 0xC000,
0x8000, 0x0, 0x0, 0x4000,
0x8000, 0x0, 0x0, 0x4000,
0x8000, 0x1DF7, 0x0, 0x4000,
0x8001, 0xFBEF, 0xB000, 0x4000,
0x800D, 0xF7DF, 0x7C00, 0x4000,
0x803B, 0xEFBE, 0xFB80, 0x4000,
0x8077, 0xDF7D, 0xF7C0, 0x4000,
0x80EF, 0xBEFB, 0xEFA0, 0x4000,
0x81DF, 0x7DF7, 0xDF70, 0x4000,
0x83BE, 0xFBEF, 0xBEF8, 0x4000,
0x837D, 0xF7DF, 0x7DF0, 0x4000,
0x82FB, 0xEFBE, 0xFBE8, 0x4000,
0x81F7, 0xDF7D, 0xF7D8, 0x4000,
0x83EF, 0xBEFB, 0xEFB8, 0x4000,
0x81DF, 0x7DF7, 0xDF70, 0x4000,
0x80BE, 0xFBEF, 0xBEE0, 0x4000,
0x807D, 0xF7DF, 0x7DC0, 0x4000,
0x803B, 0xEFBE, 0xFB80, 0x4000,
0x8007, 0xDF7D, 0xF600, 0x4000,
0x8001, 0xBEFB, 0xF000, 0x4000,
0x8000, 0x1DF7, 0x0, 0x4000,
0x8000, 0x0, 0x0, 0x4000,
0x8000, 0x0, 0x0, 0x4000,
0xFFFF, 0xFFFF, 0xFFFF, 0xC000,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x1F0, 0x0, 0x0,
0x1, 0xF860, 0x3000, 0x0,
0xC, 0x301C, 0x7C00, 0x0,
0x18, 0xE3E, 0x1800, 0x0,
0x7, 0x1F0C, 0x700, 0x0,
0xF, 0x8603, 0x8F80, 0x0,
0x1C3, 0x1C7, 0xC300, 0x0,
0x180, 0xE3E1, 0x80E0, 0x0,
0x71, 0xF0C0, 0x71F0, 0x0,
0xF8, 0x6038, 0xF860, 0x0,
0x30, 0x1C7C, 0x3018, 0x0,
0xE, 0x3E18, 0xE38, 0x0,
0x11F, 0xC07, 0x1F00, 0x0,
0x86, 0x38F, 0x8600, 0x0,
0x1, 0xC7C3, 0x1C0, 0x0,
0x3, 0xE180, 0xE380, 0x0,
0x0, 0xC071, 0xF000, 0x0,
0x0, 0x38F8, 0x7000, 0x0,
0x0, 0x1C30, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0
};
static struct Image iconimg = { /* Icon Image */
0, 0,
50, 25, 2,
icon,
0x3, 0,
NULL
};
static WORD bordbox[] = { /* A box with an X in it */
0, 0,
ICONWIDTH-1, 0,
ICONWIDTH-1, ICONHEIGHT-1,
0, ICONHEIGHT-1,
0, 0,
ICONWIDTH-1, ICONHEIGHT-1,
ICONWIDTH-1, 0,
0, ICONHEIGHT-1
};
static struct Border iconbord = { /* Icon border */
0, 0,
1, 0, JAM1,
8,
bordbox,
NULL,
};
/**************************************************************************
* Gadgets for the application's window.
*/
static WORD box[] = {
-1, -1,
48, -1,
48, 10,
-1, 10,
-1, -1
};
static struct Border bord = { /* Window gadget border */
0, 0,
1, 0, JAM1,
5,
box,
NULL,
};
static struct IntuiText text[] = {
{
1, 0, JAM1,
4, 1,
NULL,
(UBYTE *) "Image",
NULL,
}, {
1, 0, JAM1,
4, 1,
NULL,
(UBYTE *) "Bordr",
NULL,
}, {
1, 0, JAM1,
4, 1,
NULL,
(UBYTE *) "Funct",
NULL,
}
};
static struct Gadget gads[] = {
{ /* Image */
&gads[1],
0, -10, 48, 10,
GADGHCOMP | GRELBOTTOM,
RELVERIFY | BOTTOMBORDER,
BOOLGADGET,
(APTR) &bord,
NULL,
&text[0],
NULL, NULL,
ICON_IMAGE, 0
}, { /* Border */
&gads[2],
48, -10, 48, 10,
GADGHCOMP | GRELBOTTOM,
RELVERIFY | BOTTOMBORDER,
BOOLGADGET,
(APTR) &bord,
NULL,
&text[1],
NULL, NULL,
ICON_BORDER, 0
}, { /* Function */
NULL,
96, -10, 48, 10,
GADGHCOMP | GRELBOTTOM,
RELVERIFY | BOTTOMBORDER,
BOOLGADGET,
(APTR) &bord,
NULL,
&text[2],
NULL, NULL,
ICON_FUNCTION, 0
}
};
struct NewWindow windef = {
0, 0, 400, 100,
-1, -1,
CLOSEWINDOW | GADGETUP,
WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | SMART_REFRESH |
NOCAREREFRESH | ACTIVATE,
gads,
NULL,
(UBYTE *) "Click on gadgets below and be amazed!",
NULL, NULL,
0, 0, 0, 0,
WBENCHSCREEN
};
struct Window *win;
long xa1[LENGTH], xa2[LENGTH], ya1[LENGTH], ya2[LENGTH];
short rnd(); /* Forward reference */
void iconfunc(); /* Forward reference */
void *IntuitionBase, *GfxBase;
main ()
{
register struct IntuiMessage *msg;
register struct Gadget *gad;
long class;
UWORD x = 0, y = 0;
int type;
void *ptr;
openstuff ();
rnd ((int) -VBeamPos());
doline (win, 1);
while (1) {
if (msg = GetMsg (win -> UserPort)) {
class = msg -> Class;
gad = (struct Gadget *) msg -> IAddress;
ReplyMsg (msg);
if (class == CLOSEWINDOW)
break;
else {
switch (gad -> GadgetID) {
case ICON_IMAGE:
ptr = &iconimg;
break;
case ICON_BORDER:
ptr = &iconbord;
break;
case ICON_FUNCTION:
ptr = (void *) iconfunc;
break;
}
/*
* And now! The moment you've been waiting
* for!
*/
windef.LeftEdge = win -> LeftEdge;
windef.TopEdge = win -> TopEdge;
CloseWindow (win); win = NULL;
iconify (&x, &y, ICONWIDTH, ICONHEIGHT,
NULL, ptr, (int) gad -> GadgetID);
if (!(win = OpenWindow (&windef)))
die ("Window re-open failed\n");
doline (win, 1);
}
}
doline (win, 0);
WaitTOF ();
}
closestuff ();
}
doline (win, reset)
struct Window *win;
int reset;
{
register struct RastPort *rp = win -> RPort;
static long x1, x2, y1, y2, dx1, dx2, dy1, dy2;
static long xmin, ymin, xmax, ymax;
static int i, flag;
if (reset) {
xmin = win -> BorderLeft;
ymin = win -> BorderTop;
xmax = win->Width - win->BorderRight - 1;
ymax = win->Height - win->BorderBottom - 1;
x1 = rnd ((int) xmax); y1 = rnd ((int) ymax);
x2 = rnd ((int) xmax); y2 = rnd ((int) ymax);
setdisp (&dx1, &dy1);
setdisp (&dx2, &dy2);
SetDrMd (rp, COMPLEMENT);
i = flag = 0;
}
if (!rnd (20))
if (rnd (2))
setdisp (&dx1, &dy1);
else
setdisp (&dx2, &dy2);
x1 += dx1; y1 += dy1;
if (x1 > xmax || x1 < xmin) {
dx1 = -dx1;
x1 = x1<xmin ? xmin : xmax;
}
if (y1 > ymax || y1 < ymin) {
dy1 = -dy1;
y1 = y1<ymin ? ymin : ymax;
}
x2 += dx2; y2 += dy2;
if (x2 > xmax || x2 < xmin) {
dx2 = -dx2;
x2 = x2<xmin ? xmin : xmax;
}
if (y2 > ymax || y2 < ymin) {
dy2 = -dy2;
y2 = y2<ymin ? ymin : ymax;
}
Move (rp, x1, y1);
Draw (rp, x2, y2);
if (flag) {
Move (rp, xa1[i], ya1[i]);
Draw (rp, xa2[i], ya2[i]);
}
xa1[i] = x1; ya1[i] = y1;
xa2[i] = x2; ya2[i] = y2;
if (++i >= LENGTH) {
i = 0;
flag = 1;
}
}
setdisp (x, y)
register long *x, *y;
{
*x = rnd (9) - 4;
*y = rnd (9) - 4;
}
void
iconfunc (win, init)
struct Window *win;
WORD init;
{
if (init) {
/* Initialization pass, draw a border in the icon */
SetAPen (win -> RPort, 1L);
Move (win -> RPort, 0L, 0L);
Draw (win -> RPort, win -> Width - 1L, 0L);
Draw (win -> RPort, win -> Width - 1L, win -> Height - 1L);
Draw (win -> RPort, 0L, win -> Height - 1L);
Draw (win -> RPort, 0L, 0L);
doline (win, 1);
}
doline (win, 0);
}
openstuff ()
{
if (!(IntuitionBase = OpenLibrary ("intuition.library", 0L)))
die ("-=RJ=-'s missing.\n");
if (!(GfxBase = OpenLibrary ("graphics.library", 0L)))
die ("Dale, where are you?\n");
if (!(win = OpenWindow (&windef)))
die ("Window painted shut.\n");
}
closestuff ()
{
if (win) CloseWindow (win);
if (GfxBase) CloseLibrary (GfxBase);
if (IntuitionBase) CloseLibrary (IntuitionBase);
}
die (str)
char *str;
{
extern long Output();
Write (Output (), str, (long) strlen (str));
closestuff ();
exit (20);
}
/***********************************************************************/
#asm
*\
* :ts=8
* Yet Another random number generator. By Leo Schwab.
* Based on an idea posted on the USENET (Thanks, Sam Dicker!)
* For the Manx assembler.
*
* Calling convention:
* short rnd (range);
* short range;
*
* 8606.30
*/
public _rnd
_rnd lea rndseed,a0 Get address of seed
move.w 4(sp),d1 Get range argument
tst.w d1
ble.s setseed Go reset seed
move.l (a0),d0 Get seed
ADD.L D0,D0
BHI.S over
EORI.L #$1D872B41,D0
over
move.l d0,(a0) Save new seed
andi.l #$ffff,d0 Coerce into word
divu d1,d0 Divide by range
swap d0 and get remainder (modulus)
rts
setseed neg.w d1 Probably don't need this
move.l d1,(a0)
rts
dseg
rndseed dc.l 0
cseg
#endasm
SHAR_EOF
fi
exit 0
# End of shell archive