/*ScianIcons.c
  Eric Pepke
  March 22, 1990
  Does icon stuff in scian
*/

#include "Scian.h"
#include "ScianTypes.h"
#include "ScianIcons.h"
#include "ScianColors.h"
#include "ScianArrays.h"
#include "ScianErrors.h"
#include "ScianLists.h"
#include "ScianIDs.h"
#include "ScianEvents.h"
#include "ScianWindows.h"
#include "ScianControls.h"
#include "ScianScripts.h"
#include "ScianStyle.h"
#ifdef GRAPHICS
#include "ScianIconFonts.h"
#endif

ObjPtr iconClass = 0;
int iconXOff, iconYOff;		/*Offsets for icons on dragging*/

#define COLORICONXOFFSET	-5	/*X offset for color icon*/
#define COLORICONYOFFSET	0	/*Y offset for color icon*/

int rainbowColor[6] =
    {
	UIRED,
	UIORANGE,
	UIYELLOW,
	UIGREEN,
	UIBLUE,
	UIPURPLE
    };

static ObjPtr ColorIconExtraDraw(object, x, y)
ObjPtr object;
int x, y;
/*Draws extra stuff for a color icon*/
{
#ifdef GRAPHICS
    short bx, by, ex, ey, k;
    short coords[2];

    bx = x + COLORICONXOFFSET;
    by = y + COLORICONYOFFSET;
    ex = x + ICONSIZE / 2;
    ey = by - (ex - bx) / 2;
    for (k = 0; k < 6; ++k)
    {
	SetUIColor(rainbowColor[k]);
	bgnpolygon();
	coords[0] = bx;
	coords[1] = by;
	v2s(coords);
	coords[0] = ex;
	coords[1] = ey;
	v2s(coords);
	ey += (ex - bx) / 5;
	coords[1] = ey;
	v2s(coords);
	endpolygon();
    }
#endif
}

#ifdef PROTO
void DrawIcon(int x, int y, int whichIcon, char *iconTitle, char *subTitle, int backColor, int flags)
#else
void DrawIcon(x, y, whichIcon, iconTitle, subTitle, backColor, flags)
int x, y, whichIcon;
char *iconTitle;
char *subTitle;
int backColor;
int flags;
#endif
/*Draw icon whichIcon with its center at x, y with title
  iconTitle.  If iconTitle is NIL, doesn't draw a title.  
  Draws the background of the color in UIcolor backColor.
  Flags tells what parts to draw.
*/
{
#ifdef GRAPHICS
    Icoord v[4][2];
    char s[2];
    int texty;
    int k;
    int iconFont, iconChar;

    s[1] = 0;

    /*Get the icon font and character*/
    iconFont = iconFontLocationTable[whichIcon - 32][0];
    iconChar = iconFontLocationTable[whichIcon - 32][1];
    font(ICONBEGFONTS + iconFont);

    if (flags & DI_DRAWSHADOW)
    {
	SetUIColor(UISHADOW);
	cmov2i(x - ICONSIZE / 2, y - ICONSIZE / 2 - ICONSHADOW);
	s[0] = iconChar + 2;
	charstr(s);
    }

    for (k = 0; k >= 0; --k)
    {
	if (flags & DI_DRAWBACK)
	{
	    SetUIColor(k ? UIICONGREYBACK : backColor);
	    cmov2i(x - ICONSIZE / 2 + k * 2, y - ICONSIZE / 2 + k * 2);
	    s[0] = iconChar + 1;
	    charstr(s);
	}

	if (flags & DI_DRAWFORE)
	{
	    if (flags & DI_GREY || k)
	    {
		SetUIColor(UIICONGREYFORE);
	    }
	    else
	    {
		SetUIColor(UIICONFORE);
	    }
	    cmov2i(x - ICONSIZE / 2 + k * 2, y - ICONSIZE / 2 + k * 2);
	    s[0] = iconChar;
	    charstr(s);
 	}
    }

    texty = y - ICONSIZE / 2 - (flags & DI_DRAWSHADOW ? ICONSHADOW : 0) - ICONTEXTOFFSET;
    if (iconTitle)
    {
	char *s, *s2;
	SetUIColor(UITEXT);
	SetupFont(ICONTEXTFONT, flags & DI_SMALLTEXT ? 10 : 12);

	s = iconTitle;
	s2 = tempStr;

	while (*s)
	{
	    if (*s == '\n')
	    {
		*s2 = 0;
		++s;
		s2 = tempStr;
		DrawString(x - StrWidth(tempStr) / 2, 
		   texty,
		   tempStr);
		texty -= (flags & DI_SMALLTEXT ? 11 : 13);
	    }
	    else
	    {
		*s2 = *s;
		++s;
		++s2;
	    }
	}
	*s2 = 0;
	DrawString(x - StrWidth(tempStr) / 2, 
		   texty,
		   tempStr);
    }   

    if (subTitle)
    {
	texty -= (flags & DI_SMALLTEXT ? 11 : 13);
	SetUIColor(UITEXT);
	SetupFont(ICONTEXTFONT, 10);
	DrawString(x - StrWidth(subTitle) / 2, 
	           texty,
		   subTitle);
    }
#endif
}

