// Log format in clipboard: "2000/01/15 12:05:30 <LogType> <ProcessName> <FileName> <Line>: <Msg>"
// Log format on the screen: in debug   "<ProcessName> <FileName> <Line>: <Msg>"
//                           in release "<Msg>"
void CMsgBoxDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message)
{
#ifdef NL_OS_WINDOWS

	bool needSpace = false;
//	stringstream ss;
	string str;

	// create the string for the clipboard

	if (args.Date != 0)
	{
		str += dateToHumanString(args.Date);
		needSpace = true;
	}

	if (args.LogType != CLog::LOG_NO)
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		str += logTypeToString(args.LogType);
		needSpace = true;
	}

	if (!args.ProcessName.empty())
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		str += args.ProcessName;
		needSpace = true;
	}

	if (args.FileName != NULL)
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		str += CFile::getFilename(args.FileName);
		needSpace = true;
	}

	if (args.Line != -1)
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString(args.Line);
		needSpace = true;
	}

	if (args.FuncName != NULL)
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		str += args.FuncName;
		needSpace = true;
	}

	if (needSpace) { str += ": "; needSpace = false; }

	str += message;

	CSystemUtils::copyTextToClipboard(str);

	// create the string on the screen
	needSpace = false;
//	stringstream ss2;
	string str2;

#ifdef NL_DEBUG
	if (!args.ProcessName.empty())
	{
		if (needSpace) { str2 += " "; needSpace = false; }
		str2 += args.ProcessName;
		needSpace = true;
	}

	if (args.FileName != NULL)
	{
		if (needSpace) { str2 += " "; needSpace = false; }
		str2 += CFile::getFilename(args.FileName);
		needSpace = true;
	}

	if (args.Line != -1)
	{
		if (needSpace) { str2 += " "; needSpace = false; }
		str2 += NLMISC::toString(args.Line);
		needSpace = true;
	}

	if (args.FuncName != NULL)
	{
		if (needSpace) { str2 += " "; needSpace = false; }
		str2 += args.FuncName;
		needSpace = true;
	}

	if (needSpace) { str2 += ": "; needSpace = false; }

#endif // NL_DEBUG

	str2 += message;
	str2 += "\n\n(this message was copied in the clipboard)";

/*	if (IsDebuggerPresent ())
	{
		// Must break in assert call
		DebugNeedAssert = true;
	}
	else
*/	{

		// Display the report

		string body;

		body += toString(LogTypeToString[2][args.LogType]) + "\n";
		body += "ProcName: " + args.ProcessName + "\n";
		body += "Date: " + string(dateToHumanString(args.Date)) + "\n";
		if(args.FileName == NULL)
			body += "File: <Unknown>\n";
		else
			body += "File: " + string(args.FileName) + "\n";
		body += "Line: " + toString(args.Line) + "\n";
		if (args.FuncName == NULL)
			body += "FuncName: <Unknown>\n";
		else
			body += "FuncName: " + string(args.FuncName) + "\n";
		body += "Reason: " + toString(message);

		body += args.CallstackAndLog;

		string subject;

		// procname is host/service_name-sid we only want the service_name to avoid redondant mail
		string procname;
		string::size_type pos = args.ProcessName.find ("/");
		if (pos == string::npos)
		{
			procname =  args.ProcessName;
		}
		else
		{
			string::size_type pos2 = args.ProcessName.find ("-", pos+1);
			if (pos2 == string::npos)
			{
				procname =  args.ProcessName.substr (pos+1);
			}
			else
			{
				procname =  args.ProcessName.substr (pos+1, pos2-pos-1);
			}
		}

		subject += procname + " NeL " + toString(LogTypeToString[0][args.LogType]) + " " + (args.FileName?string(args.FileName):"") + " " + toString(args.Line) + " " + (args.FuncName?string(args.FuncName):"");

		// Check the envvar NEL_IGNORE_ASSERT
		if (getenv ("NEL_IGNORE_ASSERT") == NULL)
		{
			// yoyo: allow only to send the crash report once. Because users usually click ignore,
			// which create noise into list of bugs (once a player crash, it will surely continues to do it).
			std::string filename = getLogDirectory() + NL_CRASH_DUMP_FILE;

			if  (ReportDebug == report (args.ProcessName + " NeL " + toString(logTypeToString(args.LogType, true)), "", subject, body, true, 2, true, 1, !isCrashAlreadyReported(), IgnoreNextTime, filename.c_str()))
			{
				INelContext::getInstance().setDebugNeedAssert(true);
			}

			// no more sent mail for crash
			setCrashAlreadyReported(true);
		}

/*		// Check the envvar NEL_IGNORE_ASSERT
		if (getenv ("NEL_IGNORE_ASSERT") == NULL)
		{
			// Ask the user to continue, debug or ignore
			int result = MessageBox (NULL, ss2.str().c_str (), logTypeToString(args.LogType, true), MB_ABORTRETRYIGNORE | MB_ICONSTOP);
			if (result == IDABORT)
			{
				// Exit the program now
				exit (EXIT_FAILURE);
			}
			else if (result == IDRETRY)
			{
				// Give the debugger a try
				DebugNeedAssert = true;
 			}
			else if (result == IDIGNORE)
			{
				// Continue, do nothing
			}
		}
*/	}

