0f5b87febf39e17da8712185b51c199268c1c116
[scilab.git] / scilab / modules / console / src / c / windows / TermCompletion.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2008-2010 - DIGITEO - Allan CORNET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 /*--------------------------------------------------------------------------*/
17 #include <string.h>
18 #include <stdlib.h>
19 #include <sys/stat.h>
20 #include "TermCompletion.h"
21 #include "sci_malloc.h"
22 #include "freeArrayOfString.h"
23 #include "localization.h"
24 #include "TermLine.h"
25 #include "TermConsole.h"
26 #include "getPartLine.h"
27 #include "getCommonPart.h"
28 #include "completion.h"
29 #include "scilines.h"
30 #include "os_string.h"
31 #include "completeLine.h"
32 /*--------------------------------------------------------------------------*/
33 #define S_ISDIR(x) (x & _S_IFDIR)
34 /*--------------------------------------------------------------------------*/
35 static void displayCompletionDictionary(char **dictionary, int sizedictionary, char *namedictionary);
36 static char **concatenateStrings(int *sizearrayofstring, char *string1,
37                                  char *string2, char *string3,
38                                  char *string4, char *string5);
39 static void TermCompletionOnFiles(char **dictionaryFiles, int sizedictionaryFiles,
40                                   char *lineBeforeCaret, char *lineAfterCaret, char *filePattern, char *defaultPattern);
41 static void separateFilesDirectories(char** dictionnary, int size, char*** files, int* sizeFiles, char*** directories, int* sizeDirectories);
42 static void TermCompletionOnAll(char *lineBeforeCaret, char *lineAfterCaret, char *defaultPattern);
43 /*--------------------------------------------------------------------------*/
44 static void TermCompletionOnFiles(char **dictionaryFiles, int sizedictionaryFiles,
45                                   char *lineBeforeCaret, char *lineAfterCaret, char *filePattern, char *defaultPattern)
46 {
47     if (dictionaryFiles)
48     {
49         if (sizedictionaryFiles == 1)
50         {
51             char *newline = completeLine(lineBeforeCaret, dictionaryFiles[0], filePattern, defaultPattern, TRUE, lineAfterCaret);
52             if (newline)
53             {
54                 clearCurrentLine();
55                 copyLine(newline);
56                 FREE(newline);
57                 return;
58             }
59         }
60         else
61         {
62             char *common = getCommonPart(dictionaryFiles, sizedictionaryFiles);
63
64             char** files;
65             int sizeFiles;
66             char** directories;
67             int sizeDirectories;
68             separateFilesDirectories(dictionaryFiles, sizedictionaryFiles, &files, &sizeFiles, &directories, &sizeDirectories);
69
70             //displayCompletionDictionary(dictionaryFiles, sizedictionaryFiles, gettext("File or Directory"));
71             displayCompletionDictionary(files, sizeFiles, gettext("File"));
72             displayCompletionDictionary(directories, sizeDirectories, gettext("Directory"));
73             freeArrayOfString(files, sizeFiles);
74             freeArrayOfString(directories, sizeDirectories);
75
76             displayPrompt();
77             newLine();
78
79             if (defaultPattern[0] == 0)
80             {
81                 int lennewline = (int)strlen(lineBeforeCaret) + (int)strlen(lineAfterCaret);
82                 char *newline = (char*)MALLOC(sizeof(char) * (lennewline + 1));
83
84                 clearCurrentLine();
85                 if (newline)
86                 {
87                     strcpy(newline, lineBeforeCaret);
88                     strcat(newline, lineAfterCaret);
89                     copyLine(newline);
90                     FREE(newline);
91                     newline = NULL;
92                 }
93             }
94             else if (common)
95             {
96                 char *newline = completeLine(lineBeforeCaret, common, filePattern, defaultPattern, TRUE, lineAfterCaret);
97                 if (newline)
98                 {
99                     clearCurrentLine();
100                     copyLine(newline);
101                     FREE(common);
102                     FREE(newline);
103                     return;
104                 }
105                 else
106                 {
107                     int lennewline = (int)strlen(lineBeforeCaret) + (int)strlen(lineAfterCaret);
108                     newline = (char*)MALLOC(sizeof(char) * (lennewline + 1));
109
110                     clearCurrentLine();
111                     if (newline)
112                     {
113                         strcpy(newline, lineBeforeCaret);
114                         strcat(newline, lineAfterCaret);
115                         copyLine(newline);
116                         FREE(newline);
117                         newline = NULL;
118                     }
119                 }
120                 FREE(common);
121                 common = NULL;
122             }
123         }
124     }
125 }
126 /*--------------------------------------------------------------------------*/
127 static void separateFilesDirectories(char** dictionary, int size, char*** files, int* sizeFiles, char*** directories, int* sizeDirectories)
128 {
129     int i;
130     *files = NULL;
131     *sizeFiles = 0;
132     *directories = NULL;
133     *sizeDirectories = 0;
134     for (i = 0; i < size; ++i)
135     {
136         // Check that the item is a file or a directory
137         char* dict = dictionary[i];
138         int isCopy = 0;
139         int len = (int) strlen(dict);
140         if (len && dict[len - 1] == '\\')
141         {
142             isCopy = 1;
143             dict = os_strdup(dict);
144             dict[len - 1] = '\0';
145         }
146
147         struct stat statbuf;
148         if (stat(dict, &statbuf) == -1)
149         {
150             if (isCopy)
151             {
152                 free(dict);
153             }
154             return;
155         }
156
157         if (S_ISDIR(statbuf.st_mode))
158         {
159             (*sizeDirectories)++;
160             *directories = (char **) REALLOC(*directories, sizeof(char *) * (*sizeDirectories));
161             (*directories)[*sizeDirectories - 1] = strdup(dictionary[i]);
162         }
163         else
164         {
165             (*sizeFiles)++;
166             *files = (char **) REALLOC(*files, sizeof(char *) * (*sizeFiles));
167             (*files)[*sizeFiles - 1] = strdup(dictionary[i]);
168         }
169
170         if (isCopy)
171         {
172             free(dict);
173         }
174
175     }
176 }
177 /*--------------------------------------------------------------------------*/
178 static void TermCompletionOnAll(char *lineBeforeCaret, char *lineAfterCaret, char *defaultPattern)
179 {
180     if (defaultPattern)
181     {
182         int numberWordFound = 0;
183         char **completionDictionaryFunctions = NULL;
184         int sizecompletionDictionaryFunctions = 0;
185
186         char **completionDictionaryCommandWords = NULL;
187         int sizecompletionDictionaryCommandWords = 0;
188
189         char **completionDictionaryMacros = NULL;
190         int sizecompletionDictionaryMacros = 0;
191
192         char **completionDictionaryVariables = NULL;
193         int sizecompletionDictionaryVariables = 0;
194
195         char **completionDictionaryHandleGraphicsProperties = NULL;
196         int sizecompletionDictionaryHandleGraphicsProperties = 0;
197
198         char **completionDictionaryFields = NULL;
199         int sizecompletionDictionaryFields = 0;
200
201         completionDictionaryFields = completionOnFields(lineBeforeCaret, defaultPattern, &sizecompletionDictionaryFields);
202
203         if ((completionDictionaryFields == NULL) && strcmp(defaultPattern, ""))
204         {
205             completionDictionaryFunctions = completionOnFunctions(defaultPattern, &sizecompletionDictionaryFunctions);
206             completionDictionaryCommandWords = completionOnCommandWords(defaultPattern, &sizecompletionDictionaryCommandWords);
207             completionDictionaryMacros = completionOnMacros(defaultPattern, &sizecompletionDictionaryMacros);
208             completionDictionaryVariables = completionOnVariablesWithoutMacros(defaultPattern, &sizecompletionDictionaryVariables);
209             completionDictionaryHandleGraphicsProperties = completionOnHandleGraphicsProperties(defaultPattern, &sizecompletionDictionaryHandleGraphicsProperties);
210         }
211         numberWordFound = sizecompletionDictionaryFunctions + sizecompletionDictionaryCommandWords +
212                           sizecompletionDictionaryMacros + sizecompletionDictionaryVariables +
213                           sizecompletionDictionaryHandleGraphicsProperties + sizecompletionDictionaryFields;
214
215         if (numberWordFound > 0)
216         {
217             if (numberWordFound == 1)
218             {
219                 char **completionDictionary = NULL;
220                 char *new_line = NULL;
221
222                 if (completionDictionaryFields)
223                 {
224                     completionDictionary = completionDictionaryFields;
225                 }
226                 if (completionDictionaryFunctions)
227                 {
228                     completionDictionary = completionDictionaryFunctions;
229                 }
230                 if (completionDictionaryCommandWords)
231                 {
232                     completionDictionary = completionDictionaryCommandWords;
233                 }
234                 if (completionDictionaryMacros)
235                 {
236                     completionDictionary = completionDictionaryMacros;
237                 }
238                 if (completionDictionaryVariables)
239                 {
240                     completionDictionary = completionDictionaryVariables;
241                 }
242                 if (completionDictionaryHandleGraphicsProperties)
243                 {
244                     completionDictionary = completionDictionaryHandleGraphicsProperties;
245                 }
246
247                 new_line = completeLine(lineBeforeCaret, completionDictionary[0], NULL, defaultPattern, FALSE, lineAfterCaret);
248                 if (new_line)
249                 {
250                     clearCurrentLine();
251                     copyLine(new_line);
252                     FREE(new_line);
253                 }
254             }
255             else
256             {
257                 char *commonAll = NULL;
258                 if (completionDictionaryFields)
259                 {
260                     commonAll = getCommonPart(completionDictionaryFields, sizecompletionDictionaryFields);
261                     displayCompletionDictionary(completionDictionaryFields, sizecompletionDictionaryFields, (char *)_("Scilab Fields"));
262                     freeArrayOfString(completionDictionaryFields, sizecompletionDictionaryFields);
263                 }
264                 else
265                 {
266                     char *commonFunctions = getCommonPart(completionDictionaryFunctions, sizecompletionDictionaryFunctions);
267                     char *commonCommandWords = getCommonPart(completionDictionaryCommandWords, sizecompletionDictionaryCommandWords);
268                     char *commonMacros = getCommonPart(completionDictionaryMacros, sizecompletionDictionaryMacros);
269                     char *commonVariables = getCommonPart(completionDictionaryVariables, sizecompletionDictionaryVariables);
270                     char *commonHandleGraphicsProperties = getCommonPart(completionDictionaryHandleGraphicsProperties, sizecompletionDictionaryHandleGraphicsProperties);
271
272                     int sizecommonsDictionary = 0;
273                     char **commonsDictionary = concatenateStrings(&sizecommonsDictionary, commonFunctions,
274                                                commonMacros, commonCommandWords, commonVariables, commonHandleGraphicsProperties);
275
276                     if (sizecommonsDictionary > 0)
277                     {
278                         if (sizecommonsDictionary == 1)
279                         {
280                             commonAll = os_strdup(commonsDictionary[0]);
281                         }
282                         else
283                         {
284                             commonAll = getCommonPart(commonsDictionary, sizecommonsDictionary);
285                         }
286                         freeArrayOfString(commonsDictionary, sizecommonsDictionary);
287                     }
288
289                     displayCompletionDictionary(completionDictionaryFunctions, sizecompletionDictionaryFunctions, (char *)_("Scilab Function"));
290                     displayCompletionDictionary(completionDictionaryCommandWords, sizecompletionDictionaryCommandWords, (char *)_("Scilab Command"));
291                     displayCompletionDictionary(completionDictionaryMacros, sizecompletionDictionaryMacros, (char *)_("Scilab Macro"));
292                     displayCompletionDictionary(completionDictionaryVariables, sizecompletionDictionaryVariables, (char *)_("Scilab Variable"));
293                     displayCompletionDictionary(completionDictionaryHandleGraphicsProperties, sizecompletionDictionaryHandleGraphicsProperties, (char *)_("Graphics handle field"));
294                     freeArrayOfString(completionDictionaryFunctions, sizecompletionDictionaryFunctions);
295                     freeArrayOfString(completionDictionaryCommandWords, sizecompletionDictionaryCommandWords);
296                     freeArrayOfString(completionDictionaryMacros, sizecompletionDictionaryMacros);
297                     freeArrayOfString(completionDictionaryVariables, sizecompletionDictionaryVariables);
298                     freeArrayOfString(completionDictionaryHandleGraphicsProperties, sizecompletionDictionaryHandleGraphicsProperties);
299                 }
300
301                 displayPrompt();
302                 newLine();
303
304                 if (commonAll)
305                 {
306                     char *newline = NULL;
307
308                     newline = completeLine(lineBeforeCaret, commonAll, NULL, defaultPattern, FALSE, lineAfterCaret);
309
310                     if (newline)
311                     {
312                         clearCurrentLine();
313                         copyLine(newline);
314                         FREE(newline);
315                     }
316                     FREE(commonAll);
317                     commonAll = NULL;
318                 }
319             }
320         }
321     }
322 }
323 /*--------------------------------------------------------------------------*/
324 void TermCompletion(void)
325 {
326     char *LineBeforeCaret = getLineBeforeCaret();
327     char *LineAfterCaret = getLineAfterCaret();
328     char *fileSearchedPattern = getFilePartLevel(LineBeforeCaret);
329     char *SearchedPattern = getPartLevel(LineBeforeCaret);
330
331
332     char **completionDictionaryFiles = NULL;
333     int sizecompletionDictionaryFiles = 0;
334
335     completionDictionaryFiles = completionOnFiles(fileSearchedPattern, &sizecompletionDictionaryFiles);
336     if (completionDictionaryFiles)
337     {
338         TermCompletionOnFiles(completionDictionaryFiles, sizecompletionDictionaryFiles,
339                               LineBeforeCaret, LineAfterCaret, fileSearchedPattern, SearchedPattern);
340
341         freeArrayOfString(completionDictionaryFiles, sizecompletionDictionaryFiles);
342     }
343     else
344     {
345         TermCompletionOnAll(LineBeforeCaret, LineAfterCaret, SearchedPattern);
346     }
347
348     if (LineBeforeCaret)
349     {
350         FREE(LineBeforeCaret);
351         LineBeforeCaret = NULL;
352     }
353     if (LineAfterCaret)
354     {
355         FREE(LineAfterCaret);
356         LineAfterCaret = NULL;
357     }
358     if (fileSearchedPattern)
359     {
360         FREE(fileSearchedPattern);
361         fileSearchedPattern = NULL;
362     }
363     if (SearchedPattern)
364     {
365         FREE(SearchedPattern);
366         SearchedPattern = NULL;
367     }
368 }
369 /*--------------------------------------------------------------------------*/
370 static void displayCompletionDictionary(char **dictionary, int sizedictionary, char *namedictionary)
371 {
372     if (dictionary)
373     {
374         int i = 0;
375         int lenCurrentLine = 0;
376
377         TerminalPrintf("\n");
378         TerminalPrintf(namedictionary);
379         TerminalPrintf(":");
380         TerminalPrintf("\n");
381
382         for (i = 0; i < sizedictionary; i++)
383         {
384             int newlenLine = lenCurrentLine + (int)strlen(dictionary[i]) + (int)strlen(" ");
385             if (newlenLine >= (getConsoleWidth() - 10))
386             {
387                 TerminalPrintf("\n");
388                 lenCurrentLine = 0;
389             }
390             else
391             {
392                 lenCurrentLine = newlenLine;
393             }
394
395             TerminalPrintf(dictionary[i]);
396             TerminalPrintf(" ");
397         }
398         TerminalPrintf("\n");
399     }
400 }
401 /*--------------------------------------------------------------------------*/
402 static char **concatenateStrings(int *sizearrayofstring, char *string1,
403                                  char *string2, char *string3,
404                                  char *string4, char *string5)
405 {
406     int newsize = 0;
407     char **arrayOfString = NULL;
408     *sizearrayofstring = 0;
409
410     if (string1)
411     {
412         newsize++;
413     }
414     if (string2)
415     {
416         newsize++;
417     }
418     if (string3)
419     {
420         newsize++;
421     }
422     if (string4)
423     {
424         newsize++;
425     }
426     if (string5)
427     {
428         newsize++;
429     }
430
431     if (newsize > 0)
432     {
433         arrayOfString = (char**)MALLOC(sizeof(char*) * (newsize));
434         if (arrayOfString)
435         {
436             int i = 0;
437             if (string1)
438             {
439                 arrayOfString[i] = string1;
440                 i++;
441             }
442             if (string2)
443             {
444                 arrayOfString[i] = string2;
445                 i++;
446             }
447             if (string3)
448             {
449                 arrayOfString[i] = string3;
450                 i++;
451             }
452             if (string4)
453             {
454                 arrayOfString[i] = string4;
455                 i++;
456             }
457             if (string5)
458             {
459                 arrayOfString[i] = string5;
460                 i++;
461             }
462             *sizearrayofstring = i;
463         }
464         else
465         {
466             *sizearrayofstring = 0;
467         }
468     }
469     return arrayOfString;
470 }
471 /*--------------------------------------------------------------------------*/