rework rendering to use the value/period settings, and to correctly render from the...
[AROS.git] / workbench / classes / zune / graph / graph.c
blob11e1a20faf758bec99190b0839c02bbc9e7b72ae
1 /*
2 Copyright © 2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
7 #include <aros/debug.h>
9 #define MUIMASTER_YES_INLINE_STDARG
11 #include <exec/types.h>
12 #include <utility/date.h>
14 #include <aros/asmcall.h>
16 #include <proto/alib.h>
17 #include <proto/muimaster.h>
18 #include <proto/graphics.h>
19 #include <proto/intuition.h>
20 #include <proto/utility.h>
21 #include <proto/timer.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <math.h>
27 #include "graph.h"
28 #include "graph_intern.h"
30 IPTR Graph__UpdateSourceArray(struct Graph_DATA *data, IPTR count)
32 struct Graph_SourceDATA *newSourceArray = data->graph_Sources;
34 D(bug("[Graph] %s(%d)\n", __func__, count);)
36 if (data->graph_SourceCount != count)
38 IPTR copycnt;
40 if (count > data->graph_SourceCount)
41 copycnt = data->graph_SourceCount;
42 else
43 copycnt = count;
45 newSourceArray = AllocMem(sizeof(struct Graph_SourceDATA) * count, MEMF_ANY);
46 if (newSourceArray)
49 if (data->graph_Sources)
51 CopyMem(data->graph_Sources, newSourceArray, sizeof(struct Graph_SourceDATA) * copycnt);
52 FreeMem(data->graph_Sources, sizeof(struct Graph_SourceDATA) * data->graph_SourceCount);
55 if (count > data->graph_SourceCount)
57 D(bug("[Graph] %s: initializing new source\n", __func__);)
58 memset(&newSourceArray[count - 1], 0, sizeof(struct Graph_SourceDATA));
59 newSourceArray[count - 1].gs_PlotPen = -1;
60 newSourceArray[count - 1].gs_PlotFillPen = -1;
61 if (data->graph_EntryCount > 0)
62 newSourceArray[count - 1].gs_Entries = AllocMem(sizeof(IPTR) * data->graph_EntryCount, MEMF_CLEAR|MEMF_ANY);
65 data->graph_Sources = newSourceArray;
66 data->graph_SourceCount = count;
70 return (IPTR)newSourceArray;
73 IPTR Graph__UpdateSourceEntries(struct Graph_DATA *data, IPTR sourceNo, IPTR count)
75 struct Graph_SourceDATA *dataSource = NULL;
77 D(bug("[Graph] %s(%d:%d)\n", __func__, sourceNo, count);)
79 if (count > data->graph_EntryCount)
81 IPTR *newEntries;
83 dataSource = &data->graph_Sources[sourceNo];
85 newEntries = AllocMem(sizeof(IPTR) * count, MEMF_ANY);
86 if (newEntries)
88 if (dataSource->gs_Entries)
90 CopyMem(dataSource->gs_Entries, newEntries, sizeof(IPTR) * data->graph_EntryCount);
91 FreeMem(dataSource->gs_Entries, sizeof(IPTR) * data->graph_EntryCount);
93 dataSource->gs_Entries = newEntries;
97 return (IPTR)dataSource;
100 void Graph__FreeInfoText(Class *cl, Object *obj)
102 struct Graph_DATA *data = INST_DATA(cl, obj);
103 struct Node *infoLine, *tmp;
105 D(bug("[Graph] %s()\n", __func__);)
107 ForeachNodeSafe(&data->graph_InfoText, infoLine, tmp)
109 D(bug("[Graph] %s: Deleting old infotext line @ 0x%p - '%s'\n", __func__, infoLine, infoLine->ln_Name);)
110 Remove(infoLine);
111 FreeVec(infoLine);
113 data->graph_ITHeight = 0;
116 IPTR Graph__ParseInfoText(Class *cl, Object *obj, char *infoTxt)
118 struct Graph_DATA *data = INST_DATA(cl, obj);
120 int i, srcLen, start = 0;
121 struct Node *infoLine;
123 D(bug("[Graph] %s(0x%p)\n", __func__, infoTxt);)
125 Graph__FreeInfoText(cl, obj);
127 if (infoTxt)
129 srcLen = strlen(infoTxt);
131 for (i = 0; i < (srcLen + 1); i ++)
133 if (((i - start) > 0) && (infoTxt[i] == '\n') || (infoTxt[i] == '\0'))
135 infoLine = (struct Node *)AllocVec(sizeof(struct Node) + 1 + (i - start), MEMF_ANY|MEMF_CLEAR);
136 infoLine->ln_Name = (char *)&infoLine[1];
138 CopyMem(&infoTxt[start], infoLine->ln_Name, (i - start));
140 D(bug("[Graph] %s: New infotext line @ 0x%p - '%s'\n", __func__, infoLine, infoLine->ln_Name);)
141 AddTail(&data->graph_InfoText, infoLine);
143 data->graph_ITHeight += 1;
144 start = i + 1;
148 D(bug("[Graph] %s: InfoText> %d lines\n", __func__, data->graph_ITHeight);)
149 return data->graph_ITHeight;
152 /*** Methods ****************************************************************/
153 IPTR Graph__OM_NEW(Class *cl, Object *obj, struct opSet *msg)
155 struct Graph_DATA *data;
157 D(bug("[Graph] %s()\n", __func__);)
159 obj = (Object *) DoSuperNewTags
161 cl, obj, NULL,
163 MUIA_InnerLeft, 4,
164 MUIA_InnerTop, 4,
165 MUIA_InnerRight, 4,
166 MUIA_InnerBottom, 4,
168 TAG_MORE, (IPTR) msg->ops_AttrList
171 if (obj)
173 data = INST_DATA(cl, obj);
175 NEWLIST(&data->graph_InfoText);
176 data->graph_ITHeight = 0;
178 data->graph_RastPort = NULL;
180 data->graph_Flags = 0;
181 data->graph_BackPen = -1;
182 data->graph_AxisPen = -1;
183 data->graph_SegmentPen = -1;
185 /* We always have atleast one source .. */
186 Graph__UpdateSourceArray(data, 1);
188 data->ihn.ihn_Flags = MUIIHNF_TIMER;
189 data->ihn.ihn_Method = MUIM_Graph_Timer;
190 data->ihn.ihn_Object = obj;
191 data->ihn.ihn_Millis = 1000;
193 data->graph_PeriodCeiling = data->ihn.ihn_Millis * 10;
194 data->graph_PeriodStepping = data->ihn.ihn_Millis;
196 data->graph_ValCeiling = 100;
197 data->graph_ValStepping = 10;
199 SetAttrsA(obj, msg->ops_AttrList);
202 return (IPTR)obj;
205 IPTR Graph__OM_DISPOSE(Class *cl, Object *obj, Msg msg)
207 struct Graph_DATA *data = INST_DATA(cl, obj);
208 int i;
210 D(bug("[Graph] %s()\n", __func__);)
212 if (data->graph_SourceCount > 0)
214 if (data->graph_EntryCount > 0)
216 for (i = 0; i < data->graph_SourceCount; i ++)
218 FreeMem(data->graph_Sources[i].gs_Entries, sizeof(IPTR) * data->graph_EntryCount);
221 FreeMem(data->graph_Sources, sizeof(struct Graph_SourceDATA) * data->graph_SourceCount);
224 Graph__FreeInfoText(cl, obj);
226 return DoSuperMethodA(cl, obj, msg);
230 IPTR Graph__OM_SET(Class *cl, Object *obj, struct opSet *msg)
232 struct Graph_DATA *data = INST_DATA(cl, obj);
233 struct TagItem *tags = msg->ops_AttrList;
234 struct TagItem *tag;
235 BOOL redraw = FALSE;
237 D(bug("[Graph] %s()\n", __func__);)
239 while ((tag = NextTagItem(&tags)) != NULL)
241 switch(tag->ti_Tag)
243 /* Aggreagte mode plots the sum of source entries/no of sources */
244 case MUIA_Graph_Aggregate:
245 data->graph_Flags &= ~GRAPHF_AGGR;
246 if (tag->ti_Data)
247 data->graph_Flags |= GRAPHF_AGGR;
248 break;
250 /* Set the info text to display */
251 case MUIA_Graph_InfoText:
252 Graph__ParseInfoText(cl, obj, (char *)tag->ti_Data);
253 redraw = TRUE;
254 break;
256 /* Set the input value ceiling and stepping */
257 case MUIA_Graph_ValueCeiling:
258 data->graph_ValCeiling = tag->ti_Data;
259 break;
261 case MUIA_Graph_ValueStep:
262 data->graph_ValStepping = tag->ti_Data;
263 break;
265 /* Set the period ceiling and stepping */
266 case MUIA_Graph_PeriodCeiling:
267 data->graph_PeriodCeiling = tag->ti_Data;
268 break;
270 case MUIA_Graph_PeriodStep:
271 data->graph_PeriodStepping = tag->ti_Data;
272 break;
274 /* Set or turn off periodic update mode */
275 case MUIA_Graph_PeriodInterval:
276 if (tag->ti_Data)
278 data->graph_Flags |= GRAPHF_PERIODIC;
279 data->ihn.ihn_Millis = tag->ti_Data;
280 SET(obj, MUIA_Graph_EntryCount, (data->graph_PeriodCeiling/ data->ihn.ihn_Millis));
281 if ((data->graph_Flags & GRAPHF_SETUP) && !(data->graph_Flags & GRAPHF_HANDLER))
283 data->graph_Flags |= GRAPHF_HANDLER;
284 DoMethod(_app(obj), MUIM_Application_AddInputHandler, (IPTR) &data->ihn);
287 else
289 data->graph_Flags &= ~GRAPHF_PERIODIC;
290 if ((data->graph_Flags & GRAPHF_SETUP) && (data->graph_Flags & GRAPHF_HANDLER))
292 DoMethod(_app(obj), MUIM_Application_RemInputHandler, (IPTR) &data->ihn);
293 data->graph_Flags &= ~GRAPHF_HANDLER;
296 break;
298 /* Set or turn off Fixed entry count mode */
299 case MUIA_Graph_EntryCount:
300 if (tag->ti_Data)
302 int i;
303 for (i = 0; i < data->graph_SourceCount; i ++)
305 Graph__UpdateSourceEntries(data, i, tag->ti_Data);
307 data->graph_EntryCount = tag->ti_Data;
308 data->graph_Flags |= GRAPHF_FIXEDLEN;
310 else
312 data->graph_Flags &= ~GRAPHF_FIXEDLEN;
314 break;
318 if (redraw)
319 MUI_Redraw(obj, MADF_DRAWUPDATE);
321 return DoSuperMethodA(cl, obj, (Msg)msg);
325 IPTR Graph__OM_GET(Class *cl, Object *obj, struct opGet *msg)
327 struct Graph_DATA *data = INST_DATA(cl, obj);
328 IPTR retval = TRUE;
330 D(bug("[Graph] %s()\n", __func__);)
332 switch(msg->opg_AttrID)
334 case MUIA_Graph_ValueCeiling:
335 *(msg->opg_Storage) = data->graph_ValCeiling;
336 break;
338 case MUIA_Graph_EntryCount:
339 *(msg->opg_Storage) = data->graph_EntryCount;
340 break;
342 case MUIA_Graph_PeriodInterval:
343 *(msg->opg_Storage) = data->ihn.ihn_Millis;
344 break;
346 default:
347 retval = DoSuperMethodA(cl, obj, (Msg)msg);
348 break;
351 return retval;
354 IPTR Graph__MUIM_Setup(Class *cl, Object *obj, struct MUIP_Setup *msg)
356 struct Graph_DATA *data = INST_DATA(cl, obj);
358 D(bug("[Graph] %s()\n", __func__);)
360 if (!DoSuperMethodA(cl, obj, (Msg)msg)) return FALSE;
362 if ((data->graph_Flags & GRAPHF_PERIODIC) && !(data->graph_Flags & GRAPHF_HANDLER))
364 data->graph_Flags |= GRAPHF_HANDLER;
365 DoMethod(_app(obj), MUIM_Application_AddInputHandler, (IPTR) &data->ihn);
368 data->graph_BackPen = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,
369 0xF2F2F2F2,
370 0xF8F8F8F8,
371 0xFAFAFAFA,
372 OBP_Precision, PRECISION_GUI,
373 OBP_FailIfBad, FALSE,
374 TAG_DONE);
376 data->graph_AxisPen = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,
377 0x7A7A7A7A,
378 0xC5C5C5C5,
379 0xDEDEDEDE,
380 OBP_Precision, PRECISION_GUI,
381 OBP_FailIfBad, FALSE,
382 TAG_DONE);
384 data->graph_SegmentPen = ObtainBestPen(_screen(obj)->ViewPort.ColorMap,
385 0x85858585,
386 0xD3D3D3D3,
387 0xEDEDEDED,
388 OBP_Precision, PRECISION_GUI,
389 OBP_FailIfBad, FALSE,
390 TAG_DONE);
392 data->graph_Flags |= GRAPHF_SETUP;
394 return TRUE;
398 IPTR Graph__MUIM_Cleanup(Class *cl, Object *obj, struct MUIP_Cleanup *msg)
400 struct Graph_DATA *data = INST_DATA(cl, obj);
402 D(bug("[Graph] %s()\n", __func__);)
404 data->graph_Flags &= ~GRAPHF_SETUP;
406 if (data->graph_SegmentPen != -1)
408 ReleasePen(_screen(obj)->ViewPort.ColorMap, data->graph_SegmentPen);
409 data->graph_SegmentPen = -1;
412 if (data->graph_AxisPen != -1)
414 ReleasePen(_screen(obj)->ViewPort.ColorMap, data->graph_AxisPen);
415 data->graph_AxisPen = -1;
418 if (data->graph_BackPen != -1)
420 ReleasePen(_screen(obj)->ViewPort.ColorMap, data->graph_BackPen);
421 data->graph_BackPen = -1;
424 if ((data->graph_Flags & GRAPHF_PERIODIC) && (data->graph_Flags & GRAPHF_HANDLER))
426 DoMethod(_app(obj), MUIM_Application_RemInputHandler, (IPTR) &data->ihn);
427 data->graph_Flags &= ~GRAPHF_HANDLER;
430 return DoSuperMethodA(cl, obj, (Msg)msg);
434 IPTR Graph__MUIM_AskMinMax(Class *cl, Object *obj, struct MUIP_AskMinMax *msg)
436 struct Graph_DATA *data = INST_DATA(cl, obj);
438 bug("[Graph] %s()\n", __func__);
440 DoSuperMethodA(cl, obj, (Msg)msg);
442 msg->MinMaxInfo->MinWidth += (data->graph_PeriodCeiling / data->graph_PeriodStepping) * 2;
443 msg->MinMaxInfo->MinHeight += (data->graph_ValCeiling / data->graph_ValStepping) * 10;
444 msg->MinMaxInfo->DefWidth += (data->graph_PeriodCeiling / data->graph_PeriodStepping) * 10;
445 msg->MinMaxInfo->DefHeight += (data->graph_ValCeiling / data->graph_ValStepping) * 10;
446 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
447 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
449 return TRUE;
452 IPTR Graph__MUIM_Draw(Class *cl, Object *obj, struct MUIP_Draw *msg)
454 struct Graph_DATA *data = INST_DATA(cl, obj);
455 struct Graph_SourceDATA *sourceData;
456 struct Region *region;
457 struct Node *infoLine;
458 struct RastPort *renderPort;
459 struct Rectangle rect;
460 APTR clip = NULL;
461 UWORD pos, offset = 0, src, objHeight;
463 D(bug("[Graph] %s()\n", __func__);)
465 rect.MinX = _left(obj);
466 rect.MinY = _top(obj);
467 rect.MaxX = _right(obj);
468 rect.MaxY = _bottom(obj);
470 region = NewRegion();
471 if (region)
473 OrRectRegion(region, &rect);
475 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
478 DoSuperMethodA(cl, obj, (Msg)msg);
480 /* Render our graph.. */
481 if ((msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE)))
483 if (data->graph_RastPort)
485 renderPort = data->graph_RastPort;
486 rect.MinX = 0;
487 rect.MinY = 0;
488 rect.MaxX = _right(obj) - _left(obj);
489 rect.MaxY = _bottom(obj) - _top(obj);
491 else
492 renderPort = _rp(obj);
494 objHeight = rect.MaxY - rect.MinY;
496 data->graph_PeriodSize = ((rect.MaxX - rect.MinX + 1) * data->ihn.ihn_Millis) / data->graph_PeriodCeiling;
497 if (data->graph_PeriodSize < 1)
498 data->graph_PeriodSize = 1;
500 if (data->graph_Flags & GRAPHF_PERIODIC)
501 offset = (data->graph_Tick * data->graph_PeriodSize);
504 bug("[Graph] %s: height %d\n", __func__, objHeight);
505 bug("[Graph] %s: periodsize %d, offset %d\n", __func__, data->graph_PeriodSize, offset);
508 // First fill the background ..
509 SetAPen(renderPort, data->graph_BackPen);
510 RectFill(renderPort, rect.MinX, rect.MinY, rect.MaxX, rect.MaxY);
512 // Draw the segment divisions..
513 SetAPen(renderPort, data->graph_SegmentPen);
514 data->graph_SegmentSize = ((rect.MaxX - rect.MinX + 1) * data->graph_PeriodStepping) / data->graph_PeriodCeiling;
515 if (data->graph_SegmentSize < 2)
516 data->graph_SegmentSize = 2;
517 for (pos = rect.MinX; pos <= (rect.MaxX + data->graph_SegmentSize); pos += data->graph_SegmentSize)
519 Move(renderPort, pos - offset, rect.MinY);
520 Draw(renderPort, pos - offset, rect.MaxY);
522 data->graph_SegmentSize = ((rect.MaxY - rect.MinY + 1) * data->graph_ValStepping) / data->graph_ValCeiling;
523 if (data->graph_SegmentSize < 2)
524 data->graph_SegmentSize = 2;
525 for (pos = rect.MaxY; pos >= rect.MinY; pos -= data->graph_SegmentSize)
527 Move(renderPort, rect.MinX, pos);
528 Draw(renderPort, rect.MaxX, pos);
531 // Draw the Axis..
532 SetAPen(renderPort, data->graph_AxisPen);
533 Move(renderPort, rect.MinX, rect.MinY);
534 Draw(renderPort, rect.MaxX, rect.MinY);
535 Draw(renderPort, rect.MaxX, rect.MaxY);
536 Draw(renderPort, rect.MinX, rect.MaxY);
537 Draw(renderPort, rect.MinX, rect.MinY);
539 // Plot the entries..
540 if (data->graph_Sources)
542 for (src = 0; src < data->graph_SourceCount; src ++)
544 UWORD xpos, ypos;
546 sourceData = &data->graph_Sources[src];
548 ypos = (objHeight * sourceData->gs_Entries[0])/ data->graph_ValCeiling;
549 if (data->graph_Flags & GRAPHF_PERIODIC)
550 xpos = rect.MaxX - (data->graph_EntryPtr * data->graph_PeriodSize);
551 else
552 xpos = rect.MinX - offset;
554 SetAPen(renderPort, data->graph_Sources[src].gs_PlotPen);
556 if (data->graph_EntryPtr == 0)
558 WritePixel(renderPort, xpos - offset, rect.MaxY - ypos);
560 else
562 Move(renderPort, xpos - offset, rect.MaxY - ypos);
564 for (pos = 1; pos < data->graph_EntryPtr; pos++)
566 ypos = (objHeight * sourceData->gs_Entries[pos])/ data->graph_ValCeiling;
568 D(bug("[Graph] %s: YPos = %d\n", __func__, ypos);)
570 Draw(renderPort,
571 xpos + (pos * data->graph_PeriodSize),
572 rect.MaxY - ypos);
578 // Add the InfoText
579 pos = ((rect.MinY + rect.MaxY) /2) - ((_font(obj)->tf_YSize * data->graph_ITHeight) /2) + _font(obj)->tf_Baseline;
581 if (!IsListEmpty(&data->graph_InfoText))
582 SetFont(renderPort, _font(obj));
584 ForeachNode(&data->graph_InfoText, infoLine)
586 UWORD txtLen = strlen(infoLine->ln_Name);
587 UWORD textWidth = TextLength(renderPort, infoLine->ln_Name, txtLen);
589 D(bug("[Graph] %s: pos = %d, strlen = %d, wid = %d\n", __func__, pos, txtLen, textWidth);)
591 if (textWidth > 0)
593 SetAPen(renderPort, _pens(obj)[MPEN_TEXT]);
594 Move(renderPort, ((rect.MinX + rect.MaxX) /2) - (textWidth / 2), pos);
595 Text(renderPort, (CONST_STRPTR)infoLine->ln_Name, txtLen);
596 pos += _font(obj)->tf_YSize;
599 if (renderPort != _rp(obj))
601 BltBitMapRastPort(
602 renderPort->BitMap,
605 _rp(obj),
606 _left(obj),
607 _top(obj),
608 _right(obj) - _left(obj) + 1,
609 _bottom(obj) - _top(obj) + 1,
610 0x0C0 );
613 if (region)
615 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
618 D(bug("[Graph] %s: done\n", __func__);)
620 return 0;
623 IPTR Graph__MUIM_Graph_GetSourceHandle(Class *cl, Object *obj, struct MUIP_Graph_GetSourceHandle *msg)
625 struct Graph_DATA *data;
626 IPTR retVal = 0;
628 D(bug("[Graph] %s(%d)\n", __func__, msg->SourceNo);)
630 data = INST_DATA(cl, obj);
631 if (msg->SourceNo >= data->graph_SourceCount)
632 Graph__UpdateSourceArray(data, (msg->SourceNo + 1));
634 retVal = (IPTR)&data->graph_Sources[msg->SourceNo];
636 return retVal;
639 IPTR Graph__MUIM_Graph_SetSourceAttrib(Class *cl, Object *obj, struct MUIP_Graph_SetSourceAttrib *msg)
641 struct Graph_SourceDATA *dataSource = (struct Graph_SourceDATA *)msg->SourceHandle;
643 D(bug("[Graph] %s()\n", __func__);)
645 switch (msg->Attrib)
647 case MUIV_Graph_Source_ReadHook:
648 dataSource->gs_ReadHook = (struct Hook *)msg->AttribVal;
649 break;
650 case MUIV_Graph_Source_Pen:
651 dataSource->gs_PlotPen = (WORD)msg->AttribVal;
652 break;
653 case MUIV_Graph_Source_FillPen:
654 dataSource->gs_PlotFillPen = (WORD)msg->AttribVal;
655 break;
658 return 0;
661 IPTR Graph__MUIM_Graph_Reset(Class *cl, Object *obj, Msg msg)
663 D(bug("[Graph] %s()\n", __func__);)
665 return 0;
668 IPTR Graph__MUIM_Graph_Timer(Class *cl, Object *obj, Msg msg)
670 struct Graph_DATA *data;
671 int i;
673 D(bug("[Graph] %s()\n", __func__);)
675 data = INST_DATA(cl, obj);
677 if (data->graph_Tick++ == (data->graph_PeriodStepping / data->ihn.ihn_Millis))
678 data->graph_Tick = 0;
680 if (data->graph_Flags & GRAPHF_PERIODIC)
682 if (data->graph_SourceCount > 0)
684 BOOL updateEntries = FALSE, updated = FALSE, move = FALSE;
686 if (data->graph_Flags & GRAPHF_FIXEDLEN)
688 if (data->graph_EntryPtr >= data->graph_EntryCount)
690 data->graph_EntryPtr = data->graph_EntryCount - 1;
691 move = TRUE;
694 else
696 if (!(data->graph_EntryCount) || (data->graph_EntryPtr >= data->graph_EntryCount))
697 updateEntries = TRUE;
700 D(bug("[Graph] %s: reading entry %d\n", __func__, data->graph_EntryPtr);)
702 for (i = 0; i < data->graph_SourceCount; i ++)
704 if (data->graph_Sources[i].gs_ReadHook)
706 if (updateEntries)
708 Graph__UpdateSourceEntries(data, i, (data->graph_EntryPtr + 1));
709 updated = TRUE;
712 if (move)
714 CopyMem(&data->graph_Sources[i].gs_Entries[1], &data->graph_Sources[i].gs_Entries[0], sizeof(IPTR) * (data->graph_EntryCount - 1));
717 D(bug("[Graph] %s: source %d entries @ 0x%p\n", __func__, i, data->graph_Sources[i].gs_Entries);)
718 CALLHOOKPKT(data->graph_Sources[i].gs_ReadHook,
719 (APTR)&data->graph_Sources[i].gs_Entries[data->graph_EntryPtr],
720 data->graph_Sources[i].gs_ReadHook->h_Data);
723 if (updated)
724 data->graph_EntryCount++;
725 data->graph_EntryPtr++;
728 SET(obj, MUIA_Graph_PeriodicTick, TRUE);
731 return 0;