#ifdef PROTO
void DrawIconGhost(ObjPtr icon, int xDisp, int yDisp)
#else
void DrawIconGhost(icon, xDisp, yDisp)
ObjPtr icon;
int xDisp, yDisp;
#endif
/*Draw a ghost of icon icon, displacint its center by xDisp, yDisp.*/
{
#ifdef GRAPHICS
    Icoord v[4][2];
    char s[2];
    ObjPtr theName, whichIconInt, theLoc;
    int x, y;
    real loc[2];
    int whichIcon;
    char *name;
    int iconFont, iconChar;

    theName = GetVar(icon, NAME);
    if (IsString(theName))
    {
	name = GetString(theName);
    }
    else
    {
	name = 0;
    }
    whichIconInt = GetVar(icon, WHICHICON);
    if (whichIconInt && IsInt(whichIconInt))
    {
	whichIcon = GetInt(whichIconInt);
    }
    else
    {
	return;
    }
    theLoc = GetFixedArrayVar("DrawIconGhost", icon, ICONLOC, 1, 2L);
    if (!theLoc)
    {
	return;
    }
    Array2CArray(loc, theLoc);
    x = loc[0] + xDisp;
    y = loc[1] + yDisp;

    iconFont = iconFontLocationTable[whichIcon - 32][0];
    iconChar = iconFontLocationTable[whichIcon - 32][1];
    font(ICONBEGFONTS + iconFont);

    s[1] = 0;
    s[0] = iconChar;

    cmov2i(x - ICONSIZE / 2, y - ICONSIZE / 2);
    charstr(s); 

    if (name)
    {
	SetupFont(ICONTEXTFONT, 12);
	DrawString(x - StrWidth(name) / 2, 
		   y - ICONSIZE / 2 - ICONSHADOW - ICONTEXTOFFSET,
		   name);
    }
#endif
}

