* Bug #12057 fixed - Scopes with big scope buffer size simulation was much
[scilab.git] / scilab / modules / scicos_blocks / src / c / cmscope.c
index e154dc3..574f09c 100644 (file)
@@ -22,6 +22,7 @@
 #include "setGraphicObjectProperty.h"
 #include "graphicObjectProperties.h"
 #include "createGraphicObject.h"
+#include "deleteGraphicObject.h"
 
 #include "CurrentFigure.h"
 #include "CurrentObject.h"
@@ -42,6 +43,8 @@
 // #define LOG(...) printf(__VA_ARGS__)
 #define LOG(...)
 
+#define HISTORY_POINTS_THRESHOLD 4096
+
 /*****************************************************************************
  * Internal container structure
  ****************************************************************************/
@@ -54,17 +57,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;
 
@@ -83,13 +91,27 @@ 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 input, int numberOfPoints);
+static sco_data *reallocHistoryBuffer(scicos_block * block, int input, int numberOfPoints);
+
+/**
+ * Set values into the coordinates buffer.
+ *
+ * \param block the block
+ * \param input the selected input
+ * \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, int input, double* coordinates, const int numberOfPoints,
+                                  const int bufferPoints, const double t, const double value);
 
 /**
  * Append the data to the current data
@@ -140,18 +162,26 @@ static char *getAxe(char const* pFigureUID, scicos_block * block, int input);
  * \param block the block
  * \param input the current input index (0-indexed)
  * \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 input, int row);
+static char *getPolyline(char *pAxeUID, scicos_block * block, int input, int row, BOOL history);
+
+/**
+ * Delete all the buffer polylines.
+ *
+ * \param block the block
+ */
+static void deleteBufferPolylines(scicos_block * block);
 
 /**
- * Set the polylines buffer size
+ * 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
@@ -229,6 +259,15 @@ SCICOS_BLOCKS_IMPEXP void cmscope(scicos_block * block, scicos_flag flag)
             break;
 
         case Ending:
+            sco = getScoData(block);
+            for (i = 0; i < block->nin; i++)
+            {
+                sco = reallocHistoryBuffer(block, i, sco->internal.maxNumberOfPoints[i] + sco->internal.numberOfPoints[i]);
+                sco->scope.disableBufferUpdate[i] = FALSE;
+                sco->scope.historyUpdateCounter[i] = 0;
+                pushHistory(block, i, sco->internal.maxNumberOfPoints[i]);
+            }
+            deleteBufferPolylines(block);
             freeScoData(block);
             break;
 
@@ -275,50 +314,80 @@ static sco_data *getScoData(scicos_block * block)
 
         for (i = 0; i < block->nin; i++)
         {
+            // 0 points out of a block->ipar[2] points buffer
             sco->internal.numberOfPoints[i] = 0;
-            sco->internal.maxNumberOfPoints[i] = block->ipar[2];
+            // 0 points out of a 0 points history
+            sco->internal.maxNumberOfPoints[i] = 0;
         }
 
-        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;
                 }
             }
         }
 
+        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 = (int *) CALLOC(block->nin, sizeof(int));
         if (sco->scope.periodCounter == NULL)
         {
             goto error_handler_periodCounter;
         }
 
+        sco->scope.disableBufferUpdate = (int *) CALLOC(block->nin, sizeof(BOOL));
+        if (sco->scope.disableBufferUpdate == NULL)
+        {
+            goto error_handler_disableBufferUpdate;
+        }
+        sco->scope.historyUpdateCounter = (int *) CALLOC(block->nin, sizeof(int));
+        if (sco->scope.historyUpdateCounter == NULL)
+        {
+            goto error_handler_historyUpdateCounter;
+        }
+
         sco->scope.cachedFigureUID = NULL;
         sco->scope.cachedAxeUID = (char **)CALLOC(block->nin, sizeof(char *));
 
-        sco->scope.cachedPolylinesUIDs = (char ***)CALLOC(block->nin, sizeof(char **));
+        sco->scope.cachedBufferPolylinesUIDs = (char ***)CALLOC(block->nin, sizeof(char **));
+        sco->scope.cachedHistoryPolylinesUIDs = (char ***)CALLOC(block->nin, sizeof(char **));
         for (i = 0; i < block->nin; i++)
         {
-            sco->scope.cachedPolylinesUIDs[i] = (char **)CALLOC(block->insz[i], sizeof(char *));
+            sco->scope.cachedBufferPolylinesUIDs[i] = (char **)CALLOC(block->insz[i], sizeof(char *));
+            sco->scope.cachedHistoryPolylinesUIDs[i] = (char **)CALLOC(block->insz[i], sizeof(char *));
         }
 
         *(block->work) = sco;
@@ -329,25 +398,38 @@ static sco_data *getScoData(scicos_block * block)
     /*
      * Error management (out of normal flow)
      */
