1 /*
2 	Copyright (C) 2004, 2005 Stephen Bach
3 	This file is part of the Viewglob package.
4 
5 	Viewglob is free software; you can redistribute it and/or modify
6 	it under the terms of the GNU General Public License as published by
7 	the Free Software Foundation; either version 2 of the License, or
8 	(at your option) any later version.
9 
10 	Viewglob is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with Viewglob; if not, write to the Free Software
17 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include "common.h"
21 #include "string.h"
22 #include "x11-stuff.h"
23 #include "display-common.h"
24 #include "param-io.h"
25 #include "lscolors.h"
26 
27 #include <gdk/gdkx.h>
28 #include <gdk/gdkkeysyms.h>
29 
30 #include <X11/Xlib.h>
31 #include <X11/Xatom.h>
32 
33 #include "fgetopt.h"
34 
35 static void report_version(void);
36 
37 
prefs_init(struct prefs * v)38 void prefs_init(struct prefs* v) {
39 	v->show_icons = TRUE;
40 	v->jump_resize = TRUE;
41 	v->font_size_modifier = 0;
42 }
43 
44 
parse_args(int argc,char ** argv,struct prefs * v)45 void parse_args(int argc, char** argv, struct prefs* v) {
46 	gboolean in_loop = TRUE;
47 
48 	struct option long_options[] = {
49 		{ "font-size-modifier", 1, NULL, 'z' },
50 		{ "black", 1, NULL, '1' },
51 		{ "red", 1, NULL, '2' },
52 		{ "green", 1, NULL, '3' },
53 		{ "yellow", 1, NULL, '4' },
54 		{ "blue", 1, NULL, '5' },
55 		{ "magenta", 1, NULL, '6' },
56 		{ "cyan", 1, NULL, '7' },
57 		{ "white", 1, NULL, '8' },
58 		{ "jump-resize", 2, NULL, 'j' },
59 		{ "file-icons", 2, NULL, 'i' },
60 		{ "version", 0, NULL, 'V' },
61 	};
62 
63 	GdkColor color_temp;
64 
65 	optind = 0;
66 	while (in_loop) {
67 		switch (fgetopt_long(argc, argv, "j::z:i::vV", long_options, NULL)) {
68 
69 			case -1:
70 				in_loop = FALSE;
71 				break;
72 
73 			/* Font size modifier */
74 			case 'z':
75 				v->font_size_modifier = CLAMP(atoi(optarg), -10, 10);
76 				break;
77 
78 			/* Enable or disable icons */
79 			case 'i':
80 				if (!optarg || STREQ(optarg, "on"))
81 					v->show_icons = TRUE;
82 				else if (STREQ(optarg, "off"))
83 					v->show_icons = FALSE;
84 				break;
85 
86 			/* Enable or disable jump-resize */
87 			case 'j':
88 				if (!optarg || STREQ(optarg, "on"))
89 					v->jump_resize = TRUE;
90 				else if (STREQ(optarg, "off"))
91 					v->jump_resize = FALSE;
92 				break;
93 
94 			/* Colours */
95 			case '1':
96 				if (gdk_color_parse(optarg, &color_temp))
97 					set_color(TCC_BLACK, &color_temp);
98 				break;
99 			case '2':
100 				if (gdk_color_parse(optarg, &color_temp))
101 					set_color(TCC_RED, &color_temp);
102 				break;
103 			case '3':
104 				if (gdk_color_parse(optarg, &color_temp))
105 					set_color(TCC_GREEN, &color_temp);
106 				break;
107 			case '4':
108 				if (gdk_color_parse(optarg, &color_temp))
109 					set_color(TCC_YELLOW, &color_temp);
110 				break;
111 			case '5':
112 				if (gdk_color_parse(optarg, &color_temp))
113 					set_color(TCC_BLUE, &color_temp);
114 				break;
115 			case '6':
116 				if (gdk_color_parse(optarg, &color_temp))
117 					set_color(TCC_MAGENTA, &color_temp);
118 				break;
119 			case '7':
120 				if (gdk_color_parse(optarg, &color_temp))
121 					set_color(TCC_CYAN, &color_temp);
122 				break;
123 			case '8':
124 				if (gdk_color_parse(optarg, &color_temp))
125 					set_color(TCC_WHITE, &color_temp);
126 				break;
127 
128 			case 'v':
129 			case 'V':
130 				report_version();
131 				break;
132 
133 			case ':':
134 				g_warning("Option missing argument");
135 				/*exit(EXIT_FAILURE);*/
136 				break;
137 
138 			case '?':
139 			default:
140 				g_warning("Unknown option provided");
141 				/*exit(EXIT_FAILURE);*/
142 				break;
143 		}
144 	}
145 }
146 
147 
report_version(void)148 static void report_version(void) {
149 	g_print("%s %s\n", g_get_prgname(), VERSION);
150 	g_print("Released %s\n", VG_RELEASE_DATE);
151 	exit(EXIT_SUCCESS);
152 }
153 
154 
155 /* Set the application icons. */
set_icons(void)156 void set_icons(void) {
157 #include "app_icons.h"
158 
159 	GList* icons = NULL;
160 
161 	/* Setup the application icons. */
162 	icons = g_list_append(icons,
163 			gdk_pixbuf_new_from_inline(-1, icon_16x16_inline, FALSE, NULL));
164 	icons = g_list_append(icons,
165 			gdk_pixbuf_new_from_inline(-1, icon_24x24_inline, FALSE, NULL));
166 	icons = g_list_append(icons,
167 			gdk_pixbuf_new_from_inline(-1, icon_32x32_inline, FALSE, NULL));
168 	icons = g_list_append(icons,
169 			gdk_pixbuf_new_from_inline(-1, icon_36x36_inline, FALSE, NULL));
170 	gtk_window_set_default_icon_list(icons);
171 }
172 
173 
174 /* Send the id of the given window's X window to seer. */
write_xwindow_id(GtkWidget * gtk_window)175 void write_xwindow_id(GtkWidget* gtk_window) {
176 
177 	GdkWindow* gdk_window = gtk_window->window;
178 	GString* xwindow_string = g_string_new(NULL);
179 
180 	if (gdk_window)
181 		g_string_printf(xwindow_string, "%lu", GDK_WINDOW_XID(gdk_window));
182 	else {
183 		g_warning("Couldn't find an id for the display's window.");
184 		xwindow_string = g_string_assign(xwindow_string, "0");
185 	}
186 
187 	if (!put_param(STDOUT_FILENO, P_WIN_ID, xwindow_string->str)) {
188 		g_critical("Couldn't write window ID to stdout");
189 		exit(EXIT_FAILURE);
190 	}
191 
192 	g_string_free(xwindow_string, TRUE);
193 }
194 
195 
refocus_wrapped(GtkWidget * display_win_gtk,gchar * term_win_str)196 void refocus_wrapped(GtkWidget* display_win_gtk, gchar* term_win_str) {
197 	g_return_if_fail(display_win_gtk != NULL);
198 	g_return_if_fail(term_win_str != NULL);
199 	g_return_if_fail(display_win_gtk->window != NULL);
200 
201 	Display* Xdisplay;
202 	Window display_win, term_win;
203 
204 	Xdisplay = GDK_DRAWABLE_XDISPLAY(display_win_gtk->window);
205 	display_win = GDK_WINDOW_XID(display_win_gtk->window);
206 	term_win = str_to_win(term_win_str);
207 
208 	if (display_win == 0 || term_win == 0)
209 		return;
210 
211 	refocus(Xdisplay, display_win, term_win);
212 	static int i = 0; i++;
213 	g_warning("refocus %d", i);
214 }
215 
216 
raise_wrapped(GtkWidget * display_win_gtk,gchar * term_win_str)217 void raise_wrapped(GtkWidget* display_win_gtk, gchar* term_win_str) {
218 
219 	Display* Xdisplay;
220 	Window display_win, term_win;
221 
222 	Xdisplay = GDK_DRAWABLE_XDISPLAY(display_win_gtk->window);
223 	display_win = GDK_WINDOW_XID(display_win_gtk->window);
224 	term_win = str_to_win(term_win_str);
225 
226 	if (display_win == 0 || term_win == 0)
227 		return;
228 
229 	gint term_desktop = get_desktop(Xdisplay, term_win);
230 	gint disp_desktop = get_desktop(Xdisplay, display_win);
231 
232 	if (term_desktop != -1 && disp_desktop != -1
233 			&& term_desktop != disp_desktop) {
234 		window_to_desktop(Xdisplay, display_win, term_desktop);
235 	}
236 
237 	static int i = 0; i++;
238 	g_warning("raise %d", i);
239 	/*raise_window(Xdisplay, display_win, term_win, TRUE);*/
240 	//XMapRaised(Xdisplay, display_win);
241 	XRaiseWindow(Xdisplay, display_win);
242 }
243 
244 
up_to_delimiter(gchar ** ptr,char c)245 gchar* up_to_delimiter(gchar** ptr, char c) {
246 	gchar* start = *ptr;
247 	while (**ptr != c)
248 		(*ptr)++;
249 
250 	**ptr = '\0';
251 	(*ptr)++;
252 	return start;
253 }
254 
255 
256 /* Chooses a selection state based on the string's first char. */
map_selection_state(gchar c)257 FileSelection map_selection_state(gchar c) {
258 	switch (c) {
259 		case '-':
260 			return FS_NO;
261 		case '~':
262 			return FS_MAYBE;
263 		case '*':
264 			return FS_YES;
265 		default:
266 			g_warning("Unexpected selection state \"%c\".", c);
267 			return FS_NO;
268 	}
269 }
270 
271 
272 /* Chooses a file type based on the string's first char. */
map_file_type(gchar c)273 FileType map_file_type(gchar c) {
274 	switch (c) {
275 		case 'r':
276 			return FT_REGULAR;
277 		case 'e':
278 			return FT_EXECUTABLE;
279 		case 'd':
280 			return FT_DIRECTORY;
281 		case 'y':
282 			return FT_SYMLINK;
283 		case 'b':
284 			return FT_BLOCKDEV;
285 		case 'c':
286 			return FT_CHARDEV;
287 		case 'f':
288 			return FT_FIFO;
289 		case 's':
290 			return FT_SOCKET;
291 		default:
292 			g_warning("Unexpected file type \"%c\".", c);
293 			return FT_REGULAR;
294 	}
295 }
296 
297 
298 /* End the program. */
window_delete_event(GtkWidget * widget,GdkEvent * event,gpointer data)299 gboolean window_delete_event(GtkWidget* widget, GdkEvent* event,
300 		gpointer data) {
301 	gtk_main_quit();
302 	return FALSE;
303 }
304 
305 
306 /* A key has been pressed -- write it to stdout. */
window_key_press_event(GtkWidget * window,GdkEventKey * event,gpointer data)307 gboolean window_key_press_event(GtkWidget* window, GdkEventKey* event,
308 		gpointer data) {
309 
310 	gsize  bytes_written;
311 	gchar* temp1;
312 	gchar* temp2;
313 
314 	gboolean result = TRUE;
315 
316 	switch (event->keyval) {
317 		case GDK_Home:
318 		case GDK_Left:
319 		case GDK_Up:
320 		case GDK_Right:
321 		case GDK_Down:
322 		case GDK_Page_Up:
323 		case GDK_Page_Down:
324 		case GDK_End:
325 			/* These keys we let the display interpret. */
326 			result = FALSE;
327 			break;
328 
329 		default:
330 			/* The rest are passed to the terminal. */
331 			temp1 = g_malloc(2);
332 			*temp1 = event->keyval;
333 			*(temp1 + 1) = '\0';
334 
335 			/* Convert out of utf8. */
336 			temp2 = g_locale_from_utf8(temp1, -1, NULL, &bytes_written, NULL);
337 
338 			if (temp2) {
339 				if (event->state & GDK_CONTROL_MASK) {
340 					/* Control is being held.  Determine if it's a control
341 					   key and convert. */
342 					if (event->keyval >= 'a' && event->keyval <= 'z')
343 						*temp2 -= 96;
344 					else if (event->keyval >= '[' && event->keyval <= '_')
345 						*temp2 -= 64;
346 					else if (event->keyval == '@' || event->keyval == ' ')
347 						/* This will go out empty, but vgseer is smart enough
348 						   to interpret a value length of 0 as a NUL
349 						   character. */
350 						*temp2 = '\0';
351 				}
352 
353 				if (!put_param(STDOUT_FILENO, P_KEY, temp2)) {
354 					g_critical("Couldn't write key to stdout");
355 					exit(EXIT_FAILURE);
356 				}
357 
358 				g_free(temp2);
359 			}
360 			else
361 				result = FALSE;
362 
363 			g_free(temp1);
364 			break;
365 	}
366 
367 	return result;
368 }
369 
370