home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / intuition / colourwindow / colourwindow.c next >
C/C++ Source or Header  |  1995-02-27  |  37KB  |  1,262 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Intuition               Amiga C Club       */
  7. /* Chapter: ColourWindow                Tulevagen 22       */
  8. /* File:    ColourWindow.c              181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-05-01                                       */
  11. /* Version: 1.10                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20. /* COLOUR WINDOW is written to be as easy as possible to use, and is   */
  21. /* fully amigaized. COLOUR WINDOW is very easy to install in your      */
  22. /* program, and I have even done an example on how to use it. The      */
  23. /* source code is full of comments to make it easier for you to change */
  24. /* something in the program.                                           */
  25. /*                                                                     */
  26. /*  III N   N FFFFF  OOO  RRRR  M   M  AAA  TTTTTTT III  OOO  N   N    */
  27. /*   I  NN  N F     O   O R   R MM MM A   A    T     I  O   O NN  N    */
  28. /*   I  N N N FFF   O   O RRRR  M M M AAAAA    T     I  O   O N N N    */
  29. /*   I  N  NN F     O   O R  R  M   M A   A    T     I  O   O N  NN    */
  30. /*  III N   N F      OOO  R   R M   M A   A    T    III  OOO  N   N    */
  31. /*                                                                     */
  32. /*  ColourWindow is the first and only true colour requester in the    */
  33. /*  Public Domain. It adjust itself to any depth (2, 4, 8, 16 or 32    */
  34. /*  colours), and can be used with high- as well as low resolution     */
  35. /*  screens. Everything is done by the rules, and this program will    */
  36. /*  return everything it has taken, and use a minimum of processing    */
  37. /*  time. It is yet another program releaced from the Amiga C Club!    */
  38. /*                                                                     */
  39. /*  result = ColourWindow( screen, title, x, y );                      */
  40. /*                                                                     */
  41. /*  result:    (UBYTE) ColourWindow will return a flag which tells     */
  42. /*             your program what has happened:                         */
  43. /*               OK      The user selected the OK gadget.              */
  44. /*               CANCEL  The user selected the CANCEL gadget.          */
  45. /*               QUIT    The user closed the window.                   */
  46. /*               ERROR   Something went wrong. (Not enough memory,     */
  47. /*                       or the x, y coordinates were too big so       */
  48. /*                       the window could not fit on the screen.)      */
  49. /*                                                                     */
  50. /*  screen:    (struct Screen *) Pointer to the screen ColourWindow    */
  51. /*             should be connected to. If you want that the user       */
  52. /*             should be able to change the colour of the Workbench    */
  53. /*             screen, set the pointer to NULL. (REMEMBER! The         */
  54. /*             Workbench screen's colours should normally only         */
  55. /*             be changed with Preferences!)                           */
  56. /*                                                                     */
  57. /*  title:     (STRPTR) Pointer to a string containing the title of    */
  58. /*             Colour Window, or NULL if you do not want any title.    */
  59. /*                                                                     */
  60. /*  x:         (SHORT) X position of Colour Window.                    */
  61. /*                                                                     */
  62. /*  y:         (SHORT) Y position of Colour Window.                    */
  63. /*                                                                     */
  64. /*                                                                     */
  65. /*  Remember to include the file "ColourWindow.h"!                     */
  66. /*                                                                     */
  67. /*  ENJOY YOUR AMIGA, AND MAKE EVERYONE ELSE ENJOY IT TOO!             */
  68. /*  Anders Bjerin                                                      */
  69.  
  70.  
  71.  
  72. #include <intuition/intuition.h>
  73. #include "ColourWindow.h"
  74.  
  75.  
  76.  
  77. /* The Intuition and Graphics library must be opened before a program */
  78. /* may call teh ColourWindow() function:                              */
  79. extern struct IntuitionBase *IntuitionBase;
  80. extern struct GfxBase *GfxBase;
  81.  
  82.  
  83.  
  84. /* Sprite Data for the three pointers we will use: */
  85.  
  86. /* 1. Pointer data: "TO" */
  87. USHORT chip pointer_to_data[36]=
  88. {
  89.   0x0000, 0x0000,
  90.  
  91.   0x0000, 0xfc00,
  92.   0x7c00, 0xfe00,
  93.   0x7c00, 0x8600,
  94.   0x7800, 0x8c00,
  95.   0x7c00, 0x8600,
  96.   0x6e00, 0x9300,
  97.   0x0700, 0x6980,
  98.   0x0380, 0x04c0,
  99.   0x01c0, 0x0260,
  100.   0x0080, 0x0140,
  101.   0x0000, 0x0080,
  102.   0x3e70, 0x0108,
  103.   0x0888, 0x0444,
  104.   0x0888, 0x0444,
  105.   0x0888, 0x0444,
  106.   0x0870, 0x0408,
  107.  
  108.   0x0000, 0x0000
  109. };
  110.  
  111. /* 2. Pointer data: "TWO" */
  112. USHORT chip pointer_two_data[36]=
  113. {
  114.   0x0000, 0x0000,
  115.  
  116.   0x0000, 0x0c30,
  117.   0x0810, 0x1c38,
  118.   0x1818, 0x2fec,
  119.   0x3ffc, 0x47e6,
  120.   0x7ffe, 0x8003,
  121.   0x3ffc, 0x4002,
  122.   0x1818, 0x27e4,
  123.   0x0810, 0x1428,
  124.   0x0000, 0x0c30,
  125.   0x0000, 0x0000,
  126.   0x0000, 0x0000,
  127.   0x0000, 0x0000,
  128.   0x0000, 0x0000,
  129.   0x0000, 0x0000,
  130.   0x0000, 0x0000,
  131.   0x0000, 0x0000,
  132.  
  133.   0x0000, 0x0000
  134. };
  135.  
  136. /* 3. Pointer data: "NORMAL" */
  137. USHORT chip pointer_normal_data[36]=
  138. {
  139.   0x0000, 0x0000,
  140.  
  141.   0x0000, 0xfc00,
  142.   0x7c00, 0xfe00,
  143.   0x7c00, 0x8600,
  144.   0x7800, 0x8c00,
  145.   0x7c00, 0x8600,
  146.   0x6e00, 0x9300,
  147.   0x0700, 0x6980,
  148.   0x0380, 0x04c0,
  149.   0x01c0, 0x0260,
  150.   0x0080, 0x0140,
  151.   0x0000, 0x0080,
  152.   0x0000, 0x0000,
  153.   0x0000, 0x0000,
  154.   0x0000, 0x0000,
  155.   0x0000, 0x0000,
  156.   0x0000, 0x0000,
  157.  
  158.   0x0000, 0x0000
  159. };
  160.  
  161.  
  162.  
  163. /* Normal Topaz font, 80 characters/line, ROM: */
  164. struct TextAttr rom_font=
  165. {
  166.   "topaz.font", /* The name of the font. */
  167.   TOPAZ_EIGHTY, /* 80 characters/line. */
  168.   FS_NORMAL,    /* Normal (plain) style. */
  169.   FPF_ROMFONT   /* ROM font. */
  170. };
  171.  
  172.  
  173.  
  174. /* PROPORTIONAL GADGET: RED */
  175.  
  176. struct IntuiText red_text=
  177. {
  178.   1,          /* FrontPen */
  179.   0,          /* BackPen */
  180.   JAM1,       /* DrawMode */
  181.   -10, 2,     /* LeftEdge */
  182.   &rom_font,  /* ITextFont */
  183.   "R",        /* IText */
  184.   NULL,       /* NextText */
  185. };
  186.  
  187. struct Image red_knob;
  188.  
  189. struct PropInfo red_info=
  190. {
  191.   AUTOKNOB|        /* Flatgs */
  192.   FREEHORIZ,
  193.   0,               /* HorizPot */
  194.   0,               /* VertPot */
  195.   MAXBODY/16,      /* HorizBody */
  196.   0,               /* VertBody */
  197.   0, 0, 0, 0, 0, 0 /* Initialized and maintained by Intuition. */
  198. };
  199.  
  200. struct Gadget red_gadget=
  201. {
  202.   NULL,             /* NextGadget */
  203.   15,               /* LeftEdge */
  204.   11,               /* TopEdge */
  205.   153,              /* Width */
  206.   11,               /* Height */
  207.   GADGHCOMP,        /* Flags */
  208.   GADGIMMEDIATE|    /* Activation */
  209.   RELVERIFY|
  210.   FOLLOWMOUSE,
  211.   PROPGADGET,       /* GadgetType */
  212.   (APTR) &red_knob, /* GadgetRender */
  213.   NULL,             /* SelectRender */
  214.   &red_text,        /* GadgetText */
  215.   0,                /* MutualExclude */
  216.   (APTR) &red_info, /* SpecialInfo */
  217.   0,                /* GadgetID */
  218.   NULL              /* UserData */
  219. };
  220.  
  221.  
  222.  
  223. /* PROPORTIONAL GADGET: GREEN */
  224.  
  225. struct IntuiText green_text=
  226. {
  227.   1,          /* FrontPen */
  228.   0,          /* BackPen */
  229.   JAM1,       /* DrawMode */
  230.   -10, 2,     /* LeftEdge */
  231.   &rom_font,  /* ITextFont */
  232.   "G",        /* IText */
  233.   NULL,       /* NextText */
  234. };
  235.  
  236. struct Image green_knob;
  237.  
  238. struct PropInfo green_info=
  239. {
  240.   AUTOKNOB|        /* Flatgs */
  241.   FREEHORIZ,
  242.   0,               /* HorizPot */
  243.   0,               /* VertPot */
  244.   MAXBODY/16,      /* HorizBody */
  245.   0,               /* VertBody */
  246.   0, 0, 0, 0, 0, 0 /* Initialized and maintained by Intuition. */
  247. };
  248.  
  249. struct Gadget green_gadget=
  250. {
  251.   &red_gadget,        /* NextGadget */
  252.   15,                 /* LeftEdge */
  253.   23,                 /* TopEdge */
  254.   153,                /* Width */
  255.   11,                 /* Height */
  256.   GADGHCOMP,          /* Flags */
  257.   GADGIMMEDIATE|      /* Activation */
  258.   RELVERIFY|
  259.   FOLLOWMOUSE,
  260.   PROPGADGET,         /* GadgetType */
  261.   (APTR) &green_knob, /* GadgetRender */
  262.   NULL,               /* SelectRender */
  263.   &green_text,        /* GadgetText */
  264.   0,                  /* MutualExclude */
  265.   (APTR) &green_info, /* SpecialInfo */
  266.   0,                  /* GadgetID */
  267.   NULL                /* UserData */
  268. };
  269.  
  270.  
  271.  
  272. /* PROPORTIONAL GADGET: BLUE */
  273.  
  274. struct IntuiText blue_text=
  275. {
  276.   1,          /* FrontPen */
  277.   0,          /* BackPen */
  278.   JAM1,       /* DrawMode */
  279.   -10, 2,     /* LeftEdge */
  280.   &rom_font,  /* ITextFont */
  281.   "B",        /* IText */
  282.   NULL,       /* NextText */
  283. };
  284.  
  285. struct Image blue_knob;
  286.  
  287. struct PropInfo blue_info=
  288. {
  289.   AUTOKNOB|        /* Flatgs */
  290.   FREEHORIZ,
  291.   0,               /* HorizPot */
  292.   0,               /* VertPot */
  293.   MAXBODY/16,      /* HorizBody */
  294.   0,               /* VertBody */
  295.   0, 0, 0, 0, 0, 0 /* Initialized and maintained by Intuition. */
  296. };
  297.  
  298. struct Gadget blue_gadget=
  299. {
  300.   &green_gadget,     /* NextGadget */
  301.   15,                /* LeftEdge */
  302.   35,                /* TopEdge */
  303.   153,               /* Width */
  304.   11,                /* Height */
  305.   GADGHCOMP,         /* Flags */
  306.   GADGIMMEDIATE|     /* Activation */
  307.   RELVERIFY|
  308.   FOLLOWMOUSE,
  309.   PROPGADGET,        /* GadgetType */
  310.   (APTR) &blue_knob, /* GadgetRender */
  311.   NULL,              /* SelectRender */
  312.   &blue_text,        /* GadgetText */
  313.   0,                 /* MutualExclude */
  314.   (APTR) &blue_info, /* SpecialInfo */
  315.   0,                 /* GadgetID */
  316.   NULL               /* UserData */
  317. };
  318.  
  319.  
  320.  
  321. /* Data for a six-letter box: */
  322.  
  323. SHORT points6[10]=
  324. {
  325.   0,   0,
  326.   52,  0,
  327.   52, 10,
  328.   0,  10,
  329.   0,   0
  330. };
  331.  
  332. struct Border box6=
  333. {
  334.   0,       /* LeftEdge */
  335.   0,       /* TopEdge */
  336.   1,       /* FrontPen */
  337.   0,       /* BackPen */
  338.   JAM1,    /* DrawMode */
  339.   5,       /* Count */
  340.   points6, /* XY */
  341.   NULL     /* NextBorder */
  342. };
  343.  
  344.  
  345.  
  346. /* Data for a four-letter box: */
  347.  
  348. SHORT points4[10]=
  349. {
  350.   0,   0,
  351.   36,  0,
  352.   36, 10,
  353.   0,  10,
  354.   0,   0
  355. };
  356.  
  357. struct Border box4=
  358. {
  359.   0,       /* LeftEdge */
  360.   0,       /* TopEdge */
  361.   1,       /* FrontPen */
  362.   0,       /* BackPen */
  363.   JAM1,    /* DrawMode */
  364.   5,       /* Count */
  365.   points4, /* XY */
  366.   NULL     /* NextBorder */
  367. };
  368.  
  369.  
  370.  
  371. /* Data for a two-letter box: */
  372.  
  373. SHORT points2[10]=
  374. {
  375.   0,   0,
  376.   20,  0,
  377.   20, 10,
  378.   0,  10,
  379.   0,   0
  380. };
  381.  
  382. struct Border box2=
  383. {
  384.   0,       /* LeftEdge */
  385.   0,       /* TopEdge */
  386.   1,       /* FrontPen */
  387.   0,       /* BackPen */
  388.   JAM1,    /* DrawMode */
  389.   5,       /* Count */
  390.   points2, /* XY */
  391.   NULL     /* NextBorder */
  392. };
  393.  
  394.  
  395.  
  396. /* BOOLEAN GADGET: SPREAD */
  397.  
  398. struct IntuiText spread_text=
  399. {
  400.   1,          /* FrontPen */
  401.   0,          /* BackPen */
  402.   JAM1,       /* DrawMode */
  403.   3, 2,       /* LeftEdge, TopEdge */
  404.   &rom_font,  /* ITextFont */
  405.   "SPREAD",   /* IText */
  406.   NULL,       /* NextText */
  407. };
  408.  
  409. struct Gadget spread_gadget=
  410. {
  411.   &blue_gadget, /* NextGadget */
  412.   195,          /* LeftEdge */
  413.   23,           /* TopEdge */
  414.   53,           /* Width */
  415.   11,           /* Height */
  416.   GADGHCOMP,    /* Flags */
  417.   RELVERIFY,    /* Activation */
  418.   BOOLGADGET,   /* GadgetType */
  419.   (APTR) &box6, /* GadgetRender */
  420.   NULL,         /* SelectRender */
  421.   &spread_text, /* GadgetText */
  422.   0,            /* MutualExclude */
  423.   NULL,         /* SpecialInfo */
  424.   0,            /* GadgetID */
  425.   NULL          /* UserData */
  426. };
  427.  
  428.  
  429.  
  430. /* BOOLEAN GADGET: EX */
  431.  
  432. struct IntuiText ex_text=
  433. {
  434.   1,          /* FrontPen */
  435.   0,          /* BackPen */
  436.   JAM1,       /* DrawMode */
  437.   3, 2,       /* LeftEdge, TopEdge */
  438.   &rom_font,  /* ITextFont */
  439.   "EX",       /* IText */
  440.   NULL,       /* NextText */
  441. };
  442.  
  443. struct Gadget ex_gadget=
  444. {
  445.   &spread_gadget, /* NextGadget */
  446.   251,            /* LeftEdge */
  447.   23,             /* TopEdge */
  448.   21,             /* Width */
  449.   11,             /* Height */
  450.   GADGHCOMP,      /* Flags */
  451.   RELVERIFY,      /* Activation */
  452.   BOOLGADGET,     /* GadgetType */
  453.   (APTR) &box2,   /* GadgetRender */
  454.   NULL,           /* SelectRender */
  455.   &ex_text,       /* GadgetText */
  456.   0,              /* MutualExclude */
  457.   NULL,           /* SpecialInfo */
  458.   0,              /* GadgetID */
  459.   NULL            /* UserData */
  460. };
  461.  
  462.  
  463.  
  464. /* BOOLEAN GADGET: COPY */
  465.  
  466. struct IntuiText copy_text=
  467. {
  468.   1,          /* FrontPen */
  469.   0,          /* BackPen */
  470.   JAM1,       /* DrawMode */
  471.   3, 2,       /* LeftEdge, TopEdge */
  472.   &rom_font,  /* ITextFont */
  473.   "COPY",     /* IText */
  474.   NULL,       /* NextText */
  475. };
  476.  
  477. struct Gadget copy_gadget=
  478. {
  479.   &ex_gadget,   /* NextGadget */
  480.   195,          /* LeftEdge */
  481.   35,           /* TopEdge */
  482.   37,           /* Width */
  483.   11,           /* Height */
  484.   GADGHCOMP,    /* Flags */
  485.   RELVERIFY,    /* Activation */
  486.   BOOLGADGET,   /* GadgetType */
  487.   (APTR) &box4, /* GadgetRender */
  488.   NULL,         /* SelectRender */
  489.   ©_text,   /* GadgetText */
  490.   0,            /* MutualExclude */
  491.   NULL,         /* SpecialInfo */
  492.   0,            /* GadgetID */
  493.   NULL          /* UserData */
  494. };
  495.  
  496.  
  497.  
  498. /* BOOLEAN GADGET: UNDO */
  499.  
  500. struct IntuiText undo_text=
  501. {
  502.   1,          /* FrontPen */
  503.   0,          /* BackPen */
  504.   JAM1,       /* DrawMode */
  505.   3, 2,       /* LeftEdge, TopEdge */
  506.   &rom_font,  /* ITextFont */
  507.   "UNDO",     /* IText */
  508.   NULL,       /* NextText */
  509. };
  510.  
  511. struct Gadget undo_gadget=
  512. {
  513.   ©_gadget, /* NextGadget */
  514.   235,          /* LeftEdge */
  515.   35,           /* TopEdge */
  516.   37,           /* Width */
  517.   11,           /* Height */
  518.   GADGHCOMP,    /* Flags */
  519.   RELVERIFY,    /* Activation */
  520.   BOOLGADGET,   /* GadgetType */
  521.   (APTR) &box4, /* GadgetRender */
  522.   NULL,         /* SelectRender */
  523.   &undo_text,   /* GadgetText */
  524.   0,            /* MutualExclude */
  525.   NULL,         /* SpecialInfo */
  526.   0,            /* GadgetID */
  527.   NULL          /* UserData */
  528. };
  529.  
  530.  
  531.  
  532. /* BOOLEAN GADGET: OK */
  533.  
  534. struct IntuiText ok_text=
  535. {
  536.   1,          /* FrontPen */
  537.   0,          /* BackPen */
  538.   JAM1,       /* DrawMode */
  539.   3, 2,       /* LeftEdge, TopEdge */
  540.   &rom_font,  /* ITextFont */
  541.   "OK",       /* IText */
  542.   NULL,       /* NextText */
  543. };
  544.  
  545. struct Gadget ok_gadget=
  546. {
  547.   &undo_gadget, /* NextGadget */
  548.   195,          /* LeftEdge */
  549.   65,           /* TopEdge */
  550.   21,           /* Width */
  551.   11,           /* Height */
  552.   GADGHCOMP,    /* Flags */
  553.   RELVERIFY,    /* Activation */
  554.   BOOLGADGET,   /* GadgetType */
  555.   (APTR) &box2, /* GadgetRender */
  556.   NULL,         /* SelectRender */
  557.   &ok_text,     /* GadgetText */
  558.   0,            /* MutualExclude */
  559.   NULL,         /* SpecialInfo */
  560.   0,            /* GadgetID */
  561.   NULL          /* UserData */
  562. };
  563.  
  564.  
  565.  
  566. /* BOOLEAN GADGET: CANCEL */
  567.  
  568. struct IntuiText cancel_text=
  569. {
  570.   1,          /* FrontPen */
  571.   0,          /* BackPen */
  572.   JAM1,       /* DrawMode */
  573.   3, 2,       /* LeftEdge, TopEdge */
  574.   &rom_font,  /* ITextFont */
  575.   "CANCEL",   /* IText */
  576.   NULL,       /* NextText */
  577. };
  578.  
  579. struct Gadget cancel_gadget=
  580. {
  581.   &ok_gadget,   /* NextGadget */
  582.   219,          /* LeftEdge */
  583.   65,           /* TopEdge */
  584.   53,           /* Width */
  585.   11,           /* Height */
  586.   GADGHCOMP,    /* Flags */
  587.   RELVERIFY,    /* Activation */
  588.   BOOLGADGET,   /* GadgetType */
  589.   (APTR) &box6, /* GadgetRender */
  590.   NULL,         /* SelectRender */
  591.   &cancel_text, /* GadgetText */
  592.   0,            /* MutualExclude */
  593.   NULL,         /* SpecialInfo */
  594.   0,            /* GadgetID */
  595.   NULL          /* UserData */
  596. };
  597.  
  598.  
  599.  
  600. /* Declare and initialize the ColourWindow data structure: */
  601. struct NewWindow colour_window_data=
  602. {
  603.   0,             /* LeftEdge    x position, will be changed.             */
  604.   0,             /* TopEdge     y position, will be cahnged.             */
  605.   277,           /* Width       277 pixels wide.                         */
  606.   80,            /* Height      80 lines high.                           */
  607.   0,             /* DetailPen   Text should be drawn with col. reg. 0    */
  608.   1,             /* BlockPen    Blocks should be drawn with col. reg. 1  */
  609.   MOUSEMOVE|     /* IDCMPFlags  Report when: 1. The mouse moves          */
  610.   MOUSEBUTTONS|  /*                          2. Buttons are pressed      */
  611.   GADGETDOWN|    /*                          3. Gadgets down             */
  612.   GADGETUP|      /*                          4. Gadgets up               */
  613.   CLOSEWINDOW,   /*                          5. Window is closed.        */
  614.   SMART_REFRESH| /* Flags       Intuition should refresh the window.     */
  615.   WINDOWDRAG|    /*             Special gadgets: Window Drag             */
  616.   WINDOWDEPTH|   /*                              Depth Gadgets           */
  617.   WINDOWCLOSE|   /*                              Close Gadget            */
  618.   ACTIVATE|      /*             The window should be activated.          */
  619.   RMBTRAP,       /*             No menu operations.                      */
  620.   &cancel_gadget,/* FirstGadget Pointer to the first gadget.             */
  621.   NULL,          /* CheckMark   Use Intuition's default CheckMark.       */
  622.   NULL,          /* Title       Title of the window, will be changed.    */
  623.   NULL,          /* Screen      Pointer to the screen, will be changewd. */
  624.   NULL,          /* BitMap      No Custom BitMap.                        */
  625.   0,             /* MinWidth    We do not need to care about these since */
  626.   0,             /* MinHeight   we have not supplied the window with a   */
  627.   0,             /* MaxWidth    Sizing Gadget.                           */
  628.   0,             /* MaxHeight                                            */
  629.   WBENCHSCREEN   /* Type        Connected to the WBS, will be changed.   */
  630. };
  631.  
  632.  
  633.  
  634. /* Declare the functions we are going to use: */
  635. UBYTE ColourWindow();
  636. void Box();
  637. void PrintValues();
  638. void IntToStr2();
  639. void DrawScale();
  640. void DrawColourBoxes();
  641. void SelectColour();
  642. void FixProp();
  643. void Spread();
  644.  
  645.  
  646.  
  647. UBYTE ColourWindow( screen, title, x, y )
  648. struct Screen *screen;
  649. STRPTR title;
  650. SHORT x, y;
  651. {
  652.   UBYTE count; /* How many colours: 2, 4, 8, 16 or 32. */
  653.   UBYTE loop;  /* Used in loops.                       */
  654.  
  655.   UBYTE order = WORKING; /* WORKING, CANCEL, QUIT or OK.     */
  656.   UBYTE mode = NOTHING;  /* NOTHING, COPY, EXCHANGE, SPREAD. */
  657.  
  658.   /* Intuition message:                                        */
  659.   ULONG class;          /* IDCMP flag.                         */
  660.   USHORT code;          /* Extra information. (SELECTDOWN)     */
  661.   SHORT mousex, mousey; /* Mouse position.                     */
  662.   APTR address;         /* Pointer to the broadcasting gadget. */
  663.  
  664.   /* Pointer to the message structure: */
  665.   struct IntuiMessage *my_message;
  666.  
  667.   UBYTE red, green, blue; /* RGB colour values. */
  668.  
  669.   /* If the prop. gadgets need to be refreshed: */
  670.   BOOL refresh_red = FALSE;
  671.   BOOL refresh_green = FALSE;
  672.   BOOL refresh_blue = FALSE;
  673.  
  674.   UBYTE rgb1[32][3]; /* Master backup of the colour values.        */
  675.   UBYTE rgb2[32][3]; /* Backup of the colour values. Used by "UNDO". */
  676.  
  677.   UBYTE colour = 0;     /* Colour register we are working with.  */
  678.   UBYTE old_colour = 0; /* Colour register we worked with.       */
  679.   UWORD *colour_table;  /* Pointer to the screen's colour table. */
  680.  
  681.   struct Window *colour_window; /* Pointer to the ColourWindow. */
  682.  
  683.  
  684.  
  685.   /* Before we open the window we need to set the last values in the */
  686.   /* colour_window_data structure:                                   */
  687.  
  688.   if( screen ) /* Check if we are going to use a CUSTOM screen. */
  689.   {
  690.     colour_window_data.Screen = screen;
  691.     colour_window_data.Type = CUSTOMSCREEN;
  692.   }
  693.   
  694.   colour_window_data.Title = title; /* Set the title of the window. */
  695.  
  696.   colour_window_data.LeftEdge = x; /* Set the x and y position of the */
  697.   colour_window_data.TopEdge = y;  /* ColourWindow.                   */
  698.  
  699.  
  700.  
  701.   /* Open the window: */
  702.   colour_window = (struct Window *) OpenWindow( &colour_window_data );
  703.   
  704.   if(colour_window == NULL)
  705.     return( ERROR ); /* Could NOT open the Window! */
  706.  
  707.  
  708.  
  709.   /* If we do not have a pointer to a screen, we look in the Window */
  710.     /* structure to find the pointer to the Workbench Screen:         */
  711.     if( screen == NULL )
  712.       screen = colour_window->WScreen; 
  713.  
  714.   /* Find the colour table: */
  715.   colour_table = (UWORD *) screen->ViewPort.ColorMap->ColorTable;
  716.  
  717.  
  718.  
  719.   /* Change the pointer: "normal" */
  720.   SetPointer( colour_window, pointer_normal_data, 16, 16, -1, -1 );
  721.  
  722.  
  723.  
  724.   /* Update the prop. gadgets values: */
  725.   FixProp( colour_table, colour, colour_window );
  726.  
  727.   /* Draw the colour boxes: */
  728.   DrawColourBoxes( screen->BitMap.Depth, colour_window->RPort );
  729.   /* Select a colour (colour register 0): */
  730.   SelectColour( screen->BitMap.Depth, colour_window->RPort,
  731.                 colour, old_colour );
  732.  
  733.   /* Prepare the pencisl, and drawing modes: */
  734.   SetAPen( colour_window->RPort, 1 );
  735.   SetBPen( colour_window->RPort, 0 );
  736.   SetDrMd( colour_window->RPort, JAM2 );
  737.  
  738.   Box( colour_window->RPort, 171, 11, 191, 21 ); /* Box for R's values. */
  739.   Box( colour_window->RPort, 171, 23, 191, 33 ); /* Box for G's values. */
  740.   Box( colour_window->RPort, 171, 35, 191, 45 ); /* Box for B's values. */
  741.   Box( colour_window->RPort, 195, 11, 271, 21 ); /* Box for selected c. */
  742.  
  743.   /* Draw the scale under the prop. gadget: */
  744.   DrawScale( colour_window->RPort );
  745.  
  746.   /* Initialize the RGB values, corresponding to the prop. gadgets: */
  747.   red = red_info.HorizPot / (float)MAXPOT * 15 + 0.5;
  748.   green = green_info.HorizPot / (float) MAXPOT * 15 + 0.5;
  749.   blue = blue_info.HorizPot / (float) MAXPOT * 15 + 0.5;
  750.  
  751.   /* Print the RGB values: */
  752.   PrintValues( colour_window->RPort, red, green, blue );
  753.  
  754.   /* Calculate how many colours, 2, 4, 8, 16 or 32: */
  755.   count = 1 << screen->BitMap.Depth;
  756.  
  757.   /* Make a backup and a master back up of the screen's colour table: */
  758.   for( loop = 0; loop < count; loop++ )
  759.   {
  760.     /* Master back up: (Used if the user selects the CANCEL or */
  761.     /* CLOSEWINDOW gadgets)                                    */
  762.     rgb1[ loop ][ 0 ] = (colour_table[ loop ] & 0xF00) >> 8;
  763.     rgb1[ loop ][ 1 ] = (colour_table[ loop ] & 0x0F0) >> 4;
  764.     rgb1[ loop ][ 2 ] = colour_table[ loop ] & 0x00F;
  765.  
  766.     /* Back up: (Used if the user selects the UNDO gadget. Only the */
  767.     /* last change will be corrected.)                              */
  768.     rgb2[ loop ][ 0 ] = rgb1[ loop ][ 0 ];
  769.     rgb2[ loop ][ 1 ] = rgb1[ loop ][ 1 ];
  770.     rgb2[ loop ][ 2 ] = rgb1[ loop ][ 2 ];
  771.   }
  772.  
  773.  
  774.  
  775.   /* Stay in the while loop until the user has selected the CLOSEWINDOW, */
  776.   /* CANCEL or OK gadget:                                                */
  777.   while( order == WORKING )
  778.   {
  779.     /* Wait until we have recieved a message: */
  780.     /* As long as the user does not work with the Colour Window, the   */
  781.     /* CPU can work undisturbed with other tasks. I wish more programs */
  782.     /* used this function...                                           */
  783.     Wait( 1 << colour_window->UserPort->mp_SigBit );
  784.  
  785.     /* We have now recieved one or more messages. */
  786.  
  787.     /* Since we may recieve several messages we stay in the while loop  */
  788.     /* and collect, save, reply and execute the messages until there is */
  789.     /* a pause:                                                         */
  790.     while( my_message = (struct IntuiMessage *)
  791.            GetMsg( colour_window->UserPort) )
  792.     {
  793.       /* Save some important values:                              */
  794.       class = my_message->Class;      /* IDCMP flag.              */
  795.       code = my_message->Code;        /* Extra information.       */
  796.       mousex = my_message->MouseX;    /* X position of the mouse. */
  797.       mousey = my_message->MouseY;    /* Y position of the mouse. */
  798.       address = my_message->IAddress; /* Pointer to the gadget.   */
  799.  
  800.       /* After we have read the message we reply as fast as possible: */
  801.       /* REMEMBER! Do never try to read a message after you have      */
  802.       /* replied! Some other process has maybe changed it.            */
  803.       ReplyMsg( my_message );
  804.  
  805.       /* Check which IDCMP flag was sent: */
  806.       switch( class )
  807.       {
  808.         case MOUSEBUTTONS:
  809.           /* The user clicked inside the ColourWindow. */
  810.           
  811.           /* Change the pointer: "normal" */
  812.           SetPointer( colour_window, pointer_normal_data,
  813.                       16, 16, -1, -1 );
  814.  
  815.           /* Check if the left mouse button was pressed: */
  816.           if( code == SELECTDOWN )
  817.           {
  818.             old_colour = colour;
  819.             colour = ReadPixel( colour_window->RPort, mousex, mousey );
  820.             
  821.             if( colour != old_colour )
  822.             {
  823.               /* A new colour was selected. */
  824.               
  825.               /* Make a backup of the colour table: */
  826.               for( loop = 0; loop < count; loop++ )
  827.               {
  828.                 rgb2[ loop ][ 0 ] = (colour_table[ loop ] & 0xF00) >> 8;
  829.                 rgb2[ loop ][ 1 ] = (colour_table[ loop ] & 0x0F0) >> 4;
  830.                 rgb2[ loop ][ 2 ] = colour_table[ loop ] & 0x00F;
  831.               }
  832.          
  833.               switch( mode )
  834.               {
  835.                 case COPY:
  836.                   SetRGB4( &screen->ViewPort, colour, red, green, blue );
  837.                   break;
  838.                   
  839.                 case EXCHANGE:
  840.                   SetRGB4( &screen->ViewPort, old_colour,
  841.                          (colour_table[ colour ] & 0xF00) >> 8,
  842.                          (colour_table[ colour ] & 0x0F0) >> 4,
  843.                          colour_table[ colour ] & 0x00F );
  844.                   SetRGB4( &screen->ViewPort, colour, red, green, blue );
  845.                   break;
  846.               
  847.                 case SPREAD:
  848.                   Spread( colour, old_colour, colour_table,
  849.                           &screen->ViewPort );
  850.                   break;
  851.               }         
  852.               
  853.               /* Select the new colour: */
  854.               SelectColour( screen->BitMap.Depth,
  855.                             colour_window->RPort,
  856.                             colour, old_colour );
  857.  
  858.               /* Show the new colour in the colour box: */
  859.               SetAPen( colour_window->RPort, colour );
  860.               RectFill( colour_window->RPort, 196, 12, 270, 20 );
  861.               SetAPen( colour_window->RPort, 1 );
  862.  
  863.               /* Update the prop. gadgets: */
  864.               FixProp( colour_table, colour, colour_window );
  865.             }
  866.             /* Change mode to NOTHING: */
  867.             mode = NOTHING;
  868.           }
  869.           break;
  870.         
  871.         case GADGETDOWN:
  872.           /* One of the prop. gadgets have been selected. */
  873.           /* Change mode to NOTHING: */
  874.           mode = NOTHING;
  875.           /* Change the pointer: "two arrows" */
  876.           SetPointer( colour_window, pointer_two_data,
  877.                       16, 16, -8, -5 );
  878.           break;
  879.         
  880.         case GADGETUP:
  881.           /* The user has released a gadget. */
  882.           /* Change mode to NOTHING: */
  883.           mode = NOTHING;
  884.           SetPointer( colour_window, pointer_normal_data,
  885.           /* Change the pointer: "normal" */
  886.                     16, 16, -1, -1 );
  887.           
  888.           if( address == (APTR) &red_gadget )
  889.             refresh_red = TRUE;
  890.           
  891.           if( address == (APTR) &green_gadget )
  892.             refresh_green = TRUE;
  893.           
  894.           if( address == (APTR) &blue_gadget )
  895.             refresh_blue = TRUE;
  896.           
  897.           if( address == (APTR) ©_gadget )
  898.           {
  899.             /* Change the pointer: "TO" */
  900.             SetPointer( colour_window, pointer_to_data,
  901.                         16, 16, -1, -1 );
  902.             
  903.             /* Change mode to COPY: */
  904.             mode = COPY;
  905.           }
  906.           
  907.           if( address == (APTR) &ex_gadget )
  908.           {
  909.             /* Change the pointer: "TO" */
  910.             SetPointer( colour_window, pointer_to_data,
  911.                         16, 16, -1, -1 );
  912.             
  913.             /* Change mode to COPY: */
  914.             mode = EXCHANGE;
  915.           }
  916.           
  917.           if( address == (APTR) &spread_gadget )
  918.           {
  919.             /* Change the pointer: "TO" */
  920.             SetPointer( colour_window, pointer_to_data,
  921.                         16, 16, -1, -1 );
  922.             
  923.             /* Change mode to SPREAD: */
  924.             mode = SPREAD;
  925.           }
  926.           
  927.           if( address == (APTR) &undo_gadget )
  928.           {
  929.             /* Restore the colours. Use the normal backup: */
  930.             for( loop = 0; loop < count; loop++ )
  931.               SetRGB4( &screen->ViewPort, loop, rgb2[ loop ][ 0 ],
  932.                        rgb2[ loop ][ 1 ], rgb2[ loop ][ 2 ] );
  933.  
  934.             /* Update the prop. gadgets: */
  935.             FixProp( colour_table, colour, colour_window );
  936.           }
  937.           
  938.           if( address == (APTR) &ok_gadget )
  939.             order = OK;
  940.           
  941.           if( address == (APTR) &cancel_gadget )
  942.             order = CANCEL;
  943.           
  944.           break;
  945.  
  946.         case CLOSEWINDOW:
  947.           /* The user has selected the Close window gadget. */
  948.           order = QUIT;
  949.           break;
  950.       }
  951.     }
  952.     
  953.     /* Calculate the new RGB values with the prop. gadg. values: */
  954.     red = red_info.HorizPot / (float)MAXPOT * 15 + 0.5;
  955.     green = green_info.HorizPot / (float) MAXPOT * 15 + 0.5;
  956.     blue = blue_info.HorizPot / (float) MAXPOT * 15 + 0.5;
  957.  
  958.     /* Change the colour: */
  959.     SetRGB4( &screen->ViewPort, colour, red, green, blue );
  960.     
  961.     if( refresh_red )
  962.     {
  963.       ModifyProp( &red_gadget, colour_window, NULL, red_info.Flags,
  964.                   (USHORT) (red / (float) 15 * MAXPOT), 0,
  965.                   red_info.HorizBody, 0 );
  966.       refresh_red = FALSE;
  967.     }
  968.     
  969.     if( refresh_green )
  970.     {
  971.       ModifyProp( &green_gadget, colour_window, NULL, green_info.Flags,
  972.                   (USHORT) (green / (float) 15 * MAXPOT), 0,
  973.                   green_info.HorizBody, 0 );
  974.       refresh_green = FALSE;
  975.     }
  976.     
  977.     if( refresh_blue )
  978.     {
  979.       ModifyProp( &blue_gadget, colour_window, NULL, blue_info.Flags,
  980.                   (USHORT) (blue / (float) 15 * MAXPOT), 0,
  981.                   blue_info.HorizBody, 0 );
  982.       refresh_blue = FALSE;
  983.     }
  984.     
  985.     /* Print the new values in the RGB value boxes: */
  986.     PrintValues( colour_window->RPort, red, green, blue );
  987.   }
  988.  
  989.  
  990.  
  991.   /* If the user has selected the CANCEL or CLOSEWINDOW gadget we will */
  992.   /* Restore the colours by using the master backup:                   */
  993.   if( order == QUIT || order == CANCEL )
  994.     for( loop = 0; loop < count; loop++ )
  995.        SetRGB4( &screen->ViewPort, loop, rgb1[ loop ][ 0 ],
  996.                 rgb1[ loop ][ 1 ], rgb1[ loop ][ 2 ] );
  997.  
  998.  
  999.  
  1000.   /* Close the ColourWindow and return the control to the calling prog: */
  1001.   CloseWindow( colour_window );
  1002.   return( order );
  1003. }
  1004.  
  1005.  
  1006.  
  1007. /* This function will draw a box with help of four coordinates: */ 
  1008. void Box( rp, x1, y1, x2, y2 )
  1009. struct RastPort *rp;
  1010. UWORD x1, y1, x2, y2;
  1011. {
  1012.   Move( rp, x1, y1 );
  1013.   Draw( rp, x2, y1 );
  1014.   Draw( rp, x2, y2 );
  1015.   Draw( rp, x1, y2 );
  1016.   Draw( rp, x1, y1 );
  1017. }
  1018.  
  1019.  
  1020.  
  1021. /* This function will print the RGB values: */
  1022. void PrintValues( rp, red, green, blue )
  1023. struct RastPort *rp;
  1024. UBYTE red, green, blue;
  1025. {
  1026.   char colour_string[7];
  1027.  
  1028.   /* RED: */
  1029.   IntToStr2( colour_string, red );
  1030.   Move( rp, 174, 19 );
  1031.   Text( rp, colour_string, 2 );
  1032.  
  1033.   /* GREEN: */
  1034.   IntToStr2( colour_string, green );
  1035.   Move( rp, 174, 31 );
  1036.   Text( rp, colour_string, 2 );
  1037.  
  1038.   /* BLUE: */
  1039.   IntToStr2( colour_string, blue );
  1040.   Move( rp, 174, 43 );
  1041.   Text( rp, colour_string, 2 );
  1042. }
  1043.  
  1044.  
  1045.  
  1046. /* This function will shange a two dig. integer into a string: */
  1047. void IntToStr2( string, number )
  1048. STRPTR string;
  1049. int number;
  1050. {
  1051.   stci_d( string, number );
  1052.   if( number < 10 )
  1053.   {
  1054.     string[1] = string[0];
  1055.     string[0] = ' ';
  1056.   }
  1057. }
  1058.  
  1059.  
  1060.  
  1061. /* This function will draw the scale under the prop. gadgets: */
  1062. void DrawScale( rp )
  1063. struct RastPort *rp;
  1064. {
  1065.   int loop;
  1066.   
  1067.   for( loop=0; loop < 17; loop++ )
  1068.   {
  1069.     Move( rp, 19 + loop * 9, 48 );
  1070.     Draw( rp, 19 + loop * 9, 50 + (loop % 2 ? 0 : 2) );
  1071.   }
  1072. }
  1073.  
  1074.  
  1075.  
  1076. /* This function will draw the colour boxes at the bottom of the window: */
  1077. void DrawColourBoxes( depth, rp )
  1078. UBYTE depth;
  1079. struct RastPort *rp;
  1080. {
  1081.   int loop1, loop2;
  1082.   
  1083.   switch( depth )
  1084.   {
  1085.     case 5: for( loop1 = 0; loop1 < 2; loop1++ )
  1086.               for( loop2 = 0; loop2 < 16; loop2++ )
  1087.               {
  1088.                 SetAPen( rp, loop1*16+loop2 );
  1089.                 RectFill( rp, 6+11*loop2, 57+10*loop1,
  1090.                               15+11*loop2, 65+10*loop1 );
  1091.               }
  1092.               break;
  1093.               
  1094.     case 4: for( loop1 = 0; loop1 < 16; loop1++ )
  1095.             {
  1096.               SetAPen( rp, loop1 );
  1097.               RectFill( rp, 6+11*loop1, 57,
  1098.                             15+11*loop1, 75 );
  1099.             }
  1100.             break;
  1101.             
  1102.     case 3: for( loop1 = 0; loop1 < 8; loop1++ )
  1103.             {
  1104.               SetAPen( rp, loop1 );
  1105.               RectFill( rp, 6+22*loop1, 57,
  1106.                             26+22*loop1, 75 );
  1107.             }
  1108.             break;
  1109.             
  1110.     case 2: for( loop1 = 0; loop1 < 4; loop1++ )
  1111.             {
  1112.               SetAPen( rp, loop1 );
  1113.               RectFill( rp, 6+44*loop1, 57,
  1114.                             48+44*loop1, 75 );
  1115.             }
  1116.             break;
  1117.             
  1118.     case 1: for( loop1 = 0; loop1 < 2; loop1++ )
  1119.             {
  1120.               SetAPen( rp, loop1 );
  1121.               RectFill( rp, 6+88*loop1, 57,
  1122.                             92+88*loop1, 75 );
  1123.             }
  1124.   }
  1125. }
  1126.  
  1127.  
  1128.  
  1129. /* This function will draw a box around the selected colour: */
  1130. void SelectColour( depth, rp, colour, old_colour )
  1131. UBYTE depth;
  1132. struct RastPort *rp;
  1133. UBYTE colour, old_colour;
  1134. {
  1135.   switch( depth )
  1136.   {
  1137.     case 5: SetAPen( rp, 0 );
  1138.             if( old_colour < 16 )
  1139.               Box( rp, 5+11*old_colour, 56, 16+11*old_colour, 66 );
  1140.             else
  1141.               Box( rp, 5+11*(old_colour-16), 66,
  1142.                        16+11*(old_colour-16), 76 );
  1143.             
  1144.             SetAPen( rp, 1 );
  1145.             if( colour < 16 )
  1146.               Box( rp, 5+11*colour, 56, 16+11*colour, 66 );
  1147.             else
  1148.               Box( rp, 5+11*(colour-16), 66,
  1149.                        16+11*(colour-16), 76 );
  1150.             break;
  1151.  
  1152.     case 4: SetAPen( rp, 0 );
  1153.             Box( rp, 5+11*old_colour, 56, 16+11*old_colour, 76 );
  1154.             SetAPen( rp, 1 );
  1155.             Box( rp, 5+11*colour, 56, 16+11*colour, 76 );
  1156.             break;
  1157.  
  1158.     case 3: SetAPen( rp, 0 );
  1159.             Box( rp, 5+22*old_colour, 56, 27+22*old_colour, 76 );
  1160.             SetAPen( rp, 1 );
  1161.             Box( rp, 5+22*colour, 56, 27+22*colour, 76 );
  1162.             break;
  1163.  
  1164.     case 2: SetAPen( rp, 0 );
  1165.             Box( rp, 5+44*old_colour, 56, 49+44*old_colour, 76 );
  1166.             SetAPen( rp, 1 );
  1167.             Box( rp, 5+44*colour, 56, 49+44*colour, 76 );
  1168.             break;
  1169.  
  1170.     case 1: SetAPen( rp, 0 );
  1171.             Box( rp, 5+88*old_colour, 56, 93+88*old_colour, 76 );
  1172.             SetAPen( rp, 1 );
  1173.             Box( rp, 5+88*colour, 56, 93+88*colour, 76 );
  1174.             break;
  1175.   }
  1176. }
  1177.  
  1178.  
  1179.  
  1180. /* This function will update the prop. gadgets: */
  1181. void FixProp( colour_table, colour, window )
  1182. UWORD *colour_table;
  1183. UBYTE colour;
  1184. struct Window *window;
  1185. {
  1186.   UBYTE red, green, blue;
  1187.  
  1188.   red = (colour_table[ colour ] & 0xF00) >> 8;
  1189.   green = (colour_table[ colour ] & 0x0F0) >> 4;
  1190.   blue = colour_table[ colour ] & 0x00F;
  1191.  
  1192.   ModifyProp( &red_gadget, window, NULL,
  1193.               red_info.Flags,
  1194.               (USHORT) (red / (float) 15 * MAXPOT), 0,
  1195.               red_info.HorizBody, 0 );
  1196.   ModifyProp( &green_gadget, window, NULL,
  1197.               green_info.Flags,
  1198.               (USHORT) (green / (float) 15 * MAXPOT), 0,
  1199.               green_info.HorizBody, 0 );
  1200.   ModifyProp( &blue_gadget, window, NULL,
  1201.               blue_info.Flags,
  1202.               (USHORT) (blue / (float) 15 * MAXPOT), 0,
  1203.               blue_info.HorizBody, 0 );
  1204. }
  1205.  
  1206.  
  1207.  
  1208. /* This function will calculate the colour values between the new and */
  1209. /* the old colour reg:                                                */
  1210. void Spread( col, old_col, colour_table, vp )
  1211. UBYTE col, old_col;
  1212. UWORD *colour_table;
  1213. struct ViewPort *vp;
  1214. {
  1215.   UBYTE c1, c2, dif;
  1216.   UBYTE r1, g1, b1;
  1217.   UBYTE r2, g2, b2;
  1218.   float dr, dg, db;
  1219.   float fr, fg, fb;
  1220.   UBYTE loop;
  1221.  
  1222.  
  1223.   c1 = col > old_col ? old_col: col; /* Lowest reg.  */
  1224.   c2 = col > old_col ? col: old_col; /* Highest reg. */
  1225.   dif = c2 - c1;                     /* Difference.  */
  1226.   
  1227.   /* Get the RGB values: */
  1228.   r1 = (colour_table[ c1 ] & 0xF00) >> 8;
  1229.   g1 = (colour_table[ c1 ] & 0x0F0) >> 4;
  1230.   b1 = colour_table[ c1 ] & 0x00F;
  1231.   
  1232.   /* Get the RGB values: */
  1233.   r2 = (colour_table[ c2 ] & 0xF00) >> 8;
  1234.   g2 = (colour_table[ c2 ] & 0x0F0) >> 4;
  1235.   b2 = colour_table[ c2 ] & 0x00F;
  1236.   
  1237.   /* Calculate the difference between the RGB values: */
  1238.   dr = (r2 - r1) / (float) dif;
  1239.   dg = (g2 - g1) / (float) dif;
  1240.   db = (b2 - b1) / (float) dif;
  1241.   
  1242.   /* Initialize the float RGB values: */
  1243.   fr = r1;
  1244.   fg = g1;
  1245.   fb = b1;
  1246.  
  1247.   for( loop = c1+1; loop < c2; loop++ )
  1248.   {
  1249.     /* Add the difference: */
  1250.     fr += dr;
  1251.     fg += dg;
  1252.     fb += db;
  1253.  
  1254.     /* Round off to the nearest whole number: */
  1255.     r1 = fr + 0.5;
  1256.     g1 = fg + 0.5;
  1257.     b1 = fb + 0.5;
  1258.     
  1259.     /* Change the colour: */
  1260.     SetRGB4( vp, loop, r1, g1, b1 );
  1261.   }
  1262. }