/* This file is part of the Project Athena Zephyr Notification System.
 * Created by: Mark W. Eichin <eichin@athena.mit.edu>
 * zbrowser.c: prototype browser
 * $Source: /mit/zephyr/src/zwgc/zbrowser/RCS/zbrowser.c,v $
 * $Author: jtkohl $
 * [eichin:19880702.1236EST]
 *	Copyright (c) 1988 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */
#include <zephyr/mit-copyright.h>
#ifndef lint
static char rcsid[] = "$Header $";
#endif lint

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

#include <X11/Xatom.h>
#include <X11/Shell.h>

#include <X11/Xaw/Box.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Viewport.h>

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#define NL 20
#define initNL 5

#define BrSetPar 1
#define BrAddTag 2
#define BrDelTag 3

char *malloc();
#define New(type) (type *) malloc(sizeof(type))

struct _master {
  XContext	wincon, boxcon;
  Atom	tagatom;
} master = {
  NULL, NULL,
  (Atom) 0,
};

void newone();  
#ifdef REAL_WIDGETS
static char XeventXlate[] = "\
<Create>:	grabcreate()\n\
<Destroy>:	grabdestroy()\n\
<Map>:		grabmap()";

static XtActionsRec grabacts[] = {
  {"grabcreate",	grabcreate},
  {"grabdestroy",	grabdestroy},
  {"grabmap",		grabmap},
};

static void initstuff()
{
  Widget w;
  
  XtAddActions(grabacts, sizeof(grabacts)/sizeof(*grabacts));
  XtOverrideTranslations(w, XtParseTranslationTable(XeventXlate));
}
  
static void grabcreate(w,event,params,num_params)
     Widget w;
     XEvent *event;
     String *params;		/* unused */
     Cardinal *num_params;	/* unused */
{
}
  
static void grabdestroy(w,event,params,num_params)
     Widget w;
     XEvent *event;
     String *params;		/* unused */
     Cardinal *num_params;	/* unused */
{
}
  
static void grabmap(w,event,params,num_params)
     Widget w;
     XEvent *event;
     String *params;		/* unused */
     Cardinal *num_params;	/* unused */
{
}
  
#endif /* REAL_WIDGETS */

void BRGetSummary(dpy, win, summ) /* modeled on XFetchName */
     Display *dpy;
     Window win;
     char **summ;
{
  Atom act_type;
  int act_form;
  unsigned long nitms, leftover;
  
  if(XGetWindowProperty(dpy, win, master.tagatom, 0L, (long)BUFSIZ,
			False, XA_STRING, &act_type,
			&act_form, &nitms, &leftover, summ) != Success) {
    *summ = NULL;
    return;
  }
  if( (act_type == XA_STRING) && (act_form == 8) ) {
    return;
  }
  if(*summ) free(*summ);
  *summ = NULL;
  return;
}
  
void handle_map(dpy, win)
     Display *dpy;
     Window win;
{
  char *summ;
  BRGetSummary(dpy, win, &summ);
  newone(BrAddTag, 0, summ, win);
  printf("Added tag:<%s>\n", summ);
  free(summ);
}

void handle_destroy(dpy, win)
     Display *dpy;
     Window win;
{
  newone(BrDelTag, 0, 0, win);
}


int snatchable(ev)
     XEvent *ev;
{
  switch(ev->type) {
  case CreateNotify:
  case DestroyNotify:
  case MapNotify:
    return(1);
  default:
    return(0);
  }
}

void snatch(ev)
     XEvent *ev;
{
  switch(ev->type) {
  case CreateNotify:		/* change this to just read the tag... */
    {
      /* check for zgram.. */
      char *wname;
      if(XFetchName(ev->xmap.display, ev->xmap.window, &wname))
	{
	  if(!strcasecmp("Zwgc",wname))
	    {
	      XCreateWindowEvent *xcwe = New(XCreateWindowEvent);
	      *xcwe = ev->xcreatewindow;
	      XSaveContext(ev->xcreatewindow.display, ev->xcreatewindow.window,
			   master.wincon, (char *)xcwe);
	    }
	}
    }
    break;
  case DestroyNotify:
    handle_destroy(ev->xdestroywindow.display,
		   ev->xdestroywindow.window);
    XDeleteContext(ev->xdestroywindow.display,
		   ev->xdestroywindow.window, master.wincon);
    break;
  case MapNotify:
    {
	/* check for zgram.. */
	char *wname;
	if(XFetchName(ev->xmap.display, ev->xmap.window, &wname))
	  {
	    if(!strcasecmp("Zwgc",wname))
	      {
		handle_map(ev->xmap.display, ev->xmap.window);
	      }
	  } 
    }
    break;
  }
}


