home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / science / chemesthetics / source / palettereq.c < prev    next >
C/C++ Source or Header  |  1990-12-13  |  17KB  |  558 lines

  1. /****************************************************************************
  2.  *                                        *
  3.  *                 Palette Requester                    *
  4.  *                                        *
  5.  *             (c) Copyright 1989 Jonathan Potter                     *
  6.  *                                        *
  7.  * This program is freely redistributable, although all rights to it remain *
  8.  * with the author. It may be used freely in any program as long as this    *
  9.  * notice remains intact, however, if you do this, please mention the        *
  10.  * author in the program. If you wish to use this in a commercial program   *
  11.  * of any kind, you must register with a $15 donation.                *
  12.  * Please send donations, bug reports, comments and suggestions to :        *
  13.  *                                        *
  14.  *                Jonathan Potter                 *
  15.  *                3 William Street                *
  16.  *                Clarence Park 5034                *
  17.  *                South Australia                 *
  18.  *                Australia                    *
  19.  *                                        *
  20.  *               Ph : (08) 2932788  home                          *
  21.  *                                        *
  22.  ****************************************************************************/
  23.  
  24. #include <exec/types.h>
  25. #include <exec/memory.h>
  26. #include <intuition/intuitionbase.h>
  27. #include <intuition/screens.h>
  28. #include <libraries/dosextens.h>
  29. #include <graphics/gfxbase.h>
  30. #include "PaletteReq.h"
  31.  
  32. #define RED 32
  33. #define BLUE 33
  34. #define GREEN 34
  35. #define CRESET 35
  36. #define CCANCEL 36
  37. #define COK 37
  38. #define USER 38
  39. #define SPREAD 39
  40. #define COPY 40
  41. #define HUE 41
  42. #define SAT 42
  43. #define LUM 43
  44.  
  45. #define INITREG(n)     (GetRGB4(cvp->ColorMap,n))
  46. #define REDREG(n)      ((n>>8)&0xf)
  47. #define GREENREG(n)    ((n>>4)&0xf)
  48. #define BLUEREG(n)     (n&0xf)
  49.  
  50. static int redtable[32], greentable[32], bluetable[32];
  51. static char values[4];
  52.  
  53. static struct IntuiText
  54.     coktext={1,0,JAM1,41,1,NULL,(UBYTE *)"OKAY",NULL},
  55.     canceltext={1,0,JAM1,33,1,NULL,(UBYTE *)"CANCEL",NULL},
  56.     usertext={1,0,JAM1,0,1,NULL,(UBYTE *)"",NULL},
  57.     resettext={1,0,JAM1,37,1,NULL,(UBYTE *)"RESET",NULL},
  58.     spreadtext={1,0,JAM1,33,1,NULL,(UBYTE *)"SPREAD",NULL},
  59.     copytext={1,0,JAM1,41,1,NULL,(UBYTE *)"COPY",NULL},
  60.     RText={1,0,JAM1,-15,1,NULL,"R",NULL},
  61.     GText={1,0,JAM1,-15,1,NULL,"G",NULL},
  62.     BText={1,0,JAM1,-15,1,NULL,"B",NULL},
  63.     HText={1,0,JAM1,106,1,NULL,"H",NULL},
  64.     SText={1,0,JAM1,106,1,NULL,"S",NULL},
  65.     LText={1,0,JAM1,106,1,NULL,"L",NULL},
  66.     valstext={0,1,JAM2,0,0,NULL,values,NULL};
  67.  
  68. static short border1_xy[]={
  69.     0,0,115,0,115,10,0,10,0,0};
  70. static struct Border border1={
  71.     -1,-1,1,0,JAM1,5,border1_xy,NULL};
  72. static short border2_xy[]={
  73.     0,0,239,0,239,10,0,10,0,0};
  74. static struct Border border2={
  75.     -1,-1,1,0,JAM1,5,border2_xy,NULL};
  76.  
  77. static struct PropInfo
  78.     RProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  79.     GProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  80.     BProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  81.     HProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  82.     SProp={AUTOKNOB|FREEHORIZ,0,0,1<<12},
  83.     LProp={AUTOKNOB|FREEHORIZ,0,0,1<<12};
  84.  
  85. static struct Image RImage, GImage, BImage, HImage, SImage, LImage,
  86.     WCol={0,0,235,8,1,NULL,0,1,NULL};
  87.  
  88. static struct Gadget
  89.     cokgadget={
  90.         NULL,9,118,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  91.         (APTR)&border1,NULL,&coktext,NULL,NULL,COK,NULL},
  92.     cancelgadget={
  93.         &cokgadget,133,118,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  94.         (APTR)&border1,NULL,&canceltext,NULL,NULL,CCANCEL,NULL},
  95.     usergadget={
  96.         &cancelgadget,133,105,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  97.         (APTR)&border1,NULL,&usertext,NULL,NULL,USER,NULL},
  98.     resetgadget={
  99.         &usergadget,9,105,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  100.         (APTR)&border1,NULL,&resettext,NULL,NULL,CRESET,NULL},
  101.     spreadgadget={
  102.         &resetgadget,133,92,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  103.         (APTR)&border1,NULL,&spreadtext,NULL,NULL,SPREAD,NULL},
  104.     copygadget={
  105.         &spreadgadget,9,92,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  106.         (APTR)&border1,NULL,©text,NULL,NULL,COPY,NULL},
  107.     Lum={
  108.         ©gadget,132,79,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  109.         (APTR)&LImage,NULL,<ext,NULL,(APTR)&LProp,LUM,NULL},
  110.     Sat={
  111.         &Lum,132,67,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  112.         (APTR)&SImage,NULL,&SText,NULL,(APTR)&SProp,SAT,NULL},
  113.     Hue={
  114.         &Sat,132,55,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  115.         (APTR)&HImage,NULL,&HText,NULL,(APTR)&HProp,HUE,NULL},
  116.     Red={
  117.         &Hue,24,55,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  118.         (APTR)&RImage,NULL,&RText,NULL,(APTR)&RProp,RED,NULL},
  119.     Green={
  120.         &Red,24,67,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  121.         (APTR)&GImage,NULL,>ext,NULL,(APTR)&GProp,GREEN,NULL},
  122.     Blue={
  123.         &Green,24,79,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  124.         (APTR)&BImage,NULL,&BText,NULL,(APTR)&BProp,BLUE,NULL};
  125.  
  126. static struct NewWindow colwin={
  127.     40,23,255,131,0,1,CLOSEWINDOW|GADGETUP|GADGETDOWN|MOUSEBUTTONS|RAWKEY,
  128.     WINDOWDRAG|WINDOWCLOSE|ACTIVATE|SMART_REFRESH|RMBTRAP,
  129.     &Blue,NULL,"Palette",NULL,NULL,0,0,0,0,CUSTOMSCREEN};
  130.  
  131. static struct Window *PWindow;
  132. static struct IntuiMessage *PMsg;
  133. static struct ViewPort *cvp;
  134. extern struct IntuitionBase *IntuitionBase;
  135. extern struct GfxBase *GfxBase;
  136. static ULONG colb;
  137.  
  138. palette_request(win,winx,winy,hail,user,depth)
  139. struct Window *win;
  140. int winx, winy;
  141. char *hail;
  142. char *user;
  143. int depth;
  144. {
  145.     int col,reg,i,Class,Code,GadgetID,x,y,last,first,sw,sh;
  146.     if (!IntuitionBase) return(NO_INTUITION);
  147.     if (!GfxBase) return(NO_GRAPHICS);
  148.     if (!win) { colwin.Type=WBENCHSCREEN; sw=640; sh=200; }
  149.     else {
  150.         colwin.Screen=win->WScreen;
  151.         sw=win->WScreen->Width; sh=win->WScreen->Height;
  152.     }
  153.     if (hail) colwin.Title=hail;
  154.     if (user) {
  155.         if (strlen(user)>14) user[14]='\0';
  156.         usertext.IText=user;
  157.         usertext.LeftEdge=(115-(strlen(user)*8))/2;
  158.     }
  159.     else {
  160.         resetgadget.NextGadget=&cancelgadget;
  161.         resetgadget.Width=238;
  162.         resetgadget.GadgetRender=(APTR)&border2;
  163.         resettext.LeftEdge=99;
  164.     }
  165.     if (winx>-1) {
  166.         colwin.LeftEdge=winx;
  167.         if (winx+255>sw)
  168.             colwin.LeftEdge=sw-255;
  169.     }
  170.     if (winy>-1) {
  171.         colwin.TopEdge=winy;
  172.         if (winy+131>sh)
  173.             colwin.TopEdge=sh-131;
  174.     }
  175.     PWindow=(struct Window *) OpenWindow(&colwin);
  176.     if (!PWindow) return(OPENWINDOW_FAILED);
  177.     cvp=&(PWindow->WScreen->ViewPort);
  178.     if (!depth) depth=2;
  179.     if (depth<1) depth=1; if (depth>5) depth=5;
  180.     drawersquares(depth);
  181.  
  182.     InitTable(depth);
  183.     col=1; WCol.PlaneOnOff=col;
  184.     valstext.FrontPen=col^(power(2,depth)-1); valstext.BackPen=1;
  185.     DrawImage(PWindow->RPort,&WCol,10,45);
  186.     PosPots(depth,col);
  187.     PosHSLPots(depth,col);
  188.     FOREVER {
  189.         Wait(1<<PWindow->UserPort->mp_SigBit);
  190.         while (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) {
  191.             Class=PMsg->Class; Code=PMsg->Code;
  192.             if (Class==GADGETUP || Class==GADGETDOWN)
  193.                 GadgetID=((struct Gadget *) PMsg->IAddress)->GadgetID;
  194.             ReplyMsg((struct Message *) PMsg);
  195.             switch (Class) {
  196.                 case CLOSEWINDOW:
  197.                     for (reg=0;reg<(power(2,depth));reg++)
  198.                         SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]);
  199.                     CloseWindow(PWindow);
  200.                     return(FALSE);
  201.                     break;
  202.                 case MOUSEBUTTONS:
  203.                     if (Code!=SELECTDOWN) break;
  204.                     x=PWindow->MouseX; y=PWindow->MouseY;
  205.                     if (x<12 || x>243 || y<15 || y>40) break;
  206.                     if (col==ReadPixel(PWindow->RPort,x,y)) break;
  207.                     col=ReadPixel(PWindow->RPort,x,y);
  208.                     WCol.PlaneOnOff=col;
  209.                     DrawImage(PWindow->RPort,&WCol,10,45);
  210.                     PosPots(depth,col);
  211.                     PosHSLPots(depth,col);
  212.                     break;
  213.                 case GADGETDOWN:
  214.                     switch (GadgetID) {
  215.                         case RED:
  216.                         case GREEN:
  217.                         case BLUE:
  218.                             SetCols(depth,col);
  219.                             while (!(PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)))
  220.                                 SetCols(depth,col);
  221.                             ReplyMsg((struct Message *) PMsg);
  222.                             SetCols(depth,col);
  223.                             break;
  224.                         case HUE:
  225.                         case SAT:
  226.                         case LUM:
  227.                             SetHSLCols(depth,col);
  228.                             while (!(PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)))
  229.                                 SetHSLCols(depth,col);
  230.                             ReplyMsg((struct Message *) PMsg);
  231.                             SetHSLCols(depth,col);
  232.                             break;
  233.  
  234.                     }
  235.                     break;
  236.                 case RAWKEY:
  237.                     if (Code!=0x45) break;
  238.                     GadgetID=CRESET; Class=GADGETUP;
  239.                 case GADGETUP:
  240.                     switch (GadgetID) {
  241.                         case CRESET:
  242.                             for (reg=0;reg<(power(2,depth));reg++) {
  243.                                 SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]);
  244.                                 if (reg==col) {
  245.                                     PosPots(depth,col);
  246.                                     PosHSLPots(depth,col);
  247.                                 }
  248.                             }
  249.                             break;
  250.                         case USER:
  251.                             if (!user) break;
  252.                             CloseWindow(PWindow);
  253.                             return(5);
  254.                         case COK:
  255.                             CloseWindow(PWindow);
  256.                             return(TRUE);
  257.                         case CCANCEL:
  258.                             for (reg=0;reg<(power(2,depth));reg++)
  259.                                 SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]);
  260.                             CloseWindow(PWindow);
  261.                             return(FALSE);
  262.                         case COPY:
  263.                             FOREVER {
  264.                                 Wait(1<<PWindow->UserPort->mp_SigBit);
  265.                                 if (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) {
  266.                                     Class=PMsg->Class; Code=PMsg->Code;
  267.                                     ReplyMsg((struct Message *) PMsg);
  268.                                     if (Class!=MOUSEBUTTONS && Code!=SELECTDOWN) continue;
  269.                                     x=PWindow->MouseX; y=PWindow->MouseY;
  270.                                     if (x<12 || x>243 || y<15 || y>40) continue;
  271.                                     GadgetID=ReadPixel(PWindow->RPort,x,y);
  272.                                     if (GadgetID>-1 && GadgetID<32) break;
  273.                                 }
  274.                             }
  275.                             colb=INITREG(col);
  276.                             SetRGB4(cvp,GadgetID,REDREG(colb),GREENREG(colb),BLUEREG(colb));
  277.                             col=GadgetID;
  278.                             WCol.PlaneOnOff=col;
  279.                             DrawImage(PWindow->RPort,&WCol,10,45);
  280.                             PosPots(depth,col);
  281.                             PosHSLPots(depth,col);
  282.                         case SPREAD:
  283.                             FOREVER {
  284.                                 Wait(1<<PWindow->UserPort->mp_SigBit);
  285.                                 if (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) {
  286.                                     Class=PMsg->Class; Code=PMsg->Code;
  287.                                     ReplyMsg((struct Message *) PMsg);
  288.                                     if (Class!=MOUSEBUTTONS && Code!=SELECTDOWN) continue;
  289.                                     x=PWindow->MouseX; y=PWindow->MouseY;
  290.                                     if (x<12 || x>243 || y<15 || y>40) continue;
  291.                                     GadgetID=ReadPixel(PWindow->RPort,x,y);
  292.                                     if (GadgetID>-1 && GadgetID<32) break;
  293.                                 }
  294.                             }
  295.                             first=col; last=GadgetID;
  296.                             if (first>last) {
  297.                                 i=first; first=last; last=i;
  298.                             }
  299.                             if (first>=last-1) break;
  300.                             dospread(first,last);
  301.                             col=GadgetID;
  302.                             WCol.PlaneOnOff=col;
  303.                             DrawImage(PWindow->RPort,&WCol,10,45);
  304.                             PosPots(depth,col);
  305.                             PosHSLPots(depth,col);
  306.                             break;
  307.                         default:
  308.                             break;
  309.                     }
  310.             }
  311.         }
  312.     }
  313. }
  314.  
  315. static PosPots(depth,col)
  316. int depth,col;
  317. {
  318.     ULONG hpr,hpg,hpb;
  319.     colb=INITREG(col);
  320.     hpr=REDREG(colb)*0x1111;
  321.     hpg=GREENREG(colb)*0x1111;
  322.     hpb=BLUEREG(colb)*0x1111;
  323.     if (RProp.HorizPot==hpr && GProp.HorizPot==hpg && BProp.HorizPot==hpb)
  324.         return(0);
  325.     NewModifyProp(&Red,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpr,0,1<<12,0,1);
  326.     NewModifyProp(&Green,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpg,0,1<<12,0,1);
  327.     NewModifyProp(&Blue,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpb,0,1<<12,0,1);
  328.     ShowVals(depth,REDREG(colb),GREENREG(colb),BLUEREG(colb),col);
  329.     return(0);
  330. }
  331.  
  332. static PosHSLPots(depth,col)
  333. int depth, col;
  334. {
  335.     colb=INITREG(col);
  336.     RGBToHSL(colb,&HProp.HorizPot,&SProp.HorizPot,&LProp.HorizPot);
  337.     NewModifyProp(&Hue,PWindow,NULL,FREEHORIZ|AUTOKNOB,HProp.HorizPot,0,1<<12,0,1);
  338.     NewModifyProp(&Sat,PWindow,NULL,FREEHORIZ|AUTOKNOB,SProp.HorizPot,0,1<<12,0,1);
  339.     NewModifyProp(&Lum,PWindow,NULL,FREEHORIZ|AUTOKNOB,LProp.HorizPot,0,1<<12,0,1);
  340.     return(0);
  341. }
  342.  
  343. static SetHSLCols(depth,col)
  344. int depth,col;
  345. {
  346.     ULONG rgb, red, green, blue;
  347.     rgb=(ULONG) HSLToRGB(HProp.HorizPot,SProp.HorizPot,LProp.HorizPot);
  348.     red=rgb>>8; green=rgb>>4; blue=rgb;
  349.     SetRGB4(cvp,col,red,green,blue);
  350.     PosPots(depth,col);
  351.     return(0);
  352. }
  353.  
  354. static SetCols(depth,col)
  355. int depth;
  356. int col;
  357. {
  358.     USHORT re,gr,bl;
  359.     re=RProp.HorizPot/0x1111;
  360.     gr=GProp.HorizPot/0x1111;
  361.     bl=BProp.HorizPot/0x1111;
  362.     colb=INITREG(col);
  363.     if (re==REDREG(colb) && gr==GREENREG(colb) && bl==BLUEREG(colb)) return(0);
  364.     SetRGB4(cvp,col,re,gr,bl);
  365.     ShowVals(depth,re,gr,bl,col);
  366.     PosHSLPots(depth,col);
  367.     return(0);
  368. }
  369.  
  370. static InitTable(depth)
  371. int depth;
  372. {
  373.     int reg;
  374.     for (reg=0;reg<(power(2,depth));reg++) {
  375.         colb=INITREG(reg);
  376.         redtable[reg]=REDREG(colb);
  377.         greentable[reg]=GREENREG(colb);
  378.         bluetable[reg]=BLUEREG(colb);
  379.     }
  380.     return(0);
  381. }
  382.  
  383. static ShowVals(depth,re,gr,bl,col)
  384. int depth,re,gr,bl,col;
  385. {
  386.     values[0]=dostr(re);
  387.     values[1]=dostr(gr);
  388.     values[2]=dostr(bl);
  389.     values[3]='\0';
  390.     valstext.FrontPen=col^(power(2,depth)-1);
  391.     valstext.BackPen=col;
  392.     PrintIText(PWindow->RPort,&valstext,115,45);
  393.     return(0);
  394. }
  395.  
  396. static power(base,n)
  397. int base,n;
  398. {
  399.     int p;
  400.     for (p=1;n>0;--n) p*=base;
  401.     return(p);
  402. }
  403.  
  404. static drawersquares(depth)
  405. int depth;
  406. {
  407.     int w,h,ox,x,y,i;
  408.     w=235/(power(2,depth)); h=25; ox=12;
  409.     if (depth==4) { w=29; h=12; ox=13; }
  410.     if (depth==5) { w=14; h=12; ox=17; }
  411.     i=0; x=ox; y=15;
  412.     while (x<255 && y<45) {
  413.         SetAPen(PWindow->RPort,i);
  414.         RectFill(PWindow->RPort,x,y,x+w,y+h);
  415.         ++i;
  416.         x+=w;
  417.         if (i>=power(2,depth)) break;
  418.         if (depth>3 && i==(power(2,(depth-1)))) {
  419.             x=ox; y+=h;
  420.         }
  421.     }
  422.     return(0);
  423. }
  424.  
  425. static dospread(first,last)
  426. int first,last;
  427. {
  428.     int redst,greenst,bluest,red1,green1,blue1,red2,green2,blue2,
  429.         redw,greenw,bluew,i;
  430.     colb=INITREG(first);
  431.     red1=REDREG(colb); green1=GREENREG(colb); blue1=BLUEREG(colb);
  432.     colb=INITREG(last);
  433.     red2=REDREG(colb); green2=GREENREG(colb); blue2=BLUEREG(colb);
  434.     redst=((red2-red1)<<8)/(last-first);
  435.     greenst=((green2-green1)<<8)/(last-first);
  436.     bluest=((blue2-blue1)<<8)/(last-first);
  437.     for (i=first+1;i<last;i++) {
  438.         redw=red1+(((redst*(i-first))+128)>>8);
  439.         greenw=green1+(((greenst*(i-first))+128)>>8);
  440.         bluew=blue1+(((bluest*(i-first))+128)>>8);
  441.         SetRGB4(cvp,i,redw,greenw,bluew);
  442.     }
  443.     return(0);
  444. }
  445.  
  446. /* HSL <-> RGB routines
  447.    adapted from the Amiga Programmers' Suite Book 1
  448.       by Robert J. Mical
  449.  
  450. ------------------------------------------------------------------------------
  451.  
  452.  * *** hsl.c ****************************************************************
  453.  *
  454.  * ColorWindow Routine    --  HSL Translation Routines
  455.  *     from Book 1 of the Amiga Programmers' Suite by RJ Mical
  456.  *
  457.  * Copyright (C) 1986, 1987, Robert J. Mical
  458.  * All Rights Reserved.
  459.  *
  460.  * Any or all of this code can be used in any program as long as this
  461.  * entire copyright notice is retained, ok?  Thanks.
  462.  *
  463.  * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  464.  * All copyright notices and all file headers must be retained intact.
  465.  * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
  466.  * resultant object code may be included in any software product.  However, no
  467.  * portion of the source listings or documentation of the Amiga Programmer's
  468.  * Suite Book 1 may be distributed or sold for profit or in a for-profit
  469.  * product without the written authorization of the author, RJ Mical.
  470.  *
  471.  * HISTORY    NAME        DESCRIPTION
  472.  * -----------    --------------    --------------------------------------------
  473.  * 3 Jan 87    RJ >:-{)*    Clean-up for release
  474.  * 27 Feb 86    =RJ Mical=    Modified these routines for Zaphod
  475.  * January 86    =RJ=        Modified the originals for Mandelbrot
  476.  * Late 85    =RJ=        Created the color window for Graphicraft
  477.  *
  478.  * *************************************************************************
  479.  
  480. -----------------------------------------------------------------------------
  481.  
  482. */
  483.  
  484.  
  485. static HSLToRGB(hue,sat,lum)
  486. USHORT hue, sat, lum;
  487. {
  488.     ULONG red,green,blue,rdiff,gdiff,bdiff,foo,ris,fall,inv;
  489.  
  490.     foo=hue/0x2aab; ris=(hue-(foo*0x2aab))*6; fall=0xffff-ris;
  491.     red=0xffff; green=0xffff; blue=0xffff;
  492.     switch (foo) {
  493.         case 0:
  494.             green=ris; blue=0;
  495.             break;
  496.         case 1:
  497.             red=fall; blue=0;
  498.             break;
  499.         case 2:
  500.             red=0; blue=ris;
  501.             break;
  502.         case 3:
  503.             red=0; green=fall;
  504.             break;
  505.         case 4:
  506.             red=ris; green=0;
  507.             break;
  508.         case 5:
  509.             green=0; blue=fall;
  510.             break;
  511.     }
  512.  
  513.     red=(red*lum)>>16; green=(green*lum)>>16; blue=(blue*lum)>>16;
  514.     inv=0xffff-sat;
  515.     rdiff=lum-red; red=red+((rdiff*inv)>>16);
  516.     gdiff=lum-green; green=green+((gdiff*inv)>>16);
  517.     bdiff=lum-blue; blue=blue+((bdiff*inv)>>16);
  518.     red=(red>>12)&0xf; green=(green>>12)&0xf; blue=(blue>>12)&0xf;
  519.     return((SHORT)((red<<8)|(green<<4)|(blue)));
  520. }
  521.  
  522. static RGBToHSL(rgb,rhue,rsat,rlum)
  523. USHORT rgb;
  524. USHORT *rhue,*rsat,*rlum;
  525. {
  526.     LONG min,max,hue,sat,lum,diff,rpart,gpart,bpart,rwork,gwork,bwork;
  527.  
  528.     rwork=((rgb>>8)&0xf)*0x111; gwork=((rgb>>4)&0xf)*0x111; bwork=(rgb&0xf)*0x111;
  529.     if (rwork<gwork) min=rwork; else min=gwork; if (bwork<min) min=bwork;
  530.     if (rwork>gwork) max=rwork; else max=gwork; if (bwork>max) max=bwork;
  531.     lum=max; lum<<=4; diff=max-min;
  532.     if (max) {
  533.         sat=(diff<<16)/max; if (sat>0xffff) sat=0xffff;
  534.     }
  535.     else sat=0;
  536.     if (sat==0) hue=0;
  537.     else {
  538.         rpart=(((max-rwork)<<16)/diff)>>4;
  539.         gpart=(((max-gwork)<<16)/diff)>>4;
  540.         bpart=(((max-bwork)<<16)/diff)>>4;
  541.         if (rwork==max) hue=bpart-gpart;
  542.         else if (gwork==max) hue=0x2000+rpart-bpart;
  543.         else if (bwork==max) hue=0x4000+gpart-rpart;
  544.         if (hue<0) hue+=0x6000; hue=(hue*2667)/1000;
  545.     }
  546.     *rhue=hue; *rsat=sat; *rlum=lum;
  547.     return(0);
  548. }
  549.  
  550. /*--------------------------------------------------------------------------*/
  551.  
  552. dostr(val)
  553. int val;
  554. {
  555.     if (val<10) return(val+48);
  556.     return(val+87);
  557. }
  558.