* Bug #12057 fixed - Scopes with big scope buffer size simulation was much
[scilab.git] / scilab / modules / scicos_blocks / src / c / cscope.c
index d847337..2c5d6a7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- *  Copyright (C) 2011 - Scilab Enterprises - Clement DAVID
+ *  Copyright (C) 2011-2012 - Scilab Enterprises - Clement DAVID
  *
  *  This file must be used under the terms of the CeCILL.
  *  This source file is licensed as described in the file COPYING, which
@@ -22,6 +22,7 @@
 #include "setGraphicObjectProperty.h"
 #include "graphicObjectProperties.h"
 #include "createGraphicObject.h"
+#include "deleteGraphicObject.h"
 
 #include "CurrentFigure.h"
 #include "CurrentObject.h"
@@ -38,6 +39,8 @@
 #include "BuildObjects.h"
 #include "AxesModel.h"
 
+#define HISTORY_POINTS_THRESHOLD 4096
+
 /*****************************************************************************
  * Internal container structure
  ****************************************************************************/
@@ -50,17 +53,22 @@ typedef struct
     struct
     {
         int numberOfPoints;
+        double ***bufferCoordinates;
         int maxNumberOfPoints;
-        double ***coordinates;
+        double ***historyCoordinates;
     } internal;
 
     struct
     {
         int periodCounter;
 
+        BOOL disableBufferUpdate;
+        int historyUpdateCounter;
+
         char const* cachedFigureUID;
         char *cachedAxeUID;
-        char **cachedPolylinesUIDs;
+        char **cachedBufferPolylinesUIDs;
+        char **cachedHistoryPolylinesUIDs;
     } scope;
 } sco_data;
 
@@ -79,13 +87,25 @@ static sco_data *getScoData(scicos_block * block);
 static void freeScoData(scicos_block * block);
 
 /**
- * Realloc any internal data
+ * Realloc the history buffer data
  *
  * \param block the block
- * \param input the selected input
  * \param numberOfPoints realloc to store this number of points
  */
-static sco_data *reallocScoData(scicos_block * block, int numberOfPoints);
+static sco_data *reallocHistoryBuffer(scicos_block * block, int numberOfPoints);
+
+/**
+ * Set values into the coordinates buffer.
+ *
+ * \param block the block
+ * \param coordinates the buffer
+ * \param numberOfPoints the number of points to set (actual)
+ * \param bufferPoints the buffer size (max)
+ * \param t the time to set
+ * \param value the value to set
+ */
+static void setBuffersCoordinates(scicos_block * block, double* coordinates, const int numberOfPoints,
+                                  const int bufferPoints, const double t, const double value);
 
 /**
  * Append the data to the current data
@@ -135,18 +155,26 @@ static char *getAxe(char const* pFigureUID, scicos_block * block, int input);
  * \param pAxeUID the parent axe UID
  * \param block the block
  * \param row the current row index (0-indexed)
+ * \param history get the history polyline
  * \return a valid polyline UID or NULL on error
  */
-static char *getPolyline(char *pAxeUID, scicos_block * block, int row);
+static char *getPolyline(char *pAxeUID, scicos_block * block, int row, BOOL history);
 
 /**
- * Set the polylines buffer size
+ * Delete all the buffer polylines.
+ *
+ * \param block the block
+ */
+static void deleteBufferPolylines(scicos_block * block);
+
+/**
+ * Set the polylines history size and push the history buffer
  *
  * \param block the block
  * \param input the input port index
  * \param maxNumberOfPoints the size of the buffer
  */
