* Bug 15876 fixed: now struct and cells are reported native in browsevar
[scilab.git] / scilab / modules / ui_data / src / cpp / BrowseVarManager.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO - Allan CORNET
4  * Copyright (C) 2010 - DIGITEO - Bruno JOFRET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include <iterator>
21 #include <set>
22 #include <cmath>
23 #include "alltypes.hxx"
24 #include "types_tools.hxx"
25
26 #include "BrowseVar.hxx"
27 #ifdef _MSC_VER
28 #ifdef max
29 #undef max
30 #endif
31 #ifdef min
32 #undef min
33 #endif
34 #endif
35 #include "context.hxx"
36
37 extern "C"
38 {
39 #include "BrowseVarManager.h"
40 #include "localization.h"
41 #include "sci_malloc.h"
42 #include "BOOL.h"
43 #include "getScilabJavaVM.h"
44 #include "Scierror.h"
45 #include "freeArrayOfString.h"
46 #include "os_string.h"
47 #include "api_scilab.h"
48 #include "sci_types.h"
49 #include "sciprint.h"
50 }
51
52 #define N_A             "N/A"
53 #define EMPTY_MATRIX    "[ ]"
54 #define EMPTY_CELL      "{}"
55 #define EMPTY_LIST      "()"
56 #define LOCAL_STR       "local"
57 #define GLOBAL_STR      "global"
58 #define INHERITED_STR   "inherited"
59 #define NEG_INF_STR     "-Inf"
60 #define INF_STR         "Inf"
61 #define NAN_STR         "NaN"
62 #define PLUS_STR        " + "
63 #define MINUS_STR       " - "
64 #define I_STR           "i"
65 #define LBRACKET_STR    "["
66 #define RBRACKET_STR    "]"
67 #define COMMA_STR       ", "
68 #define SEMICOLON_STR   "; "
69
70 using namespace org_scilab_modules_ui_data;
71 using std::string;
72
73 static std::set<string> createScilabDefaultVariablesSet();
74 static char * getListName(char * variableName);
75 static std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg);
76 static char * valueToDisplay(types::InternalType* pIT);
77 void OpenBrowseVar()
78 {
79     BrowseVar::openVariableBrowser(getScilabJavaVM());
80     SetBrowseVarData();
81 }
82
83 void UpdateBrowseVar()
84 {
85     if (BrowseVar::isVariableBrowserOpened(getScilabJavaVM()))
86     {
87         SetBrowseVarData();
88     }
89 }
90
91 void SetBrowseVarData()
92 {
93     SciErr err;
94     int iLocalVariablesUsed = 0;
95     int i = 0;
96
97     symbol::Context* ctx = symbol::Context::getInstance();
98
99     std::list<symbol::Variable*> lstVars;
100     std::list<symbol::Library*> lstLibs;
101
102     iLocalVariablesUsed = ctx->getVarsToVariableBrowser(lstVars);
103     iLocalVariablesUsed += ctx->getLibsToVariableBrowser(lstLibs);
104
105     char **pstAllVariableNames = new char*[iLocalVariablesUsed]();
106     char **pstAllVariableVisibility = new char*[iLocalVariablesUsed]();
107     char **pstAllVariableListTypes = new char*[iLocalVariablesUsed]();
108     int *piAllVariableBytes = new int[iLocalVariablesUsed]();
109     char **pstAllVariableSizes = new char*[iLocalVariablesUsed]();
110     int *piAllVariableTypes = new int[iLocalVariablesUsed]();
111     int *piAllVariableIntegerTypes = new int[iLocalVariablesUsed]();
112     bool *piAllVariableFromUser = new bool[iLocalVariablesUsed]();
113     /* Necessary for the plots in the var browser */
114     int *piAllVariableNbRows = new int[iLocalVariablesUsed]();
115     int *piAllVariableNbCols = new int[iLocalVariablesUsed]();
116
117     int nbRows, nbCols;
118     char *sizeStr = NULL;
119
120     std::set<string> scilabDefaultVariablesSet = createScilabDefaultVariablesSet();
121     int iLevel = ctx->getScopeLevel();
122
123     // for each local variable get information
124     for (auto var : lstVars)
125     {
126         //get top level value
127         symbol::ScopedVariable* sv = var->top();
128         //get value
129         types::InternalType* pIT = sv->m_pIT;
130
131         // get name
132         pstAllVariableNames[i] = wide_string_to_UTF8(var->getSymbol().getName().data());
133
134         // get visibility
135         if (sv->m_globalVisible == true)
136         {
137             pstAllVariableVisibility[i] = os_strdup(GLOBAL_STR);
138             pIT = var->getGlobalValue();
139         }
140         else if (sv->m_iLevel != iLevel)
141         {
142             pstAllVariableVisibility[i] = os_strdup(INHERITED_STR);
143         }
144         else
145         {
146             pstAllVariableVisibility[i] = os_strdup(LOCAL_STR);
147         }
148
149         // type with Scilab < 6 compatibility (structs and cells have type 17)
150         err = getVarType(NULL, (int*)pIT, &piAllVariableTypes[i]);
151
152         if (pIT->isArrayOf() || pIT->isSparse())
153         {
154             int nbRows = pIT->getAs<types::GenericType>()->getRows();
155             int nbCols = pIT->getAs<types::GenericType>()->getCols();
156             piAllVariableNbRows[i] = nbRows;
157             piAllVariableNbCols[i] = nbCols;                
158             if (nbRows*nbCols == 0)
159             {
160                 pstAllVariableSizes[i] = pIT->isCell() ? os_strdup(EMPTY_CELL) : os_strdup(EMPTY_MATRIX);                
161             }
162             else if (pIT->isArrayOf())
163             {
164                 pstAllVariableSizes[i] = valueToDisplay(pIT);
165             }
166             else
167             {
168                 std::string sizeString = std::to_string(nbRows) + "x" + std::to_string(nbCols);
169                 pstAllVariableSizes[i] =  os_strdup(sizeString.data());
170             }
171         }
172         else if (pIT->isMList() || pIT->isTList() || pIT->isList() )
173         {
174             pstAllVariableSizes[i] = pIT->getAs<types::List>()->getSize() == 0 ? os_strdup(EMPTY_LIST) : os_strdup(N_A);
175         }
176         else
177         {
178             pstAllVariableSizes[i] =  os_strdup(N_A);
179         }
180
181         if (piAllVariableTypes[i] == sci_ints)
182         {
183             // Integer case
184             int iPrec       = 0;
185             err = getMatrixOfIntegerPrecision(NULL, (int*)pIT, &iPrec);
186             switch (iPrec)
187             {
188                 case SCI_INT8:
189                     piAllVariableIntegerTypes[i] = 8;
190                     break;
191                 case SCI_INT16:
192                     piAllVariableIntegerTypes[i] = 16;
193                     break;
194                 case SCI_INT32:
195                     piAllVariableIntegerTypes[i] = 32;
196                     break;
197 #ifdef __SCILAB_INT64__
198                 case SCI_INT64:
199                     piAllVariableIntegerTypes[i] = 64;
200                     break;
201 #endif
202                 default:
203                     piAllVariableIntegerTypes[i] = 0; // Should never occurs
204                     break;
205             }
206         }
207         else
208         {
209             piAllVariableIntegerTypes[i] = -1;
210         }
211
212         if (pIT->isTList() || pIT->isMList())
213         {
214             pstAllVariableListTypes[i] = getListName(pstAllVariableNames[i]);
215         }
216         else if (pIT->isStruct())
217         {
218             piAllVariableTypes[i] = sci_struct;
219             pstAllVariableListTypes[i] = os_strdup("");
220         }
221         else if (pIT->isCell())
222         {
223             piAllVariableTypes[i] = sci_cell;
224             pstAllVariableListTypes[i] = os_strdup("");
225         }
226         else
227         {
228             pstAllVariableListTypes[i] = os_strdup("");
229         }
230
231         if (scilabDefaultVariablesSet.find(string(pstAllVariableNames[i])) == scilabDefaultVariablesSet.end() && piAllVariableTypes[i] != sci_lib)
232         {
233             piAllVariableFromUser[i] = TRUE;
234         }
235         else
236         {
237             piAllVariableFromUser[i] = FALSE;
238         }
239
240         ++i;
241     }
242
243     // Launch Java Variable Browser through JNI
244     BrowseVar::setVariableBrowserData(getScilabJavaVM(),
245                                       pstAllVariableNames, iLocalVariablesUsed,
246                                       piAllVariableBytes, iLocalVariablesUsed,
247                                       piAllVariableTypes, iLocalVariablesUsed,
248                                       piAllVariableIntegerTypes, iLocalVariablesUsed,
249                                       pstAllVariableListTypes, iLocalVariablesUsed,
250                                       pstAllVariableSizes, iLocalVariablesUsed,
251                                       piAllVariableNbRows, iLocalVariablesUsed,
252                                       piAllVariableNbCols, iLocalVariablesUsed,
253                                       pstAllVariableVisibility, iLocalVariablesUsed,
254                                       piAllVariableFromUser, iLocalVariablesUsed);
255
256     for (int i = 0; i < iLocalVariablesUsed; ++i)
257     {
258         FREE(pstAllVariableNames[i]);
259         FREE(pstAllVariableVisibility[i]);
260         FREE(pstAllVariableSizes[i]);
261         FREE(pstAllVariableListTypes[i]);
262     }
263
264     delete[] pstAllVariableNames;
265     delete[] pstAllVariableVisibility;
266     delete[] pstAllVariableSizes;
267     delete[] pstAllVariableListTypes;
268
269     delete[] piAllVariableFromUser;
270     delete[] piAllVariableBytes;
271     delete[] piAllVariableTypes;
272     delete[] piAllVariableIntegerTypes;
273     delete[] piAllVariableNbRows;
274     delete[] piAllVariableNbCols;
275 }
276
277 /*--------------------------------------------------------------------------*/
278 static std::set<string> createScilabDefaultVariablesSet()
279 {
280     string arr[] = { "home",
281                      "PWD",
282                      "%tk",
283                      "%pvm",
284                      "MSDOS",
285                      "%F",
286                      "%T",
287                      "%f",
288                      "%t",
289                      "%e",
290                      "%pi",
291                      "%modalWarning",
292                      "%nan",
293                      "%inf",
294                      "SCI",
295                      "WSCI",
296                      "SCIHOME",
297                      "TMPDIR",
298                      "%gui",
299                      "%fftw",
300                      "%helps",
301                      "%eps",
302                      "%io",
303                      "%i",
304                      "demolist",
305                      "%z",
306                      "%s",
307                      "$",
308                      "%toolboxes",
309                      "%toolboxes_dir",
310                      "TICTOC",
311                      "%helps_modules",
312                      "%_atoms_cache",
313                      "evoid", // Constant for external object
314                      "jvoid", // Constant for external object Java (jims)
315                      "jnull", // Constant for external object Java (jims)
316                      "enull"  // Constant for external object
317                    };
318     int i = 0;
319
320 #define NBELEMENT 37
321     std::set<string> ScilabDefaultVariables;
322
323     for (i = 0; i < NBELEMENT; i++)
324     {
325         ScilabDefaultVariables.insert(arr[i]);
326     }
327
328     return ScilabDefaultVariables;
329 }
330
331 static char * getListName(char * variableName)
332 {
333     SciErr sciErr;
334     int *piAddr = NULL;
335     int* piAddr1 = NULL;
336     int iRows = 0;
337     int iCols = 0;
338     char **pstType;
339     char *tmpChar;
340     sciErr = getVarAddressFromName(NULL, variableName, &piAddr);
341     if (sciErr.iErr)
342     {
343         return os_strdup("");
344     }
345
346     sciErr = getListItemAddress(NULL, piAddr, 1, &piAddr1);
347     if (sciErr.iErr)
348     {
349         return os_strdup("");
350     }
351
352     if (getAllocatedMatrixOfString(NULL, piAddr1, &iRows, &iCols, &pstType))
353     {
354
355         return os_strdup("");
356     }
357     tmpChar = os_strdup(pstType[0]);
358     freeAllocatedMatrixOfString(iRows, iCols, pstType);
359     return tmpChar;
360 }
361
362 static char *valueToDisplay(types::InternalType* pIT)
363 {
364     types::GenericType *pGT = pIT->getAs<types::GenericType>();
365     int *piDims = pGT->getDimsArray();
366
367     if (pIT->isDouble() && pGT->getDims() < 3 && pGT->getSize() <= 4) {
368         // 4 is the dimension max to which display the content
369         types::Double* pD = pIT->getAs<types::Double>();
370         // Small double value, display it
371         double* pdblReal = nullptr;
372         double* pdblImg = nullptr;
373         pdblReal = pD->get();
374
375         if (pD->isComplex())
376         {
377             pdblImg = pD->getImg();
378         }
379
380         return os_strdup(formatMatrix(piDims[0], piDims[1], pdblReal, pdblImg).c_str());
381     }
382     else
383     {
384         std::string sizeStr = std::to_string(piDims[0]);
385         for (int i = 1; i < pGT->getDims(); i++)
386         {
387             sizeStr.append("x");
388             sizeStr.append(std::to_string(piDims[i]));
389         }
390
391         return os_strdup(sizeStr.data());
392     }
393 }
394
395 std::string addDouble(double dbl)
396 {
397 #define PRECISION_DISPLAY 3
398     std::ostringstream os;
399     if (ISNAN(dbl))
400     {
401         os << NAN_STR;
402     }
403     else if (finite(dbl))
404     {
405         os.precision(PRECISION_DISPLAY);
406         os << dbl; // Convert the double to string
407     }
408     else
409     {
410         if (dbl > 0)
411         {
412             os << INF_STR;
413         }
414         else
415         {
416             os << NEG_INF_STR;
417         }
418     }
419
420     return os.str();
421 }
422 std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg)
423 {
424     int i, j ;
425     if (nbRows * nbCols == 1)
426     {
427         std::ostringstream os;
428         std::string formatted = addDouble(pdblReal[0]);
429         if (pdblImg)
430         {
431             double img = pdblImg[0];
432             if (img > 0)
433             {
434                 formatted += PLUS_STR;
435             }
436             else
437             {
438                 formatted += MINUS_STR;
439             }
440             formatted += addDouble(std::fabs(img));
441             formatted += I_STR;
442         }
443         return formatted;
444     }
445
446     std::string formatted = LBRACKET_STR;
447     for (j = 0 ; j < nbRows ; j++)
448     {
449         for (i = 0 ; i < nbCols ; i++)
450         {
451             /* Display the formatted matrix ... the way the user
452              * expect */
453             formatted += addDouble(pdblReal[i * nbRows + j]);
454             if (pdblImg)
455             {
456                 double img = pdblImg[i * nbRows + j];
457                 if (img > 0)
458                 {
459                     formatted += PLUS_STR;
460                 }
461                 else
462                 {
463                     formatted += MINUS_STR;
464                 }
465
466                 formatted += addDouble(std::fabs(img));
467                 formatted += I_STR;
468             }
469
470
471             if (i + 1 != nbCols) // Not the last element of the matrix
472             {
473                 formatted += COMMA_STR;
474             }
475         }
476         if (j + 1 != nbRows) // Not the last line of the matrix
477         {
478             formatted += SEMICOLON_STR;
479         }
480     }
481     return formatted + "]";
482 }