e6b1537b75c445e0ca2cc63d9511361d947b68fc
[scilab.git] / scilab / modules / history_manager / src / cpp / HistoryManager.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2007-2008 - INRIA - Allan CORNET
4 * Copyright (C) 2010 - DIGITEO - Vincent COUVERT
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 <iostream>
20 #include "HistoryManager.hxx"
21 /*------------------------------------------------------------------------*/
22 extern "C"
23 {
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include "sciprint.h"
28 #include "sci_home.h"
29 #include "InitializeHistoryManager.h"
30 #include "TerminateHistoryManager.h"
31 #include "freeArrayOfString.h"
32 #include "os_string.h"
33 #include "CommandHistory_Wrap.h"
34 #include "localization.h"
35 #include "getCommentDateSession.h"
36 #include "sci_malloc.h"
37 #include "HistoryManager.h"
38 };
39 /*------------------------------------------------------------------------*/
40 #define MAXBUF  1024
41 /*------------------------------------------------------------------------*/
42 HistoryManager* HistoryManager::m_pHM = NULL;
43 /*------------------------------------------------------------------------*/
44 HistoryManager* HistoryManager::getInstance()
45 {
46     if (m_pHM == NULL)
47     {
48         m_pHM = new HistoryManager();
49
50         /* add date & time @ begin session */
51         char *commentbeginsession = getCommentDateSession(FALSE);
52         if (commentbeginsession)
53         {
54             appendLineToScilabHistory(commentbeginsession);
55             FREE(commentbeginsession);
56             commentbeginsession = NULL;
57         }
58
59         m_pHM->setToken("");
60
61     }
62     return m_pHM;
63 }
64 /*------------------------------------------------------------------------*/
65 void HistoryManager::killInstance(void)
66 {
67     if (m_pHM)
68     {
69         delete m_pHM;
70         m_pHM = NULL;
71     }
72 }
73 /*------------------------------------------------------------------------*/
74 BOOL historyIsEnabled(void)
75 {
76     return HistoryManager::historyIsEnabled();
77 }
78 /*------------------------------------------------------------------------*/
79 BOOL InitializeHistoryManager(void)
80 {
81     if (HistoryManager::getInstance())
82     {
83         return TRUE;
84     }
85     return FALSE;
86 }
87 /*------------------------------------------------------------------------*/
88 BOOL TerminateHistoryManager(void)
89 {
90     HistoryManager::getInstance()->killInstance();
91     return TRUE;
92 }
93 /*------------------------------------------------------------------------*/
94 BOOL setSearchedTokenInScilabHistory(char* _pstToken)
95 {
96     return HistoryManager::getInstance()->setToken(_pstToken);
97 }
98 /*------------------------------------------------------------------------*/
99 BOOL resetSearchedTokenInScilabHistory(void)
100 {
101     return HistoryManager::getInstance()->resetToken();
102 }
103 /*------------------------------------------------------------------------*/
104 char* getSearchedTokenInScilabHistory(void)
105 {
106     return HistoryManager::getInstance()->getToken();
107 }
108 /*------------------------------------------------------------------------*/
109 BOOL appendLineToScilabHistory(char* _pstLine)
110 {
111     return HistoryManager::getInstance()->appendLine(_pstLine);
112 }
113 /*------------------------------------------------------------------------*/
114 BOOL appendLinesToScilabHistory(char** _pstLines, int _iLines)
115 {
116     for (int i = 0 ; i < _iLines ; i++)
117     {
118         if (HistoryManager::getInstance()->appendLine(_pstLines[i]) == FALSE)
119         {
120             return FALSE;
121         }
122     }
123     return TRUE;
124 }
125 /*------------------------------------------------------------------------*/
126 void displayScilabHistory(void)
127 {
128     HistoryManager::getInstance()->displayHistory();
129 }
130 /*------------------------------------------------------------------------*/
131 BOOL writeScilabHistoryToFile(char* _pstFilename)
132 {
133     return HistoryManager::getInstance()->writeToFile(_pstFilename);
134 }
135 /*------------------------------------------------------------------------*/
136 BOOL loadScilabHistoryFromFile(char* _pstFilename)
137 {
138     return HistoryManager::getInstance()->loadFromFile(_pstFilename);
139 }
140 /*------------------------------------------------------------------------*/
141 BOOL isScilabHistoryTruncated(void)
142 {
143     return HistoryManager::getInstance()->isTruncated();
144 }
145 /*------------------------------------------------------------------------*/
146 BOOL setFilenameScilabHistory(char* _pstFilename)
147 {
148     return HistoryManager::getInstance()->setFilename(_pstFilename);
149 }
150 /*------------------------------------------------------------------------*/
151 char* getFilenameScilabHistory(void)
152 {
153     return HistoryManager::getInstance()->getFilename();
154 }
155 /*------------------------------------------------------------------------*/
156 BOOL setDefaultFilenameScilabHistory(void)
157 {
158     return HistoryManager::getInstance()->setDefaultFilename();
159 }
160 /*------------------------------------------------------------------------*/
161 BOOL resetScilabHistory(void)
162 {
163     return HistoryManager::getInstance()->reset();
164 }
165 /*------------------------------------------------------------------------*/
166 char** getAllLinesOfScilabHistory(void)
167 {
168     int iItems = 0;
169     return HistoryManager::getInstance()->getAllLines(&iItems);
170 }
171 /*------------------------------------------------------------------------*/
172 int getSizeAllLinesOfScilabHistory(void)
173 {
174     return HistoryManager::getInstance()->getNumberOfLines();
175 }
176 /*------------------------------------------------------------------------*/
177 char* getLastLineInScilabHistory(void)
178 {
179     return HistoryManager::getInstance()->getLastLine();
180 }
181 /*------------------------------------------------------------------------*/
182 char* getPreviousLineInScilabHistory(void)
183 {
184     return HistoryManager::getInstance()->getPreviousLine();
185 }
186 /*------------------------------------------------------------------------*/
187 char* getNextLineInScilabHistory(void)
188 {
189     return HistoryManager::getInstance()->getNextLine();
190 }
191 /*------------------------------------------------------------------------*/
192 int getNumberOfLinesInScilabHistory(void)
193 {
194     return HistoryManager::getInstance()->getNumberOfLines();
195 }
196 /*------------------------------------------------------------------------*/
197 void setSaveConsecutiveDuplicateLinesInScilabHistory(BOOL _bAllow)
198 {
199     HistoryManager::getInstance()->setSaveConsecutiveDuplicateLines(_bAllow);
200 }
201 /*------------------------------------------------------------------------*/
202 BOOL getSaveConsecutiveDuplicateLinesInScilabHistory(void)
203 {
204     return HistoryManager::getInstance()->getSaveConsecutiveDuplicateLines();
205 }
206 /*------------------------------------------------------------------------*/
207 void setAfterHowManyLinesScilabHistoryIsSaved(int _iNum)
208 {
209     HistoryManager::getInstance()->setAfterHowManyLinesHistoryIsSaved(_iNum);
210 }
211 /*------------------------------------------------------------------------*/
212 int getAfterHowManyLinesScilabHistoryIsSaved(void)
213 {
214     return HistoryManager::getInstance()->getAfterHowManyLinesHistoryIsSaved();
215 }
216 /*------------------------------------------------------------------------*/
217 char* getNthLineInScilabHistory(int _iLine)
218 {
219     return HistoryManager::getInstance()->getNthLine(_iLine);
220 }
221 /*------------------------------------------------------------------------*/
222 BOOL deleteNthLineScilabHistory(int _iLine)
223 {
224     return HistoryManager::getInstance()->deleteNthLine(_iLine);
225 }
226 /*------------------------------------------------------------------------*/
227 int getSizeScilabHistory(void)
228 {
229     return (HistoryManager::getInstance()->getNumberOfLines() - 1);
230 }
231 /*------------------------------------------------------------------------*/
232 BOOL setSizeMaxScilabHistory(int _iMaxLines)
233 {
234     return HistoryManager::getInstance()->setNumberOfLinesMax(_iMaxLines);
235 }
236 /*------------------------------------------------------------------------*/
237 int getSizeMaxScilabHistory(void)
238 {
239     return HistoryManager::getInstance()->getNumberOfLinesMax();
240 }
241 /*------------------------------------------------------------------------*/
242 HistoryManager::HistoryManager()
243 {
244     m_bTruncated                = FALSE;
245     m_bAllowConsecutiveCommand  = FALSE;
246     m_iSaveLimit                = 0;
247     m_iSavedLines               = 0;
248     m_Commands.clear();
249
250     CommandHistoryInitialize();
251 }
252 /*------------------------------------------------------------------------*/
253 HistoryManager::~HistoryManager()
254 {
255     m_Commands.clear();
256 }
257 /*------------------------------------------------------------------------*/
258 BOOL HistoryManager::historyIsEnabled(void)
259 {
260     if (m_pHM)
261     {
262         return TRUE;
263     }
264     return FALSE;
265 }
266 /*------------------------------------------------------------------------*/
267 BOOL HistoryManager::appendLine(char* _pstLine)
268 {
269     BOOL bOK = FALSE;
270     if (_pstLine)
271     {
272         int i                   = 0;
273         int len                 = 0;
274         char* pstCleanedLine    = NULL;
275
276         /* remove space & carriage return at the end of line */
277         len = (int)strlen(_pstLine);
278         pstCleanedLine = (char*) MALLOC(len + 1);
279         memcpy(pstCleanedLine, _pstLine, len + 1);
280
281         /* remove carriage return at the end of line */
282         for (i = len ; i > 0 ; i--)
283         {
284             if (pstCleanedLine[i] == '\n')
285             {
286                 pstCleanedLine[i] = '\0';
287                 len = i - 1;
288                 break;
289             }
290         }
291
292         /* remove spaces at the end of line */
293         i = len;
294         while (i >= 0)
295         {
296             if (pstCleanedLine[i] == ' ')
297             {
298                 pstCleanedLine[i] = '\0';
299             }
300             else
301             {
302                 break;
303             }
304             i--;
305         }
306
307         if (strlen(pstCleanedLine) == 0)
308         {
309             FREE(pstCleanedLine);
310             return TRUE;
311         }
312
313         // append
314         if (m_bAllowConsecutiveCommand)
315         {
316             m_Commands.push_back(pstCleanedLine);
317             m_iSavedLines++;
318             bOK = TRUE;
319             CommandHistoryAppendLine(pstCleanedLine);
320         }
321         else
322         {
323             char* pstPreviousLine = getLastLine();
324             if (pstPreviousLine && strcmp(pstPreviousLine, pstCleanedLine) == 0)
325             {
326                 bOK = TRUE;
327             }
328             else
329             {
330                 m_Commands.push_back(pstCleanedLine);
331                 m_iSavedLines++;
332                 bOK = TRUE;
333
334                 CommandHistoryAppendLine(pstCleanedLine);
335             }
336             if (pstPreviousLine)
337             {
338                 FREE(pstPreviousLine);
339                 pstPreviousLine = NULL;
340             }
341         }
342
343         if (m_iSaveLimit != 0)
344         {
345             if (m_iSavedLines >= m_iSaveLimit)
346             {
347                 m_HF.setHistory(m_Commands);
348                 m_HF.writeToFile();
349                 m_iSavedLines = 0;
350             }
351         }
352         else
353         {
354             m_iSavedLines = 0;
355         }
356
357         if (pstCleanedLine)
358         {
359             FREE(pstCleanedLine);
360             pstCleanedLine = NULL;
361         }
362     }
363
364     return bOK;
365 }
366 /*------------------------------------------------------------------------*/
367 BOOL HistoryManager::appendLines(char** _pstLines, int _iLines)
368 {
369     for (int i = 0 ; i < _iLines ; i++)
370     {
371         if (appendLine(_pstLines[i]) == FALSE)
372         {
373             return FALSE;
374         }
375     }
376     return TRUE;
377 }
378 /*------------------------------------------------------------------------*/
379 void HistoryManager::displayHistory(void)
380 {
381     int nbline = 0;
382     std::list<std::string>::const_iterator it;
383     for (it = m_Commands.begin() ; it != m_Commands.end() ; it++)
384     {
385         sciprint(_("%d : %s\n"), nbline++, (*it).c_str());
386     }
387 }
388 /*------------------------------------------------------------------------*/
389 char* HistoryManager::getFilename(void)
390 {
391     if (m_HF.getFilename().empty() == false)
392     {
393         return os_strdup(m_HF.getFilename().c_str());
394     }
395     return NULL;
396 }
397 /*------------------------------------------------------------------------*/
398 BOOL HistoryManager::setFilename(char* _pstFilename)
399 {
400     if (_pstFilename)
401     {
402         m_HF.setFilename(_pstFilename);
403         return TRUE;
404     }
405     return FALSE;
406 }
407 /*------------------------------------------------------------------------*/
408 BOOL HistoryManager::setDefaultFilename(void)
409 {
410     return m_HF.setDefaultFilename();
411 }
412 /*------------------------------------------------------------------------*/
413 BOOL HistoryManager::writeToFile(char* _pstFilename)
414 {
415     if (_pstFilename)
416     {
417         m_HF.setHistory(m_Commands);
418         return m_HF.writeToFile(_pstFilename);
419     }
420     return FALSE;
421 }
422 /*------------------------------------------------------------------------*/
423 BOOL HistoryManager::loadFromFile(char* _pstFilename)
424 {
425     if (_pstFilename)
426     {
427         char* pstCommentBeginSession = NULL;
428         if (m_HF.loadFromFile(_pstFilename) == HISTORY_TRUNCATED)
429         {
430             m_bTruncated = TRUE;
431         }
432
433         m_Commands.clear();
434         m_Commands = m_HF.getHistory();
435
436         if (m_Commands.size() > 0)
437         {
438             char* pstFirstLine = getFirstLine();
439             if (pstFirstLine)
440             {
441                 if (!isBeginningSessionLine(pstFirstLine))
442                 {
443                     fixHistorySession();
444                 }
445                 FREE(pstFirstLine);
446                 pstFirstLine = NULL;
447             }
448         }
449
450         /* add date & time @ begin session */
451         pstCommentBeginSession = getCommentDateSession(FALSE);
452         appendLine(pstCommentBeginSession);
453         FREE(pstCommentBeginSession);
454         pstCommentBeginSession = NULL;
455
456         CommandHistoryLoadFromFile();
457
458         return TRUE;
459     }
460     return FALSE;
461 }
462 /*--------------------------------------------------------------------------*/
463 BOOL HistoryManager::reset(void)
464 {
465     char* pstCommentBeginSession = NULL;
466
467     m_Commands.clear();
468
469     m_HF.reset();
470     m_HF.setDefaultFilename();
471
472     m_HS.reset();
473
474     m_bAllowConsecutiveCommand  = FALSE;
475     m_iSaveLimit                = 0;
476     m_iSavedLines               = 0;
477
478     CommandHistoryReset();
479
480     /* Add date & time begin session */
481     pstCommentBeginSession = getCommentDateSession(FALSE);
482     if (pstCommentBeginSession)
483     {
484         appendLine(pstCommentBeginSession);
485         FREE(pstCommentBeginSession);
486         pstCommentBeginSession = NULL;
487         return TRUE;
488     }
489
490     return FALSE;
491 }
492 /*--------------------------------------------------------------------------*/
493 char** HistoryManager::getAllLines(int* _piLines)
494 {
495     char** pstLines = NULL;
496     *_piLines       = 0;
497
498     if (m_Commands.empty())
499     {
500         return pstLines;
501     }
502     else
503     {
504         std::list<std::string>::const_iterator it;
505
506         pstLines = (char**)MALLOC((int)(m_Commands.size() + 1) * (sizeof(char*)));
507         for (it = m_Commands.begin() ; it != m_Commands.end(); ++it)
508         {
509             pstLines[(*_piLines)++] = os_strdup((*it).c_str());
510         }
511
512         /* SWIG need array finish with NULL */
513         pstLines[(*_piLines)] = NULL;
514     }
515     return pstLines;
516 }
517 /*--------------------------------------------------------------------------*/
518 char* HistoryManager::getFirstLine(void)
519 {
520     if (m_Commands.empty() == false)
521     {
522         return os_strdup(m_Commands.front().c_str());
523     }
524     return NULL;
525 }
526 /*--------------------------------------------------------------------------*/
527 char* HistoryManager::getLastLine(void)
528 {
529     if (m_Commands.empty() == false)
530     {
531         return os_strdup(m_Commands.back().c_str());
532     }
533     return NULL;
534 }
535 /*--------------------------------------------------------------------------*/
536 int HistoryManager::getNumberOfLines(void)
537 {
538     return (int)m_Commands.size();
539 }
540 /*--------------------------------------------------------------------------*/
541 char* HistoryManager::getNthLine(int _iLine)
542 {
543     if (_iLine < 0)
544     {
545         //reverse search Oo
546         _iLine = getNumberOfLines() + _iLine;
547     }
548
549     if (_iLine >= 0 && _iLine <= getNumberOfLines())
550     {
551         int i = 0;
552         std::list<std::string>::const_iterator it;
553         for (it = m_Commands.begin() ; it != m_Commands.end() ; it++)
554         {
555             if (i == _iLine)
556             {
557                 return os_strdup((*it).c_str());
558             }
559             i++;
560         }
561     }
562
563     return NULL;
564 }
565 /*--------------------------------------------------------------------------*/
566 BOOL HistoryManager::deleteNthLine(int _iLine)
567 {
568     if (_iLine >= 0 && _iLine <= getNumberOfLines())
569     {
570         int i = 0;
571         std::list<std::string>::iterator it;
572         for (it = m_Commands.begin() ; it != m_Commands.end(); it++)
573         {
574             if (i == _iLine)
575             {
576                 m_Commands.erase(it);
577                 // After a remove , we update search
578                 m_HS.setHistory(m_Commands);
579                 m_HS.setToken("");
580
581                 CommandHistoryDeleteLine(_iLine);
582                 return TRUE;
583             }
584             i++;
585         }
586     }
587     return FALSE;
588 }
589 /*--------------------------------------------------------------------------*/
590 void HistoryManager::setSaveConsecutiveDuplicateLines(BOOL _bAllow)
591 {
592     m_bAllowConsecutiveCommand = _bAllow;
593 }
594 /*--------------------------------------------------------------------------*/
595 BOOL HistoryManager::getSaveConsecutiveDuplicateLines(void)
596 {
597     return m_bAllowConsecutiveCommand;
598 }
599 /*--------------------------------------------------------------------------*/
600 void HistoryManager::setAfterHowManyLinesHistoryIsSaved(int _iSaveLimit)
601 {
602     if (_iSaveLimit >= 0)
603     {
604         m_iSaveLimit    = _iSaveLimit;
605         m_iSavedLines   = 0;
606     }
607 }
608 /*--------------------------------------------------------------------------*/
609 int HistoryManager::getAfterHowManyLinesHistoryIsSaved(void)
610 {
611     return m_iSaveLimit;
612 }
613 /*--------------------------------------------------------------------------*/
614 char* HistoryManager::getPreviousLine(void)
615 {
616     if (m_HS.getSize() > 0)
617     {
618         std::string stLine = m_HS.getPreviousLine();
619         if (stLine.empty() == false)
620         {
621             return os_strdup(stLine.c_str());
622         }
623     }
624     return NULL;
625 }
626 /*--------------------------------------------------------------------------*/
627 char* HistoryManager::getNextLine(void)
628 {
629     if (m_HS.getSize() > 0)
630     {
631         std::string stLine = m_HS.getNextLine();
632         return os_strdup(stLine.c_str());
633     }
634     return NULL;
635 }
636 /*--------------------------------------------------------------------------*/
637 BOOL HistoryManager::setToken(const char* _pstToken)
638 {
639     m_HS.setHistory(m_Commands);
640
641     if (_pstToken)
642     {
643         return m_HS.setToken(_pstToken);
644     }
645     else
646     {
647         return m_HS.setToken("");
648     }
649 }
650 /*--------------------------------------------------------------------------*/
651 char* HistoryManager::getToken(void)
652 {
653     std::string stToken = m_HS.getToken();
654     if (stToken.empty() == false)
655     {
656         return os_strdup(stToken.c_str());
657     }
658     return NULL;
659 }
660 /*--------------------------------------------------------------------------*/
661 BOOL HistoryManager::resetToken(void)
662 {
663     return m_HS.reset();
664 }
665 /*--------------------------------------------------------------------------*/
666 BOOL HistoryManager::isBeginningSessionLine(char* _pstLine)
667 {
668     if (_pstLine)
669     {
670         if (strlen(_pstLine) > strlen(SESSION_PRAGMA_BEGIN) + strlen(SESSION_PRAGMA_END))
671         {
672             if ((strncmp(   _pstLine,
673                             SESSION_PRAGMA_BEGIN,
674                             strlen(SESSION_PRAGMA_BEGIN)) == 0) &&
675                     (strncmp(    _pstLine + strlen(_pstLine) - strlen(SESSION_PRAGMA_END),
676                                  SESSION_PRAGMA_END,
677                                  strlen(SESSION_PRAGMA_END)) == 0))
678             {
679                 return TRUE;
680             }
681         }
682     }
683     return FALSE;
684 }
685 /*--------------------------------------------------------------------------*/
686 void HistoryManager::fixHistorySession(void)
687 {
688     /* add date & time @ begin session */
689     char* pstCommentBeginSession = getCommentDateSession(FALSE);
690     if (pstCommentBeginSession)
691     {
692         m_Commands.push_front(pstCommentBeginSession);
693         FREE(pstCommentBeginSession);
694         pstCommentBeginSession = NULL;
695     }
696 }
697 /*--------------------------------------------------------------------------*/
698 BOOL HistoryManager::isTruncated(void)
699 {
700     return m_bTruncated;
701 }
702 /*--------------------------------------------------------------------------*/
703 BOOL HistoryManager::setNumberOfLinesMax(int _iMaxLines)
704 {
705     return m_HF.setDefaultMaxNbLines(_iMaxLines);
706 }
707 /*--------------------------------------------------------------------------*/
708 int HistoryManager::getNumberOfLinesMax(void)
709 {
710     return m_HF.getDefaultMaxNbLines();
711 }
712 /*--------------------------------------------------------------------------*/