home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 260.lha / backdrop / backdrop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-06  |  11.0 KB  |  382 lines

  1. /*
  2.  * Backdrop (C) Copyright Eddy Carroll 1989, may be Freely Redistributed
  3.  *
  4.  * Backdrop allows you to define a pattern which will then be displayed
  5.  * in the empty screen area behind all the windows (who said Macintosh? :-)
  6.  *
  7.  * Usage: Backdrop { -a# | -b# | -f | -p# | -q | -s | B1B2B3B4B5B6B7B8}
  8.  *
  9.  * If no parameters are given, the default is a half tone grey pattern.
  10.  *
  11.  * -a or -b followed by a number sets the foreground or background colour
  12.  * to the corresponding pen number (0 - 3)
  13.  *
  14.  * -f and -s select either a SMART_REFRESH or SIMPLE_REFRESH window to
  15.  * display the backdrop pattern in. The former gives fast screen updates,
  16.  * but uses up quite a bit of memory, whereas the latter uses up very
  17.  * little memory but is slower at updating the screen.
  18.  *
  19.  * -p followed by a number selects the built in pattern corresponding to that
  20.  * number. If you try and select a pattern number not available, you get
  21.  * the default.
  22.  *
  23.  * -q kills the background copy of Backdrop currently installed, if any.
  24.  *
  25.  * A list of 16 hex digits will be interpreted as a user defined pattern,
  26.  * which should be viewed as an 8x8 grid.
  27.  *
  28.  * The first time you run Backdrop, it installs itself in memory. Future
  29.  * invocations of Backdrop will merely tell this first copy about any
  30.  * changes in parameters, until the -q option is used to remove it. Note
  31.  * that all the parameters, including window type, can be changed even
  32.  * while Backdrop is currently running.
  33.  *
  34.  * Compiles under Lattice C V4.0
  35.  *
  36.  */
  37.  
  38. #include <exec/types.h>
  39. #include <graphics/gfxbase.h>
  40. #include <graphics/gfxmacros.h>
  41. #include <intuition/intuition.h>
  42. #include <intuition/intuitionbase.h>
  43. #include <libraries/dos.h>
  44. #include <proto/exec.h>
  45. #include <proto/graphics.h>
  46. #include <proto/dos.h>
  47. #include <proto/intuition.h>
  48. #include <string.h>
  49.  
  50. #define tolower(c) ((c) >= 'A' && (c) <= 'Z' ? (c) + 'a' - 'A' : (c))
  51. #define YES        1
  52. #define NO        0
  53. #define NUMPATS    19        /* Number of predefined patterns available        */
  54. #define REPEAT  9999    /* Special return value indicates reopen window */
  55. #define UNSET    -1        /* Indicates a parameter is currently unset        */
  56.  
  57. #define htoi(c) (((c) - '0' - 7 * ((c) >= 'A')) & 0x0F)    /* Hex to int */
  58.  
  59. struct IntuitionBase *IntuitionBase;
  60. struct GfxBase *GfxBase;
  61. ULONG BackGroundIO = 0;
  62.  
  63. char usage1[] = "\
  64. Backdrop (C) Copyright Eddy Carroll 1989, adds backdrop to Workbench screen\n",
  65. usage2[] = "\
  66. Usage: Backdrop {-f | -p# | -q | -s | B1B2B3B4B5B6B7B8}\n\
  67. \n\
  68.         -a# - Set foreground colour to specified pen #\n\
  69.         -b# - Set background colour to specified pen #\n",
  70. usage3[] = "\
  71.         -f  - Enable fast update (uses more memory)\n\
  72.         -p# - Use specified pattern # (1-5)\n\
  73.         -q  - Remove backdrop from memory\n\
  74.         -s  - Enable slow update\n\
  75.    B1B2B3B4B5B6B7B8 - 16 hex digits defining an 8x8 pattern\n\
  76. \n> ";
  77.  
  78. char Portname[] = "Backdrop";
  79.  
  80. struct Pattern {
  81.     UWORD value[8];
  82. } Patterns[] = {
  83.     { 0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA }, /* Check */
  84.     { 0xFFFF,0x4040,0x4040,0x4040,0xFFFF,0x0404,0x0404,0x0404 }, /* Brick */
  85.     { 0x8888,0x0000,0x0000,0x0000,0x8888,0x0000,0x0000,0x0000 },
  86.     { 0x8888,0x0000,0x2222,0x0000,0x8888,0x0000,0x2222,0x0000 },
  87.     { 0xAAAA,0x0000,0xAAAA,0x0000,0xAAAA,0x0000,0xAAAA,0x0000 },
  88.     { 0xAAAA,0x0000,0x5555,0x0000,0xAAAA,0x0000,0x5555,0x0000 },
  89.     { 0x8888,0x2222,0x8888,0x2222,0x8888,0x2222,0x8888,0x2222 },
  90.     { 0xAAAA,0xAAAA,0x5555,0x5555,0xAAAA,0xAAAA,0x5555,0x5555 },
  91.     { 0xCCCC,0x3333,0xCCCC,0x3333,0xCCCC,0x3333,0xCCCC,0x3333 },
  92.     { 0xFFFF,0x8181,0xBDBD,0xA5A5,0xA5A5,0xBDBD,0x8181,0xFFFF },
  93.     { 0xFEFE,0x8282,0xBABA,0xAAAA,0xBABA,0x8282,0xFEFE,0x0000 },
  94.     { 0x9999,0xCCCC,0x6666,0x3333,0x9999,0xCCCC,0x6666,0x3333 },
  95.     { 0x9999,0x3333,0x6666,0xCCCC,0x9999,0x3333,0x6666,0xCCCC },
  96.     { 0x0000,0x4444,0x2828,0x1010,0x2828,0x4444,0x0000,0x0000 },
  97.     { 0x0000,0x5454,0x0202,0x5858,0x1A1A,0x4040,0x2A2A,0x0000 },
  98.     { 0xAAAA,0x4444,0xAAAA,0x0000,0xAAAA,0x4444,0xAAAA,0x0000 },
  99.     { 0xC3C3,0x6666,0x3C3C,0x1818,0x3C3C,0x6666,0xC3C3,0x8181 },
  100.     { 0xDBDB,0x6666,0x3C3C,0x9999,0x9999,0x3C3C,0x6666,0xDBDB },
  101.     { 0x6666,0xF0F0,0x9999,0x0F0F,0x6666,0xF0F0,0x9999,0x0F0F },
  102.     { 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF }
  103. };
  104.  
  105. struct MyMsgPort {
  106.     struct MsgPort mp;                /* A genuine message port    */
  107.     struct Pattern pat;                /* Current pattern            */
  108.     ULONG  windowflags;                /* Flags for our window        */
  109.     UBYTE  foreground,background;    /* Colours for window        */
  110. } port;
  111.  
  112. typedef struct MessagePort    MP;
  113. typedef struct MyMsgPort    MyMP;
  114. typedef struct IntuiMessage    IM;
  115.  
  116. #define WINDOWFLAGS    (BORDERLESS | BACKDROP)
  117.  
  118. struct NewWindow nw = {
  119.     0,0,
  120.     320,200,    /* Max dimensions will be filled in at run time */
  121.     0,1,        /* These colours are also filled in at run time */
  122.     REFRESHWINDOW,
  123.     NULL,    /* Window flags will be filled in at run time */
  124.     NULL, NULL,
  125.     NULL,
  126.     NULL, NULL,
  127.     0,0,0,0,
  128.     WBENCHSCREEN
  129. };
  130.  
  131. /*
  132.  * The start of the program. All main does is interpret the command line
  133.  * parameters, and then determine whether there is already a copy of Backdrop
  134.  * running or not. If there isn't, a public message port is set up for
  135.  * future reference, else the other copy of Backdrop is informed of the
  136.  * changes to the parameters.
  137.  *
  138.  */
  139.  
  140. void main(argc,argv)
  141. int argc;
  142. char *argv[];
  143. {
  144.     int quit = NO, error = NO;
  145.     UWORD n,i,j;
  146.     MyMP *myport;
  147.     struct Task *FindTask(), *othertask;
  148.     char *p;
  149.     int doback();
  150.     void resloop();
  151.     BPTR stdout;
  152.  
  153.     stdout = Output();
  154.     Write(stdout,usage1,sizeof(usage1));
  155.  
  156.     /*   Check to see if we are already running. If we are, initialise
  157.      *   contents of our local port structure with the current contents,
  158.      *   else initialise them to default values.
  159.      */
  160.  
  161.     if ((myport = (MyMP *)FindPort(Portname)) == NULL) {
  162.         /* --- First time being run --- */
  163.         port.foreground = 1;                     /* Default pen colour     */
  164.         port.background = 0;                     /* Default background col */
  165.         port.windowflags = SMART_REFRESH | WINDOWFLAGS;     /* Window type    */
  166.         port.pat = Patterns[0];                     /* Default pattern        */
  167.         port.mp.mp_Node.ln_Name = Portname;      /* Set the port name      */
  168.         port.mp.mp_SigBit = AllocSignal(-1L);     /* Get signal # for port  */
  169.     } else {
  170.         /* --- Already running a copy --- */
  171.         port = *myport;    /* Get copy of current contents */
  172.     }
  173.  
  174.     /* Now parse command line, updating parameters as necessary */
  175.  
  176.     while (argc > 1) {
  177.         if (argv[1][0] == '-') {
  178.             n = atoi(&argv[1][2]);    /* Get possible second parameter */
  179.             switch (tolower(argv[1][1])) {
  180.                 case 'a':
  181.                     port.foreground = n;
  182.                     break;
  183.                 case 'b':
  184.                     port.background = n;
  185.                     break;
  186.                 case 'p':
  187.                     if (n < 0 || n > NUMPATS-1)
  188.                         n = 0;
  189.                     port.pat = Patterns[n];
  190.                     break;
  191.                 case 'q':
  192.                     quit = YES;
  193.                     break;
  194.                 case 'f':
  195.                     port.windowflags = WINDOWFLAGS | SMART_REFRESH;
  196.                     break;
  197.                 case 's':
  198.                     port.windowflags = WINDOWFLAGS | SIMPLE_REFRESH;
  199.                     break;
  200.                 default:
  201.                     error = YES;
  202.                     break;
  203.             }
  204.         } else if ((strlen(p = argv[1])) == 16) {
  205.             /* Convert 16 digit hex value into pattern */
  206.             for (i = 0; i < 8; i++) {
  207.                 for (n = 0, j = 0; j < 2; j++,p++) {
  208.                     n = n<<4 | htoi(*p);
  209.                 }
  210.                 port.pat.value[i] = n<<8 | n;
  211.             }
  212.         } else
  213.             error = YES;
  214.  
  215.         if (error) {
  216.             Write(stdout,usage2,sizeof(usage2));
  217.             Write(stdout,usage3,sizeof(usage3));
  218.             exit(10);
  219.         }
  220.         argv++;
  221.         argc--;
  222.     }
  223.  
  224.     /*   Now local copy of port contains an up-to-date copy of the
  225.      *   current settings
  226.      */
  227.  
  228.     if (myport == NULL) {
  229.         /* --- First time being run --- */
  230.         if (quit)
  231.             exit(10);    /* No work to do if backdrop not active already */
  232.         AddPort(&port);                             /* Make our port public  */
  233.         /* Detach this process from CLI, and setup process ID in port    */
  234.         if (!res("Backdrop",4,resloop,4000))
  235.             RemPort(&port);
  236.         exit(0);
  237.     } else {
  238.         othertask = myport->mp.mp_SigTask;
  239.  
  240.         /* If quit, tell the other copy to quit */
  241.         if (quit) {
  242.             Signal(othertask, SIGBREAKF_CTRL_C);
  243.             exit(0);
  244.         }
  245.  
  246.         /* Else we have a new pattern to install */
  247.         Forbid();    /* Stop other copy trying to access the array */
  248.         *myport = port; /* Copy updated parameters back to global store */
  249.         Permit();
  250.         Signal(othertask, SIGBREAKF_CTRL_F); /* Force screen update */
  251.         exit(0);
  252.     }
  253. }
  254.  
  255. /*
  256.  * This is the main loop. It just keeps looping around, until it is told
  257.  * to exit (via a special return value from doback()). When it returns,
  258.  * it actually is returning to AmigaDOS() which will then remove it from
  259.  * the system.
  260.  *
  261.  */
  262. void resloop()
  263. {
  264.     port.mp.mp_SigTask = FindTask(0L);    /* Set pointer to our task */
  265.     while (doback() == REPEAT)         /* Do intuition stuff      */
  266.         ;
  267.     /* We got some kind of exit code, so clean up */
  268.     RemPort(&port);    /* Kill our public port  */
  269. }
  270.  
  271. /*
  272.  * This routine is where all the actual work gets done. A backdrop window
  273.  * is opened on the workbench screen, and filled with the current pattern.
  274.  * Then it waits for messages from Intuition saying the window needs to be
  275.  * refreshed, and for signals from other invocations of Backdrop. A CTRL-C
  276.  * signal causes Backdrop to remove itself, and CTRL-F forces the screen
  277.  * to be updated. The return value is an error code, in case some resources
  278.  * couldn't be allocated (0 or 10).
  279.  *
  280.  */
  281.  
  282. #define OLIB(a,b) ((a = (struct a *)OpenLibrary(b,33L)) == NULL)
  283.  
  284. int doback()
  285. {
  286.     struct Window *win;
  287.     struct RastPort *rp;
  288.     struct Screen *scr;
  289.     IM *msg;
  290.     int err = 10, xmax, ymax,;
  291.     ULONG signal,lock;
  292.  
  293.     if (OLIB(IntuitionBase,"intuition.library"))
  294.         goto err1;
  295.  
  296.     if (OLIB(GfxBase,"graphics.library"))
  297.         goto err2;
  298.  
  299.     /* Now find the maximum size for our window by peeking at the dimensions
  300.      * of the Workbench screen. If no workbench screen is open, we exit.
  301.      */
  302.     lock = LockIBase(0L);
  303.     for (scr = IntuitionBase->FirstScreen; scr; scr = scr->NextScreen) {
  304.         if ((scr->Flags & SCREENTYPE) == WBENCHSCREEN) {
  305.             xmax = scr->Width;
  306.             ymax = scr->Height;
  307.             break;
  308.         }
  309.     }
  310.     UnlockIBase(lock);
  311.  
  312.     if (scr == NULL)
  313.         goto err2;    /* If couldn't find workbench screen, we fail */
  314.  
  315.     nw.Width  = xmax;
  316.     nw.Height = ymax;
  317.     nw.Flags  = port.windowflags;
  318.  
  319.     if ((win = OpenWindow(&nw)) == NULL)
  320.         goto err3;
  321.  
  322.     err = 0;    /* Everything opened ok, so indicate no error */
  323.     rp = win->RPort;
  324.     SetDrMd(rp,JAM2);
  325.     SetAfPt(rp,&port.pat.value[0],3);    /* Set area pattern */
  326.  
  327.  
  328. #define IDCMPMASK (1<<win->UserPort->mp_SigBit)
  329. #define CTRL_C (SIGBREAKF_CTRL_C)
  330. #define CTRL_F (SIGBREAKF_CTRL_F)
  331.  
  332.     while (1) {
  333.         SetAPen(rp,port.foreground);
  334.         SetBPen(rp,port.background);
  335.         RectFill(rp,0,0,xmax,ymax);
  336.         signal = Wait(CTRL_C | CTRL_F | IDCMPMASK);
  337.  
  338.         /* If we got a CTRL_C, break out of this loop */
  339.         if (signal & CTRL_C)
  340.             break;
  341.  
  342.         /* Else was CTRL_F or a refresh event from Intuition */
  343.  
  344.         if (signal & IDCMPMASK) {
  345.             /* Flush Intuition messages */
  346.             while ((msg = (IM *)GetMsg(win->UserPort)) != NULL)
  347.                 ReplyMsg((APTR)msg);
  348.         }
  349.  
  350.         /* Now check if user wants a different sort of window type */
  351.  
  352.         if (nw.Flags != port.windowflags) {
  353.             err = REPEAT;    /* Indicate we want to reopen window */
  354.             break;
  355.         }
  356.         /* Else loop back to start, and force redraw of window */
  357.     }
  358.  
  359.     /* We get down to here if a CTRL_C is received */
  360.  
  361.     err4:
  362.         CloseWindow(win);
  363.  
  364.     err3:
  365.         CloseLibrary(GfxBase);
  366.  
  367.     err2:
  368.         CloseLibrary(IntuitionBase);
  369.  
  370.     err1:
  371.         return(err);
  372. }
  373.  
  374. /*
  375.  *   These definitions just stop the corresponding library routines getting
  376.  *   pulled in, which helps keep the code size down.
  377.  */
  378.  
  379. int brk(){return(0);}
  380. void MemCleanup(){}
  381. void chkabort(){}
  382.