ObjPtr DrawIconObj(object)
ObjPtr object;
/*Draws this icon thing*/
{
#ifdef GRAPHICS
    ObjPtr theLoc;
    ObjPtr theName;
    char *title, *subTitle;
    ObjPtr whichIconInt;
    real loc[2];
    int whichIcon;
    FuncTyp method;
    ObjPtr repObj;

    theLoc = GetFixedArrayVar("DrawIconObj", object, ICONLOC, 1, 2L);
    if (!theLoc)
    {
	return NULLOBJ;
    }

    MakeVar(object, NAME);
    theName = GetVar(object, NAME);
    if (theName && IsString(theName))
    {
	title = GetString(theName);
    }
    else
    {
	title = (char *) 0;
    }

    MakeVar(object, FORMAT);
    theName = GetVar(object, FORMAT);
    if (theName && IsString(theName))
    {
	subTitle = GetString(theName);
    }
    else
    {
	subTitle = (char *) 0;
    }

    whichIconInt = GetVar(object, WHICHICON);
    if (whichIconInt && IsInt(whichIconInt))
    {
	whichIcon = GetInt(whichIconInt);
    }
    else
    {
	whichIcon = ICONQUESTION;
    }

    Array2CArray(loc, theLoc);

    repObj = GetVar(object, REPOBJ);
    MakeVar(object, ICONGREYED);
    DrawIcon((int) loc[0], (int) loc[1], whichIcon, 
		title, subTitle, 
		IsSelected(repObj ? repObj : object) ? UIICONSELBACK : 
		    (GetPredicate(object, ICONGREYED) ? UIICONGREYBACK : UIICONBACK),
		GetPredicate(object, ICONGREYED) ?
		    DI_DRAWFORE | DI_DRAWBACK | DI_DRAWSHADOW | DI_GREY :
		    DI_DRAWFORE | DI_DRAWBACK | DI_DRAWSHADOW);

    method = GetMethod(object, ICONEXTRADRAW);
    if (method)
    {
	(*method)(object, (int) loc[0], (int) loc[1]);
    }
#endif
    return ObjTrue;
}

ObjPtr NewIcon(x, y, whichIcon, name)
int x, y;
int whichIcon;
char *name;
/*Makes and returns a new icon of type whichIcon and name name*/
{
    ObjPtr retVal;

    retVal = NewObject(iconClass, 0);
    if (whichIcon == ICONCOLOR)
    {
	SetMethod(retVal, ICONEXTRADRAW, ColorIconExtraDraw);
    }
    if (retVal)
    {
	real loc[2];
	ObjPtr locArray;
	
	loc[0] = x;
	loc[1] = y;
	locArray = NewRealArray(1, (long) 2);
	if (locArray)
	{
	    CArray2Array(locArray, loc);
	    SetVar(retVal, ICONLOC, locArray);
	}

	SetVar(retVal, WHICHICON, NewInt(whichIcon));

	if (name)
	{
	    SetVar(retVal, NAME, NewString(name));
	}
    }

    return retVal;
}

ObjPtr MakeIconGreyed(icon)
ObjPtr icon;
/*Makes an icon greyed or not*/
{
    ObjPtr repObj;
    repObj = GetVar(icon, REPOBJ);
    if (repObj)
    {
	SetVar(icon, ICONGREYED, GetVar(repObj, HIDDEN));
    }
    else
    {
	SetVar(icon, ICONGREYED, ObjFalse);
    }
}

static ObjPtr MakeIconAppearance(icon)
ObjPtr icon;
/*Dummy make for icon appearance*/
{
    SetVar(icon, APPEARANCE, ObjTrue);
    ImInvalid(icon);
    return ObjTrue;
}

void InitIcons()
/*Initializes the icon system*/
{
    int i;
#ifdef GRAPHICS
    for (i = 0; i < NICONFONTS; ++i)
    {
	defrasterfont(ICONBEGFONTS + i,
		iconFontParameters[i] . ht,
		iconFontParameters[i] . nc,
		iconFontParameters[i] . chars,
		iconFontParameters[i] . rs,
		(void *) iconFontParameters[i] . rasters);
	/*Have to use (void *) cast to make compatible both
	 with SGI and IBM*/
    }
#endif

    iconClass = NewObject(screenClass, 0);
    AddToReferenceList(iconClass);
    SetVar(iconClass, CLASSID, NewInt(CLASS_ICON));
    SetMethod(iconClass, DRAW, DrawIconObj);
    SetVar(iconClass, TYPESTRING, NewString("icon"));
    DeclareIndirectDependency(iconClass, ICONGREYED, REPOBJ, HIDDEN);
    SetMethod(iconClass, ICONGREYED, MakeIconGreyed);
    DeclareIndirectDependency(iconClass, APPEARANCE, REPOBJ, SELECTED);
    DeclareIndirectDependency(iconClass, APPEARANCE, REPOBJ, HIDDEN);
    SetMethod(iconClass, APPEARANCE, MakeIconAppearance);
}

void KillIcons()
/*Kills the icons*/
{
    DeleteThing(iconClass);
}