#endif
}
// Log format: "2000/01/15 12:05:30 <ProcessName> <LogType> <ThreadId> <FileName> <Line> : <Msg>"
void CFileDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message )
{
	bool needSpace = false;
	//stringstream ss;
	string str;

	// if the filename is not set, don't log
	if (_FileName.empty()) return;

	if (args.Date != 0 && !_Raw)
	{
		str += dateToHumanString(args.Date);
		needSpace = true;
	}

	if (args.LogType != CLog::LOG_NO && !_Raw)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += logTypeToString(args.LogType);
		needSpace = true;
	}

	// Write thread identifier
	if ( args.ThreadId != 0 && !_Raw)
	{
		if (needSpace) { str += " "; needSpace = false; }
#ifdef NL_OS_WINDOWS
		str += NLMISC::toString("%4x", args.ThreadId);
#else
		str += NLMISC::toString("%4u", args.ThreadId);
#endif
		needSpace = true;
	}

	if (!args.ProcessName.empty() && !_Raw)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += args.ProcessName;
		needSpace = true;
	}

	if (args.FileName != NULL && !_Raw)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += CFile::getFilename(args.FileName);
		needSpace = true;
	}

	if (args.Line != -1 && !_Raw)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString(args.Line);
		needSpace = true;
	}

	if (args.FuncName != NULL && !_Raw)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += args.FuncName;
		needSpace = true;
	}

	if (needSpace) { str += " : "; needSpace = false; }

	str += message;

	if (_FilePointer > (FILE*)1)
	{
		// if the file is too big (>5mb), rename it and create another one (check only after 20 lines to speed up)
		if (_LastLogSizeChecked++ > 20)
		{
		  int res = ftell (_FilePointer);
		  if (res > 5*1024*1024)
		    {
			fclose (_FilePointer);
			rename (_FileName.c_str(), CFile::findNewFile (_FileName).c_str());
			_FilePointer = (FILE*) 1;
			_LastLogSizeChecked = 0;
		    }
		}
	}

	if (_FilePointer == (FILE*)1)
	{
		_FilePointer = fopen (_FileName.c_str(), "at");
		if (_FilePointer == NULL)
			printf ("Can't open log file '%s': %s\n", _FileName.c_str(), strerror (errno));
	}

	if (_FilePointer != 0)
	{
		if (_NeedHeader)
		{
			const char *hs = HeaderString();
			fwrite (hs, strlen (hs), 1, _FilePointer);
			_NeedHeader = false;
		}

		if(!str.empty())
			fwrite (str.c_str(), str.size(), 1, _FilePointer);

		if(!args.CallstackAndLog.empty())
			fwrite (args.CallstackAndLog.c_str(), args.CallstackAndLog.size (), 1, _FilePointer);

		fflush (_FilePointer);
	}
}
// Log format : "<LogType> <ThreadNo> <FileName> <Line> <ProcessName> : <Msg>"
void CStdDisplayer::doDisplay ( const CLog::TDisplayInfo& args, const char *message )
{
	bool needSpace = false;
	//stringstream ss;
	string str;

	if (args.LogType != CLog::LOG_NO)
	{
		//ss << logTypeToString(args.LogType);
		str += logTypeToString(args.LogType);
		needSpace = true;
	}

	// Write thread identifier
	if ( args.ThreadId != 0 )
	{
		//ss << setw(5) << args.ThreadId;
		if (needSpace) { str += " "; needSpace = false; }
#ifdef NL_OS_WINDOWS
		str += NLMISC::toString("%5x", args.ThreadId);
#else
		str += NLMISC::toString("%08x", args.ThreadId);
#endif
		needSpace = true;
	}

	if (args.FileName != NULL)
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		//ss << CFile::getFilename(args.FileName);
		str += CFile::getFilename(args.FileName);
		needSpace = true;
	}

	if (args.Line != -1)
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		//ss << args.Line;
		str += NLMISC::toString(args.Line);
		needSpace = true;
	}

	if (args.FuncName != NULL)
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		//ss << args.FuncName;
		str += args.FuncName;
		needSpace = true;
	}

	if (!args.ProcessName.empty())
	{
		//if (needSpace) { ss << " "; needSpace = false; }
		if (needSpace) { str += " "; needSpace = false; }
		//ss << args.ProcessName;
		str += args.ProcessName;
		needSpace = true;
	}

	//if (needSpace) { ss << " : "; needSpace = false; }
	if (needSpace) { str += " : "; needSpace = false; }

	//ss << message;
	str += message;

