dmxlog.c revision 706f2543
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