b0d16e95f639d2f47f93c381504f01ffbdf48419
[scilab.git] / scilab / modules / completion / src / c / completeLine.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009-2010 - DIGITEO - Allan CORNET
4 * Copyright (C) 2010 - DIGITEO - Vincent LEJEUNE
5 * Copyright (C) 2011 - DIGITEO - Allan CORNET
6 *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15 *
16 */
17
18 /*--------------------------------------------------------------------------*/
19 #include <string.h>
20 #include <ctype.h>
21 #include "completeLine.h"
22 #include "sci_malloc.h"
23 #include "os_string.h"
24 #include "getPartLine.h"
25 #include "splitpath.h"
26 #include "PATH_MAX.h"
27 #include "stristr.h"
28
29 /*--------------------------------------------------------------------------*/
30 /*!  Get the position of the longest suffix of string that match with a prefix of find
31 *  @param[in] string  A string that has a suffix that match a prefix of find ; Assumed to be non null because of the first guard in completeLine
32 *  @param[in] find A string that has a prefix that match with a suffix of string
33 *  @return Position in string where suffix of string and prefix of find does match
34 *
35 */
36 static int findMatchingPrefixSuffix(const char* string, const char* find, BOOL stringToAddIsPath)
37 {
38     char* pointerOnString = NULL;
39     char* pointerOnFindCopy = NULL;
40     char* movingPointerOnFindCopy = NULL;
41     char lastchar;
42     size_t stringLength = 0;
43
44     //get a working copy of find
45     pointerOnFindCopy = os_strdup(find);
46     //last character of string
47     lastchar = *(string + strlen(string) - 1);
48     stringLength = strlen(string);
49
50     // Convert to upper-case
51     {
52         char* str;
53         for (str = pointerOnFindCopy; *str != '\0'; str++)
54         {
55             *str = toupper(*str);
56         }
57     }
58
59     //Tips : no infinite loop there, tmpfind string length is always reduced at each iteration
60     movingPointerOnFindCopy = strrchr(pointerOnFindCopy, toupper(lastchar));
61
62     while ( movingPointerOnFindCopy )
63     {
64         //find the last occurence of last char of string in tmpfind
65         movingPointerOnFindCopy = strrchr(pointerOnFindCopy, toupper(lastchar));
66         if (movingPointerOnFindCopy == NULL)
67         {
68             break;
69         }
70         // Cut tmpfind at this position
71         movingPointerOnFindCopy[0] = '\0';
72         //Check if the cutted tmpfind match with the suffix of string that has adequat length
73         pointerOnString = (char*)(string + stringLength - 1 - strlen(pointerOnFindCopy));
74         if ( !strnicmp(pointerOnFindCopy, pointerOnString, strlen(pointerOnFindCopy)) )
75         {
76             FREE(pointerOnFindCopy);
77             pointerOnFindCopy = NULL;
78             return (int)(pointerOnString - string);
79         }
80
81     }
82     //if no return, no position is correct, return last char of string.
83     FREE(pointerOnFindCopy);
84     pointerOnFindCopy = NULL;
85     return (int)stringLength;
86 }
87 /*--------------------------------------------------------------------------*/
88 char *completeLine(char *currentline, char *stringToAdd, char *filePattern,
89                    char *defaultPattern, BOOL stringToAddIsPath, char *postCaretLine)
90 {
91     char *new_line = NULL;
92     int lengthNewLine = 0;
93
94     char *stringToAddAtTheEnd = NULL;
95     int lenstringToAddAtTheEnd = 0;
96
97     char *res = NULL;
98
99     int lencurrentline = 0;
100
101     int iposInsert = 0;
102
103     if (currentline == NULL)
104     {
105         return  os_strdup("");
106     }
107     lencurrentline = (int)strlen(currentline);
108
109     if (postCaretLine == NULL)
110     {
111         stringToAddAtTheEnd = os_strdup("");
112         lenstringToAddAtTheEnd = (int)strlen(stringToAddAtTheEnd);
113     }
114     else
115     {
116         stringToAddAtTheEnd = os_strdup(postCaretLine);
117         lenstringToAddAtTheEnd = (int)strlen(stringToAddAtTheEnd);
118     }
119
120     if ( (stringToAdd == NULL)  || (strcmp(stringToAdd, "") == 0) )
121     {
122         lengthNewLine = lencurrentline + lenstringToAddAtTheEnd;
123         new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
124         if (new_line)
125         {
126             strcpy(new_line, currentline);
127             strcat(new_line, stringToAddAtTheEnd);
128         }
129
130         if (stringToAddAtTheEnd)
131         {
132             FREE(stringToAddAtTheEnd);
133             stringToAddAtTheEnd = NULL;
134         }
135
136         return new_line;
137     }
138
139     if (stringToAddIsPath == FALSE)
140     {
141         char *filePatternBuf = NULL;
142         BOOL bfilePatternBuf = FALSE;
143
144         if (filePattern != NULL)
145         {
146             filePatternBuf = filePattern;
147         }
148         else
149         {
150             filePatternBuf = getFilePartLevel(currentline);
151             bfilePatternBuf = TRUE;
152         }
153
154         if (filePatternBuf)
155         {
156             char* drv = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
157             char* dir = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
158             char* name = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
159             char* ext = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
160
161             splitpath(filePatternBuf, TRUE, drv, dir, name, ext);
162
163             if (bfilePatternBuf)
164             {
165                 FREE(filePatternBuf);
166                 filePatternBuf = NULL;
167             }
168
169             if ( strcmp(drv, "") || strcmp(dir, "") )
170             {
171                 /* bug 4365 */
172                 /*cd SCI/modules/arnoldi/nonreg_tes */
173
174                 if (drv)
175                 {
176                     FREE(drv);
177                     drv = NULL;
178                 }
179                 if (dir)
180                 {
181                     FREE(dir);
182                     dir = NULL;
183                 }
184                 if (name)
185                 {
186                     FREE(name);
187                     name = NULL;
188                 }
189                 if (ext)
190                 {
191                     FREE(ext);
192                     ext = NULL;
193                 }
194
195                 lengthNewLine = lencurrentline + lenstringToAddAtTheEnd;
196                 new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
197                 if (new_line)
198                 {
199                     strcpy(new_line, currentline);
200                     strcat(new_line, stringToAddAtTheEnd);
201                 }
202
203                 if (stringToAddAtTheEnd)
204                 {
205                     FREE(stringToAddAtTheEnd);
206                     stringToAddAtTheEnd = NULL;
207                 }
208
209                 return new_line;
210             }
211
212             if (drv)
213             {
214                 FREE(drv);
215                 drv = NULL;
216             }
217             if (dir)
218             {
219                 FREE(dir);
220                 dir = NULL;
221             }
222             if (name)
223             {
224                 FREE(name);
225                 name = NULL;
226             }
227             if (ext)
228             {
229                 FREE(ext);
230                 ext = NULL;
231             }
232         }
233     }
234
235     // Does the end of line (currentLine) matches the beginning of completed word (stringToAdd) ?
236     iposInsert = findMatchingPrefixSuffix(currentline, stringToAdd, stringToAddIsPath);
237     res = stristr(stringToAdd, &currentline[iposInsert]);
238
239     if (res == NULL)
240     {
241         // No, find the last occurence of completed word word in line
242         char* foundCompletedWordPtr = NULL;
243         char* nextFoundCompletedWordPtr = stristr(currentline, stringToAdd);
244         while (nextFoundCompletedWordPtr)
245         {
246             foundCompletedWordPtr = nextFoundCompletedWordPtr;
247             nextFoundCompletedWordPtr =
248                 stristr(foundCompletedWordPtr + strlen(foundCompletedWordPtr), stringToAdd);
249         }
250
251         if (foundCompletedWordPtr)
252         {
253             iposInsert = (int) (foundCompletedWordPtr - currentline);
254         }
255     }
256
257     // if it is a path, we add at the end
258     if ((currentline[lencurrentline - 1] == '/') || (currentline[lencurrentline - 1] == '\\'))
259     {
260         iposInsert = lencurrentline;
261     }
262
263     lengthNewLine = (int)(strlen(currentline) + strlen(stringToAdd) + lenstringToAddAtTheEnd);
264     new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
265     if (new_line)
266     {
267         strcpy(new_line, currentline);
268         new_line[iposInsert] = 0;
269
270         strcat(new_line, stringToAdd);
271         strcat(new_line, stringToAddAtTheEnd);
272     }
273
274     if (stringToAddAtTheEnd)
275     {
276         FREE(stringToAddAtTheEnd);
277         stringToAddAtTheEnd = NULL;
278     }
279
280     return new_line;
281 }
282 /*--------------------------------------------------------------------------*/