//	string s = ss.str();

	static bool consoleMode = true;

#if defined(NL_OS_WINDOWS)
	static bool consoleModeTest = false;
	if (!consoleModeTest)
	{
		HANDLE handle = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
		consoleMode = handle != INVALID_HANDLE_VALUE;
		if (consoleMode)
			CloseHandle (handle);
		consoleModeTest = true;
	}
#endif // NL_OS_WINDOWS

	// Printf ?
	if (consoleMode)
	{
		// we don't use cout because sometimes, it crashs because cout isn't already init, printf doesn t crash.
		if (!str.empty())
			printf ("%s", str.c_str());

		if (!args.CallstackAndLog.empty())
			printf ("%s", args.CallstackAndLog.c_str());

		fflush(stdout);
	}

#ifdef NL_OS_WINDOWS
	// display the string in the debugger is the application is started with the debugger
	if (IsDebuggerPresent ())
	{
		//stringstream ss2;
		string str2;
		needSpace = false;

		if (args.FileName != NULL) str2 += args.FileName;

		if (args.Line != -1)
		{
			str2 += "(" + NLMISC::toString(args.Line) + ")";
			needSpace = true;
		}

		if (needSpace) { str2 += " : "; needSpace = false; }

		if (args.FuncName != NULL) str2 += string(args.FuncName) + " ";

		if (args.LogType != CLog::LOG_NO)
		{
			str2 += logTypeToString(args.LogType);
			needSpace = true;
		}

		// Write thread identifier
		if ( args.ThreadId != 0 )
		{
			str2 += NLMISC::toString("%5x: ", args.ThreadId);
		}

		str2 += message;

		const sint maxOutString = 2*1024;

		if(str2.size() < maxOutString)
		{
			//////////////////////////////////////////////////////////////////
			// WARNING: READ THIS !!!!!!!!!!!!!!!! ///////////////////////////
			// If at the release time, it freezes here, it's a microsoft bug:
			// http://support.microsoft.com/support/kb/articles/q173/2/60.asp
			OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(str2).c_str());
		}
		else
		{
			/*OutputDebugString(ss2.str().c_str());
			OutputDebugString("\n\t\t\t");
			OutputDebugString("message end: ");
			OutputDebugString(&message[strlen(message) - 1024]);
			OutputDebugString("\n");*/

			sint count = 0;
			uint n = (uint)strlen(message);
			std::string s(&str2.c_str()[0], (str2.size() - n));
			OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str());

			for(;;)
			{

				if((n - count) < maxOutString )
				{
					s = std::string(&message[count], (n - count));
					OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str());
					OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8("\n").c_str());
					break;
				}
				else
				{
					s = std::string(&message[count] , count + maxOutString);
					OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(s).c_str());
					OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8("\n\t\t\t").c_str());
					count += maxOutString;
				}
			}
		}

		// OutputDebugString is a big shit, we can't display big string in one time, we need to split
		uint32 pos = 0;
		string splited;
		for(;;)
		{
			if (pos+1000 < args.CallstackAndLog.size ())
			{
				splited = args.CallstackAndLog.substr (pos, 1000);
				OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(splited).c_str());
				pos += 1000;
			}
			else
			{
				splited = args.CallstackAndLog.substr (pos);
				OutputDebugStringW((LPCWSTR)ucstring::makeFromUtf8(splited).c_str());
				break;
			}
		}
	}