+
+error_handler_historyUpdateCounter:
+    FREE(sco->scope.disableBufferUpdate);
+error_handler_disableBufferUpdate:
+    FREE(sco->scope.periodCounter);
 error_handler_periodCounter:
+    i = block->nin;
+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 = 2 ^ 31;
-error_handler_coordinates_ij:
+    j = block->insz[i] - 1;
+error_handler_bufferCoordinates_ij:
     for (k = 0; k < i; k++)
     {
-        for (l = 0; l < j && l < block->insz[i]; l++)
+        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->internal.maxNumberOfPoints);
 error_handler_maxNumberOfPoints:
     FREE(sco->internal.numberOfPoints);
@@ -370,66 +452,100 @@ 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->nin; i++)
+        FREE(sco->scope.periodCounter);
+
+        FREE(sco->scope.disableBufferUpdate);
+        FREE(sco->scope.historyUpdateCounter);
+
+        for (i = 0; i < block->insz[0]; i++)
         {
-            for (j = 0; j < block->insz[i]; j++)
-            {
-                FREE(sco->scope.cachedPolylinesUIDs[i][j]);
-            }
-            FREE(sco->scope.cachedAxeUID[i]);
+            FREE(sco->scope.cachedHistoryPolylinesUIDs[i]);
+            FREE(sco->scope.cachedBufferPolylinesUIDs[i]);
         }
+        FREE(sco->scope.cachedAxeUID);
 
         FREE(sco);
         *(block->work) = NULL;
     }
 }
 
