/* This is stolen from the zephyr lib.  I'm replacing it so that Xlib
can still function while zephyr is waiting for a packet.  This will
lose miserably if Xt isn't reentrant, but I think it is */

/* This file is part of the Project Athena Zephyr Notification System.
 * It contains the ZCheckIfNotice/select loop used for waiting for
 * a notice, with a timeout.
 *
 *	Created by:	<Joe Random Hacker>
 *
 *	$Source: /afs/sipb/project/xznol/src/RCS/ZWaitForNotice.c,v $
 *	$Author: marc $
 *
 *	Copyright (c) 1991 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */

#include "xznol.h"
#include "zephyr.h"

#include <zephyr/mit-copyright.h>

#if !defined(lint) && !defined(SABER)
static char rcsid_ZWaitForNotice_c[] =
  "$Zephyr: /mit/zephyr/src/lib/RCS/ZWaitForNotice.c,v 1.1 91/03/21 12:05:21 raeburn Exp $";
#endif

#include <zephyr/zephyr.h>

#ifdef ZWFNDEBUG
#define dprintf(args) printf args
#else
#define dprintf(args)
#endif

static int already_here = 0;

Code_t
Z_WaitForNotice (notice, pred, uid, timeout)
     ZNotice_t *notice;
     int (*pred) ();
     ZUnique_Id_t *uid;
     int timeout;
{
  Code_t retval;

  /* give X a chance first */
  process_xinput();

  retval = ZCheckIfNotice (notice, (struct sockaddr_in *) 0, pred,
			   (char *) uid);
  if (retval == ZERR_NONE)
    return ZERR_NONE;
  if (retval != ZERR_NONOTICE)
    return retval;

  /* sigh.  Not much of a better way to do this */
  if (already_here) return EWOULDBLOCK;

  already_here = 1;

  dprintf(("add_zwfn_timeout(%d)\n",timeout));

  add_zwfn_timeout(timeout);

  while (!app_zwfn()) {
     /* activity on the zephyr socket. see if it's the one we're waiting for */
     retval = ZCheckIfNotice (notice, (struct sockaddr_in *) 0, pred,
			      (char *) uid);
     if (retval == ZERR_NONOTICE) {
	dprintf(("zwfn: dispatching to zephyr_input()\n"));
	/* not the one we're looking for.  run xznol dispatcher on the first
	   packet only.  otherwise, it may come in later and be thrown out
	   by the dispatcher.  If it's an incomplete packet, zephyr_input()
	   will return immediately. */

	   zephyr_input(1);
     } else {
	dprintf(("zwfn: returning to user: retval=%d\n", retval));
	/* otherwise, we either succeeded or got an error for the user.
	   kill off the timeout, and return the status */
	remove_zwfn_timeout();
	already_here = 0;
	return retval;
     }
  }

  already_here = 0;

  dprintf(("zwfn: timed out\n"));

  return ETIMEDOUT;
}
