home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************/
- /* */
- /* SmartIcon, release 1.0 - An Intuition object iconifier for the Amiga */
- /* Copyright (c) 1988 Gauthier H. Groult */
- /* */
- /* Written in January 1988 by Gauthier H. Groult */
- /* 33, Boulevard Saint Denis, */
- /* 92400 Courbevoie */
- /* France - Europe */
- /* Tel: (16) 1 47 89 09 54 */
- /* email: mcvax!inria!litp!germinal!groult */
- /* */
- /* This source code is not in public domain, please do not distribute. */
- /* The binary program is shareaware. Read docs files for details. */
- /* */
- /***************************************************************************/
-
-
- /* */
- /* SmartIcon Tech Notes. */
- /* */
- /* The general techniques used in the program are the following: */
- /* */
- /* ° The program keeps track of what as been patched trouch a linked */
- /* list of "IconGadgets". The structure IconGadget is a superset */
- /* of the Gadget structure. The added fields contains the information */
- /* needed to reset things when cleaning up. */
- /* */
- /* ° The windows that are already opened when the program starts are */
- /* patched by scanning the Intuition window list. */
- /* */
- /* ° The windows which open *after* the program as been laoded are */
- /* patched trough a rom call trap to OpenWindow(). */
- /* */
- /* ° The windows that close *while* the program is running are */
- /* un-patched trough a rom call trap to CloseWindow(). */
- /* */
- /* ° The icon gadgets selection for any window is detected to a rom */
- /* call trap to PutMsg(). */
- /* */
- /* ° For every icon created, a program capable of un-iconifying the */
- /* window is written to the ram disk. This program is contained in */
- /* this code, under its binary form. */
- /* */
- /* ° The revealing program needs to have a pointer on the window it */
- /* must reveal. This is given to it trough the "comment" field of */
- /* the window's icon. */
- /* */
- /* ° The revealing program self-destroys it's ram-disk file before */
- /* exiting to keep things clean. */
- /* */
- /* ° The windows are hidden only by resizing and moving their layers. */
- /* */
-
- #include "exec/types.h"
- #include "graphics/gfx.h"
- #include "hardware/dmabits.h"
- #include "hardware/custom.h"
- #include "hardware/blit.h"
- #include "graphics/gfxmacros.h"
- #include "graphics/copper.h"
- #include "graphics/view.h"
- #include "graphics/gels.h"
- #include "graphics/regions.h"
- #include "graphics/clip.h"
- #include "exec/exec.h"
- #include "graphics/text.h"
- #include "graphics/gfxbase.h"
- #include "graphics/layers.h"
- #include "graphics/clip.h"
- #include "intuition/intuition.h"
- #include "intuition/intuitionbase.h"
- #include "libraries/dos.h"
- #include "workbench/workbench.h"
- #include "string.h"
- /*
- #include "proto/exec.h"
- #include "proto/intuition.h"
- #include "proto/dos.h"
- */
- #define ICONGADGET 11366
- #define MAXFILELEN 13
-
- struct IconGadget
- {
- struct IconGadget *NextIGadget;
- struct Gadget *IconGadget, *DepthGadget;
- struct Window *Window;
- struct MsgPort *ReelPort;
- ULONG Flags;
- };
-
- BOOL HooksSet;
- ULONG IconEvent;
- ULONG IconBase;
- struct GfxBase *GfxBase;
- struct IntuitionBase *IntuitionBase;
- struct LayersBase *LayersBase;
- struct MsgPort *IconPort;
- struct IconGadget AddedGadgets;
- struct Task *IconTask;
- struct Window *theSelectedWindow;
- struct FileHandle *file;
-
- extern UBYTE RevealCode[];
- extern USHORT RevealCodeSize;
- extern USHORT IconImageData[], theWindowIData[];
- extern VOID SetHooks(), CleanHooks(), DisplayWindow();
-
- struct Image IconImage =
- {
- -14,0,
- 51,10,
- 2,
- IconImageData,
- 0x0003,0x0000,
- NULL
- };
-
- struct Gadget theIconGadget =
- {
- NULL,
- -36, 0, 17, 10,
- GADGIMAGE | GRELRIGHT,
- RELVERIFY,
- BOOLGADGET,
- (APTR)&IconImage,
- NULL,
- NULL,
- NULL,
- NULL,
- ICONGADGET,
- NULL
- };
-
- struct Image theWindowImage = {
- 0,0,
- 55,20,
- 2,
- &theWindowIData[0],
- 3,0
- };
-
- struct DiskObject theWindowIcon = {
- WB_DISKMAGIC,
- WB_DISKVERSION,
-
- /* Gadget Structure */
- NULL, /* Ptr to next gadget */
- 0,0, /* Leftedge, Topedge */
- 55,20, /* Width, Height */
- GADGHBOX|GADGIMAGE, /* Flags */
- RELVERIFY|GADGIMMEDIATE, /* Activation */
- BOOLGADGET, /* Type */
- (APTR)&theWindowImage, /* Render */
- NULL, /* Select Render */
- NULL, /* Text */
- NULL,NULL,NULL,NULL, /* Exclude, Special, ID, UserData */
-
- WBTOOL, /* WBObject type */
- NULL, /* Default tool */
- NULL, /* Tool Types */
- NO_ICON_POSITION, /* Current X */
- NO_ICON_POSITION, /* Current Y */
- NULL,NULL,NULL, /* Drawer, ToolWindow, Stack */
- };
-
- VOID main(), Cleanup(), DepthGadgetsHNone(), Expurge(),
- AddIconGadget(), HideWindow(), RevealWindow(), Recover();
- VOID MyOpenWindow(), MyCloseWindow(), MyPutMsg();
- struct IconGadget *AllocIGadget(), *FindIGadget();
-
- /* Main() calls the initialisation functions (the startup window and the */
- /* library hooks); scans the Intuition window list to patch all depth */
- /* gadgets for already opened windows; and wait forever for icon messages. */
-
- VOID
- main(argc, argv)
- UBYTE argc, **argv;
- {
- UBYTE mystring[80], filename[MAXFILELEN+10], comment[20];
- ULONG mask, IconPortMsg;
- struct Screen *screen;
- struct Window *window, *iwindow;
- struct IntuiMessage *message;
-
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
- if (!GfxBase) Cleanup(10);
-
- IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 0);
- if (!IntuitionBase) Cleanup(11);
-
- LayersBase = (struct LayersBase *)OpenLibrary("layers.library", 0);
- if (!LayersBase) Cleanup(12);
-
- IconBase = OpenLibrary("icon.library",0);
- if (!IconBase) Cleanup(13);
-
- if (strcmp(argv[1],"-f")) DisplayWindow();
-
- IconTask = (struct Task *)FindTask(0);
-
- IconEvent = AllocSignal(-1);
- if (IconEvent == -1) Cleanup(21);
-
- IconPort = (struct MsgPort *)CreatePort(0, 0); /* The message port for */
- if (!IconPort) Cleanup(22); /* where icon msgs are */
- IconPortMsg = 1 << IconPort->mp_SigBit; /* posted. */
-
- SetHooks();
- HooksSet = TRUE;
-
-
- screen = IntuitionBase->FirstScreen; /* First system screen */
- while (screen)
- {
- window = screen->FirstWindow; /* First system window */
- while (window)
- {
- if (window->Title && (window->Flags & WINDOWDEPTH))
- {
- AddIconGadget(window);
- }
- window = window->NextWindow;
- }
- screen = screen->NextScreen;
- }
-
- for(;;)
- {
- mask = Wait(SIGBREAKF_CTRL_C | IconPortMsg | IconEvent);
-
- if (mask & SIGBREAKF_CTRL_C)
- Cleanup(0);
-
- if (mask & IconEvent)
- while (message=(struct IntuiMessage *)GetMsg(IconPort))
- ReplyMsg(message);
-
- if (mask & IconEvent)
- {
- Forbid();
- iwindow = theSelectedWindow;
- HideWindow(iwindow->WScreen, iwindow);
-
- strcpy(mystring, iwindow->Title);
- mystring[MAXFILELEN]=0;
- Expurge(mystring);
- sprintf(filename, "ram:%s", mystring);
-
- if (!(file = (struct FileHandle *)Open(filename, MODE_NEWFILE)))
- {
- DisplayBeep(NULL);
- RevealWindow(iwindow->WScreen, iwindow);
- }
- else
- {
- Write(file, RevealCode, RevealCodeSize);
- Close(file);
- sprintf(comment, "%ld", iwindow);
- if (!SetComment(filename, comment)) Recover(filename, iwindow);
- else if (!PutDiskObject(filename, &theWindowIcon))
- Recover(filename, iwindow);
- }
- Permit();
- }
- }
- }
-
- /* Expurge() retrieves all special caracters used by AmigaDos from */
- /* a string. This is used to purge window titles, for they are used as */
- /* the file name for the icon. */
-
- VOID
- Expurge(text)
- UBYTE *text;
- {
- while (*text)
- {
- if (*text == ':' || *text == '/' || *text == ' ')
- strcpy(text, text+1);
- else text++;
- }
- }
-
- /* This function is called when attempting to iconify fails. It just */
- /* undoes what as already be done. Its sole purpose as a function is */
- /* to evitate a "goto". */
-
- VOID
- Recover(fname, window)
- UBYTE *fname;
- struct Window *window;
- {
- DeleteFile(fname);
- DisplayBeep(NULL);
- RevealWindow(window->WScreen, window);
- }
-
- /* This function adds the new depth gadgets to a window. Dynamic */
- /* allocation is required as we use a linked list (nodes) for the */
- /* modified windows. Instead of just allocating and filling the */
- /* gadget structyre, we CopyMemQuick() it for speed. */
-
- VOID
- AddIconGadget(window)
- struct Window *window;
- {
- struct IconGadget *node;
-
- Forbid();
- node = AllocIGadget();
- node->Window = window;
- DepthGadgetsHNone(node);
-
- CopyMemQuick(&theIconGadget, node->IconGadget, sizeof(struct Gadget));
- if (window->Flags & GIMMEZEROZERO)
- node->IconGadget->GadgetType |= GZZGADGET;
-
- AddGadget(window, node->IconGadget, 0);
- RefreshGList(window->FirstGadget, window, NULL, 1);
- if (!window->UserPort) window->UserPort = IconPort;
- ModifyIDCMP(window, window->IDCMPFlags);
- Permit();
- }
-
- /* AllocIGadget(): allocates an IconGadget. IconGadgets are actually a */
- /* superset of the gadget structure. The linked list of allocated */
- /* IconGadgets is the only way we know about which windows have been */
- /* modified. */
-
- struct IconGadget
- *AllocIGadget()
- {
- struct IconGadget *node;
-
- node = (struct IconGadget *)
- AllocMem(sizeof(struct IconGadget), MEMF_CLEAR);
-
- node->NextIGadget = AddedGadgets.NextIGadget;
- AddedGadgets.NextIGadget = node;
-
- node->IconGadget = (struct Gadget *)
- AllocMem(sizeof(struct Gadget), MEMF_CLEAR);
- return(node);
- }
-
- /* DepthGadgetsHNone() changes the position and size of the original depth */
- /* gadgets so they can match the new imagery. The name of this function */
- /* doesn't discribe it's meaning, it just there for historical reasons. */
-
- VOID
- DepthGadgetsHNone(node)
- struct IconGadget *node;
- {
- struct Gadget *gadget;
- struct Window *window;
-
- window = node->Window;
- gadget = window->FirstGadget;
- while (gadget)
- {
- if (!gadget->TopEdge)
- if (gadget->LeftEdge == -28)
- {
- node->DepthGadget = gadget;
- gadget->LeftEdge = -20;
- gadget->Width = 18;
- }
- else if (gadget->LeftEdge == -52) gadget->Width = 17;
- gadget = gadget->NextGadget;
- }
- }
-
- /* HideWindow().
- /* This is the key to window iconification. This call removes the window */
- /* from the display without releasing any of it's attributes. This is */
- /* sort of a visual trick: the layer of the window is made small (one */
- /* pixel), and is moved to the lower rightmost position of the display. */
- /* Thus the window is invisible, but it keeps it's rastport, bitmap, */
- /* gadgets, etc... The only way the trick can be seen is by checking */
- /* Intuition's window list, or by using a program such as DropShadow */
- /* which highlights window levels. */
- /* This screws up with programs messing with layers, of course, but */
- /* they are pretty rare. */
- /* */
- /* One good question is: does this work the same way with screens?? */
-
- VOID
- HideWindow(screen, window)
- struct Screen *screen;
- struct Window *window;
- {
- struct Layer *layer;
- struct Layer_Info *linfo;
-
- layer = window->RPort->Layer;
- linfo = layer->LayerInfo;
-
- SizeLayer(linfo, layer, 1-window->Width, 1-window->Height);
- MoveLayer(linfo, layer,
- screen->Width - window->LeftEdge - 1,
- screen->Height - window->TopEdge - 1);
- ShowTitle(screen, TRUE);
- MakeScreen(screen);
- }
-
- /* RevealWindow() is the exact opposition of HideWindow(). It resizes and */
- /* puts back to its original position the window's layer. The nice thing */
- /* about it is that we DO NOT need to give it the position where to move */
- /* to: this is described by the window itself! */
- /* */
- /* This function is not actually called within THIS program. It's in the */
- /* code for it's a good place for it to be. It is called by the "Reveal" */
- /* program which is encoded in and written to disk by this program. */
-
- VOID
- RevealWindow(screen, window)
- struct Screen *screen;
- struct Window *window;
- {
- struct Layer *layer;
- struct Layer_Info *linfo;
-
- layer = window->RPort->Layer;
- linfo = layer->LayerInfo;
-
- MoveLayer(linfo, layer,
- window->LeftEdge - screen->Width + 1,
- window->TopEdge - screen->Height + 1);
- SizeLayer(linfo, layer, window->Width-1, window->Height-1);
- WindowToFront(window);
- }
-
- /* This where a rom call to OpenWindow() ends to. If the new window has */
- /* depth gadgets, than add an icon to it. */
-
- VOID
- MyOpenWindow(window)
- struct Window *window;
- {
- if (window && window->Title && (window->Flags & WINDOWDEPTH))
- AddIconGadget(window);
- }
-
- /* This is where a rom call to CloseWindow() comes before actually */
- /* closing the window. The jump to the rom code is done when returning */
- /* from this function (see hook.asm). */
- /* If the window has been patched, then deallocate what was ealier */
- /* given to it. */
-
- VOID
- MyCloseWindow(window)
- struct Window *window;
- {
- struct IconGadget *node, *next;
-
- Forbid();
- if (node = FindIGadget(window))
- {
- next = node->NextIGadget;
- RemoveGadget(window, next->IconGadget);
- FreeMem(next->IconGadget, sizeof(struct Gadget));
- if (window->UserPort==IconPort) window->UserPort = NULL;
- node->NextIGadget = next->NextIGadget;
- FreeMem(next, sizeof(struct IconGadget));
- }
- Permit();
- }
-
- /* MyPutMsg(). This is another trick. */
- /* How can we get the messages from the icon gadgets? The only way I */
- /* figured out is by trapping all the PutMsg() calls. Thus every time */
- /* there's a PutMsg(), you first come here. */
- /* Now we had to signal our main() that we recognized an icon gadget */
- /* message. Doing this by a PutMsg wasn't possible: as the function is */
- /* trapped, using it in the trap leads to an infinite loop. So we */
- /* use a signal. */
-
- VOID
- MyPutMsg(port, msg)
- struct MsgPort *port;
- struct IntuiMessage *msg;
- {
- if ( msg->Class == GADGETUP &&
- ((struct Gadget *)(msg->IAddress))->GadgetID == ICONGADGET )
- {
- theSelectedWindow = msg->IDCMPWindow;
- Signal(IconTask, IconEvent);
- }
- }
-
- /* FindIGadget() returns an IconGadget given a window pointer, i.e. */
- /* finds back the allocated memory from an IntuiMessage IDCMPWindow */
- /* field. */
-
- struct IconGadget
- *FindIGadget(window)
- struct Window *window;
- {
- struct IconGadget *ig;
-
- ig = &AddedGadgets;
-
- while (ig->NextIGadget)
- {
- if (ig->NextIGadget->Window == window) return(ig);
- ig = ig->NextIGadget;
- }
- return(NULL);
- }
-
- /* Cleanup() de-patches all patched windows, closes everything and leaves. */
- /* Currently called only when a "Break C" is sent to the task. */
-
- VOID
- Cleanup(code)
- UBYTE code;
- {
- struct IconGadget *node, *next;
- struct IntuiMessage *msg;
-
- if (code>11) DisplayBeep(NULL);
-
- if (HooksSet) CleanHooks();
-
- Forbid();
- node = AddedGadgets.NextIGadget;
- while (node)
- {
- next = node->NextIGadget;
- RemoveGadget(node->Window, node->IconGadget);
- node->DepthGadget->LeftEdge = -28;
- node->DepthGadget->Width = 26;
- node->DepthGadget->NextGadget->Width = 24;
- RefreshGList(node->DepthGadget, node->Window, NULL, 2);
- FreeMem(node->IconGadget, sizeof(struct Gadget));
- FreeMem(node, sizeof(struct IconGadget));
- node = next;
- }
- Permit();
-
- if (IconPort)
- {
- while(msg = (struct IntuiMessage *)GetMsg(IconPort)) ReplyMsg(msg);
- DeletePort(IconPort);
- }
- FreeSignal(IconEvent);
-
- if (IconBase) CloseLibrary(IconBase);
- if (GfxBase) CloseLibrary(GfxBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- if (LayersBase) CloseLibrary(LayersBase);
-
- exit(code);
- }
-
-