-static BOOL setPolylinesBuffers(scicos_block * block, int input, int maxNumberOfPoints);
+static BOOL pushHistory(scicos_block * block, int input, int maxNumberOfPoints);
 
 /**
  * Set the polylines bounds
@@ -222,6 +250,12 @@ SCICOS_BLOCKS_IMPEXP void cscope(scicos_block * block, scicos_flag flag)
             break;
 
         case Ending:
+            sco = getScoData(block);
+            sco = reallocHistoryBuffer(block, sco->internal.maxNumberOfPoints + sco->internal.numberOfPoints);
+            sco->scope.disableBufferUpdate = FALSE;
+            sco->scope.historyUpdateCounter = 0;
+            pushHistory(block, 0, sco->internal.maxNumberOfPoints);
+            deleteBufferPolylines(block);
             freeScoData(block);
             break;
 
@@ -255,40 +289,65 @@ static sco_data *getScoData(scicos_block * block)
             goto error_handler_sco;
         }
 
+        // 0 points out of a block->ipar[2] points buffer
         sco->internal.numberOfPoints = 0;
-        sco->internal.maxNumberOfPoints = block->ipar[2];
 
-        sco->internal.coordinates = (double ***)CALLOC(block->nin, sizeof(double **));
-        if (sco->internal.coordinates == NULL)
+        sco->internal.bufferCoordinates = (double ***)CALLOC(block->nin, sizeof(double **));
+        if (sco->internal.bufferCoordinates == NULL)
         {
-            goto error_handler_coordinates;
+            goto error_handler_bufferCoordinates;
         }
 
         for (i = 0; i < block->nin; i++)
         {
-            sco->internal.coordinates[i] = (double **)CALLOC(block->insz[i], sizeof(double *));
-            if (sco->internal.coordinates[i] == NULL)
+            sco->internal.bufferCoordinates[i] = (double **)CALLOC(block->insz[i], sizeof(double *));
+            if (sco->internal.bufferCoordinates[i] == NULL)
             {
-                goto error_handler_coordinates_i;
+                goto error_handler_bufferCoordinates_i;
             }
         }
         for (i = 0; i < block->nin; i++)
         {
             for (j = 0; j < block->insz[i]; j++)
             {
-                sco->internal.coordinates[i][j] = (double *)CALLOC(3 * block->ipar[2], sizeof(double));
+                sco->internal.bufferCoordinates[i][j] = (double *)CALLOC(3 * block->ipar[2], sizeof(double));
 
-                if (sco->internal.coordinates[i][j] == NULL)
+                if (sco->internal.bufferCoordinates[i][j] == NULL)
                 {
-                    goto error_handler_coordinates_ij;
+                    goto error_handler_bufferCoordinates_ij;
                 }
             }
         }
 
+        // 0 points out of a 0 points history
+        sco->internal.maxNumberOfPoints = 0;
+
+        sco->internal.historyCoordinates = (double ***)CALLOC(block->nin, sizeof(double **));
+        if (sco->internal.historyCoordinates == NULL)
+        {
+            goto error_handler_historyCoordinates;
+        }
+
+        for (i = 0; i < block->nin; i++)
+        {
+            sco->internal.historyCoordinates[i] = (double **)CALLOC(block->insz[i], sizeof(double *));
+            if (sco->internal.historyCoordinates[i] == NULL)
+            {
+                goto error_handler_historyCoordinates_i;
+            }
+        }
+
         sco->scope.periodCounter = 0;
+
+        // flag to avoid pushing the buffer each time
+        sco->scope.disableBufferUpdate = FALSE;
+        // counter use to delay the history push
+        sco->scope.historyUpdateCounter = 0;
+
         sco->scope.cachedFigureUID = NULL;
         sco->scope.cachedAxeUID = NULL;
-        sco->scope.cachedPolylinesUIDs = (char **)CALLOC(block->insz[0], sizeof(char *));
+        sco->scope.cachedBufferPolylinesUIDs = (char **)CALLOC(block->insz[0], sizeof(char *));
+        sco->scope.cachedHistoryPolylinesUIDs = (char **)CALLOC(block->insz[0], sizeof(char *));
 
         *(block->work) = sco;
     }
@@ -299,22 +358,31 @@ static sco_data *getScoData(scicos_block * block)
      * Error management (out of normal flow)
      */
 
-error_handler_coordinates_ij:
+error_handler_historyCoordinates_i:
+    for (j = 0; j < i; j++)
+    {
+        FREE(sco->internal.historyCoordinates[i]);
+    }
+    FREE(sco->internal.historyCoordinates);
+error_handler_historyCoordinates:
+    i = block->nin - 1;
+    j = block->insz[i] - 1;
+error_handler_bufferCoordinates_ij:
     for (k = 0; k < i; k++)
     {
         for (l = 0; l < j; l++)
         {
-            FREE(sco->internal.coordinates[k][l]);
+            FREE(sco->internal.bufferCoordinates[k][l]);
         }
     }
     i = block->nin - 1;
-error_handler_coordinates_i:
+error_handler_bufferCoordinates_i:
     for (j = 0; j < i; j++)
     {
-        FREE(sco->internal.coordinates[i]);
+        FREE(sco->internal.bufferCoordinates[i]);
     }
