This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/cdk-5.0-20161210/graph.c

596 lines
14 KiB
C
Raw Normal View History

#include <cdk_int.h>
/*
* $Author: tom $
* $Date: 2013/06/16 15:05:27 $
* $Revision: 1.86 $
*/
DeclareCDKObjects (GRAPH, Graph, setCdk, Unknown);
#define TITLE_LM 3
/*
* Create a graph widget.
*/
CDKGRAPH *newCDKGraph (CDKSCREEN *cdkscreen,
int xplace,
int yplace,
int height,
int width,
const char *title,
const char *xtitle,
const char *ytitle)
{
/* *INDENT-EQLS* */
CDKGRAPH *widget = 0;
int parentWidth = getmaxx (cdkscreen->window);
int parentHeight = getmaxy (cdkscreen->window);
int boxWidth;
int boxHeight;
int xpos = xplace;
int ypos = yplace;
if ((widget = newCDKObject (CDKGRAPH, &my_funcs)) == 0)
return (0);
setCDKGraphBox (widget, FALSE);
/* *INDENT-EQLS* */
boxHeight = setWidgetDimension (parentHeight, height, 3);
boxWidth = setWidgetDimension (parentWidth, width, 0);
boxWidth = setCdkTitle (ObjOf (widget), title, boxWidth);
boxHeight += TitleLinesOf (widget);
boxWidth = MINIMUM (boxWidth, parentWidth);
boxHeight = MINIMUM (boxHeight, parentHeight);
/* Rejustify the x and y positions if we need to. */
alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
/* *INDENT-EQLS* Create the widget pointer. */
ScreenOf (widget) = cdkscreen;
widget->parent = cdkscreen->window;
widget->win = newwin (boxHeight, boxWidth, ypos, xpos);
widget->boxHeight = boxHeight;
widget->boxWidth = boxWidth;
widget->minx = 0;
widget->maxx = 0;
widget->xscale = 0;
widget->yscale = 0;
widget->count = 0;
widget->displayType = vLINE;
if (widget->win == 0)
{
destroyCDKObject (widget);
return (0);
}
keypad (widget->win, TRUE);
/* Translate the X Axis title char * to a chtype * */
if (xtitle != 0)
{
widget->xtitle = char2Chtype (xtitle, &widget->xtitleLen, &widget->xtitlePos);
widget->xtitlePos = justifyString (widget->boxHeight,
widget->xtitleLen,
widget->xtitlePos);
}
else
{
widget->xtitle = char2Chtype ("<C></5>X Axis", &widget->xtitleLen, &widget->xtitlePos);
widget->xtitlePos = justifyString (widget->boxHeight,
widget->xtitleLen,
widget->xtitlePos);
}
/* Translate the Y Axis title char * to a chtype * */
if (ytitle != 0)
{
widget->ytitle = char2Chtype (ytitle, &widget->ytitleLen, &widget->ytitlePos);
widget->ytitlePos = justifyString (widget->boxWidth,
widget->ytitleLen,
widget->ytitlePos);
}
else
{
widget->ytitle = char2Chtype ("<C></5>Y Axis", &widget->ytitleLen, &widget->ytitlePos);
widget->ytitlePos = justifyString (widget->boxWidth,
widget->ytitleLen,
widget->ytitlePos);
}
widget->graphChar = 0;
registerCDKObject (cdkscreen, vGRAPH, widget);
return (widget);
}
/*
* This was added for the builder.
*/
void activateCDKGraph (CDKGRAPH *widget, chtype *actions GCC_UNUSED)
{
drawCDKGraph (widget, ObjOf (widget)->box);
}
/*
* Set multiple attributes of the widget.
*/
int setCDKGraph (CDKGRAPH *widget,
int *values,
int count,
const char *graphChar,
boolean startAtZero,
EGraphDisplayType displayType)
{
int ret;
ret = setCDKGraphValues (widget, values, count, startAtZero);
setCDKGraphCharacters (widget, graphChar);
setCDKGraphDisplayType (widget, displayType);
return ret;
}
/*
* Set the scale factors for the graph after we have loaded new values.
*/
static void setScales (CDKGRAPH *widget)
{
widget->xscale = ((widget->maxx - widget->minx)
/ MAXIMUM (1, (widget->boxHeight
- TitleLinesOf (widget)
- 5)));
if (widget->xscale <= 0)
widget->xscale = 1;
widget->yscale = ((widget->boxWidth - 4) / MAXIMUM (1, widget->count));
if (widget->yscale <= 0)
widget->yscale = 1;
}
/*
* Set the values of the graph.
*/
int setCDKGraphValues (CDKGRAPH *widget, int *values, int count, boolean startAtZero)
{
int min = INT_MAX;
int max = INT_MIN;
int x;
/* Make sure everything is happy. */
if (count < 0)
return (FALSE);
if (widget->values != 0)
{
free (widget->values);
widget->values = 0;
widget->count = 0;
}
if ((widget->values = typeCallocN (int, count + 1)) == 0)
return FALSE;
/* Copy the X values. */
for (x = 0; x < count; x++)
{
/* Determine the min/max values of the graph. */
min = MINIMUM (values[x], widget->minx);
max = MAXIMUM (values[x], widget->maxx);
/* Copy the value. */
widget->values[x] = values[x];
}
/* Keep the count and min/max values. */
widget->count = count;
widget->minx = min;
widget->maxx = max;
/* Check the start at zero status. */
if (startAtZero)
{
widget->minx = 0;
}
setScales (widget);
return (TRUE);
}
int *getCDKGraphValues (CDKGRAPH *widget, int *size)
{
(*size) = widget->count;
return widget->values;
}
/*
* Set the value of the graph at the given index.
*/
int setCDKGraphValue (CDKGRAPH *widget, int Index, int value, boolean startAtZero)
{
/* Make sure the index is within range. */
if (Index < 0 || Index >= widget->count)
{
return (FALSE);
}
/* Set the min, max, and value for the graph. */
widget->minx = MINIMUM (value, widget->minx);
widget->maxx = MAXIMUM (value, widget->maxx);
widget->values[Index] = value;
/* Check the start at zero status. */
if (startAtZero)
{
widget->minx = 0;
}
setScales (widget);
return (TRUE);
}
int getCDKGraphValue (CDKGRAPH *widget, int Index)
{
return Index >= 0 && Index < widget->count ? widget->values[Index] : 0;
}
/*
* Set the characters of the graph widget.
*/
int setCDKGraphCharacters (CDKGRAPH *widget, const char *characters)
{
chtype *newTokens = 0;
int charCount, junk;
newTokens = char2Chtype (characters, &charCount, &junk);
if (charCount != widget->count)
{
freeChtype (newTokens);
return (FALSE);
}
freeChtype (widget->graphChar);
widget->graphChar = newTokens;
return (TRUE);
}
chtype *getCDKGraphCharacters (CDKGRAPH *widget)
{
return widget->graphChar;
}
/*
* Set the character of the graph widget of the given index.
*/
int setCDKGraphCharacter (CDKGRAPH *widget, int Index, const char *character)
{
chtype *newTokens = 0;
int charCount, junk;
/* Make sure the index is within range. */
if (Index < 0 || Index > widget->count)
{
return (FALSE);
}
/* Convert the string given to us. */
newTokens = char2Chtype (character, &charCount, &junk);
/*
* Check if the number of characters back is the same as the number
* of elements in the list.
*/
if (charCount != widget->count)
{
freeChtype (newTokens);
return (FALSE);
}
/* Everything OK so far. Set the value of the array. */
widget->graphChar[Index] = newTokens[0];
freeChtype (newTokens);
return (TRUE);
}
chtype getCDKGraphCharacter (CDKGRAPH *widget, int Index)
{
return widget->graphChar[Index];
}
/*
* Set the display type of the graph.
*/
void setCDKGraphDisplayType (CDKGRAPH *widget, EGraphDisplayType type)
{
widget->displayType = type;
}
EGraphDisplayType getCDKGraphDisplayType (CDKGRAPH *widget)
{
return widget->displayType;
}
/*
* Set the background attribute of the widget.
*/
static void _setBKattrGraph (CDKOBJS *object, chtype attrib)
{
if (object != 0)
{
CDKGRAPH *widget = (CDKGRAPH *)object;
wbkgd (widget->win, attrib);
}
}
/*
* Move the graph field to the given location.
*/
static void _moveCDKGraph (CDKOBJS *object,
int xplace,
int yplace,
boolean relative,
boolean refresh_flag)
{
CDKGRAPH *widget = (CDKGRAPH *)object;
/* *INDENT-EQLS* */
int currentX = getbegx (widget->win);
int currentY = getbegy (widget->win);
int xpos = xplace;
int ypos = yplace;
int xdiff = 0;
int ydiff = 0;
/*
* If this is a relative move, then we will adjust where we want
* to move to.
*/
if (relative)
{
xpos = getbegx (widget->win) + xplace;
ypos = getbegy (widget->win) + yplace;
}
/* Adjust the window if we need to. */
alignxy (WindowOf (widget), &xpos, &ypos, widget->boxWidth, widget->boxHeight);
/* Get the difference. */
xdiff = currentX - xpos;
ydiff = currentY - ypos;
/* Move the window to the new location. */
moveCursesWindow (widget->win, -xdiff, -ydiff);
moveCursesWindow (widget->shadowWin, -xdiff, -ydiff);
/* Touch the windows so they 'move'. */
refreshCDKWindow (WindowOf (widget));
/* Redraw the window, if they asked for it. */
if (refresh_flag)
{
drawCDKGraph (widget, ObjOf (widget)->box);
}
}
/*
* Set whether or not the graph will be boxed.
*/
void setCDKGraphBox (CDKGRAPH *widget, boolean Box)
{
ObjOf (widget)->box = Box;
ObjOf (widget)->borderSize = Box ? 1 : 0;
}
boolean getCDKGraphBox (CDKGRAPH *widget)
{
return ObjOf (widget)->box;
}
/*
* Draw the graph widget.
*/
static void _drawCDKGraph (CDKOBJS *object, boolean Box)
{
/* *INDENT-EQLS* */
CDKGRAPH *widget = (CDKGRAPH *)object;
int adj = 2 + (widget->xtitle == 0 ? 0 : 1);
int spacing = 0;
chtype attrib = ' ' | A_REVERSE;
char temp[100];
int x, y, xpos, ypos, len;
/* Box it if needed. */
if (Box)
{
drawObjBox (widget->win, ObjOf (widget));
}
/* Draw in the vertical axis. */
drawLine (widget->win,
2,
TitleLinesOf (widget) + 1,
2,
widget->boxHeight - 3,
ACS_VLINE);
/* Draw in the horizontal axis. */
drawLine (widget->win,
3,
widget->boxHeight - 3,
widget->boxWidth,
widget->boxHeight - 3,
ACS_HLINE);
drawCdkTitle (widget->win, object);
/* Draw in the X axis title. */
if (widget->xtitle != 0)
{
writeChtype (widget->win,
0,
widget->xtitlePos,
widget->xtitle,
VERTICAL,
0,
widget->xtitleLen);
attrib = widget->xtitle[0] & A_ATTRIBUTES;
}
/* Draw in the X axis high value. */
sprintf (temp, "%d", widget->maxx);
len = (int)strlen (temp);
writeCharAttrib (widget->win,
1,
TitleLinesOf (widget) + 1,
temp,
attrib,
VERTICAL,
0,
len);
/* Draw in the X axis low value. */
sprintf (temp, "%d", widget->minx);
len = (int)strlen (temp);
writeCharAttrib (widget->win,
1,
widget->boxHeight - 2 - len,
temp,
attrib,
VERTICAL,
0,
len);
/* Draw in the Y axis title. */
if (widget->ytitle != 0)
{
writeChtype (widget->win,
widget->ytitlePos,
widget->boxHeight - 1,
widget->ytitle,
HORIZONTAL,
0,
widget->ytitleLen);
attrib = widget->ytitle[0] & A_ATTRIBUTES;
}
/* Draw in the Y axis high value. */
sprintf (temp, "%d", widget->count);
len = (int)strlen (temp);
writeCharAttrib (widget->win,
widget->boxWidth - len - adj,
widget->boxHeight - 2,
temp,
attrib,
HORIZONTAL,
0,
len);
/* Draw in the Y axis low value. */
sprintf (temp, "0");
writeCharAttrib (widget->win,
3,
widget->boxHeight - 2,
temp,
attrib,
HORIZONTAL,
0,
(int)strlen (temp));
/* If the count is zero, then there aren't any points. */
if (widget->count == 0)
{
wrefresh (widget->win);
return;
}
spacing = (widget->boxWidth - TITLE_LM) / widget->count;
/* Draw in the graph line/plot points. */
for (y = 0; y < widget->count; y++)
{
int colheight = (widget->values[y] / widget->xscale) - 1;
/* Add the marker on the Y axis. */
(void)mvwaddch (widget->win,
widget->boxHeight - 3,
(y + 1) * spacing + adj,
ACS_TTEE);
/* If this is a plot graph, all we do is draw a dot. */
if (widget->displayType == vPLOT)
{
xpos = widget->boxHeight - 4 - colheight;
ypos = (y + 1) * spacing + adj;
(void)mvwaddch (widget->win, xpos, ypos, widget->graphChar[y]);
}
else
{
for (x = 0; x <= widget->yscale; x++)
{
xpos = widget->boxHeight - 3;
ypos = (y + 1) * spacing + adj;
drawLine (widget->win,
ypos,
xpos - colheight,
ypos,
xpos,
widget->graphChar[y]);
}
}
}
/* Draw in the axis corners. */
(void)mvwaddch (widget->win, TitleLinesOf (widget), 2, ACS_URCORNER);
(void)mvwaddch (widget->win, widget->boxHeight - 3, 2, ACS_LLCORNER);
(void)mvwaddch (widget->win, widget->boxHeight - 3, widget->boxWidth, ACS_URCORNER);
/* Refresh and lets see 'er. */
wrefresh (widget->win);
}
/*
* Destroy the graph widget.
*/
static void _destroyCDKGraph (CDKOBJS *object)
{
if (object != 0)
{
CDKGRAPH *widget = (CDKGRAPH *)object;
cleanCdkTitle (object);
freeChtype (widget->xtitle);
freeChtype (widget->ytitle);
freeChtype (widget->graphChar);
freeChecked (widget->values);
/* Clean the key bindings. */
cleanCDKObjectBindings (vGRAPH, widget);
/* Unregister this object. */
unregisterCDKObject (vGRAPH, widget);
/* Clean up the windows. */
deleteCursesWindow (widget->win);
}
}
/*
* Erase the graph widget from the screen.
*/
static void _eraseCDKGraph (CDKOBJS *object)
{
if (validCDKObject (object))
{
CDKGRAPH *widget = (CDKGRAPH *)object;
eraseCursesWindow (widget->win);
}
}
dummyInject (Graph)
dummyFocus (Graph)
dummyUnfocus (Graph)
dummyRefreshData (Graph)
dummySaveData (Graph)