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