-    FREE(sco->internal.coordinates);
-error_handler_coordinates:
+    FREE(sco->internal.bufferCoordinates);
+error_handler_bufferCoordinates:
     FREE(sco);
 error_handler_sco:
     // allocation error
@@ -333,15 +401,22 @@ static void freeScoData(scicos_block * block)
         {
             for (j = 0; j < block->insz[i]; j++)
             {
-                FREE(sco->internal.coordinates[i][j]);
+                if (sco->internal.historyCoordinates[i][j] != NULL)
+                {
+                    FREE(sco->internal.historyCoordinates[i][j]);
+                }
+                FREE(sco->internal.bufferCoordinates[i][j]);
             }
-            FREE(sco->internal.coordinates[i]);
+            FREE(sco->internal.historyCoordinates[i]);
+            FREE(sco->internal.bufferCoordinates[i]);
         }
-        FREE(sco->internal.coordinates);
+        FREE(sco->internal.historyCoordinates);
+        FREE(sco->internal.bufferCoordinates);
 
         for (i = 0; i < block->insz[0]; i++)
         {
-            FREE(sco->scope.cachedPolylinesUIDs[i]);
+            FREE(sco->scope.cachedHistoryPolylinesUIDs[i]);
+            FREE(sco->scope.cachedBufferPolylinesUIDs[i]);
         }
         FREE(sco->scope.cachedAxeUID);
 
@@ -350,47 +425,71 @@ static void freeScoData(scicos_block * block)
     }
 }
 
