/*
 * Copyright (C) 1999 Sasha Vasko <sashav@sprintmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/time.h>

#if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_
#include <sys/select.h>
#endif

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

#include "../configure.h"
#include "../include/aftersteplib.h"
#include "../include/afterstep.h"
#include "../include/style.h"
#include "../include/mystyle.h"
#include "../include/screen.h"
#include "../include/module.h"

int ConnectX(ScreenInfo* scr, char* display_name, unsigned long message_mask)
{
  int x_fd ;
    /* Initialize X connection */
    if (!(dpy = XOpenDisplay (display_name)))
    {
	fprintf (stderr, "%s: can't open display %s", MyName,
		 XDisplayName (display_name));
        exit (1);
    }
    x_fd = XConnectionNumber (dpy);

    screen = scr->screen = DefaultScreen (dpy);
    scr->Root = RootWindow (dpy, scr->screen);
    if (scr->Root == None)
    {
	fprintf (stderr, "%s: Screen %d is not valid ", MyName, (int) scr->screen);
        exit (1);
    }
    scr->d_depth = DefaultDepth (dpy, scr->screen);
    scr->MyDisplayWidth = DisplayWidth( dpy, scr->screen);
    scr->MyDisplayHeight = DisplayHeight( dpy, scr->screen); 
    scr->CurrentDesk = -1;

    XSelectInput( dpy, scr->Root, message_mask );
    return x_fd ;
}

void InitAtoms(Display* dpy, ASAtom *atoms)
{
  int i ;
    for (i = 0; atoms[i].name != NULL ; i++)
	atoms[i].atom = XInternAtom(dpy, atoms[i].name, False); 
}

void DeadPipe( int nonsense );

int My_XNextEvent(Display* dpy, int x_fd, int as_fd, void (*as_msg_handler)(unsigned long type, unsigned long* body) ,XEvent *event)
{
  fd_set in_fdset;
  ASMessage msg ;  
  static int miss_counter = 0;
  struct timeval tv;
  struct timeval *t = NULL;
  static int fd_width = 0 ;

    if( fd_width == 0 ) fd_width = GetFdWidth();

    if( as_msg_handler == NULL || as_fd < 0 || x_fd < 0 ) 
	return 0;

    if (XPending (dpy))
    {
        XNextEvent (dpy, event);
        miss_counter = 0;
	return 1 ;
    }else
    {
        FD_ZERO (&in_fdset);
        FD_SET (x_fd, &in_fdset);
        FD_SET (as_fd, &in_fdset);
        if (timer_delay_till_next_alarm ((time_t *) & tv.tv_sec, (time_t *) & tv.tv_usec))
	    t = &tv;
#ifdef __hpux
	while (select (fd_width, (int *) &in_fdset, 0, 0, t) == -1)
	    if (errno != EINTR)  break;
#else
	while (select (fd_width, &in_fdset, 0, 0, t) == -1)
	    if (errno != EINTR)  break;
#endif
	if (FD_ISSET (x_fd, &in_fdset))
	{
	    if (XPending (dpy))
	    {
	        XNextEvent (dpy, event);
	        miss_counter = 0;
		return 1;
	    }		
    	    if (++miss_counter > 100)    DeadPipe (0);
	}
	if (FD_ISSET(as_fd, &in_fdset))
	    if( ReadASPacket( as_fd, msg.header, &(msg.body)) > 0)
	    {
	        as_msg_handler(msg.header[1], msg.body);
	        free (msg.body);
	    }
    }
    return 0 ;    
}
