home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 377a.lha / libraries / graphics / primitives / HAMExample.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-02-04  |  12.1 KB  |  388 lines

  1. /*
  2.    Hold-And-Modify Example
  3.    For Lattice, compile and link with:  LC -b1 -cfist -L -v -y HAMExample.c
  4.  
  5.    Copyright (c) 1990 Commodore-Amiga, Inc.
  6.   
  7.    This example is provided in electronic form by Commodore-Amiga, Inc. for
  8.    use with the 1.3 revisions of the Addison-Wesley Amiga reference manuals. 
  9.    The 1.3 Addison-Wesley Amiga Reference Manual series contains additional
  10.    information on the correct usage of the techniques and operating system
  11.    functions presented in this example.  The source and executable code of
  12.    this example may only be distributed in free electronic form, via bulletin
  13.    board or as part of a fully non-commercial and freely redistributable
  14.    diskette.  Both the source and executable code (including comments) must
  15.    be included, without modification, in any copy.  This example may not be
  16.    published in printed form or distributed with any commercial product.
  17.    However, the programming techniques and support routines set forth in
  18.    this example may be used in the development of original executable
  19.    software products for Commodore Amiga computers.
  20.    All other rights reserved.
  21.    This example is provided "as-is" and is subject to change; no warranties
  22.    are made.  All use is at your own risk.  No liability or responsibility
  23.    is assumed.
  24. */
  25.  
  26. #include <exec/types.h>
  27. #include <intuition/intuitionbase.h>
  28. #include <graphics/gfxbase.h>
  29. #include <libraries/dos.h>
  30.  
  31. #include <proto/all.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <stdio.h>
  35.  
  36. #define  XSIZE 11    /* Color box sizes. */
  37. #define  YSIZE 6
  38.  
  39. struct IntuitionBase *IntuitionBase = NULL;
  40. struct GfxBase *GfxBase = NULL;
  41.  
  42. struct TextAttr textAttr =
  43. {
  44.     "topaz.font",    /* Standard system font. */
  45.     8,
  46.     0,
  47.     0
  48. };
  49.  
  50. struct Window *window = NULL;
  51. struct Screen *screen = NULL;
  52.  
  53. struct NewScreen newScreen =
  54. {
  55.     0, 0,
  56.     320, 200, 6,
  57.     0, 1,
  58.     HAM,
  59.     CUSTOMSCREEN,
  60.     &textAttr,
  61.     (UBYTE *)" 256 different colors out of",
  62.     NULL,
  63.     NULL
  64. };
  65.  
  66. struct NewWindow newWindow =
  67. {
  68.     0, 11,                    /* LeftEdge, TopEdge, */
  69.     320, 186,                 /* Width, Height, */
  70.     -1, -1,                   /* DetailPen, BlockPen, (-1 == "use Screen's") */
  71.     MOUSEBUTTONS|CLOSEWINDOW, /* IDCMPFlags, */
  72.     ACTIVATE|WINDOWCLOSE,     /* Flags, */
  73.     NULL,                     /* FirstGadget, */
  74.     NULL,                     /* CheckMark, */
  75.     (UBYTE *)"4,096 at any given moment.",    /* Title, */
  76.     NULL,                     /* Screen, */
  77.     NULL,                     /* BitMap, */
  78.     0, 0,                     /* MinWidth, MinHeight, */
  79.     320, 186,                 /* MaxWidth, MaxHeight, */
  80.     CUSTOMSCREEN              /* Type */
  81. };
  82.  
  83. #define BLACK 0x000
  84. #define RED   0xf00
  85. #define GREEN 0x0f0
  86. #define BLUE  0x00f
  87. #define WHITE 0xfff
  88.  
  89. #define COLOR0 0
  90. #define COLOR1 1
  91. #define COLOR2 2
  92. #define COLOR3 3
  93.  
  94. VOID cleanExit(LONG exitStatus);
  95. VOID hamBox(struct RastPort *rastPort, LONG color, LONG x, LONG y);
  96. VOID prompt(struct RastPort *rastPort);
  97. VOID
  98.   colorWheel(struct RastPort *rastPort, SHORT xpos[], SHORT ypos[], BOOL textneeded);
  99. VOID
  100.   colorFull(struct RastPort *rastPort, SHORT xpos[], SHORT ypos[], BOOL textneeded);
  101. extern ULONG RangeRand(ULONG);
  102.  
  103. VOID main(VOID)
  104. {
  105. BOOL wheelmode = TRUE, textneeded = TRUE;
  106. SHORT xpos[16], ypos[16];
  107. USHORT code, i;
  108. static UWORD colors[] = {BLACK, RED, GREEN, BLUE, WHITE};
  109. ULONG class;
  110. struct RastPort *rastPort;    /* Graphics structures. */
  111. struct ViewPort *viewPort;
  112. struct IntuiMessage *intuiMessage;
  113.  
  114. for(i=0; i<16; i++)     /* Establish color square positions. */
  115.     {
  116.     xpos[i] = (XSIZE + 4) * i + 20;
  117.     ypos[i] = (YSIZE + 3) * i + 21;
  118.     }
  119.  
  120. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 33L);
  121. if (IntuitionBase == NULL)
  122.     cleanExit(ERROR_INVALID_RESIDENT_LIBRARY);
  123.  
  124. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33L);
  125. if (GfxBase == NULL)
  126.     cleanExit(ERROR_INVALID_RESIDENT_LIBRARY);
  127.  
  128. screen = OpenScreen(&newScreen); 
  129. if (screen == NULL)
  130.     cleanExit(ERROR_NO_FREE_STORE);
  131.  
  132. newWindow.Screen = screen;    /* Open window in our new screen. */
  133. window = OpenWindow(&newWindow);
  134. if (window == NULL)
  135.     cleanExit(ERROR_NO_FREE_STORE);
  136.  
  137. viewPort = &(screen->ViewPort);     /* Set colors in screen's ViewPort. */
  138. rastPort = window->RPort;    /* Render into the window's RastPort. */
  139.  
  140. /*  Set the color registers:  Black, Red, Green, Blue, White. */
  141. LoadRGB4(viewPort, colors, 5L);
  142.  
  143. SetBPen(rastPort, COLOR0);    /* Insure clean text. */
  144.  
  145. /* Process any and all messages in the queue, then update the display
  146.  * colors once, then come back here to look at the queue again.  If you
  147.  * see a left-mouse-button-down event, then switch display modes.  If you
  148.  * see a Close-Window-gadget event, then clean up and exit the program.
  149.  * NOTE: This is a BUSY LOOP so the colors will cycle as quickly as possible.
  150.  */
  151. while (1)
  152.     {
  153.     while(intuiMessage=(struct IntuiMessage *)GetMsg(window->UserPort))
  154.         {
  155.          /* Can't reply until done using it! */
  156.          class = intuiMessage->Class;
  157.          code = intuiMessage->Code;
  158.          ReplyMsg((struct Message *)intuiMessage);
  159.  
  160.          if (class == CLOSEWINDOW)    /* Exit the program. */
  161.                 cleanExit(RETURN_OK);
  162.  
  163.          if (class == MOUSEBUTTONS && code == SELECTDOWN)    /* Swap modes. */
  164.              {
  165.              wheelmode = NOT wheelmode;
  166.  
  167.              SetAPen(rastPort, COLOR0);    /* Clear the drawing area. */
  168.              SetDrMd(rastPort, JAM1);
  169.              RectFill(rastPort, 3, 12, 318, 183);
  170.              textneeded = TRUE; 
  171.              }
  172.         }
  173.     if (wheelmode)
  174.         colorWheel(rastPort, xpos, ypos, textneeded);
  175.     else
  176.         colorFull(rastPort, xpos, ypos, textneeded);
  177.  
  178.     textneeded = FALSE;
  179.     }
  180. }
  181.  
  182.  
  183. /*
  184.     Display a randomized set of colors.
  185. */
  186. VOID
  187.   colorFull(struct RastPort *rastPort, SHORT xpos[], SHORT ypos[], BOOL textneeded)
  188. {
  189. SHORT usesquare;
  190. ULONG sChoice, cChoice;
  191. LONG usecolor;
  192. static SHORT sStop, cStop;
  193. static SHORT squares[16 * 16];
  194. static LONG squarecolor[16 * 16], freecolors[4096-(16*16)];
  195.  
  196. if(textneeded)    /* First call since mode change? */
  197.     {
  198.     prompt(rastPort);
  199.     sStop = 255;    /* Top of list of squares yet to change. */
  200.     cStop = 4095 - 256;    /* Top of list of colors still needing use. */
  201.  
  202.     for(usecolor=0; usecolor<256; usecolor++)    /* Initialize colors. */
  203.         {
  204.         usesquare = usecolor;
  205.         squares[usesquare] = usesquare;
  206.         squarecolor[usesquare] = usecolor;
  207.         hamBox(rastPort, usecolor, xpos[usesquare % 16], ypos[usesquare / 16]);
  208.         }
  209.  
  210.     for(usecolor=256; usecolor<4095; usecolor++)    /* Ones not yet used. */
  211.         freecolors[usecolor - 256] = usecolor;
  212.  
  213.     }
  214.  
  215. /***************************************************************************
  216. * Randomly choose next square to change such that all squares change color
  217. * at least once before any square changes twice.  squares[0] through squares
  218. * [sStop] are the square numbers that have not yet changed in this pass.
  219. * RangeRand(r) is an integer function provided in "amiga.lib" that produces
  220. * a random result in the range 0 to (r-1) given an integer r in the range 1 to 65535.
  221. **************************************************************************/
  222.  
  223. sChoice = RangeRand(sStop + 1);    /* Pick a remaining square. */
  224.  
  225. usesquare = squares[sChoice];    /* Extract square number. */
  226. squares[sChoice] = squares[sStop];    /* Swap it with sStop slot. */
  227. squares[sStop] = usesquare;
  228.  
  229. if (NOT sStop--)
  230.     sStop = 255;    /* Only one change per pass. */
  231.  
  232. /***************************************************************************
  233.  * Randomly choose new color for selected square such that all colors are
  234.  * used once before any color is used again, and such that no two squares
  235.  * simultaneously have the same color.  freecolors[0] through freecolors[cStop]
  236.  * are the colors that have not yet been chosen in this pass.  Note that
  237.  * the 256 colors in use at the end of the previous pass are not available
  238.  * for choice in this pass.
  239.  ***************************************************************************/
  240.  
  241. cChoice = RangeRand(cStop + 1);
  242.  
  243. usecolor = freecolors[cChoice];
  244. freecolors[cChoice] = freecolors[cStop];
  245. freecolors[cStop] = squarecolor[usesquare];
  246. squarecolor[usesquare] = usecolor;
  247.  
  248. if (NOT cStop--)
  249.     cStop = 4095 - 256;
  250.  
  251. hamBox(rastPort, usecolor, xpos[usesquare % 16], ypos[usesquare / 16]);
  252. }
  253.  
  254.  
  255. /*
  256.     Display an ordered set of colors.
  257. */
  258. VOID
  259.   colorWheel(struct RastPort *rastPort, SHORT xpos[], SHORT ypos[], BOOL textneeded)
  260. {
  261. SHORT  i, j;
  262. static SHORT sequence;
  263. static UBYTE  *number[] =
  264. {
  265.     "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
  266. };
  267. static UBYTE red[] = "Red", blue[] = "Blue", green[] = "Green";
  268. if(textneeded)
  269.     {
  270.     prompt(rastPort);
  271.  
  272.     SetAPen(rastPort, COLOR2);    /* Green pen for green color numbers. */
  273.     Move(rastPort, 260, ypos[15]+17);
  274.     Text(rastPort, green, strlen(green));
  275.     for(i=0; i<16; i++)
  276.         {
  277.         Move(rastPort, xpos[i]+3, ypos[15]+17);
  278.         Text(rastPort, number[i], strlen(number[i]));
  279.         }
  280.  
  281.     SetAPen(rastPort, COLOR3);    /* Blue pen for blue color numbers. */
  282.     Move(rastPort, 4, 18);
  283.     Text(rastPort, blue, strlen(blue));
  284.     for(i=0; i<16; i++)
  285.         {
  286.         Move(rastPort, 7, ypos[i]+6);
  287.         Text(rastPort, number[i], strlen(number[i]));
  288.         }
  289.  
  290.     SetAPen(rastPort, COLOR1);    /* Red pen for red color numbers. */
  291.     Move(rastPort, 271, 100);
  292.     Text(rastPort, red, strlen(red));
  293.  
  294.     sequence = 0;
  295.     }
  296.  
  297. SetAPen(rastPort, COLOR1);    /* Identify the red color in use. */
  298. SetDrMd(rastPort, JAM2);
  299. Move(rastPort, 280, 115);
  300. Text(rastPort, number[sequence], strlen(number[sequence]));
  301.  
  302. for(j=0; j<16; j++)    /* Update all of the squares. */
  303.     {
  304.     for(i=0; i<16; i++)
  305.         hamBox(rastPort, (sequence<<8 | i<<4 | j), xpos[i], ypos[j]);
  306.  
  307.     }
  308.  
  309. if (++sequence == 16)
  310.     sequence = 0;
  311. }
  312.  
  313.  
  314. /* Display mode changing prompt. */
  315. VOID  prompt(struct RastPort *rastPort)
  316. {
  317. static UBYTE text[] = "[left mouse button = new mode]";
  318.  
  319. SetDrMd(rastPort, JAM2);
  320. SetAPen(rastPort, 4);
  321. Move(rastPort, 23, 183);
  322. Text(rastPort, text, strlen(text));
  323. }
  324.  
  325.  
  326. /**********************************************************************
  327.  *  hamBox() -- routine to draw a colored box in Hold and Modify mode.  Draws a
  328.  *    box of size XSIZE by YSIZE with an upper left corner at (x,y).  The
  329.  *    desired color is achieved in 3 steps on each horizontal line of the box.
  330.  *    First we set the red component, then the green, then the blue.  We
  331.  *    achieve this by drawing a vertical line of Modify-Red, followed by a
  332.  *    vertical line of Modify-Green, followed by a rectangle of Modify-Blue.
  333.  *    Note that the resulting color for the first two vertical lines depends 
  334.  *    upon the color(s) of the pixels immediately to the left of that
  335.  *    line.  By the time we reach the rectangle we are assured of getting
  336.  *    (and maintaining) the desired color because we have set all 3
  337.  *    components (R, G, and B) straight from the bit map.
  338.  ***********************************************************************/
  339.  
  340. VOID hamBox(struct RastPort *rastPort, LONG color, LONG x, LONG y)
  341. {
  342. SHORT  c;
  343.  
  344. SetDrMd(rastPort, JAM1);    /* Establish Drawing Mode in RastPort. */
  345.  
  346. c = (color & 0xf00) >> 8;    /* Extract desired Red color component. */
  347. SetAPen(rastPort, c + 0x20);    /* Hold G, B from previous pixel.  Set R=n. */
  348. Move(rastPort, x, y);
  349. Draw(rastPort, x, y+YSIZE);
  350.  
  351. x++;
  352. c = (color & 0xf0) >> 4;    /* Extract desired Green color component. */
  353. SetAPen(rastPort, c + 0x30);    /* Hold R, B from previous pixel.  Set G=n. */
  354. Move(rastPort, x, y);
  355. Draw(rastPort, x, y+YSIZE);
  356.  
  357. x++;
  358. c = (color & 0xf);        /* Extract desired Blue color component.*/
  359. SetAPen(rastPort, c + 0x10);    /* Hold R, G from previous pixel.  Set B=n. */
  360. RectFill(rastPort, x, y, x+XSIZE-2, y+YSIZE);
  361. }
  362.  
  363.  
  364. /*
  365.     Clean up and exit.
  366. */
  367. VOID  cleanExit(LONG exitStatus)
  368. {
  369. struct IntuiMessage *intuiMessage;
  370.  
  371. if (window)
  372.     {
  373.     /* Reply to any pending IntuiMessages. */
  374.     while(intuiMessage=(struct IntuiMessage *)GetMsg(window->UserPort))
  375.         ReplyMsg((struct Message *)intuiMessage);
  376.     CloseWindow(window);
  377.     }
  378. if (screen)
  379.     CloseScreen(screen);
  380. if (GfxBase)
  381.     CloseLibrary((struct Library *)GfxBase);
  382. if (IntuitionBase)
  383.     CloseLibrary((struct Library *)IntuitionBase);
  384.  
  385. exit(exitStatus);
  386. }
  387.  
  388.