util.c

Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 
00003 /* Metacity utilities */
00004 
00005 /* 
00006  * Copyright (C) 2001 Havoc Pennington
00007  * Copyright (C) 2005 Elijah Newren
00008  * 
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License as
00011  * published by the Free Software Foundation; either version 2 of the
00012  * License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful, but
00015  * WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00022  * 02111-1307, USA.
00023  */
00024 
00025 #define _GNU_SOURCE
00026 #define _POSIX_C_SOURCE /* for fdopen() */
00027 
00028 #include <config.h>
00029 #include "util.h"
00030 #include "main.h"
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <errno.h>
00036 #include <string.h>
00037 #include <X11/Xlib.h>   /* must explicitly be included for Solaris; #326746 */
00038 #include <X11/Xutil.h>  /* Just for the definition of the various gravities */
00039 
00040 #ifdef HAVE_BACKTRACE
00041 #include <execinfo.h>
00042 void
00043 meta_print_backtrace (void)
00044 {
00045   void *bt[500];
00046   int bt_size;
00047   int i;
00048   char **syms;
00049   
00050   bt_size = backtrace (bt, 500);
00051 
00052   syms = backtrace_symbols (bt, bt_size);
00053   
00054   i = 0;
00055   while (i < bt_size)
00056     {
00057       meta_verbose ("  %s\n", syms[i]);
00058       ++i;
00059     }
00060 
00061   free (syms);
00062 }
00063 #else
00064 void
00065 meta_print_backtrace (void)
00066 {
00067   meta_verbose ("Not compiled with backtrace support\n");
00068 }
00069 #endif
00070 
00071 static gboolean is_verbose = FALSE;
00072 static gboolean is_debugging = FALSE;
00073 static gboolean replace_current = FALSE;
00074 static int no_prefix = 0;
00075 
00076 #ifdef WITH_VERBOSE_MODE
00077 static FILE* logfile = NULL;
00078 
00079 static void
00080 ensure_logfile (void)
00081 {
00082   if (logfile == NULL && g_getenv ("METACITY_USE_LOGFILE"))
00083     {
00084       char *filename = NULL;
00085       char *tmpl;
00086       int fd;
00087       GError *err;
00088       
00089       tmpl = g_strdup_printf ("metacity-%d-debug-log-XXXXXX",
00090                               (int) getpid ());
00091 
00092       err = NULL;
00093       fd = g_file_open_tmp (tmpl,
00094                             &filename,
00095                             &err);
00096 
00097       g_free (tmpl);
00098       
00099       if (err != NULL)
00100         {
00101           meta_warning (_("Failed to open debug log: %s\n"),
00102                         err->message);
00103           g_error_free (err);
00104           return;
00105         }
00106       
00107       logfile = fdopen (fd, "w");
00108       
00109       if (logfile == NULL)
00110         {
00111           meta_warning (_("Failed to fdopen() log file %s: %s\n"),
00112                         filename, strerror (errno));
00113           close (fd);
00114         }
00115       else
00116         {
00117           g_printerr (_("Opened log file %s\n"), filename);
00118         }
00119       
00120       g_free (filename);
00121     }
00122 }
00123 #endif
00124 
00125 gboolean
00126 meta_is_verbose (void)
00127 {
00128   return is_verbose;
00129 }
00130 
00131 void
00132 meta_set_verbose (gboolean setting)
00133 {
00134 #ifndef WITH_VERBOSE_MODE
00135   if (setting)
00136     meta_fatal (_("Metacity was compiled without support for verbose mode\n"));
00137 #else 
00138   if (setting)
00139     ensure_logfile ();
00140 #endif
00141   
00142   is_verbose = setting;
00143 }
00144 
00145 gboolean
00146 meta_is_debugging (void)
00147 {
00148   return is_debugging;
00149 }
00150 
00151 void
00152 meta_set_debugging (gboolean setting)
00153 {
00154 #ifdef WITH_VERBOSE_MODE
00155   if (setting)
00156     ensure_logfile ();
00157 #endif
00158 
00159   is_debugging = setting;
00160 }
00161 
00162 gboolean
00163 meta_get_replace_current_wm (void)
00164 {
00165   return replace_current;
00166 }
00167 
00168 void
00169 meta_set_replace_current_wm (gboolean setting)
00170 {
00171   replace_current = setting;
00172 }
00173 
00174 char *
00175 meta_g_utf8_strndup (const gchar *src,
00176                      gsize        n)
00177 {
00178   const gchar *s = src;
00179   while (n && *s)
00180     {
00181       s = g_utf8_next_char (s);
00182       n--;
00183     }
00184 
00185   return g_strndup (src, s - src);
00186 }
00187 
00188 static int
00189 utf8_fputs (const char *str,
00190             FILE       *f)
00191 {
00192   char *l;
00193   int retval;
00194   
00195   l = g_locale_from_utf8 (str, -1, NULL, NULL, NULL);
00196 
00197   if (l == NULL)
00198     retval = fputs (str, f); /* just print it anyway, better than nothing */
00199   else
00200     retval = fputs (l, f);
00201 
00202   g_free (l);
00203 
00204   return retval;
00205 }
00206 
00207 void
00208 meta_free_gslist_and_elements (GSList *list_to_deep_free)
00209 {
00210   g_slist_foreach (list_to_deep_free,
00211                    (void (*)(gpointer,gpointer))&g_free, /* ew, for ugly */
00212                    NULL);
00213   g_slist_free (list_to_deep_free);
00214 }
00215 
00216 #ifdef WITH_VERBOSE_MODE
00217 void
00218 meta_debug_spew_real (const char *format, ...)
00219 {
00220   va_list args;
00221   gchar *str;
00222   FILE *out;
00223   
00224   g_return_if_fail (format != NULL);
00225 
00226   if (!is_debugging)
00227     return;
00228   
00229   va_start (args, format);
00230   str = g_strdup_vprintf (format, args);
00231   va_end (args);
00232 
00233   out = logfile ? logfile : stderr;
00234   
00235   if (no_prefix == 0)
00236     utf8_fputs (_("Window manager: "), out);
00237   utf8_fputs (str, out);
00238 
00239   fflush (out);
00240   
00241   g_free (str);
00242 }
00243 #endif /* WITH_VERBOSE_MODE */
00244 
00245 #ifdef WITH_VERBOSE_MODE
00246 void
00247 meta_verbose_real (const char *format, ...)
00248 {
00249   va_list args;
00250   gchar *str;
00251   FILE *out;
00252 
00253   g_return_if_fail (format != NULL);
00254 
00255   if (!is_verbose)
00256     return;
00257   
00258   va_start (args, format);
00259   str = g_strdup_vprintf (format, args);
00260   va_end (args);
00261 
00262   out = logfile ? logfile : stderr;
00263   
00264   if (no_prefix == 0)
00265     utf8_fputs ("Window manager: ", out);
00266   utf8_fputs (str, out);
00267 
00268   fflush (out);
00269   
00270   g_free (str);
00271 }
00272 #endif /* WITH_VERBOSE_MODE */
00273 
00274 #ifdef WITH_VERBOSE_MODE
00275 static const char*
00276 topic_name (MetaDebugTopic topic)
00277 {
00278   switch (topic)
00279     {
00280     case META_DEBUG_FOCUS:
00281       return "FOCUS";
00282     case META_DEBUG_WORKAREA:
00283       return "WORKAREA";
00284     case META_DEBUG_STACK:
00285       return "STACK";
00286     case META_DEBUG_THEMES:
00287       return "THEMES";
00288     case META_DEBUG_SM:
00289       return "SM";
00290     case META_DEBUG_EVENTS:
00291       return "EVENTS";
00292     case META_DEBUG_WINDOW_STATE:
00293       return "WINDOW_STATE";
00294     case META_DEBUG_WINDOW_OPS:
00295       return "WINDOW_OPS";
00296     case META_DEBUG_PLACEMENT:
00297       return "PLACEMENT";
00298     case META_DEBUG_GEOMETRY:
00299       return "GEOMETRY";
00300     case META_DEBUG_PING:
00301       return "PING";
00302     case META_DEBUG_XINERAMA:
00303       return "XINERAMA";
00304     case META_DEBUG_KEYBINDINGS:
00305       return "KEYBINDINGS";
00306     case META_DEBUG_SYNC:
00307       return "SYNC";
00308     case META_DEBUG_ERRORS:
00309       return "ERRORS";
00310     case META_DEBUG_STARTUP:
00311       return "STARTUP";
00312     case META_DEBUG_PREFS:
00313       return "PREFS";
00314     case META_DEBUG_GROUPS:
00315       return "GROUPS";
00316     case META_DEBUG_RESIZING:
00317       return "RESIZING";
00318     case META_DEBUG_SHAPES:
00319       return "SHAPES";
00320     case META_DEBUG_COMPOSITOR:
00321       return "COMPOSITOR";
00322     case META_DEBUG_EDGE_RESISTANCE:
00323       return "EDGE_RESISTANCE";
00324     }
00325 
00326   return "WM";
00327 }
00328 
00329 static int sync_count = 0;
00330 
00331 void
00332 meta_topic_real (MetaDebugTopic topic,
00333                  const char *format,
00334                  ...)
00335 {
00336   va_list args;
00337   gchar *str;
00338   FILE *out;
00339 
00340   g_return_if_fail (format != NULL);
00341 
00342   if (!is_verbose)
00343     return;
00344   
00345   va_start (args, format);  
00346   str = g_strdup_vprintf (format, args);
00347   va_end (args);
00348 
00349   out = logfile ? logfile : stderr;
00350 
00351   if (no_prefix == 0)
00352     fprintf (out, "%s: ", topic_name (topic));
00353 
00354   if (topic == META_DEBUG_SYNC)
00355     {
00356       ++sync_count;
00357       fprintf (out, "%d: ", sync_count);
00358     }
00359   
00360   utf8_fputs (str, out);
00361   
00362   fflush (out);
00363   
00364   g_free (str);
00365 }
00366 #endif /* WITH_VERBOSE_MODE */
00367 
00368 void
00369 meta_bug (const char *format, ...)
00370 {
00371   va_list args;
00372   gchar *str;
00373   FILE *out;
00374 
00375   g_return_if_fail (format != NULL);
00376   
00377   va_start (args, format);
00378   str = g_strdup_vprintf (format, args);
00379   va_end (args);
00380 
00381 #ifdef WITH_VERBOSE_MODE
00382   out = logfile ? logfile : stderr;
00383 #else
00384   out = stderr;
00385 #endif
00386 
00387   if (no_prefix == 0)
00388     utf8_fputs (_("Bug in window manager: "), out);
00389   utf8_fputs (str, out);
00390 
00391   fflush (out);
00392   
00393   g_free (str);
00394 
00395   meta_print_backtrace ();
00396   
00397   /* stop us in a debugger */
00398   abort ();
00399 }
00400 
00401 void
00402 meta_warning (const char *format, ...)
00403 {
00404   va_list args;
00405   gchar *str;
00406   FILE *out;
00407   
00408   g_return_if_fail (format != NULL);
00409   
00410   va_start (args, format);
00411   str = g_strdup_vprintf (format, args);
00412   va_end (args);
00413 
00414 #ifdef WITH_VERBOSE_MODE
00415   out = logfile ? logfile : stderr;
00416 #else
00417   out = stderr;
00418 #endif
00419 
00420   if (no_prefix == 0)
00421     utf8_fputs (_("Window manager warning: "), out);
00422   utf8_fputs (str, out);
00423 
00424   fflush (out);
00425   
00426   g_free (str);
00427 }
00428 
00429 void
00430 meta_fatal (const char *format, ...)
00431 {
00432   va_list args;
00433   gchar *str;
00434   FILE *out;
00435   
00436   g_return_if_fail (format != NULL);
00437   
00438   va_start (args, format);
00439   str = g_strdup_vprintf (format, args);
00440   va_end (args);
00441 
00442 #ifdef WITH_VERBOSE_MODE
00443   out = logfile ? logfile : stderr;
00444 #else
00445   out = stderr;
00446 #endif
00447 
00448   if (no_prefix == 0)
00449     utf8_fputs (_("Window manager error: "), out);
00450   utf8_fputs (str, out);
00451 
00452   fflush (out);
00453   
00454   g_free (str);
00455 
00456   meta_exit (META_EXIT_ERROR);
00457 }
00458 
00459 void
00460 meta_push_no_msg_prefix (void)
00461 {
00462   ++no_prefix;
00463 }
00464 
00465 void
00466 meta_pop_no_msg_prefix (void)
00467 {
00468   g_return_if_fail (no_prefix > 0);
00469 
00470   --no_prefix;
00471 }
00472 
00473 void
00474 meta_exit (MetaExitCode code)
00475 {
00476   
00477   exit (code);
00478 }
00479 
00480 gint
00481 meta_unsigned_long_equal (gconstpointer v1,
00482                           gconstpointer v2)
00483 {
00484   return *((const gulong*) v1) == *((const gulong*) v2);
00485 }
00486 
00487 guint
00488 meta_unsigned_long_hash  (gconstpointer v)
00489 {
00490   gulong val = * (const gulong *) v;
00491 
00492   /* I'm not sure this works so well. */
00493 #if GLIB_SIZEOF_LONG > 4
00494   return (guint) (val ^ (val >> 32));
00495 #else
00496   return val;
00497 #endif
00498 }
00499 
00500 const char*
00501 meta_gravity_to_string (int gravity)
00502 {
00503   switch (gravity)
00504     {
00505     case NorthWestGravity:
00506       return "NorthWestGravity";
00507       break;
00508     case NorthGravity:
00509       return "NorthGravity";
00510       break;
00511     case NorthEastGravity:
00512       return "NorthEastGravity";
00513       break;
00514     case WestGravity:
00515       return "WestGravity";
00516       break;
00517     case CenterGravity:
00518       return "CenterGravity";
00519       break;
00520     case EastGravity:
00521       return "EastGravity";
00522       break;
00523     case SouthWestGravity:
00524       return "SouthWestGravity";
00525       break;
00526     case SouthGravity:
00527       return "SouthGravity";
00528       break;
00529     case SouthEastGravity:
00530       return "SouthEastGravity";
00531       break;
00532     case StaticGravity:
00533       return "StaticGravity";
00534       break;
00535     default:
00536       return "NorthWestGravity";
00537       break;
00538     }
00539 }

Generated on Sat Aug 23 22:04:17 2008 for metacity by  doxygen 1.5.5