-static sco_data *reallocScoData(scicos_block * block, int input, int numberOfPoints)
+static sco_data *reallocHistoryBuffer(scicos_block * block, int input, int numberOfPoints)
 {
     sco_data *sco = (sco_data *) * (block->work);
     int i;
 
     double *ptr;
-    int setLen;
+    int allocatedNumberOfPoints;
+
     int previousNumberOfPoints = sco->internal.maxNumberOfPoints[input];
-    int newPoints = numberOfPoints - previousNumberOfPoints;
+    int numberOfCopiedPoints = numberOfPoints - sco->internal.maxNumberOfPoints[input];
 
-    LOG("%s: %s at %d to %d\n", "cmscope", "reallocScoData", input, numberOfPoints);
+    double *buffer;
+    int bufferNumberOfPoints = block->ipar[2];
+    int bufferNewPointInc;
+
+    if (previousNumberOfPoints == 0)
+    {
+        allocatedNumberOfPoints = numberOfPoints;
+        bufferNewPointInc = 0;
+    }
+    else
+    {
+        allocatedNumberOfPoints = numberOfPoints - 1;
+        bufferNewPointInc = 1;
+    }
+
+    if (sco->scope.historyUpdateCounter[input] <= 0)
+    {
+        if (numberOfPoints > HISTORY_POINTS_THRESHOLD)
+        {
+            sco->scope.disableBufferUpdate[input] = TRUE;
+            sco->scope.historyUpdateCounter[input] = numberOfPoints / HISTORY_POINTS_THRESHOLD;
+        }
+        else
+        {
+            sco->scope.disableBufferUpdate[input] = FALSE;
+            sco->scope.historyUpdateCounter[input] = 0;
+        }
+    }
 
     for (i = 0; i < block->insz[input]; i++)
     {
-        ptr = (double *)REALLOC(sco->internal.coordinates[input][i], 3 * numberOfPoints * sizeof(double));
+        ptr = (double *)MALLOC(3 * allocatedNumberOfPoints * sizeof(double));
         if (ptr == NULL)
         {
             goto error_handler;
         }
 
+        // memcpy existing X-axis values from the history
+        memcpy(ptr, sco->internal.historyCoordinates[input][i], previousNumberOfPoints * sizeof(double));
+        // memcpy existing Y-axis values from the history
+        memcpy(ptr + allocatedNumberOfPoints, sco->internal.historyCoordinates[input][i] + previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
         // clear the last points, the Z-axis values
-        memset(ptr + 2 * numberOfPoints, 0, numberOfPoints * sizeof(double));
-
-        // memcpy existing Y-axis values (use memmove to handle memory overlapping)
-        memmove(ptr + numberOfPoints, ptr + previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
+        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[input][i];
+        memcpy(ptr + previousNumberOfPoints, buffer + bufferNewPointInc, (numberOfCopiedPoints - bufferNewPointInc) * sizeof(double));
+        memcpy(ptr + allocatedNumberOfPoints + previousNumberOfPoints, buffer + bufferNumberOfPoints + bufferNewPointInc, (numberOfCopiedPoints - bufferNewPointInc) * sizeof(double));
 
-        sco->internal.coordinates[input][i] = ptr;
+        FREE(sco->internal.historyCoordinates[input][i]);
+        sco->internal.historyCoordinates[input][i] = ptr;
     }
 
-    sco->internal.maxNumberOfPoints[input] = numberOfPoints;
+    sco->internal.maxNumberOfPoints[input] = allocatedNumberOfPoints;
     return sco;
 
 error_handler:
@@ -439,14 +555,37 @@ error_handler:
     return NULL;
 }
 
+static void setBuffersCoordinates(scicos_block * block, int input, 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[input] == 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[input];
-    int numberOfPoints = sco->internal.numberOfPoints[input];
-
 
     /*
      * Handle the case where the t is greater than the data_bounds
@@ -455,8 +594,26 @@ static void appendData(scicos_block * block, int input, double t, double *data)
     {
         sco->scope.periodCounter[input]++;
 
-        numberOfPoints = 0;
-        sco->internal.numberOfPoints[input] = 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[input] - 1];
+            sco->internal.bufferCoordinates[input][i][block->ipar[2]] = sco->internal.bufferCoordinates[input][i][block->ipar[2] + sco->internal.numberOfPoints[input] - 1];
+        }
+        sco->internal.numberOfPoints[input] = 1;
+
+        // clear the history coordinates
+        sco->internal.maxNumberOfPoints[input] = 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[input]) == FALSE)
         {
             set_block_error(-5);
@@ -468,14 +625,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[input] >= block->ipar[2])
     {
-        // on a full scope, re-alloc
+        int maxNumberOfPoints = sco->internal.maxNumberOfPoints[input];
+
+        // on a full scope, re-alloc history coordinates
         maxNumberOfPoints = maxNumberOfPoints + block->ipar[2];
-        sco = reallocScoData(block, input, maxNumberOfPoints);
+        sco = reallocHistoryBuffer(block, input, 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[input] = 1;
 
         // reconfigure related graphic objects
-        if (setPolylinesBuffers(block, input, maxNumberOfPoints) == FALSE)
+        if (pushHistory(block, input, sco->internal.maxNumberOfPoints[input]) == FALSE)
         {
             set_block_error(-5);
             freeScoData(block);
@@ -488,23 +655,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, input, sco->internal.bufferCoordinates[input][i], sco->internal.numberOfPoints[input], block->ipar[2], t, value);
         }
 
         sco->internal.numberOfPoints[input]++;
@@ -522,7 +676,7 @@ static BOOL pushData(scicos_block * block, int input, int row)
 
     pFigureUID = getFigure(block);
     pAxeUID = getAxe(pFigureUID, block, input);
-    pPolylineUID = getPolyline(pAxeUID, block, input, row);
+    pPolylineUID = getPolyline(pAxeUID, block, input, row, FALSE);
 
     sco = getScoData(block);
     if (sco == NULL)
@@ -530,10 +684,16 @@ static BOOL pushData(scicos_block * block, int input, int row)
         return FALSE;
     }
 
+    // do not push any data if disabled
+    if (sco->scope.disableBufferUpdate[input] == 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[input]);
+    return setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_COORDINATES__, data, jni_double_vector, block->ipar[2]);
 }
 
 /*****************************************************************************
@@ -552,6 +712,7 @@ static void setFigureSettings(char const* pFigureUID, scicos_block * block)
 {
     int win_pos[2];
     int win_dim[2];
+    char* label;
 
     int *ipar = block->ipar;
 
@@ -569,7 +730,16 @@ static void setFigureSettings(char const* pFigureUID, scicos_block * block)
     {
         setGraphicObjectProperty(pFigureUID, __GO_SIZE__, &win_dim, jni_int_vector, 2);
     }
-};
+
+    label = GetLabelPtrs(block);
+    if (label != NULL)
+    {
+        if (strlen(label) > 0)
+        {
+            setGraphicObjectProperty(pFigureUID, __GO_NAME__, label, jni_string, 1);
+        }
+    }
+}
 
 /**
  * Set properties on the axes.
@@ -711,7 +881,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, input, i);
+            getPolyline(pAxe, block, input, i, TRUE);
+        }
+        for (i = 0; i < block->insz[input]; i++)
+        {
+            getPolyline(pAxe, block, input, i, FALSE);
         }
 
         setAxesSettings(pAxe, block, input);
@@ -728,13 +902,17 @@ static char *getAxe(char const* pFigureUID, scicos_block * block, int input)
     return sco->scope.cachedAxeUID[input];
 }
 
-static char *getPolyline(char *pAxeUID, scicos_block * block, int input, int row)
+static char *getPolyline(char *pAxeUID, scicos_block * block, int input, 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
@@ -743,13 +921,26 @@ static char *getPolyline(char *pAxeUID, scicos_block * block, int input, int row
         return NULL;
     }
 
+    if (!history)
+    {
+        polylinesUIDs = sco->scope.cachedBufferPolylinesUIDs;
+        polylineIndex = block->insz[input] + 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[input] != NULL && sco->scope.cachedPolylinesUIDs[input][row] != NULL)
+    if (polylinesUIDs != NULL && polylinesUIDs[input] != NULL && polylinesUIDs[input][row] != NULL)
     {
-        return sco->scope.cachedPolylinesUIDs[input][row];
+        return polylinesUIDs[input][row];
     }
 
-    pPolyline = findChildWithKindAt(pAxeUID, __GO_POLYLINE__, row);
+    pPolyline = findChildWithKindAt(pAxeUID, __GO_POLYLINE__, polylineIndex);
 
     /*
      * Allocate if necessary
@@ -775,7 +966,7 @@ static char *getPolyline(char *pAxeUID, scicos_block * block, int input, 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);
         }
 
@@ -808,15 +999,34 @@ static char *getPolyline(char *pAxeUID, scicos_block * block, int input, int row
     /*
      * then cache with local storage
      */
-    if (sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[input] != NULL)
+    if (pPolyline != NULL && polylinesUIDs != NULL && polylinesUIDs[input] != NULL)
     {
-        sco->scope.cachedPolylinesUIDs[input][row] = strdup(pPolyline);
+        polylinesUIDs[input][row] = strdup(pPolyline);
         releaseGraphicObjectProperty(__GO_PARENT__, pPolyline, jni_string, 1);
     }
-    return sco->scope.cachedPolylinesUIDs[input][row];
+    return polylinesUIDs[input][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[i][j];
+            deleteGraphicObject(pPolylineUID);
+        }
+    }
+}
+
+static BOOL pushHistory(scicos_block * block, int input, int maxNumberOfPoints)
 {
     int i;
 
@@ -824,18 +1034,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 };
 
-    LOG("%s: %s at %d to %d\n", "cmscope", "setPolylinesBuffers", input, 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[input] > 0)
+    {
+        sco->scope.historyUpdateCounter[input]--;
+    }
+    if (sco->scope.historyUpdateCounter[input] > 0)
+    {
+        return result;
+    }
+
     for (i = 0; i < block->insz[input]; i++)
     {
-        pPolylineUID = getPolyline(pAxeUID, block, input, i);
+        pPolylineUID = getPolyline(pAxeUID, block, input, 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;