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