From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/displayer_8cpp-source.html | 733 ++++++++++++++++++++++++++++ 1 file changed, 733 insertions(+) create mode 100644 docs/doxygen/nel/displayer_8cpp-source.html (limited to 'docs/doxygen/nel/displayer_8cpp-source.html') diff --git a/docs/doxygen/nel/displayer_8cpp-source.html b/docs/doxygen/nel/displayer_8cpp-source.html new file mode 100644 index 00000000..04d8f8f2 --- /dev/null +++ b/docs/doxygen/nel/displayer_8cpp-source.html @@ -0,0 +1,733 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

displayer.cpp

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