/* console.c * This file is part of "Pharmacy: A GNOME CVS front-end" * Copyright 1998 Reklaw (N. Adam Walker) * Copyright 2000, 2001 Matthias Kranz * "Pharmacy" is released under the GPL. * See the LICENCE for more details. */ #include #include #include "console.h" #include "pharmacy.h" #include #define BUFSIZE 255 #define MENU_GO 0 #define MENU_STOP 1 #define TOOLBAR_STOP 9 /* sep */ #define MENU_CLEAR 3 #define MENU_PRINT 4 void console_execute_cmd_in_dir (const gchar * text, const gchar * dir) { gchar output[BUFSIZE]; gchar *cmd = NULL; CVSConsole *pCon = pharmacy_get_console (); g_assert (pCon); g_assert (text); g_assert (dir); g_debug_message (text); if (agent_in_use (pharmacy_get_agent ())) { /* Warning */ gnome_app_message (GNOME_APP (pharmacy_get_app ()), "The console is busy."); } else { /* Emit a ui update */ cmd = g_strconcat ("(cd ", dir, " ; ", text, " ) 2>&1", NULL); gnome_appbar_push (pharmacy_get_appbar (), g_strconcat (_("Executing... "), text, NULL)); gtk_widget_set_sensitive (pCon->pGo, FALSE); g_assert (pharmacy_get_agent ()); agent_run (pharmacy_get_agent (), cmd); pharmacy_update_ui ("run-begin"); gnome_appbar_pop (pharmacy_get_appbar ()); } } void console_execute_cmd (const gchar * text) { CVSConsole *pCon = pharmacy_get_console (); g_assert (pCon); g_assert (pCon->pCurrentNode && pCon->pCurrentNode->pgcDir); console_execute_cmd_in_dir (text, pCon->pCurrentNode->pgcDir); } static void go_set_sensitive (CVSConsole * pCon, gint b) { g_return_if_fail (pCon); g_return_if_fail (GTK_IS_BUTTON (pCon->pGo)); g_return_if_fail (console_menu[MENU_GO].widget); gtk_widget_set_sensitive (pCon->pGo, b); gtk_widget_set_sensitive (console_menu[MENU_GO].widget, b); pCon->bGo = b; } static void stop_set_sensitive (CVSConsole * pCon, gint b) { g_return_if_fail (pCon); g_return_if_fail (GTK_IS_BUTTON (pCon->pStop)); g_return_if_fail (console_menu[MENU_STOP].widget); gtk_widget_set_sensitive (pCon->pStop, b); gtk_widget_set_sensitive (console_menu[MENU_STOP].widget, b); gtk_widget_set_sensitive (toolbar[TOOLBAR_STOP].widget, b); pCon->bStop = b; } static void stop_cb () { gdk_flush (); if (GTK_WIDGET (pharmacy_get_console ()->pStop)->state != GTK_STATE_INSENSITIVE) { agent_abort (pharmacy_get_agent ()); pharmacy_update_ui ("console-stop"); } } void stop_menu_cb () { stop_cb (); } /* User Interface Update */ static void console_ui_update_cb (gchar * pgcHint) { Agent *pAgent = pharmacy_get_agent (); CVSConsole *pCon = pharmacy_get_console (); gint bDirExists = TRUE; gint bHasContent = FALSE; g_return_if_fail (pAgent); g_return_if_fail (pCon); g_return_if_fail (pgcHint); /* ignore it if it is a row-[un]select */ if (strstr (pgcHint, "row-")) return; if (pCon->pCurrentNode) { if (g_file_exists (pCon->pCurrentNode->pgcDir)) { gtk_widget_set_sensitive (pCon->pCmdLine, TRUE); bDirExists = TRUE; } else { gtk_widget_set_sensitive (pCon->pCmdLine, FALSE); bDirExists = FALSE; } } else { gtk_widget_set_sensitive (pCon->pCmdLine, FALSE); bDirExists = FALSE; } if (agent_in_use (pAgent)) { go_set_sensitive (pCon, FALSE); stop_set_sensitive (pCon, TRUE); } else { go_set_sensitive (pCon, bDirExists); stop_set_sensitive (pCon, FALSE); } if (gtk_text_get_length (GTK_TEXT (pCon->pOutput))) bHasContent = TRUE; gtk_widget_set_sensitive (console_menu[MENU_PRINT].widget, bHasContent); gtk_widget_set_sensitive (console_menu[MENU_CLEAR].widget, bHasContent); } /* 'Go' button on the console */ static void go_cb (GtkButton * pButton) { gchar *text; gchar output[BUFSIZE]; gchar *cmd = NULL; CVSConsole *pCon = pharmacy_get_console (); gdk_flush (); g_return_if_fail (pCon); g_return_if_fail (pCon->bGo); text = g_strdup (gtk_entry_get_text (GTK_ENTRY (pCon->pCmdLine))); if (pCon->pAgent->input_id == -1) { console_execute_cmd (text); gtk_entry_set_text (GTK_ENTRY (pCon->pCmdLine), ""); } g_free (text); } void go_menu_cb () { go_cb (NULL); } /* Callback: When a process controlled by the 'agent' receives input display it on the console. */ static void console_agent_reader (Agent * pAgent, gchar * str, gint count) { CVSConsole *pCon = pharmacy_get_console (); if (pAgent && str && count && pCon) { gtk_text_insert (GTK_TEXT (pCon->pOutput), NULL, NULL, NULL, str, count); } else { g_assert (0); } gdk_flush (); } static void agent_stream_cb (Agent * agent, gchar * str, gint len) { CVSConsole *pCon = pharmacy_get_console (); if (pCon && len && str && agent) { gtk_text_insert (GTK_TEXT (pCon->pOutput), NULL, NULL, NULL, str, len); } else { g_assert (0); } gdk_flush (); } static void console_agent_done (Agent * pAgent) { /* Don't want to rebuild all the time */ /*filelist_rebuild_list(pharmacy_get_filelist(), pharmacy_get_console()->pCurrentNode); */ pharmacy_update_ui ("console-done"); } CVSConsole * console_new () { CVSConsole *pConsole = g_malloc (sizeof (CVSConsole)); GtkWidget *phBox = NULL; GtkWidget *pScroll = NULL; GtkWidget *phOutBox = NULL; GtkTooltips *pToolTips = NULL; gchar *str = NULL; gint len; pConsole->bGo = FALSE; pConsole->bStop = FALSE; phBox = gtk_hbox_new (0, 0); pConsole->pvBox = gtk_vbox_new (0, 0); pConsole->pOutput = gtk_text_new (NULL, NULL); pConsole->pCmdLine = gtk_entry_new (); pConsole->pCurrentNode = NULL; pConsole->pGo = gtk_button_new (); pConsole->pStop = gtk_button_new (); pConsole->pClear = gtk_button_new (); gtk_button_set_relief (GTK_BUTTON (pConsole->pGo), GTK_RELIEF_NONE); gtk_button_set_relief (GTK_BUTTON (pConsole->pStop), GTK_RELIEF_NONE); gtk_button_set_relief (GTK_BUTTON (pConsole->pClear), GTK_RELIEF_NONE); gtk_container_add (GTK_CONTAINER (pConsole->pGo), gnome_stock_pixmap_widget_at_size (GTK_WIDGET (pConsole->pGo), GNOME_STOCK_PIXMAP_FORWARD, 16, 16)); gtk_widget_show (GTK_WIDGET (GTK_BIN (pConsole->pGo)->child)); gtk_container_add (GTK_CONTAINER (pConsole->pStop), gnome_stock_pixmap_widget_at_size (GTK_WIDGET (pConsole->pStop), GNOME_STOCK_PIXMAP_STOP, 16, 16)); gtk_widget_show (GTK_WIDGET (GTK_BIN (pConsole->pStop)->child)); gtk_container_add (GTK_CONTAINER (pConsole->pClear), gnome_stock_pixmap_widget_at_size (GTK_WIDGET (pConsole->pClear), GNOME_STOCK_PIXMAP_CLEAR, 16, 16)); gtk_widget_show (GTK_WIDGET (GTK_BIN (pConsole->pClear)->child)); pConsole->pAgent = AGENT (agent_new ()); phOutBox = gtk_hbox_new (0, 0); pScroll = gtk_vscrollbar_new (GTK_TEXT (pConsole->pOutput)->vadj); gtk_box_pack_start (GTK_BOX (phOutBox), pConsole->pOutput, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (phOutBox), pScroll, FALSE, FALSE, 0); gtk_text_set_editable (GTK_TEXT (pConsole->pOutput), FALSE); gtk_widget_set_sensitive (pConsole->pCmdLine, FALSE); gtk_widget_set_sensitive (pConsole->pGo, FALSE); gtk_signal_connect (GTK_OBJECT (pConsole->pCmdLine), "activate", go_cb, NULL); gtk_signal_connect (GTK_OBJECT (pConsole->pGo), "clicked", go_cb, NULL); gtk_signal_connect (GTK_OBJECT (pConsole->pStop), "clicked", stop_cb, NULL); gtk_signal_connect (GTK_OBJECT (pConsole->pClear), "clicked", console_clear_cb, NULL); gtk_box_pack_start (GTK_BOX (phBox), pConsole->pCmdLine, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (phBox), pConsole->pGo, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (phBox), pConsole->pStop, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (phBox), pConsole->pClear, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (pConsole->pvBox), phOutBox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (pConsole->pvBox), phBox, FALSE, FALSE, 3); #define NEWLINE "\r\n" str = g_strconcat (PACKAGE, " ", VERSION, _(" Copyright 1999 N. Adam Walker, 2000, 2001 Matthias Kranz " "comes with ABSOLUTELY NO WARRANTY."), NEWLINE, _("This is free software, and you " "are welcome to redistrubute it " "under certain conditions; see " "the GNU General Public License " "version 2 for details."), NEWLINE, NULL); len = strlen (str); gtk_text_insert (GTK_TEXT (pConsole->pOutput), NULL, NULL, NULL, str, len); gtk_widget_show (phOutBox); gtk_widget_show (pScroll); gtk_widget_show (phBox); gtk_widget_show (pConsole->pGo); gtk_widget_show (pConsole->pStop); gtk_widget_show (pConsole->pClear); gtk_widget_show (pConsole->pvBox); gtk_widget_show (pConsole->pOutput); gtk_widget_show (pConsole->pCmdLine); pToolTips = gtk_tooltips_new (); gtk_tooltips_set_tip (pToolTips, pConsole->pGo, _("Execute command."), NULL); pToolTips = gtk_tooltips_new (); gtk_tooltips_set_tip (pToolTips, pConsole->pStop, _("Stop executing current command."), NULL); pToolTips = gtk_tooltips_new (); gtk_tooltips_set_tip (pToolTips, pConsole->pClear, _("Clear console output."), NULL); /* connect signals to agent */ gtk_signal_connect (GTK_OBJECT (pConsole->pAgent), AGENT_READ_CHILD_OUTPUT_SIGNAL, console_agent_reader, NULL); gtk_signal_connect (GTK_OBJECT (pConsole->pAgent), AGENT_STREAM_SIGNAL, agent_stream_cb, NULL); gtk_signal_connect (GTK_OBJECT (pConsole->pAgent), AGENT_CHILD_DIED_SIGNAL, console_agent_done, NULL); gtk_signal_connect (GTK_OBJECT (pharmacy_get_app ()), PHARMACY_UI_UPDATE_SIGNAL, console_ui_update_cb, NULL); return pConsole; } GtkWidget * console_get_widget (CVSConsole * pConsole) { g_assert (pConsole); return pConsole->pvBox; } void console_set_node (CVSConsole * pCVS, DirTreeNode * pNode) { g_assert (pCVS); pCVS->pCurrentNode = pNode; } static gint nPrintDoneSignal = -1; static gchar pgcTempFilename[] = "/tmp/pharmacy.XXXXXX"; static void print_done (Agent * pAgent) { gtk_signal_disconnect (GTK_OBJECT (pAgent), nPrintDoneSignal); unlink (pgcTempFilename); gnome_appbar_pop (pharmacy_get_appbar ()); } void console_print_cb () { FILE *fTemp = NULL; gchar *cmd = NULL; GtkText *pTextWidget = GTK_TEXT (pharmacy_get_console ()->pOutput); strcpy (pgcTempFilename, "/tmp/pharmacy.XXXXXX"); gnome_appbar_push (pharmacy_get_appbar (), _("Printing...")); mkstemp (pgcTempFilename); fTemp = fopen (pgcTempFilename, "w"); fwrite (pTextWidget->text.ch, pTextWidget->text_end - pTextWidget->gap_size, 1, fTemp); fclose (fTemp); nPrintDoneSignal = gtk_signal_connect (GTK_OBJECT (pharmacy_get_agent ()), "child_died", print_done, NULL); g_debug_message (pgcTempFilename); cmd = g_strconcat ("lpr ", pgcTempFilename, NULL); console_execute_cmd (cmd); g_free (cmd); } void console_clear_cb () { GtkText *pText = GTK_TEXT (pharmacy_get_console ()->pOutput); gtk_text_backward_delete (pText, gtk_text_get_length (pText)); pharmacy_update_ui ("clear-console"); }