Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / console / src / c / windows / TermLine.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2008 - 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 <windows.h>
18 #include <wincon.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include "TermLine.h"
22 #include "HistoryManager.h"
23 #include "TermConsole.h"
24 #include "localization.h"
25 #include "sci_malloc.h"
26 #include "TermPosition.h"
27 #include "../../../windows_tools/src/c/scilab_windows/console.h"
28 #include "os_string.h"
29 #include "storeCommand.h"
30 /*--------------------------------------------------------------------------*/
31 static int CURRENT_MAX_LINE_SIZE = bsiz;
32 static char *cur_line = NULL;   /* current contents of the line */
33 static const char *currentPrompt = NULL;
34 static int cur_pos = 0;         /* current position of the cursor */
35 static int max_pos = 0;
36 /*--------------------------------------------------------------------------*/
37 /* do backspace on line */
38 static void backSpace(void);
39 static void initializeLineBuffer(void);
40 static void reallocLineBuffer(void);
41 /*--------------------------------------------------------------------------*/
42 static void initializeLineBuffer(void)
43 {
44     int i = 0;
45     if (cur_line)
46     {
47         FREE(cur_line);
48         cur_line = NULL;
49     }
50     cur_line = (char*) MALLOC(sizeof(char) * CURRENT_MAX_LINE_SIZE);
51     if (cur_line)
52     {
53         for (i = 0; i < CURRENT_MAX_LINE_SIZE; i++)
54         {
55             cur_line[i] = '\0';
56         }
57     }
58     else
59     {
60         fprintf(stderr, "Error: Buffer line allocation.\n");
61         exit(1);
62     }
63 }
64 /*--------------------------------------------------------------------------*/
65 static void reallocLineBuffer(void)
66 {
67     if (cur_line)
68     {
69         if ( max_pos > (CURRENT_MAX_LINE_SIZE - 1) )
70         {
71             char *ptrBackup = cur_line;
72             int newCURRENT_MAX_LINE_SIZE = CURRENT_MAX_LINE_SIZE * 2;
73             cur_line = (char*)REALLOC(cur_line, sizeof(char) * (newCURRENT_MAX_LINE_SIZE));
74             if (cur_line == NULL)
75             {
76                 cur_line = ptrBackup;
77             }
78             else
79             {
80                 CURRENT_MAX_LINE_SIZE = newCURRENT_MAX_LINE_SIZE;
81             }
82         }
83     }
84     else
85     {
86         initializeLineBuffer();
87     }
88 }
89 /*--------------------------------------------------------------------------*/
90 void moveBeginningLine(void)
91 {
92     reallocLineBuffer();
93     while (cur_pos > 0)
94     {
95         cur_pos -= 1;
96         backSpace();
97     }
98 }
99 /*--------------------------------------------------------------------------*/
100 void moveEndLine(void)
101 {
102     reallocLineBuffer();
103     while (cur_pos < max_pos)
104     {
105         TerminalPutc (cur_line[cur_pos]);
106         cur_pos += 1;
107     }
108 }
109 /*--------------------------------------------------------------------------*/
110 void moveBackSingleChar(void)
111 {
112     reallocLineBuffer();
113     if (cur_pos > 0)
114     {
115         cur_pos -= 1;
116         backSpace();
117     }
118 }
119 /*--------------------------------------------------------------------------*/
120 void moveForwardSingleChar(void)
121 {
122     reallocLineBuffer();
123     if (cur_pos < max_pos)
124     {
125         TerminalPutc(cur_line[cur_pos]);
126         cur_pos += 1;
127     }
128 }
129 /*--------------------------------------------------------------------------*/
130 void moveBackSingleWord(void)
131 {
132     reallocLineBuffer();
133     while ((cur_pos > 0) && (isspace(cur_line[cur_pos - 1]) ))
134     {
135         cur_pos -= 1;
136         backSpace ();
137     }
138     while ((cur_pos > 0) && ( !isspace(cur_line[cur_pos - 1]) ))
139     {
140         cur_pos -= 1;
141         backSpace ();
142     }
143     refreshLine();
144 }
145 /*--------------------------------------------------------------------------*/
146 void moveForwardSingleWord(void)
147 {
148     reallocLineBuffer();
149     while ( !isspace(cur_line[cur_pos]) && (cur_pos < max_pos) )
150     {
151         TerminalPutc(cur_line[cur_pos]);
152         cur_pos++;
153     }
154     while ( isspace(cur_line[cur_pos]) && (cur_pos < max_pos) )
155     {
156         TerminalPutc(cur_line[cur_pos]);
157         cur_pos++;
158     }
159     refreshLine();
160 }
161 /*--------------------------------------------------------------------------*/
162 void killCurrentPositionToEndLine(void)
163 {
164     int i = 0;
165     reallocLineBuffer();
166     for (i = cur_pos; i < max_pos; i++)
167     {
168         cur_line[i] = '\0';
169     }
170     for (i = cur_pos; i < max_pos; i++)
171     {
172         TerminalPutc(VK_SPACE);
173     }
174     for (i = cur_pos; i < max_pos; i++)
175     {
176         backSpace ();
177     }
178     max_pos = cur_pos;
179 }
180 /*--------------------------------------------------------------------------*/
181 void deletePreviousChar(void)
182 {
183     reallocLineBuffer();
184     if (cur_pos > 0)
185     {
186         int i = 0;
187         cur_pos -= 1;
188         backSpace ();
189         for (i = cur_pos; i < max_pos; i++)
190         {
191             cur_line[i] = cur_line[i + 1];
192         }
193         max_pos -= 1;
194         refreshLine();
195     }
196     else
197     {
198         TerminalBeep();
199     }
200 }
201 /*--------------------------------------------------------------------------*/
202 void deleteCurrentChar(void)
203 {
204     reallocLineBuffer();
205     if (max_pos == 0)
206     {
207         StorePrioritaryCommand("exit");
208     }
209     else
210     {
211         if (cur_pos < max_pos)
212         {
213             int i = 0;
214             for (i = cur_pos; i < max_pos; i++)
215             {
216                 cur_line[i] = cur_line[i + 1];
217             }
218             max_pos -= 1;
219             refreshLine();
220         }
221     }
222 }
223 /*--------------------------------------------------------------------------*/
224 void moveBackHistory(void)
225 {
226     char *newline = NULL;
227
228     reallocLineBuffer();
229
230     cur_line[max_pos + 1] = '\0';
231     if (cur_line[0] == '\0')
232     {
233         resetSearchedTokenInScilabHistory();
234         setSearchedTokenInScilabHistory(NULL);
235     }
236
237     newline = getPreviousLineInScilabHistory();
238
239     if (newline)
240     {
241         clearCurrentLine();
242         copyLine(newline);
243         FREE(newline);
244         newline = NULL;
245     }
246 }
247 /*--------------------------------------------------------------------------*/
248 void moveForwardHistory(void)
249 {
250     char *newline = NULL;
251
252     reallocLineBuffer();
253
254     cur_line[max_pos + 1] = '\0';
255     if (cur_line[0] == '\0')
256     {
257         resetSearchedTokenInScilabHistory();
258         setSearchedTokenInScilabHistory(NULL);
259     }
260
261     newline = getNextLineInScilabHistory();
262
263     if (newline)
264     {
265         clearCurrentLine();
266         copyLine(newline);
267         FREE(newline);
268         newline = NULL;
269     }
270 }
271 /*--------------------------------------------------------------------------*/
272 void redrawLine(void)
273 {
274     int i = 0;
275     char *line = getCurrentLine();
276
277     displayPrompt();
278     for (i = max_pos; i > cur_pos; i--)
279     {
280         backSpace ();
281     }
282     if (line)
283     {
284         copyLine(line);
285         FREE(line);
286         line = NULL;
287     }
288 }
289 /*--------------------------------------------------------------------------*/
290 void copyLine(char *line)
291 {
292     reallocLineBuffer();
293
294     if (line)
295     {
296         TerminalPrintf(line);
297         CharToOem(line, cur_line);
298         cur_pos = max_pos = (int)strlen (cur_line);
299     }
300 }
301 /*--------------------------------------------------------------------------*/
302 void killLastWord(void)
303 {
304     reallocLineBuffer();
305
306     while ((cur_pos > 0) && (cur_line[cur_pos - 1] == VK_SPACE))
307     {
308         cur_pos -= 1;
309         backSpace ();
310     }
311     while ((cur_pos > 0) && (cur_line[cur_pos - 1] != VK_SPACE))
312     {
313         cur_pos -= 1;
314         backSpace ();
315     }
316
317     killCurrentPositionToEndLine();
318 }
319 /*--------------------------------------------------------------------------*/
320 void newLine(void)
321 {
322     reallocLineBuffer();
323
324     cur_line[0] = '\0';
325     cur_pos = 0;
326     max_pos = 0;
327 }
328 /*--------------------------------------------------------------------------*/
329 void refreshLine(void)
330 {
331     int i = 0;
332
333     reallocLineBuffer();
334
335     /* write tail of string */
336     for (i = cur_pos; i < max_pos; i++)
337     {
338         TerminalPutc(cur_line[i]);
339     }
340
341     /* write a space at the end of the line in case we deleted one */
342     TerminalPutc(VK_SPACE);
343
344     /* backup to original position */
345     for (i = max_pos + 1; i > cur_pos; i--)
346     {
347         backSpace ();
348     }
349
350 }
351 /*--------------------------------------------------------------------------*/
352 void clearCurrentLine(void)
353 {
354     int i = 0;
355
356     reallocLineBuffer();
357
358     for (i = 0; i < max_pos; i++)
359     {
360         cur_line[i] = '\0';
361     }
362
363     moveBeginningLine();
364
365     for (i = 0; i < max_pos; i++)
366     {
367         TerminalPutc(VK_SPACE);
368     }
369
370     TerminalPutc('\r');
371     displayPrompt();
372
373     newLine();
374 }
375 /*--------------------------------------------------------------------------*/
376 static void backSpace(void)
377 {
378     int X = 0, Y = 0;
379     reallocLineBuffer();
380
381     TermGetPosition(&X, &Y);
382     if ( (X - 1) < 0 )
383     {
384         X = getXConsoleScreenSize();
385         Y = Y - 1;
386         TermSetPosition(X, Y);
387     }
388     else
389     {
390         TerminalPutc(VK_BACK);
391     }
392 }
393 /*--------------------------------------------------------------------------*/
394 static const char *getCurrentPrompt(void)
395 {
396     return currentPrompt;
397 }
398 /*--------------------------------------------------------------------------*/
399 void setCurrentPrompt(const char *prompt)
400 {
401     currentPrompt = prompt;
402 }
403 /*--------------------------------------------------------------------------*/
404 void displayPrompt(void)
405 {
406     int X = 0, Y = 0;
407
408     /* check position */
409     TermGetPosition(&X, &Y);
410     if (X)
411     {
412         TerminalPrintf("\n");
413     }
414
415     TerminalPrintf(getCurrentPrompt());
416 }
417 /*--------------------------------------------------------------------------*/
418 char *getCurrentLine(void)
419 {
420     char *line = NULL;
421
422     reallocLineBuffer();
423
424     cur_line[max_pos + 1] = '\0';
425     line = os_strdup(cur_line);
426     if (line)
427     {
428         OemToChar(cur_line, line);
429     }
430     return line;
431 }
432 /*--------------------------------------------------------------------------*/
433 char *getLineBeforeCaret(void)
434 {
435     char *line = NULL;
436
437     reallocLineBuffer();
438     line = os_strdup(cur_line);
439     line[cur_pos] = '\0';
440     return line;
441 }
442 /*--------------------------------------------------------------------------*/
443 char *getLineAfterCaret(void)
444 {
445     char *line = NULL;
446
447     reallocLineBuffer();
448     if (cur_pos != max_pos)
449     {
450         line = os_strdup(&cur_line[cur_pos]);
451         line[(max_pos - cur_pos) + 1] = '\0';
452     }
453     else
454     {
455         line = os_strdup("");
456     }
457     return line;
458 }
459 /*--------------------------------------------------------------------------*/
460 void addCharacterCurrentLine(unsigned char ch)
461 {
462     int i = 0;
463
464     reallocLineBuffer();
465
466     for (i = max_pos; i > cur_pos; i--)
467     {
468         cur_line[i] = cur_line[i - 1];
469     }
470
471     cur_line[cur_pos] = ch;
472     cur_pos += 1;
473     max_pos += 1;
474     cur_line[max_pos] = '\0';
475
476     setSearchedTokenInScilabHistory(cur_line);
477
478     if (cur_pos < max_pos)
479     {
480         refreshLine();
481     }
482 }
483 /*--------------------------------------------------------------------------*/
484 BOOL isHistorySearch(void)
485 {
486     return (cur_line[0] == '!');
487 }
488 /*--------------------------------------------------------------------------*/
489 void putLineSearchedHistory(void)
490 {
491     char *line = NULL;
492     char *token = getCurrentLine();
493
494     if (token)
495     {
496         if ( (int)strlen(token) > 1 )
497         {
498             setSearchedTokenInScilabHistory(&token[1]);
499             line = getNextLineInScilabHistory();
500         }
501         FREE(token);
502         token = NULL;
503     }
504
505     clearCurrentLine();
506
507     if (line)
508     {
509         copyLine(line);
510         FREE(line);
511         line = NULL;
512     }
513 }
514 /*--------------------------------------------------------------------------*/
515 void pasteClipBoard(void)
516 {
517     HGLOBAL hGMem = NULL;
518     LPSTR lpMem; /* Ptr on clipboard */
519
520     int typeClipboard = CF_TEXT;
521
522     OpenClipboard(NULL);
523
524     hGMem = GetClipboardData (typeClipboard);
525     if (hGMem)
526     {
527
528         char *CurrentLine = getCurrentLine();
529
530         lpMem = (LPSTR)GlobalLock( hGMem );
531         if (lpMem)
532         {
533             char *newline = (char*)MALLOC(sizeof(char) * (strlen(CurrentLine) + strlen(lpMem) + 1));
534             memset(newline, 0x00, strlen(CurrentLine) + strlen(lpMem) + 1);
535             strncpy(newline, CurrentLine, cur_pos);
536             strcat(newline, lpMem);
537
538             clearCurrentLine();
539             copyLine(newline);
540             FREE(newline);
541         }
542         GlobalUnlock (hGMem);
543         FREE(CurrentLine);
544     }
545
546     CloseClipboard ();
547 }
548 /*--------------------------------------------------------------------------*/
549 void finalizeLineBuffer(void)
550 {
551     if (cur_line)
552     {
553         FREE(cur_line);
554         cur_line = NULL;
555     }
556 }