Commit | Line | Data |
---|---|---|
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 | ||
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 | } |