Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / dmxlog.c
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
48 static dmxLogLevel dmxCurrentLogLevel = dmxDebug;
49
50 /** Set the default level for logging to #dmxLogLevel. Returns the
51 * previous log level. */
52 dmxLogLevel
53 dmxSetLogLevel(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. */
64 dmxLogLevel
65 dmxGetLogLevel(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. */
75 void
76 ErrorF(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. */
88 static void
89 VFatalError(const char *format, va_list args) _X_ATTRIBUTE_PRINTF(1, 0) _X_NORETURN;
90 static void
91 VFatalError(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. */
100 void
101 VErrorF(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. */
109 extern void AbortServer(void) _X_NORETURN;
110 static void
111 VFatalError(const char *format, va_list args) _X_ATTRIBUTE_PRINTF(1, 0) _X_NORETURN;
112 static void
113 VFatalError(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. */
122 static void
123 dmxHeader(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. */
169 static void
170 dmxMessage(dmxLogLevel logLevel, const char *format, va_list args) _X_ATTRIBUTE_PRINTF(2, 0);
171 static void
172 dmxMessage(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. */
184 void
185 dmxLog(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. */
196 void
197 dmxLogCont(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. */
210 void
211 dmxLogOutput(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. */
223 void
224 dmxLogOutputCont(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. */
236 void
237 dmxLogOutputWarning(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. */
249 void
250 dmxLogInput(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. */
262 void
263 dmxLogInputCont(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. */
274 void
275 dmxLogArgs(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. */
284 void
285 dmxLogVisual(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. */
331 const char *
332 dmxXInputEventName(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. */
373 const char *
374 dmxEventName(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 }