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