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