Bug 12909 fixed: Completion on (mt)list led to a crash
[scilab.git] / scilab / modules / completion / src / c / getfieldsdictionary.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010-2011 - Calixte DENIZET
4 * Copyright (C) 2013 - Scilab Enterprises - Calixte DENIZET
5 *
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11 *
12 */
13 #include <string.h> /* strcmp */
14 #include <stdlib.h> /* qsort */
15 #include "Scierror.h"
16 #include "api_scilab.h"
17 #include "MALLOC.h"
18 #include "getfieldsdictionary.h"
19 #include "getPartLine.h"
20 #include "completion.h"
21 #include "freeArrayOfString.h"
22
23 #include "getfields.h"
24
25 static int isInitialized = 0;
26
27 /*--------------------------------------------------------------------------*/
28 static int cmpNames(const void *a, const void *b)
29 {
30     return strcmp(*(const char **)a, *(const char **)b);
31 }
32 /*--------------------------------------------------------------------------*/
33 char **getfieldsdictionary(char *lineBeforeCaret, char *pattern, int *size)
34 {
35     SciErr sciErr;
36     int *piAddr = NULL;
37     int *piLen = NULL;
38     int piType = 0;
39     int rows = 0;
40     int cols = 0;
41     int rc = 0;
42     int i;
43     int last = 0;
44     char **pstData = NULL;
45     char **fields = NULL;
46     char **_fields = NULL;
47     char *var = NULL;
48     char *lineBeforePoint = NULL;
49     int pos = (int)(strlen(lineBeforeCaret) - strlen(pattern) - 1);
50     char ** fieldPath = NULL;
51     int fieldPathLen = 0;
52     int fieldCompt = 0;
53     int fieldsSize = 0;
54
55     if (!isInitialized)
56     {
57         initializeFieldsGetter(1);
58         isInitialized = 1;
59     }
60
61     if (pos <= 0 || lineBeforeCaret[pos] != '.')
62     {
63         return NULL;
64     }
65
66     lineBeforePoint = (char*)MALLOC(sizeof(char) * (pos + 1));
67     if (lineBeforePoint == NULL)
68     {
69         return NULL;
70     }
71     memcpy(lineBeforePoint, lineBeforeCaret, pos);
72     lineBeforePoint[pos] = '\0';
73     fieldPath = getFieldPath(lineBeforePoint, &fieldPathLen);
74     if (fieldPathLen == 0)
75     {
76         return NULL;
77     }
78
79     FREE(lineBeforePoint);
80     lineBeforePoint = NULL;
81
82     sciErr = getNamedVarType(pvApiCtx, fieldPath[0], &piType);
83     if (sciErr.iErr && piType != sci_mlist && piType != sci_tlist && piType != sci_handles)
84     {
85         freeArrayOfString(fieldPath, fieldPathLen);
86         return NULL;
87     }
88
89     if (piType == sci_mlist || piType == sci_tlist || piType == sci_handles)
90     {
91         getVarAddressFromName(pvApiCtx, fieldPath[0], &piAddr);
92         if (sciErr.iErr)
93         {
94             freeArrayOfString(fieldPath, fieldPathLen);
95             return NULL;
96         }
97
98         fields = (char**)getFields(piAddr, fieldPath, fieldPathLen, &fieldsSize);
99         freeArrayOfString(fieldPath, fieldPathLen);
100         if (!fields)
101         {
102             return NULL;
103         }
104
105         _fields = (char**)MALLOC(sizeof(char *) * (fieldsSize + 1));
106         last = 0;
107
108         for (i = 0; i < fieldsSize ; i++)
109         {
110             if (strstr(fields[i], pattern) == fields[i])
111             {
112                 _fields[last++] = fields[i];
113             }
114             else
115             {
116                 FREE(fields[i]);
117                 fields[i] = NULL;
118             }
119         }
120
121         FREE(fields);
122
123         *size = last;
124         qsort(_fields, *size, sizeof(char*), cmpNames);
125         _fields[last] = NULL; // don't forget, it SWIG is using first NULL item to guess array size
126
127         return _fields;
128     }
129     else
130     {
131         pstData = completionOnHandleGraphicsProperties(pattern, size);
132     }
133
134     return pstData;
135 }
136 /*--------------------------------------------------------------------------*/