gschem
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gschem - gEDA Schematic Capture 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 /* 00022 * \file x_log.c 00023 * \brief GType class and functions to support the gschem log window. 00024 */ 00025 00026 #include <config.h> 00027 00028 #include <stdio.h> 00029 #include <sys/types.h> 00030 #include <sys/stat.h> 00031 #ifdef HAVE_STDLIB_H 00032 #include <stdlib.h> 00033 #endif 00034 #ifdef HAVE_UNISTD_H 00035 #include <unistd.h> 00036 #endif 00037 #ifdef HAVE_FCNTL_H 00038 #include <fcntl.h> 00039 #endif 00040 #ifdef HAVE_STRING_H 00041 #include <string.h> 00042 #endif 00043 00044 #include "gschem.h" 00045 00046 #ifdef HAVE_LIBDMALLOC 00047 #include <dmalloc.h> 00048 #endif 00049 00050 static void x_log_callback_response (GtkDialog *dialog, 00051 gint arg1, 00052 gpointer user_data); 00053 static void log_message (Log *log, 00054 const gchar *message, 00055 const gchar *style); 00056 00057 static void log_class_init (LogClass *class); 00058 static void log_init (Log *log); 00059 00060 static GtkWidget *log_dialog = NULL; 00061 00072 void x_log_open () 00073 { 00074 if (log_dialog == NULL) { 00075 gchar *contents; 00076 00077 log_dialog = GTK_WIDGET (g_object_new (TYPE_LOG, 00078 /* GtkWindow */ 00079 "type", GTK_WINDOW_TOPLEVEL, 00080 /* GschemDialog */ 00081 "settings-name", "log", 00082 /* "toplevel", TOPEVEL * */ 00083 NULL)); 00084 00085 g_signal_connect (log_dialog, 00086 "response", 00087 G_CALLBACK (x_log_callback_response), 00088 NULL); 00089 00090 /* make it read the content of the current log file */ 00091 /* and add its contents to the dialog */ 00092 contents = s_log_read (); 00093 00094 /* s_log_read can return NULL if the log file cannot be written to */ 00095 if (contents == NULL) 00096 { 00097 return; 00098 } 00099 00100 log_message (LOG (log_dialog), contents, "old"); 00101 g_free (contents); 00102 00103 x_log_update_func = x_log_message; 00104 00105 if( auto_place_mode ) 00106 gtk_widget_set_uposition( log_dialog, 10, 10); 00107 gtk_widget_show (log_dialog); 00108 } else { 00109 g_assert (IS_LOG (log_dialog)); 00110 gtk_window_present ((GtkWindow*)log_dialog); 00111 } 00112 00113 } 00114 00120 void x_log_close () 00121 { 00122 if (log_dialog) { 00123 g_assert (IS_LOG (log_dialog)); 00124 gtk_widget_destroy (log_dialog); 00125 x_log_update_func = NULL; 00126 log_dialog = NULL; 00127 } 00128 00129 } 00130 00140 void x_log_message (const gchar *log_domain, GLogLevelFlags log_level, 00141 const gchar *message) 00142 { 00143 gchar *style; 00144 g_return_if_fail (log_dialog != NULL); 00145 00146 if (log_level & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR)) { 00147 style = "critical"; 00148 } else if (log_level & G_LOG_LEVEL_WARNING) { 00149 style = "warning"; 00150 } else { 00151 style = "message"; 00152 } 00153 00154 log_message (LOG(log_dialog), message, style); 00155 } 00156 00163 static void x_log_callback_response (GtkDialog *dialog, 00164 gint arg1, 00165 gpointer user_data) 00166 { 00167 switch (arg1) { 00168 case GTK_RESPONSE_DELETE_EVENT: 00169 case LOG_RESPONSE_CLOSE: 00170 g_assert (GTK_WIDGET (dialog) == log_dialog); 00171 x_log_close (); 00172 break; 00173 default: 00174 g_assert_not_reached (); 00175 } 00176 00177 } 00178 00187 static void log_message (Log *log, const gchar *message, 00188 const gchar *style) 00189 { 00190 GtkTextBuffer *buffer; 00191 GtkTextIter iter; 00192 GtkTextMark *mark; 00193 00194 g_return_if_fail (IS_LOG (log)); 00195 00196 buffer = gtk_text_view_get_buffer (log->textview); 00197 gtk_text_buffer_get_end_iter (buffer, &iter); 00198 /* Apply the "plain" tag before the level-specific tag in order to 00199 * reset the formatting */ 00200 00201 if (g_utf8_validate (message, -1, NULL)) { 00202 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, message, -1, 00203 "plain", style, NULL); 00204 } else { 00205 /* If UTF-8 wasn't valid (due to a system locale encoded filename or 00206 * other string being included by mistake), log a warning, and print 00207 * the original message to stderr, where it may be partly intelligible */ 00208 gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, 00209 _("** Invalid UTF-8 in log message. See stderr or gschem.log.\n"), 00210 -1, "plain", style, NULL); 00211 fprintf (stderr, "%s", message); 00212 } 00213 00214 mark = gtk_text_buffer_create_mark(buffer, NULL, &iter, FALSE); 00215 gtk_text_view_scroll_to_mark (log->textview, mark, 0, TRUE, 0, 1); 00216 gtk_text_buffer_delete_mark (buffer, mark); 00217 } 00218 00228 GType log_get_type () 00229 { 00230 static GType log_type = 0; 00231 00232 if (!log_type) { 00233 static const GTypeInfo log_info = { 00234 sizeof(LogClass), 00235 NULL, /* base_init */ 00236 NULL, /* base_finalize */ 00237 (GClassInitFunc) log_class_init, 00238 NULL, /* class_finalize */ 00239 NULL, /* class_data */ 00240 sizeof(Log), 00241 0, /* n_preallocs */ 00242 (GInstanceInitFunc) log_init, 00243 }; 00244 00245 log_type = g_type_register_static (GSCHEM_TYPE_DIALOG, 00246 "Log", 00247 &log_info, 0); 00248 } 00249 00250 return log_type; 00251 } 00252 00261 static void log_class_init (LogClass *klass) 00262 { 00263 /* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */ 00264 00265 } 00266 00277 static void log_init (Log *log) 00278 { 00279 GtkWidget *scrolled_win, *text_view; 00280 GtkTextBuffer *text_buffer; 00281 GtkTextMark *mark; 00282 00283 /* dialog initialization */ 00284 g_object_set (G_OBJECT (log), 00285 /* GtkContainer */ 00286 "border-width", 0, 00287 /* GtkWindow */ 00288 "title", _("Status"), 00289 "default-width", 600, 00290 "default-height", 200, 00291 "modal", FALSE, 00292 "window-position", GTK_WIN_POS_NONE, 00293 "type-hint", GDK_WINDOW_TYPE_HINT_NORMAL, 00294 /* GtkDialog */ 00295 "has-separator", TRUE, 00296 NULL); 00297 00298 /* create a scrolled window for the textview */ 00299 scrolled_win = GTK_WIDGET ( 00300 g_object_new (GTK_TYPE_SCROLLED_WINDOW, 00301 /* GtkContainer */ 00302 "border-width", 5, 00303 /* GtkScrolledWindow */ 00304 "hscrollbar-policy", GTK_POLICY_AUTOMATIC, 00305 "vscrollbar-policy", GTK_POLICY_AUTOMATIC, 00306 "shadow-type", GTK_SHADOW_ETCHED_IN, 00307 NULL)); 00308 /* create the text buffer */ 00309 text_buffer = GTK_TEXT_BUFFER (g_object_new (GTK_TYPE_TEXT_BUFFER, 00310 NULL)); 00311 00312 /* Add some tags for highlighting log messages to the buffer */ 00313 gtk_text_buffer_create_tag (text_buffer, "plain", 00314 "foreground", "black", 00315 "foreground-set", TRUE, 00316 "weight", PANGO_WEIGHT_NORMAL, 00317 "weight-set", TRUE, 00318 NULL); 00319 /* The default "message" style is plain */ 00320 gtk_text_buffer_create_tag (text_buffer, "message", NULL); 00321 /* "old" messages are in dark grey */ 00322 gtk_text_buffer_create_tag (text_buffer, "old", 00323 "foreground", "#404040", 00324 "foreground-set", TRUE, 00325 NULL); 00326 /* "warning" messages are printed in red */ 00327 gtk_text_buffer_create_tag (text_buffer, "warning", 00328 "foreground", "red", 00329 "foreground-set", TRUE, 00330 NULL); 00331 /* "critical" messages are bold red */ 00332 gtk_text_buffer_create_tag (text_buffer, "critical", 00333 "foreground", "red", 00334 "foreground-set", TRUE, 00335 "weight", PANGO_WEIGHT_BOLD, 00336 "weight-set", TRUE, 00337 NULL); 00338 00339 /* create the text view and attach the buffer to it */ 00340 text_view = GTK_WIDGET (g_object_new (GTK_TYPE_TEXT_VIEW, 00341 /* GtkTextView */ 00342 /* unknown property in GTK 2.2, use gtk_text_view_set_buffer() instead */ 00343 /* "buffer", text_buffer, */ 00344 "editable", FALSE, 00345 NULL)); 00346 gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), text_buffer); 00347 00348 /* add the text view to the scrolled window */ 00349 gtk_container_add (GTK_CONTAINER (scrolled_win), text_view); 00350 /* set textview of log */ 00351 log->textview = GTK_TEXT_VIEW (text_view); 00352 00353 /* add the scrolled window to the dialog vbox */ 00354 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (log)->vbox), scrolled_win, 00355 TRUE, TRUE, 0); 00356 gtk_widget_show_all (scrolled_win); 00357 00358 /* now add the close button to the action area */ 00359 gtk_dialog_add_button (GTK_DIALOG (log), 00360 GTK_STOCK_CLOSE, LOG_RESPONSE_CLOSE); 00361 00362 /* scroll to the end of the buffer */ 00363 mark = gtk_text_buffer_get_insert (text_buffer); 00364 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (text_view), mark, 0.0, TRUE, 0.0, 1.0); 00365 }