Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / dmxlog.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright 2001 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28/*
29 * Authors:
30 * Rickard E. (Rik) Faith <faith@redhat.com>
31 *
32 */
33
34/** \file
35 * This file encapsulated all of the logging functions that are used by
36 * DMX for informational, warning, and error messages. */
37
38#ifdef HAVE_DMX_CONFIG_H
39#include <dmx-config.h>
40#endif
41
42#include "dmx.h"
43#include "dmxlog.h"
44#include "dmxinput.h"
45#include <X11/extensions/XI.h>
46#include <X11/extensions/XIproto.h>
47
48static dmxLogLevel dmxCurrentLogLevel = dmxDebug;
49
50/** Set the default level for logging to #dmxLogLevel. Returns the
51 * previous log level. */
52dmxLogLevel
53dmxSetLogLevel(dmxLogLevel newLevel)
54{
55 dmxLogLevel oldLevel = dmxCurrentLogLevel;
56
57 if (newLevel > dmxFatal)
58 newLevel = dmxFatal;
59 dmxCurrentLogLevel = newLevel;
60 return oldLevel;
61}
62
63/** Returns the log level set by #dmxLogLevel. */
64dmxLogLevel
65dmxGetLogLevel(void)
66{
67 return dmxCurrentLogLevel;
68}
69
70#ifdef DMX_LOG_STANDALONE
71/* When using this file as part of a stand-alone (i.e., non-X-Server
72 * program, then the ultimate output routines have to be defined. */
73
74/** Provide an ErrorF function when used stand-alone. */
75void
76ErrorF(const char *format, ...)
77{
78 va_list args;
79
80 va_start(args, format);
81 vfprintf(stderr, format, args); /* RATS: We assume the format string
82 * is trusted, since it is always
83 * from a log message in our code. */
84 va_end(args);
85}
86
87/** Provide an VFatalError function when used stand-alone. */
88static void
89VFatalError(const char *format, va_list args) _X_ATTRIBUTE_PRINTF(1, 0) _X_NORETURN;
90static void
91VFatalError(const char *format, va_list args)
92{
93 vfprintf(stderr, format, args); /* RATS: We assume the format string
94 * is trusted, since it is always
95 * from a log message in our code. */
96 exit(1);
97}
98
99/** Provide an VErrorF function when used stand-alone. */
100void
101VErrorF(const char *format, va_list args)
102{
103 vfprintf(stderr, format, args); /* RATS: We assume the format string
104 * is trusted, since it is always
105 * from a log message in our code. */
106}
107#else
108/** This function was removed between XFree86 4.3.0 and XFree86 4.4.0. */
109extern void AbortServer(void) _X_NORETURN;
110static void
111VFatalError(const char *format, va_list args) _X_ATTRIBUTE_PRINTF(1, 0) _X_NORETURN;
112static void
113VFatalError(const char *format, va_list args)
114{
115 VErrorF(format, args);
116 ErrorF("\n");
117 AbortServer();
118 /*NOTREACHED*/}
119#endif
120
121/* Prints a consistent header for each line. */
122static void
123dmxHeader(dmxLogLevel logLevel, DMXInputInfo * dmxInput,
124 DMXScreenInfo * dmxScreen)
125{
126 const char *type = "??";
127
128 switch (logLevel) {
129 case dmxDebug:
130 type = "..";
131 break;
132 case dmxInfo:
133 type = "II";
134 break;
135 case dmxWarning:
136 type = "**";
137 break;
138 case dmxError:
139 type = "!!";
140 break;
141 case dmxFatal:
142 type = "Fatal Error";
143 break;
144 }
145
146 if (dmxInput && dmxScreen) {
147 ErrorF("(%s) dmx[i%d/%s;o%d/%s]: ", type,
148 dmxInput->inputIdx, dmxInput->name,
149 dmxScreen->index, dmxScreen->name);
150 }
151 else if (dmxScreen) {
152 ErrorF("(%s) dmx[o%d/%s]: ", type, dmxScreen->index, dmxScreen->name);
153 }
154 else if (dmxInput) {
155 const char *pt = strchr(dmxInput->name, ',');
156 int len = (pt ? (size_t) (pt - dmxInput->name)
157 : strlen(dmxInput->name));
158
159 ErrorF("(%s) dmx[i%d/%*.*s]: ", type,
160 dmxInput->inputIdx, len, len, dmxInput->name);
161 }
162 else {
163 ErrorF("(%s) dmx: ", type);
164 }
165}
166
167/* Prints the error message with the appropriate low-level X output
168 * routine. */
169static void
170dmxMessage(dmxLogLevel logLevel, const char *format, va_list args) _X_ATTRIBUTE_PRINTF(2, 0);
171static void
172dmxMessage(dmxLogLevel logLevel, const char *format, va_list args)
173{
174 if (logLevel == dmxFatal || logLevel >= dmxCurrentLogLevel) {
175 if (logLevel == dmxFatal)
176 VFatalError(format, args);
177 else
178 VErrorF(format, args);
179 }
180}
181
182/** Log the specified message at the specified \a logLevel. \a format
183 * can be a printf-like format expression. */
184void
185dmxLog(dmxLogLevel logLevel, const char *format, ...)
186{
187 va_list args;
188
189 dmxHeader(logLevel, NULL, NULL);
190 va_start(args, format);
191 dmxMessage(logLevel, format, args);
192 va_end(args);
193}
194
195/** Continue a log message without printing the message prefix. */
196void
197dmxLogCont(dmxLogLevel logLevel, const char *format, ...)
198{
199 va_list args;
200
201 va_start(args, format);
202 dmxMessage(logLevel, format, args);
203 va_end(args);
204}
205
206#ifndef DMX_LOG_STANDALONE
207/** Log an informational message (at level #dmxInfo) related to ouput.
208 * The message prefix will contain backend information from \a
209 * dmxScreen. */
210void
211dmxLogOutput(DMXScreenInfo * dmxScreen, const char *format, ...)
212{
213 va_list args;
214
215 dmxHeader(dmxInfo, NULL, dmxScreen);
216 va_start(args, format);
217 dmxMessage(dmxInfo, format, args);
218 va_end(args);
219}
220
221/** Continue a message related to output without printing the message
222 * prefix. */
223void
224dmxLogOutputCont(DMXScreenInfo * dmxScreen, const char *format, ...)
225{
226 va_list args;
227
228 va_start(args, format);
229 dmxMessage(dmxInfo, format, args);
230 va_end(args);
231}
232
233/** Log a warning message (at level #dmxWarning) related to output.
234 * The message prefix will contain backend information from \a
235 * dmxScreen. */
236void
237dmxLogOutputWarning(DMXScreenInfo * dmxScreen, const char *format, ...)
238{
239 va_list args;
240
241 dmxHeader(dmxWarning, NULL, dmxScreen);
242 va_start(args, format);
243 dmxMessage(dmxWarning, format, args);
244 va_end(args);
245}
246
247/** Log an informational message (at level #dmxInfo) related to input.
248 * The message prefix will contain information from \a dmxInput. */
249void
250dmxLogInput(DMXInputInfo * dmxInput, const char *format, ...)
251{
252 va_list args;
253
254 dmxHeader(dmxInfo, dmxInput, NULL);
255 va_start(args, format);
256 dmxMessage(dmxInfo, format, args);
257 va_end(args);
258}
259
260/** Continue a message related to input without printing the message
261 * prefix. */
262void
263dmxLogInputCont(DMXInputInfo * dmxInput, const char *format, ...)
264{
265 va_list args;
266
267 va_start(args, format);
268 dmxMessage(dmxInfo, format, args);
269 va_end(args);
270}
271
272/** Print \a argc messages, each describing an element in \a argv. This
273 * is maingly for debugging purposes. */
274void
275dmxLogArgs(dmxLogLevel logLevel, int argc, char **argv)
276{
277 int i;
278
279 for (i = 0; i < argc; i++)
280 dmxLog(logLevel, " Arg[%d] = \"%s\"\n", i, argv[i]);
281}
282
283/** Print messages at level #dmxInfo describing the visuals in \a vi. */
284void
285dmxLogVisual(DMXScreenInfo * dmxScreen, XVisualInfo * vi, int defaultVisual)
286{
287 const char *class = "Unknown";
288
289 switch (vi->class) {
290 case StaticGray:
291 class = "StaticGray ";
292 break;
293 case GrayScale:
294 class = "GrayScale ";
295 break;
296 case StaticColor:
297 class = "StaticColor";
298 break;
299 case PseudoColor:
300 class = "PseudoColor";
301 break;
302 case TrueColor:
303 class = "TrueColor ";
304 break;
305 case DirectColor:
306 class = "DirectColor";
307 break;
308 }
309#define VisualLogFormat "0x%02lx %s %2db %db/rgb %3d 0x%04lx 0x%04lx 0x%04lx%s\n"
310
311 if (dmxScreen) {
312 dmxLogOutput(dmxScreen,
313 VisualLogFormat,
314 vi->visualid, class, vi->depth, vi->bits_per_rgb,
315 vi->colormap_size,
316 vi->red_mask, vi->green_mask, vi->blue_mask,
317 defaultVisual ? " *" : "");
318 }
319 else {
320 dmxLog(dmxInfo,
321 " " VisualLogFormat,
322 vi->visualid, class, vi->depth, vi->bits_per_rgb,
323 vi->colormap_size,
324 vi->red_mask, vi->green_mask, vi->blue_mask,
325 defaultVisual ? " *" : "");
326 }
327}
328
329/** Translate a (normalized) XInput event \a type into a human-readable
330 * string. */
331const char *
332dmxXInputEventName(int type)
333{
334 switch (type) {
335 case XI_DeviceValuator:
336 return "XI_DeviceValuator";
337 case XI_DeviceKeyPress:
338 return "XI_DeviceKeyPress";
339 case XI_DeviceKeyRelease:
340 return "XI_DeviceKeyRelease";
341 case XI_DeviceButtonPress:
342 return "XI_DeviceButtonPress";
343 case XI_DeviceButtonRelease:
344 return "XI_DeviceButtonRelease";
345 case XI_DeviceMotionNotify:
346 return "XI_DeviceMotionNotify";
347 case XI_DeviceFocusIn:
348 return "XI_DeviceFocusIn";
349 case XI_DeviceFocusOut:
350 return "XI_DeviceFocusOut";
351 case XI_ProximityIn:
352 return "XI_ProximityIn";
353 case XI_ProximityOut:
354 return "XI_ProximityOut";
355 case XI_DeviceStateNotify:
356 return "XI_DeviceStateNotify";
357 case XI_DeviceMappingNotify:
358 return "XI_DeviceMappingNotify";
359 case XI_ChangeDeviceNotify:
360 return "XI_ChangeDeviceNotify";
361 case XI_DeviceKeystateNotify:
362 return "XI_DeviceKeystateNotify";
363 case XI_DeviceButtonstateNotify:
364 return "XI_DeviceButtonstateNotify";
365 default:
366 return "unknown";
367 }
368}
369
370#endif
371
372/** Translate an event \a type into a human-readable string. */
373const char *
374dmxEventName(int type)
375{
376 switch (type) {
377 case KeyPress:
378 return "KeyPress";
379 case KeyRelease:
380 return "KeyRelease";
381 case ButtonPress:
382 return "ButtonPress";
383 case ButtonRelease:
384 return "ButtonRelease";
385 case MotionNotify:
386 return "MotionNotify";
387 case EnterNotify:
388 return "EnterNotify";
389 case LeaveNotify:
390 return "LeaveNotify";
391 case FocusIn:
392 return "FocusIn";
393 case FocusOut:
394 return "FocusOut";
395 case KeymapNotify:
396 return "KeymapNotify";
397 case Expose:
398 return "Expose";
399 case GraphicsExpose:
400 return "GraphicsExpose";
401 case NoExpose:
402 return "NoExpose";
403 case VisibilityNotify:
404 return "VisibilityNotify";
405 case CreateNotify:
406 return "CreateNotify";
407 case DestroyNotify:
408 return "DestroyNotify";
409 case UnmapNotify:
410 return "UnmapNotify";
411 case MapNotify:
412 return "MapNotify";
413 case MapRequest:
414 return "MapRequest";
415 case ReparentNotify:
416 return "ReparentNotify";
417 case ConfigureNotify:
418 return "ConfigureNotify";
419 case ConfigureRequest:
420 return "ConfigureRequest";
421 case GravityNotify:
422 return "GravityNotify";
423 case ResizeRequest:
424 return "ResizeRequest";
425 case CirculateNotify:
426 return "CirculateNotify";
427 case CirculateRequest:
428 return "CirculateRequest";
429 case PropertyNotify:
430 return "PropertyNotify";
431 case SelectionClear:
432 return "SelectionClear";
433 case SelectionRequest:
434 return "SelectionRequest";
435 case SelectionNotify:
436 return "SelectionNotify";
437 case ColormapNotify:
438 return "ColormapNotify";
439 case ClientMessage:
440 return "ClientMessage";
441 case MappingNotify:
442 return "MappingNotify";
443 default:
444 return "<unknown>";
445 }
446}