displayer.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdmisc.h"
00025 
00026 
00027 #ifdef NL_OS_WINDOWS
00028 #   include <io.h>
00029 #   include <fcntl.h>
00030 #   include <sys/types.h>
00031 #   include <sys/stat.h>
00032 #else
00033 #   include <cerrno>
00034 #endif // NL_OS_WINDOWS
00035 
00036 #include <cstdio>
00037 #include <cstdlib>
00038 #include <ctime>
00039 
00040 #include <iostream>
00041 #include <fstream>
00042 //#include <sstream>
00043 #include <iomanip>
00044 
00045 #include "nel/misc/path.h"
00046 #include "nel/misc/mutex.h"
00047 #include "nel/misc/report.h"
00048 
00049 #include "nel/misc/debug.h"
00050 
00051 
00052 #ifdef NL_OS_WINDOWS
00053 // these defines is for IsDebuggerPresent(). it'll not compile on windows 95
00054 // just comment this and the IsDebuggerPresent to compile on windows 95
00055 #   define _WIN32_WINDOWS   0x0410
00056 #   define WINVER           0x0400
00057 #   define NOMINMAX
00058 #   include <windows.h>
00059 #else
00060 #   define IsDebuggerPresent() false
00061 #endif
00062 
00063 #include "nel/misc/displayer.h"
00064 
00065 using namespace std;
00066 
00067 namespace NLMISC
00068 {
00069 
00070 static const char *LogTypeToString[][8] = {
00071     { "", "ERR", "WRN", "INF", "DBG", "STT", "AST", "UKN" },
00072     { "", "Error", "Warning", "Information", "Debug", "Statistic", "Assert", "Unknown" },
00073     { "", "A fatal error occurs. The program must quit", "", "", "", "", "A failed assertion occurs", "" },
00074 };
00075 
00076 const char *IDisplayer::logTypeToString (CLog::TLogType logType, bool longFormat)
00077 {
00078     if (logType < CLog::LOG_NO || logType > CLog::LOG_UNKNOWN)
00079         return "<NotDefined>";
00080 
00081     return LogTypeToString[longFormat?1:0][logType];
00082 }
00083 
00084 const char *IDisplayer::dateToHumanString ()
00085 {
00086     time_t date;
00087     time (&date);
00088     return dateToHumanString (date);
00089 }
00090 
00091 const char *IDisplayer::dateToHumanString (time_t date)
00092 {
00093     static char cstime[25];
00094     struct tm *tms = localtime(&date);
00095     if (tms)
00096         strftime (cstime, 25, "%Y/%m/%d %H:%M:%S", tms);
00097     else
00098         sprintf(cstime, "bad date %d", (uint32)date);
00099     return cstime;
00100 }
00101 
00102 const char *IDisplayer::dateToComputerString (time_t date)
00103 {
00104     static char cstime[25];
00105     smprintf (cstime, 25, "%ld", &date);
00106     return cstime;
00107 }
00108 
00109 const char *IDisplayer::HeaderString ()
00110 {
00111     static char header[1024];
00112     smprintf(header, 1024, "\nLog Starting [%s]\n", dateToHumanString());
00113     return header;
00114 }
00115 
00116 
00117 IDisplayer::IDisplayer(const char *displayerName)
00118 {
00119     _Mutex = new CMutex (string(displayerName)+"DISP");
00120     DisplayerName = displayerName;
00121 }
00122 
00123 IDisplayer::~IDisplayer()
00124 {
00125     delete _Mutex;
00126 }
00127 
00128 /*
00129  * Display the string where it does.
00130  */
00131 void IDisplayer::display ( const CLog::TDisplayInfo& args, const char *message )
00132 {
00133     _Mutex->enter();
00134     try
00135     {
00136         doDisplay( args, message );
00137     }
00138     catch (Exception &)
00139     {
00140         // silence
00141     }
00142     _Mutex->leave();
00143 }
00144 
00145 
00146 // Log format : "<LogType> <ThreadNo> <FileName> <Line> <ProcessName> : <Msg>"
00147 void CStdDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message )
00148 {
00149     bool needSpace = false;
00150     //stringstream ss;
00151     string str;
00152 
00153     if (args.LogType != CLog::LOG_NO)
00154     {
00155         //ss << logTypeToString(args.LogType);
00156         str += logTypeToString(args.LogType);
00157         needSpace = true;
00158     }
00159 
00160     // Write thread identifier
00161     if ( args.ThreadId != 0 )
00162     {
00163         //ss << setw(5) << args.ThreadId;
00164         if (needSpace) { str += " "; needSpace = false; }
00165 #ifdef NL_OS_WINDOWS
00166         str += NLMISC::toString("%5x", args.ThreadId);
00167 #else
00168         str += NLMISC::toString("%08x", args.ThreadId);
00169 #endif
00170         needSpace = true;
00171     }
00172 
00173     if (args.FileName != NULL)
00174     {
00175         //if (needSpace) { ss << " "; needSpace = false; }
00176         if (needSpace) { str += " "; needSpace = false; }
00177         //ss << CFile::getFilename(args.FileName);
00178         str += CFile::getFilename(args.FileName);
00179         needSpace = true;
00180     }
00181 
00182     if (args.Line != -1)
00183     {
00184         //if (needSpace) { ss << " "; needSpace = false; }
00185         if (needSpace) { str += " "; needSpace = false; }
00186         //ss << args.Line;
00187         str += NLMISC::toString(args.Line);
00188         needSpace = true;
00189     }
00190 
00191     if (args.FuncName != NULL)
00192     {
00193         //if (needSpace) { ss << " "; needSpace = false; }
00194         if (needSpace) { str += " "; needSpace = false; }
00195         //ss << args.FuncName;
00196         str += args.FuncName;
00197         needSpace = true;
00198     }
00199 
00200     if (!args.ProcessName.empty())
00201     {
00202         //if (needSpace) { ss << " "; needSpace = false; }
00203         if (needSpace) { str += " "; needSpace = false; }
00204         //ss << args.ProcessName;
00205         str += args.ProcessName;
00206         needSpace = true;
00207     }
00208 
00209     //if (needSpace) { ss << " : "; needSpace = false; }
00210     if (needSpace) { str += " : "; needSpace = false; }
00211 
00212     //ss << message;
00213     str += message;
00214 
00215 //  string s = ss.str();
00216 
00217     static bool consoleMode = true;
00218 
00219 #if defined(NL_OS_WINDOWS)
00220     static bool consoleModeTest = false;
00221     if (!consoleModeTest)
00222     {
00223         HANDLE handle = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
00224         consoleMode = handle != INVALID_HANDLE_VALUE;
00225         if (consoleMode)
00226             CloseHandle (handle);
00227         consoleModeTest = true;
00228     }
00229 #endif // NL_OS_WINDOWS
00230 
00231     // Printf ?
00232     if (consoleMode)
00233     {
00234         // we don't use cout because sometimes, it crashs because cout isn't already init, printf doesn t crash.
00235         if (!str.empty())
00236             printf ("%s", str.c_str());
00237 
00238         if (!args.CallstackAndLog.empty())
00239             printf (args.CallstackAndLog.c_str());
00240 
00241         fflush(stdout);
00242     }
00243 
00244 #ifdef NL_OS_WINDOWS
00245     // display the string in the debugger is the application is started with the debugger
00246     if (IsDebuggerPresent ())
00247     {
00248         //stringstream ss2;
00249         string str2;
00250         needSpace = false;
00251 
00252         if (args.FileName != NULL) str2 += args.FileName;
00253 
00254         if (args.Line != -1)
00255         {
00256             str2 += "(" + NLMISC::toString(args.Line) + ")";
00257             needSpace = true;
00258         }
00259 
00260         if (needSpace) { str2 += " : "; needSpace = false; }
00261 
00262         if (args.FuncName != NULL) str2 += string(args.FuncName) + " ";
00263 
00264         if (args.LogType != CLog::LOG_NO)
00265         {
00266             str2 += logTypeToString(args.LogType);
00267             needSpace = true;
00268         }
00269 
00270         // Write thread identifier
00271         if ( args.ThreadId != 0 )
00272         {
00273             str2 += NLMISC::toString("%5x: ", args.ThreadId);
00274         }
00275 
00276         str2 += message;
00277 
00278         const sint maxOutString = 2*1024;
00279 
00280         if(str2.size() < maxOutString)
00281         {
00283             // WARNING: READ THIS !!!!!!!!!!!!!!!! ///////////////////////////
00284             // If at the release time, it freezes here, it's a microsoft bug:
00285             // http://support.microsoft.com/support/kb/articles/q173/2/60.asp
00286             OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(str2).c_str());
00287         }
00288         else
00289         {
00290             /*OutputDebugString(ss2.str().c_str());
00291             OutputDebugString("\n\t\t\t");
00292             OutputDebugString("message end: ");
00293             OutputDebugString(&message[strlen(message) - 1024]);
00294             OutputDebugString("\n");*/
00295 
00296             sint count = 0;
00297             uint n = strlen(message);
00298             std::string s(&str2.c_str()[0], (str2.size() - n));
00299             OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str());
00300 
00301             for(;;)
00302             {
00303 
00304                 if((n - count) < maxOutString )
00305                 {
00306                     s = std::string(&message[count], (n - count));
00307                     OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str());
00308                     OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8("\n").c_str());
00309                     break;
00310                 }
00311                 else
00312                 {
00313                     s = std::string(&message[count] , count + maxOutString);
00314                     OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str());
00315                     OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8("\n\t\t\t").c_str());
00316                     count += maxOutString;
00317                 }
00318             }
00319         }
00320 
00321         // OutputDebugString is a big shit, we can't display big string in one time, we need to split
00322         uint32 pos = 0;
00323         string splited;
00324         for(;;)
00325         {
00326             if (pos+1000 < args.CallstackAndLog.size ())
00327             {
00328                 splited = args.CallstackAndLog.substr (pos, 1000);
00329                 OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(splited).c_str());
00330                 pos += 1000;
00331             }
00332             else
00333             {
00334                 splited = args.CallstackAndLog.substr (pos);
00335                 OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(splited).c_str());
00336                 break;
00337             }
00338         }
00339     }
00340 #endif
00341 }
00342 
00343 CFileDisplayer::CFileDisplayer (const std::string &filename, bool eraseLastLog, const char *displayerName, bool raw) :
00344     IDisplayer (displayerName), _NeedHeader(true), _LastLogSizeChecked(0), _Raw(raw)
00345 {
00346     _FilePointer = (FILE*)1;
00347     setParam (filename, eraseLastLog);
00348 }
00349 
00350 CFileDisplayer::CFileDisplayer () :
00351     IDisplayer (""), _NeedHeader(true), _LastLogSizeChecked(0), _Raw(false)
00352 {
00353     _FilePointer = (FILE*)1;
00354 }
00355 
00356 CFileDisplayer::~CFileDisplayer ()
00357 {
00358     if (_FilePointer > (FILE*)1)
00359     {
00360         fclose(_FilePointer);
00361         _FilePointer = NULL;
00362     }
00363 }
00364 
00365 void CFileDisplayer::setParam (const std::string &filename, bool eraseLastLog)
00366 {
00367     _FileName = filename;
00368 
00369     if (filename.empty())
00370     {
00371         // can't do nlwarning or infinite recurs
00372         printf ("CFileDisplayer::setParam(): Can't create file with empty filename\n");
00373         return;
00374     }
00375 
00376     if (eraseLastLog)
00377     {
00378 /*      ofstream ofs (filename.c_str(), ios::out | ios::trunc);
00379         if (!ofs.is_open())
00380         {
00381             // can't do nlwarning or infinite recurs
00382             printf ("CFileDisplayer::setParam(): Can't open and clear the log file '%s'\n", filename.c_str());
00383         }*/
00384 
00385         // Erase all the derived log files
00386         int i = 0;
00387         bool fileExist = true;
00388         while (fileExist)
00389         {
00390             string fileToDelete = CFile::getPath (filename) + CFile::getFilenameWithoutExtension (filename) +
00391                 toString ("%03d.", i) + CFile::getExtension (filename);
00392             fileExist = CFile::isExists (fileToDelete);
00393             if (fileExist)
00394                 CFile::deleteFile (fileToDelete);
00395             i++;
00396         }
00397     }
00398 
00399     if (_FilePointer > (FILE*)1)
00400     {
00401         fclose (_FilePointer);
00402         _FilePointer = (FILE*)1;
00403     }
00404 }
00405 
00406 // Log format: "2000/01/15 12:05:30 <ProcessName> <LogType> <ThreadId> <FileName> <Line> : <Msg>"
00407 void CFileDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message )
00408 {
00409     bool needSpace = false;
00410     //stringstream ss;
00411     string str;
00412 
00413     // if the filename is not set, don't log
00414     if (_FileName.empty()) return;
00415 
00416     if (args.Date != 0 && !_Raw)
00417     {
00418         str += dateToHumanString(args.Date);
00419         needSpace = true;
00420     }
00421 
00422     if (args.LogType != CLog::LOG_NO && !_Raw)
00423     {
00424         if (needSpace) { str += " "; needSpace = false; }
00425         str += logTypeToString(args.LogType);
00426         needSpace = true;
00427     }
00428 
00429     // Write thread identifier
00430     if ( args.ThreadId != 0 && !_Raw)
00431     {
00432         if (needSpace) { str += " "; needSpace = false; }
00433 #ifdef NL_OS_WINDOWS
00434         str += NLMISC::toString("%4x", args.ThreadId);
00435 #else
00436         str += NLMISC::toString("%4u", args.ThreadId);
00437 #endif
00438         needSpace = true;
00439     }
00440 
00441     if (!args.ProcessName.empty() && !_Raw)
00442     {
00443         if (needSpace) { str += " "; needSpace = false; }
00444         str += args.ProcessName;
00445         needSpace = true;
00446     }
00447 
00448     if (args.FileName != NULL && !_Raw)
00449     {
00450         if (needSpace) { str += " "; needSpace = false; }
00451         str += CFile::getFilename(args.FileName);
00452         needSpace = true;
00453     }
00454 
00455     if (args.Line != -1 && !_Raw)
00456     {
00457         if (needSpace) { str += " "; needSpace = false; }
00458         str += NLMISC::toString(args.Line);
00459         needSpace = true;
00460     }
00461 
00462     if (args.FuncName != NULL && !_Raw)
00463     {
00464         if (needSpace) { str += " "; needSpace = false; }
00465         str += args.FuncName;
00466         needSpace = true;
00467     }
00468 
00469     if (needSpace) { str += " : "; needSpace = false; }
00470 
00471     str += message;
00472 
00473     if (_FilePointer > (FILE*)1)
00474     {
00475         // if the file is too big (>5mb), rename it and create another one (check only after 20 lines to speed up)
00476         if (_LastLogSizeChecked++ > 20)
00477         {
00478           int res = ftell (_FilePointer);
00479           if (res > 5*1024*1024)
00480             {
00481             fclose (_FilePointer);
00482             rename (_FileName.c_str(), CFile::findNewFile (_FileName).c_str());
00483             _FilePointer = (FILE*) 1;
00484             _LastLogSizeChecked = 0;
00485             }
00486         }
00487     }
00488 
00489     if (_FilePointer == (FILE*)1)
00490     {
00491         _FilePointer = fopen (_FileName.c_str(), "at");
00492         if (_FilePointer == NULL)
00493             printf ("Can't open log file '%s': %s\n", _FileName.c_str(), strerror (errno));
00494     }
00495 
00496     if (_FilePointer != 0)
00497     {
00498         if (_NeedHeader)
00499         {
00500             const char *hs = HeaderString();
00501             fwrite (hs, strlen (hs), 1, _FilePointer);
00502             _NeedHeader = false;
00503         }
00504 
00505         if(!str.empty())
00506             fwrite (str.c_str(), str.size(), 1, _FilePointer);
00507 
00508         if(!args.CallstackAndLog.empty())
00509             fwrite (args.CallstackAndLog.c_str(), args.CallstackAndLog.size (), 1, _FilePointer);
00510 
00511         fflush (_FilePointer);
00512     }
00513 }
00514 
00515 // Log format in clipboard: "2000/01/15 12:05:30 <LogType> <ProcessName> <FileName> <Line>: <Msg>"
00516 // Log format on the screen: in debug   "<ProcessName> <FileName> <Line>: <Msg>"
00517 //                           in release "<Msg>"
00518 void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message)
00519 {
00520 #ifdef NL_OS_WINDOWS
00521 
00522     bool needSpace = false;
00523 //  stringstream ss;
00524     string str;
00525 
00526     // create the string for the clipboard
00527 
00528     if (args.Date != 0)
00529     {
00530         str += dateToHumanString(args.Date);
00531         needSpace = true;
00532     }
00533 
00534     if (args.LogType != CLog::LOG_NO)
00535     {
00536         //if (needSpace) { ss << " "; needSpace = false; }
00537         if (needSpace) { str += " "; needSpace = false; }
00538         str += logTypeToString(args.LogType);
00539         needSpace = true;
00540     }
00541 
00542     if (!args.ProcessName.empty())
00543     {
00544         //if (needSpace) { ss << " "; needSpace = false; }
00545         if (needSpace) { str += " "; needSpace = false; }
00546         str += args.ProcessName;
00547         needSpace = true;
00548     }
00549 
00550     if (args.FileName != NULL)
00551     {
00552         //if (needSpace) { ss << " "; needSpace = false; }
00553         if (needSpace) { str += " "; needSpace = false; }
00554         str += CFile::getFilename(args.FileName);
00555         needSpace = true;
00556     }
00557 
00558     if (args.Line != -1)
00559     {
00560         //if (needSpace) { ss << " "; needSpace = false; }
00561         if (needSpace) { str += " "; needSpace = false; }
00562         str += NLMISC::toString(args.Line);
00563         needSpace = true;
00564     }
00565 
00566     if (args.FuncName != NULL)
00567     {
00568         //if (needSpace) { ss << " "; needSpace = false; }
00569         if (needSpace) { str += " "; needSpace = false; }
00570         str += args.FuncName;
00571         needSpace = true;
00572     }
00573 
00574     if (needSpace) { str += ": "; needSpace = false; }
00575 
00576     str += message;
00577 
00578     if (OpenClipboard (NULL))
00579     {
00580         HGLOBAL mem = GlobalAlloc (GHND|GMEM_DDESHARE, str.size()+1);
00581         if (mem)
00582         {
00583             char *pmem = (char *)GlobalLock (mem);
00584             strcpy (pmem, str.c_str());
00585             GlobalUnlock (mem);
00586             EmptyClipboard ();
00587             SetClipboardData (CF_TEXT, mem);
00588         }
00589         CloseClipboard ();
00590     }
00591 
00592     // create the string on the screen
00593     needSpace = false;
00594 //  stringstream ss2;
00595     string str2;
00596 
00597 #ifdef NL_DEBUG
00598     if (!args.ProcessName.empty())
00599     {
00600         if (needSpace) { str2 += " "; needSpace = false; }
00601         str2 += args.ProcessName;
00602         needSpace = true;
00603     }
00604 
00605     if (args.FileName != NULL)
00606     {
00607         if (needSpace) { str2 += " "; needSpace = false; }
00608         str2 += CFile::getFilename(args.FileName);
00609         needSpace = true;
00610     }
00611 
00612     if (args.Line != -1)
00613     {
00614         if (needSpace) { str2 += " "; needSpace = false; }
00615         str2 += NLMISC::toString(args.Line);
00616         needSpace = true;
00617     }
00618 
00619     if (args.FuncName != NULL)
00620     {
00621         if (needSpace) { str2 += " "; needSpace = false; }
00622         str2 += args.FuncName;
00623         needSpace = true;
00624     }
00625 
00626     if (needSpace) { str2 += ": "; needSpace = false; }
00627 
00628 #endif // NL_DEBUG
00629 
00630     str2 += message;
00631     str2 += "\n\n(this message was copied in the clipboard)";
00632 
00633 /*  if (IsDebuggerPresent ())
00634     {
00635         // Must break in assert call
00636         DebugNeedAssert = true;
00637     }
00638     else
00639 */  {
00640 
00641         // Display the report
00642 
00643         string body;
00644 
00645         body += toString(LogTypeToString[2][args.LogType]) + "\n";
00646         body += "ProcName: " + args.ProcessName + "\n";
00647         body += "Date: " + string(dateToHumanString(args.Date)) + "\n";
00648         if(args.FileName == NULL)
00649             body += "File: <Unknown>\n";
00650         else
00651             body += "File: " + string(args.FileName) + "\n";
00652         body += "Line: " + toString(args.Line) + "\n";
00653         if (args.FuncName == NULL)
00654             body += "FuncName: <Unknown>\n";
00655         else
00656             body += "FuncName: " + string(args.FuncName) + "\n";
00657         body += "Reason: " + toString(message);
00658 
00659         body += args.CallstackAndLog;
00660 
00661         string subject;
00662 
00663         // procname is host/service_name-sid we only want the service_name to avoid redondant mail
00664         string procname;
00665         sint pos = args.ProcessName.find ("/");
00666         if (pos == string::npos)
00667         {
00668             procname =  args.ProcessName;
00669         }
00670         else
00671         {
00672             string::size_type pos2 = args.ProcessName.find ("-", pos+1);
00673             if (pos2 == string::npos)
00674             {
00675                 procname =  args.ProcessName.substr (pos+1);
00676             }
00677             else
00678             {
00679                 procname =  args.ProcessName.substr (pos+1, pos2-pos-1);
00680             }
00681         }
00682 
00683         subject += procname + " NeL " + toString(LogTypeToString[0][args.LogType]) + " " + (args.FileName?string(args.FileName):"") + " " + toString(args.Line) + " " + (args.FuncName?string(args.FuncName):"");
00684 
00685         // Check the envvar NEL_IGNORE_ASSERT
00686         if (getenv ("NEL_IGNORE_ASSERT") == NULL)
00687         {
00688             // yoyo: allow only to send the crash report once. Because users usually click ignore,
00689             // which create noise into list of bugs (once a player crash, it will surely continues to do it).
00690             if  (ReportDebug == report (args.ProcessName + " NeL " + toString(logTypeToString(args.LogType, true)), "", subject, body, true, 2, true, 1, !isCrashAlreadyReported(), IgnoreNextTime, NL_CRASH_DUMP_FILE))
00691             {
00692                 INelContext::getInstance().setDebugNeedAssert(true);
00693             }
00694 
00695             // no more sent mail for crash
00696             setCrashAlreadyReported(true);
00697         }
00698 
00699 /*      // Check the envvar NEL_IGNORE_ASSERT
00700         if (getenv ("NEL_IGNORE_ASSERT") == NULL)
00701         {
00702             // Ask the user to continue, debug or ignore
00703             int result = MessageBox (NULL, ss2.str().c_str (), logTypeToString(args.LogType, true), MB_ABORTRETRYIGNORE | MB_ICONSTOP);
00704             if (result == IDABORT)
00705             {
00706                 // Exit the program now
00707                 exit (EXIT_FAILURE);
00708             }
00709             else if (result == IDRETRY)
00710             {
00711                 // Give the debugger a try
00712                 DebugNeedAssert = true;
00713             }
00714             else if (result == IDIGNORE)
00715             {
00716                 // Continue, do nothing
00717             }
00718         }
00719 */  }
00720 
00721 #endif
00722 }
00723 
00724 
00725 
00726 /***************************************************************/
00727 /******************* THE FOLLOWING CODE IS COMMENTED OUT *******/
00728 /***************************************************************
00729 void CStdDisplayer::display (const std::string& str)
00730 {
00731 //  printf("%s", str.c_str ());
00732     cout << str;
00733 
00734 #ifdef NL_OS_WINDOWS
00735     // display the string in the debugger is the application is started with the debugger
00736     if (IsDebuggerPresent ())
00737         OutputDebugString(str.c_str ());
00738 #endif
00739 }
00740 
00741 
00742 void CFileDisplayer::display (const std::string& str)
00743 {
00744     if (_FileName.size () == 0) return;
00745 
00746     ofstream ofs (_FileName.c_str (), ios::out | ios::app);
00747     if (ofs.is_open ())
00748     {
00749         ofs << str;
00750         ofs.close();
00751     }
00752 
00753 
00754 //  FILE *fp = fopen (_FileName.c_str (), "a");
00755 //  if (fp == NULL) return;
00756 
00757 //  fprintf (fp, "%s", str.c_str ());
00758 
00759 //  fclose (fp);
00760 }
00761 
00762 
00763 
00764 void CMsgBoxDisplayer::display (const std::string& str)
00765 {
00766 #ifdef NL_OS_WINDOWS
00767 
00768     if (OpenClipboard (NULL))
00769     {
00770         HGLOBAL mem = GlobalAlloc (GHND|GMEM_DDESHARE, str.size()+1);
00771         if (mem)
00772         {
00773             char *pmem = (char *)GlobalLock (mem);
00774             strcpy (pmem, str.c_str());
00775             GlobalUnlock (mem);
00776             EmptyClipboard ();
00777             SetClipboardData (CF_TEXT, mem);
00778         }
00779         CloseClipboard ();
00780     }
00781 
00782     string strf = str;
00783     strf += "\n\n(this message was copied in the clipboard)";
00784     MessageBox (NULL, strf.c_str (), "", MB_OK | MB_ICONEXCLAMATION);
00785 #endif
00786 }
00787 **************************************************************************/
00788 
00789 
00790 } // NLMISC

Generated on Thu Jan 7 08:26:33 2010 for NeL by  doxygen 1.6.1