~ubuntu-branches/ubuntu/natty/geany/natty

« back to all changes in this revision

Viewing changes to plugins/vcdiff.c

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2009-01-01 18:40:50 UTC
  • mfrom: (1.1.8 upstream) (3.1.2 experimental)
  • Revision ID: james.westby@ubuntu.com-20090101184050-u635kualu7amyt4a
Tags: 0.15-1ubuntu1
* Merge from debian experimental, remaining change:
  - patches/20_add_debdiff_as_diff_type.dpatch: Also recognize .dpatch files
    as diff's
  - debian/geany.xpm: Replace icon with a .xpm of the new one

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 * e.g. ".svn". */
29
29
 
30
30
#include "geany.h"
 
31
#include <string.h>
 
32
 
31
33
#include "support.h"
32
34
#include "plugindata.h"
33
35
#include "document.h"
 
36
#include "editor.h"
34
37
#include "filetypes.h"
35
38
#include "utils.h"
36
39
#include "project.h"
 
40
#include "ui_utils.h"
37
41
#include "pluginmacros.h"
38
42
 
39
 
 
40
 
PluginFields    *plugin_fields;
 
43
#define project geany->app->project
 
44
 
 
45
 
41
46
GeanyData               *geany_data;
42
 
 
43
 
 
44
 
PLUGIN_VERSION_CHECK(27)
45
 
 
46
 
