⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diff.c

📁 一个简单的文本编辑器
💻 C
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *//* diff.c - diff plugin. * * Copyright (C) 2000 Chema Celorio * * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <config.h>#include <gnome.h>#include <glade/glade.h>#include <libgnomevfs/gnome-vfs.h>#include "window.h"#include "document.h"#include "plugin.h"#include "view.h"#include "utils.h"#define GEDIT_PLUGIN_PROGRAM "diff"/* xgettext translators: !!!!!!!!!!!---------> the name of the plugin only.   it is used to display "you can not use the [name] plugin without this program... */#define GEDIT_PLUGIN_NAME  _("diff")#define GEDIT_PLUGIN_GLADE_FILE "/diff.glade"static GtkWidget *from_document_1;static GtkWidget *from_document_2;static GtkWidget *document_list_1;static GtkWidget *document_list_2;static GtkWidget *from_file_1;static GtkWidget *from_file_2;static GtkWidget *file_entry_1;static GtkWidget *file_entry_2;static GtkWidget *unified_checkbutton;static gint document_selected_1;static gint document_selected_2;static voidgedit_plugin_destroy (PluginData *pd){	g_free (pd->name);}static voidgedit_plugin_finish (GtkWidget *widget, gpointer data){	gnome_dialog_close (GNOME_DIALOG(widget));}static voidgedit_plugin_cancel_button_pressed (GtkWidget *widget, GtkWidget* data){	gnome_dialog_close (GNOME_DIALOG (data));}static voidgedit_plugin_help_button_pressed (GtkWidget *widget, gpointer data){	static GnomeHelpMenuEntry help_entry = { "gedit", "plugins.html#diff" };	gnome_help_display (NULL, &help_entry);}static voidgedit_plugin_execute (GtkWidget *widget, GtkWidget* data){	gint state_1;	gint state_2;	gchar * file_name_1;	gchar * file_name_2;	GeditDocument *document;	gboolean unified_mode;		int pid;	char buff[1025];	guint length, pos; 	GeditDocument *doc;	int fdpipe[2];	gchar * program_location;	GtkLabel *label;	label  = gtk_object_get_data (GTK_OBJECT (data), "location_label");	g_return_if_fail (label != NULL);	program_location = GTK_LABEL(label)->label;		unified_mode = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (unified_checkbutton)); 	gnome_config_set_bool ("/gedit/diff_plugin/unified_mode", unified_mode);	state_1 = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (from_document_1));	state_2 = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (from_document_2));	file_name_1 = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY(file_entry_1), FALSE);	file_name_2 = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY(file_entry_2), FALSE);	/* We need to:	   - if !state_1 & !state_2. Verify that the doc numbers are	   not the same. If they are display an err msg and return;	   - if state_x verify that the file exists and that we can read from	   it. If not, display err messg and return;	   -  if !state_? get the buffer with g_list_nth (mdi->child) and	   copy the buffer to a temp file in /temp. Verify that we have a temp	   place to copy the buffer to.	   - compose the diff command from the files or the temp files	   - execute the command and create a new document.	*/		if (!state_1 && !state_2 && (document_selected_1 == document_selected_2))	{		gedit_utils_error_dialog (_("The two documents you selected are the same."), data);		return;	}	if (state_1 && ((file_name_1 == NULL ) || (!g_file_exists (file_name_1))))	{		gedit_utils_error_dialog (_("The \"first\" file you selected does not exist.\n\n"					    "Please provide a valid file."), data);		return;	}	if (state_2 && ((file_name_2 == NULL ) || (!g_file_exists (file_name_2)))) 	{		gedit_utils_error_dialog (_("The \"second\" file you selected does not exist.\n\n"					    "Please provide a valid file."), data);		return;	}	if (!state_1)	{		g_free (file_name_1);		document = (GeditDocument *)g_list_nth_data (mdi->children, document_selected_1);		if (gedit_document_get_buffer_length (document) < 1)		{			gedit_utils_error_dialog (_("The \"first\" document contains no text."), data);			return;		}		file_name_1 = gedit_utils_create_temp_from_doc (document, 1);	}	if (!state_2)	{		g_free (file_name_2);		document = (GeditDocument *)g_list_nth_data (mdi->children, document_selected_2);		if (gedit_document_get_buffer_length (document) < 1)		{			gedit_utils_error_dialog (_("The \"second\" document contains no text."), data);			return;		}		file_name_2 = gedit_utils_create_temp_from_doc (document, 2);	}	if (file_name_1 == NULL || file_name_2 == NULL)	{		/* FIXME: do better error reporting ... . Chema */		gedit_utils_error_dialog (_("gedit could not create a temp file.\n\n"), data);		return;	}		document = NULL;	if (pipe (fdpipe) == -1)	{		_exit (1);	}  	pid = fork();	if (pid == 0)	{		/* New process. */	        gint i;		char *argv[5];		if (unified_mode) 			i = 1;		else			i = 0;		close (1);		dup (fdpipe[1]);		close (fdpipe[0]);		close (fdpipe[1]);      		argv[0] = "diff";				if (unified_mode) 			argv[1] = "-u";				argv[i + 1] = file_name_1;		argv[i + 2] = file_name_2;		argv[i + 3] = NULL;		execv (program_location, argv);		/* This is only reached if something goes wrong. */		_exit (1);	}	close (fdpipe[1]);	doc = gedit_document_new_with_title ("diff");	length = 1;	pos = 0;	while (length > 0)	{		buff [ length = read (fdpipe[0], buff, 1024) ] = 0;		if (length > 0)		{		     	gedit_document_insert_text (doc, buff, pos, FALSE);			pos += length;		}	}	gedit_view_set_position (gedit_view_active (), 0);	if (!state_1)		gedit_utils_delete_temp (file_name_1);	if (!state_2)		gedit_utils_delete_temp (file_name_2);	g_free (file_name_1);	g_free (file_name_2);	gnome_dialog_close (GNOME_DIALOG (data));}static voidgedit_plugin_change_location (GtkWidget *button, gpointer userdata){	GtkWidget *dialog;	GtkWidget *label;	gchar * new_location;	gedit_debug (DEBUG_PLUGINS, "");	dialog = userdata;	new_location = gedit_plugin_program_location_change (GEDIT_PLUGIN_PROGRAM,							     GEDIT_PLUGIN_NAME);	if ( new_location == NULL)	{		gdk_window_raise (dialog->window);		return;	}	/* We need to update the label */	label  = gtk_object_get_data (GTK_OBJECT (dialog), "location_label");	g_return_if_fail (label!=NULL);	gtk_label_set_text (GTK_LABEL (label),			    new_location);	g_free (new_location);	gdk_window_raise (dialog->window);	}static voidgedit_plugin_diff_update_document (GtkWidget *widget, gpointer data){	gint item = GPOINTER_TO_INT (data);	if (item>999)		document_selected_2 = item-1000;	else		document_selected_1 = item;}static voidgedit_plugin_diff_load_documents (GtkWidget ** options_menu, gint second_menu){	GtkWidget *menu;	GtkWidget *menu_item;	gint n;	GeditDocument *nth_doc;	gchar * document_name;		menu = gtk_menu_new();     	for (n = 0; n < g_list_length (mdi->children); n++)	{		nth_doc = (GeditDocument *)g_list_nth_data (mdi->children, n);		if (nth_doc->filename == NULL) {			document_name = g_strdup_printf (_("Untitled %i"), nth_doc->untitled_number);		} else {			document_name = gnome_vfs_unescape_string_for_display (nth_doc->filename);				}						menu_item = gtk_menu_item_new_with_label (g_basename(document_name));		gtk_signal_connect (GTK_OBJECT (menu_item), "activate",				    GTK_SIGNAL_FUNC (gedit_plugin_diff_update_document),				    GINT_TO_POINTER (n+(second_menu?1000:0)));		gtk_menu_append (GTK_MENU (menu), menu_item);		g_free (document_name);	}     	gtk_option_menu_set_menu (GTK_OPTION_MENU(*options_menu), menu);}static voidgedit_plugin_diff_file_selected (GtkWidget *widget, gpointer data){	GtkToggleButton *toggle_button = data;	g_return_if_fail (toggle_button!=NULL);	gtk_toggle_button_set_active (toggle_button, TRUE);}static voidgedit_plugin_diff_file_selected_event (GtkWidget *widget, GdkEvent *event, gpointer data){	gedit_plugin_diff_file_selected (widget, data);}static voidgedit_plugin_diff_document_selected (GtkWidget *widget, GdkEvent *event, gpointer data){	gedit_plugin_diff_file_selected (widget, data);}static voidgedit_plugin_create_dialog (void){	GladeXML *gui;	GtkWidget *dialog;	GtkWidget *change_button;	GtkWidget *location_label;	GtkWidget *ok_button;	GtkWidget *cancel_button;	GtkWidget *help_button;	GtkWidget *file_selector_combo_1;	GtkWidget *file_selector_combo_2;		gchar * program_location;	gboolean unified_mode;	program_location = gedit_plugin_program_location_get (GEDIT_PLUGIN_PROGRAM,							      GEDIT_PLUGIN_NAME,							      FALSE);	g_return_if_fail (program_location != NULL);	gui = glade_xml_new (GEDIT_GLADEDIR			     GEDIT_PLUGIN_GLADE_FILE,			     NULL);	if (!gui)	{		g_warning ("Could not find %s",			   GEDIT_GLADEDIR			   GEDIT_PLUGIN_GLADE_FILE);		return;	}	dialog                 = glade_xml_get_widget (gui, "dialog");	from_document_1        = glade_xml_get_widget (gui, "from_document_1");	document_list_1        = glade_xml_get_widget (gui, "document_list_1");		from_file_1            = glade_xml_get_widget (gui, "from_file_1");	file_entry_1           = glade_xml_get_widget (gui, "file_entry_1");	file_selector_combo_1  = glade_xml_get_widget (gui, "file_selector_combo_1");	from_document_2        = glade_xml_get_widget (gui, "from_document_2");	document_list_2        = glade_xml_get_widget (gui, "document_list_2");	from_file_2            = glade_xml_get_widget (gui, "from_file_2");	file_entry_2           = glade_xml_get_widget (gui, "file_entry_2");	file_selector_combo_2  = glade_xml_get_widget (gui, "file_selector_combo_2");	location_label         = glade_xml_get_widget (gui, "location_label");	change_button          = glade_xml_get_widget (gui, "change_button");	unified_checkbutton    = glade_xml_get_widget (gui, "unified_checkbutton");		ok_button              = glade_xml_get_widget (gui, "ok_button");	cancel_button          = glade_xml_get_widget (gui, "cancel_button");	help_button            = glade_xml_get_widget (gui, "help_button");	g_return_if_fail (dialog                != NULL);		g_return_if_fail (from_document_1       != NULL);	g_return_if_fail (document_list_1       != NULL);	g_return_if_fail (from_file_1           != NULL);	g_return_if_fail (file_entry_1          != NULL);	g_return_if_fail (file_selector_combo_1 != NULL);	g_return_if_fail (from_document_2       != NULL);	g_return_if_fail (document_list_2       != NULL);	g_return_if_fail (from_file_2           != NULL);	g_return_if_fail (file_entry_2          != NULL);	g_return_if_fail (file_selector_combo_2 != NULL);	g_return_if_fail (location_label        != NULL);	g_return_if_fail (change_button         != NULL);	g_return_if_fail (unified_checkbutton   != NULL);		g_return_if_fail (ok_button             != NULL);	g_return_if_fail (cancel_button         != NULL);	g_return_if_fail (help_button           != NULL);	/* Set the location label */	gtk_object_set_data (GTK_OBJECT (dialog), "location_label", location_label);	gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (gui, "location_label")),			    program_location);	g_free (program_location);		unified_mode = gnome_config_get_bool ("/gedit/diff_plugin/unified_mode=FALSE");	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (unified_checkbutton), unified_mode); 	        /* Connect the signals */	gtk_signal_connect (GTK_OBJECT (ok_button), "clicked",			    GTK_SIGNAL_FUNC (gedit_plugin_execute), dialog);	gtk_signal_connect (GTK_OBJECT (cancel_button), "clicked",			    GTK_SIGNAL_FUNC (gedit_plugin_cancel_button_pressed), dialog);	gtk_signal_connect (GTK_OBJECT (help_button), "clicked",			    GTK_SIGNAL_FUNC (gedit_plugin_help_button_pressed), NULL);		gtk_signal_connect (GTK_OBJECT (dialog), "destroy",			    GTK_SIGNAL_FUNC (gedit_plugin_finish), NULL);	gtk_signal_connect (GTK_OBJECT (change_button), "clicked",			    GTK_SIGNAL_FUNC (gedit_plugin_change_location), dialog);	/* Load and connect the document list */	gtk_signal_connect (GTK_OBJECT (document_list_1), "button_press_event",			    GTK_SIGNAL_FUNC (gedit_plugin_diff_document_selected),			    from_document_1);	gtk_signal_connect (GTK_OBJECT (document_list_2), "button_press_event",			    GTK_SIGNAL_FUNC (gedit_plugin_diff_document_selected),			    from_document_2);		document_selected_1 = 0;	document_selected_2 = 0;	if (g_list_length (mdi->children) == 0)	{		gtk_widget_set_sensitive (from_document_1, FALSE);		gtk_widget_set_sensitive (from_document_2, FALSE);		gtk_widget_set_sensitive (document_list_1, FALSE);		gtk_widget_set_sensitive (document_list_2, FALSE);		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (from_file_1), TRUE);		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (from_file_2), TRUE);	}	else	{ 		gedit_plugin_diff_load_documents (&document_list_1, FALSE); 		gedit_plugin_diff_load_documents (&document_list_2, TRUE);	}	gtk_signal_connect (GTK_OBJECT (file_entry_1), "browse_clicked",			    GTK_SIGNAL_FUNC (gedit_plugin_diff_file_selected),			    from_file_1);	gtk_signal_connect (GTK_OBJECT (file_selector_combo_1), "focus_in_event",			    GTK_SIGNAL_FUNC (gedit_plugin_diff_file_selected_event),			    from_file_1);	gtk_signal_connect (GTK_OBJECT (file_entry_2), "browse_clicked",			    GTK_SIGNAL_FUNC (gedit_plugin_diff_file_selected),			    from_file_2);	gtk_signal_connect (GTK_OBJECT (file_selector_combo_2), "focus_in_event",			    GTK_SIGNAL_FUNC (gedit_plugin_diff_file_selected_event),			    from_file_2);	/* Set the dialog parent and modal type */ 	gnome_dialog_set_parent  (GNOME_DIALOG (dialog), gedit_window_active());	gtk_window_set_modal     (GTK_WINDOW (dialog), TRUE);	gnome_dialog_set_default (GNOME_DIALOG (dialog), 0);	/* Show everything then free the GladeXML memmory */	gtk_widget_show_all (dialog);	gtk_object_unref (GTK_OBJECT (gui));}gintinit_plugin (PluginData *pd){	/* initialize */	pd->destroy_plugin = gedit_plugin_destroy;	pd->name = _("Diff");	pd->desc = _("Makes a diff file from two documents or files");	pd->long_desc = _("Makes a diff file from two documents or files on disk\n"			  "For more info on diff, type \"man diff\" in a shell prompt\n");	pd->author = "Chema Celorio";	pd->needs_a_document = FALSE;	pd->private_data = (gpointer)gedit_plugin_create_dialog;	pd->installed_by_default = TRUE;		return PLUGIN_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -