e154dc35256815b15072129bdd6ff51d06826870
[scilab.git] / scilab / modules / scicos_blocks / src / c / cmscope.c
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011-2012 - Scilab Enterprises - Clement DAVID
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include <string.h>
14
15 #include "dynlib_scicos_blocks.h"
16 #include "scoUtils.h"
17
18 #include "MALLOC.h"
19 #include "elementary_functions.h"
20
21 #include "getGraphicObjectProperty.h"
22 #include "setGraphicObjectProperty.h"
23 #include "graphicObjectProperties.h"
24 #include "createGraphicObject.h"
25
26 #include "CurrentFigure.h"
27 #include "CurrentObject.h"
28
29 #include "scicos_block4.h"
30 #include "scicos.h"
31
32 #include "localization.h"
33 #ifdef _MSC_VER
34 #include "strdup_windows.h"
35 #endif
36
37 #include "FigureList.h"
38 #include "BuildObjects.h"
39 #include "AxesModel.h"
40
41 // #include <stdio.h>
42 // #define LOG(...) printf(__VA_ARGS__)
43 #define LOG(...)
44
45 /*****************************************************************************
46  * Internal container structure
47  ****************************************************************************/
48
49 /**
50  * Container structure
51  */
52 typedef struct
53 {
54     struct
55     {
56         int *numberOfPoints;
57         int *maxNumberOfPoints;
58         double ***coordinates;
59     } internal;
60
61     struct
62     {
63         int *periodCounter;
64
65         char const* cachedFigureUID;
66         char **cachedAxeUID;
67         char ***cachedPolylinesUIDs;
68     } scope;
69 } sco_data;
70
71 /**
72  * Get (and allocate on demand) the internal data used on this scope
73  * \param block the block
74  * \return the scope data
75  */
76 static sco_data *getScoData(scicos_block * block);
77
78 /**
79  * Release any internal data
80  *
81  * \param block the block
82  */
83 static void freeScoData(scicos_block * block);
84
85 /**
86  * Realloc any internal data
87  *
88  * \param block the block
89  * \param input the selected input
90  * \param numberOfPoints realloc to store this number of points
91  */
92 static sco_data *reallocScoData(scicos_block * block, int input, int numberOfPoints);
93
94 /**
95  * Append the data to the current data
96  *
97  * \param block the block
98  * \param input the input (0-indexed)
99  * \param t the current time
100  * \param data the data to append
101  */
102 static void appendData(scicos_block * block, int input, double t, double *data);
103
104 /**
105  * Push the block data to the polyline
106  *
107  * \param block the block
108  * \param input the selected input
109  * \param row the selected row
110  * \param pPolylineUID the polyline uid
111  *
112  */
113 static BOOL pushData(scicos_block * block, int input, int row);
114
115 /*****************************************************************************
116  * Graphics utils
117  ****************************************************************************/
118
119 /**
120  * Get (and allocate on demand) the figure associated with the block
121  * \param block the block
122  * \return a valid figure UID or NULL on error
123  */
124 static char const* getFigure(scicos_block * block);
125
126 /**
127  * Get (and allocate on demand) the axe associated with the input
128  *
129  * \param pFigureUID the parent figure UID
130  * \param block the block
131  * \param input the current input index (0-indexed)
132  * \return a valid axe UID or NULL on error
133  */
134 static char *getAxe(char const* pFigureUID, scicos_block * block, int input);
135
136 /**
137  * Get (and allocate on demand) the polyline associated with the row
138  *
139  * \param pAxeUID the parent axe UID
140  * \param block the block
141  * \param input the current input index (0-indexed)
142  * \param row the current row index (0-indexed)
143  * \return a valid polyline UID or NULL on error
144  */
145 static char *getPolyline(char *pAxeUID, scicos_block * block, int input, int row);
146
147 /**
148  * Set the polylines buffer size
149  *
150  * \param block the block
151  * \param input the input port index
152  * \param maxNumberOfPoints the size of the buffer
153  */
154 static BOOL setPolylinesBuffers(scicos_block * block, int input, int maxNumberOfPoints);
155
156 /**
157  * Set the polylines bounds
158  *
159  * \param block the block
160  * \param input the input port index
161  * \param periodCounter number of past periods since startup
162  */
163 static BOOL setPolylinesBounds(scicos_block * block, int input, int periodCounter);
164
165 /*****************************************************************************
166  * Simulation function
167  ****************************************************************************/
168
169 /** \fn void cmscope(scicos_block * block,int flag)
170     \brief the computational function
171     \param block A pointer to a scicos_block
172     \param flag An int which indicates the state of the block (init, update, ending)
173 */
174 SCICOS_BLOCKS_IMPEXP void cmscope(scicos_block * block, scicos_flag flag)
175 {
176     char const* pFigureUID;
177
178     double t;
179     double *u;
180     sco_data *sco;
181
182     int i, j;
183     BOOL result;
184
185     switch (flag)
186     {
187
188         case Initialization:
189             sco = getScoData(block);
190             if (sco == NULL)
191             {
192                 set_block_error(-5);
193                 break;
194             }
195             pFigureUID = getFigure(block);
196             if (pFigureUID == NULL)
197             {
198                 // allocation error
199                 set_block_error(-5);
200                 break;
201             }
202             break;
203
204         case StateUpdate:
205             pFigureUID = getFigure(block);
206             if (pFigureUID == NULL)
207             {
208                 // allocation error
209                 set_block_error(-5);
210                 break;
211             }
212
213             t = get_scicos_time();
214             for (i = 0; i < block->nin; i++)
215             {
216                 u = (double *)block->inptr[i];
217
218                 appendData(block, i, t, u);
219                 for (j = 0; j < block->insz[i]; j++)
220                 {
221                     result = pushData(block, i, j);
222                     if (result == FALSE)
223                     {
224                         Coserror("%s: unable to push some data.", "cmscope");
225                         break;
226                     }
227                 }
228             }
229             break;
230
231         case Ending:
232             freeScoData(block);
233             break;
234
235         default:
236             break;
237     }
238 }
239
240 /*-------------------------------------------------------------------------*/
241
242 /*****************************************************************************
243  *
244  * Container management
245  *
246  ****************************************************************************/
247
248 static sco_data *getScoData(scicos_block * block)
249 {
250     sco_data *sco = (sco_data *) * (block->work);
251     int i, j, k, l;
252
253     if (sco == NULL)
254     {
255         /*
256          * Data allocation
257          */
258
259         sco = (sco_data *) MALLOC(sizeof(sco_data));
260         if (sco == NULL)
261         {
262             goto error_handler_sco;
263         }
264
265         sco->internal.numberOfPoints = (int *) MALLOC(block->nin * sizeof(int));
266         if (sco->internal.numberOfPoints == NULL)
267         {
268             goto error_handler_numberOfPoints;
269         }
270         sco->internal.maxNumberOfPoints = (int *) MALLOC(block->nin * sizeof(int));
271         if (sco->internal.maxNumberOfPoints == NULL)
272         {
273             goto error_handler_maxNumberOfPoints;
274         }
275
276         for (i = 0; i < block->nin; i++)
277         {
278             sco->internal.numberOfPoints[i] = 0;
279             sco->internal.maxNumberOfPoints[i] = block->ipar[2];
280         }
281
282         sco->internal.coordinates = (double ***)CALLOC(block->nin, sizeof(double **));
283         if (sco->internal.coordinates == NULL)
284         {
285             goto error_handler_coordinates;
286         }
287
288         for (i = 0; i < block->nin; i++)
289         {
290             sco->internal.coordinates[i] = (double **)CALLOC(block->insz[i], sizeof(double *));
291             if (sco->internal.coordinates[i] == NULL)
292             {
293                 goto error_handler_coordinates_i;
294             }
295         }
296         for (i = 0; i < block->nin; i++)
297         {
298             for (j = 0; j < block->insz[i]; j++)
299             {
300                 sco->internal.coordinates[i][j] = (double *)CALLOC(3 * block->ipar[2], sizeof(double));
301
302                 if (sco->internal.coordinates[i][j] == NULL)
303                 {
304                     goto error_handler_coordinates_ij;
305                 }
306             }
307         }
308
309         sco->scope.periodCounter = (int *) CALLOC(block->nin, sizeof(int));
310         if (sco->scope.periodCounter == NULL)
311         {
312             goto error_handler_periodCounter;
313         }
314
315         sco->scope.cachedFigureUID = NULL;
316         sco->scope.cachedAxeUID = (char **)CALLOC(block->nin, sizeof(char *));
317
318         sco->scope.cachedPolylinesUIDs = (char ***)CALLOC(block->nin, sizeof(char **));
319         for (i = 0; i < block->nin; i++)
320         {
321             sco->scope.cachedPolylinesUIDs[i] = (char **)CALLOC(block->insz[i], sizeof(char *));
322         }
323
324         *(block->work) = sco;
325     }
326
327     return sco;
328
329     /*
330      * Error management (out of normal flow)
331      */
332 error_handler_periodCounter:
333     i = block->nin - 1;
334     j = 2 ^ 31;
335 error_handler_coordinates_ij:
336     for (k = 0; k < i; k++)
337     {
338         for (l = 0; l < j && l < block->insz[i]; l++)
339         {
340             FREE(sco->internal.coordinates[k][l]);
341         }
342     }
343     i = block->nin - 1;
344 error_handler_coordinates_i:
345     for (j = 0; j < i; j++)
346     {
347         FREE(sco->internal.coordinates[i]);
348     }
349     FREE(sco->internal.coordinates);
350 error_handler_coordinates:
351     FREE(sco->internal.maxNumberOfPoints);
352 error_handler_maxNumberOfPoints:
353     FREE(sco->internal.numberOfPoints);
354 error_handler_numberOfPoints:
355     FREE(sco);
356 error_handler_sco:
357     // allocation error
358     set_block_error(-5);
359     return NULL;
360 }
361
362 static void freeScoData(scicos_block * block)
363 {
364     sco_data *sco = (sco_data *) * (block->work);
365     int i, j;
366
367     if (sco != NULL)
368     {
369         for (i = 0; i < block->nin; i++)
370         {
371             for (j = 0; j < block->insz[i]; j++)
372             {
373                 FREE(sco->internal.coordinates[i][j]);
374             }
375             FREE(sco->internal.coordinates[i]);
376         }
377         FREE(sco->internal.coordinates);
378
379         for (i = 0; i < block->nin; i++)
380         {
381             for (j = 0; j < block->insz[i]; j++)
382             {
383                 FREE(sco->scope.cachedPolylinesUIDs[i][j]);
384             }
385             FREE(sco->scope.cachedAxeUID[i]);
386         }
387
388         FREE(sco);
389         *(block->work) = NULL;
390     }
391 }
392
393 static sco_data *reallocScoData(scicos_block * block, int input, int numberOfPoints)
394 {
395     sco_data *sco = (sco_data *) * (block->work);
396     int i;
397
398     double *ptr;
399     int setLen;
400     int previousNumberOfPoints = sco->internal.maxNumberOfPoints[input];
401     int newPoints = numberOfPoints - previousNumberOfPoints;
402
403     LOG("%s: %s at %d to %d\n", "cmscope", "reallocScoData", input, numberOfPoints);
404
405     for (i = 0; i < block->insz[input]; i++)
406     {
407         ptr = (double *)REALLOC(sco->internal.coordinates[input][i], 3 * numberOfPoints * sizeof(double));
408         if (ptr == NULL)
409         {
410             goto error_handler;
411         }
412
413         // clear the last points, the Z-axis values
414         memset(ptr + 2 * numberOfPoints, 0, numberOfPoints * sizeof(double));
415
416         // memcpy existing Y-axis values (use memmove to handle memory overlapping)
417         memmove(ptr + numberOfPoints, ptr + previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
418
419         // then set the last points to the last values for Y-axis and X-axis values
420         for (setLen = newPoints - 1; setLen >= 0; setLen--)
421         {
422             ptr[numberOfPoints + previousNumberOfPoints + setLen] = ptr[numberOfPoints + previousNumberOfPoints - 1];
423         }
424         for (setLen = newPoints - 1; setLen >= 0; setLen--)
425         {
426             ptr[previousNumberOfPoints + setLen] = ptr[previousNumberOfPoints - 1];
427         }
428
429         sco->internal.coordinates[input][i] = ptr;
430     }
431
432     sco->internal.maxNumberOfPoints[input] = numberOfPoints;
433     return sco;
434
435 error_handler:
436     freeScoData(block);
437     // allocation error
438     set_block_error(-5);
439     return NULL;
440 }
441
442 static void appendData(scicos_block * block, int input, double t, double *data)
443 {
444     int i;
445
446     sco_data *sco = (sco_data *) * (block->work);
447     int maxNumberOfPoints = sco->internal.maxNumberOfPoints[input];
448     int numberOfPoints = sco->internal.numberOfPoints[input];
449
450
451     /*
452      * Handle the case where the t is greater than the data_bounds
453      */
454     if (t > ((sco->scope.periodCounter[input] + 1) * block->rpar[1 + input]))
455     {
456         sco->scope.periodCounter[input]++;
457
458         numberOfPoints = 0;
459         sco->internal.numberOfPoints[input] = 0;
460         if (setPolylinesBounds(block, input, sco->scope.periodCounter[input]) == FALSE)
461         {
462             set_block_error(-5);
463             freeScoData(block);
464             sco = NULL;
465         }
466     }
467
468     /*
469      * Handle the case where the scope has more points than maxNumberOfPoints
470      */
471     if (sco != NULL && numberOfPoints >= maxNumberOfPoints)
472     {
473         // on a full scope, re-alloc
474         maxNumberOfPoints = maxNumberOfPoints + block->ipar[2];
475         sco = reallocScoData(block, input, maxNumberOfPoints);
476
477         // reconfigure related graphic objects
478         if (setPolylinesBuffers(block, input, maxNumberOfPoints) == FALSE)
479         {
480             set_block_error(-5);
481             freeScoData(block);
482             sco = NULL;
483         }
484     }
485
486     /*
487      * Update data
488      */
489     if (sco != NULL)
490     {
491         int setLen;
492
493         for (i = 0; i < block->insz[input]; i++)
494         {
495             // X-axis values first
496             for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
497             {
498                 sco->internal.coordinates[input][i][numberOfPoints + setLen] = t;
499             }
500
501             // then Y-axis values
502             for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
503             {
504                 sco->internal.coordinates[input][i][maxNumberOfPoints + numberOfPoints + setLen] = data[i];
505             }
506
507             // do not update Z-axis values, always cleared
508         }
509
510         sco->internal.numberOfPoints[input]++;
511     }
512 }
513
514 static BOOL pushData(scicos_block * block, int input, int row)
515 {
516     char const* pFigureUID;
517     char *pAxeUID;
518     char *pPolylineUID;
519
520     double *data;
521     sco_data *sco;
522
523     pFigureUID = getFigure(block);
524     pAxeUID = getAxe(pFigureUID, block, input);
525     pPolylineUID = getPolyline(pAxeUID, block, input, row);
526
527     sco = getScoData(block);
528     if (sco == NULL)
529     {
530         return FALSE;
531     }
532
533     // select the right input and row
534     data = sco->internal.coordinates[input][row];
535
536     return setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_COORDINATES__, data, jni_double_vector, sco->internal.maxNumberOfPoints[input]);
537 }
538
539 /*****************************************************************************
540  *
541  * Graphic utils
542  *
543  ****************************************************************************/
544
545 /**
546  * Set properties on the figure.
547  *
548  * \param pFigureUID the figure uid
549  * \param block the current block
550  */
551 static void setFigureSettings(char const* pFigureUID, scicos_block * block)
552 {
553     int win_pos[2];
554     int win_dim[2];
555
556     int *ipar = block->ipar;
557
558     win_pos[0] = ipar[3];
559     win_pos[1] = ipar[4];
560     win_dim[0] = ipar[5];
561     win_dim[1] = ipar[6];
562
563     if (win_pos[0] > 0 && win_pos[1] > 0)
564     {
565         setGraphicObjectProperty(pFigureUID, __GO_POSITION__, &win_pos, jni_int_vector, 2);
566     }
567
568     if (win_dim[0] > 0 && win_dim[1] > 0)
569     {
570         setGraphicObjectProperty(pFigureUID, __GO_SIZE__, &win_dim, jni_int_vector, 2);
571     }
572 };
573
574 /**
575  * Set properties on the axes.
576  *
577  * \param pAxeUID the axe uid
578  * \param block the current block
579  * \param index axe index (0-indexed)
580  */
581 static void setAxesSettings(char *pAxeUID, scicos_block * block, int index)
582 {
583     double axesBounds[4];
584     double margins[4];
585
586     double nin = (double) block->nin;
587
588     axesBounds[0] = 0;              // x
589     axesBounds[1] = index / nin;    // y
590     axesBounds[2] = 1.0;            // w
591     axesBounds[3] = 1 / nin;        // h
592     setGraphicObjectProperty(pAxeUID, __GO_AXES_BOUNDS__, axesBounds, jni_double_vector, 4);
593
594     margins[0] = 0.125;
595     margins[1] = 0.125;
596     margins[2] = 0.125;
597     margins[3] = 0.125;
598     setGraphicObjectProperty(pAxeUID, __GO_MARGINS__, margins, jni_double_vector, 4);
599
600 };
601
602 /*****************************************************************************
603  *
604  * Graphic
605  *
606  ****************************************************************************/
607
608 static char const* getFigure(scicos_block * block)
609 {
610     signed int figNum;
611     char const* pFigureUID = NULL;
612     char *pAxe = NULL;
613     int i__1 = 1;
614     sco_data *sco = (sco_data *) * (block->work);
615
616     int i;
617
618     // assert the sco is not NULL
619     if (sco == NULL)
620     {
621         return NULL;
622     }
623
624     // fast path for an existing object
625     if (sco->scope.cachedFigureUID != NULL)
626     {
627         return sco->scope.cachedFigureUID;
628     }
629
630     figNum = block->ipar[0];
631
632     // with a negative id, use the block number indexed from a constant.
633     if (figNum < 0)
634     {
635         figNum = 20000 + get_block_number();
636     }
637
638     pFigureUID = getFigureFromIndex(figNum);
639     // create on demand
640     if (pFigureUID == NULL)
641     {
642         pFigureUID = createNewFigureWithAxes();
643         setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
644
645         // the stored uid is a reference to the figure map, not to the current figure
646         pFigureUID = getFigureFromIndex(figNum);
647         sco->scope.cachedFigureUID = pFigureUID;
648
649         // set configured parameters
650         setFigureSettings(pFigureUID, block);
651
652         // allocate the axes through the getter
653         for (i = 0; i < GetNin(block); i++)
654         {
655             pAxe = getAxe(pFigureUID, block, i);
656
657             /*
658              * Setup according to block settings
659              */
660             setLabel(pAxe, __GO_X_AXIS_LABEL__, "t");
661             setLabel(pAxe, __GO_Y_AXIS_LABEL__, "y");
662
663             setGraphicObjectProperty(pAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
664             setGraphicObjectProperty(pAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
665
666             setPolylinesBounds(block, i, 0);
667         }
668     }
669
670     if (sco->scope.cachedFigureUID == NULL)
671     {
672         sco->scope.cachedFigureUID = pFigureUID;
673     }
674     return pFigureUID;
675 }
676
677 static char *getAxe(char const* pFigureUID, scicos_block * block, int input)
678 {
679     char *pAxe;
680     int i;
681     sco_data *sco = (sco_data *) * (block->work);
682
683     // assert the sco is not NULL
684     if (sco == NULL)
685     {
686         return NULL;
687     }
688
689     // fast path for an existing object
690     if (sco->scope.cachedAxeUID != NULL && sco->scope.cachedAxeUID[input] != NULL)
691     {
692         return sco->scope.cachedAxeUID[input];
693     }
694
695     pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, input);
696
697     /*
698      * Allocate if necessary
699      */
700     if (pAxe == NULL)
701     {
702         cloneAxesModel(pFigureUID);
703         pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, input);
704     }
705
706     /*
707      * Setup on first access
708      */
709     if (pAxe != NULL)
710     {
711         // allocate the polylines through the getter
712         for (i = 0; i < block->insz[input]; i++)
713         {
714             getPolyline(pAxe, block, input, i);
715         }
716
717         setAxesSettings(pAxe, block, input);
718     }
719
720     /*
721      * then cache with local storage
722      */
723     if (pAxe != NULL && sco->scope.cachedAxeUID != NULL && sco->scope.cachedAxeUID[input] == NULL)
724     {
725         sco->scope.cachedAxeUID[input] = strdup(pAxe);
726         releaseGraphicObjectProperty(__GO_PARENT__, pAxe, jni_string, 1);
727     }
728     return sco->scope.cachedAxeUID[input];
729 }
730
731 static char *getPolyline(char *pAxeUID, scicos_block * block, int input, int row)
732 {
733     char *pPolyline;
734     BOOL b__true = TRUE;
735
736     int color;
737
738     sco_data *sco = (sco_data *) * (block->work);
739
740     // assert the sco is not NULL
741     if (sco == NULL)
742     {
743         return NULL;
744     }
745
746     // fast path for an existing object
747     if (sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[input] != NULL && sco->scope.cachedPolylinesUIDs[input][row] != NULL)
748     {
749         return sco->scope.cachedPolylinesUIDs[input][row];
750     }
751
752     pPolyline = findChildWithKindAt(pAxeUID, __GO_POLYLINE__, row);
753
754     /*
755      * Allocate if necessary
756      */
757     if (pPolyline == NULL)
758     {
759         pPolyline = createGraphicObject(__GO_POLYLINE__);
760
761         if (pPolyline != NULL)
762         {
763             createDataObject(pPolyline, __GO_POLYLINE__);
764             setGraphicObjectRelationship(pAxeUID, pPolyline);
765         }
766     }
767
768     /*
769      * Setup on first access
770      */
771     if (pPolyline != NULL)
772     {
773
774         /*
775          * Default setup (will crash if removed)
776          */
777         {
778             int polylineSize[2] = { 1, block->ipar[2] };
779             setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_NUM_ELEMENTS_ARRAY__, polylineSize, jni_int_vector, 2);
780         }
781
782         // ipar=[win;size(in,'*');N;wpos(:);wdim(:);in(:);clrs(:);heritance]
783         //        1     1         1   2       2      nin   nin       1
784         color = block->ipar[7 + block->nin + input + row];
785         if (color > 0)
786         {
787             LOG("%s: %s at %d at %d to %d\n", "cmscope", "set lines mode", input, row, color);
788
789             setGraphicObjectProperty(pPolyline, __GO_LINE_MODE__, &b__true, jni_bool, 1);
790             setGraphicObjectProperty(pPolyline, __GO_LINE_COLOR__, &color, jni_int, 1);
791         }
792         else
793         {
794             color = -color;
795
796             LOG("%s: %s at %d at %d to %d\n", "cmscope", "set mark mode", input, row, -color);
797
798             setGraphicObjectProperty(pPolyline, __GO_MARK_MODE__, &b__true, jni_bool, 1);
799             setGraphicObjectProperty(pPolyline, __GO_MARK_STYLE__, &color, jni_int, 1);
800         }
801
802         {
803             int iClipState = 1; //on
804             setGraphicObjectProperty(pPolyline, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
805         }
806     }
807
808     /*
809      * then cache with local storage
810      */
811     if (sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[input] != NULL)
812     {
813         sco->scope.cachedPolylinesUIDs[input][row] = strdup(pPolyline);
814         releaseGraphicObjectProperty(__GO_PARENT__, pPolyline, jni_string, 1);
815     }
816     return sco->scope.cachedPolylinesUIDs[input][row];
817 }
818
819 static BOOL setPolylinesBuffers(scicos_block * block, int input, int maxNumberOfPoints)
820 {
821     int i;
822
823     char const* pFigureUID;
824     char *pAxeUID;
825     char *pPolylineUID;
826
827     BOOL result = TRUE;
828     int polylineSize[2] = { 1, maxNumberOfPoints };
829
830     LOG("%s: %s at %d to %d\n", "cmscope", "setPolylinesBuffers", input, maxNumberOfPoints);
831
832     pFigureUID = getFigure(block);
833     pAxeUID = getAxe(pFigureUID, block, input);
834
835     for (i = 0; i < block->insz[input]; i++)
836     {
837         pPolylineUID = getPolyline(pAxeUID, block, input, i);
838         result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_NUM_ELEMENTS_ARRAY__, polylineSize, jni_int_vector, 2);
839     }
840
841     return result;
842 }
843
844 static BOOL setPolylinesBounds(scicos_block * block, int input, int periodCounter)
845 {
846     char const* pFigureUID;
847     char *pAxeUID;
848
849     double dataBounds[6];
850     int nin = block->nin;
851     double period = block->rpar[block->nrpar - 3 * nin + input];
852
853     dataBounds[0] = periodCounter * period; // xMin
854     dataBounds[1] = (periodCounter + 1) * period;   // xMax
855     dataBounds[2] = block->rpar[block->nrpar - 2 * nin + 2 * input];    // yMin
856     dataBounds[3] = block->rpar[block->nrpar - 2 * nin + 2 * input + 1];    // yMax
857     dataBounds[4] = -1.0;       // zMin
858     dataBounds[5] = 1.0;        // zMax
859
860     LOG("%s: %s at %d to %f\n", "cmscope", "setPolylinesBounds", input, dataBounds[1]);
861
862     pFigureUID = getFigure(block);
863     pAxeUID = getAxe(pFigureUID, block, input);
864     return setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
865 }