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