void BrowserLoop(w)
  Widget w;
{
  XEvent event;
  Display *dpy = XtDisplay(w);
  

  XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureNotifyMask);
  XFlush(dpy);

  for(;;) {
    XtNextEvent(&event);
    if(snatchable(&event)) {
      snatch(&event);
    } else {
      XtDispatchEvent(&event);
    }
  }
}

static Window glbwin;

void selectFn(w, client_data, call_data)
     Widget w;
     caddr_t client_data;	/* window... */
     caddr_t call_data;
{
  glbwin = (Window) client_data;
}

void deleteFn(w, client_data, call_data)
     Widget w;
     caddr_t client_data;
     caddr_t call_data;
{
  int st;
  XEvent xev;
  XButtonEvent *xpbe = &xev.xbutton;
  if(!glbwin) {
    XBell(XtDisplay(w),0);
    return;
  }
  xpbe->display = XtDisplay(w);
  xpbe->window = glbwin;
  xpbe->root = DefaultRootWindow(xpbe->display);
  xpbe->subwindow = glbwin;
  xpbe->x = xpbe->y = 1;
  xpbe->x_root = xpbe->y_root = 1;
  xpbe->state = 0;
  xpbe->button = Button1;
  xpbe->same_screen = True;
  xpbe->serial = 0L;
  xpbe->send_event = True;
  xpbe->time = 0L;

  xev.type = xpbe->type = ButtonPress;
  st = XSendEvent(XtDisplay(w), glbwin, False,
	     ButtonPressMask, xpbe);
  xev.type = xpbe->type = ButtonRelease;
  st = XSendEvent(XtDisplay(w), glbwin, False,
	     ButtonReleaseMask, xpbe);
  glbwin = 0;
}

void unmapFn(w, client_data, call_data)
     Widget w;
     caddr_t client_data;
     caddr_t call_data;
{
  if(!glbwin) {
    XBell(XtDisplay(w),0);
    return;
  }
  XUnmapWindow(XtDisplay(w), glbwin);
  glbwin = 0;
}

void mapFn(w, client_data, call_data)
     Widget w;
     caddr_t client_data;
     caddr_t call_data;
{
  if(!glbwin) {
    XBell(XtDisplay(w),0);
    return;
  }
  XMapRaised(XtDisplay(w), glbwin);
  glbwin = 0;
}

void quitFn(w, client_data, call_data)
     Widget w;
     caddr_t client_data;
     caddr_t call_data;
{
  exit(0);
}

void newone(func, par, tag, win)
     int func;
     Widget par;
     char *tag;
     Window win;
{
  static char *strs;
  Widget tmpwdg;
  Arg anarg[5];
  static int i;
  static Widget parent;
  XtCallbackRec selectList[2];

  selectList[0].callback = selectFn;
  selectList[0].closure = (caddr_t) win;
  selectList[1].callback = NULL;
  selectList[1].closure = (caddr_t) NULL;

  printf("newone[%d]\n", func);
  
  switch(func) {
  case BrSetPar:
    parent = par;
    break;

  case BrAddTag:
    if(XFindContext(XtDisplay(parent), win, master.boxcon,
		    (char **)&tmpwdg)) {
      strs = strcpy(malloc(strlen(tag)+1),tag);
      XtSetArg(anarg[0], XtNlabel, strs);
      XtSetArg(anarg[1], XtNcallback, selectList);
      tmpwdg = XtCreateManagedWidget("tag", commandWidgetClass,
				     parent, anarg, 2);
      XSaveContext(XtDisplay(parent), win, master.boxcon, (char *)tmpwdg);
    } else {
      printf("Already added...\n");
    }
    break;

  case BrDelTag:
    if(XFindContext(XtDisplay(parent), win, master.boxcon,
		    (char **)&tmpwdg)) {
      printf("cnct: lost context of box 0x%x\n", win);
    } else {
      if(glbwin==win) glbwin = 0;
      XtDestroyWidget(tmpwdg);
    }
    break;
  }
}

#define ZWGCATOMNAME "ZEPHYR_SUMMARY"

main (argc, argv)
     int argc;
     char **argv;
{

#include "zbrowser_body.c"
  
  master.tagatom = XInternAtom(XtDisplay(top), ZWGCATOMNAME, False);
  master.wincon = XUniqueContext();
  master.boxcon = XUniqueContext();

  newone(BrSetPar, panes, 0, 0);

  XtRealizeWidget(top);
  
  BrowserLoop(top);
}

