2
#include <glib/gi18n.h>
9
#include <signal.h> /* for kill(2) */
11
#include "ptk-utils.h"
13
typedef struct _PtkConsoleOutputData
22
GIOChannel *chstdo, *chstdi, *chstde;
23
}PtkConsoleOutputData;
25
static gboolean on_complete( gpointer user_data )
27
GtkAdjustment* adj = GTK_ADJUSTMENT( user_data );
29
gtk_adjustment_set_value( adj, adj->upper-adj->page_size );
34
static gboolean delayed_destroy( gpointer dlg )
37
gtk_widget_destroy( GTK_WIDGET( dlg ) );
42
static gboolean on_output( GIOChannel* ch, GIOCondition cond, gpointer user_data )
49
PtkConsoleOutputData *data = (PtkConsoleOutputData*)user_data;
53
g_io_channel_read_chars( ch, buffer, sizeof(buffer), &rlen, NULL );
55
/*gdk_window_freeze_updates( GTK_WIDGET(data->view)->window );*/
56
gtk_text_buffer_get_end_iter( data->buf, &it );
57
gtk_text_buffer_insert( data->buf, &it, buffer, rlen );
58
adj = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(data->scroll) );
59
gtk_adjustment_set_value( adj, adj->upper-adj->page_size );
60
/*gdk_window_thaw_updates( GTK_WIDGET(data->view)->window );*/
63
if( cond == G_IO_HUP )
65
if( data->chstdo == ch )
67
strcpy(buffer, _("\nComplete!"));
68
rlen = strlen(buffer);
72
gtk_text_buffer_get_end_iter( data->buf, &it );
73
gtk_text_buffer_insert( data->buf, &it, buffer, rlen );
74
gtk_dialog_set_response_sensitive( GTK_DIALOG(data->main_dlg), GTK_RESPONSE_CANCEL, FALSE );
75
gtk_dialog_set_response_sensitive( GTK_DIALOG(data->main_dlg), GTK_RESPONSE_CLOSE, TRUE );
80
waitpid( data->pid, &status, 0 );
83
if( WIFEXITED(status) && 0 == WEXITSTATUS(status) )
85
g_idle_add( delayed_destroy, data->main_dlg );
89
adj = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(data->scroll) );
90
gtk_adjustment_set_value( adj, adj->upper-adj->page_size );
91
g_idle_add( on_complete, adj );
101
static void on_destroy( gpointer data, GObject* obj )
104
PtkConsoleOutputData* ptk_data = (PtkConsoleOutputData *)data;
107
while( g_source_remove_by_user_data( ptk_data ) );
109
if( ptk_data->chstdo )
111
g_io_channel_unref(ptk_data->chstdo);
112
close( ptk_data->stdo );
114
if( ptk_data->chstde )
116
g_io_channel_unref(ptk_data->chstde);
117
close( ptk_data->stde );
122
kill( ptk_data->pid, 15 );
123
waitpid( ptk_data->pid, &status, 0 );
125
g_slice_free( PtkConsoleOutputData, ptk_data );
128
static void on_response( GtkDialog* dlg, int response,
129
PtkConsoleOutputData* data )
131
gtk_widget_destroy( data->main_dlg );
134
int ptk_console_output_run( GtkWindow* parent_win,
137
const char* working_dir,
138
int argc, char* argv[] )
141
GtkWidget* desc_label;
142
PtkConsoleOutputData* data;
145
GdkColor black={0}, white={0, 65535, 65535, 65535};
149
data = g_slice_new0( PtkConsoleOutputData );
150
cmd = g_strjoinv( " ", &argv[0] );
152
main_dlg = gtk_dialog_new_with_buttons( title, NULL, 0,
153
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
154
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL );
155
gtk_dialog_set_alternative_button_order( GTK_DIALOG(main_dlg), GTK_RESPONSE_CLOSE, GTK_RESPONSE_CANCEL, -1 );
157
g_object_weak_ref( G_OBJECT(main_dlg), on_destroy, data );
159
data->main_dlg = main_dlg;
160
gtk_dialog_set_response_sensitive( GTK_DIALOG(main_dlg), GTK_RESPONSE_CLOSE, FALSE );
161
gtk_window_set_type_hint( GTK_WINDOW(main_dlg),
162
GDK_WINDOW_TYPE_HINT_NORMAL );
164
desc_label = gtk_label_new( desc );
165
gtk_label_set_line_wrap( GTK_LABEL(desc_label), TRUE );
166
gtk_box_pack_start( GTK_BOX(GTK_DIALOG(main_dlg)->vbox),
167
desc_label, FALSE, TRUE, 2 );
169
hbox = gtk_hbox_new( FALSE, 2 );
171
gtk_box_pack_start( GTK_BOX(hbox), gtk_label_new( _("Command:") ),
174
entry = gtk_entry_new();
175
gtk_entry_set_text( GTK_ENTRY(entry), cmd );
176
gtk_editable_set_position( GTK_EDITABLE(entry), 0 );
177
gtk_editable_set_editable( GTK_EDITABLE(entry), FALSE );
178
gtk_editable_select_region( GTK_EDITABLE(entry), 0, 0 );
180
gtk_box_pack_start( GTK_BOX(hbox), entry, TRUE, TRUE, 2 );
182
gtk_box_pack_start( GTK_BOX(GTK_DIALOG(main_dlg)->vbox),
183
hbox, FALSE, TRUE, 2 );
185
data->buf = GTK_TEXT_BUFFER(gtk_text_buffer_new(NULL));
186
data->view = GTK_TEXT_VIEW(gtk_text_view_new_with_buffer( data->buf ));
187
gtk_widget_modify_base( GTK_WIDGET(data->view), GTK_STATE_NORMAL, &black );
188
gtk_widget_modify_text( GTK_WIDGET(data->view), GTK_STATE_NORMAL, &white );
189
data->scroll = gtk_scrolled_window_new(NULL, NULL);
190
gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(data->scroll),
191
GTK_POLICY_AUTOMATIC,
193
gtk_container_add( GTK_CONTAINER(data->scroll), GTK_WIDGET(data->view) );
194
gtk_box_pack_start( GTK_BOX(GTK_DIALOG(main_dlg)->vbox), data->scroll, TRUE, TRUE, 2 );
195
gtk_widget_show_all( GTK_DIALOG(main_dlg)->vbox );
196
gtk_window_set_default_size( GTK_WINDOW(main_dlg), 480, 240 );
198
gtk_widget_show( main_dlg );
200
if( g_spawn_async_with_pipes( working_dir, argv, NULL,
201
G_SPAWN_SEARCH_PATH, NULL, NULL,
202
&data->pid, NULL/*&stdi*/,
203
&data->stdo, &data->stde, &err ) )
205
/* fcntl(stdi,F_SETFL,O_NONBLOCK); */
206
fcntl(data->stdo,F_SETFL,O_NONBLOCK);
207
fcntl(data->stde,F_SETFL,O_NONBLOCK);
209
data->chstdo = g_io_channel_unix_new( data->stdo );
210
g_io_channel_set_encoding( data->chstdo, NULL, NULL );
211
g_io_channel_set_buffered( data->chstdo, FALSE );
212
g_io_add_watch( data->chstdo, G_IO_IN|G_IO_HUP, on_output, data );
214
fcntl(data->stde,F_SETFL,O_NONBLOCK);
215
data->chstde = g_io_channel_unix_new( data->stde );
216
g_io_channel_set_encoding( data->chstde, NULL, NULL );
217
g_io_channel_set_buffered( data->chstde, FALSE );
218
g_io_add_watch( data->chstde, G_IO_IN|G_IO_HUP, on_output, data );
219
g_signal_connect( main_dlg, "delete-event", G_CALLBACK(gtk_widget_destroy), NULL );
220
g_signal_connect( main_dlg, "response", G_CALLBACK(on_response), data );
224
gtk_widget_destroy( main_dlg );
225
ptk_show_error( parent_win, _("Error"), err->message );