completion: fix tests
[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     // as we try to "find" within "string", "find" should be smaller than or equal to "string"
60     if (strlen(pointerOnFindCopy) > strlen(string))
61     {
62         pointerOnFindCopy[strlen(string)] = '\0';
63     }
64     movingPointerOnFindCopy = strrchr(pointerOnFindCopy, toupper(lastchar));
65
66     //Tips : no infinite loop there, tmpfind string length is always reduced at each iteration
67     while ( movingPointerOnFindCopy )
68     {
69         //find the last occurence of last char of string in tmpfind
70         movingPointerOnFindCopy = strrchr(pointerOnFindCopy, toupper(lastchar));
71         if (movingPointerOnFindCopy == NULL)
72         {
73             break;
74         }
75         // Cut tmpfind at this position
76         movingPointerOnFindCopy[0] = '\0';
77         //Check if the cutted tmpfind match with the suffix of string that has adequat length
78         pointerOnString = (char*)(string + stringLength - 1 - strlen(pointerOnFindCopy));
79         if ( !strnicmp(pointerOnFindCopy, pointerOnString, strlen(pointerOnFindCopy)) )
80         {
81             FREE(pointerOnFindCopy);
82             pointerOnFindCopy = NULL;
83             return (int)(pointerOnString - string);
84         }
85
86     }
87     //if no return, no position is correct, return last char of string.
88     FREE(pointerOnFindCopy);
89     pointerOnFindCopy = NULL;
90     return (int)stringLength;
91 }
92 /*--------------------------------------------------------------------------*/
93 char *completeLine(char *currentline, char *stringToAdd, char *filePattern,
94                    char *defaultPattern, BOOL stringToAddIsPath, char *postCaretLine)
95 {
96     char *new_line = NULL;
97     int lengthNewLine = 0;
98
99     char *stringToAddAtTheEnd = NULL;
100     int lenstringToAddAtTheEnd = 0;
101
102     char *res = NULL;
103
104     int lencurrentline = 0;
105
106     int iposInsert = 0;
107
108     if (currentline == NULL)
109     {
110         return  os_strdup("");
111     }
112     lencurrentline = (int)strlen(currentline);
113
114     if (postCaretLine == NULL)
115     {
116         stringToAddAtTheEnd = os_strdup("");
117         lenstringToAddAtTheEnd = (int)strlen(stringToAddAtTheEnd);
118     }
119     else
120     {
121         stringToAddAtTheEnd = os_strdup(postCaretLine);
122         lenstringToAddAtTheEnd = (int)strlen(stringToAddAtTheEnd);
123     }
124
125     if ( (stringToAdd == NULL)  || (strcmp(stringToAdd, "") == 0) )
126     {
127         lengthNewLine = lencurrentline + lenstringToAddAtTheEnd;
128         new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
129         if (new_line)
130         {
131             strcpy(new_line, currentline);
132             strcat(new_line, stringToAddAtTheEnd);
133         }
134
135         FREE(stringToAddAtTheEnd);
136         stringToAddAtTheEnd = NULL;
137
138         return new_line;
139     }
140
141     if (stringToAddIsPath == FALSE)
142     {
143         char *filePatternBuf = NULL;
144         BOOL bfilePatternBuf = FALSE;
145
146         if (filePattern != NULL)
147         {
148             filePatternBuf = filePattern;
149         }
150         else
151         {
152             filePatternBuf = getFilePartLevel(currentline);
153             bfilePatternBuf = TRUE;
154         }
155
156         if (filePatternBuf)
157         {
158             char* drv = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
159             char* dir = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
160             char* name = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
161             char* ext = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
162
163             splitpath(filePatternBuf, TRUE, drv, dir, name, ext);
164
165             if (bfilePatternBuf)
166             {
167                 FREE(filePatternBuf);
168                 filePatternBuf = NULL;
169             }
170
171             if ( strcmp(drv, "") || strcmp(dir, "") )
172             {
173                 /* bug 4365 */
174                 /*cd SCI/modules/arnoldi/nonreg_tes */
175
176                 FREE(drv);
177                 drv = NULL;
178                 FREE(dir);
179                 dir = NULL;
180                 FREE(name);
181                 name = NULL;
182                 FREE(ext);
183                 ext = NULL;
184
185                 lengthNewLine = lencurrentline + lenstringToAddAtTheEnd;
186                 new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
187                 if (new_line)
188                 {
189                     strcpy(new_line, currentline);
190                     strcat(new_line, stringToAddAtTheEnd);
191                 }
192
193                 FREE(stringToAddAtTheEnd);
194                 stringToAddAtTheEnd = NULL;
195
196                 return new_line;
197             }
198
199             FREE(drv);
200             drv = NULL;
201             FREE(dir);
202             dir = NULL;
203             FREE(name);
204             name = NULL;
205             FREE(ext);
206             ext = NULL;
207         }
208     }
209
210     // Does the end of line (currentLine) matches the beginning of completed word (stringToAdd) ?
211     iposInsert = findMatchingPrefixSuffix(currentline, stringToAdd, stringToAddIsPath);
212     res = stristr(stringToAdd, &currentline[iposInsert]);
213
214     if (res == NULL)
215     {
216         // No, find the last occurence of completed word word in line
217         char* foundCompletedWordPtr = NULL;
218         char* nextFoundCompletedWordPtr = stristr(currentline, stringToAdd);
219         while (nextFoundCompletedWordPtr)
220         {
221             foundCompletedWordPtr = nextFoundCompletedWordPtr;
222             nextFoundCompletedWordPtr =
223                 stristr(foundCompletedWordPtr + strlen(foundCompletedWordPtr), stringToAdd);
224         }
225
226         if (foundCompletedWordPtr)
227         {
228             iposInsert = (int) (foundCompletedWordPtr - currentline);
229         }
230     }
231
232     // if it is a path, we add at the end
233     if ((currentline[lencurrentline - 1] == '/') || (currentline[lencurrentline - 1] == '\\'))
234     {
235         iposInsert = lencurrentline;
236     }
237
238     lengthNewLine = (int)(strlen(currentline) + strlen(stringToAdd) + lenstringToAddAtTheEnd);
239     new_line = (char*)MALLOC(sizeof(char) * (lengthNewLine + 1));
240     if (new_line)
241     {
242         strcpy(new_line, currentline);
243         new_line[iposInsert] = 0;
244
245         strcat(new_line, stringToAdd);
246         strcat(new_line, stringToAddAtTheEnd);
247     }
248
249     FREE(stringToAddAtTheEnd);
250     stringToAddAtTheEnd = NULL;
251
252     return new_line;
253 }
254 /*--------------------------------------------------------------------------*/