1 /*
2  *      externdiff.h - Plugin to geany light IDE to work with vc
3  *
4  *      Copyright 2008 Yura Siamashka <yurand2@gmail.com>
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 2 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program; if not, write to the Free Software
18  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include <string.h>
22 #include <geanyplugin.h>
23 #include "geanyvc.h"
24 
25 #ifdef G_OS_WIN32
26 #include <shlobj.h>
27 #endif
28 
29 
30 enum
31 {
32 	EXTERNAL_DIFF_MELD,
33 	EXTERNAL_DIFF_KOMPARE,
34 	EXTERNAL_DIFF_KDIFF3,
35 	EXTERNAL_DIFF_DIFFUSE,
36 	EXTERNAL_DIFF_TKDIFF,
37 	EXTERNAL_DIFF_WINMERGE,
38 	EXTERNAL_DIFF_COUNT
39 };
40 
41 
42 static const gchar *viewers[EXTERNAL_DIFF_COUNT] = { "Meld/meld", "kompare", "kdiff3", "diffuse", "tkdiff", "WinMerge/WinMergeU" };
43 
44 static gchar *extern_diff_viewer = NULL;
45 
external_diff_viewer_init(void)46 void external_diff_viewer_init(void)
47 {
48 	gint i;
49 
50 	for (i = 0; i < EXTERNAL_DIFF_COUNT; i++)
51 	{
52 		gchar *filename = g_path_get_basename(viewers[i]);
53 		gchar *path = g_find_program_in_path(filename);
54 		g_free(filename);
55 		if (path)
56 		{
57 			extern_diff_viewer = path;
58 			return;
59 		}
60 	}
61 #ifdef G_OS_WIN32
62 	TCHAR szPathProgramFiles[MAX_PATH];
63 	TCHAR szPathProgramFiles86[MAX_PATH];
64 	SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, szPathProgramFiles);
65 	SHGetFolderPath(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, szPathProgramFiles86);
66 
67 	for (i = 0; i < EXTERNAL_DIFF_COUNT; i++)
68 	{
69 		gchar *filename = g_build_filename(szPathProgramFiles, viewers[i], NULL);
70 		gchar *path = g_find_program_in_path(filename);
71 		g_free(filename);
72 		if (path)
73 		{
74 			extern_diff_viewer = path;
75 			return;
76 		}
77 	}
78 	for (i = 0; i < EXTERNAL_DIFF_COUNT; i++)
79 	{
80 		gchar *filename = g_build_filename(szPathProgramFiles86, viewers[i], NULL);
81 		gchar *path = g_find_program_in_path(filename);
82 		g_free(filename);
83 		if (path)
84 		{
85 			extern_diff_viewer = path;
86 			return;
87 		}
88 	}
89 #endif
90 }
91 
external_diff_viewer_deinit(void)92 void external_diff_viewer_deinit(void)
93 {
94 	if (extern_diff_viewer)
95 	{
96 		g_free(extern_diff_viewer);
97 		extern_diff_viewer = NULL;
98 	}
99 }
100 
101 const gchar *
get_external_diff_viewer(void)102 get_external_diff_viewer(void)
103 {
104 	if (extern_diff_viewer)
105 		return extern_diff_viewer;
106 	return NULL;
107 }
108 
109 
110 void
vc_external_diff(const gchar * src,const gchar * dest)111 vc_external_diff(const gchar * src, const gchar * dest)
112 {
113 	gchar *argv[4] = { NULL, NULL, NULL, NULL };
114 	const gchar *diff = get_external_diff_viewer();
115 	if (!diff)
116 		return;
117 
118 	argv[0] = (gchar *) diff;
119 	argv[1] = (gchar *) src;
120 	argv[2] = (gchar *) dest;
121 
122 	g_spawn_sync(NULL, argv, NULL,
123 			 G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL |
124 			 G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, NULL, NULL, NULL);
125 }
126