/* * Copyright (C) 2000 Laurent Mazet * * This program is free software and may be used for any purpose. This * copyright notice must be maintained. Paul Kienzle is not responsible * for the consequences of using this software. */ /* * Graphics extention for hacking gnuplot on X11 */ #include #include #include #include extern "C" { #include #include #include } #include "graphics.h" using namespace std; /* * Ask gnuplot for current figure */ string find_gnuplot_window (const char* const func) { /* send gget command to get terminal */ octave_value_list gget_args; gget_args(0) = "terminal"; octave_value_list gget_ret = feval ("gget", gget_args, 0); /* get figure number */ string st = gget_ret(0).string_value(); int fig_nb = -1; if (st.length() > 2 && (st[0] == 'x' || st[0] == 'X') && st[1] == '1' && st[2] == '1') fig_nb = strtol (st.substr(3, st.length()).c_str(), NULL, 10); /* check if there is a gnuplot figure */ if (fig_nb < 0) { warning("%s: no figure.", func); return (""); } /* Identify current figure window title */ char win_name[11]; /* Big enough to hold "Gnuplot " + 2 digit number */ if (fig_nb > 0) sprintf(win_name, "Gnuplot %2d", fig_nb); else strcpy(win_name, "Gnuplot"); return (win_name); } /* * Recursively search the window heirarchy for a window of the given name */ Window find_x11_window(Display *display, Window top, std::string name) { Window root, parent, *children, found; char *window_name; unsigned int N, i; /* Check if we've already got it */ XFetchName(display, top, &window_name); if (!window_name==None && name.compare(window_name) == 0) { XFree(window_name); return top; } /* If not, recursively check all children */ if (!XQueryTree(display, top, &root, &parent, &children, &N)) { XFree(window_name); return 0; } found = 0; for (i=0; i < N; i++) { found = find_x11_window(display, children[i], name); if (found) break; } XFree(children); XFree(window_name); return found; } /* * Initialize gwindow structure */ int init_gwindow (gwindow &gw, string wname, const char* const func) { /* Find plot window from title */ gw.display = XOpenDisplay(NULL); gw.screen = DefaultScreen(gw.display); gw.root = RootWindow(gw.display, gw.screen); gw.window = find_x11_window(gw.display, gw.root, wname); if (gw.window == 0) { warning("%s: plot window not found.", func); XCloseDisplay (gw.display); return 0; } /* Make sure we can capture the clicks */ XWindowAttributes wattr; XGetWindowAttributes(gw.display, gw.window, &wattr); if (wattr.all_event_masks & ButtonPressMask) { warning ("%s: could not capture button events.", func); XCloseDisplay (gw.display); return 0; } /* Set cross-hairs cursor */ Cursor cursor; cursor = XCreateFontCursor (gw.display, XC_crosshair); XDefineCursor (gw.display, gw.window, cursor); /* Get width and height */ Window wroot; int wx, wy; unsigned int bw; XGetGeometry(gw.display, gw.window, &wroot, &wx, &wy, &gw.width, &gw.height, &bw, &gw.depth); /* Check scale and origin */ octave_value_list gget_args, gget_ret; string st; char *second; gget_args(0) = "size"; gget_ret = feval ("gget", gget_args, 0); st = gget_ret(0).string_value(); gw.xscale = strtod (st.substr (st.rfind(" "), st.length()).c_str(), &second); gw.yscale = strtod (second+1, NULL); gget_args(0) = "origin"; gget_ret = feval ("gget", gget_args, 0); st = gget_ret(0).string_value(); gw.xorigin = strtod (st.c_str(), &second); gw.yorigin = strtod (second+1, NULL); /* now grab the keyboard on window to avoid gnuplot event */ // XGrabKeyboard (gw.display, gw.window, // False, GrabModeSync, GrabModeSync, CurrentTime); return 1; } /* * close gwindow structure */ void close_gwindow (gwindow &gw) { // XUngrabKeyboard (gw.display, CurrentTime); /* Stop watching for key/button press (among others) */ XSelectInput (gw.display, gw.window, 0); /* Restore cursor */ XUndefineCursor (gw.display, gw.window); XCloseDisplay (gw.display); } /* * warp on window center */ void warp_center (gwindow &gw) { /* Warp to window center */ XWarpPointer (gw.display, gw.root, gw.window, 0, 0, 0, 0, int(gw.width*(gw.xorigin+gw.xscale/2)), int(gw.height*(1-gw.yorigin-gw.yscale/2))); } /* * Get one point or abort if any key. Return button number or 0 if abort. */ int get_point (gwindow &gw, int &x, int &y) { /* Watch for key/button press (among others) */ XSelectInput (gw.display, gw.window, ButtonPressMask|KeyPressMask); XEvent event; XNextEvent (gw.display, &event); if (event.type != ButtonPress) return 0; x = event.xbutton.x; y = event.xbutton.y; return event.xbutton.button; } /* * Get one area, one point or abort if any key. * Return button number, 0 for a key, or -1 if abort. */ int get_area_point (gwindow &gw, MArray &x, MArray &y) { /* Watch for key/button press (among others) */ XSelectInput (gw.display, gw.window, ButtonPressMask|KeyPressMask); /* First point */ XEvent event; XNextEvent (gw.display, &event); if (event.type != ButtonPress) return 0; if (x.length() != 2) x.resize(2); if (y.length() != 2) y.resize(2); x(0) = event.xbutton.x; y(0) = event.xbutton.y; if (event.xbutton.button != 1) return event.xbutton.button; XGCValues gcv; GC gc; // FIX ME! White is 0xffffff for TrueColor ! gcv.function = GXxor; gcv.foreground = 0xffffff; gc = XCreateGC (gw.display, gw.window, GCForeground|GCFunction, &gcv); x(1) = x(0); y(1) = x(0); XSelectInput (gw.display, gw.window, ButtonPressMask | PointerMotionMask | KeyPressMask); /* Loop to get second point */ while (1) { XNextEvent (gw.display, &event); /* Erase old rectangle */ if (x(1) != x(0) || y(1) != x(0)) XDrawRectangle (gw.display, gw.window, gc, (x(1) < x(0)) ? x(1) : x(0), (y(1) < y(0)) ? y(1) : y(0), abs (x(1) - x(0))+1, abs (y(1) - y(0))+1); switch (event.type) { case ButtonPress: XFreeGC(gw.display, gc); /* Check button and quit */ x(1) = event.xbutton.x; y(1) = event.xbutton.y; XFlush(gw.display); return (event.xbutton.button == 1) ? 1 : -1; break; case MotionNotify: /* Draw new rectangle */ x(1) = event.xmotion.x; y(1) = event.xmotion.y; if (x(1) != x(0) || y(1) != x(0)) XDrawRectangle (gw.display, gw.window, gc, (x(1) < x(0)) ? x(1) : x(0), (y(1) < y(0)) ? y(1) : y(0), abs (x(1) - x(0))+1, abs (y(1) - y(0))+1); break; case KeyPress: XFreeGC(gw.display, gc); /* Quit and send key code */ XFlush(gw.display); return 0; break; } } XFreeGC(gw.display, gc); XFlush(gw.display); return -1; } /* * Guess border from gnuplot image */ ColumnVector guess_border (gwindow &gw) { // FIX ME! White is 0xffffffL for TrueColor ! XImage *image = XGetImage (gw.display, gw.window, int(gw.width*gw.xorigin), int(gw.height*(1-gw.yorigin-gw.yscale)), int(gw.width*gw.xscale), int(gw.height*gw.yscale), 0xffffffL, ZPixmap); int width = image->width; int height = image->height; /* compute line and column correlations */ MArray x_cor (width, 0); MArray y_cor (height, 0); for (int i=0; i