00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "intl.h"
00032 #include <stdio.h>
00033 #include <string.h>
00034
00035 #ifdef __MINGW32__
00036 #include <gdk/gdkwin32.h>
00037 #else
00038 #include <gdk/gdkx.h>
00039 #include <stdlib.h>
00040 #endif
00041
00042 #include <gdk/gdkprivate.h>
00043
00044 #include "dialog.h"
00045 #include "util.h"
00046 #include "gtk_globals.h"
00047 #include "prefs.h"
00048
00049 enum
00050 {
00051 BROWSER_NETSCAPE,
00052 BROWSER_KFM,
00053 BROWSER_MANUAL,
00054 BROWSER_INTERNAL
00055 };
00056
00057 #ifndef _WIN32
00058 gint web_browser = BROWSER_NETSCAPE;
00059
00060
00061
00062
00063
00064 #include <X11/Xlib.h>
00065 #include <X11/Xatom.h>
00066
00067
00068
00069 static const char *expected_mozilla_version = "1.1";
00070
00071 #define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
00072 #define MOZILLA_LOCK_PROP "_MOZILLA_LOCK"
00073 #define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND"
00074 #define MOZILLA_RESPONSE_PROP "_MOZILLA_RESPONSE"
00075
00076 static GdkAtom XA_MOZILLA_VERSION = 0;
00077 static GdkAtom XA_MOZILLA_LOCK = 0;
00078 static GdkAtom XA_MOZILLA_COMMAND = 0;
00079 static GdkAtom XA_MOZILLA_RESPONSE = 0;
00080
00081
00082 static int netscape_lock;
00083
00084
00085 static Window
00086 VirtualRootWindowOfScreen(screen)
00087 Screen *screen;
00088 {
00089 static Screen *save_screen = (Screen *)0;
00090 static Window root = (Window)0;
00091
00092 if (screen != save_screen) {
00093 Display *dpy = DisplayOfScreen(screen);
00094 Atom __SWM_VROOT = None;
00095 unsigned int i;
00096 Window rootReturn, parentReturn, *children;
00097 unsigned int numChildren;
00098
00099 root = RootWindowOfScreen(screen);
00100
00101
00102 __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
00103 if (XQueryTree(dpy, root, &rootReturn, &parentReturn,
00104 &children, &numChildren)) {
00105 for (i = 0; i < numChildren; i++) {
00106 Atom actual_type;
00107 int actual_format;
00108 unsigned long nitems, bytesafter;
00109 Window *newRoot = (Window *)0;
00110
00111 if (XGetWindowProperty(dpy, children[i],
00112 __SWM_VROOT, 0, 1, False, XA_WINDOW,
00113 &actual_type, &actual_format,
00114 &nitems, &bytesafter,
00115 (unsigned char **) &newRoot) == Success
00116 && newRoot) {
00117 root = *newRoot;
00118 break;
00119 }
00120 }
00121 if (children)
00122 XFree((char *)children);
00123 }
00124
00125 save_screen = screen;
00126 }
00127
00128 return root;
00129 }
00130
00131
00132
00133 static Window TryChildren();
00134
00135
00136
00137 static Window GClientWindow (dpy, win)
00138 Display *dpy;
00139 Window win;
00140 {
00141 Atom WM_STATE;
00142 Atom type = None;
00143 int format;
00144 unsigned long nitems, after;
00145 unsigned char *data;
00146 Window inf;
00147
00148 WM_STATE = XInternAtom(dpy, "WM_STATE", True);
00149 if (!WM_STATE)
00150 return win;
00151 XGetWindowProperty(dpy, win, WM_STATE, 0, 0, False, AnyPropertyType,
00152 &type, &format, &nitems, &after, &data);
00153 if (type)
00154 return win;
00155 inf = TryChildren(dpy, win, WM_STATE);
00156 if (!inf)
00157 inf = win;
00158 return inf;
00159 }
00160
00161 static
00162 Window TryChildren (dpy, win, WM_STATE)
00163 Display *dpy;
00164 Window win;
00165 Atom WM_STATE;
00166 {
00167 Window root, parent;
00168 Window *children;
00169 unsigned int nchildren;
00170 unsigned int i;
00171 Atom type = None;
00172 int format;
00173 unsigned long nitems, after;
00174 unsigned char *data;
00175 Window inf = 0;
00176
00177 if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren))
00178 return 0;
00179 for (i = 0; !inf && (i < nchildren); i++) {
00180 XGetWindowProperty(dpy, children[i], WM_STATE, 0, 0, False,
00181 AnyPropertyType, &type, &format, &nitems,
00182 &after, &data);
00183 if (type)
00184 inf = children[i];
00185 }
00186 for (i = 0; !inf && (i < nchildren); i++)
00187 inf = TryChildren(dpy, children[i], WM_STATE);
00188 if (children) XFree((char *)children);
00189 return inf;
00190 }
00191
00192
00193
00194
00195
00196 static void mozilla_remote_init_atoms()
00197 {
00198 if (!XA_MOZILLA_VERSION)
00199 XA_MOZILLA_VERSION = gdk_atom_intern(MOZILLA_VERSION_PROP, 0);
00200 if (!XA_MOZILLA_LOCK)
00201 XA_MOZILLA_LOCK = gdk_atom_intern(MOZILLA_LOCK_PROP, 0);
00202 if (! XA_MOZILLA_COMMAND)
00203 XA_MOZILLA_COMMAND = gdk_atom_intern(MOZILLA_COMMAND_PROP, 0);
00204 if (! XA_MOZILLA_RESPONSE)
00205 XA_MOZILLA_RESPONSE = gdk_atom_intern(MOZILLA_RESPONSE_PROP, 0);
00206 }
00207
00208 static GdkWindow *mozilla_remote_find_window()
00209 {
00210 int i;
00211 Window root = VirtualRootWindowOfScreen(DefaultScreenOfDisplay(gdk_display));
00212 Window root2, parent, *kids;
00213 unsigned int nkids;
00214 Window result = 0;
00215 Window tenative = 0;
00216 unsigned char *tenative_version = 0;
00217
00218 if (!XQueryTree (gdk_display, root, &root2, &parent, &kids, &nkids))
00219 {
00220 }
00221
00222
00223
00224 if (!(kids && nkids)) {
00225 return NULL;
00226 }
00227
00228 for (i = nkids-1; i >= 0; i--)
00229 {
00230 Atom type;
00231 int format;
00232 unsigned long nitems, bytesafter;
00233 unsigned char *version = 0;
00234 Window w = GClientWindow (gdk_display, kids[i]);
00235 int status = XGetWindowProperty (gdk_display, w, XA_MOZILLA_VERSION,
00236 0, (65536 / sizeof (long)),
00237 False, XA_STRING,
00238 &type, &format, &nitems, &bytesafter,
00239 &version);
00240 if (! version)
00241 continue;
00242 if (strcmp ((char *) version, expected_mozilla_version) &&
00243 !tenative)
00244 {
00245 tenative = w;
00246 tenative_version = version;
00247 continue;
00248 }
00249 g_free (version);
00250 if (status == Success && type != None)
00251 {
00252 result = w;
00253 break;
00254 }
00255 }
00256
00257 if (result && tenative)
00258 {
00259 g_free (tenative_version);
00260 return gdk_window_foreign_new(result);
00261 }
00262 else if (tenative)
00263 {
00264 g_free (tenative_version);
00265 return gdk_window_foreign_new(tenative);
00266 }
00267 else if (result)
00268 {
00269 return gdk_window_foreign_new(result);
00270 }
00271 else
00272 {
00273 return NULL;
00274 }
00275 }
00276
00277
00278 static char *lock_data = 0;
00279
00280 static void mozilla_remote_obtain_lock (GdkWindow *window)
00281 {
00282 Bool locked = False;
00283
00284 if (!lock_data) {
00285 lock_data = (char *)g_malloc (255);
00286 sprintf (lock_data, "pid%d@", getpid ());
00287 if (gethostname (lock_data + strlen (lock_data), 100)) {
00288 return;
00289 }
00290 }
00291
00292 do {
00293 int result;
00294 GdkAtom actual_type;
00295 gint actual_format;
00296 gint nitems;
00297 unsigned char *data = 0;
00298
00299 result = gdk_property_get (window, XA_MOZILLA_LOCK,
00300 XA_STRING, 0,
00301 (65536 / sizeof (long)), 0,
00302 &actual_type, &actual_format,
00303 &nitems, &data);
00304 if (result != Success || actual_type == None)
00305 {
00306
00307
00308 gdk_property_change(window, XA_MOZILLA_LOCK, XA_STRING,
00309 8, PropModeReplace,
00310 (unsigned char *) lock_data,
00311 strlen (lock_data));
00312 locked = True;
00313 }
00314
00315 if (!locked) {
00316
00317 if (data)
00318 g_free(data);
00319 return;
00320 }
00321 if (data)
00322 g_free(data);
00323 } while (!locked);
00324 }
00325
00326
00327 static void mozilla_remote_free_lock (GdkWindow *window)
00328 {
00329 int result = 0;
00330 GdkAtom actual_type;
00331 gint actual_format;
00332 gint nitems;
00333 unsigned char *data = 0;
00334
00335
00336 result = gdk_property_get(window, XA_MOZILLA_LOCK, XA_STRING,
00337 0, (65536 / sizeof (long)),
00338 1, &actual_type, &actual_format,
00339 &nitems, &data);
00340 if (result != Success)
00341 {
00342 return;
00343 }
00344 else if (!data || !*data)
00345 {
00346 return;
00347 }
00348 else if (strcmp ((char *) data, lock_data))
00349 {
00350 return;
00351 }
00352
00353 if (data)
00354 g_free(data);
00355 }
00356
00357
00358 static int
00359 mozilla_remote_command (GdkWindow *window, const char *command,
00360 Bool raise_p)
00361 {
00362 int result = 0;
00363 Bool done = False;
00364 char *new_command = 0;
00365
00366
00367
00368
00369 if (!raise_p)
00370 {
00371 char *close;
00372 new_command = (char *) malloc (strlen (command) + 20);
00373 strcpy (new_command, command);
00374 close = strrchr (new_command, ')');
00375 if (close)
00376 strcpy (close, ", noraise)");
00377 else
00378 strcat (new_command, "(noraise)");
00379 command = new_command;
00380 }
00381
00382
00383 gdk_property_change(window, XA_MOZILLA_COMMAND, XA_STRING, 8,
00384 GDK_PROP_MODE_REPLACE, (unsigned char *) command,
00385 strlen (command));
00386
00387 while (!done) {
00388 GdkEvent *event;
00389
00390 event = gdk_event_get();
00391
00392 if (!event)
00393 continue;
00394
00395 if (event->any.window != window) {
00396 gtk_main_do_event(event);
00397 continue;
00398 }
00399
00400 if (event->type == GDK_DESTROY &&
00401 event->any.window == window) {
00402
00403
00404 result = 6;
00405 goto DONE;
00406 } else if (event->type == GDK_PROPERTY_NOTIFY &&
00407 event->property.state == GDK_PROPERTY_NEW_VALUE &&
00408 event->property.window == window &&
00409 event->property.atom == XA_MOZILLA_RESPONSE) {
00410 GdkAtom actual_type;
00411 gint actual_format, nitems;
00412 unsigned char *data = 0;
00413
00414 result = gdk_property_get (window, XA_MOZILLA_RESPONSE,
00415 XA_STRING, 0,
00416 (65536 / sizeof (long)),
00417 1,
00418 &actual_type, &actual_format,
00419 &nitems, &data);
00420
00421
00422 if (result == Success && data && *data) {
00423 }
00424
00425 if (result != Success) {
00426 result = 6;
00427 done = True;
00428 } else if (!data || strlen((char *) data) < 5) {
00429 result = 6;
00430 done = True;
00431 } else if (*data == '1') {
00432 } else if (!strncmp ((char *)data, "200", 3)) {
00433 result = 0;
00434 done = True;
00435 } else if (*data == '2') {
00436 result = 0;
00437 done = True;
00438 } else if (*data == '3') {
00439 result = 3;
00440 done = True;
00441 } else if (*data == '4' || *data == '5') {
00442 result = (*data - '0');
00443 done = True;
00444 } else {
00445 result = 6;
00446 done = True;
00447 }
00448
00449 if (data)
00450 g_free(data);
00451 }
00452 else if (event->type == GDK_PROPERTY_NOTIFY &&
00453 event->property.window == window &&
00454 event->property.state == GDK_PROPERTY_DELETE &&
00455 event->property.atom == XA_MOZILLA_COMMAND) {
00456 }
00457 gdk_event_free(event);
00458 }
00459
00460 DONE:
00461
00462 if (new_command)
00463 g_free (new_command);
00464
00465 return result;
00466 }
00467
00468
00469 gint check_netscape(char *msg)
00470 {
00471 int status;
00472 GdkWindow *window;
00473
00474 mozilla_remote_init_atoms ();
00475 window = mozilla_remote_find_window();
00476
00477 if (window) {
00478
00479 XSelectInput(gdk_display, ((GdkWindowPrivate *)window)->xwindow,
00480 (PropertyChangeMask|StructureNotifyMask));
00481
00482
00483 mozilla_remote_obtain_lock(window);
00484
00485 status = mozilla_remote_command(window, msg, False);
00486
00487 if (status != 6)
00488 mozilla_remote_free_lock(window);
00489
00490 gtk_timeout_add(1000, (GtkFunction)clean_pid, NULL);
00491
00492 netscape_lock = 0;
00493
00494 g_free(msg);
00495 return FALSE;
00496 } else
00497 return TRUE;
00498 }
00499
00500
00501 static void netscape_command(char *command)
00502 {
00503 int status;
00504 pid_t pid;
00505 GdkWindow *window;
00506
00507 if (netscape_lock)
00508 return;
00509
00510 netscape_lock = 1;
00511
00512
00513
00514 mozilla_remote_init_atoms();
00515 window = mozilla_remote_find_window();
00516
00517 if (window) {
00518
00519 XSelectInput(gdk_display, ((GdkWindowPrivate *)window)->xwindow,
00520 (PropertyChangeMask|StructureNotifyMask));
00521
00522 mozilla_remote_obtain_lock(window);
00523
00524 status = mozilla_remote_command(window, command, False);
00525
00526 if (status != 6)
00527 mozilla_remote_free_lock(window);
00528
00529 netscape_lock = 0;
00530
00531 } else {
00532 pid = fork();
00533 if (pid == 0) {
00534 char *args[2];
00535 int e;
00536
00537 args[0] = g_strdup("netscape");
00538 args[1] = NULL;
00539 e = execvp(args[0], args);
00540
00541 _exit(0);
00542 } else {
00543 char *tmp = g_strdup(command);
00544 gtk_timeout_add(200, (GtkFunction)check_netscape, tmp);
00545 }
00546 }
00547
00548 }
00549
00550 void open_url(GtkWidget *w, char *url) {
00551 if (web_browser == BROWSER_NETSCAPE) {
00552 char *command = g_malloc(1024);
00553
00554 g_snprintf(command, 1024, "OpenURL(%s)", url);
00555
00556 netscape_command(command);
00557 g_free(command);
00558 } else if (web_browser == BROWSER_KFM) {
00559 pid_t pid;
00560
00561 pid = fork();
00562
00563 if (pid == 0) {
00564 char *args[4];
00565
00566 args[0] = g_strdup("kfmclient");
00567 args[1] = g_strdup("openURL");
00568 args[2] = url;;
00569 args[3] = NULL;
00570
00571 execvp(args[0], args);
00572 _exit(0);
00573 } else {
00574 gtk_timeout_add(1000, (GtkFunction)clean_pid, NULL);
00575 }
00576 }
00577 }
00578
00579 void add_bookmark(GtkWidget *w, char *url) {
00580 if (web_browser == BROWSER_NETSCAPE) {
00581 char *command = g_malloc(1024);
00582
00583 g_snprintf(command, 1024, "AddBookmark(%s)", url);
00584
00585 netscape_command(command);
00586 g_free(command);
00587 }
00588 }
00589
00590 void open_url_nw(GtkWidget *w, char *url) {
00591 char *alternate_browser=cGetLocalPref("alternate_browser");
00592 if ((use_alternate_browser == 1) && (strlen(alternate_browser) > 0)) {
00593 char *command = g_malloc(1024);
00594 char *url_pos = strstr(alternate_browser, "%s");
00595
00596
00597
00598
00599
00600 if(url_pos) {
00601 int pre_len = url_pos-alternate_browser;
00602 strncpy(command, alternate_browser, pre_len);
00603 command[pre_len] = 0;
00604 strncat(command, url, 1024 - pre_len);
00605 strncat(command, url_pos+2, 1024 - strlen(command));
00606 strncat(command, " &", 1024 - strlen(command));
00607 } else
00608 g_snprintf(command, 1024, "%s \"%s\" &", alternate_browser, url);
00609 eb_debug(DBG_CORE, "launching %s\n", command);
00610 system(command);
00611 g_free(command);
00612 } else if (web_browser == BROWSER_NETSCAPE) {
00613 char *command = g_malloc(1024);
00614 g_snprintf(command, 1024, "OpenURL(%s, new-window)", url);
00615
00616 netscape_command(command);
00617 g_free(command);
00618 }
00619 }
00620
00621 #else
00622 #include <shellapi.h>
00623 #include <process.h>
00624 gint web_browser = BROWSER_INTERNAL;
00625
00626 void add_bookmark(GtkWidget *w, char *url) {
00627 }
00628
00629 void open_url_nw(GdkWindow *w, char *url) {
00630 ShellExecute(GDK_DRAWABLE_XID(w),"open",url,NULL,"C:\\",0);
00631 }
00632
00633 void open_url(GdkWindow *w, char *url) {
00634 open_url_nw(w,url);
00635 }
00636
00637 #endif // _WIN32