* Bug 16333: tree_show(xcos_block) crashed
[scilab.git] / scilab / modules / data_structures / macros / list2tree.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2019 - 2020 - Samuel GOUGEON
3 //
4 // This file is hereby licensed under the terms of the GNU GPL v2.0,
5 // pursuant to article 5.3.4 of the CeCILL v.2.1.
6 // This file was originally licensed under the terms of the CeCILL v2.1,
7 // and continues to be available under such terms.
8 // For more information, see the COPYING file which you should have received
9 // along with this program.
10
11 // Internal function (for the time being..)
12
13 function tree = list2tree(x, titleRoot, styles, arrayByFields)
14     // x : list, cells or structs array, tlist, mlist, Xcos block
15     // titleRoot: single string: label of the tree root, for instance
16     //     the name of x in the calling environment
17     // styles: single string = HTML.4 tag embedding the address
18     //   of each data (fields names, lists indices..).
19     //   Example: "<b>$</b>"  where $ will be replaced with the address.
20     // arrayByFields: single boolean (when x is an array of structs).
21     //   %T => For each field: the array of its values is displayed.
22     //   %F => For each array component, all its fields are displayed.
23
24     // CHECKING INPUT ARGUMENTS
25     // ------------------------
26     if argn(2) < 1 then
27         msg = _("%s: Wrong number of input argument(s): %d to %d expected.\n")
28         error(msprintf(msg, "list2tree", 1, 4));
29     end
30
31     if and(type(x)<>[15 16 17 128]) then
32         msg = _("%s: Argument #%d: Container or Xcos object expected.\n")
33         error(msprintf(msg, "list2tree", 1))
34     end
35
36     if ~isdef("titleRoot","l")
37         titleRoot = "";
38     end
39
40     if ~isdef("arrayByFields","l") then
41         arrayByFields = %f
42     elseif type(arrayByFields) <> 4
43         msg = _("%s: Argument #%d: Boolean(s) expected.\n")
44         error(msprintf(msg, "tree_show", 3))
45     else
46         arrayByFields = arrayByFields(1)
47     end
48
49     if ~isdef("styles","l") then
50         styles = ""
51     elseif type(styles) <> 10
52         msg = _("%s: Argument #%d: Text(s) expected.\n")
53         error(msprintf(msg, "tree_show", 4))
54     else
55         styles = styles(1)
56     end
57
58     // BUILDING THE TREE
59     // -----------------
60     tree = uiCreateNode(titleRoot);
61     tree = list2tree_inc(x, "root", tree, styles, arrayByFields);
62 endfunction
63
64 // ===========================================================================
65
66 function tree = list2tree_inc(x, Path, tree, styles, arrayByFields)
67
68     if type(x) <> 15 then
69         list_field_content = %f
70     end
71     if type(x)==15 then
72         if length(x)==0 then
73             tree($).label = tree($).label + " list()"
74             return
75         end
76         II = 1:size(x);
77         if isdef("list_field_content") & list_field_content
78             if sum(list_field_content>1)>1
79                 // Generating all "(i,j,..)" headers
80                 v = container_get_ijk_labels(list_field_content)
81             else
82                 v = msprintf("%d\n",II')';
83                 if prod(list_field_content)==1  // parent struct is scalar
84                     tree($).label = tree($).label + " [list]"
85                 end
86             end
87         else
88             tree($).label = tree($).label + " [list]"
89             v = msprintf("%d\n",II')';
90         end
91
92     elseif typeof(x)=="ce"
93         nb = length(x)
94         if nb==0
95             tree($).label = tree($).label + " { }"
96             return
97         else
98             if nb==1 then
99                 tmp = " [cell]"
100             else
101                 tmp = msprintf(" [%s cell]", ..
102                         strcat(msprintf("%d\n",size(x)'),"x"));
103             end
104             tree($).label = tree($).label + tmp
105             II = 1:nb
106             // Generating all "(i,j,..)" headers
107             v = container_get_ijk_labels(size(x))
108         end
109
110     elseif (type(x)==17 & typeof(x)=="st") then
111         // Structures are displayed first by k indices, then
112         // for each x(k), by field. In this way, each x(k) is
113         // displayed as a whole object/record, instead of being split.
114         if length(x)==0 then
115             tree($).label = tree($).label + " struct()"
116             return
117         else
118             if arrayByFields | length(x)==1 then
119                 if length(x)==1 then
120                     if isdef("struct_array") & struct_array then
121                         tmp = "↴"
122                     else
123                         tmp = " [struct]"
124                     end
125                 else
126                     tmp = msprintf(" [%s struct]", ..
127                             strcat(msprintf("%d\n",size(x)'),"x"));
128                 end
129                 struct_array = %f
130                 v = ["" ; fieldnames(x)]
131                 II = 2:size(v,"*")  // fields indices
132                 list_field_content = size(x)
133             else
134                 tmp = msprintf(" [%s struct]", ..
135                         strcat(msprintf("%d\n",size(x)'),"x"));
136                 II = 1:size(x,"*")
137                 v = container_get_ijk_labels(size(x))
138                 struct_array = %t
139             end
140             tree($).label = tree($).label + tmp
141         end
142
143     elseif typeof(x)=="rational"
144         v = getfield(1,x);
145         II = 2:4
146         if x.dt == []
147             II = 2:3 // dt field skipped
148         end
149         if size(x,"*")<=1 then
150             tmp = " [rational]"
151         else
152             tmp = msprintf(" [%s rational]", ..
153                     strcat(msprintf("%d\n",size(x)'),"x"));
154         end
155         tree($).label = tree($).label + tmp
156
157     elseif type(x)==128 & or(typeof(x)==["diagram" "Block"])
158         tmp = _(" [Xcos diagram]")
159         if typeof(x)=="Block" then
160             tmp = _(" [Xcos block]")
161         end
162         struct_array = %f
163         v = ["" ; fieldnames(x)]
164         II = 2:size(v,"*")  // fields indices
165         //list_field_content = size(x)
166         tree($).label = tree($).label + tmp
167
168     else // or(type(x)==[16 17])
169         v = getfield(1,x);
170         II = 2:size(v,"*")
171         if II==[] // No field
172             tree($).label = tree($).label + " " + sci2exp(x)
173             return
174         end
175         // Header:
176         tpof = typeof(x)
177         sz = []
178         if or(tpof==["st" "ce"]) | isdef("%"+tpof+"_size") then
179             sz = size(x)
180         end
181         tmp = "tlist"
182         if type(x)==17
183             tmp = "mlist"
184         end
185         if sz == [] | prod(sz)<2
186             tmp = "[" + tpof + " " + tmp + "]"
187         else
188             tmp = msprintf(" [%s %s %s]", ..
189                     strcat(msprintf("%d\n",size(x)'),"x"), tpof, tmp);
190         end
191         tree($).label = tree($).label + tmp
192     end
193
194     // Loop over container components or fields
195     // ----------------------------------------
196     for i = II
197         path = Path+"," + msprintf("%d",i)
198         titre = v(i) + ": ";
199         if styles <> ""
200             titre = strsubst("<html>"+styles, "$", titre)
201         end
202
203         // Reads the object
204         clear o
205         if typeof(x)=="st" | (type(x)==128 & or(typeof(x)==["diagram" "Block"])) then
206             if ~struct_array
207                 o = x(v(i))
208             else
209                 o = x(i)
210             end
211         elseif typeof(x)=="ce"
212             o = x{i}
213         elseif or(type(x)==[15 16 17])
214             try // there may be more field names than data
215                 o = getfield(i,x);
216             catch
217                 o = list(,2)(1)
218             end
219         else
220             o = x
221         end
222         //
223         if ~isdef("o","l")  // void element in lists
224             currentNode = uiCreateNode(titre);
225             tree = uiConcatTree(tree, currentNode);
226
227         elseif or(type(o)==[15 16 17 128])
228             // Recursive call:
229             currentNode = uiCreateNode(titre);
230             currentNode = list2tree_inc(o, path, currentNode, styles, arrayByFields)
231             tree = uiConcatTree(tree, currentNode);
232
233         elseif typeof(o)=="implicitlist"
234             tree = uiConcatTree(tree, uiCreateNode(titre + sci2exp(o)));
235
236         elseif type(o)== 13    // function
237             p = macr2tree(o)
238             tmp = msprintf(_("%s() (%d lines)"), p.name, p.nblines)
239             tree = uiConcatTree(tree, uiCreateNode(titre + tmp));
240
241         elseif type(o)== 14    // library
242             tmp = string(o)
243             p = strsubst(tmp(1), "\", "/"); // not escaped chars for mprintf()
244             libname = xmlGetValues("/scilablib","name",p + "lib")
245             tmp = msprintf(_("%s library of %d functions @ %s"), ..
246                            libname, size(tmp,1)-1, p)
247             tree = uiConcatTree(tree, uiCreateNode(titre + tmp));
248
249         else
250             tp = typeof(o)
251             try
252                 if size(o, "*") > 40 then
253                     tts = tp + " of size " + sci2exp(size(o))
254                 else
255                     tts = sci2exp(o)
256                     if or(type(o)==(1:8))
257                         tts = strsubst(tts, ",", ", ");
258                         tts = strsubst(tts, ";", " ; ");
259                     elseif type(o)==10
260                         tts = strsubst(tts, """,""", """, """);
261                         tts = strsubst(tts, """;""", """ ; """);
262                     end
263                     if type(o)==2 | typeof(o)=="rational"
264                         vn = varn(o)
265                         if or(vn==["s" "z"])
266                             tts = strsubst(tts, "%"+vn, vn)
267                             tts = strsubst(tts, "*", "")
268                         end
269                     end
270                     if (or(type(o)==[1 2 5]) | typeof(o)=="rational")
271                         tts = strsubst(tts, "%inf","Inf")
272                         tts = strsubst(tts, "%nan","Nan")
273                         tts = strsubst(tts, "%i","i")
274                     end
275                     if or(type(o)==[4 6])
276                         tts = strsubst(tts, "%t", "T")
277                         tts = strsubst(tts, "%f", "F")
278                         tts = strsubst(tts, "],", "]]")
279                         tts = strsubst(tts, ",", "")
280                         tts = strsubst(tts, "]]", "],")
281                     end
282                 end
283             catch
284                 tts = tp;
285             end
286             titre2 = titre + tts  ;
287             tree = uiConcatTree(tree, uiCreateNode(titre2));
288         end
289     end
290
291 endfunction
292
293 // -------------------------------------------------------------------
294
295 function v = container_get_ijk_labels(sz)
296     if sum(sz>1) < 2 then
297         // if it's a vector, we display linearized indices
298         v = msprintf("%d\n", (1:prod(sz))')
299     else
300         // Otherwise we display (i,j,.) indices
301         L = list()
302         nd = length(sz);
303         in = "=ndgrid(" + strcat(msprintf("1:%d\n",sz'),",") + ")";
304         out = "[" + strcat(msprintf("L(%d)\n",(1:nd)'),",") + "]";
305         execstr(out + in);
306         v = []
307         for i = 1:nd
308             v = [v, msprintf("%d\n",L(i)(:))];
309         end
310         v = "(" + strcat(v,",","c") + ") ";
311     end
312 endfunction