Home | History | Annotate | Line # | Download | only in dmx
      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 (at) 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 dmxSetLogLevel(dmxLogLevel newLevel)
     53 {
     54     dmxLogLevel oldLevel = dmxCurrentLogLevel;
     55     if (newLevel > dmxFatal) newLevel = dmxFatal;
     56     dmxCurrentLogLevel = newLevel;
     57     return oldLevel;
     58 }
     59 
     60 /** Returns the log level set by #dmxLogLevel. */
     61 dmxLogLevel dmxGetLogLevel(void)
     62 {
     63     return dmxCurrentLogLevel;
     64 }
     65 
     66 #ifdef DMX_LOG_STANDALONE
     67 /* When using this file as part of a stand-alone (i.e., non-X-Server
     68  * program, then the ultimate output routines have to be defined.  */
     69 
     70 /** Provide an ErrorF function when used stand-alone. */
     71 void ErrorF(const char *format, ...)
     72 {
     73     va_list args;
     74 
     75     va_start(args, format);
     76     vfprintf(stderr, format, args); /* RATS: We assume the format string
     77                                      * is trusted, since it is always
     78                                      * from a log message in our code. */
     79     va_end(args);
     80 }
     81 
     82 /** Provide an VFatalError function when used stand-alone. */
     83 static void VFatalError(const char *format, va_list args)
     84 {
     85     vfprintf(stderr, format, args); /* RATS: We assume the format string
     86                                      * is trusted, since it is always
     87                                      * from a log message in our code. */
     88     exit(1);
     89 }
     90 
     91 /** Provide an VErrorF function when used stand-alone. */
     92 void VErrorF(const char *format, va_list args)
     93 {
     94     vfprintf(stderr, format, args); /* RATS: We assume the format string
     95                                      * is trusted, since it is always
     96                                      * from a log message in our code. */
     97 }
     98 #else
     99 /** This function was removed between XFree86 4.3.0 and XFree86 4.4.0. */
    100 extern void AbortServer(void);
    101 static void VFatalError(const char *format, va_list args)
    102 {
    103     VErrorF(format, args);
    104     ErrorF("\n");
    105 #ifdef DDXOSFATALERROR
    106     OsVendorFatalError();
    107 #endif
    108     AbortServer();
    109     /*NOTREACHED*/
    110 }
    111 #endif
    112 
    113 /* Prints a consistent header for each line. */
    114 static void dmxHeader(dmxLogLevel logLevel, DMXInputInfo *dmxInput,
    115                       DMXScreenInfo *dmxScreen)
    116 {
    117     const char *type = "??";
    118 
    119     switch (logLevel) {
    120     case dmxDebug:   type = ".."; break;
    121     case dmxInfo:    type = "II"; break;
    122     case dmxWarning: type = "**"; break;
    123     case dmxError:   type = "!!"; break;
    124     case dmxFatal:   type = "Fatal Error"; break;
    125     }
    126 
    127     if (dmxInput && dmxScreen) {
    128         ErrorF("(%s) dmx[i%d/%s;o%d/%s]: ", type,
    129                dmxInput->inputIdx, dmxInput->name,
    130                dmxScreen->index, dmxScreen->name);
    131     } else if (dmxScreen) {
    132         ErrorF("(%s) dmx[o%d/%s]: ", type,
    133                dmxScreen->index, dmxScreen->name);
    134     } else if (dmxInput) {
    135         const char *pt = strchr(dmxInput->name, ',');
    136         int        len = (pt
    137                           ? (size_t)(pt-dmxInput->name)
    138                           : strlen(dmxInput->name));
    139 
    140         ErrorF("(%s) dmx[i%d/%*.*s]: ", type,
    141                dmxInput->inputIdx, len, len, dmxInput->name);
    142     } else {
    143         ErrorF("(%s) dmx: ", type);
    144     }
    145 }
    146 
    147 /* Prints the error message with the appropriate low-level X output
    148  * routine. */
    149 static void dmxMessage(dmxLogLevel logLevel, const char *format, va_list args)
    150 {
    151     if (logLevel == dmxFatal || logLevel >= dmxCurrentLogLevel) {
    152         if (logLevel == dmxFatal) VFatalError(format, args);
    153         else VErrorF(format, args);
    154     }
    155 }
    156 
    157 /** Log the specified message at the specified \a logLevel.  \a format
    158  * can be a printf-like format expression. */
    159 void dmxLog(dmxLogLevel logLevel, const char *format, ...)
    160 {
    161     va_list args;
    162 
    163     dmxHeader(logLevel, NULL, NULL);
    164     va_start(args, format);
    165     dmxMessage(logLevel, format, args);
    166     va_end(args);
    167 }
    168 
    169 /** Continue a log message without printing the message prefix. */
    170 void dmxLogCont(dmxLogLevel logLevel, const char *format, ...)
    171 {
    172     va_list args;
    173 
    174     va_start(args, format);
    175     dmxMessage(logLevel, format, args);
    176     va_end(args);
    177 }
    178 
    179 #ifndef DMX_LOG_STANDALONE
    180 /** Log an informational message (at level #dmxInfo) related to ouput.
    181  * The message prefix will contain backend information from \a
    182  * dmxScreen. */
    183 void dmxLogOutput(DMXScreenInfo *dmxScreen, const char *format, ...)
    184 {
    185     va_list args;
    186 
    187     dmxHeader(dmxInfo, NULL, dmxScreen);
    188     va_start(args, format);
    189     dmxMessage(dmxInfo, format, args);
    190     va_end(args);
    191 }
    192 
    193 /** Continue a message related to output without printing the message
    194  * prefix. */
    195 void dmxLogOutputCont(DMXScreenInfo *dmxScreen, const char *format, ...)
    196 {
    197     va_list args;
    198 
    199     va_start(args, format);
    200     dmxMessage(dmxInfo, format, args);
    201     va_end(args);
    202 }
    203 
    204 /** Log a warning message (at level #dmxWarning) related to output.
    205  * The message prefix will contain backend information from \a
    206  * dmxScreen. */
    207 void dmxLogOutputWarning(DMXScreenInfo *dmxScreen, const char *format, ...)
    208 {
    209     va_list args;
    210 
    211     dmxHeader(dmxWarning, NULL, dmxScreen);
    212     va_start(args, format);
    213     dmxMessage(dmxWarning, format, args);
    214     va_end(args);
    215 }
    216 
    217 /** Log an informational message (at level #dmxInfo) related to input.
    218  * The message prefix will contain information from \a dmxInput. */
    219 void dmxLogInput(DMXInputInfo *dmxInput, const char *format, ...)
    220 {
    221     va_list args;
    222 
    223     dmxHeader(dmxInfo, dmxInput, NULL);
    224     va_start(args, format);
    225     dmxMessage(dmxInfo, format, args);
    226     va_end(args);
    227 }
    228 
    229 /** Continue a message related to input without printing the message
    230  * prefix. */
    231 void dmxLogInputCont(DMXInputInfo *dmxInput, const char *format, ...)
    232 {
    233     va_list args;
    234 
    235     va_start(args, format);
    236     dmxMessage(dmxInfo, format, args);
    237     va_end(args);
    238 }
    239 
    240 /** Print \a argc messages, each describing an element in \a argv.  This
    241  * is maingly for debugging purposes. */
    242 void dmxLogArgs(dmxLogLevel logLevel, int argc, char **argv)
    243 {
    244     int i;
    245     for (i = 0; i < argc; i++)
    246         dmxLog(logLevel, "   Arg[%d] = \"%s\"\n", i, argv[i]);
    247 }
    248 
    249 /** Print messages at level #dmxInfo describing the visuals in \a vi. */
    250 void dmxLogVisual(DMXScreenInfo *dmxScreen, XVisualInfo *vi, int defaultVisual)
    251 {
    252     const char  *class = "Unknown";
    253 
    254     switch (vi->class) {
    255     case StaticGray:  class = "StaticGray "; break;
    256     case GrayScale:   class = "GrayScale  "; break;
    257     case StaticColor: class = "StaticColor"; break;
    258     case PseudoColor: class = "PseudoColor"; break;
    259     case TrueColor:   class = "TrueColor  "; break;
    260     case DirectColor: class = "DirectColor"; break;
    261     }
    262 
    263     if (dmxScreen) {
    264         dmxLogOutput(dmxScreen,
    265                      "0x%02x %s %2db %db/rgb %3d 0x%04x 0x%04x 0x%04x%s\n",
    266                      vi->visualid, class, vi->depth, vi->bits_per_rgb,
    267                      vi->colormap_size,
    268                      vi->red_mask, vi->green_mask, vi->blue_mask,
    269                      defaultVisual ? " *" : "");
    270     } else {
    271         dmxLog(dmxInfo,
    272                "  0x%02x %s %2db %db/rgb %3d 0x%04x 0x%04x 0x%04x%s\n",
    273                vi->visualid, class, vi->depth, vi->bits_per_rgb,
    274                vi->colormap_size,
    275                vi->red_mask, vi->green_mask, vi->blue_mask,
    276                defaultVisual ? " *" : "");
    277     }
    278 }
    279 
    280 /** Translate a (normalized) XInput event \a type into a human-readable
    281  * string. */
    282 const char *dmxXInputEventName(int type)
    283 {
    284     switch (type) {
    285     case XI_DeviceValuator:          return "XI_DeviceValuator";
    286     case XI_DeviceKeyPress:          return "XI_DeviceKeyPress";
    287     case XI_DeviceKeyRelease:        return "XI_DeviceKeyRelease";
    288     case XI_DeviceButtonPress:       return "XI_DeviceButtonPress";
    289     case XI_DeviceButtonRelease:     return "XI_DeviceButtonRelease";
    290     case XI_DeviceMotionNotify:      return "XI_DeviceMotionNotify";
    291     case XI_DeviceFocusIn:           return "XI_DeviceFocusIn";
    292     case XI_DeviceFocusOut:          return "XI_DeviceFocusOut";
    293     case XI_ProximityIn:             return "XI_ProximityIn";
    294     case XI_ProximityOut:            return "XI_ProximityOut";
    295     case XI_DeviceStateNotify:       return "XI_DeviceStateNotify";
    296     case XI_DeviceMappingNotify:     return "XI_DeviceMappingNotify";
    297     case XI_ChangeDeviceNotify:      return "XI_ChangeDeviceNotify";
    298     case XI_DeviceKeystateNotify:    return "XI_DeviceKeystateNotify";
    299     case XI_DeviceButtonstateNotify: return "XI_DeviceButtonstateNotify";
    300     default:                         return "unknown";
    301     }
    302 }
    303 
    304 #endif
    305 
    306 /** Translate an event \a type into a human-readable string. */
    307 const char *dmxEventName(int type)
    308 {
    309     switch (type) {
    310     case KeyPress:         return "KeyPress";
    311     case KeyRelease:       return "KeyRelease";
    312     case ButtonPress:      return "ButtonPress";
    313     case ButtonRelease:    return "ButtonRelease";
    314     case MotionNotify:     return "MotionNotify";
    315     case EnterNotify:      return "EnterNotify";
    316     case LeaveNotify:      return "LeaveNotify";
    317     case FocusIn:          return "FocusIn";
    318     case FocusOut:         return "FocusOut";
    319     case KeymapNotify:     return "KeymapNotify";
    320     case Expose:           return "Expose";
    321     case GraphicsExpose:   return "GraphicsExpose";
    322     case NoExpose:         return "NoExpose";
    323     case VisibilityNotify: return "VisibilityNotify";
    324     case CreateNotify:     return "CreateNotify";
    325     case DestroyNotify:    return "DestroyNotify";
    326     case UnmapNotify:      return "UnmapNotify";
    327     case MapNotify:        return "MapNotify";
    328     case MapRequest:       return "MapRequest";
    329     case ReparentNotify:   return "ReparentNotify";
    330     case ConfigureNotify:  return "ConfigureNotify";
    331     case ConfigureRequest: return "ConfigureRequest";
    332     case GravityNotify:    return "GravityNotify";
    333     case ResizeRequest:    return "ResizeRequest";
    334     case CirculateNotify:  return "CirculateNotify";
    335     case CirculateRequest: return "CirculateRequest";
    336     case PropertyNotify:   return "PropertyNotify";
    337     case SelectionClear:   return "SelectionClear";
    338     case SelectionRequest: return "SelectionRequest";
    339     case SelectionNotify:  return "SelectionNotify";
    340     case ColormapNotify:   return "ColormapNotify";
    341     case ClientMessage:    return "ClientMessage";
    342     case MappingNotify:    return "MappingNotify";
    343     default:               return "<unknown>";
    344     }
    345 }
    346 
    347