errorconsole.c 9.56 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * errorconsole.c - text window for collecting error messages
 * Copyright (C) 1998 Nick Fetchak <nuke@bayside.net>
 *
 * 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.
 */
21 22
#include "config.h"

Tor Lillqvist's avatar
Tor Lillqvist committed
23 24
#include <glib.h>

25 26 27
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
28
#include <sys/types.h>
29
#ifdef HAVE_DIRENT_H
30
#include <dirent.h>
31 32
#endif
#ifdef HAVE_UNISTD_H
33
#include <unistd.h>
34
#endif
35 36 37
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
38

39
#ifdef G_OS_WIN32
40 41 42 43 44 45 46 47 48 49
#include <io.h>
#ifndef S_IRUSR
#define S_IRUSR _S_IREAD
#endif
#ifndef S_IWUSR
#define S_IWUSR _S_IWRITE
#endif
#endif

#include <gtk/gtk.h>
50

51
#include "appenv.h"
52
#include "commands.h"
53
#include "gimpui.h"
54
#include "session.h"
55
#include "dialog_handler.h"
56

57 58
#include "libgimp/gimpintl.h"

59
#define ERRORS_ALL       0
60 61
#define ERRORS_SELECTION 1

62 63
static GtkWidget * error_console = NULL;
static GtkWidget * text;
64

65 66

static void
67
error_console_close_callback (GtkWidget	*widget,
Michael Natterer's avatar
Michael Natterer committed
68
			      gpointer	 data)
69
{
70
  gtk_widget_hide (error_console);
71 72 73

  /* FIXME: interact with preferences */
  message_handler = MESSAGE_BOX;
74 75
}

Tor Lillqvist's avatar
Tor Lillqvist committed
76 77 78 79 80 81 82 83
static void
error_console_clear_callback (GtkWidget	*widget,
			      gpointer	 data)
{
  gtk_editable_delete_text
    (GTK_EDITABLE (text), 0, gtk_text_get_length (GTK_TEXT (text)));
}

84 85 86 87 88
void
error_console_free (void)
{                                     
  if (error_console)
    session_get_window_info (error_console, &error_console_session_info);
89 90 91
}

gint
92 93
error_console_write_file (gchar *path,
			  gint   textscope)
94
{
95 96 97
  gint fd;
  gint text_length;
  gint bytes_written;
98
  gchar	*text_contents;
99 100 101
  GtkText *gtext;

  gtext = GTK_TEXT (text);
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

  fd = open (path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
  
  if (fd == -1)
    return FALSE;

  if (textscope == ERRORS_ALL)
    {
      text_contents =
        gtk_editable_get_chars (GTK_EDITABLE (text), 0,
				gtk_text_get_length (GTK_TEXT (text)));
    }
  else
    {
      gint selection_start, selection_end, temp;
      
      selection_start = GTK_TEXT (text)->editable.selection_start_pos;
      selection_end = GTK_TEXT (text)->editable.selection_end_pos;

      if (selection_start > selection_end)
        {
	  temp = selection_start;
	  selection_start = selection_end;
	  selection_end = temp;
	}

      text_contents = gtk_editable_get_chars (GTK_EDITABLE (text),
					      selection_start,
					      selection_end);
    }

  text_length = strlen (text_contents);

  if (text_contents && (text_length > 0))
    {
      bytes_written = write (fd, text_contents, text_length);
      
      g_free (text_contents);
      close (fd);
      
      if (bytes_written != text_length)
        return FALSE;
      else
	return TRUE;
    }

  close (fd);
  return TRUE;
}

static void
153 154
error_console_file_ok_callback (GtkWidget *widget,
				gpointer   data)
155
{
156 157 158
  GtkWidget *filesel;
  gchar	    *filename;
  gint	     textscope;
159 160 161 162 163 164 165 166 167 168

  filesel = (GtkWidget *) data;
  filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (filesel));
  
  textscope = (gint) gtk_object_get_user_data (GTK_OBJECT (filesel));

  if (!error_console_write_file (filename, textscope))
    {
      GString	*string;

169
      string = g_string_new ("");
170 171
      g_string_sprintf (string, _("Error opening file %s: %s"),
			filename, g_strerror (errno));
172 173 174 175 176 177 178 179 180 181
      g_message (string->str);
      g_string_free (string, TRUE);
    }
  else
    gtk_widget_destroy (filesel);
}

static void
error_console_menu_callback (gint textscope)
{
182
  GtkWidget *filesel;
183

184 185
  if (!(GTK_TEXT (text)->editable.has_selection) &&
      (textscope == ERRORS_SELECTION))
186
    {
187
      g_message (_("Can't save, nothing selected!"));
188 189 190
      return;
    }
  
191
  filesel = gtk_file_selection_new (_("Save error log to file..."));
192
  gtk_window_set_position (GTK_WINDOW (filesel), GTK_WIN_POS_MOUSE);
193
  gtk_window_set_wmclass (GTK_WINDOW (filesel), "save_errors", "Gimp");
194 195 196 197

  gtk_container_set_border_width (GTK_CONTAINER (filesel), 2);
  gtk_container_set_border_width (GTK_CONTAINER (GTK_FILE_SELECTION (filesel)->button_area), 2);

198 199 200 201 202 203 204 205 206 207 208 209
  gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
			     "clicked", (GtkSignalFunc) gtk_widget_destroy,
			     GTK_OBJECT (filesel));

  gtk_object_set_user_data (GTK_OBJECT (filesel), (gpointer) textscope);
  gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
  		      "clicked", (GtkSignalFunc) error_console_file_ok_callback,
		      filesel);

  gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
			     "delete_event", (GtkSignalFunc) gtk_widget_destroy,
			     GTK_OBJECT (filesel));
