7594d22f4c323f021c8f3ca86a4deb2b1faec2bd
[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         FREE(pstCleanedLine);
358         pstCleanedLine = NULL;
359     }
360
361     return bOK;
362 }
363 /*------------------------------------------------------------------------*/
364 BOOL HistoryManager::appendLines(char** _pstLines, int _iLines)
365 {
366     for (int i = 0 ; i < _iLines ; i++)
367     {
368         if (appendLine(_pstLines[i]) == FALSE)
369         {
370             return FALSE;
371         }
372     }
373     return TRUE;
374 }
375 /*------------------------------------------------------------------------*/
376 void HistoryManager::displayHistory(void)
377 {
378     int nbline = 0;
379     std::list<std::string>::const_iterator it;
380     for (it = m_Commands.begin() ; it != m_Commands.end() ; it++)
381     {
382         sciprint(_("%d : %s\n"), nbline++, (*it).c_str());
383     }
384 }
385 /*------------------------------------------------------------------------*/
386 char* HistoryManager::getFilename(void)
387 {
388     if (m_HF.getFilename().empty() == false)
389     {
390         return os_strdup(m_HF.getFilename().c_str());
391     }
392     return NULL;
393 }
394 /*------------------------------------------------------------------------*/
395 BOOL HistoryManager::setFilename(char* _pstFilename)
396 {
397     if (_pstFilename)
398     {
399         m_HF.setFilename(_pstFilename);
400         return TRUE;
401     }
402     return FALSE;
403 }
404 /*------------------------------------------------------------------------*/
405 BOOL HistoryManager::setDefaultFilename(void)
406 {
407     return m_HF.setDefaultFilename();
408 }
409 /*------------------------------------------------------------------------*/
410 BOOL HistoryManager::writeToFile(char* _pstFilename)
411 {
412     if (_pstFilename)
413     {
414         m_HF.setHistory(m_Commands);
415         return m_HF.writeToFile(_pstFilename);
416     }
417     return FALSE;
418 }
419 /*------------------------------------------------------------------------*/
420 BOOL HistoryManager::loadFromFile(char* _pstFilename)
421 {
422     if (_pstFilename)
423     {
424         char* pstCommentBeginSession = NULL;
425         if (m_HF.loadFromFile(_pstFilename) == HISTORY_TRUNCATED)
426         {
427             m_bTruncated = TRUE;
428         }
429
430         m_Commands.clear();
431         m_Commands = m_HF.getHistory();
432
433         if (m_Commands.size() > 0)
434         {
435             char* pstFirstLine = getFirstLine();
436             if (pstFirstLine)
437             {
438                 if (!isBeginningSessionLine(pstFirstLine))
439                 {
440                     fixHistorySession();
441                 }
442                 FREE(pstFirstLine);
443                 pstFirstLine = NULL;
444             }
445         }
446
447         /* add date & time @ begin session */
448         pstCommentBeginSession = getCommentDateSession(FALSE);
449         appendLine(pstCommentBeginSession);
450         FREE(pstCommentBeginSession);
451         pstCommentBeginSession = NULL;
452
453         CommandHistoryLoadFromFile();
454
455         return TRUE;
456     }
457     return FALSE;
458 }
459 /*--------------------------------------------------------------------------*/
460 BOOL HistoryManager::reset(void)
461 {
462     char* pstCommentBeginSession = NULL;
463
464     m_Commands.clear();
465
466     m_HF.reset();
467     m_HF.setDefaultFilename();
468
469     m_HS.reset();
470
471     m_bAllowConsecutiveCommand  = FALSE;
472     m_iSaveLimit                = 0;
473     m_iSavedLines               = 0;
474
475     CommandHistoryReset();
476
477     /* Add date & time begin session */
478     pstCommentBeginSession = getCommentDateSession(FALSE);
479     if (pstCommentBeginSession)
480     {
481         appendLine(pstCommentBeginSession);
482         FREE(pstCommentBeginSession);
483         pstCommentBeginSession = NULL;
484         return TRUE;
485     }
486
487     return FALSE;
488 }
489 /*--------------------------------------------------------------------------*/
490 char** HistoryManager::getAllLines(int* _piLines)
491 {
492     char** pstLines = NULL;
493     *_piLines       = 0;
494
495     if (m_Commands.empty())
496     {
497         return pstLines;
498     }
499     else
500     {
501         std::list<std::string>::const_iterator it;
502
503         pstLines = (char**)MALLOC((int)(m_Commands.size() + 1) * (sizeof(char*)));
504         for (it = m_Commands.begin() ; it != m_Commands.end(); ++it)
505         {
506             pstLines[(*_piLines)++] = os_strdup((*it).c_str());
507         }
508
509         /* SWIG need array finish with NULL */
510         pstLines[(*_piLines)] = NULL;
511     }
512     return pstLines;
513 }
514 /*--------------------------------------------------------------------------*/
515 char* HistoryManager::getFirstLine(void)
516 {
517     if (m_Commands.empty() == false)
518     {
519         return os_strdup(m_Commands.front().c_str());
520     }
521     return NULL;
522 }
523 /*--------------------------------------------------------------------------*/
524 char* HistoryManager::getLastLine(void)
525 {
526     if (m_Commands.empty() == false)
527     {
528         return os_strdup(m_Commands.back().c_str());
529     }
530     return NULL;
531 }
532 /*--------------------------------------------------------------------------*/
533 int HistoryManager::getNumberOfLines(void)
534 {
535     return (int)m_Commands.size();
536 }
537 /*--------------------------------------------------------------------------*/
538 char* HistoryManager::getNthLine(int _iLine)
539 {
540     if (_iLine < 0)
541     {
542         //reverse search Oo
543         _iLine = getNumberOfLines() + _iLine;
544     }
545
546     if (_iLine >= 0 && _iLine <= getNumberOfLines())
547     {
548         int i = 0;
549         std::list<std::string>::const_iterator it;
550         for (it = m_Commands.begin() ; it != m_Commands.end() ; it++)
551         {
552             if (i == _iLine)
553             {
554                 return os_strdup((*it).c_str());
555             }
556             i++;
557         }
558     }
559
560     return NULL;
561 }
562 /*--------------------------------------------------------------------------*/
563 BOOL HistoryManager::deleteNthLine(int _iLine)
564 {
565     if (_iLine >= 0 && _iLine <= getNumberOfLines())
566     {
567         int i = 0;
568         std::list<std::string>::iterator it;
569         for (it = m_Commands.begin() ; it != m_Commands.end(); it++)
570         {
571             if (i == _iLine)
572             {
573                 m_Commands.erase(it);
574                 // After a remove , we update search
575                 m_HS.setHistory(m_Commands);
576                 m_HS.setToken("");
577
578                 CommandHistoryDeleteLine(_iLine);
579                 return TRUE;
580             }
581             i++;
582         }
583     }
584     return FALSE;
585 }
586 /*--------------------------------------------------------------------------*/
587 void HistoryManager::setSaveConsecutiveDuplicateLines(BOOL _bAllow)
588 {
589     m_bAllowConsecutiveCommand = _bAllow;
590 }
591 /*--------------------------------------------------------------------------*/
592 BOOL HistoryManager::getSaveConsecutiveDuplicateLines(void)
593 {
594     return m_bAllowConsecutiveCommand;
595 }
596 /*--------------------------------------------------------------------------*/
597 void HistoryManager::setAfterHowManyLinesHistoryIsSaved(int _iSaveLimit)
598 {
599     if (_iSaveLimit >= 0)
600     {
601         m_iSaveLimit    = _iSaveLimit;
602         m_iSavedLines   = 0;
603     }
604 }
605 /*--------------------------------------------------------------------------*/
606 int HistoryManager::getAfterHowManyLinesHistoryIsSaved(void)
607 {
608     return m_iSaveLimit;
609 }
610 /*--------------------------------------------------------------------------*/
611 char* HistoryManager::getPreviousLine(void)
612 {
613     if (m_HS.getSize() > 0)
614     {
615         std::string stLine = m_HS.getPreviousLine();
616         if (stLine.empty() == false)
617         {
618             return os_strdup(stLine.c_str());
619         }
620     }
621     return NULL;
622 }
623 /*--------------------------------------------------------------------------*/
624 char* HistoryManager::getNextLine(void)
625 {
626     if (m_HS.getSize() > 0)
627     {
628         std::string stLine = m_HS.getNextLine();
629         return os_strdup(stLine.c_str());
630     }
631     return NULL;
632 }
633 /*--------------------------------------------------------------------------*/
634 BOOL HistoryManager::setToken(const char* _pstToken)
635 {
636     m_HS.setHistory(m_Commands);
637
638     if (_pstToken)
639     {
640         return m_HS.setToken(_pstToken);
641     }
642     else
643     {
644         return m_HS.setToken("");
645     }
646 }
647 /*--------------------------------------------------------------------------*/
648 char* HistoryManager::getToken(void)
649 {
650     std::string stToken = m_HS.getToken();
651     if (stToken.empty() == false)
652     {
653         return os_strdup(stToken.c_str());
654     }
655     return NULL;
656 }
657 /*--------------------------------------------------------------------------*/
658 BOOL HistoryManager::resetToken(void)
659 {
660     return m_HS.reset();
661 }
662 /*--------------------------------------------------------------------------*/
663 BOOL HistoryManager::isBeginningSessionLine(char* _pstLine)
664 {
665     if (_pstLine)
666     {
667         if (strlen(_pstLine) > strlen(SESSION_PRAGMA_BEGIN) + strlen(SESSION_PRAGMA_END))
668         {
669             if ((strncmp(   _pstLine,
670                             SESSION_PRAGMA_BEGIN,
671                             strlen(SESSION_PRAGMA_BEGIN)) == 0) &&
672                     (strncmp(    _pstLine + strlen(_pstLine) - strlen(SESSION_PRAGMA_END),
673                                  SESSION_PRAGMA_END,
674                                  strlen(SESSION_PRAGMA_END)) == 0))
675             {
676                 return TRUE;
677             }
678         }
679     }
680     return FALSE;
681 }
682 /*--------------------------------------------------------------------------*/
683 void HistoryManager::fixHistorySession(void)
684 {
685     /* add date & time @ begin session */
686     char* pstCommentBeginSession = getCommentDateSession(FALSE);
687     if (pstCommentBeginSession)
688     {
689         m_Commands.push_front(pstCommentBeginSession);
690         FREE(pstCommentBeginSession);
691         pstCommentBeginSession = NULL;
692     }
693 }
694 /*--------------------------------------------------------------------------*/
695 BOOL HistoryManager::isTruncated(void)
696 {
697     return m_bTruncated;
698 }
699 /*--------------------------------------------------------------------------*/
700 BOOL HistoryManager::setNumberOfLinesMax(int _iMaxLines)
701 {
702     return m_HF.setDefaultMaxNbLines(_iMaxLines);
703 }
704 /*--------------------------------------------------------------------------*/
705 int HistoryManager::getNumberOfLinesMax(void)
706 {
707     return m_HF.getDefaultMaxNbLines();
708 }
709 /*--------------------------------------------------------------------------*/