Bug 12818 fixed: Segfault with invalid property name on figure handle
[scilab.git] / scilab / modules / graphics / sci_gateway / c / sci_set.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2006 - INRIA - Allan Cornet
4  * Copyright (C) 2006 - INRIA - Fabrice Leray
5  * Copyright (C) 2006 - INRIA - Jean-Baptiste Silvy
6  * Copyright (C) 2006 - INRIA - Vincent Couvert
7  * Copyright (C) 2011 - DIGITEO - Allan CORNET
8  *
9  * This file must be used under the terms of the CeCILL.
10  * This source file is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution.  The terms
12  * are also available at
13  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
14  *
15  */
16
17 /*------------------------------------------------------------------------*/
18 /* file: sci_set.h                                                        */
19 /* desc : interface for sci_set routine                                   */
20 /*------------------------------------------------------------------------*/
21 #include <stdio.h>
22 /*------------------------------------------------------------------------*/
23 #include "gw_graphics.h"
24 #include "stack-c.h"
25 #include "Scierror.h"
26 #include "HandleManagement.h"
27 #include "GetProperty.h"
28 #include "InitObjects.h"
29 #include "freeArrayOfString.h"
30
31 #include "SetHashTable.h"
32 #include "SetPropertyStatus.h"
33
34 #include "MALLOC.h"             /* MALLOC */
35 #include "localization.h"
36 #include "stricmp.h"
37 #include "api_scilab.h"
38 /*--------------------------------------------------------------------------
39  * sciset(choice-name,x1,x2,x3,x4,x5)
40  * or   xset()
41  *-----------------------------------------------------------*/
42 int sci_set(char *fname, unsigned long fname_len)
43 {
44     SciErr sciErr;
45
46     int* piAddr1 = NULL;
47     int* piAddr2 = NULL;
48     int* piAddr3 = NULL;
49     int lw = 0;
50     int isMatrixOfString = 0;
51
52     char* pstProperty = NULL;
53     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1);
54     if (sciErr.iErr)
55     {
56         Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
57         return 1;
58     }
59
60     if (isMListType(pvApiCtx, piAddr1) || isTListType(pvApiCtx, piAddr1))
61     {
62         OverLoad(1);
63         return 0;
64     }
65
66     CheckRhs(2, 3);
67     CheckLhs(0, 1);
68
69     if (isDoubleType(pvApiCtx, piAddr1))   /* tclsci handle */
70     {
71         /* call "set" for tcl/tk see tclsci/sci_gateway/c/sci_set.c */
72         OverLoad(1);
73         return 0;
74     }
75     else                        /* others types */
76     {
77         int iRows1 = 0, iCols1 = 0;
78         int iRows2 = 0, iCols2 = 0;
79         int iRows3 = 0, iCols3 = 0;
80         void* _pvData = NULL;
81         unsigned long hdl;
82         char *pobjUID = NULL;
83
84         int iType1 = 0;
85
86         int valueType = 0;      /* type of the rhs */
87
88         int setStatus = 0;
89
90         /* after the call to sciSet get the status : 0 <=> OK,          */
91         /*                                          -1 <=> Error,       */
92         /*                                           1 <=> nothing done */
93
94         /*  set or create a graphic window */
95         sciErr = getVarType(pvApiCtx, piAddr1, &iType1);
96         if (sciErr.iErr)
97         {
98             printError(&sciErr, 0);
99             Scierror(999, _("%s: Can not get type of input argument #%d.\n"), fname, 1);
100             return 1;
101         }
102
103         switch (iType1)
104         {
105             case sci_handles:
106                 /* first is a scalar argument so it's a gset(hdl,"command",[param]) */
107                 /* F.Leray; INFO: case 9 is considered for a matrix of graphic handles */
108                 CheckRhs(3, 3);
109
110                 if (isScalar(pvApiCtx, piAddr1) == FALSE)
111                 {
112                     OverLoad(1);
113                     return 0;
114                 }
115
116                 if (getScalarHandle(pvApiCtx, piAddr1, (long long*)&hdl))
117                 {
118                     Scierror(999, _("%s: Wrong size for input argument #%d: A single handle expected.\n"), fname, 1);
119                     return 1;
120                 }
121
122                 pobjUID = (char*)getObjectFromHandle(hdl);
123
124                 sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2);
125                 if (sciErr.iErr)
126                 {
127                     Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 2);
128                     return 1;
129                 }
130
131                 if (getAllocatedSingleString(pvApiCtx, piAddr2, &pstProperty))
132                 {
133                     Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 2);
134                     return 1;
135                 }
136                 valueType = getInputArgumentType(pvApiCtx, 3);
137
138                 sciErr = getVarAddressFromPosition(pvApiCtx, 3, &piAddr3);
139                 if (sciErr.iErr)
140                 {
141                     Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 3);
142                     return 1;
143                 }
144
145                 if ((strcmp(pstProperty, "user_data") == 0) || (stricmp(pstProperty, "userdata") == 0))
146                 {
147                     /* in this case set_user_data_property
148                      * directly uses the  third position in the stack
149                      * to get the variable which is to be set in
150                      * the user_data property (any data type is allowed) S. Steer */
151                     _pvData = (void*)piAddr3;         /*position in the stack */
152                     iRows3 = -1;   /*unused */
153                     iCols3 = -1;   /*unused */
154                     valueType = -1;
155                 }
156                 else
157                 {
158                     switch (valueType)
159                     {
160                         case sci_matrix :
161                             getMatrixOfDouble(pvApiCtx, piAddr3, &iRows3, &iCols3, (double**)&_pvData);
162                             break;
163                         case sci_boolean :
164                             getMatrixOfBoolean(pvApiCtx, piAddr3, &iRows3, &iCols3, (int**)&_pvData);
165                             break;
166                         case sci_handles :
167                             getMatrixOfHandle(pvApiCtx, piAddr3, &iRows3, &iCols3, (long long**)&_pvData);
168                             break;
169                         case sci_strings :
170                             if (   strcmp(pstProperty, "tics_labels") != 0 && strcmp(pstProperty, "auto_ticks") != 0 &&
171                                     strcmp(pstProperty, "axes_visible") != 0 && strcmp(pstProperty, "axes_reverse") != 0 &&
172                                     strcmp(pstProperty, "text") != 0 && stricmp(pstProperty, "string") != 0 &&
173                                     stricmp(pstProperty, "tooltipstring") != 0) /* Added for uicontrols */
174                             {
175                                 if (getAllocatedSingleString(pvApiCtx, piAddr3, (char**)&_pvData))
176                                 {
177                                     Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 3);
178                                     return 1;
179                                 }
180                                 iRows3 = (int)strlen((char*)_pvData);
181                                 iCols3 = 1;
182                             }
183                             else
184                             {
185                                 isMatrixOfString = 1;
186                                 getAllocatedMatrixOfString(pvApiCtx, piAddr3, &iRows3, &iCols3, (char***)&_pvData);
187                             }
188                             break;
189                         case sci_list :
190                             iCols3 = 1;
191                             getListItemNumber(pvApiCtx, piAddr3, &iRows3);
192                             _pvData = (void*)piAddr3;         /* In this case l3 is the list position in stack */
193                             break;
194                         default :
195                             _pvData = (void*)piAddr3;         /* In this case l3 is the list position in stack */
196                             break;
197                     }
198                 }
199                 break;
200             case sci_strings:      /* first is a string argument so it's a set("command",[param]) */
201                 CheckRhs(2, 2);
202                 if (getAllocatedSingleString(pvApiCtx, piAddr1, &pstProperty))
203                 {
204                     Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 1);
205                     return 1;
206                 }
207
208                 hdl = 0;
209                 pobjUID = NULL;
210                 valueType = getInputArgumentType(pvApiCtx, 2);
211                 sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2);
212                 if (sciErr.iErr)
213                 {
214                     Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 2);
215                     return 1;
216                 }
217
218                 if (valueType == sci_matrix)
219                 {
220                     sciErr = getMatrixOfDouble(pvApiCtx, piAddr2, &iRows3, &iCols3, (double**)&_pvData);
221                     if (sciErr.iErr)
222                     {
223                         printError(&sciErr, 0);
224                         Scierror(999, _("%s: Wrong type for input argument #%d: Matrix expected.\n"), fname, 2);
225                         return sciErr.iErr;
226                     }
227                 }
228                 else if (valueType == sci_handles)
229                 {
230                     sciErr = getMatrixOfHandle(pvApiCtx, piAddr2, &iRows3, &iCols3, (long long**)&_pvData);
231                     if (sciErr.iErr)
232                     {
233                         printError(&sciErr, 0);
234                         Scierror(999, _("%s: Wrong type for input argument #%d: Matrix of handle expected.\n"), fname, 3);
235                         return 1;
236                     }
237                 }
238                 else if (valueType == sci_strings)
239                 {
240                     if (strcmp(pstProperty, "tics_labels") == 0 || strcmp(pstProperty, "auto_ticks") == 0 ||
241                             strcmp(pstProperty, "axes_visible") == 0 || strcmp(pstProperty, "axes_reverse") == 0 ||
242                             strcmp(pstProperty, "text") == 0)
243                     {
244                         isMatrixOfString = 1;
245                         if (getAllocatedMatrixOfString(pvApiCtx, piAddr2, &iRows3, &iCols3, (char***)&_pvData))
246                         {
247                             Scierror(999, _("%s: Wrong size for input argument #%d: A matrix of string expected.\n"), fname, 2);
248                             return 1;
249                         }
250                     }
251                     else
252                     {
253                         if (getAllocatedSingleString(pvApiCtx, piAddr2, (char**)&_pvData))
254                         {
255                             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 2);
256                             return 1;
257                         }
258                         iRows3 = (int)strlen((char*)_pvData);
259                         iCols3 = 1;
260                     }
261                 }
262                 break;
263
264             default:
265                 Scierror(999, _("%s: Wrong type for input argument #%d: String or handle expected.\n"), fname, 1);
266                 return 0;
267                 break;
268         }
269
270         if (hdl != 0)
271         {
272             pobjUID = (char*)getObjectFromHandle(hdl);
273
274             if (pobjUID == NULL)
275             {
276                 Scierror(999, _("%s: The handle is not or no more valid.\n"), fname);
277                 return 0;
278             }
279
280             // Only set the property whitout doing anythig else.
281             //static int sciSet(void* _pvCtx, char *pobjUID, char *marker, void* value, int valueType, int *numrow, int *numcol)
282             setStatus = callSetProperty(pvApiCtx, pobjUID, _pvData, valueType, iRows3, iCols3, pstProperty);
283             if (valueType == sci_strings)
284             {
285                 //free allacted data
286                 if (isMatrixOfString == 1)
287                 {
288                     freeAllocatedMatrixOfString(iRows3, iCols3, (char**)_pvData);
289                 }
290                 else
291                 {
292                     freeAllocatedSingleString((char*)_pvData);
293                 }
294             }
295         }
296         else
297         {
298 #define NB_PROPERTIES_SUPPORTED 7
299             /* No object specified */
300             /* ONLY supported properties are */
301             /* 'current_entity' */
302             /* 'hdl' */
303             /* 'current_figure' */
304             /* 'current_axes' */
305             /* 'default_values' */
306             /* 'figure_style' for compatibility but do nothing */
307             /* others values must return a error */
308             char *propertiesSupported[NB_PROPERTIES_SUPPORTED] = { "current_entity",
309                                                                    "hdl",
310                                                                    "current_figure",
311                                                                    "current_axes",
312                                                                    "figure_style",
313                                                                    "default_values",
314                                                                    "auto_clear"
315                                                                  };
316
317             int i = 0;
318             int iPropertyFound = 0;
319
320             for (i = 0; i < NB_PROPERTIES_SUPPORTED; i++)
321             {
322
323                 if (strcmp(propertiesSupported[i], pstProperty) == 0)
324                 {
325                     iPropertyFound = 1;
326                 }
327             }
328
329             if (iPropertyFound)
330             {
331                 setStatus = callSetProperty(pvApiCtx, NULL, _pvData, valueType, iRows3, iCols3, pstProperty);
332                 if (valueType == sci_strings)
333                 {
334                     //free allocated data
335                     if (isMatrixOfString == 1)
336                     {
337                         freeAllocatedMatrixOfString(iRows3, iCols3, (char**)_pvData);
338                     }
339                     else
340                     {
341                         freeAllocatedSingleString((char*)_pvData);
342                     }
343                 }
344             }
345             else
346             {
347                 Scierror(999, _("%s: Wrong value for input argument #%d: a valid property expected.\n"), fname, 1);
348                 if (isMatrixOfString)
349                 {
350                     freeArrayOfString((char **)_pvData, iRows3 * iCols3);
351                 }
352                 return 0;
353             }
354         }
355
356         AssignOutputVariable(pvApiCtx, 1) = 0;
357         ReturnArguments(pvApiCtx);
358     }
359
360     return 0;
361 }
362
363 /*--------------------------------------------------------------------------*/