PLUGIN_INFO(_("Version Diff"), _("Creates a patch of a file against version control."), VERSION,
 
47
GeanyFunctions  *geany_functions;
 
48
 
 
49
 
 
50
PLUGIN_VERSION_CHECK(GEANY_API_VERSION)
 
51
 
 
52
PLUGIN_SET_INFO(_("Version Diff"), _("Creates a patch of a file against version control."), VERSION,
47
53
        _("The Geany developer team"))
48
54
 
49
55
 
 
56
static GtkWidget *main_menu_item = NULL;
 
57
 
 
58
 
50
59
enum
51
60
{
52
61
        VC_COMMAND_DIFF_FILE,
74
83
static void* CVS_COMMANDS[] = { CVS_CMD_DIFF_FILE, CVS_CMD_DIFF_DIR, CVS_CMD_DIFF_PROJECT };
75
84
 
76
85
 
77
 
static const gchar* GIT_CMD_DIFF_FILE[] = {"git", "diff", BASE_FILENAME,  NULL};
78
 
static const gchar* GIT_CMD_DIFF_DIR[]  = {"git", "diff", NULL};
79
 
static const gchar* GIT_CMD_DIFF_PROJECT[] = {"git", "diff", NULL};
 
86
static const gchar* GIT_CMD_DIFF_FILE[] = {"git", "diff", "HEAD", "--", BASE_FILENAME,  NULL};
 
87
static const gchar* GIT_CMD_DIFF_DIR[]  = {"git", "diff", "HEAD", NULL};
 
88
static const gchar* GIT_CMD_DIFF_PROJECT[] = {"git", "diff", "HEAD", NULL};
80
89
 
81
90
static const gchar* GIT_ENV_DIFF_FILE[] = {"PAGER=cat", NULL};
82
91
static const gchar* GIT_ENV_DIFF_DIR[]  = {"PAGER=cat", NULL};
114
123
        gchar *base_prev = g_strdup(":");
115
124
 
116
125
        if (g_file_test(filename, G_FILE_TEST_IS_DIR))
117
 
            base = g_strdup(filename);
 
126
                base = g_strdup(filename);
118
127
        else
119
 
            base = g_path_get_dirname(filename);
 
128
                base = g_path_get_dirname(filename);
120
129
 
121
 
        while(strcmp(base, base_prev) != 0)
 
130
        while (strcmp(base, base_prev) != 0)
122
131
        {
123
 
            gitdir = g_build_path("/", base, subdir, NULL);
124
 
            ret = g_file_test(gitdir, G_FILE_TEST_IS_DIR);
125
 
            g_free(gitdir);
126
 
            if (ret)
 
132
                gitdir = g_build_path("/", base, subdir, NULL);
 
133
                ret = g_file_test(gitdir, G_FILE_TEST_IS_DIR);
 
134
                g_free(gitdir);
 
135
                if (ret)
127
136
                        break;
128
 
            g_free(base_prev);
129
 
            base_prev = base;
130
 
            base = g_path_get_dirname(base);
 
137
                g_free(base_prev);
 
138
                base_prev = base;
 
139
                base = g_path_get_dirname(base);
131
140
        }
132
141
 
133
142
        g_free(base);
155
164
                return find_subdir(filename, vc->subdir);
156
165
 
157
166
        if (g_file_test(filename, G_FILE_TEST_IS_DIR))
158
 
            base = g_strdup(filename);
 
167
                base = g_strdup(filename);
159
168
        else
160
 
            base = g_path_get_dirname(filename);
 
169
                base = g_path_get_dirname(filename);
161
170
        dir = g_build_path("/", base, vc->subdir, NULL);
162
171
 
163
172
        ret = g_file_test(dir, G_FILE_TEST_IS_DIR);
244
253
}
245
254
 
246
255
 
247
 
static int find_by_filename(const gchar* filename)
248
 
{
249
 
        guint i;
250
 
 
251
 
        for (i = 0; i < doc_array->len; i++)
252
 
        {
253
 
                if (doc_list[i].is_valid && doc_list[i].file_name &&
254
 
                        strcmp(doc_list[i].file_name, filename) == 0)
255
 
                        return i;
256
 
        }
257
 
        return -1;
258
 
}
259
 
 
260
 
 
261
 
/* name_prefix should be in UTF-8, and can have a path. */
262
 
static void show_output(const gchar *std_output, const gchar *name_prefix,
 
256
/* utf8_name_prefix can have a path. */
 
257
static void show_output(const gchar *std_output, const gchar *utf8_name_prefix,
263
258
                const gchar *force_encoding)
264
259
{
265
260
        gchar   *text, *detect_enc = NULL;
266
 
        gint    idx, page;
 
261
        gint    page;
 
262
        GeanyDocument *doc;
267
263
        GtkNotebook *book;
268
264
        gchar   *filename;
269
265
 
270
 
        filename = g_path_get_basename(name_prefix);
 
266
        filename = g_path_get_basename(utf8_name_prefix);
271
267
        setptr(filename, g_strconcat(filename, ".vc.diff", NULL));
272
268
 
273
269
        /* need to convert input text from the encoding of the original file into
274
270
         * UTF-8 because internally Geany always needs UTF-8 */
275
271
        if (force_encoding)
276
272
        {
277
 
                text = p_encoding->convert_to_utf8_from_charset(
 
273
                text = p_encodings->convert_to_utf8_from_charset(
278
274
                        std_output, (gsize)-1, force_encoding, TRUE);
279
275
        }
280
276
        else
281
277
        {
282
 
                text = p_encoding->convert_to_utf8(std_output, (gsize)-1, &detect_enc);
 
278
                text = p_encodings->convert_to_utf8(std_output, (gsize)-1, &detect_enc);
283
279
        }
284
280
        if (text)
285
281
        {
286
 
                idx = find_by_filename(filename);
287
 
                if ( idx == -1)
 
282
                doc = p_document->find_by_filename(filename);
 
283
                if (doc == NULL)
288
284
                {
289
 
                        idx = p_document->new_file(filename,
290
 
                                geany_data->filetypes[GEANY_FILETYPES_DIFF], text);
 
285
                        GeanyFiletype *ft = p_filetypes->lookup_by_name("Diff");
 
286
                        doc = p_document->new_file(filename, ft, text);
291
287
                }
292
288
                else
293
289
                {
294
 
                        p_sci->set_text(doc_list[idx].sci, text);
295
 
                        book = GTK_NOTEBOOK(app->notebook);
296
 
                        page = gtk_notebook_page_num(book, GTK_WIDGET(doc_list[idx].sci));
 
290
                        p_sci->set_text(doc->editor->sci, text);
 
291
                        book = GTK_NOTEBOOK(geany->main_widgets->notebook);
 
292
                        page = gtk_notebook_page_num(book, GTK_WIDGET(doc->editor->sci));
297
293
                        gtk_notebook_set_current_page(book, page);
298
 
                        doc_list[idx].changed = FALSE;
299
 
                        p_document->set_text_changed(idx);
 
294
                        p_document->set_text_changed(doc, FALSE);
300
295
                }
301
296
 
302
 
                p_document->set_encoding(idx,
 
297
                p_document->set_encoding(doc,
303
298
                        force_encoding ? force_encoding : detect_enc);
304
299
        }
305
300
        else
306
301
        {
307
 
                p_ui->set_statusbar(FALSE, _("Could not parse the output of the diff"));
 
302
                p_ui->set_statusbar(FALSE, _("Input conversion of the diff output failed."));
308
303
        }
309
304
        g_free(text);
310
305
        g_free(detect_enc);
346
341
                /* CVS dump stuff to stderr when diff nested dirs */
347
342
                if (strcmp(argv[0], "cvs") != 0 && NZV(std_error))
348
343
                {
349
 
                    p_dialogs->show_msgbox(1,
 
344
                        p_dialogs->show_msgbox(1,
350
345
                                _("%s exited with an error: \n%s."), argv[0], g_strstrip(std_error));
351
346
                }
352
347
                else if (NZV(std_output))
392
387
/* Make a diff from the current directory */
393
388
static void vcdirectory_activated(GtkMenuItem *menuitem, gpointer gdata)
394
389
{
395
 
        gint    idx;
 
390
        GeanyDocument *doc;
396
391
        gchar   *base_name = NULL;
397
392
        gchar   *locale_filename = NULL;
398
393
        gchar   *text;
399
394
 
400
 
        idx = p_document->get_cur_idx();
401
 
 
402
 
        g_return_if_fail(DOC_IDX_VALID(idx) && doc_list[idx].file_name != NULL);
403
 
 
404
 
        if (doc_list[idx].changed)
 
395
        doc = p_document->get_current();
 
396
 
 
397
        g_return_if_fail(doc != NULL && doc->file_name != NULL);
 
398
 
 
399
        if (doc->changed)
405
400
        {
406
 
                p_document->save_file(idx, FALSE);
 
401
                p_document->save_file(doc, FALSE);
407
402
        }
408
403
 
409
 
        locale_filename = p_utils->get_locale_from_utf8(doc_list[idx].file_name);
 
404
        locale_filename = p_utils->get_locale_from_utf8(doc->file_name);
410
405
        base_name = g_path_get_dirname(locale_filename);
411
406
 
412
407
        text = make_diff(base_name, VC_COMMAND_DIFF_DIR);
413
408
        if (text)
414
409
        {
 
410
                setptr(base_name, p_utils->get_utf8_from_locale(base_name));
415
411
                show_output(text, base_name, NULL);
416
412
                g_free(text);
417
413
        }
424
420
/* Callback if menu item for the current project was activated */
425
421
static void vcproject_activated(GtkMenuItem *menuitem, gpointer gdata)
426
422
{
427
 
        gint    idx;
 
423
        GeanyDocument *doc;
428
424
        gchar   *locale_filename = NULL;
429
425
        gchar   *text;
430
426
 
431
 
        idx = p_document->get_cur_idx();
 
427
        doc = p_document->get_current();
432
428
 
433
429
        g_return_if_fail(project != NULL && NZV(project->base_path));
434
430
 
435
 
        if (DOC_IDX_VALID(idx) && doc_list[idx].changed && doc_list[idx].file_name != NULL)
 
431
        if (doc != NULL && doc->changed && doc->file_name != NULL)
436
432
        {
437
 
                p_document->save_file(idx, FALSE);
 
433
                p_document->save_file(doc, FALSE);
438
434
        }
439
435
 
440
436
        locale_filename = p_utils->get_locale_from_utf8(project->base_path);
451
447
/* Callback if menu item for a single file was activated */
452
448
static void vcfile_activated(GtkMenuItem *menuitem, gpointer gdata)
453
449
{
454
 
        gint    idx;
455
 
        gchar   *locale_filename, *text;
456
 
 
457
 
        idx = p_document->get_cur_idx();
458
 
 
459
 
        g_return_if_fail(DOC_IDX_VALID(idx) && doc_list[idx].file_name != NULL);
460
 
 
461
 
        if (doc_list[idx].changed)
 
450
        GeanyDocument *doc;
 
451
        gchar *locale_filename, *text;
 
452
 
 
453
        doc = p_document->get_current();
 
454
 
 
455
        g_return_if_fail(doc != NULL && doc->file_name != NULL);
 
456
 
 
457
        if (doc->changed)
462
458
        {
463
 
                p_document->save_file(idx, FALSE);
 
459
                p_document->save_file(doc, FALSE);
464
460
        }
465
461
 
466
 
        locale_filename = p_utils->get_locale_from_utf8(doc_list[idx].file_name);
 
462
        locale_filename = p_utils->get_locale_from_utf8(doc->file_name);
467
463
 
468
464
        text = make_diff(locale_filename, VC_COMMAND_DIFF_FILE);
469
465
        if (text)
470
466
        {
471
 
                show_output(text, doc_list[idx].file_name, doc_list[idx].encoding);
 
467
                show_output(text, doc->file_name, doc->encoding);
472
468
                g_free(text);
473
469
        }
474
470
        g_free(locale_filename);
481
477
 
482
478
static void update_menu_items(void)
483
479
{
484
 
        document        *doc;
 
480
        GeanyDocument *doc;
485
481
        gboolean        have_file;
486
482
        gboolean    have_vc = FALSE;
487
483
 
498
494
 
499
495
 
500
496
/* Called by Geany to initialize the plugin */
501
 
void init(GeanyData *data)
 
497
void plugin_init(GeanyData *data)
502
498
{
503
499
        GtkWidget       *menu_vcdiff = NULL;
504
500
        GtkWidget       *menu_vcdiff_menu = NULL;
507
503
        tooltips = gtk_tooltips_new();
508
504
 
509
505
        menu_vcdiff = gtk_image_menu_item_new_with_mnemonic(_("_Version Diff"));
510
 
        gtk_container_add(GTK_CONTAINER(data->tools_menu), menu_vcdiff);
 
506
        gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), menu_vcdiff);
511
507
 
512
 
        g_signal_connect((gpointer) menu_vcdiff, "activate",
513
 
                G_CALLBACK(update_menu_items), NULL);
 
508
        g_signal_connect(menu_vcdiff, "activate", G_CALLBACK(update_menu_items), NULL);
514
509
 
515
510
        menu_vcdiff_menu = gtk_menu_new ();
516
511
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_vcdiff), menu_vcdiff_menu);
521
516
        gtk_tooltips_set_tip (tooltips, menu_vcdiff_file,
522
517
                _("Make a diff from the current active file"), NULL);
523
518
 
524
 
        g_signal_connect((gpointer) menu_vcdiff_file, "activate",
525
 
                G_CALLBACK(vcfile_activated), NULL);
 
519
        g_signal_connect(menu_vcdiff_file, "activate", G_CALLBACK(vcfile_activated), NULL);
526
520
 
527
521
        /* Directory */
528
522
        menu_vcdiff_dir = gtk_menu_item_new_with_mnemonic(_("From Current _Directory"));
530
524
        gtk_tooltips_set_tip (tooltips, menu_vcdiff_dir,
531
525
                _("Make a diff from the directory of the current active file"), NULL);
532
526
 
533
 
        g_signal_connect((gpointer) menu_vcdiff_dir, "activate",
534
 
                G_CALLBACK(vcdirectory_activated), NULL);
 
527
        g_signal_connect(menu_vcdiff_dir, "activate", G_CALLBACK(vcdirectory_activated), NULL);
535
528
 
536
529
        /* Project */
537
530
        menu_vcdiff_project = gtk_menu_item_new_with_mnemonic(_("From Current _Project"));
539
532
        gtk_tooltips_set_tip (tooltips, menu_vcdiff_project,
540
533
                _("Make a diff from the current project's base path"), NULL);
541
534
 
542
 
        g_signal_connect((gpointer) menu_vcdiff_project, "activate",
543
 
                G_CALLBACK(vcproject_activated), NULL);
 
535
        g_signal_connect(menu_vcdiff_project, "activate", G_CALLBACK(vcproject_activated), NULL);
544
536
 
545
537
        gtk_widget_show_all(menu_vcdiff);
546
538
 
547
 
        plugin_fields->menu_item = menu_vcdiff;
548
 
        plugin_fields->flags = PLUGIN_IS_DOCUMENT_SENSITIVE;
 
539
        p_ui->add_document_sensitive(menu_vcdiff);
 
540
        main_menu_item = menu_vcdiff;
549
541
}
550
542
 
551
543
 
552
544
/* Called by Geany before unloading the plugin. */
553
 
void cleanup(void)
 
545
void plugin_cleanup(void)
554
546
{
555
 
        /* remove the menu item added in init() */
556
 
        gtk_widget_destroy(plugin_fields->menu_item);
 
547
        /* remove the menu item added in plugin_init() */
 
548
        gtk_widget_destroy(main_menu_item);
557
549
}