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