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