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