/* winselect.c
 *
 * Some of this code was taken from the xwininfo package that comes with most
 * X11 distributions.  Of the functions taken, everything has been rewritten
 * to reflect GTKeyboard's needs.
 *
 * rewritten by David Allen 
 * s2mdalle@titan.vcu.edu
 * http://opop.nols.com/
 */
/* GTKeyboard - A Graphical Keyboard For X
 * Copyright (C) 1999, 2000 David Allen  
 *
 * 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 Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */

#define WINSELECT_C
#include "master.h"

#ifndef WINSELECT_H
#  include "include/winselect.h"
#endif /* WINSELECT_H */

#define ARGC               (*rargc)
#define OPTION             rargv[0]
#define NXTOPTP            ++rargv, --argc>0
#define NXTOPT             if (++rargv, --argc==0)\
                              printf("Would have called usage.\n") 
#define COPYOPT            nargv++[0]=OPTION, nargc++


/*
 * Routine to let user select a window using the mouse
 */
Window Select_Window(Display *dpy)
{
     int status;
     Cursor cursor;
     XEvent event;
     Window target_win = None, root = GDK_ROOT_WINDOW();
     int buttons = 0;
     
     /* Make the target cursor */
     cursor = XCreateFontCursor(dpy, XC_crosshair);
     
     /* Grab the pointer using target cursor, letting it room all over */
     status = XGrabPointer(dpy, root, False,
			   (ButtonPressMask | ButtonReleaseMask), GrabModeSync,
			   GrabModeAsync, root, cursor, CurrentTime);
     if (status != GrabSuccess) 
     {
	  gtkeyboard_error(1,"Can't grab mouse!\n");
     } /* End if */
     
     /* Let the user select a window... */
     while ((target_win == None) || (buttons != 0)) 
     {
	  /* allow one more event */
	  XAllowEvents(dpy, SyncPointer, CurrentTime);
	  XWindowEvent(dpy, root, (ButtonPressMask | ButtonReleaseMask), 
		       &event);

	  switch (event.type) 
	  {
	  case ButtonPress:
	       if (target_win == None) 
	       {
		    target_win = event.xbutton.subwindow; /* window selected */
		    if (target_win == None) target_win = root;
	       } /* End if */
	       buttons++;
	       break;
	  case ButtonRelease:
	       if (buttons > 0) /* there may have been some down before start*/
		    buttons--;
	       break;
	  } /* End switch */
     } /* End while */
     
     XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
     return(target_win);
} /* End Select_Window */

/*
 * Select_Window_Args: a rountine to provide an interface for
 * applications that need to allow the user to select one
 * window on the screen for special consideration.
 */
Window Select_Window_Args(int *rargc, char **rargv)
{
     int nargc=1;
     int argc;
     char **nargv;
     Window w=0;
     
     nargv = rargv+1; 
     argc = ARGC;
     
     while (NXTOPTP) 
     {
	  if (!strcmp(OPTION, "-")) 
	  {
	       COPYOPT;
	       while (NXTOPTP)
		    COPYOPT;
	       break;
	  } /* End if */
	  if (!strcmp(OPTION, "-root")) 
	  {
	       w = GDK_ROOT_WINDOW();
	       continue;
	  } /* End if */
	  if (!strcmp(OPTION, "-name")) 
	  {
	       NXTOPT;
	       w = Window_With_Name(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
				    OPTION);
	       if (!w)
	       {
		    gtkeyboard_error(3,"No window with name ",OPTION,
				     "exists!\n");
	       } /* End if */
	       continue;
	  } /* End if */
	  if (!strcmp(OPTION, "-id")) 
	  {
	       NXTOPT;
	       w=0;
	       sscanf(OPTION, "0x%lx", &w);
	       if (!w)
		    sscanf(OPTION, "%ld", &w);
	       if (!w)
	       {
		    gtkeyboard_error(3,"Invalid window id format:  ",
				     OPTION,"\n");
	       } /* End if */
	       continue;
	  } /* End if */

	  COPYOPT;
     } /* End while */
     ARGC = nargc;
     return(w);
} /* End select_window_args */


/*
 * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
 * If found, remove it from command line.  Don't go past a lone -.
 */
char *Get_Display_Name(int *pargc, char **argv)
{
     int argc = *pargc;
     char **pargv = argv+1;
     char *displayname = NULL;
     int i;
     
     for (i=1; i<argc; i++) 
     {
	  char *arg = argv[i];
	  
	  if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) 
	  {
	       if (++i >= argc) 
	       {
		    fprintf(Q,"Would have called usage.\n");
	       } /* End if */
	       
	       displayname = argv[i];
	       *pargc -= 2;
	       continue;
	  } /* End if */
	  if (!strcmp(arg,"-")) 
	  {
	       while (i<argc)
		    *pargv++ = argv[i++];
	       break;
	  } /* End if */
	  *pargv++ = arg;
     } /* End for */
     
     *pargv = NULL;
     return (displayname);
} /* End get_display_name */

/* Window_With_Name - locates a window with a given name on the display.
 * If no window found, return 0.  If > 1 window found, return first.
 * Top should probably be RootWindow normally.
 */
Window Window_With_Name(Display *dpy, Window top, char *name)
{
     Window *children, dummy;
     unsigned int nchildren;
     int i;
     Window w=0;
     char *window_name;
     
     if (XFetchName(dpy, top, &window_name) ) 
     {
	  if( !strcmp(window_name, name))
	  {
	       XFree( window_name );
	       return(top);
	  } /* End if */
	  XFree( window_name );
     } /* End if */
 
     if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
	  return(0);
     
     for (i=0; i<nchildren; i++) 
     {
	  w = Window_With_Name(dpy, children[i], name);
	  if (w)
	       break;
     } /* End for */
     if (children) 
	  XFree ((char *)children);
     return(w);
} /* End window_with_name */

/*
 * Routine to get the new window name
 */
char *Display_Window_Id(Window window, Bool newline_wanted)
{
     char *win_name;
     
     if (!window) 
     {
	  if(options.redirect_window_name)
	  {
	       g_free(options.redirect_window_name);
	       options.redirect_window_name=NULL;
	  } /* End if */
     } /* End if */
     else 
     {
	  if (window == GDK_ROOT_WINDOW()) 
	  {
	       if(options.redirect_window_name)
	       {
		    g_free(options.redirect_window_name);
		    options.redirect_window_name = NULL;
	       } /* End if */
	  } /* End if */

	  if (!XFetchName(GDK_DISPLAY(), window, &win_name)) 
	  { 
               /* Get window name if any */
	       if(options.redirect_window_name)
	       {
		    g_free(options.redirect_window_name);
		    options.redirect_window_name = NULL;
	       } /* End if */
	       return(NULL);
	  } /* End if */
	  else if (win_name) 
	  {
	       if(options.redirect_window_name)
	       {
		    g_free(options.redirect_window_name);
		    options.redirect_window_name=NULL;
	       } /* End if */
	       
	       options.redirect_window_name = g_strdup_(win_name);

	       XFree(win_name);
	       return(NULL);
	  } /* End else if */
	  else
	       return(NULL);
     } /* End else */
     return(NULL);
} /* End display_window_id */