210 211 212 213 214 215

  /*  Connect the "F1" help key  */
  gimp_help_connect_help_accel (filesel,
				gimp_standard_help_func,
				"dialogs/error_console.html");

216 217 218 219
  gtk_widget_show (filesel);
}

static gint
220 221 222
text_clicked_callback (GtkWidget      *widget,
		       GdkEventButton *event, 
		       gpointer	       data)
223
{
224 225
  GtkMenu *menu = (GtkMenu *) data;
  GtkText *gtext;
226 227 228
  
  gtext = GTK_TEXT (text);

229
  switch (event->button)
230
    {
231 232 233
    case 1:
    case 2:
      break;
234

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
    case 3:
      gtk_signal_emit_stop_by_name (GTK_OBJECT (text), "button_press_event");
      gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time);

      /*  wheelmouse support  */
    case 4:
      {
	GtkAdjustment *adj = gtext->vadj;
	gfloat new_value = adj->value - adj->page_increment / 2;
	new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
	gtk_adjustment_set_value (adj, new_value);
      }
      break;

    case 5:
      {
	GtkAdjustment *adj = gtext->vadj;
	gfloat new_value = adj->value + adj->page_increment / 2;
	new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
	gtk_adjustment_set_value (adj, new_value);
      }
      break;

    default:
      break;
260 261 262 263 264 265 266 267
    }

  return TRUE; 
}

static void
error_console_create_window (void)
{
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
  GtkWidget *table;
  GtkWidget *vscrollbar;
  GtkWidget *menu;
  GtkWidget *menuitem;

  error_console = gimp_dialog_new (_("GIMP Error Console"), "error_console",
				   gimp_standard_help_func,
				   "dialogs/error_console.html",
				   GTK_WIN_POS_NONE,
				   TRUE, TRUE, FALSE,

				   _("Clear"), error_console_clear_callback,
				   NULL, NULL, FALSE, FALSE,
				   _("Close"), error_console_close_callback,
				   text, NULL, TRUE, TRUE,

				   NULL);
285
  /* register this one only */
286
  dialog_register (error_console);
287 288
  session_set_window_geometry (error_console, &error_console_session_info,
			       TRUE); 
289

290 291
  /* The next line should disappear when setting the size works in SM */
  gtk_widget_set_usize (error_console, 250, 300);
292 293 294 295 296 297 298

  table = gtk_table_new (2, 2, FALSE);
  gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
  gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
  gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (error_console)->vbox), table);
  gtk_widget_show (table);
299 300 301

  menu = gtk_menu_new ();

302
  menuitem = gtk_menu_item_new_with_label (_("Write all errors to file..."));
303 304 305 306 307 308
  gtk_menu_append (GTK_MENU (menu), menuitem);
  gtk_signal_connect_object (GTK_OBJECT(menuitem), "activate",
			     (GtkSignalFunc) error_console_menu_callback,
			     (gpointer) ERRORS_ALL);
  gtk_widget_show (menuitem);
  
309
  menuitem = gtk_menu_item_new_with_label (_("Write selection to file..."));
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
  gtk_menu_append (GTK_MENU (menu), menuitem);
  gtk_signal_connect_object (GTK_OBJECT(menuitem), "activate",
			     (GtkSignalFunc) error_console_menu_callback,
			     (gpointer) ERRORS_SELECTION);
  gtk_widget_show (menuitem);

  /*  The output text widget  */
  text = gtk_text_new (NULL, NULL);
  gtk_text_set_editable (GTK_TEXT (text), FALSE);
  gtk_text_set_word_wrap (GTK_TEXT (text), TRUE);
  gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
                    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
                    GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);

  gtk_widget_set_events (text, GDK_BUTTON_PRESS_MASK);
  gtk_signal_connect (GTK_OBJECT (text), "button_press_event",
		      GTK_SIGNAL_FUNC (text_clicked_callback), GTK_MENU (menu));

  gtk_widget_show (text);

  vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
  gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
                    GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
  gtk_widget_show (vscrollbar);

335
  gtk_widget_show (error_console);
336 337 338 339 340
}

void
error_console_add (gchar *errormsg)
{
341 342 343
  if (!error_console)
    {
      error_console_create_window ();
344 345 346

      /* FIMXE: interact with preferences */
      message_handler = ERROR_CONSOLE;
347 348 349 350
    } 
  else 
    {
      if (!GTK_WIDGET_VISIBLE (error_console))
351 352 353 354 355 356
	{
	  gtk_widget_show (error_console);

	  /* FIXME: interact with preferences */
	  message_handler = ERROR_CONSOLE;
	}
357 358 359
      else 
	gdk_window_raise (error_console->window);
    }
360 361 362 363 364 365 366
    
  if (errormsg)
    {
      gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, errormsg, -1);
      gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
    }
}