1706f2543Smrg/* 2706f2543Smrg * Copyright 2001 Red Hat Inc., Durham, North Carolina. 3706f2543Smrg * 4706f2543Smrg * All Rights Reserved. 5706f2543Smrg * 6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining 7706f2543Smrg * a copy of this software and associated documentation files (the 8706f2543Smrg * "Software"), to deal in the Software without restriction, including 9706f2543Smrg * without limitation on the rights to use, copy, modify, merge, 10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software, 11706f2543Smrg * and to permit persons to whom the Software is furnished to do so, 12706f2543Smrg * subject to the following conditions: 13706f2543Smrg * 14706f2543Smrg * The above copyright notice and this permission notice (including the 15706f2543Smrg * next paragraph) shall be included in all copies or substantial 16706f2543Smrg * portions of the Software. 17706f2543Smrg * 18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21706f2543Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25706f2543Smrg * SOFTWARE. 26706f2543Smrg */ 27706f2543Smrg 28706f2543Smrg/* 29706f2543Smrg * Authors: 30706f2543Smrg * Rickard E. (Rik) Faith <faith@redhat.com> 31706f2543Smrg * 32706f2543Smrg */ 33706f2543Smrg 34706f2543Smrg/** \file 35706f2543Smrg * This file encapsulated all of the logging functions that are used by 36706f2543Smrg * DMX for informational, warning, and error messages. */ 37706f2543Smrg 38706f2543Smrg#ifdef HAVE_DMX_CONFIG_H 39706f2543Smrg#include <dmx-config.h> 40706f2543Smrg#endif 41706f2543Smrg 42706f2543Smrg#include "dmx.h" 43706f2543Smrg#include "dmxlog.h" 44706f2543Smrg#include "dmxinput.h" 45706f2543Smrg#include <X11/extensions/XI.h> 46706f2543Smrg#include <X11/extensions/XIproto.h> 47706f2543Smrg 48706f2543Smrgstatic dmxLogLevel dmxCurrentLogLevel = dmxDebug; 49706f2543Smrg 50706f2543Smrg/** Set the default level for logging to #dmxLogLevel. Returns the 51706f2543Smrg * previous log level. */ 52706f2543SmrgdmxLogLevel dmxSetLogLevel(dmxLogLevel newLevel) 53706f2543Smrg{ 54706f2543Smrg dmxLogLevel oldLevel = dmxCurrentLogLevel; 55706f2543Smrg if (newLevel > dmxFatal) newLevel = dmxFatal; 56706f2543Smrg dmxCurrentLogLevel = newLevel; 57706f2543Smrg return oldLevel; 58706f2543Smrg} 59706f2543Smrg 60706f2543Smrg/** Returns the log level set by #dmxLogLevel. */ 61706f2543SmrgdmxLogLevel dmxGetLogLevel(void) 62706f2543Smrg{ 63706f2543Smrg return dmxCurrentLogLevel; 64706f2543Smrg} 65706f2543Smrg 66706f2543Smrg#ifdef DMX_LOG_STANDALONE 67706f2543Smrg/* When using this file as part of a stand-alone (i.e., non-X-Server 68706f2543Smrg * program, then the ultimate output routines have to be defined. */ 69706f2543Smrg 70706f2543Smrg/** Provide an ErrorF function when used stand-alone. */ 71706f2543Smrgvoid ErrorF(const char *format, ...) 72706f2543Smrg{ 73706f2543Smrg va_list args; 74706f2543Smrg 75706f2543Smrg va_start(args, format); 76706f2543Smrg vfprintf(stderr, format, args); /* RATS: We assume the format string 77706f2543Smrg * is trusted, since it is always 78706f2543Smrg * from a log message in our code. */ 79706f2543Smrg va_end(args); 80706f2543Smrg} 81706f2543Smrg 82706f2543Smrg/** Provide an VFatalError function when used stand-alone. */ 83706f2543Smrgstatic void VFatalError(const char *format, va_list args) 84706f2543Smrg{ 85706f2543Smrg vfprintf(stderr, format, args); /* RATS: We assume the format string 86706f2543Smrg * is trusted, since it is always 87706f2543Smrg * from a log message in our code. */ 88706f2543Smrg exit(1); 89706f2543Smrg} 90706f2543Smrg 91706f2543Smrg/** Provide an VErrorF function when used stand-alone. */ 92706f2543Smrgvoid VErrorF(const char *format, va_list args) 93706f2543Smrg{ 94706f2543Smrg vfprintf(stderr, format, args); /* RATS: We assume the format string 95706f2543Smrg * is trusted, since it is always 96706f2543Smrg * from a log message in our code. */ 97706f2543Smrg} 98706f2543Smrg#else 99706f2543Smrg/** This function was removed between XFree86 4.3.0 and XFree86 4.4.0. */ 100706f2543Smrgextern void AbortServer(void); 101706f2543Smrgstatic void VFatalError(const char *format, va_list args) 102706f2543Smrg{ 103706f2543Smrg VErrorF(format, args); 104706f2543Smrg ErrorF("\n"); 105706f2543Smrg#ifdef DDXOSFATALERROR 106706f2543Smrg OsVendorFatalError(); 107706f2543Smrg#endif 108706f2543Smrg AbortServer(); 109706f2543Smrg /*NOTREACHED*/ 110706f2543Smrg} 111706f2543Smrg#endif 112706f2543Smrg 113706f2543Smrg/* Prints a consistent header for each line. */ 114706f2543Smrgstatic void dmxHeader(dmxLogLevel logLevel, DMXInputInfo *dmxInput, 115706f2543Smrg DMXScreenInfo *dmxScreen) 116706f2543Smrg{ 117706f2543Smrg const char *type = "??"; 118706f2543Smrg 119706f2543Smrg switch (logLevel) { 120706f2543Smrg case dmxDebug: type = ".."; break; 121706f2543Smrg case dmxInfo: type = "II"; break; 122706f2543Smrg case dmxWarning: type = "**"; break; 123706f2543Smrg case dmxError: type = "!!"; break; 124706f2543Smrg case dmxFatal: type = "Fatal Error"; break; 125706f2543Smrg } 126706f2543Smrg 127706f2543Smrg if (dmxInput && dmxScreen) { 128706f2543Smrg ErrorF("(%s) dmx[i%d/%s;o%d/%s]: ", type, 129706f2543Smrg dmxInput->inputIdx, dmxInput->name, 130706f2543Smrg dmxScreen->index, dmxScreen->name); 131706f2543Smrg } else if (dmxScreen) { 132706f2543Smrg ErrorF("(%s) dmx[o%d/%s]: ", type, 133706f2543Smrg dmxScreen->index, dmxScreen->name); 134706f2543Smrg } else if (dmxInput) { 135706f2543Smrg const char *pt = strchr(dmxInput->name, ','); 136706f2543Smrg int len = (pt 137706f2543Smrg ? (size_t)(pt-dmxInput->name) 138706f2543Smrg : strlen(dmxInput->name)); 139706f2543Smrg 140706f2543Smrg ErrorF("(%s) dmx[i%d/%*.*s]: ", type, 141706f2543Smrg dmxInput->inputIdx, len, len, dmxInput->name); 142706f2543Smrg } else { 143706f2543Smrg ErrorF("(%s) dmx: ", type); 144706f2543Smrg } 145706f2543Smrg} 146706f2543Smrg 147706f2543Smrg/* Prints the error message with the appropriate low-level X output 148706f2543Smrg * routine. */ 149706f2543Smrgstatic void dmxMessage(dmxLogLevel logLevel, const char *format, va_list args) 150706f2543Smrg{ 151706f2543Smrg if (logLevel == dmxFatal || logLevel >= dmxCurrentLogLevel) { 152706f2543Smrg if (logLevel == dmxFatal) VFatalError(format, args); 153706f2543Smrg else VErrorF(format, args); 154706f2543Smrg } 155706f2543Smrg} 156706f2543Smrg 157706f2543Smrg/** Log the specified message at the specified \a logLevel. \a format 158706f2543Smrg * can be a printf-like format expression. */ 159706f2543Smrgvoid dmxLog(dmxLogLevel logLevel, const char *format, ...) 160706f2543Smrg{ 161706f2543Smrg va_list args; 162706f2543Smrg 163706f2543Smrg dmxHeader(logLevel, NULL, NULL); 164706f2543Smrg va_start(args, format); 165706f2543Smrg dmxMessage(logLevel, format, args); 166706f2543Smrg va_end(args); 167706f2543Smrg} 168706f2543Smrg 169706f2543Smrg/** Continue a log message without printing the message prefix. */ 170706f2543Smrgvoid dmxLogCont(dmxLogLevel logLevel, const char *format, ...) 171706f2543Smrg{ 172706f2543Smrg va_list args; 173706f2543Smrg 174706f2543Smrg va_start(args, format); 175706f2543Smrg dmxMessage(logLevel, format, args); 176706f2543Smrg va_end(args); 177706f2543Smrg} 178706f2543Smrg 179706f2543Smrg#ifndef DMX_LOG_STANDALONE 180706f2543Smrg/** Log an informational message (at level #dmxInfo) related to ouput. 181706f2543Smrg * The message prefix will contain backend information from \a 182706f2543Smrg * dmxScreen. */ 183706f2543Smrgvoid dmxLogOutput(DMXScreenInfo *dmxScreen, const char *format, ...) 184706f2543Smrg{ 185706f2543Smrg va_list args; 186706f2543Smrg 187706f2543Smrg dmxHeader(dmxInfo, NULL, dmxScreen); 188706f2543Smrg va_start(args, format); 189706f2543Smrg dmxMessage(dmxInfo, format, args); 190706f2543Smrg va_end(args); 191706f2543Smrg} 192706f2543Smrg 193706f2543Smrg/** Continue a message related to output without printing the message 194706f2543Smrg * prefix. */ 195706f2543Smrgvoid dmxLogOutputCont(DMXScreenInfo *dmxScreen, const char *format, ...) 196706f2543Smrg{ 197706f2543Smrg va_list args; 198706f2543Smrg 199706f2543Smrg va_start(args, format); 200706f2543Smrg dmxMessage(dmxInfo, format, args); 201706f2543Smrg va_end(args); 202706f2543Smrg} 203706f2543Smrg 204706f2543Smrg/** Log a warning message (at level #dmxWarning) related to output. 205706f2543Smrg * The message prefix will contain backend information from \a 206706f2543Smrg * dmxScreen. */ 207706f2543Smrgvoid dmxLogOutputWarning(DMXScreenInfo *dmxScreen, const char *format, ...) 208706f2543Smrg{ 209706f2543Smrg va_list args; 210706f2543Smrg 211706f2543Smrg dmxHeader(dmxWarning, NULL, dmxScreen); 212706f2543Smrg va_start(args, format); 213706f2543Smrg dmxMessage(dmxWarning, format, args); 214706f2543Smrg va_end(args); 215706f2543Smrg} 216706f2543Smrg 217706f2543Smrg/** Log an informational message (at level #dmxInfo) related to input. 218706f2543Smrg * The message prefix will contain information from \a dmxInput. */ 219706f2543Smrgvoid dmxLogInput(DMXInputInfo *dmxInput, const char *format, ...) 220706f2543Smrg{ 221706f2543Smrg va_list args; 222706f2543Smrg 223706f2543Smrg dmxHeader(dmxInfo, dmxInput, NULL); 224706f2543Smrg va_start(args, format); 225706f2543Smrg dmxMessage(dmxInfo, format, args); 226706f2543Smrg va_end(args); 227706f2543Smrg} 228706f2543Smrg 229706f2543Smrg/** Continue a message related to input without printing the message 230706f2543Smrg * prefix. */ 231706f2543Smrgvoid dmxLogInputCont(DMXInputInfo *dmxInput, const char *format, ...) 232706f2543Smrg{ 233706f2543Smrg va_list args; 234706f2543Smrg 235706f2543Smrg va_start(args, format); 236706f2543Smrg dmxMessage(dmxInfo, format, args); 237706f2543Smrg va_end(args); 238706f2543Smrg} 239706f2543Smrg 240706f2543Smrg/** Print \a argc messages, each describing an element in \a argv. This 241706f2543Smrg * is maingly for debugging purposes. */ 242706f2543Smrgvoid dmxLogArgs(dmxLogLevel logLevel, int argc, char **argv) 243706f2543Smrg{ 244706f2543Smrg int i; 245706f2543Smrg for (i = 0; i < argc; i++) 246706f2543Smrg dmxLog(logLevel, " Arg[%d] = \"%s\"\n", i, argv[i]); 247706f2543Smrg} 248706f2543Smrg 249706f2543Smrg/** Print messages at level #dmxInfo describing the visuals in \a vi. */ 250706f2543Smrgvoid dmxLogVisual(DMXScreenInfo *dmxScreen, XVisualInfo *vi, int defaultVisual) 251706f2543Smrg{ 252706f2543Smrg const char *class = "Unknown"; 253706f2543Smrg 254706f2543Smrg switch (vi->class) { 255706f2543Smrg case StaticGray: class = "StaticGray "; break; 256706f2543Smrg case GrayScale: class = "GrayScale "; break; 257706f2543Smrg case StaticColor: class = "StaticColor"; break; 258706f2543Smrg case PseudoColor: class = "PseudoColor"; break; 259706f2543Smrg case TrueColor: class = "TrueColor "; break; 260706f2543Smrg case DirectColor: class = "DirectColor"; break; 261706f2543Smrg } 262706f2543Smrg 263706f2543Smrg if (dmxScreen) { 264706f2543Smrg dmxLogOutput(dmxScreen, 265706f2543Smrg "0x%02x %s %2db %db/rgb %3d 0x%04x 0x%04x 0x%04x%s\n", 266706f2543Smrg vi->visualid, class, vi->depth, vi->bits_per_rgb, 267706f2543Smrg vi->colormap_size, 268706f2543Smrg vi->red_mask, vi->green_mask, vi->blue_mask, 269706f2543Smrg defaultVisual ? " *" : ""); 270706f2543Smrg } else { 271706f2543Smrg dmxLog(dmxInfo, 272706f2543Smrg " 0x%02x %s %2db %db/rgb %3d 0x%04x 0x%04x 0x%04x%s\n", 273706f2543Smrg vi->visualid, class, vi->depth, vi->bits_per_rgb, 274706f2543Smrg vi->colormap_size, 275706f2543Smrg vi->red_mask, vi->green_mask, vi->blue_mask, 276706f2543Smrg defaultVisual ? " *" : ""); 277706f2543Smrg } 278706f2543Smrg} 279706f2543Smrg 280706f2543Smrg/** Translate a (normalized) XInput event \a type into a human-readable 281706f2543Smrg * string. */ 282706f2543Smrgconst char *dmxXInputEventName(int type) 283706f2543Smrg{ 284706f2543Smrg switch (type) { 285706f2543Smrg case XI_DeviceValuator: return "XI_DeviceValuator"; 286706f2543Smrg case XI_DeviceKeyPress: return "XI_DeviceKeyPress"; 287706f2543Smrg case XI_DeviceKeyRelease: return "XI_DeviceKeyRelease"; 288706f2543Smrg case XI_DeviceButtonPress: return "XI_DeviceButtonPress"; 289706f2543Smrg case XI_DeviceButtonRelease: return "XI_DeviceButtonRelease"; 290706f2543Smrg case XI_DeviceMotionNotify: return "XI_DeviceMotionNotify"; 291706f2543Smrg case XI_DeviceFocusIn: return "XI_DeviceFocusIn"; 292706f2543Smrg case XI_DeviceFocusOut: return "XI_DeviceFocusOut"; 293706f2543Smrg case XI_ProximityIn: return "XI_ProximityIn"; 294706f2543Smrg case XI_ProximityOut: return "XI_ProximityOut"; 295706f2543Smrg case XI_DeviceStateNotify: return "XI_DeviceStateNotify"; 296706f2543Smrg case XI_DeviceMappingNotify: return "XI_DeviceMappingNotify"; 297706f2543Smrg case XI_ChangeDeviceNotify: return "XI_ChangeDeviceNotify"; 298706f2543Smrg case XI_DeviceKeystateNotify: return "XI_DeviceKeystateNotify"; 299706f2543Smrg case XI_DeviceButtonstateNotify: return "XI_DeviceButtonstateNotify"; 300706f2543Smrg default: return "unknown"; 301706f2543Smrg } 302706f2543Smrg} 303706f2543Smrg 304706f2543Smrg#endif 305706f2543Smrg 306706f2543Smrg/** Translate an event \a type into a human-readable string. */ 307706f2543Smrgconst char *dmxEventName(int type) 308706f2543Smrg{ 309706f2543Smrg switch (type) { 310706f2543Smrg case KeyPress: return "KeyPress"; 311706f2543Smrg case KeyRelease: return "KeyRelease"; 312706f2543Smrg case ButtonPress: return "ButtonPress"; 313706f2543Smrg case ButtonRelease: return "ButtonRelease"; 314706f2543Smrg case MotionNotify: return "MotionNotify"; 315706f2543Smrg case EnterNotify: return "EnterNotify"; 316706f2543Smrg case LeaveNotify: return "LeaveNotify"; 317706f2543Smrg case FocusIn: return "FocusIn"; 318706f2543Smrg case FocusOut: return "FocusOut"; 319706f2543Smrg case KeymapNotify: return "KeymapNotify"; 320706f2543Smrg case Expose: return "Expose"; 321706f2543Smrg case GraphicsExpose: return "GraphicsExpose"; 322706f2543Smrg case NoExpose: return "NoExpose"; 323706f2543Smrg case VisibilityNotify: return "VisibilityNotify"; 324706f2543Smrg case CreateNotify: return "CreateNotify"; 325706f2543Smrg case DestroyNotify: return "DestroyNotify"; 326706f2543Smrg case UnmapNotify: return "UnmapNotify"; 327706f2543Smrg case MapNotify: return "MapNotify"; 328706f2543Smrg case MapRequest: return "MapRequest"; 329706f2543Smrg case ReparentNotify: return "ReparentNotify"; 330706f2543Smrg case ConfigureNotify: return "ConfigureNotify"; 331706f2543Smrg case ConfigureRequest: return "ConfigureRequest"; 332706f2543Smrg case GravityNotify: return "GravityNotify"; 333706f2543Smrg case ResizeRequest: return "ResizeRequest"; 334706f2543Smrg case CirculateNotify: return "CirculateNotify"; 335706f2543Smrg case CirculateRequest: return "CirculateRequest"; 336706f2543Smrg case PropertyNotify: return "PropertyNotify"; 337706f2543Smrg case SelectionClear: return "SelectionClear"; 338706f2543Smrg case SelectionRequest: return "SelectionRequest"; 339706f2543Smrg case SelectionNotify: return "SelectionNotify"; 340706f2543Smrg case ColormapNotify: return "ColormapNotify"; 341706f2543Smrg case ClientMessage: return "ClientMessage"; 342706f2543Smrg case MappingNotify: return "MappingNotify"; 343706f2543Smrg default: return "<unknown>"; 344706f2543Smrg } 345706f2543Smrg} 346706f2543Smrg 347