mirror of
https://github.com/debauchee/barrier.git
synced 2026-02-08 04:45:03 +08:00
CServer to the primary screen when the configuration changes so it can make necessary adjustments (the win32 primary screen must tell the hook dll about the new jump zones). changed includes of some std c++ library files to go through our own include files. these wrap the include with stuff to keep vc++ quiet when compiling at warning level 4, which is what it does now. it also works around missing <istream> and <ostream> on g++2.96. added missing std:: where necessary. g++ doesn't really support namespaces so it lets references without the namespace slip through. added workaround or fix. not sure if istringstream::str(string) should reset eofbit. it does on g++ but does not on vc++. added clear() after str() so it works either way. added low-level keyboard hook to win32. if available (it's only available on NT SP3 and up) it allows us to catch and handle alt+tab, alt+esc, ctrl+esc, and windows key hot keys. i think that leaves only ctrl+alt+del and accessibility functions uncaught on those systems.
284 lines
6.3 KiB
C++
284 lines
6.3 KiB
C++
#include "CLog.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#if defined(CONFIG_PLATFORM_WIN32)
|
|
#include <windows.h>
|
|
#define vsnprintf _vsnprintf
|
|
#endif
|
|
|
|
static const char* g_priority[] = {
|
|
"FATAL",
|
|
"ERROR",
|
|
"WARNING",
|
|
"NOTE",
|
|
"INFO",
|
|
"DEBUG",
|
|
"DEBUG1",
|
|
"DEBUG2"
|
|
};
|
|
static const int g_numPriority = (int)(sizeof(g_priority) /
|
|
sizeof(g_priority[0]));
|
|
#if defined(NDEBUG)
|
|
static const int g_defaultMaxPriority = 4;
|
|
#else
|
|
static const int g_defaultMaxPriority = 5;
|
|
#endif
|
|
static const int g_maxPriorityLength = 7; // length of longest string
|
|
static const int g_prioritySuffixLength = 2;
|
|
static const int g_priorityPad = g_maxPriorityLength +
|
|
g_prioritySuffixLength;
|
|
static const int g_newlineLength = 2;
|
|
|
|
//
|
|
// CLog
|
|
//
|
|
|
|
CLog::Outputter CLog::s_outputter = NULL;
|
|
CLog::Lock CLog::s_lock = &CLog::dummyLock;
|
|
int CLog::s_maxPriority = -1;
|
|
|
|
void CLog::print(const char* fmt, ...)
|
|
{
|
|
// check if fmt begins with a priority argument
|
|
int priority = 4;
|
|
if (fmt[0] == '%' && fmt[1] == 'z') {
|
|
priority = fmt[2] - '\060';
|
|
fmt += 3;
|
|
}
|
|
|
|
// compute prefix padding length
|
|
int pad = g_priorityPad;
|
|
|
|
// print to buffer
|
|
char stack[1024];
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
char* buffer = vsprint(pad, stack,
|
|
sizeof(stack) / sizeof(stack[0]), fmt, args);
|
|
va_end(args);
|
|
|
|
// output buffer
|
|
output(priority, buffer);
|
|
|
|
// clean up
|
|
if (buffer != stack)
|
|
delete[] buffer;
|
|
}
|
|
|
|
void CLog::printt(const char* file, int line,
|
|
const char* fmt, ...)
|
|
{
|
|
// check if fmt begins with a priority argument
|
|
int priority = 4;
|
|
if (fmt[0] == '%' && fmt[1] == 'z') {
|
|
priority = fmt[2] - '\060';
|
|
fmt += 3;
|
|
}
|
|
|
|
// compute prefix padding length
|
|
char stack[1024];
|
|
sprintf(stack, "%d", line);
|
|
int pad = strlen(file) + 1 /* comma */ +
|
|
strlen(stack) + 1 /* colon */ + 1 /* space */ +
|
|
g_priorityPad;
|
|
|
|
// print to buffer, leaving space for a newline at the end
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
char* buffer = vsprint(pad, stack,
|
|
sizeof(stack) / sizeof(stack[0]), fmt, args);
|
|
va_end(args);
|
|
|
|
// print the prefix to the buffer. leave space for priority label.
|
|
sprintf(buffer + g_priorityPad, "%s,%d:", file, line);
|
|
buffer[pad - 1] = ' ';
|
|
|
|
// output buffer
|
|
output(priority, buffer);
|
|
|
|
// clean up
|
|
if (buffer != stack)
|
|
delete[] buffer;
|
|
}
|
|
|
|
void CLog::setOutputter(Outputter outputter)
|
|
{
|
|
CHoldLock lock(s_lock);
|
|
s_outputter = outputter;
|
|
}
|
|
|
|
CLog::Outputter CLog::getOutputter()
|
|
{
|
|
CHoldLock lock(s_lock);
|
|
return s_outputter;
|
|
}
|
|
|
|
void CLog::setLock(Lock newLock)
|
|
{
|
|
CHoldLock lock(s_lock);
|
|
s_lock = (newLock == NULL) ? dummyLock : newLock;
|
|
}
|
|
|
|
CLog::Lock CLog::getLock()
|
|
{
|
|
CHoldLock lock(s_lock);
|
|
return (s_lock == dummyLock) ? NULL : s_lock;
|
|
}
|
|
|
|
void CLog::setFilter(int maxPriority)
|
|
{
|
|
CHoldLock lock(s_lock);
|
|
s_maxPriority = maxPriority;
|
|
}
|
|
|
|
int CLog::getFilter()
|
|
{
|
|
CHoldLock lock(s_lock);
|
|
return getMaxPriority();
|
|
}
|
|
|
|
void CLog::dummyLock(bool)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
int CLog::getMaxPriority()
|
|
{
|
|
CHoldLock lock(s_lock);
|
|
|
|
if (s_maxPriority == -1) {
|
|
s_maxPriority = g_defaultMaxPriority;
|
|
const char* priEnv = getenv("SYN_LOG_PRI");
|
|
if (priEnv != NULL) {
|
|
for (int i = 0; i < g_numPriority; ++i) {
|
|
if (strcmp(priEnv, g_priority[i]) == 0) {
|
|
s_maxPriority = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return s_maxPriority;
|
|
}
|
|
|
|
void CLog::output(int priority, char* msg)
|
|
{
|
|
assert(priority >= 0 && priority < g_numPriority);
|
|
assert(msg != 0);
|
|
|
|
if (priority <= getMaxPriority()) {
|
|
// insert priority label
|
|
int n = strlen(g_priority[priority]);
|
|
sprintf(msg + g_maxPriorityLength - n, "%s:", g_priority[priority]);
|
|
msg[g_maxPriorityLength + 1] = ' ';
|
|
|
|
// put a newline at the end
|
|
#if defined(CONFIG_PLATFORM_WIN32)
|
|
strcat(msg + g_priorityPad, "\r\n");
|
|
#else
|
|
strcat(msg + g_priorityPad, "\n");
|
|
#endif
|
|
|
|
// print it
|
|
CHoldLock lock(s_lock);
|
|
if (s_outputter) {
|
|
s_outputter(msg + g_maxPriorityLength - n);
|
|
}
|
|
else {
|
|
#if defined(CONFIG_PLATFORM_WIN32)
|
|
openConsole();
|
|
#endif
|
|
fprintf(stderr, "%s", msg + g_maxPriorityLength - n);
|
|
}
|
|
}
|
|
}
|
|
|
|
char* CLog::vsprint(int pad, char* buffer, int len,
|
|
const char* fmt, va_list args)
|
|
{
|
|
assert(len > 0);
|
|
|
|
// try writing to input buffer
|
|
int n;
|
|
if (len >= pad) {
|
|
n = vsnprintf(buffer + pad, len - pad, fmt, args);
|
|
if (n != -1 && n <= len - pad + g_newlineLength)
|
|
return buffer;
|
|
}
|
|
|
|
// start allocating buffers until we write the whole string
|
|
buffer = 0;
|
|
do {
|
|
delete[] buffer;
|
|
len *= 2;
|
|
buffer = new char[len + pad];
|
|
n = vsnprintf(buffer + pad, len - pad, fmt, args);
|
|
} while (n == -1 || n > len - pad + g_newlineLength);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
#if defined(CONFIG_PLATFORM_WIN32)
|
|
|
|
static DWORD s_thread = 0;
|
|
|
|
static BOOL WINAPI CLogSignalHandler(DWORD)
|
|
{
|
|
// terminate cleanly and skip remaining handlers
|
|
PostThreadMessage(s_thread, WM_QUIT, 0, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
void CLog::openConsole()
|
|
{
|
|
static bool s_hasConsole = false;
|
|
|
|
// ignore if already created
|
|
if (s_hasConsole)
|
|
return;
|
|
|
|
// remember the current thread. when we get a ctrl+break or the
|
|
// console is closed we'll post WM_QUIT to this thread to shutdown
|
|
// cleanly.
|
|
// note -- win95/98/me are broken and will not receive a signal
|
|
// when the console is closed nor during logoff or shutdown,
|
|
// see microsoft articles Q130717 and Q134284. we could work
|
|
// around this in a painful way using hooks and hidden windows
|
|
// (as apache does) but it's not worth it. the app will still
|
|
// quit, just not cleanly. users in-the-know can use ctrl+c.
|
|
s_thread = GetCurrentThreadId();
|
|
|
|
// open a console
|
|
if (!AllocConsole())
|
|
return;
|
|
|
|
// get the handle for error output
|
|
HANDLE herr = GetStdHandle(STD_ERROR_HANDLE);
|
|
|
|
// prep console. windows 95 and its ilk have braindead
|
|
// consoles that can't even resize independently of the
|
|
// buffer size. use a 25 line buffer for those systems.
|
|
OSVERSIONINFO osInfo;
|
|
COORD size = { 80, 1000 };
|
|
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
|
|
if (GetVersionEx(&osInfo) &&
|
|
osInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
|
size.Y = 25;
|
|
SetConsoleScreenBufferSize(herr, size);
|
|
SetConsoleTextAttribute(herr,
|
|
FOREGROUND_RED |
|
|
FOREGROUND_GREEN |
|
|
FOREGROUND_BLUE);
|
|
SetConsoleCtrlHandler(CLogSignalHandler, TRUE);
|
|
|
|
// reopen stderr to point at console
|
|
freopen("con", "w", stderr);
|
|
s_hasConsole = true;
|
|
}
|
|
|
|
#endif
|