/* $Id: guppi-debug.c,v 1.17 2001/09/27 05:07:30 trow Exp $ */

/*
 * guppi-debug.c
 *
 * Copyright (C) 2000 EMC Capital Management, Inc.
 * Copyright (C) 2001 The Free Software Foundation
 *
 * Developed by Jon Trowbridge <trow@gnu.org>
 * and Havoc Pennington <hp@pobox.com>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include <config.h>
#include "guppi-debug.h"

/* #include <gnome.h> */
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include "guppi-dialogs.h"

static gint guppi_verbosity_level = GUPPI_NORMAL_VERBOSITY;

gint
guppi_verbosity (void)
{
  return guppi_verbosity_level;
}

void
guppi_set_verbosity (gint x)
{
  guppi_verbosity_level = x;
}

gboolean
guppi_is_not_silent (void)
{
  return guppi_verbosity () > GUPPI_SILENT;
}

gboolean
guppi_is_verbose (void)
{
  return guppi_verbosity () >= GUPPI_VERBOSE;
}

gboolean
guppi_is_very_verbose (void)
{
  return guppi_verbosity () >= GUPPI_VERY_VERBOSE;
}

/**********************************************************************/

void
_guppi_debug_corev (gint verbosity,
		    const gchar * log_domain, GLogLevelFlags log_level,
		    const gchar * file, gint line, const gchar * func,
		    const gchar * format, va_list args)
{
  if (file) {
    fputs (file, stderr);
    fputc (':', stderr);
  }

  if (func) {
    fputs (func, stderr);
    fputc (':', stderr);
  }

  if (line >= 0) {
    fprintf (stderr, "%d:", line);
  }

  fputc (' ', stderr);

  vfprintf (stderr, format, args);
  fputc ('\n', stderr);
}

void
_guppi_debug_core (gint verbosity,
		   const gchar * log_domain, GLogLevelFlags log_level,
		   const gchar * file, gint line, const gchar * func,
		   const gchar * format, ...)
{
  va_list args;
  va_start (args, format);
  _guppi_debug_corev (verbosity, log_domain, log_level, file, line, func,
		      format, args);
}

/**********************************************************************/

static gboolean guppi_sync = FALSE;

void
guppi_set_synchronous (void)
{
  guppi_sync = TRUE;
}

gboolean
guppi_is_synchronous (void)
{
  return guppi_sync;
}

/**********************************************************************/

/**
 * guppi_FIXME
 *
 * A synonym for g_assert_not_reached which has the benefit that it can easily
 * be grepped for in source code.  guppi_FIXME() is used both as an informational
 * placeholder and as a way to gracefully terminate incomplete or unimplemented
 * code paths.
 */
void
guppi_FIXME (void)
{
  g_assert_not_reached ();
}

/**********************************************************************/

void
_guppi_unimplemented_function_dialog (const gchar * function,
				      const gchar * filename,
				      gint line)
{
  g_return_if_fail (function != NULL);
  g_return_if_fail (filename != NULL);
  g_return_if_fail (line > 0);

  guppi_warning_dialog ("\"%s\" is not implemented yet.\n\nCode needs to be added at %s, line %d.", function, filename, line);
}

/**********************************************************************/

static gint layer = 0;

void
_guppi_track_entry (const gchar * filename, const gchar * function, gint line,
		    const gchar * msg)
{
  gint i;

  for (i = 0; i < layer; ++i)
    g_print ("  ");

  g_print ("+ %s:%d ", function, line);

  if (msg) {
    g_print (msg);
    g_print (" ");
  }

  g_print ("(%s)\n", filename);

  ++layer;
}

void
_guppi_track_exit (const gchar * filename, const gchar * function, gint line,
		   const gchar * msg)
{
  gint i;

  --layer;

  for (i = 0; i < layer; ++i)
    g_print ("  ");

  g_print ("- %s:%d ", function, line);

  if (msg) {
    g_print (msg);
    g_print (" ");
  }

  g_print ("(%s)\n", filename);
}

/**********************************************************************/

/*
  All of the following code is blatently stolen from Nautilus
  (extracted from nautilus-debug.h on 23 Mar 2000)
*/

/*
  Raise a SIGINT signal to get the attention of the debugger.
  When not running under the debugger, we don't want to stop,
  so we ignore the signal for just the moment that we raise it.
*/

void
guppi_stop_in_debugger (void)
{
  void (*saved_handler) (int);

  saved_handler = signal (SIGINT, SIG_IGN);
  raise (SIGINT);
  signal (SIGINT, saved_handler);
}

/* 
   Stop in the debugger after running the default log handler.
   This makes certain kinds of messages stop in the debugger
   without making them fatal.
*/

static void
guppi_stop_after_default_log_handler (const char *domain,
				      GLogLevelFlags level,
				      const char *message, gpointer data)
{
  g_log_default_handler (domain, level, message, data);
  guppi_stop_in_debugger ();
}

static void
guppi_set_stop_after_default_log_handler (const char *domain)
{
  g_log_set_handler (domain, G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING,
		     guppi_stop_after_default_log_handler, NULL);
}


void
guppi_make_warnings_and_criticals_stop_in_debugger (const char *first_domain,
						    ...)
{
  va_list domains;
  const char *domain;

  guppi_set_stop_after_default_log_handler (first_domain);

  va_start (domains, first_domain);

  for (;;) {
    domain = va_arg (domains, const char *);
    if (domain == NULL)
      break;
    guppi_set_stop_after_default_log_handler (domain);
  }

  va_end (domains);
}


/* $Id: guppi-debug.c,v 1.17 2001/09/27 05:07:30 trow Exp $ */


syntax highlighted by Code2HTML, v. 0.9.1