/* * Backdrop (C) Copyright Eddy Carroll 1989, may be Freely Redistributed * * Backdrop allows you to define a pattern which will then be displayed * in the empty screen area behind all the windows (who said Macintosh? :-) * * Usage: Backdrop { -a# | -b# | -f | -p# | -q | -s | B1B2B3B4B5B6B7B8} * * If no parameters are given, the default is a half tone grey pattern. * * -a or -b followed by a number sets the foreground or background colour * to the corresponding pen number (0 - 3) * * -f and -s select either a SMART_REFRESH or SIMPLE_REFRESH window to * display the backdrop pattern in. The former gives fast screen updates, * but uses up quite a bit of memory, whereas the latter uses up very * little memory but is slower at updating the screen. * * -p followed by a number selects the built in pattern corresponding to that * number. If you try and select a pattern number not available, you get * the default. * * -q kills the background copy of Backdrop currently installed, if any. * * A list of 16 hex digits will be interpreted as a user defined pattern, * which should be viewed as an 8x8 grid. * * The first time you run Backdrop, it installs itself in memory. Future * invocations of Backdrop will merely tell this first copy about any * changes in parameters, until the -q option is used to remove it. Note * that all the parameters, including window type, can be changed even * while Backdrop is currently running. * * Compiles under Lattice C V4.0 * */ #include #include #include #include #include #include #include #include #include #include #include #define tolower(c) ((c) >= 'A' && (c) <= 'Z' ? (c) + 'a' - 'A' : (c)) #define YES 1 #define NO 0 #define NUMPATS 19 /* Number of predefined patterns available */ #define REPEAT 9999 /* Special return value indicates reopen window */ #define UNSET -1 /* Indicates a parameter is currently unset */ #define htoi(c) (((c) >= 'A' ? (c) - 7 : (c)) & 0x0F) /* Hex to int */ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; ULONG BackGroundIO = 0; char usage1[] = "\ Backdrop (C) Copyright Eddy Carroll 1989, adds backdrop to Workbench screen\n", usage2[] = "\ Usage: Backdrop {-f | -p# | -q | -s | B1B2B3B4B5B6B7B8}\n\ \n\ -a# - Set foreground colour to specified pen #\n\ -b# - Set background colour to specified pen #\n", usage3[] = "\ -f - Enable fast update (uses more memory)\n\ -p# - Use specified pattern # (1-5)\n\ -q - Remove backdrop from memory\n\ -s - Enable slow update\n\ B1B2B3B4B5B6B7B8 - 16 hex digits defining an 8x8 pattern\n\ \n> "; char quit1[] = "Backdrop removed.\n"; char quit2[] = "Backdrop not installed.\n"; char Portname[] = "Backdrop"; struct Pattern { UWORD value[8]; } Patterns[] = { { 0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA }, /* Check */ { 0xFFFF,0x4040,0x4040,0x4040,0xFFFF,0x0404,0x0404,0x0404 }, /* Brick */ { 0x8888,0x0000,0x0000,0x0000,0x8888,0x0000,0x0000,0x0000 }, { 0x8888,0x0000,0x2222,0x0000,0x8888,0x0000,0x2222,0x0000 }, { 0xAAAA,0x0000,0xAAAA,0x0000,0xAAAA,0x0000,0xAAAA,0x0000 }, { 0xAAAA,0x0000,0x5555,0x0000,0xAAAA,0x0000,0x5555,0x0000 }, { 0x8888,0x2222,0x8888,0x2222,0x8888,0x2222,0x8888,0x2222 }, { 0xAAAA,0xAAAA,0x5555,0x5555,0xAAAA,0xAAAA,0x5555,0x5555 }, { 0xCCCC,0x3333,0xCCCC,0x3333,0xCCCC,0x3333,0xCCCC,0x3333 }, { 0xFFFF,0x8181,0xBDBD,0xA5A5,0xA5A5,0xBDBD,0x8181,0xFFFF }, { 0xFEFE,0x8282,0xBABA,0xAAAA,0xBABA,0x8282,0xFEFE,0x0000 }, { 0x9999,0xCCCC,0x6666,0x3333,0x9999,0xCCCC,0x6666,0x3333 }, { 0x9999,0x3333,0x6666,0xCCCC,0x9999,0x3333,0x6666,0xCCCC }, { 0x0000,0x4444,0x2828,0x1010,0x2828,0x4444,0x0000,0x0000 }, { 0x0000,0x5454,0x0202,0x5858,0x1A1A,0x4040,0x2A2A,0x0000 }, { 0xAAAA,0x4444,0xAAAA,0x0000,0xAAAA,0x4444,0xAAAA,0x0000 }, { 0xC3C3,0x6666,0x3C3C,0x1818,0x3C3C,0x6666,0xC3C3,0x8181 }, { 0xDBDB,0x6666,0x3C3C,0x9999,0x9999,0x3C3C,0x6666,0xDBDB }, { 0x6666,0xF0F0,0x9999,0x0F0F,0x6666,0xF0F0,0x9999,0x0F0F }, { 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF } }; struct MyMsgPort { struct MsgPort mp; /* A genuine message port */ struct Pattern pat; /* Current pattern */ ULONG windowflags; /* Flags for our window */ UBYTE foreground,background; /* Colours for window */ } port; typedef struct MessagePort MP; typedef struct MyMsgPort MyMP; typedef struct IntuiMessage IM; #define WINDOWFLAGS (BORDERLESS | BACKDROP) struct NewWindow nw = { 0,0, 320,200, /* Max dimensions will be filled in at run time */ 0,1, /* These colours are also filled in at run time */ REFRESHWINDOW, NULL, /* Window flags will be filled in at run time */ NULL, NULL, NULL, NULL, NULL, 0,0,0,0, WBENCHSCREEN }; /* * The start of the program. All main does is interpret the command line * parameters, and then determine whether there is already a copy of Backdrop * running or not. If there isn't, a public message port is set up for * future reference, else the other copy of Backdrop is informed of the * changes to the parameters. * */ void main(argc,argv) int argc; char *argv[]; { int quit = NO, error = NO; UWORD n,i,j; MyMP *myport; struct Task *FindTask(), *othertask; char *p; int doback(); void resloop(); BPTR stdout; stdout = Output(); /* Check to see if we are already running. If we are, initialise * contents of our local port structure with the current contents, * else initialise them to default values. */ if ((myport = (MyMP *)FindPort(Portname)) == NULL) { /* --- First time being run --- */ port.foreground = 1; /* Default pen colour */ port.background = 0; /* Default background col */ port.windowflags = SMART_REFRESH | WINDOWFLAGS; /* Window type */ port.pat = Patterns[0]; /* Default pattern */ port.mp.mp_Node.ln_Name = Portname; /* Set the port name */ port.mp.mp_SigBit = AllocSignal(-1L); /* Get signal # for port */ } else { /* --- Already running a copy --- */ port = *myport; /* Get copy of current contents */ } /* Now parse command line, updating parameters as necessary */ while (argc > 1) { if (argv[1][0] == '-') { n = atoi(&argv[1][2]); /* Get possible second parameter */ switch (tolower(argv[1][1])) { case 'a': port.foreground = n; break; case 'b': port.background = n; break; case 'p': if (n < 0 || n > NUMPATS-1) n = 0; port.pat = Patterns[n]; break; case 'q': quit = YES; break; case 'f': port.windowflags = WINDOWFLAGS | SMART_REFRESH; break; case 's': port.windowflags = WINDOWFLAGS | SIMPLE_REFRESH; break; default: error = YES; break; } } else if ((strlen(p = argv[1])) == 16) { /* Convert 16 digit hex value into pattern */ for (i = 0; i < 8; i++) { for (n = 0, j = 0; j < 2; j++,p++) { n = n<<4 | htoi(*p); } port.pat.value[i] = n<<8 | n; } } else error = YES; if (error) { Write(stdout,usage1,sizeof(usage1)); Write(stdout,usage2,sizeof(usage2)); Write(stdout,usage3,sizeof(usage3)); exit(10); } argv++; argc--; } /* Now local copy of port contains an up-to-date copy of the * current settings */ if (myport == NULL) { /* --- First time being run --- */ if (quit) { Write(stdout,quit2,sizeof(quit2)); exit(10); /* No work to do if backdrop not active already */ } Write(stdout,usage1,sizeof(usage1)); AddPort(&port); /* Make our port public */ /* Detach this process from CLI, and setup process ID in port */ if (!res("Backdrop",4,resloop,4000)) RemPort(&port); exit(0); } else { othertask = myport->mp.mp_SigTask; /* If quit, tell the other copy to quit */ if (quit) { Write(stdout,quit1,sizeof(quit1)); Signal(othertask, SIGBREAKF_CTRL_C); exit(0); } /* Else we have a new pattern to install */ Forbid(); /* Stop other copy trying to access the array */ *myport = port; /* Copy updated parameters back to global store */ Permit(); Signal(othertask, SIGBREAKF_CTRL_F); /* Force screen update */ exit(0); } } /* * This is the main loop. It just keeps looping around, until it is told * to exit (via a special return value from doback()). When it returns, * it actually is returning to AmigaDOS() which will then remove it from * the system. * */ void resloop() { port.mp.mp_SigTask = FindTask(0L); /* Set pointer to our task */ while (doback() == REPEAT) /* Do intuition stuff */ ; /* We got some kind of exit code, so clean up */ RemPort(&port); /* Kill our public port */ } /* * This routine is where all the actual work gets done. A backdrop window * is opened on the workbench screen, and filled with the current pattern. * Then it waits for messages from Intuition saying the window needs to be * refreshed, and for signals from other invocations of Backdrop. A CTRL-C * signal causes Backdrop to remove itself, and CTRL-F forces the screen * to be updated. The return value is an error code, in case some resources * couldn't be allocated (0 or 10). * */ #define OLIB(a,b) ((a = (struct a *)OpenLibrary(b,33L)) == NULL) int doback() { struct Window *win; struct RastPort *rp; struct Screen *scr; IM *msg; int err = 10, xmax, ymax,; ULONG signal,lock; if (OLIB(IntuitionBase,"intuition.library")) goto err1; if (OLIB(GfxBase,"graphics.library")) goto err2; /* Now find the maximum size for our window by peeking at the dimensions * of the Workbench screen. If no workbench screen is open, we exit. */ lock = LockIBase(0L); for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen) { if ((scr->Flags & SCREENTYPE) == WBENCHSCREEN) { xmax = scr->Width; ymax = scr->Height; break; } } UnlockIBase(lock); if (scr == NULL) goto err2; /* If couldn't find workbench screen, we fail */ nw.Width = xmax; nw.Height = ymax; nw.Flags = port.windowflags; if ((win = OpenWindow(&nw)) == NULL) goto err3; err = 0; /* Everything opened ok, so indicate no error */ rp = win->RPort; SetDrMd(rp,JAM2); SetAfPt(rp,&port.pat.value[0],3); /* Set area pattern */ #define IDCMPMASK (1<UserPort->mp_SigBit) #define CTRL_C (SIGBREAKF_CTRL_C) #define CTRL_F (SIGBREAKF_CTRL_F) while (1) { SetAPen(rp,port.foreground); SetBPen(rp,port.background); RectFill(rp,0,0,xmax,ymax); signal = Wait(CTRL_C | CTRL_F | IDCMPMASK); /* If we got a CTRL_C, break out of this loop */ if (signal & CTRL_C) break; /* Else was CTRL_F or a refresh event from Intuition */ if (signal & IDCMPMASK) { /* Flush Intuition messages */ while ((msg = (IM *)GetMsg(win->UserPort)) != NULL) ReplyMsg(msg); } /* Now check if user wants a different sort of window type */ if (nw.Flags != port.windowflags) { err = REPEAT; /* Indicate we want to reopen window */ break; } /* Else loop back to start, and force redraw of window */ } /* We get down to here if a CTRL_C is received */ err4: CloseWindow(win); err3: CloseLibrary(GfxBase); err2: CloseLibrary(IntuitionBase); err1: return(err); } /* * These definitions just stop the corresponding library routines getting * pulled in, which helps keep the code size down. */ int brk(){return(0);} void MemCleanup(){} void chkabort(){}