[BACK]Return to graph.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / othersrc / dist / cdk

Annotation of othersrc/dist/cdk/graph.c, Revision 1.1.1.1

1.1       garbled     1: #include <cdk.h>
                      2:
                      3: /*
                      4:  * $Author: tom $
                      5:  * $Date: 2000/02/18 23:20:55 $
                      6:  * $Revision: 1.55 $
                      7:  */
                      8:
                      9: DeclareCDKObjects(my_funcs,Graph);
                     10:
                     11: /*
                     12:  * This creates a graph widget.
                     13:  */
                     14: CDKGRAPH *newCDKGraph (CDKSCREEN *cdkscreen, int xplace, int yplace, int height, int width, char *title, char *xtitle, char *ytitle)
                     15: {
                     16:    /* Declare local variables. */
                     17:    CDKGRAPH *graph     = newCDKObject(CDKGRAPH, &my_funcs);
                     18:    int parentWidth     = getmaxx(cdkscreen->window);
                     19:    int parentHeight    = getmaxy(cdkscreen->window);
                     20:    int boxWidth                = width;
                     21:    int boxHeight       = height;
                     22:    int xpos            = xplace;
                     23:    int ypos            = yplace;
                     24:    char **temp         = 0;
                     25:    int x;
                     26:
                     27:   /*
                     28:    * If the height is a negative value, the height will
                     29:    * be ROWS-height, otherwise, the height will be the
                     30:    * given height.
                     31:    */
                     32:    boxHeight = setWidgetDimension (parentHeight, height, 3);
                     33:
                     34:   /*
                     35:    * If the width is a negative value, the width will
                     36:    * be COLS-width, otherwise, the width will be the
                     37:    * given width.
                     38:    */
                     39:    boxWidth = setWidgetDimension (parentWidth, width, 0);
                     40:
                     41:   /*
                     42:    * If the width is a negative value, the width will
                     43:    * be COLS-width, otherwise, the width will be the
                     44:    * given width.
                     45:    */
                     46:    boxWidth = setWidgetDimension (parentWidth, width, 0);
                     47:
                     48:    /* Translate the char * items to chtype * */
                     49:    if (title != 0)
                     50:    {
                     51:       /* We need to split the title on \n. */
                     52:       temp = CDKsplitString (title, '\n');
                     53:       graph->titleLines = CDKcountStrings (temp);
                     54:
                     55:       /* For each line in the title, convert from char * to chtype * */
                     56:       for (x=0; x < graph->titleLines; x++)
                     57:       {
                     58:         graph->title[x]        = char2Chtype (temp[x], &graph->titleLen[x], &graph->titlePos[x]);
                     59:         graph->titlePos[x]     = justifyString (boxWidth, graph->titleLen[x], graph->titlePos[x]);
                     60:       }
                     61:
                     62:       CDKfreeStrings(temp);
                     63:    }
                     64:    else
                     65:    {
                     66:       /* No title? Set the required variables. */
                     67:       graph->titleLines = 0;
                     68:    }
                     69:    boxHeight += graph->titleLines;
                     70:
                     71:   /*
                     72:    * Make sure we didn't extend beyond the dimensions of the window.
                     73:    */
                     74:    boxWidth = MINIMUM (boxWidth, parentWidth);
                     75:    boxHeight = MINIMUM (boxHeight, parentHeight);
                     76:
                     77:    /* Rejustify the x and y positions if we need to. */
                     78:    alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
                     79:
                     80:    /* Create the graph pointer. */
                     81:    ScreenOf(graph)     = cdkscreen;
                     82:    graph->parent       = cdkscreen->window;
                     83:    graph->win          = newwin (boxHeight, boxWidth, ypos, xpos);
                     84:    graph->boxHeight    = boxHeight;
                     85:    graph->boxWidth     = boxWidth;
                     86:    ObjOf(graph)->box   = FALSE;
                     87:    graph->minx         = 0;
                     88:    graph->maxx         = 0;
                     89:    graph->xscale       = 0;
                     90:    graph->yscale       = 0;
                     91:    graph->count                = 0;
                     92:    graph->displayType  = vLINE;
                     93:    graph->ULChar       = ACS_ULCORNER;
                     94:    graph->URChar       = ACS_URCORNER;
                     95:    graph->LLChar       = ACS_LLCORNER;
                     96:    graph->LRChar       = ACS_LRCORNER;
                     97:    graph->HChar                = ACS_HLINE;
                     98:    graph->VChar                = ACS_VLINE;
                     99:    graph->BoxAttrib    = A_NORMAL;
                    100:
                    101:    /* Is the graph pointer null? */
                    102:    if (graph->win == 0)
                    103:    {
                    104:       /* Clean up any memory used. */
                    105:       free (graph);
                    106:
                    107:       /* Return a null pointer. */
                    108:       return ( 0 );
                    109:    }
                    110:    keypad (graph->win, TRUE);
                    111:    leaveok (graph->win, TRUE);
                    112:
                    113:    /* Translate the X Axis title char * to a chtype * */
                    114:    if (xtitle != 0)
                    115:    {
                    116:       graph->xtitle    = char2Chtype (xtitle, &graph->xtitleLen, &graph->xtitlePos);
                    117:       graph->xtitlePos = justifyString (graph->boxHeight, graph->xtitleLen, graph->xtitlePos);
                    118:    }
                    119:    else
                    120:    {
                    121:       graph->xtitle    = char2Chtype ("<C></5>X Axis", &graph->xtitleLen, &graph->xtitlePos);
                    122:       graph->xtitlePos = justifyString (graph->boxHeight, graph->xtitleLen, graph->xtitlePos);
                    123:    }
                    124:
                    125:    /* Translate the Y Axis title char * to a chtype * */
                    126:    if (ytitle != 0)
                    127:    {
                    128:       graph->ytitle    = char2Chtype (ytitle, &graph->ytitleLen, &graph->ytitlePos);
                    129:       graph->ytitlePos = justifyString (graph->boxWidth, graph->ytitleLen, graph->ytitlePos);
                    130:    }
                    131:    else
                    132:    {
                    133:       graph->ytitle    = char2Chtype ("<C></5>Y Axis", &graph->ytitleLen, &graph->ytitlePos);
                    134:       graph->ytitlePos = justifyString (graph->boxWidth, graph->ytitleLen, graph->ytitlePos);
                    135:    }
                    136:
                    137:    /* Set some values of the graph structure. */
                    138:    graph->graphChar = 0;
                    139:
                    140:    /* Register this baby. */
                    141:    registerCDKObject (cdkscreen, vGRAPH, graph);
                    142:
                    143:    /* Return the graph pointer. */
                    144:    return (graph);
                    145: }
                    146:
                    147: /*
                    148:  * This was added for the builder.
                    149:  */
                    150: void activateCDKGraph (CDKGRAPH *graph, chtype *actions GCC_UNUSED)
                    151: {
                    152:    drawCDKGraph (graph, ObjOf(graph)->box);
                    153: }
                    154:
                    155: /*
                    156:  * This sets multiple attributes of the widget.
                    157:  */
                    158: int setCDKGraph (CDKGRAPH *graph, int *values, int count, char *graphChar, boolean startAtZero, EGraphDisplayType displayType)
                    159: {
                    160:    int ret;
                    161:
                    162:    ret = setCDKGraphValues (graph, values, count, startAtZero);
                    163:    setCDKGraphCharacters (graph, graphChar);
                    164:    setCDKGraphDisplayType (graph, displayType);
                    165:    return ret;
                    166: }
                    167:
                    168: /*
                    169:  * This sets the values of the graph.
                    170:  */
                    171: int setCDKGraphValues (CDKGRAPH *graph, int *values, int count, boolean startAtZero)
                    172: {
                    173:    /* Declare local variables. */
                    174:    int min             = INT_MAX;
                    175:    int max             = INT_MIN;
                    176:    int x;
                    177:
                    178:    /* Make sure everything is happy. */
                    179:    if (count < 0)
                    180:    {
                    181:       return (FALSE);
                    182:    }
                    183:
                    184:    /* Copy the X values. */
                    185:    for (x=0; x < count; x++)
                    186:    {
                    187:       /* Determine the min/max values of the graph. */
                    188:       min = MINIMUM (values[x], graph->minx);
                    189:       max = MAXIMUM (values[x], graph->maxx);
                    190:
                    191:       /* Copy the value. */
                    192:       graph->values[x] = values[x];
                    193:    }
                    194:
                    195:    /* Keep the count and min/max values. */
                    196:    graph->count = count;
                    197:    graph->minx = min;
                    198:    graph->maxx = max;
                    199:
                    200:    /* Check the start at zero status. */
                    201:    if (startAtZero)
                    202:    {
                    203:       graph->minx = 0;
                    204:    }
                    205:
                    206:    /* Determine the scales. */
                    207:    graph->xscale = ((graph->maxx - graph->minx) / (graph->boxHeight - graph->titleLines - 5));
                    208:    graph->yscale = ((graph->boxWidth-4) / count);
                    209:    return (TRUE);
                    210: }
                    211: int *getCDKGraphValues (CDKGRAPH *graph, int *size)
                    212: {
                    213:    (*size) = graph->count;
                    214:    return graph->values;
                    215: }
                    216:
                    217: /*
                    218:  * This sets the value of the graph at the given index.
                    219:  */
                    220: int setCDKGraphValue (CDKGRAPH *graph, int Index, int value, boolean startAtZero)
                    221: {
                    222:    /* Make sure the index is within range. */
                    223:    if (Index < 0 || Index > graph->count)
                    224:    {
                    225:       return (FALSE);
                    226:    }
                    227:
                    228:    /* Set the min, max, and value for the graph. */
                    229:    graph->minx = MINIMUM (value, graph->minx);
                    230:    graph->maxx = MAXIMUM (value, graph->maxx);
                    231:    graph->values[Index] = value;
                    232:
                    233:    /* Check the start at zero status. */
                    234:    if (startAtZero)
                    235:    {
                    236:       graph->minx = 0;
                    237:    }
                    238:
                    239:    /* Determine the scales. */
                    240:    graph->xscale = ((graph->maxx - graph->minx) / (graph->boxHeight - 5));
                    241:    graph->yscale = ((graph->boxWidth-4) / graph->count);
                    242:    return (TRUE);
                    243: }
                    244: int getCDKGraphValue (CDKGRAPH *graph, int Index)
                    245: {
                    246:    return graph->values[Index];
                    247: }
                    248:
                    249: /*
                    250:  * This sets the characters of the graph widget.
                    251:  */
                    252: int setCDKGraphCharacters (CDKGRAPH *graph, char *characters)
                    253: {
                    254:    /* Declare local variables. */
                    255:    chtype *newTokens = 0;
                    256:    int charCount, junk;
                    257:
                    258:    /* Convert the string given to us. */
                    259:    newTokens = char2Chtype (characters, &charCount, &junk);
                    260:
                    261:   /*
                    262:    * Check if the number of characters back is the same as the number
                    263:    * of elements in the list.
                    264:    */
                    265:    if (charCount != graph->count)
                    266:    {
                    267:       freeChtype (newTokens);
                    268:       return (FALSE);
                    269:    }
                    270:
                    271:    /* Evrything OK so far. Nuke the old pointer and use the new one. */
                    272:    freeChtype (graph->graphChar);
                    273:    graph->graphChar = newTokens;
                    274:    return (TRUE);
                    275: }
                    276: chtype *getCDKGraphCharacters (CDKGRAPH *graph)
                    277: {
                    278:    return graph->graphChar;
                    279: }
                    280:
                    281: /*
                    282:  * This sets the character of the graph widget of the given index.
                    283:  */
                    284: int setCDKGraphCharacter (CDKGRAPH *graph, int Index, char *character)
                    285: {
                    286:    /* Declare local variables. */
                    287:    chtype *newTokens = 0;
                    288:    int charCount, junk;
                    289:
                    290:    /* Make sure the index is within range. */
                    291:    if (Index < 0 || Index > graph->count)
                    292:    {
                    293:       return (FALSE);
                    294:    }
                    295:
                    296:    /* Convert the string given to us. */
                    297:    newTokens = char2Chtype (character, &charCount, &junk);
                    298:
                    299:   /*
                    300:    * Check if the number of characters back is the same as the number
                    301:    * of elements in the list.
                    302:    */
                    303:    if (charCount != graph->count)
                    304:    {
                    305:       freeChtype (newTokens);
                    306:       return (FALSE);
                    307:    }
                    308:
                    309:    /* Evrything OK so far. Set the value of the array. */
                    310:    graph->graphChar[Index] = newTokens[0];
                    311:    freeChtype (newTokens);
                    312:    return (TRUE);
                    313: }
                    314: chtype getCDKGraphCharacter (CDKGRAPH *graph, int Index)
                    315: {
                    316:    return graph->graphChar[Index];
                    317: }
                    318:
                    319: /*
                    320:  * This sets the display type of the graph.
                    321:  */
                    322: void setCDKGraphDisplayType (CDKGRAPH *graph, EGraphDisplayType type)
                    323: {
                    324:    graph->displayType = type;
                    325: }
                    326: EGraphDisplayType getCDKGraphDisplayType (CDKGRAPH *graph)
                    327: {
                    328:    return graph->displayType;
                    329: }
                    330:
                    331: /*
                    332:  * These functions set the drawing characters of the widget.
                    333:  */
                    334: void setCDKGraphULChar (CDKGRAPH *graph, chtype character)
                    335: {
                    336:    graph->ULChar = character;
                    337: }
                    338: void setCDKGraphURChar (CDKGRAPH *graph, chtype character)
                    339: {
                    340:    graph->URChar = character;
                    341: }
                    342: void setCDKGraphLLChar (CDKGRAPH *graph, chtype character)
                    343: {
                    344:    graph->LLChar = character;
                    345: }
                    346: void setCDKGraphLRChar (CDKGRAPH *graph, chtype character)
                    347: {
                    348:    graph->LRChar = character;
                    349: }
                    350: void setCDKGraphVerticalChar (CDKGRAPH *graph, chtype character)
                    351: {
                    352:    graph->VChar = character;
                    353: }
                    354: void setCDKGraphHorizontalChar (CDKGRAPH *graph, chtype character)
                    355: {
                    356:    graph->HChar = character;
                    357: }
                    358: void setCDKGraphBoxAttribute (CDKGRAPH *graph, chtype character)
                    359: {
                    360:    graph->BoxAttrib = character;
                    361: }
                    362:
                    363: /*
                    364:  * This sets the background color of the widget.
                    365:  */
                    366: void setCDKGraphBackgroundColor (CDKGRAPH *graph, char *color)
                    367: {
                    368:    chtype *holder = 0;
                    369:    int junk1, junk2;
                    370:
                    371:    /* Make sure the color isn't null. */
                    372:    if (color == 0)
                    373:    {
                    374:       return;
                    375:    }
                    376:
                    377:    /* Convert the value of the environment variable to a chtype. */
                    378:    holder = char2Chtype (color, &junk1, &junk2);
                    379:
                    380:    /* Set the widgets background color. */
                    381:    wbkgd (graph->win, holder[0]);
                    382:
                    383:    /* Clean up. */
                    384:    freeChtype (holder);
                    385: }
                    386:
                    387: /*
                    388:  * This moves the graph field to the given location.
                    389:  */
                    390: static void _moveCDKGraph (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag)
                    391: {
                    392:    CDKGRAPH *graph = (CDKGRAPH *)object;
                    393:
                    394:    /*
                    395:     * If this is a relative move, then we will adjust where we want
                    396:     * to move to.
                    397:     */
                    398:    if (relative)
                    399:    {
                    400:       xplace += getbegx(graph->win);
                    401:       yplace += getbegy(graph->win);
                    402:    }
                    403:
                    404:    /* Adjust the window if we need to. */
                    405:    alignxy (WindowOf(graph), &xplace, &yplace, graph->boxWidth, graph->boxHeight);
                    406:
                    407:    /* Move the window to the new location. */
                    408:    moveCursesWindow(graph->win, xplace, yplace);
                    409:
                    410:    /* Redraw the window, if they asked for it. */
                    411:    if (refresh_flag)
                    412:    {
                    413:       drawCDKGraph (graph, ObjOf(graph)->box);
                    414:    }
                    415: }
                    416:
                    417: /*
                    418:  * This sets whether or not the graph will be boxed.
                    419:  */
                    420: void setCDKGraphBox (CDKGRAPH *graph, boolean Box)
                    421: {
                    422:    ObjOf(graph)->box = Box;
                    423: }
                    424: boolean getCDKGraphBox (CDKGRAPH *graph)
                    425: {
                    426:    return ObjOf(graph)->box;
                    427: }
                    428:
                    429: /*
                    430:  * This function draws the graph widget.
                    431:  */
                    432: static void _drawCDKGraph (CDKOBJS *object, boolean Box)
                    433: {
                    434:    CDKGRAPH *graph = (CDKGRAPH *)object;
                    435:    int adj             = 2 + (graph->xtitle == 0 ? 0 : 1);
                    436:    int spacing         = 0;
                    437:    chtype attrib       = ' '|A_REVERSE;
                    438:    char temp[100];
                    439:    int x, y, xpos, ypos, len;
                    440:
                    441:    /* Box it if needed. */
                    442:    if (Box)
                    443:    {
                    444:       attrbox (graph->win,
                    445:                graph->ULChar, graph->URChar,
                    446:                graph->LLChar, graph->LRChar,
                    447:                graph->HChar,  graph->VChar,
                    448:                graph->BoxAttrib,
                    449:                FALSE);
                    450:    }
                    451:
                    452:    /* Draw in the vertical axis. */
                    453:    drawLine (graph->win, 2, graph->titleLines + 1, 2, graph->boxHeight-3, ACS_VLINE);
                    454:
                    455:    /* Draw in the horizontal axis. */
                    456:    drawLine (graph->win, 3, graph->boxHeight-3, graph->boxWidth, graph->boxHeight-3, ACS_HLINE);
                    457:
                    458:    /* Draw in the title if there is one. */
                    459:    for (x=0; x < graph->titleLines; x++)
                    460:    {
                    461:       writeChtype (graph->win,
                    462:                        graph->titlePos[x],
                    463:                        x + 1,
                    464:                        graph->title[x],
                    465:                        HORIZONTAL, 0,
                    466:                        graph->titleLen[x]);
                    467:    }
                    468:
                    469:    /* Draw in the X axis title. */
                    470:    if (graph->xtitle != 0)
                    471:    {
                    472:       writeChtype (graph->win, 0, graph->xtitlePos, graph->xtitle, VERTICAL, 0, graph->xtitleLen);
                    473:       attrib   = graph->xtitle[0] & A_ATTRIBUTES;
                    474:    }
                    475:
                    476:    /* Draw in the X axis high value. */
                    477:    sprintf (temp, "%d", graph->maxx);
                    478:    len = (int)strlen (temp);
                    479:    writeCharAttrib (graph->win, 1, graph->titleLines + 1, temp, attrib, VERTICAL, 0, len);
                    480:
                    481:    /* Draw in the X axis low value. */
                    482:    sprintf (temp, "%d", graph->minx);
                    483:    len = (int)strlen (temp);
                    484:    writeCharAttrib (graph->win, 1, graph->boxHeight-2-len, temp, attrib, VERTICAL, 0, len);
                    485:
                    486:    /* Draw in the Y axis title. */
                    487:    if (graph->ytitle != 0)
                    488:    {
                    489:       writeChtype (graph->win, graph->ytitlePos, graph->boxHeight-1, graph->ytitle, HORIZONTAL, 0, graph->ytitleLen);
                    490:       attrib   = graph->ytitle[0] & A_ATTRIBUTES;
                    491:    }
                    492:
                    493:    /* Draw in the Y axis high value. */
                    494:    sprintf (temp, "%d", graph->count);
                    495:    len = (int)strlen (temp);
                    496:    writeCharAttrib (graph->win, graph->boxWidth-len-adj, graph->boxHeight-2, temp, attrib, HORIZONTAL, 0, len);
                    497:
                    498:    /* Draw in the Y axis low value. */
                    499:    sprintf (temp, "0");
                    500:    writeCharAttrib (graph->win, 3, graph->boxHeight-2, temp, attrib, HORIZONTAL, 0, (int)strlen(temp));
                    501:
                    502:    /* If the count is zero, then there aren't any points. */
                    503:    if (graph->count == 0)
                    504:    {
                    505:       wnoutrefresh (graph->win);
                    506:       return;
                    507:    }
                    508:
                    509:    spacing = (graph->boxWidth - 3) / graph->count;
                    510:
                    511:    /* Draw in the graph line/plot points. */
                    512:    for (y=0; y < graph->count; y++)
                    513:    {
                    514:        int colheight = (graph->values[y] / graph->xscale) - 1;
                    515:
                    516:        /* Add the marker on the Y axis. */
                    517:        mvwaddch (graph->win, graph->boxHeight-3, (y + 1)*spacing + adj, ACS_TTEE);
                    518:
                    519:        /* If this is a plot graph, all we do is draw a dot. */
                    520:        if (graph->displayType == vPLOT)
                    521:        {
                    522:          xpos = graph->boxHeight-4-colheight;
                    523:          ypos = (y + 1)*spacing + adj;
                    524:          mvwaddch (graph->win, xpos, ypos, graph->graphChar[y]);
                    525:        }
                    526:        else
                    527:        {
                    528:          for (x=0; x <= graph->yscale; x++)
                    529:          {
                    530:             xpos = graph->boxHeight-3;
                    531:             ypos = (y + 1)*spacing + adj;
                    532:             drawLine (graph->win, ypos, xpos-colheight, ypos, xpos, graph->graphChar[y]);
                    533:          }
                    534:        }
                    535:    }
                    536:
                    537:    /* Draw in the axis corners. */
                    538:    mvwaddch (graph->win, graph->titleLines, 2, ACS_URCORNER);
                    539:    mvwaddch (graph->win, graph->boxHeight-3, 2, ACS_LLCORNER);
                    540:    mvwaddch (graph->win, graph->boxHeight-3, graph->boxWidth, ACS_URCORNER);
                    541:
                    542:    /* Refresh and lets see 'er. */
                    543:    wnoutrefresh (graph->win);
                    544: }
                    545:
                    546: /*
                    547:  * This function destroys the graph widget.
                    548:  */
                    549: void destroyCDKGraph (CDKGRAPH *graph)
                    550: {
                    551:    int x;
                    552:
                    553:    /* Erase the object. */
                    554:    eraseCDKGraph (graph);
                    555:
                    556:    /* Clear up the char pointers. */
                    557:    for (x=0; x < graph->titleLines; x++)
                    558:    {
                    559:       freeChtype (graph->title[x]);
                    560:    }
                    561:    freeChtype (graph->xtitle);
                    562:    freeChtype (graph->ytitle);
                    563:    freeChtype (graph->graphChar);
                    564:
                    565:    /* Clean up the windows. */
                    566:    deleteCursesWindow (graph->win);
                    567:
                    568:    /* Unregister this object. */
                    569:    unregisterCDKObject (vGRAPH, graph);
                    570:
                    571:    /* Finish cleaning up. */
                    572:    free (graph);
                    573: }
                    574:
                    575: /*
                    576:  * This function erases the graph widget from the screen.
                    577:  */
                    578: static void _eraseCDKGraph (CDKOBJS *object)
                    579: {
                    580:    CDKGRAPH *graph = (CDKGRAPH *)object;
                    581:
                    582:    eraseCursesWindow (graph->win);
                    583: }

CVSweb <webmaster@jp.NetBSD.org>