-static sco_data *reallocScoData(scicos_block * block, int numberOfPoints)
+static sco_data *reallocHistoryBuffer(scicos_block * block, int numberOfPoints)
 {
     sco_data *sco = (sco_data *) * (block->work);
-    int i, j;
+    int i;
 
     double *ptr;
-    int setLen;
+    int allocatedNumberOfPoints;
+
     int previousNumberOfPoints = sco->internal.maxNumberOfPoints;
-    int newPoints = numberOfPoints - previousNumberOfPoints;
+    int numberOfCopiedPoints = numberOfPoints - sco->internal.maxNumberOfPoints;
 
-    for (i = 0; i < block->nin; i++)
+    double *buffer;
+    int bufferNumberOfPoints = block->ipar[2];
+    int bufferNewPointInc;
+
+    if (previousNumberOfPoints == 0)
     {
-        for (j = 0; j < block->insz[i]; j++)
+        allocatedNumberOfPoints = numberOfPoints;
+        bufferNewPointInc = 0;
+    }
+    else
+    {
+        allocatedNumberOfPoints = numberOfPoints - 1;
+        bufferNewPointInc = 1;
+    }
+
+    if (sco->scope.historyUpdateCounter <= 0)
+    {
+        if (numberOfPoints > HISTORY_POINTS_THRESHOLD)
         {
-            ptr = (double *)REALLOC(sco->internal.coordinates[i][j], 3 * numberOfPoints * sizeof(double));
-            if (ptr == NULL)
-            {
-                goto error_handler;
-            }
+            sco->scope.disableBufferUpdate = TRUE;
+            sco->scope.historyUpdateCounter = numberOfPoints / HISTORY_POINTS_THRESHOLD;
+        }
+        else
+        {
+            sco->scope.disableBufferUpdate = FALSE;
+            sco->scope.historyUpdateCounter = 0;
+        }
+    }
 
-            // clear the last points, the Z-axis values
-            memset(ptr + 2 * numberOfPoints, 0, numberOfPoints * sizeof(double));
+    for (i = 0; i < block->insz[0]; i++)
+    {
+        ptr = (double *)MALLOC(3 * allocatedNumberOfPoints * sizeof(double));
+        if (ptr == NULL)
+        {
+            goto error_handler;
+        }
 
-            // memcpy existing Y-axis values (use memmove to handle memory overlapping)
-            memmove(ptr + numberOfPoints, ptr + previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
+        // memcpy existing X-axis values from the history
+        memcpy(ptr, sco->internal.historyCoordinates[0][i], previousNumberOfPoints * sizeof(double));
+        // memcpy existing Y-axis values from the history
+        memcpy(ptr + allocatedNumberOfPoints, sco->internal.historyCoordinates[0][i] + previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
+        // clear the last points, the Z-axis values
+        memset(ptr + 2 * allocatedNumberOfPoints, 0, allocatedNumberOfPoints * sizeof(double));
 
-            // then set the last points to the last values for Y-axis and X-axis values
-            for (setLen = newPoints - 1; setLen >= 0; setLen--)
-            {
-                ptr[numberOfPoints + previousNumberOfPoints + setLen] = ptr[numberOfPoints + previousNumberOfPoints - 1];
-            }
-            for (setLen = newPoints - 1; setLen >= 0; setLen--)
-            {
-                ptr[previousNumberOfPoints + setLen] = ptr[previousNumberOfPoints - 1];
-            }
+        // then set the last points to the last values for X-axis and Y-axis values from the buffer points
+        buffer = sco->internal.bufferCoordinates[0][i];
+        memcpy(ptr + previousNumberOfPoints, buffer + bufferNewPointInc, (numberOfCopiedPoints - bufferNewPointInc) * sizeof(double));
+        memcpy(ptr + allocatedNumberOfPoints + previousNumberOfPoints, buffer + bufferNumberOfPoints + bufferNewPointInc, (numberOfCopiedPoints - bufferNewPointInc) * sizeof(double));
 
-            sco->internal.coordinates[i][j] = ptr;
-        }
+        FREE(sco->internal.historyCoordinates[0][i]);
+        sco->internal.historyCoordinates[0][i] = ptr;
     }
 
-    sco->internal.maxNumberOfPoints = numberOfPoints;
+    sco->internal.maxNumberOfPoints = allocatedNumberOfPoints;
     return sco;
 
 error_handler:
@@ -400,13 +499,37 @@ error_handler:
     return NULL;
 }
 
+static void setBuffersCoordinates(scicos_block* block, double* coordinates, const int numberOfPoints,
+                                  const int bufferPoints, const double t, const double value)
+{
+    int setLen;
+    sco_data *sco = (sco_data *) * (block->work);
+
+    if (sco->scope.disableBufferUpdate == TRUE)
+    {
+        coordinates[numberOfPoints] = t;
+        coordinates[bufferPoints + numberOfPoints] = value;
+        return;
+    }
+
+    // X-axis values first
+    for (setLen = numberOfPoints; setLen < bufferPoints; setLen++)
+    {
+        coordinates[setLen] = t;
+    }
+    // then Y-axis values
+    for (setLen = numberOfPoints; setLen < bufferPoints; setLen++)
+    {
+        coordinates[bufferPoints + setLen] = value;
+    }
+    // then Z-axis values (always clear'ed)
+}
+
 static void appendData(scicos_block * block, int input, double t, double *data)
 {
     int i;
 
     sco_data *sco = (sco_data *) * (block->work);
-    int maxNumberOfPoints = sco->internal.maxNumberOfPoints;
-    int numberOfPoints = sco->internal.numberOfPoints;
 
     /*
      * Handle the case where the t is greater than the data_bounds
@@ -415,8 +538,26 @@ static void appendData(scicos_block * block, int input, double t, double *data)
     {
         sco->scope.periodCounter++;
 
-        numberOfPoints = 0;
-        sco->internal.numberOfPoints = 0;
+        // set the buffer coordinates to the last point
+        for (i = 0; i < block->insz[input]; i++)
+        {
+            sco->internal.bufferCoordinates[input][i][0] = sco->internal.bufferCoordinates[input][i][sco->internal.numberOfPoints - 1];
+            sco->internal.bufferCoordinates[input][i][block->ipar[2]] = sco->internal.bufferCoordinates[input][i][block->ipar[2] + sco->internal.numberOfPoints - 1];
+        }
+        sco->internal.numberOfPoints = 1;
+
+        // clear the history coordinates
+        sco->internal.maxNumberOfPoints = 0;
+        for (i = 0; i < block->insz[input]; i++)
+        {
+            if (sco->internal.historyCoordinates[input][i] != NULL)
+            {
+                FREE(sco->internal.historyCoordinates[input][i]);
+                sco->internal.historyCoordinates[input][i] = NULL;
+            }
+        }
+
+        // configure scope setting
         if (setPolylinesBounds(block, input, sco->scope.periodCounter) == FALSE)
         {
             set_block_error(-5);
@@ -428,14 +569,24 @@ static void appendData(scicos_block * block, int input, double t, double *data)
     /*
      * Handle the case where the scope has more points than maxNumberOfPoints
      */
-    if (sco != NULL && numberOfPoints >= maxNumberOfPoints)
+    if (sco != NULL && sco->internal.numberOfPoints >= block->ipar[2])
     {
-        // on a full scope, re-alloc
+        int maxNumberOfPoints = sco->internal.maxNumberOfPoints;
+
+        // on a full scope, re-alloc history coordinates
         maxNumberOfPoints = maxNumberOfPoints + block->ipar[2];
-        sco = reallocScoData(block, maxNumberOfPoints);
+        sco = reallocHistoryBuffer(block, maxNumberOfPoints);
+
+        // set the buffer coordinates to the last point
+        for (i = 0; i < block->insz[input]; i++)
+        {
+            sco->internal.bufferCoordinates[input][i][0] = sco->internal.bufferCoordinates[input][i][block->ipar[2] - 1];
+            sco->internal.bufferCoordinates[input][i][block->ipar[2]] = sco->internal.bufferCoordinates[input][i][2 * block->ipar[2] - 1];
+        }
+        sco->internal.numberOfPoints = 1;
 
         // reconfigure related graphic objects
-        if (setPolylinesBuffers(block, input, maxNumberOfPoints) == FALSE)
+        if (pushHistory(block, input, sco->internal.maxNumberOfPoints) == FALSE)
         {
             set_block_error(-5);
             freeScoData(block);
@@ -448,23 +599,10 @@ static void appendData(scicos_block * block, int input, double t, double *data)
      */
     if (sco != NULL)
     {
-        int setLen;
-
         for (i = 0; i < block->insz[input]; i++)
         {
-            // X-axis values first
-            for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
-            {
-                sco->internal.coordinates[input][i][numberOfPoints + setLen] = t;
-            }
-
-            // then Y-axis values
-            for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
-            {
-                sco->internal.coordinates[input][i][maxNumberOfPoints + numberOfPoints + setLen] = data[i];
-            }
-
-            // do not update Z-axis values, always cleared
+            const double value = data[i];
+            setBuffersCoordinates(block, sco->internal.bufferCoordinates[input][i], sco->internal.numberOfPoints, block->ipar[2], t, value);
         }
 
         sco->internal.numberOfPoints++;
@@ -482,7 +620,7 @@ static BOOL pushData(scicos_block * block, int input, int row)
 
     pFigureUID = getFigure(block);
     pAxeUID = getAxe(pFigureUID, block, input);
-    pPolylineUID = getPolyline(pAxeUID, block, row);
+    pPolylineUID = getPolyline(pAxeUID, block, row, FALSE);
 
     sco = getScoData(block);
     if (sco == NULL)
@@ -490,10 +628,16 @@ static BOOL pushData(scicos_block * block, int input, int row)
         return FALSE;
     }
 
+    // do not push any data if disabled
+    if (sco->scope.disableBufferUpdate == TRUE)
+    {
+        return TRUE;
+    }
+
     // select the right input and row
-    data = sco->internal.coordinates[input][row];
+    data = sco->internal.bufferCoordinates[input][row];
 
-    return setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_COORDINATES__, data, jni_double_vector, sco->internal.maxNumberOfPoints);
+    return setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_COORDINATES__, data, jni_double_vector, block->ipar[2]);
 }
 
 /*****************************************************************************
@@ -655,7 +799,11 @@ static char *getAxe(char const* pFigureUID, scicos_block * block, int input)
         // allocate the polylines through the getter
         for (i = 0; i < block->insz[input]; i++)
         {
-            getPolyline(pAxe, block, i);
+            getPolyline(pAxe, block, i, TRUE);
+        }
+        for (i = 0; i < block->insz[input]; i++)
+        {
+            getPolyline(pAxe, block, i, FALSE);
         }
     }
 
@@ -670,13 +818,17 @@ static char *getAxe(char const* pFigureUID, scicos_block * block, int input)
     return sco->scope.cachedAxeUID;
 }
 
-static char *getPolyline(char *pAxeUID, scicos_block * block, int row)
+static char *getPolyline(char *pAxeUID, scicos_block * block, int row, BOOL history)
 {
     char *pPolyline;
     BOOL b__true = TRUE;
 
     int color;
 
+    char** polylinesUIDs;
+    int polylineIndex;
+    int polylineDefaultNumElement;
+
     sco_data *sco = (sco_data *) * (block->work);
 
     // assert the sco is not NULL
@@ -685,13 +837,26 @@ static char *getPolyline(char *pAxeUID, scicos_block * block, int row)
         return NULL;
     }
 
+    if (!history)
+    {
+        polylinesUIDs = sco->scope.cachedBufferPolylinesUIDs;
+        polylineIndex = block->insz[0] + row;
+        polylineDefaultNumElement = block->ipar[2];
+    }
+    else
+    {
+        polylinesUIDs = sco->scope.cachedHistoryPolylinesUIDs;
+        polylineIndex = row;
+        polylineDefaultNumElement = 0;
+    }
+
     // fast path for an existing object
-    if (sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[row] != NULL)
+    if (polylinesUIDs != NULL && polylinesUIDs[row] != NULL)
     {
-        return sco->scope.cachedPolylinesUIDs[row];
+        return polylinesUIDs[row];
     }
 
-    pPolyline = findChildWithKindAt(pAxeUID, __GO_POLYLINE__, row);
+    pPolyline = findChildWithKindAt(pAxeUID, __GO_POLYLINE__, polylineIndex);
 
     /*
      * Allocate if necessary
@@ -717,7 +882,7 @@ static char *getPolyline(char *pAxeUID, scicos_block * block, int row)
          * Default setup (will crash if removed)
          */
         {
-            int polylineSize[2] = { 1, block->ipar[2] };
+            int polylineSize[2] = { 1, polylineDefaultNumElement };
             setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_NUM_ELEMENTS_ARRAY__, polylineSize, jni_int_vector, 2);
         }
 
