Add missing return
[scilab.git] / scilab / modules / gui / sci_gateway / c / sci_figure.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2014 - Scilab Enterprises - Antoine ELIAS
4  * Copyright (C) 2014 - Scilab Enterprises - Bruno JOFRET
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11  *
12  */
13
14 #include "gw_gui.h"
15 #include "MALLOC.h"
16 #include "api_scilab.h"
17 #include "localization.h"
18 #include "Scierror.h"
19 #include "createGraphicObject.h"
20 #include "BuildObjects.h"
21 #include "setGraphicObjectProperty.h"
22 #include "getGraphicObjectProperty.h"
23 #include "graphicObjectProperties.h"
24 #include "CurrentFigure.h"
25 #include "CurrentSubwin.h"
26 #include "FigureList.h"
27 #include "FigureModel.h"
28 #include "HandleManagement.h"
29 #include "SetHashTable.h"
30 #include "stricmp.h"
31 #ifdef _MSC_VER
32 #include "strdup_windows.h"
33 #endif
34
35 #include "sciprint.h"
36 #include "addColor.h"
37
38 /*--------------------------------------------------------------------------*/
39 int setDefaultProperties(int _iFig, BOOL bDefaultAxes, BOOL _axesSize);
40 int getStackArgumentAsBoolean(void* _pvCtx, int* _piAddr);
41 /*--------------------------------------------------------------------------*/
42 int sci_figure(char * fname, unsigned long fname_len)
43 {
44     SciErr sciErr;
45     int* piAddr = NULL;
46     int iFig = 0;
47     int iRhs = nbInputArgument(pvApiCtx);
48     int iId = 0;
49     int iPos = 0;
50     int i = 0;
51     int iNewId = -1;
52     int iAxes = 0;
53     int iPropertyOffset = 0;
54     BOOL bDoCreation = TRUE;
55     BOOL bVisible = TRUE; // Create a visible figure by default
56     BOOL bDockable = TRUE; // Create a dockable figure by default
57     BOOL bDefaultAxes = TRUE; // Create an Axes by default
58     double* figureSize = NULL;
59     double* axesSize = NULL;
60     double* position = NULL;
61     BOOL bMenuBar = TRUE;
62     BOOL bToolBar = TRUE;
63     BOOL bInfoBar = TRUE;
64     int iMenubarType = 1; // Create a 'figure' menubar by default
65     int iToolbarType = 1; // Create a 'figure' toolbar by default
66     double dblId = 0;
67     BOOL status = FALSE;
68
69     //figure(num) -> scf(num)
70     //figure() -> scf()
71
72     //figure(x, "...", ...)
73
74     // figure()
75     if (iRhs == 0) // Auto ID
76     {
77         iFig = createNewFigureWithAxes();
78         iAxes = setDefaultProperties(iFig, TRUE, TRUE);
79         createScalarHandle(pvApiCtx, iRhs + 1, getHandle(iFig));
80         AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
81         ReturnArguments(pvApiCtx);
82         return 0;
83     }
84
85     if (iRhs == 1)
86     {
87         //figure(x);
88         sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
89         if (sciErr.iErr)
90         {
91             printError(&sciErr, 0);
92             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
93             return 0;
94         }
95
96         if (isVarMatrixType(pvApiCtx, piAddr) == 0)
97         {
98             Scierror(999, _("%s: Wrong type for input argument #%d: An integer value expected.\n"), fname, 1);
99             return 0;
100         }
101
102         if (getScalarDouble(pvApiCtx, piAddr, &dblId))
103         {
104             Scierror(999, _("%s: No more memory.\n"), fname);
105             return 0;
106         }
107
108         iId = (int)(dblId + 0.5); //avoid 1.999 -> 1
109
110         //get current fig from id
111         iFig = getFigureFromIndex(iId);
112         if (iFig == 0) // Figure does not exists, create a new one
113         {
114             iFig = createNewFigureWithAxes();
115             setGraphicObjectProperty(iFig, __GO_ID__, &iId, jni_int,  1);
116             iAxes = setDefaultProperties(iFig, TRUE, TRUE);
117         }
118
119         createScalarHandle(pvApiCtx, iRhs + 1, getHandle(iFig));
120         AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
121         ReturnArguments(pvApiCtx);
122         return 0;
123     }
124
125     // Prepare property analysis
126     if (iRhs % 2 == 0)
127     {
128         //get highest value of winsid to create the new windows @ + 1
129         iNewId = getValidDefaultFigureId();
130         iPos = 0;
131     }
132     else
133     {
134         iPos = 1;
135         //figure(x, ...);
136         sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
137         if (sciErr.iErr)
138         {
139             printError(&sciErr, 0);
140             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
141             return 0;
142         }
143
144         if (isVarMatrixType(pvApiCtx, piAddr) == 0)
145         {
146             Scierror(999, _("%s: Wrong type for input argument #%d: An integer value expected.\n"), fname, 1);
147             return 0;
148         }
149
150         if (getScalarDouble(pvApiCtx, piAddr, &dblId))
151         {
152             Scierror(999, _("%s: No more memory.\n"), fname);
153             return 0;
154         }
155
156         iNewId = (int)(dblId + 0.5); //avoid 1.999 -> 1
157         //get current fig from id
158         iFig = getFigureFromIndex(iId);
159         if (iFig != 0) // Figure already exists
160         {
161             bDoCreation = FALSE;
162         }
163     }
164
165     if (bDoCreation)
166     {
167         int* piAddrProp = NULL;
168         char* pstProName = NULL;
169         int* piAddrData = NULL;
170         for (i = iPos + 1 ; i <= iRhs ; i += 2)
171         {
172             //get property name
173             sciErr = getVarAddressFromPosition(pvApiCtx, i, &piAddrProp);
174             if (sciErr.iErr)
175             {
176                 Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i);
177                 return 1;
178             }
179
180             if (getAllocatedSingleString(pvApiCtx, piAddrProp, &pstProName))
181             {
182                 Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, i);
183                 return 1;
184             }
185
186             if (stricmp(pstProName, "dockable") != 0 &&
187                     stricmp(pstProName, "toolbar") != 0 &&
188                     stricmp(pstProName, "menubar") != 0 &&
189                     stricmp(pstProName, "default_axes") != 0 &&
190                     stricmp(pstProName, "visible") != 0 &&
191                     stricmp(pstProName, "figure_size") != 0 &&
192                     stricmp(pstProName, "axes_size") != 0 &&
193                     stricmp(pstProName, "position") != 0 &&
194                     stricmp(pstProName, "menubar_visible") != 0 &&
195                     stricmp(pstProName, "toolbar_visible") != 0 &&
196                     stricmp(pstProName, "infobar_visible") != 0)
197             {
198                 freeAllocatedSingleString(pstProName);
199                 continue;
200             }
201
202             //get address of value on stack
203             sciErr = getVarAddressFromPosition(pvApiCtx, i + 1, &piAddrData);
204             if (sciErr.iErr)
205             {
206                 Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i + 1);
207                 return 1;
208             }
209
210             //check property value to compatibility
211             if (stricmp(pstProName, "dockable") == 0)
212             {
213                 bDockable = getStackArgumentAsBoolean(pvApiCtx, piAddrData);
214                 if (bDockable == -1)
215                 {
216                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "dockable", "on", "off");
217                     freeAllocatedSingleString(pstProName);
218                     return 1;
219                 }
220             }
221             else if (stricmp(pstProName, "toolbar") == 0)
222             {
223                 char* pstVal = NULL;
224                 if (isStringType(pvApiCtx, piAddrData) == FALSE || isScalar(pvApiCtx, piAddrData) == FALSE)
225                 {
226                     Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, i);
227                     freeAllocatedSingleString(pstProName);
228                 }
229
230                 getAllocatedSingleString(pvApiCtx, piAddrData, &pstVal);
231
232                 if (stricmp(pstVal, "none") == 0)
233                 {
234                     iToolbarType = 0;
235                 }
236                 else if (stricmp(pstVal, "figure") == 0)
237                 {
238                     iToolbarType = 1;
239                 }
240                 else
241                 {
242                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "toolbar", "none", "figure");
243                     freeAllocatedSingleString(pstProName);
244                     freeAllocatedSingleString(pstVal);
245                     return 1;
246                 }
247
248                 freeAllocatedSingleString(pstVal);
249             }
250             else if (stricmp(pstProName, "menubar") == 0)
251             {
252                 char* pstVal = NULL;
253                 if (isStringType(pvApiCtx, piAddrData) == FALSE || isScalar(pvApiCtx, piAddrData) == FALSE)
254                 {
255                     Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, i + 1);
256                     freeAllocatedSingleString(pstProName);
257                     return 1;
258                 }
259
260                 getAllocatedSingleString(pvApiCtx, piAddrData, &pstVal);
261
262                 if (stricmp(pstVal, "none") == 0)
263                 {
264                     iMenubarType = 0;
265                 }
266                 else if (stricmp(pstVal, "figure") == 0)
267                 {
268                     iMenubarType = 1;
269                 }
270                 else
271                 {
272                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "menubar", "none", "figure");
273                     freeAllocatedSingleString(pstProName);
274                     freeAllocatedSingleString(pstVal);
275                     return 1;
276                 }
277
278                 freeAllocatedSingleString(pstVal);
279             }
280             else if (stricmp(pstProName, "default_axes") == 0)
281             {
282                 bDefaultAxes = getStackArgumentAsBoolean(pvApiCtx, piAddrData);
283                 if (bDefaultAxes == -1)
284                 {
285                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "default_axes", "on", "off");
286                     freeAllocatedSingleString(pstProName);
287                     return 1;
288                 }
289             }
290             else if (stricmp(pstProName, "visible") == 0)
291             {
292                 bVisible = getStackArgumentAsBoolean(pvApiCtx, piAddrData);
293                 if (bVisible == -1)
294                 {
295                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "visible", "on", "off");
296                     freeAllocatedSingleString(pstProName);
297                     return 1;
298                 }
299             }
300             else if (stricmp(pstProName, "figure_size") == 0)
301             {
302                 int iRows = 0;
303                 int iCols = 0;
304                 if (isDoubleType(pvApiCtx, piAddrData) == FALSE)
305                 {
306                     Scierror(999, _("%s: Wrong type for input argument #%d: A double vector expected.\n"), fname, i + 1);
307                     return 1;
308                 }
309
310                 getMatrixOfDouble(pvApiCtx, piAddrData, &iRows, &iCols, &figureSize);
311                 if (iRows * iCols != 2)
312                 {
313                     Scierror(999, _("Wrong size for '%s' property: %d elements expected.\n"), "figure_size", 2);
314                     return 1;
315                 }
316             }
317             else if (stricmp(pstProName, "axes_size") == 0)
318             {
319                 int iRows = 0;
320                 int iCols = 0;
321                 if (isDoubleType(pvApiCtx, piAddrData) == FALSE)
322                 {
323                     Scierror(999, _("%s: Wrong type for input argument #%d: A double vector expected.\n"), fname, i + 1);
324                     return 1;
325                 }
326
327                 getMatrixOfDouble(pvApiCtx, piAddrData, &iRows, &iCols, &axesSize);
328                 if (iRows * iCols != 2)
329                 {
330                     Scierror(999, _("Wrong size for '%s' property: %d elements expected.\n"), "axes_size", 2);
331                     return 1;
332                 }
333             }
334             else if (stricmp(pstProName, "position") == 0)
335             {
336                 int iRows = 0;
337                 int iCols = 0;
338                 double* pdbl = NULL;
339                 if (isDoubleType(pvApiCtx, piAddrData) == FALSE)
340                 {
341                     Scierror(999, _("%s: Wrong type for input argument #%d: A double vector expected.\n"), fname, i + 1);
342                     return 1;
343                 }
344
345                 getMatrixOfDouble(pvApiCtx, piAddrData, &iRows, &iCols, &pdbl);
346                 if (iRows * iCols != 4)
347                 {
348                     Scierror(999, _("Wrong size for '%s' property: %d elements expected.\n"), "position", 4);
349                     return 1;
350                 }
351
352                 position = pdbl;
353                 axesSize = (pdbl + 2);
354             }
355             else if (stricmp(pstProName, "menubar_visible") == 0)
356             {
357                 bMenuBar = getStackArgumentAsBoolean(pvApiCtx, piAddrData);
358                 if (bMenuBar == -1)
359                 {
360                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "menubar_visible", "on", "off");
361                     freeAllocatedSingleString(pstProName);
362                     return 1;
363                 }
364             }
365             else if (stricmp(pstProName, "toolbar_visible") == 0)
366             {
367                 bToolBar = getStackArgumentAsBoolean(pvApiCtx, piAddrData);
368                 if (bToolBar == -1)
369                 {
370                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "toolbar_visible", "on", "off");
371                     freeAllocatedSingleString(pstProName);
372                     return 1;
373                 }
374             }
375             else if (stricmp(pstProName, "infobar_visible") == 0)
376             {
377                 bInfoBar = getStackArgumentAsBoolean(pvApiCtx, piAddrData);
378                 if (bInfoBar == -1)
379                 {
380                     Scierror(999, _("Wrong value for '%s' property: '%s' or '%s' expected."), "infobar_visible", "on", "off");
381                     freeAllocatedSingleString(pstProName);
382                     return 1;
383                 }
384             }
385
386         }
387
388         iFig = createFigure(bDockable, iMenubarType, iToolbarType, bDefaultAxes, bVisible, figureSize, axesSize, position, bMenuBar, bToolBar, bInfoBar);
389         setGraphicObjectProperty(iFig, __GO_ID__, &iNewId, jni_int, 1);
390         iAxes = setDefaultProperties(iFig, bDefaultAxes, figureSize || axesSize ? FALSE : TRUE);
391     }
392
393     //set(iFig, iPos, iPos + 1)
394     for (i = iPos + 1 ; i <= iRhs ; i += 2)
395     {
396         int isMatrixOfString = 0;
397         int* piAddrProp = NULL;
398         char* pstProName = NULL;
399         int* piAddrData = NULL;
400         int iRows = 0;
401         int iCols = 0;
402         void* _pvData = NULL;
403         int iType = 0;
404
405         //get property name
406         sciErr = getVarAddressFromPosition(pvApiCtx, i, &piAddrProp);
407         if (sciErr.iErr)
408         {
409             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i);
410             return 1;
411         }
412
413         if (getAllocatedSingleString(pvApiCtx, piAddrProp, &pstProName))
414         {
415             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, i);
416             return 1;
417         }
418
419         if (bDoCreation && (
420                     stricmp(pstProName, "dockable") == 0 ||
421                     stricmp(pstProName, "toolbar") == 0 ||
422                     stricmp(pstProName, "menubar") == 0 ||
423                     stricmp(pstProName, "default_axes") == 0 ||
424                     stricmp(pstProName, "visible") == 0 ||
425                     stricmp(pstProName, "figure_size") == 0 ||
426                     stricmp(pstProName, "axes_size") == 0 ||
427                     stricmp(pstProName, "position") == 0 ||
428                     stricmp(pstProName, "menubar_visible") == 0 ||
429                     stricmp(pstProName, "toolbar_visible") == 0 ||
430                     stricmp(pstProName, "infobar_visible") == 0))
431         {
432             // Already set creating new figure
433             // but let the set_ function fail if figure already exists
434             continue;
435         }
436
437         //get address of value on stack
438         sciErr = getVarAddressFromPosition(pvApiCtx, i + 1, &piAddrData);
439         if (sciErr.iErr)
440         {
441             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, i + 1);
442             return 1;
443         }
444
445         getVarType(pvApiCtx, piAddrData, &iType);
446
447         if ((strcmp(pstProName, "user_data") == 0) || (stricmp(pstProName, "userdata") == 0))
448         {
449             /* in this case set_user_data_property
450              * directly uses the  third position in the stack
451              * to get the variable which is to be set in
452              * the user_data property (any data type is allowed) S. Steer */
453             _pvData = (void*)piAddrData;         /*position in the stack */
454             iRows = -1;   /*unused */
455             iCols = -1;   /*unused */
456             iType = -1;
457         }
458         else
459         {
460             switch (iType)
461             {
462                 case sci_matrix :
463                     getMatrixOfDouble(pvApiCtx, piAddrData, &iRows, &iCols, (double**)&_pvData);
464                     break;
465                 case sci_boolean :
466                     getMatrixOfBoolean(pvApiCtx, piAddrData, &iRows, &iCols, (int**)&_pvData);
467                     break;
468                 case sci_handles :
469                     getMatrixOfHandle(pvApiCtx, piAddrData, &iRows, &iCols, (long long**)&_pvData);
470                     break;
471                 case sci_strings :
472                     if (   strcmp(pstProName, "tics_labels") != 0 && strcmp(pstProName, "auto_ticks") != 0 &&
473                             strcmp(pstProName, "axes_visible") != 0 && strcmp(pstProName, "axes_reverse") != 0 &&
474                             strcmp(pstProName, "text") != 0 && stricmp(pstProName, "string") != 0 &&
475                             stricmp(pstProName, "tooltipstring") != 0) /* Added for uicontrols */
476                     {
477                         if (getAllocatedSingleString(pvApiCtx, piAddrData, (char**)&_pvData))
478                         {
479                             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 3);
480                             return 1;
481                         }
482                         iRows = (int)strlen((char*)_pvData);
483                         iCols = 1;
484                     }
485                     else
486                     {
487                         isMatrixOfString = 1;
488                         getAllocatedMatrixOfString(pvApiCtx, piAddrData, &iRows, &iCols, (char***)&_pvData);
489                     }
490                     break;
491                 case sci_list :
492                     iCols = 1;
493                     getListItemNumber(pvApiCtx, piAddrData, &iRows);
494                     _pvData = (void*)piAddrData;         /* In this case l3 is the list position in stack */
495                     break;
496                 default :
497                     _pvData = (void*)piAddrData;         /* In this case l3 is the list position in stack */
498                     break;
499             }
500         }
501
502         callSetProperty(pvApiCtx, iFig, _pvData, iType, iRows, iCols, pstProName);
503
504         // If backgroundcolor is set :
505         // * add it to colormap => performed by callSetProperty
506         // * set background to index => performed by callSetProperty
507         // * copy value into axes background property
508         if (stricmp(pstProName, "backgroundcolor") == 0 && iAxes > 0)
509         {
510             int iBackground = 0;
511             int *piBackground = &iBackground;
512
513             getGraphicObjectProperty(iFig, __GO_BACKGROUND__, jni_int, (void **)&piBackground);
514             setGraphicObjectProperty(iAxes, __GO_BACKGROUND__, piBackground, jni_int, 1);
515         }
516
517         if (iType == sci_strings)
518         {
519             //free allacted data
520             if (isMatrixOfString == 1)
521             {
522                 freeAllocatedMatrixOfString(iRows, iCols, (char**)_pvData);
523             }
524             else
525             {
526                 freeAllocatedSingleString((char*)_pvData);
527             }
528         }
529     }
530
531     //return new created fig
532     createScalarHandle(pvApiCtx, iRhs + 1, getHandle(iFig));
533     AssignOutputVariable(pvApiCtx, 1) = iRhs + 1;
534     ReturnArguments(pvApiCtx);
535     return 0;
536 }
537 /*--------------------------------------------------------------------------*/
538 int getStackArgumentAsBoolean(void* _pvCtx, int* _piAddr)
539 {
540     if (isScalar(_pvCtx, _piAddr))
541     {
542         if (isDoubleType(_pvCtx, _piAddr))
543         {
544             double dbl = 0;
545             getScalarDouble(_pvCtx, _piAddr, &dbl);
546             return ((int)dbl == 0 ? FALSE : TRUE);
547         }
548         else if (isBooleanType(_pvCtx, _piAddr))
549         {
550             int i = 0;
551             getScalarBoolean(_pvCtx, _piAddr, &i);
552             return (i == 0 ? FALSE : TRUE);
553         }
554         else if (isStringType(_pvCtx, _piAddr))
555         {
556             int ret = 0;
557             char* pst = NULL;
558             getAllocatedSingleString(_pvCtx, _piAddr, &pst);
559
560             if (stricmp(pst, "on") == 0)
561             {
562                 ret = TRUE;
563             }
564
565             freeAllocatedSingleString(pst);
566
567             return ret;
568         }
569     }
570     return -1;
571 }
572 /*--------------------------------------------------------------------------*/
573 int setDefaultProperties(int _iFig, BOOL _bDefaultAxes, BOOL _axesSize)
574 {
575     //get figure axes
576     int iAxes = -1;
577     int iDrawing = 0;
578     int iColorIndex = 0;
579     int iFilled = 0;
580     int iAxesVisible = 0;
581     int* piAxesSize = NULL;
582     double pdblNewColor[COLOR_COMPONENT] = {0.8, 0.8, 0.8};
583
584     setGraphicObjectProperty(_iFig, __GO_IMMEDIATE_DRAWING__, &iDrawing, jni_bool, 1);
585
586     iColorIndex = addColor(_iFig, pdblNewColor);
587
588     setGraphicObjectProperty(_iFig, __GO_BACKGROUND__, &iColorIndex, jni_int, 1);
589     if (_bDefaultAxes)
590     {
591         iAxes = getOrCreateDefaultSubwin();
592         //set background in figure and axes to new ( or existting ) color
593         setGraphicObjectProperty(iAxes, __GO_BACKGROUND__, &iColorIndex, jni_int, 1);
594
595         //a.filled = "off"
596         setGraphicObjectProperty(iAxes, __GO_FILLED__, &iFilled, jni_bool, 1);
597
598         //a.axes_visible = "off"
599         setGraphicObjectProperty(iAxes, __GO_X_AXIS_VISIBLE__, &iAxesVisible, jni_bool, 1);
600         setGraphicObjectProperty(iAxes, __GO_Y_AXIS_VISIBLE__, &iAxesVisible, jni_bool, 1);
601         setGraphicObjectProperty(iAxes, __GO_Z_AXIS_VISIBLE__, &iAxesVisible, jni_bool, 1);
602     }
603
604     // axes_size
605     if (_axesSize)
606     {
607         getGraphicObjectProperty(getFigureModel(), __GO_AXES_SIZE__, jni_int_vector, (void **)&piAxesSize);
608         setGraphicObjectProperty(_iFig, __GO_AXES_SIZE__, piAxesSize, jni_int_vector, 2);
609     }
610
611     //f.immediate_drawing = "on"
612     iDrawing = 1;
613     setGraphicObjectProperty(_iFig, __GO_IMMEDIATE_DRAWING__, &iDrawing, jni_bool, 1);
614
615     return iAxes;
616 }
617 /*--------------------------------------------------------------------------*/