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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
10  *
11  * This file is hereby licensed under the terms of the GNU GPL v2.0,
12  * pursuant to article 5.3.4 of the CeCILL v.2.1.
13  * This file was originally licensed under the terms of the CeCILL v2.1,
14  * and continues to be available under such terms.
15  * For more information, see the COPYING file which you should have received
16  * along with this program.
17  *
18  */
19 
20 /*------------------------------------------------------------------------*/
21 /* file: sci_set.h                                                        */
22 /* desc : interface for sci_set routine                                   */
23 /*------------------------------------------------------------------------*/
24 #ifdef _MSC_VER
25 #include <Windows.h>
26 #endif
27 
28 #include <stdio.h>
29 /*------------------------------------------------------------------------*/
30 #include "gw_graphics.h"
31 #include "Scierror.h"
32 #include "HandleManagement.h"
33 #include "GetProperty.h"
34 #include "InitObjects.h"
35 #include "freeArrayOfString.h"
36 
37 #include "SetHashTable.h"
38 #include "SetPropertyStatus.h"
39 
40 #include "sci_malloc.h"             /* MALLOC */
41 #include "localization.h"
42 #include "os_string.h"
43 #include "api_scilab.h"
44 #include "FigureList.h"
45 #include "sciprint.h"
46 
47 /*--------------------------------------------------------------------------
48  * sciset(choice-name,x1,x2,x3,x4,x5)
49  * or   xset()
50  *-----------------------------------------------------------*/
sci_set(char * fname,void * pvApiCtx)51 int sci_set(char *fname, void *pvApiCtx)
52 {
53     SciErr sciErr;
54     int i = 0;
55     int* piAddr1 = NULL;
56 
57     int isMatrixOfString = 0;
58 
59     char* pstNewProperty = NULL;
60 
61     unsigned long hdl;
62     int iObjUID = 0;
63     int iType = 0;
64     int* piType = &iType;
65 
66     int iSetProperty = 0;
67 
68     int iRhs = nbInputArgument(pvApiCtx);
69     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1);
70     if (sciErr.iErr)
71     {
72         Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
73         return 1;
74     }
75 
76     if (isMListType(pvApiCtx, piAddr1) || isTListType(pvApiCtx, piAddr1))
77     {
78         OverLoad(1);
79         return 0;
80     }
81 
82     CheckInputArgumentAtLeast(pvApiCtx, 2);
83     CheckOutputArgument(pvApiCtx, 0, 1);
84 
85     if (isDoubleType(pvApiCtx, piAddr1))   /* tclsci handle */
86     {
87         /* call "set" for tcl/tk see tclsci/sci_gateway/c/sci_set.c */
88         OverLoad(1);
89         return 0;
90     }
91 
92     if (iRhs == 2)
93     {
94 #define NB_PROPERTIES_SUPPORTED 7
95         /* No object specified */
96         /* ONLY supported properties are */
97         /* 'current_entity' */
98         /* 'hdl' */
99         /* 'current_figure' */
100         /* 'current_axes' */
101         /* 'default_values' */
102         /* 'figure_style' for compatibility but do nothing */
103         /* others values must return a error */
104         char *propertiesSupported[NB_PROPERTIES_SUPPORTED] =
105         {
106             "current_entity",
107             "hdl",
108             "current_figure",
109             "current_axes",
110             "figure_style",
111             "default_values",
112             "auto_clear"
113         };
114 
115         int iPropertyFound = 0;
116         int* piAddr2 = NULL;
117         int iType2 = 0;
118         int iRows2 = 0;
119         int iCols2 = 0;
120         void* pvData = NULL;
121         char* pstProperty = NULL;
122 
123         if (isStringType(pvApiCtx, piAddr1) == 0)
124         {
125             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 1);
126             return 0;
127         }
128 
129         if (getAllocatedSingleString(pvApiCtx, piAddr1, &pstProperty))
130         {
131             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 1);
132             return 1;
133         }
134 
135         sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddr2);
136         if (sciErr.iErr)
137         {
138             freeAllocatedSingleString(pstProperty);
139             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 2);
140             return 1;
141         }
142 
143         sciErr = getVarType(pvApiCtx, piAddr2, &iType2);
144         if (sciErr.iErr)
145         {
146             freeAllocatedSingleString(pstProperty);
147             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 2);
148             return 1;
149         }
150 
151         switch (iType2)
152         {
153             case sci_matrix:
154                 sciErr = getMatrixOfDouble(pvApiCtx, piAddr2, &iRows2, &iCols2, (double**)&pvData);
155                 if (sciErr.iErr)
156                 {
157                     freeAllocatedSingleString(pstProperty);
158                     printError(&sciErr, 0);
159                     Scierror(999, _("%s: Wrong type for input argument #%d: Matrix expected.\n"), fname, 2);
160                     return sciErr.iErr;
161                 }
162                 break;
163             case sci_handles :
164                 sciErr = getMatrixOfHandle(pvApiCtx, piAddr2, &iRows2, &iCols2, (long long**)&pvData);
165                 if (sciErr.iErr)
166                 {
167                     freeAllocatedSingleString(pstProperty);
168                     printError(&sciErr, 0);
169                     Scierror(999, _("%s: Wrong type for input argument #%d: Matrix of handle expected.\n"), fname, 3);
170                     return 1;
171                 }
172                 break;
173             case sci_strings :
174                 if (stricmp(pstProperty, "tics_labels") == 0 || stricmp(pstProperty, "auto_ticks") == 0 ||
175                         stricmp(pstProperty, "axes_visible") == 0 || stricmp(pstProperty, "axes_reverse") == 0 ||
176                         stricmp(pstProperty, "text") == 0 || stricmp(pstProperty, "ticks_format") == 0)
177                 {
178                     isMatrixOfString = 1;
179                     if (getAllocatedMatrixOfString(pvApiCtx, piAddr2, &iRows2, &iCols2, (char***)&pvData))
180                     {
181                         freeAllocatedSingleString(pstProperty);
182                         Scierror(999, _("%s: Wrong size for input argument #%d: A matrix of string expected.\n"), fname, 2);
183                         return 1;
184                     }
185                 }
186                 else
187                 {
188                     if (getAllocatedSingleString(pvApiCtx, piAddr2, (char**)&pvData))
189                     {
190                         freeAllocatedSingleString(pstProperty);
191                         Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 2);
192                         return 1;
193                     }
194                     iRows2 = (int)strlen((char*)pvData);
195                     iCols2 = 1;
196                     isMatrixOfString = 0;
197                 }
198                 break;
199         }
200 
201 
202 
203         for (i = 0; i < NB_PROPERTIES_SUPPORTED; i++)
204         {
205 
206             if (strcmp(propertiesSupported[i], pstProperty) == 0)
207             {
208                 iPropertyFound = 1;
209             }
210         }
211 
212         if (iPropertyFound)
213         {
214             callSetProperty(pvApiCtx, 0, pvData, iType2, iRows2, iCols2, pstProperty);
215             if (iType2 == sci_strings)
216             {
217                 //free allocated data
218                 if (isMatrixOfString == 1)
219                 {
220                     freeAllocatedMatrixOfString(iRows2, iCols2, (char**)pvData);
221                 }
222                 else
223                 {
224                     freeAllocatedSingleString((char*)pvData);
225                 }
226             }
227         }
228         else
229         {
230             freeAllocatedSingleString(pstProperty);
231             Scierror(999, _("%s: Wrong value for input argument #%d: a valid property expected.\n"), fname, 1);
232             if (iType2 == sci_strings)
233             {
234                 if (isMatrixOfString == 1)
235                 {
236                     freeAllocatedMatrixOfString(iRows2, iCols2, (char**)pvData);
237                 }
238                 else
239                 {
240                     freeAllocatedSingleString((char*)pvData);
241                 }
242             }
243             return 0;
244         }
245 
246         freeAllocatedSingleString(pstProperty);
247         AssignOutputVariable(pvApiCtx, 1) = 0;
248         ReturnArguments(pvApiCtx);
249         return 0;
250     }
251 
252     if (iRhs % 2 != 1)
253     {
254         Scierror(999, _("%s: Wrong number of input argument(s) : an odd number is expected.\n"), fname);
255         return 0;
256     }
257 
258 
259     /* after the call to sciSet get the status : 0 <=> OK,          */
260     /*                                          -1 <=> Error,       */
261     /*                                           1 <=> nothing done */
262 
263     /*  set or create a graphic window */
264     if (isHandleType(pvApiCtx, piAddr1) == 0 && isStringType(pvApiCtx, piAddr1) == 0)
265     {
266         Scierror(999, _("%s: Wrong type for input argument #%d: A handle or a string expected.\n"), fname, 1);
267         return 0;
268     }
269 
270     if (isStringType(pvApiCtx, piAddr1))
271     {
272         char* pstPath = NULL;
273         if (getAllocatedSingleString(pvApiCtx, piAddr1, &pstPath))
274         {
275             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, 1);
276             return 1;
277         }
278 
279         iObjUID = search_path(pstPath);
280         if (iObjUID == 0)
281         {
282             Scierror(999, _("%s: Unable to find handle for path %s.\n"), fname, pstPath);
283             freeAllocatedSingleString(pstPath);
284             return 1;
285         }
286         freeAllocatedSingleString(pstPath);
287     }
288     else
289     {
290         //matrix of handle are managed by a %h_set
291         if (isScalar(pvApiCtx, piAddr1) == FALSE)
292         {
293             OverLoad(1);
294             return 0;
295         }
296 
297         if (getScalarHandle(pvApiCtx, piAddr1, (long long*)&hdl))
298         {
299             Scierror(999, _("%s: Wrong size for input argument #%d: A single handle expected.\n"), fname, 1);
300             return 1;
301         }
302 
303         iObjUID = getObjectFromHandle(hdl);
304     }
305 
306     if (iObjUID == 0)
307     {
308         Scierror(999, _("%s: The handle is not or no more valid.\n"), fname);
309         return 0;
310     }
311 
312     for (i = 1 ; i < iRhs ; i = i + 2)
313     {
314         int setStatus = 0;
315         int* piAddr2 = NULL;
316         int* piAddr3 = NULL;
317 
318         int iPos = i + 1;
319         int isData = 0;
320 
321         int iRows3 = 0;
322         int iCols3 = 0;
323         int iType3 = 0;
324         void* pvData = NULL;
325         char* pstProperty = NULL;
326 
327         sciErr = getVarAddressFromPosition(pvApiCtx, iPos, &piAddr2);
328         if (sciErr.iErr)
329         {
330             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, iPos);
331             return 1;
332         }
333 
334         if (isStringType(pvApiCtx, piAddr2) == 0)
335         {
336             Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), fname, iPos);
337             return 0;
338         }
339 
340         if (getAllocatedSingleString(pvApiCtx, piAddr2, &pstProperty))
341         {
342             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, iPos);
343             return 1;
344         }
345 
346         sciErr = getVarAddressFromPosition(pvApiCtx, iPos + 1, &piAddr3);
347         if (sciErr.iErr)
348         {
349             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, iPos + 1);
350             freeAllocatedSingleString(pstProperty);
351             return 1;
352         }
353 
354         if ((pstProperty[0] == 'd' || pstProperty[0] == 'D') && stricmp("data", pstProperty) == 0)
355         {
356             //send to datamodel
357             isData = 1;
358         }
359 
360         if (stricmp(pstProperty, "user_data") == 0 ||
361                 stricmp(pstProperty, "userdata") == 0 ||
362                 stricmp(pstProperty, "display_function_data") == 0 ||
363                 stricmp(pstProperty, "data") == 0)
364         {
365             /* in this case set_user_data_property
366             * directly uses the  third position in the stack
367             * to get the variable which is to be set in
368             * the user_data property (any data type is allowed) S. Steer */
369             pvData = (void*)piAddr3;         /*position in the stack */
370             iRows3 = -1;   /*unused */
371             iCols3 = -1;   /*unused */
372             iType3 = -1;
373         }
374         else
375         {
376             sciErr = getVarType(pvApiCtx, piAddr3, &iType3);
377             if (sciErr.iErr)
378             {
379                 Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, iPos + 1);
380                 freeAllocatedSingleString(pstProperty);
381                 return 1;
382             }
383 
384             switch (iType3)
385             {
386                 case sci_matrix :
387                     sciErr = getMatrixOfDouble(pvApiCtx, piAddr3, &iRows3, &iCols3, (double**)&pvData);
388                     break;
389                 case sci_boolean :
390                     sciErr = getMatrixOfBoolean(pvApiCtx, piAddr3, &iRows3, &iCols3, (int**)&pvData);
391                     break;
392                 case sci_handles :
393                     sciErr = getMatrixOfHandle(pvApiCtx, piAddr3, &iRows3, &iCols3, (long long**)&pvData);
394                     break;
395                 case sci_strings :
396                     if (stricmp(pstProperty, "tics_labels") != 0 && stricmp(pstProperty, "auto_ticks") != 0 && stricmp(pstProperty, "tight_limits") != 0 &&
397                             stricmp(pstProperty, "axes_visible") != 0 && stricmp(pstProperty, "axes_reverse") != 0 &&
398                             stricmp(pstProperty, "text") != 0 && stricmp(pstProperty, "string") != 0 &&
399                             stricmp(pstProperty, "tooltipstring") != 0 && stricmp(pstProperty, "ticks_format") != 0) /* Added for uicontrols */
400                     {
401                         if (isScalar(pvApiCtx, piAddr3) == 0)
402                         {
403                             Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), fname, iPos + 1);
404                             freeAllocatedSingleString(pstProperty);
405                             return 1;
406                         }
407 
408                         if (getAllocatedSingleString(pvApiCtx, piAddr3, (char**)&pvData))
409                         {
410                             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, iPos + 1);
411                             freeAllocatedSingleString(pstProperty);
412                             return 1;
413                         }
414                         iRows3 = (int)strlen((char*)pvData);
415                         iCols3 = 1;
416                         isMatrixOfString = 0;
417                     }
418                     else
419                     {
420                         isMatrixOfString = 1;
421                         if (getAllocatedMatrixOfString(pvApiCtx, piAddr3, &iRows3, &iCols3, (char***)&pvData))
422                         {
423                             Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, iPos + 1);
424                             freeAllocatedSingleString(pstProperty);
425                             return 1;
426                         }
427                     }
428                     break;
429                 case sci_list :
430                     iCols3 = 1;
431                     sciErr = getListItemNumber(pvApiCtx, piAddr3, &iRows3);
432                     pvData = (void*)piAddr3;         /* In this case l3 is the list position in stack */
433                     break;
434                 default :
435                     pvData = (void*)piAddr3;         /* In this case l3 is the list position in stack */
436                     break;
437             }
438 
439             if (sciErr.iErr)
440             {
441                 Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, iPos + 1);
442                 freeAllocatedSingleString(pstProperty);
443                 if (isMatrixOfString == 1)
444                 {
445                     freeAllocatedMatrixOfString(iRows3, iCols3, (char**)pvData);
446                 }
447                 else
448                 {
449                     freeAllocatedSingleString((char*)pvData);
450                 }
451                 return 1;
452             }
453         }
454 
455         setStatus = callSetProperty(pvApiCtx, iObjUID, pvData, iType3, iRows3, iCols3, pstProperty);
456         if (iType3 == sci_strings)
457         {
458             //free allacted data
459             if (isMatrixOfString == 1)
460             {
461                 freeAllocatedMatrixOfString(iRows3, iCols3, (char**)pvData);
462             }
463             else
464             {
465                 freeAllocatedSingleString((char*)pvData);
466             }
467         }
468 
469         freeAllocatedSingleString(pstProperty);
470     }
471 
472 #ifdef _MSC_VER
473     //never occurs, just to break weird optimisation (bug 14896)
474     if (iRhs == 0)
475     {
476         Sleep(1);
477     }
478 #endif
479 
480     AssignOutputVariable(pvApiCtx, 1) = 0;
481     ReturnArguments(pvApiCtx);
482     return 0;
483 }
484 /*--------------------------------------------------------------------------*/
485