Console.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   (c) Jürgen Riegel (juergen.riegel@web.de) 2002                        *   
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU Library General Public License (LGPL)   *
00008  *   as published by the Free Software Foundation; either version 2 of     *
00009  *   the License, or (at your option) any later version.                   *
00010  *   for detail see the LICENCE text file.                                 *
00011  *                                                                         *
00012  *   FreeCAD is distributed in the hope that it will be useful,            *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * 
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU Library General Public License for more details.                  *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU Library General Public     *
00018  *   License along with FreeCAD; if not, write to the Free Software        * 
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
00020  *   USA                                                                   *
00021  *                                                                         *
00022  *   Juergen Riegel 2002                                                   *
00023  ***************************************************************************/
00024 
00025 #include "PreCompiled.h"
00026 
00027 #ifndef _PreComp_
00028 # include <time.h>
00029 # include <stdio.h>
00030 # ifdef FC_OS_WIN32
00031 # include <io.h>
00032 # include <windows.h>
00033 # endif
00034 # include "fcntl.h"
00035 #endif
00036 
00037 #include "Console.h"
00038 #include "Exception.h"
00039 #include "PyObjectBase.h"
00040 
00041 using namespace Base;
00042 
00043 
00044 
00045 char format[4024];  // global buffer 
00046 const unsigned int format_len = 4024;
00047 
00048 
00049 //**************************************************************************
00050 // Construction destruction
00051 
00052 
00053 ConsoleSingleton::ConsoleSingleton(void)
00054   :_bVerbose(false)
00055 {
00056 
00057 }
00058 
00059 ConsoleSingleton::~ConsoleSingleton()
00060 {
00061     for(std::set<ConsoleObserver * >::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
00062         delete (*Iter);   
00063 
00064 }
00065 
00066 
00067 //**************************************************************************
00068 // methods
00069 
00073 void ConsoleSingleton::SetMode(ConsoleMode m)
00074 {
00075     if(m && Verbose)
00076         _bVerbose = true;
00077 }
00081 void ConsoleSingleton::UnsetMode(ConsoleMode m)
00082 {
00083     if(m && Verbose)
00084         _bVerbose = false;
00085 }
00086 
00103 ConsoleMsgFlags ConsoleSingleton::SetEnabledMsgType(const char* sObs, ConsoleMsgFlags type, bool b)
00104 {
00105     ConsoleObserver* pObs = Get(sObs);
00106     if ( pObs ){
00107         ConsoleMsgFlags flags=0;
00108 
00109         if ( type&MsgType_Err ){
00110             if ( pObs->bErr != b )
00111                 flags |= MsgType_Err;
00112             pObs->bErr = b;
00113         }
00114         if ( type&MsgType_Wrn ){
00115             if ( pObs->bWrn != b )
00116                 flags |= MsgType_Wrn;
00117             pObs->bWrn = b;
00118         }
00119         if ( type&MsgType_Txt ){
00120             if ( pObs->bMsg != b )
00121                 flags |= MsgType_Txt;
00122             pObs->bMsg = b;
00123         }
00124         if ( type&MsgType_Log ){
00125             if ( pObs->bLog != b )
00126                 flags |= MsgType_Log;
00127             pObs->bLog = b;
00128         }
00129         return flags;
00130     }
00131     else {
00132         return 0;
00133     }
00134 }
00135 
00150 void ConsoleSingleton::Message( const char *pMsg, ... )
00151 {
00152     va_list namelessVars;
00153     va_start(namelessVars, pMsg);  // Get the "..." vars
00154     vsnprintf(format, format_len, pMsg, namelessVars);
00155     va_end(namelessVars);
00156     NotifyMessage(format);
00157 }
00158 
00174 void ConsoleSingleton::Warning( const char *pMsg, ... )
00175 {
00176     va_list namelessVars;
00177     va_start(namelessVars, pMsg);  // Get the "..." vars
00178     vsnprintf(format, format_len, pMsg, namelessVars);
00179     va_end(namelessVars);
00180     NotifyWarning(format);
00181 }
00182 
00198 void ConsoleSingleton::Error( const char *pMsg, ... )
00199 {
00200     va_list namelessVars;
00201     va_start(namelessVars, pMsg);  // Get the "..." vars
00202     vsnprintf(format, format_len, pMsg, namelessVars);
00203     va_end(namelessVars);
00204     NotifyError(format);
00205 }
00206 
00207 
00225 void ConsoleSingleton::Log( const char *pMsg, ... )
00226 {
00227     if (!_bVerbose)
00228     {
00229         va_list namelessVars;
00230         va_start(namelessVars, pMsg);  // Get the "..." vars
00231         vsnprintf(format, format_len, pMsg, namelessVars);
00232         va_end(namelessVars);
00233         NotifyLog(format);
00234     }
00235 }
00236 
00237 
00243 const char* ConsoleSingleton::Time(void)
00244 {
00245     struct tm *newtime;
00246     time_t aclock;
00247     time( &aclock );                 // Get time in seconds 
00248     newtime = localtime( &aclock );  // Convert time to struct tm form 
00249     char* st = asctime( newtime );
00250     st[24] = 0;
00251     return st;
00252 }
00253 
00254 
00255 
00256 //**************************************************************************
00257 // Observer stuff
00258 
00265 void ConsoleSingleton::AttachObserver(ConsoleObserver *pcObserver)
00266 {
00267     // double insert !!
00268     assert(_aclObservers.find(pcObserver) == _aclObservers.end() );
00269 
00270     _aclObservers.insert(pcObserver);
00271 }
00272 
00278 void ConsoleSingleton::DetachObserver(ConsoleObserver *pcObserver)
00279 {
00280     _aclObservers.erase(pcObserver);
00281 }
00282 
00283 void ConsoleSingleton::NotifyMessage(const char *sMsg)
00284 {
00285     for(std::set<ConsoleObserver * >::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
00286         if((*Iter)->bMsg)
00287             (*Iter)->Message(sMsg);   // send string to the listener
00288 }
00289 
00290 void ConsoleSingleton::NotifyWarning(const char *sMsg)
00291 {
00292     for(std::set<ConsoleObserver * >::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
00293         if((*Iter)->bWrn)
00294             (*Iter)->Warning(sMsg);   // send string to the listener
00295 }
00296 
00297 void ConsoleSingleton::NotifyError(const char *sMsg)
00298 {
00299     for(std::set<ConsoleObserver * >::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
00300         if((*Iter)->bErr)
00301             (*Iter)->Error(sMsg);   // send string to the listener
00302 }
00303 
00304 void ConsoleSingleton::NotifyLog(const char *sMsg)
00305 {
00306     for(std::set<ConsoleObserver * >::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
00307         if((*Iter)->bLog)
00308             (*Iter)->Log(sMsg);   // send string to the listener
00309 }
00310 
00311 ConsoleObserver *ConsoleSingleton::Get(const char *Name)
00312 {
00313     const char* OName;
00314     for(std::set<ConsoleObserver * >::iterator Iter=_aclObservers.begin();Iter!=_aclObservers.end();Iter++)
00315     {
00316         OName = (*Iter)->Name();   // get the name
00317         if(OName && strcmp(OName,Name) == 0)
00318             return *Iter;
00319     }
00320     return 0;
00321 }
00322 
00323 
00324 //**************************************************************************
00325 // Singleton stuff
00326 
00327 ConsoleSingleton * ConsoleSingleton::_pcSingleton = 0;
00328 
00329 void ConsoleSingleton::Destruct(void)
00330 {
00331     // not initialized or double destructed!
00332     assert(_pcSingleton);
00333     delete _pcSingleton;
00334     _pcSingleton=0;
00335 }
00336 
00337 ConsoleSingleton & ConsoleSingleton::Instance(void)
00338 {
00339     // not initialized?
00340     if(!_pcSingleton)
00341     {
00342         _pcSingleton = new ConsoleSingleton();
00343     }
00344     return *_pcSingleton;
00345 }
00346 
00347 //**************************************************************************
00348 // Python stuff
00349 
00350 // ConsoleSingleton Methods                                             // Methods structure
00351 PyMethodDef ConsoleSingleton::Methods[] = {
00352     {"PrintMessage",         (PyCFunction) ConsoleSingleton::sPyMessage, 1, 
00353      "PrintMessage(string) -- Print a message to the output"},
00354     {"PrintLog",             (PyCFunction) ConsoleSingleton::sPyLog, 1,
00355      "PrintLog(string) -- Print a log message to the output"},
00356     {"PrintError"  ,         (PyCFunction) ConsoleSingleton::sPyError, 1,
00357      "PrintError(string) -- Print an error message to the output"},
00358     {"PrintWarning",         (PyCFunction) ConsoleSingleton::sPyWarning, 1,
00359      "PrintWarning -- Print a warning to the output"},
00360     {"SetStatus",            (PyCFunction) ConsoleSingleton::sPySetStatus, 1,
00361      "Set the status for either Log, Msg, Wrn or Error for an observer"},
00362     {"GetStatus",            (PyCFunction) ConsoleSingleton::sPyGetStatus, 1,
00363      "Get the status for either Log, Msg, Wrn or Error for an observer"},
00364     {NULL, NULL, 0, NULL}               /* Sentinel */
00365 };
00366 
00367 
00368 PyObject *ConsoleSingleton::sPyMessage(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
00369 {
00370     PyObject *output;
00371     if (!PyArg_ParseTuple(args, "O", &output))
00372         return NULL;
00373 
00374     const char* string=0;
00375     PyObject* unicode=0;
00376     if (PyUnicode_Check(output)) {
00377         unicode = PyUnicode_AsEncodedObject(output, "utf-8", "strict");
00378         if (unicode)
00379             string = PyString_AsString(unicode);
00380     }
00381     else if (PyString_Check(output)) {
00382         string = PyString_AsString(output);
00383     }
00384     else {
00385         unicode = PyObject_Str(output);
00386         if (unicode)
00387             string = PyString_AsString(unicode);
00388     }
00389 
00390     PY_TRY {
00391         if (string)
00392             Instance().Message("%s",string);            // process message
00393     } PY_CATCH;
00394 
00395     Py_XDECREF(unicode);
00396 
00397     Py_INCREF(Py_None);
00398     return Py_None;
00399 }
00400 
00401 PyObject *ConsoleSingleton::sPyWarning(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
00402 {
00403     PyObject *output;
00404     if (!PyArg_ParseTuple(args, "O", &output))
00405         return NULL;
00406 
00407     const char* string=0;
00408     PyObject* unicode=0;
00409     if (PyUnicode_Check(output)) {
00410         unicode = PyUnicode_AsEncodedObject(output, "utf-8", "strict");
00411         if (unicode)
00412             string = PyString_AsString(unicode);
00413     }
00414     else if (PyString_Check(output)) {
00415         string = PyString_AsString(output);
00416     }
00417     else {
00418         unicode = PyObject_Str(output);
00419         if (unicode)
00420             string = PyString_AsString(unicode);
00421     }
00422 
00423     PY_TRY {
00424         if (string)
00425             Instance().Warning("%s",string);            // process message
00426     } PY_CATCH;
00427 
00428     Py_XDECREF(unicode);
00429 
00430     Py_INCREF(Py_None);
00431     return Py_None;
00432 }
00433 
00434 PyObject *ConsoleSingleton::sPyError(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
00435 {
00436     PyObject *output;
00437     if (!PyArg_ParseTuple(args, "O", &output))
00438         return NULL;
00439 
00440     const char* string=0;
00441     PyObject* unicode=0;
00442     if (PyUnicode_Check(output)) {
00443         unicode = PyUnicode_AsEncodedObject(output, "utf-8", "strict");
00444         if (unicode)
00445             string = PyString_AsString(unicode);
00446     }
00447     else if (PyString_Check(output)) {
00448         string = PyString_AsString(output);
00449     }
00450     else {
00451         unicode = PyObject_Str(output);
00452         if (unicode)
00453             string = PyString_AsString(unicode);
00454     }
00455 
00456     PY_TRY {
00457         if (string)
00458             Instance().Error("%s",string);            // process message
00459     } PY_CATCH;
00460 
00461     Py_XDECREF(unicode);
00462 
00463     Py_INCREF(Py_None);
00464     return Py_None;
00465 }
00466 
00467 PyObject *ConsoleSingleton::sPyLog(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
00468 {
00469     PyObject *output;
00470     if (!PyArg_ParseTuple(args, "O", &output))
00471         return NULL;
00472 
00473     const char* string=0;
00474     PyObject* unicode=0;
00475     if (PyUnicode_Check(output)) {
00476         unicode = PyUnicode_AsEncodedObject(output, "utf-8", "strict");
00477         if (unicode)
00478             string = PyString_AsString(unicode);
00479     }
00480     else if (PyString_Check(output)) {
00481         string = PyString_AsString(output);
00482     }
00483     else {
00484         unicode = PyObject_Str(output);
00485         if (unicode)
00486             string = PyString_AsString(unicode);
00487     }
00488 
00489     PY_TRY {
00490         if (string)
00491             Instance().Log("%s",string);            // process message
00492     } PY_CATCH;
00493 
00494     Py_XDECREF(unicode);
00495 
00496     Py_INCREF(Py_None);
00497     return Py_None;
00498 }
00499 
00500 PyObject *ConsoleSingleton::sPyGetStatus(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
00501 {
00502     char *pstr1;
00503     char *pstr2;
00504     if (!PyArg_ParseTuple(args, "ss", &pstr1, &pstr2))     // convert args: Python->C 
00505         return NULL;                             // NULL triggers exception 
00506 
00507     PY_TRY{
00508         bool b=false;
00509         ConsoleObserver *pObs = Instance().Get(pstr1);
00510         if(!pObs)
00511         {
00512             Py_INCREF(Py_None);
00513             return Py_None;
00514         }
00515 
00516         if(strcmp(pstr2,"Log") == 0)
00517             b = pObs->bLog;
00518         else if(strcmp(pstr2,"Wrn") == 0)
00519             b = pObs->bWrn;
00520         else if(strcmp(pstr2,"Msg") == 0)
00521             b = pObs->bMsg;
00522         else if(strcmp(pstr2,"Err") == 0)
00523             b = pObs->bErr;
00524         
00525         return Py_BuildValue("i",b?1:0);
00526     }PY_CATCH;
00527 }
00528 
00529 PyObject *ConsoleSingleton::sPySetStatus(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
00530 {
00531     char *pstr1;
00532     char *pstr2;
00533     int  Bool;
00534     if (!PyArg_ParseTuple(args, "ssi", &pstr1, &pstr2,&Bool))   // convert args: Python->C 
00535         return NULL;                                              // NULL triggers exception 
00536 
00537     PY_TRY{
00538         ConsoleObserver *pObs = Instance().Get(pstr1);
00539         if(pObs)
00540         {
00541             if(strcmp(pstr2,"Log") == 0)
00542                 pObs->bLog = (Bool==0)?false:true;                               
00543             else if(strcmp(pstr2,"Wrn") == 0)
00544                 pObs->bWrn = (Bool==0)?false:true;                               
00545             else if(strcmp(pstr2,"Msg") == 0)
00546                 pObs->bMsg = (Bool==0)?false:true;                               
00547             else if(strcmp(pstr2,"Err") == 0)
00548                 pObs->bErr = (Bool==0)?false:true;  
00549             else
00550                 Py_Error(PyExc_Exception,"Unknown Message Type (use Log,Err,Msg or Wrn)");
00551 
00552             Py_INCREF(Py_None);
00553             return Py_None;
00554         } else {
00555             Py_Error(PyExc_Exception,"Unknown Console Type");                     
00556     }
00557 
00558     } PY_CATCH;
00559 }
00560 
00561 //=========================================================================
00562 // some special observers
00563 
00564 ConsoleObserverFile::ConsoleObserverFile(const char *sFileName)
00565   : cFileStream(Base::FileInfo(sFileName)) // can be in UTF8
00566 {
00567     if (!cFileStream.is_open())
00568         Console().Warning("Cannot open log file '%s'.\n", sFileName);
00569     // mark the file as a UTF-8 encoded file
00570     unsigned char bom[3] = {0xef, 0xbb, 0xbf};
00571     cFileStream.write((const char*)bom,3*sizeof(char));
00572 }
00573 
00574 ConsoleObserverFile::~ConsoleObserverFile()
00575 {
00576     cFileStream.close();
00577 }
00578 
00579 void ConsoleObserverFile::Warning(const char *sWarn)
00580 {
00581     cFileStream << "Wrn: " << sWarn;
00582     cFileStream.flush();
00583 }
00584 
00585 void ConsoleObserverFile::Message(const char *sMsg)
00586 {
00587     cFileStream << "Msg: " << sMsg;
00588     cFileStream.flush();
00589 }
00590 
00591 void ConsoleObserverFile::Error  (const char *sErr)
00592 {
00593     cFileStream << "Err: " << sErr;
00594     cFileStream.flush();
00595 }
00596 
00597 void ConsoleObserverFile::Log    (const char *sLog)
00598 {
00599     cFileStream << "Log: " << sLog;
00600     cFileStream.flush();
00601 }
00602 
00603 
00604 ConsoleObserverStd::ConsoleObserverStd()
00605 {
00606     bLog = false;
00607 }
00608 
00609 ConsoleObserverStd::~ConsoleObserverStd()
00610 {
00611 }
00612 
00613 void ConsoleObserverStd::Message(const char *sMsg)
00614 {
00615     printf("%s",sMsg);
00616 }
00617 
00618 void ConsoleObserverStd::Warning(const char *sWarn)
00619 {
00620 #   if defined(FC_OS_WIN32)
00621     ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN| FOREGROUND_BLUE);
00622 #   elif defined(FC_OS_LINUX)
00623     printf("\033[1;33m");
00624 #   endif
00625     printf("%s",sWarn);
00626 #   if defined(FC_OS_WIN32)
00627     ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
00628 #   elif defined(FC_OS_LINUX)
00629     printf("\033[0m");
00630 #   endif
00631 }
00632 
00633 void ConsoleObserverStd::Error  (const char *sErr)
00634 {
00635 #   if defined(FC_OS_WIN32)
00636     ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED|FOREGROUND_INTENSITY );
00637 #   elif defined(FC_OS_LINUX)
00638     printf("\033[1;31m");
00639 #   endif
00640     printf("%s",sErr);
00641 #   if defined(FC_OS_WIN32)
00642     ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
00643 #   elif defined(FC_OS_LINUX)
00644     printf("\033[0m");
00645 #   endif
00646 }
00647 
00648 void ConsoleObserverStd::Log    (const char *sErr)
00649 {
00650 #   if defined(FC_OS_WIN32)
00651     ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED |FOREGROUND_GREEN);
00652 #   elif defined(FC_OS_LINUX)
00653     printf("\033[1;36m");
00654 #   endif
00655     printf("%s",sErr);
00656 #   if defined(FC_OS_WIN32)
00657     ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
00658 #   elif defined(FC_OS_LINUX)
00659     printf("\033[0m");
00660 #   endif
00661 }
00662 
00663 RedirectStdOutput::RedirectStdOutput() 
00664 {
00665     buffer.reserve(80);
00666 }
00667 
00668 int RedirectStdOutput::overflow(int c)
00669 {
00670     if (c != EOF)
00671         buffer.push_back((char)c);
00672     return c;
00673 }
00674 
00675 int RedirectStdOutput::sync()
00676 {
00677     // Print as log as this might be verbose
00678     if (!buffer.empty()) {
00679         Base::Console().Log("%s", buffer.c_str());
00680         buffer.clear();
00681     }
00682     return 0;
00683 }
00684 
00685 RedirectStdLog::RedirectStdLog() 
00686 {
00687     buffer.reserve(80);
00688 }
00689 
00690 int RedirectStdLog::overflow(int c)
00691 {
00692     if (c != EOF)
00693         buffer.push_back((char)c);
00694     return c;
00695 }
00696 
00697 int RedirectStdLog::sync()
00698 {
00699     // Print as log as this might be verbose
00700     if (!buffer.empty()) {
00701         Base::Console().Log("%s", buffer.c_str());
00702         buffer.clear();
00703     }
00704     return 0;
00705 }
00706 
00707 RedirectStdError::RedirectStdError() 
00708 {
00709     buffer.reserve(80);
00710 }
00711 
00712 int RedirectStdError::overflow(int c)
00713 {
00714     if (c != EOF)
00715         buffer.push_back((char)c);
00716     return c;
00717 }
00718 
00719 int RedirectStdError::sync()
00720 {
00721     if (!buffer.empty()) {
00722         Base::Console().Error("%s", buffer.c_str());
00723         buffer.clear();
00724     }
00725     return 0;
00726 }

Generated on Wed Nov 23 19:00:04 2011 for FreeCAD by  doxygen 1.6.1