/*------------------------------------------------------------------------------
  xfmc.c

  Created Thu Sep 17 12:49:49 BST 1992
  by Simon Marlow (simonm@dcs.glasgow.ac.uk)

  Program to send control signals to a running xfm process.
------------------------------------------------------------------------------*/

#include <stdio.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

#include "xfmc.h"

extern char *optarg;
extern int optind;

Display *dpy;
Atom open, update;

static Window searchWindow(Window win)
{
  int i, n_children;
  Window *children, w;
  XClassHint ch;

  XQueryTree(dpy, win, &w, &w, &children, &n_children);

  for (i=0; i < n_children; i++) {
    XGetClassHint(dpy, children[i], &ch); 
    if (ch.res_class && ch.res_name &&
	!strcmp(ch.res_class, "Xfm") && !strcmp(ch.res_name,"xfm"))
	return children[i];
    if (w = searchWindow(children[i]))
	return w;
  }
  return None;
}  

void main(int argc, char *argv[])
{
  int i, j;
  Window xfm;
  XClientMessageEvent e;
  char *s, c;

  dpy = XOpenDisplay(NULL);

  open   = XInternAtom(dpy, XFM_OPEN_WINDOW,   True);
  update = XInternAtom(dpy, XFM_UPDATE_WINDOW, True);

  if (open == None || update == None) {
    fprintf(stderr,
	    "%s: Unable to find atoms; is xfm running on this display?\n",
	    argv[0]);
    exit(1);
  }


  /* Must have one of the arguments -u or -o. The rest of the arguments are
   * directories to be opened/updated */

  e.message_type = None;
  while ((c = getopt(argc,argv,"uo")) != -1)
    switch (c) {
    case 'u':
    case 'o':
      if (e.message_type)
	goto usage;
      e.message_type = c == 'u' ? update : open;
      break;
    default:
      goto usage;
    }

  if (optind == argc || !e.message_type)
    goto usage;

  /* Look for xfm in the current window tree. This is a bit inefficient,
   * but it seems to work. Searching the top level windows isn't sufficient,
   * since window managers tend to reparent windows. */

  if (!(xfm = searchWindow(DefaultRootWindow(dpy)))) {
    fprintf(stderr, "%s: xfm is not running on this display\n", argv[0]);
    exit(1);
  }
  
  e.type = ClientMessage;
  e.display = dpy;
  e.window = xfm;
  e.format = 8;

  /* Send messages in batches of 20 characters each, because that's all that
   * fits in the ClientMessage event structure */

  for (j = optind; j < argc; j++) {
    s = argv[j];
    for (i = strlen(s); i >= 0; i -= 20, s += 20) {    
      strncpy(e.data.b,s,20);  
      if (!XSendEvent(dpy, xfm, False, 0, (XEvent *)&e)) {
	fprintf(stderr, "xfmc: XSendEvent failed\n");
	exit(1);
      }
    }
  }
  
  XFlush(dpy); /* doesn't work without this! */
  exit(0);
  
 usage:
  fprintf(stderr, "usage: %s -[u/o] message ...\n", argv[0]);
  exit(1);
}

  
  
