1 /* $Id: gtkconcb.c,v 1.3 2003/12/13 12:52:58 j_ali Exp $ */
2 /* Copyright (c) Slash'EM Development Team 2003 */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include <stdlib.h>
6 #include <errno.h>
7 #include <gtk/gtk.h>
8 #include "gtkconcb.h"
9 #include "gtkconnect.h"
10 #include "gtksupport.h"
11 #include "winGTK.h"
12 #include "prxyclnt.h"
13 
14 void
GTK_add_connection(GtkButton * button,gpointer user_data)15 GTK_add_connection(GtkButton *button, gpointer user_data)
16 {
17     GtkWidget *w = create_AddConnection();
18     gtk_widget_show(w);
19 }
20 
21 void
GTK_edit_connection(GtkTreeView * treeview,gpointer user_data)22 GTK_edit_connection(GtkTreeView *treeview, gpointer user_data)
23 {
24     GtkTreeSelection *sel = gtk_tree_view_get_selection(treeview);
25     GtkWidget *w = NULL;
26     GtkEntry *entry;
27     GtkTreeModel *model;
28     GtkTreeIter iter;
29     gchar *name, *scheme, *address, *port;
30     if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
31 	gtk_tree_model_get(model, &iter, COLUMN_NAME, &name,
32 	  COLUMN_SCHEME, &scheme, COLUMN_ADDRESS, &address, -1);
33 	if (!strcmp(scheme, "file")) {
34 	    w = create_LocalExecutable();
35 	    entry = GTK_ENTRY(lookup_widget(w, "LocalExecutablePath"));
36 	    gtk_entry_set_text(GTK_ENTRY(entry), address);
37 	} else if (!strcmp(scheme, "tcp")) {
38 	    w = create_RemoteMachine();
39 	    port = strrchr(address, ':');
40 	    if (port)
41 		*port++ = '\0';
42 	    else
43 		port = "2700";		/* Should never happen */
44 	    entry = GTK_ENTRY(lookup_widget(w, "RemoteMachineHostname"));
45 	    gtk_entry_set_text(GTK_ENTRY(entry), address);
46 	    entry = GTK_ENTRY(lookup_widget(w, "RemoteMachinePort"));
47 	    gtk_entry_set_text(GTK_ENTRY(entry), port);
48 	} else
49 	    g_critical("Unknown server scheme '%s'", scheme);
50 	if (w) {
51 	    g_object_set_data_full(G_OBJECT(w), "connection-name", name,
52 	      g_free);
53 	    gtk_widget_show(w);
54 	} else
55 	    g_free(name);
56 	g_free(scheme);
57 	g_free(address);
58     }
59 }
60 
61 void
GTK_delete_connection(GtkTreeView * treeview,gpointer user_data)62 GTK_delete_connection(GtkTreeView *treeview, gpointer user_data)
63 {
64     GtkTreeSelection *sel = gtk_tree_view_get_selection(treeview);
65     GtkTreeModel *model;
66     GtkTreeIter iter;
67     if (gtk_tree_selection_get_selected(sel, &model, &iter))
68 	gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
69 }
70 
71 void
GTK_set_default_connection(GtkTreeView * treeview,gpointer user_data)72 GTK_set_default_connection(GtkTreeView *treeview, gpointer user_data)
73 {
74     GtkTreeSelection *sel = gtk_tree_view_get_selection(treeview);
75     GtkTreeModel *model;
76     GtkTreeIter iter;
77     gchar *name;
78     if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
79 	gtk_tree_model_get(model, &iter, COLUMN_NAME, &name, -1);
80 	GTK_connection_set_default(name);
81 	g_free(name);
82     }
83 }
84 
85 void
GTK_revert_connections(GtkTreeView * treeview,gpointer user_data)86 GTK_revert_connections(GtkTreeView *treeview, gpointer user_data)
87 {
88     GtkTreeModel *model = gtk_tree_view_get_model(treeview);
89     gtk_list_store_clear(GTK_LIST_STORE(model));
90     nh_read_gtkhackrc();
91     if (!gtk_tree_model_iter_n_children(model, NULL))
92 	GTK_connection_add("local", "file", "slashem", 0UL);
93 }
94 
95 void
GTK_create_connection(GtkWidget * dialog,gpointer user_data)96 GTK_create_connection(GtkWidget *dialog, gpointer user_data)
97 {
98     GtkWidget *w;
99     GtkWidget *ConnectionName = lookup_widget(dialog, "ConnectionName");
100     GtkWidget *ServerType = lookup_widget(dialog, "ServerType");
101     GtkWidget *DisableAsync = lookup_widget(dialog, "DisableAsync");
102     GtkWidget *EnableLogging = lookup_widget(dialog, "EnableLogging");
103     GtkTreeRowReference *ref;
104     const gchar *name = gtk_entry_get_text(GTK_ENTRY(ConnectionName));
105     const gchar *type = gtk_entry_get_text(GTK_ENTRY(ServerType));
106     unsigned long flags = 0UL;
107     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(DisableAsync)))
108 	flags |= PROXY_CLNT_SYNCHRONOUS;
109     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(EnableLogging)))
110 	flags |= PROXY_CLNT_LOGGED;
111     if (!*name) {
112 	w = gtk_message_dialog_new(GTK_WINDOW(dialog),
113 	  GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
114 	  "Please enter a name for your new connection.");
115 	gtk_dialog_run(GTK_DIALOG(w));
116 	gtk_widget_destroy(w);
117 	return;
118     } else if ((ref = GTK_connection_lookup(name))) {
119 	gtk_tree_row_reference_free(ref);
120 	w = gtk_message_dialog_new(GTK_WINDOW(dialog),
121 	  GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
122 	  "You already have a connection with the name %s.\n\n"
123 	  "Please enter a different name for your connection.", name);
124 	gtk_dialog_run(GTK_DIALOG(w));
125 	gtk_widget_destroy(w);
126 	return;
127     }
128     if (!strcmp(type, "Local executable"))
129 	w = create_LocalExecutable();
130     else if (!strcmp(type, "Remote machine"))
131 	w = create_RemoteMachine();
132     else {
133 	g_critical("Unknown server type '%s'", type);
134 	return;
135     }
136     g_object_set_data_full(G_OBJECT(w), "connection-name", g_strdup(name),
137       g_free);
138     g_object_set_data(G_OBJECT(w), "proxy-clnt-flags", GUINT_TO_POINTER(flags));
139     gtk_widget_destroy(dialog);
140     gtk_widget_show(w);
141 }
142 
143 void
GTK_browse_server_executable(GtkWidget * entry,gpointer user_data)144 GTK_browse_server_executable(GtkWidget *entry, gpointer user_data)
145 {
146     GtkWidget *w;
147     const gchar *path = gtk_entry_get_text(GTK_ENTRY(entry));
148     const gchar *os_path;
149     gchar *s;
150     w = gtk_file_selection_new("Select Local Executable");
151     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(w));
152     if (*path) {
153 	os_path = g_filename_from_utf8(path, -1, NULL, NULL, NULL);
154 	if (os_path) {
155 	    s = g_find_program_in_path(os_path);
156 	    gtk_file_selection_set_filename(GTK_FILE_SELECTION(w),
157 	      s ? s : os_path);
158 	    g_free(s);
159 	    g_free((void *)os_path);
160 	}
161     }
162     if (gtk_dialog_run(GTK_DIALOG(w)) == GTK_RESPONSE_OK) {
163 	os_path = gtk_file_selection_get_filename(GTK_FILE_SELECTION(w));
164 	path = g_filename_to_utf8(os_path, -1, NULL, NULL, NULL);
165 	if (path) {
166 	    gtk_entry_set_text(GTK_ENTRY(entry), path);
167 	    g_free((void *)path);
168 	}
169     }
170     gtk_widget_destroy(w);
171 }
172 
173 void
GTK_add_file_server(GtkWidget * entry,gpointer user_data)174 GTK_add_file_server(GtkWidget *entry, gpointer user_data)
175 {
176     GtkWidget *LocalExecutable = lookup_widget(entry, "LocalExecutable");
177     const gchar *name = g_object_get_data(G_OBJECT(LocalExecutable),
178       "connection-name");
179     unsigned long flags = GPOINTER_TO_UINT(
180       g_object_get_data(G_OBJECT(LocalExecutable), "proxy-clnt-flags"));
181     const gchar *path = gtk_entry_get_text(GTK_ENTRY(entry));
182     GTK_connection_add(name, "file", path, flags);
183     gtk_widget_destroy(LocalExecutable);
184 }
185 
186 void
GTK_add_tcp_server(GtkWidget * RemoteExecutable,gpointer user_data)187 GTK_add_tcp_server(GtkWidget *RemoteExecutable, gpointer user_data)
188 {
189     GtkWidget *w;
190     gchar *address;
191     GtkWidget *Hostname = lookup_widget(RemoteExecutable,
192       "RemoteMachineHostname");
193     GtkWidget *Port = lookup_widget(RemoteExecutable, "RemoteMachinePort");
194     const gchar *name = g_object_get_data(G_OBJECT(RemoteExecutable),
195       "connection-name");
196     unsigned long flags = GPOINTER_TO_UINT(
197       g_object_get_data(G_OBJECT(RemoteExecutable), "proxy-clnt-flags"));
198     const gchar *host = gtk_entry_get_text(GTK_ENTRY(Hostname));
199     const gchar *port = gtk_entry_get_text(GTK_ENTRY(Port));
200     if (!*host) {
201 	w = gtk_message_dialog_new(GTK_WINDOW(RemoteExecutable),
202 	  GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
203 	  "Please enter the name of the host on which the server runs.");
204 	gtk_dialog_run(GTK_DIALOG(w));
205 	gtk_widget_destroy(w);
206 	return;
207     }
208     if (!*port) {
209 	w = gtk_message_dialog_new(GTK_WINDOW(RemoteExecutable),
210 	  GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
211 	  "Please enter the TCP/IP port that the server listens to.");
212 	gtk_dialog_run(GTK_DIALOG(w));
213 	gtk_widget_destroy(w);
214 	return;
215     }
216     /* We should check the port number more carefully, but this at least
217      * means that we won't get confused.
218      */
219     if (!atoi(port) || strchr(port, ':')) {
220 	w = gtk_message_dialog_new(GTK_WINDOW(RemoteExecutable),
221 	  GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
222 	  "Illegal TCP/IP port number.\n\n"
223 	  "Please enter a number corresponding to the remote TCP/IP port.");
224 	gtk_dialog_run(GTK_DIALOG(w));
225 	gtk_widget_destroy(w);
226 	return;
227     }
228     address = g_strdup_printf("%s:%s", host, port);
229     GTK_connection_add(name, "tcp", address, flags);
230     g_free(address);
231     gtk_widget_destroy(RemoteExecutable);
232 }
233 
234 void
on_DisableAsync_toggled(GtkToggleButton * button,gpointer user_data)235 on_DisableAsync_toggled(GtkToggleButton *button, gpointer user_data)
236 {
237     unsigned long flags;
238     GtkTreePath *path;
239     GtkTreeIter iter;
240     path = gtk_tree_row_reference_get_path(GTK_current_connection);
241     if (gtk_tree_model_get_iter(GTK_TREE_MODEL(GTK_connections), &iter, path)) {
242 	gtk_tree_model_get(GTK_TREE_MODEL(GTK_connections), &iter,
243 	  COLUMN_FLAGS, &flags, -1);
244 	if (gtk_toggle_button_get_active(button))
245 	    flags |= PROXY_CLNT_SYNCHRONOUS;
246 	else
247 	    flags &= ~PROXY_CLNT_SYNCHRONOUS;
248 	gtk_list_store_set(GTK_connections, &iter, COLUMN_FLAGS, flags, -1);
249     }
250     gtk_tree_path_free(path);
251 }
252 
253 void
on_EnableLogging_toggled(GtkToggleButton * button,gpointer user_data)254 on_EnableLogging_toggled(GtkToggleButton *button, gpointer user_data)
255 {
256     unsigned long flags;
257     GtkTreePath *path;
258     GtkTreeIter iter;
259     path = gtk_tree_row_reference_get_path(GTK_current_connection);
260     if (gtk_tree_model_get_iter(GTK_TREE_MODEL(GTK_connections), &iter, path)) {
261 	gtk_tree_model_get(GTK_TREE_MODEL(GTK_connections), &iter,
262 	  COLUMN_FLAGS, &flags, -1);
263 	if (gtk_toggle_button_get_active(button))
264 	    flags |= PROXY_CLNT_LOGGED;
265 	else
266 	    flags &= ~PROXY_CLNT_LOGGED;
267 	gtk_list_store_set(GTK_connections, &iter, COLUMN_FLAGS, flags, -1);
268     }
269     gtk_tree_path_free(path);
270     gtkhack_enable_logging(flags & PROXY_CLNT_LOGGED);
271 }
272 
273 void
on_ViewLog_clicked(GtkButton * button,gpointer user_data)274 on_ViewLog_clicked(GtkButton *button, gpointer user_data)
275 {
276     static GtkWidget *ViewLog = NULL;
277     GtkWidget *textview;
278     if (ViewLog)
279 	gtk_window_present(GTK_WINDOW(ViewLog));
280     else {
281 	ViewLog = create_ViewLog();
282 	textview = lookup_widget(ViewLog, "ViewLogTextView");
283 	gtk_text_view_set_buffer(GTK_TEXT_VIEW(textview), GTK_nhext_log);
284 	gtk_window_set_default_size(GTK_WINDOW(ViewLog), 200, 300);
285 	gtk_widget_show(ViewLog);
286 	gtk_signal_connect(GTK_OBJECT(ViewLog), "destroy",
287 	  GTK_SIGNAL_FUNC(gtk_widget_destroyed), &ViewLog);
288     }
289 }
290 
291 void
on_viewlog_clear(GtkMenuItem * menuitem,gpointer user_data)292 on_viewlog_clear(GtkMenuItem *menuitem, gpointer user_data)
293 {
294     gtk_text_buffer_set_text(GTK_nhext_log, "", 0);
295 }
296 
297 void
on_viewlog_saveas_ok(GtkButton * button,GtkFileSelection * fs)298 on_viewlog_saveas_ok(GtkButton *button, GtkFileSelection *fs)
299 {
300     gint resp;
301     FILE *fp;
302     const gchar *filename;
303     gchar *text;
304     GtkTextIter start, end;
305     GtkWidget *dialog;
306     filename = gtk_file_selection_get_filename(fs);
307     if (g_file_test(filename, G_FILE_TEST_EXISTS)) {
308 	dialog = gtk_message_dialog_new(GTK_WINDOW(fs),
309 	   GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING,
310 	   GTK_BUTTONS_NONE, "File '%s' exists.", filename);
311 	gtk_dialog_add_buttons(GTK_DIALOG(dialog), "gtk-cancel",
312 	  GTK_RESPONSE_CANCEL, "_Overwrite", GTK_RESPONSE_OK, NULL);
313 	gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
314 	resp = gtk_dialog_run(GTK_DIALOG(dialog));
315 	gtk_widget_destroy(dialog);
316 	if (resp != GTK_RESPONSE_OK)
317 	    return;
318     }
319     fp = fopen(filename, "w");
320     gtk_text_buffer_get_bounds(GTK_nhext_log, &start, &end);
321     text = gtk_text_buffer_get_text(GTK_nhext_log, &start, &end, FALSE);
322     if (fwrite(text, strlen(text), 1, fp) != 1) {
323 	dialog = gtk_message_dialog_new(GTK_WINDOW(fs),
324 	   GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
325 	   GTK_BUTTONS_CLOSE, "Error saving file '%s': %s",
326 	   filename, g_strerror(errno));
327 	gtk_dialog_run(GTK_DIALOG(dialog));
328 	gtk_widget_destroy(dialog);
329     }
330     fclose(fp);
331     free(text);
332     gtk_widget_destroy(GTK_WIDGET(fs));
333 }
334 
335 void
on_viewlog_save_as(GtkMenuItem * menuitem,gpointer user_data)336 on_viewlog_save_as(GtkMenuItem *menuitem, gpointer user_data)
337 {
338     static GtkWidget *SaveAs = NULL;
339     if (SaveAs)
340 	gtk_window_present(GTK_WINDOW(SaveAs));
341     else {
342 	GtkWidget *SaveAs = gtk_file_selection_new("Save connection log");
343 	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(SaveAs)->ok_button),
344 	  "clicked", G_CALLBACK(on_viewlog_saveas_ok), SaveAs);
345 	g_signal_connect_swapped(
346 	  GTK_OBJECT(GTK_FILE_SELECTION(SaveAs)->cancel_button), "clicked",
347 	  G_CALLBACK(gtk_widget_destroy), SaveAs);
348 	gtk_widget_show(SaveAs);
349 	gtk_signal_connect(GTK_OBJECT(SaveAs), "destroy",
350 	  GTK_SIGNAL_FUNC(gtk_widget_destroyed), &SaveAs);
351     }
352 }
353 
354 void
on_viewlog_quit(GtkMenuItem * menuitem,gpointer user_data)355 on_viewlog_quit(GtkMenuItem *menuitem, gpointer user_data)
356 {
357     GtkWidget *w;
358     w = lookup_widget(GTK_WIDGET(menuitem), "ViewLog");
359     gtk_widget_destroy(w);
360 }
361 
362 void
on_viewlog_copy(GtkMenuItem * menuitem,gpointer user_data)363 on_viewlog_copy(GtkMenuItem *menuitem, gpointer user_data)
364 {
365     GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
366     gtk_text_buffer_copy_clipboard( GTK_nhext_log, clipboard);
367 }
368