#endif
}
Beispiel #4
0
void CWindowDisplayer::doDisplay (const NLMISC::CLog::TDisplayInfo &args, const char *message)
{
	bool needSpace = false;
	//stringstream ss;
	string str;

	uint32 color = 0xFF000000;

	if (args.LogType != CLog::LOG_NO)
	{
		str += logTypeToString(args.LogType);
		if (args.LogType == CLog::LOG_ERROR || args.LogType == CLog::LOG_ASSERT) color = 0x00FF0000;
		else if (args.LogType == CLog::LOG_WARNING) color = 0x00800000;
		else if (args.LogType == CLog::LOG_DEBUG) color = 0x00808080;
		else color = 0;
		needSpace = true;
	}

	// Write thread identifier
	if ( args.ThreadId != 0 )
	{
		if (needSpace) { str += " "; needSpace = false; }
#ifdef NL_OS_WINDOWS
		str += NLMISC::toString("%4x", args.ThreadId);
#else
		str += NLMISC::toString("%08x", args.ThreadId);
#endif
		needSpace = true;
	}

	if (args.FileName != NULL)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString("%20s", CFile::getFilename(args.FileName).c_str());
		needSpace = true;
	}

	if (args.Line != -1)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString("%4u", args.Line);
		//ss << setw(4) << args.Line;
		needSpace = true;
	}

	if (args.FuncName != NULL)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString("%20s", args.FuncName);
		needSpace = true;
	}

	if (needSpace) { str += ": "; needSpace = false; }

	uint nbl = 1;

	char *npos, *pos = const_cast<char *>(message);
	while ((npos = strchr (pos, '\n')))
	{
		*npos = '\0';
		str += pos;
		if (needSlashR)
			str += "\r";
		str += "\n";
		*npos = '\n';
		pos = npos+1;
		nbl++;
	}
	str += pos;

	pos = const_cast<char *>(args.CallstackAndLog.c_str());
	while ((npos = strchr (pos, '\n')))
	{
		*npos = '\0';
		str += pos;
		if (needSlashR)
			str += "\r";
		str += "\n";
		*npos = '\n';
		pos = npos+1;
		nbl++;
	}
	str += pos;

	{
		CSynchronized<std::list<std::pair<uint32, std::string> > >::CAccessor access (&_Buffer);
		if (_HistorySize > 0 && access.value().size() >= (uint)_HistorySize)
		{
			access.value().erase (access.value().begin());
		}
		access.value().push_back (make_pair (color, str));
	}
}
Beispiel #5
0
void CCommandLog::doDisplay(const CLog::TDisplayInfo& args, const char *message)
{
	switch (args.LogType)
	{
	case CLog::LOG_DEBUG:
		m_DisplayerOutput->setTextColor(Qt::darkGray);
		break;
	case CLog::LOG_STAT:
		m_DisplayerOutput->setTextColor(Qt::darkGreen);
		break;
	case CLog::LOG_NO:
	case CLog::LOG_UNKNOWN:
	case CLog::LOG_INFO:
		m_DisplayerOutput->setTextColor(Qt::black);
		break;
	case CLog::LOG_WARNING:
		m_DisplayerOutput->setTextColor(Qt::darkBlue);
		break;
	case CLog::LOG_ERROR:
	case CLog::LOG_ASSERT:
		m_DisplayerOutput->setTextColor(Qt::darkRed);
		break;
	}

	bool needSpace = false;
	//stringstream ss;
	string str;

	if (args.LogType != CLog::LOG_NO)
	{
		str += logTypeToString(args.LogType);
		needSpace = true;
	}

	// Write thread identifier
	if (args.ThreadId != 0)
	{
		if (needSpace) { str += " "; needSpace = false; }
#ifdef NL_OS_WINDOWS
		str += NLMISC::toString("%4x", args.ThreadId);
#else
		str += NLMISC::toString("%08x", args.ThreadId);
#endif
		needSpace = true;
	}

	if (args.FileName != NULL)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString("%20s", CFile::getFilename(args.FileName).c_str());
		needSpace = true;
	}

	if (args.Line != -1)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString("%4u", args.Line);
		//ss << setw(4) << args.Line;
		needSpace = true;
	}

	if (args.FuncName != NULL)
	{
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString("%20s", args.FuncName);
		needSpace = true;
	}

	if (needSpace) { str += ": "; needSpace = false; }

	uint nbl = 1;

	char *npos, *pos = const_cast<char *>(message);
	while ((npos = strchr (pos, '\n')))
	{
		*npos = '\0';
		str += pos;
		/*if (needSlashR)
			str += "\r";*/
		str += "\n";
		*npos = '\n';
		pos = npos+1;
		nbl++;
	}
	str += pos;

	pos = const_cast<char *>(args.CallstackAndLog.c_str());
	while ((npos = strchr (pos, '\n')))
	{
		*npos = '\0';
		str += pos;
		/*if (needSlashR)
			str += "\r";*/
		str += "\n";
		*npos = '\n';
		pos = npos+1;
		nbl++;
	}
	str += pos;

	m_DisplayerOutput->append(str.substr(0, str.size() - 1).c_str());
}
Beispiel #6
0
	void CQtDisplayer::doDisplay ( const NLMISC::CLog::TDisplayInfo& args, const char *message )
	{
		bool needSpace = false;
		std::string str;

		if(m_DlgDebug==NULL)
			return;

		QTextCharFormat format;

		if (args.Date != 0 && !_Raw) {
			str += dateToHumanString(args.Date);
			needSpace = true;
		}

		if (args.LogType != NLMISC::CLog::LOG_NO && !_Raw) 
		{
			if (needSpace) { str += " "; needSpace = false; }
			str += logTypeToString(args.LogType);
			if (args.LogType == NLMISC::CLog::LOG_WARNING)
				format.setForeground(QBrush(QColor("red")));
			else
				format.setForeground(QBrush(QColor("black")));
			needSpace = true;
		}

		// Write thread identifier
		/*if ( args.ThreadId != 0 && !_Raw) {
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString(args.ThreadId);
		needSpace = true;
		}*/
		/*if (!args.ProcessName.empty() && !_Raw) {
		if (needSpace) { str += " "; needSpace = false; }
		str += args.ProcessName;
		needSpace = true;
		}*/

		//if (args.FileName != NULL && !_Raw) {
		//	if (needSpace) { str += " "; needSpace = false; }
		//	str += NLMISC::CFile::getFilename(args.FileName);
		//	needSpace = true;
		//}

		/*if (args.Line != -1 && !_Raw) {
		if (needSpace) { str += " "; needSpace = false; }
		str += NLMISC::toString(args.Line);
		needSpace = true;
		}*/

		if (args.FuncName != NULL && !_Raw) 
		{
			if (needSpace) 
			{ 
				str += " "; needSpace = false; 
			}
			str += args.FuncName;
			needSpace = true;
		}

		if (needSpace)
		{ 
			str += " : "; needSpace = false; 
		}
		str += message;



		m_DlgDebug->textCursor().insertText(str.c_str(), format);
		//m_DlgDebug->setCenterOnScroll(true);
		m_DlgDebug->centerCursor();
		//m_DlgDebug->ensureCursorVisible();

	}