@@ -743,15 +908,34 @@ static char *getPolyline(char *pAxeUID, scicos_block * block, int row)
     /*
      * then cache with local storage
      */
-    if (pPolyline != NULL && sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[row] == NULL)
+    if (pPolyline != NULL && polylinesUIDs != NULL && polylinesUIDs[row] == NULL)
     {
-        sco->scope.cachedPolylinesUIDs[row] = strdup(pPolyline);
+        polylinesUIDs[row] = strdup(pPolyline);
         releaseGraphicObjectProperty(__GO_PARENT__, pPolyline, jni_string, 1);
     }
-    return sco->scope.cachedPolylinesUIDs[row];
+    return polylinesUIDs[row];
 }
 
-static BOOL setPolylinesBuffers(scicos_block * block, int input, int maxNumberOfPoints)
+static void deleteBufferPolylines(scicos_block * block)
+{
+    int i, j;
+
+    char *pPolylineUID;
+
+    sco_data *sco;
+
+    sco = getScoData(block);
+    for (i = 0; i < block->nin; i++)
+    {
+        for (j = 0; j < block->insz[i]; j++)
+        {
+            pPolylineUID = sco->scope.cachedBufferPolylinesUIDs[j];
+            deleteGraphicObject(pPolylineUID);
+        }
+    }
+}
+
+static BOOL pushHistory(scicos_block * block, int input, int maxNumberOfPoints)
 {
     int i;
 
@@ -759,16 +943,33 @@ static BOOL setPolylinesBuffers(scicos_block * block, int input, int maxNumberOf
     char *pAxeUID;
     char *pPolylineUID;
 
+    double *data;
+    sco_data *sco;
+
     BOOL result = TRUE;
     int polylineSize[2] = { 1, maxNumberOfPoints };
 
+    sco = getScoData(block);
     pFigureUID = getFigure(block);
     pAxeUID = getAxe(pFigureUID, block, input);
 
+    // push the data only if the counter == 0, decrement the counter if positive
+    if (sco->scope.historyUpdateCounter > 0)
+    {
+        sco->scope.historyUpdateCounter--;
+    }
+    if (sco->scope.historyUpdateCounter > 0)
+    {
+        return result;
+    }
+
     for (i = 0; i < block->insz[input]; i++)
     {
-        pPolylineUID = getPolyline(pAxeUID, block, i);
+        pPolylineUID = getPolyline(pAxeUID, block, i, TRUE);
         result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_NUM_ELEMENTS_ARRAY__, polylineSize, jni_int_vector, 2);
+
+        data = sco->internal.historyCoordinates[input][i];
+        result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_COORDINATES__, data, jni_double_vector, maxNumberOfPoints);
     }
 
     return result;