/*==================================================================
  ==================================================================
  ==	XMusic -- An Interactive Interface to Csound		  ==
  ==       Copyright (C) 1988 by George D. Drapeau                ==
  ==                  All Rights Reserved                         ==
  ==================================================================
  ==================================================================
*/
/* $Log:	connect.c,v $
 * Revision 1.3  89/08/06  17:58:28  drapeau
 * Cleanedup the code for first X11 release.
 *  */

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <string.h>
#define USEBITMAPS						    /* This is so I can use the "sine64_width" value */
#include "defs.h"
#include "externs.h"


ConnectTools()
{
  Window	rootReturn,childReturn;
  XEvent	event;
  Tool		*tool1, *tool2, *GetToolFromCoords();
  int		x1,y1, x2,y2, whichSide;
  int		rootX,rootY;
  unsigned int	maskReturn;
  Bool		returnVal;

  returnVal = XQueryPointer(dpy,musicWin,
			    &rootReturn,&childReturn,
			    &rootX,&rootY,
			    &x1,&y1,
			    &maskReturn);
  if ((tool1 = GetToolFromCoords(x1,y1)) == NULL)
    {
      printf("Not pointing to any tool.\n");
      XUngrabPointer(dpy,CurrentTime);
      return;
    }
  XGrabPointer(dpy,musicWin,False,ButtonPressMask,
	       GrabModeAsync,GrabModeAsync,
	       None,tCursor,CurrentTime);
  XNextEvent(dpy,&event);
  returnVal = XQueryPointer(dpy,musicWin,
			    &rootReturn,&childReturn,
			    &rootX,&rootY,
			    &x2,&y2,
			    &maskReturn);
  if ((tool2 = GetToolFromCoords(x2,y2)) == NULL)
    {
      printf("Not pointing to any tool.\n");
      XUngrabPointer(dpy,CurrentTime);
      return;
    }
  XUngrabPointer(dpy,CurrentTime);
  if ((tool1->y > tool2->y) &&					    /* Is the first tool underneath the second, and is... */
      (tool1->type == SineTool))				    /* ...the underneath tool a SineTool? */
    {								    /* Yes, this means a SineTool's input is being used. */
      if (x1 < (tool1->x - (sine64_width/6)))			    /* Determine which side the user wants to connect with */
	whichSide = AmpSide;					    /* Side is one of three choices: AmpSide, FreqSide,... */
      else if (x1 > (tool1->x + (sine64_width/6)))		    /* ...or Middle */
	whichSide = FreqSide;
      else whichSide = Middle;
      ConnectSineTool(tool2,tool1,whichSide);			    /* Connect the tools (tool2 is output, tool1 input) */
    }
  else
    if ((tool2->y > tool1->y) &&				    /* Is the 2nd tool below the 1st, and is the tool... */
	(tool2->type == SineTool))				    /* ...below a SineTool? */
      {								    /* Yes, then tool2 is SineTool */
	if (x2 < (tool2->x - (sine64_width/6)))			    /* Determine which side the user wants to connect with */
	  whichSide = AmpSide;					    /* Side is one of three choices: AmpSide, FreqSide,... */
	else if (x2 > (tool2->x + (sine64_width/6)))		    /* ...or Middle */
	  whichSide = FreqSide;
	else whichSide = Middle;
	ConnectSineTool(tool1,tool2,whichSide);			    /* Connect the tools (tool1 is output, tool2 input) */
      }
  else								    /* We're not trying to connect to the input of a... */
    CheckToolConnection(tool1,tool2);				    /* ...SineTool, so do a normal tool connection. */
}								    /* end function ConnectTools */



DisconnectTools()
{
  Window	rootReturn,childReturn;
  XEvent	event;
  Tool		*tool1, *tool2, *inputTool, *outputTool, *GetToolFromCoords();
  int		x,y,whichSide;
  int		rootX,rootY;
  unsigned int	maskReturn;
  Bool		returnVal;

  returnVal = XQueryPointer(dpy,musicWin,
			    &rootReturn,&childReturn,
			    &rootX,&rootY,
			    &x,&y,
			    &maskReturn);
  if ((tool1 = GetToolFromCoords(x,y)) == NULL)
    {
      printf("Not pointing to any tool.\n");
      XUngrabPointer(dpy,CurrentTime);
      return;
    }
  XGrabPointer(dpy,musicWin,False,ButtonPressMask,
	       GrabModeAsync,GrabModeAsync,
	       None,tCursor,CurrentTime);
  XNextEvent(dpy,&event);
  returnVal = XQueryPointer(dpy,musicWin,
			    &rootReturn,&childReturn,
			    &rootX,&rootY,
			    &x,&y,
			    &maskReturn);
  if ((tool2 = GetToolFromCoords(x,y)) == NULL)
    {
      printf("Not pointing to any tool.\n");
      XUngrabPointer(dpy,CurrentTime);
      return;
    }
  XUngrabPointer(dpy,CurrentTime);
  if (tool1->y < tool2->y)					    /* Is the first tool above the 2nd in the diagram? */
    {
      outputTool = tool1;					    /* Yes, 1st tool is top and is the 'output' tool */
      inputTool = tool2;					    /* 2nd tool is below and receives input from 1st */
    }
  else								    /* No, do the reverse of the above, that is,... */
    {
      outputTool = tool2;					    /* 2nd tool is above and is 'output' tool */
      inputTool = tool1;					    /* 1st tool is below and receives input from 2nd */
    }
  if ((outputTool->output != inputTool) &&			    /* Are the two tools connected? i.e., is output of one... */
      (inputTool->input1 != outputTool) &&			    /* ...connected to the input of the other? */
      (inputTool->input2 != outputTool) &&
      (inputTool->input3 != outputTool) && (inputTool->input4 != outputTool) &&
      (inputTool->input5 != outputTool) && (inputTool->input6 != outputTool) &&
      (inputTool->input7 != outputTool) && (inputTool->input8 != outputTool))
    {
      printf("Those two tools are not connected; nothing will be disconnected.\n");
      return;
    }
  if (inputTool->input1 == outputTool)				    /* Yes, they're connected, which input is the one... */
    inputTool->input1 = NULL;					    /* ...to disconnect?  Input1,2, ...,8? */
  else if (inputTool->input2 == outputTool)			    /* Disconnect the appropriate input connection */
    inputTool->input2 = NULL;
  else if (inputTool->input3 == outputTool)
    inputTool->input3 = NULL;
  else if (inputTool->input4 == outputTool)
    inputTool->input4 = NULL;
  else if (inputTool->input5 == outputTool)
    inputTool->input5 = NULL;
  else if (inputTool->input6 == outputTool)
    inputTool->input6 = NULL;
  else if (inputTool->input7 == outputTool)
    inputTool->input7 = NULL;
  else if (inputTool->input8 == outputTool)
    inputTool->input8 = NULL;
  outputTool->output = NULL;					    /* Disconnect the output connection */
  changesMade = 1;						    /* Signal that changes were made to the diagram */
  DrawMusicWin();						    /* Redraw the Music window */
}								    /* end function DisconnectTools */



CheckToolConnection(tool1,tool2)				    /* Function checks if the two tools passed as... */
     Tool	*tool1, *tool2;					    /* ...args are suitable for linking to each other */
{
  Tool	*inputTool, *outputTool;

  if (tool1 == tool2)						    /* Did user try to connect a tool to itself? */
    {
      printf("Sorry, a tool cannot be connected to itself, except through feedback.\n");
      return;
    }
  if (tool1->y < tool2->y)					    /* Is the first tool above the 2nd in the diagram? */
    {
      outputTool = tool1;					    /* Yes, 1st tool is top and is the 'output' tool */
      inputTool = tool2;					    /* 2nd tool is below and receives input from 1st */
    }
  else								    /* No, do the reverse of the above, that is,... */
    {
      outputTool = tool2;					    /* 2nd tool is above and is 'output' tool */
      inputTool = tool1;					    /* 1st tool is below and receives input from 2nd */
    }
  if (outputTool->output !=NULL)				    /* Is the output pointer of this tool being used? */
    {
      printf("Sorry, Output is already being used.\n");		    /* Yes, outputs can only be used once, so report this... */
      return;							    /* ...to the user and exit this function */
    }
  if (inputTool->type == ParamTool)				    /* Is the user trying to provide an input to a ParamTool? */
    {								    /* Yes, this is illegal; report the error, exit function */
      printf("Sorry, parameters cannot take input -- they can only produce output.\n");
      return;
    }
  if ((inputTool->input1) && (inputTool->input2) &&		    /* Are all inputs to this tool being used? */
      (inputTool->input3) && (inputTool->input4) &&
      (inputTool->input5) && (inputTool->input6) &&
      (inputTool->input7) && (inputTool->input8))
    {
      printf("Sorry, all inputs are already being used.\n");	    /* Yes, report this to the user & exit the function */
      return;
    }
  outputTool->output = inputTool;				    /* Connect the output of one tool to input of the other */
  if (inputTool->input1 == NULL)				    /* Has the first of this tool's inputs been used? */
    inputTool->input1 = outputTool;				    /* No, use it to connect to the output of the other tool */
  else if (inputTool->input2 == NULL)				    /* Yes, keep checking for the first available input... */
    inputTool->input2 = outputTool;				    /* ...and connect it to the output tool when found */
  else if (inputTool->input3 == NULL)
    inputTool->input3 = outputTool;
  else if (inputTool->input4 == NULL)
    inputTool->input4 = outputTool;
  else if (inputTool->input5 == NULL)
    inputTool->input5 = outputTool;
  else if (inputTool->input6 == NULL)
    inputTool->input6 = outputTool;
  else if (inputTool->input7 == NULL)
    inputTool->input7 = outputTool;
  else if (inputTool->input8 == NULL)
    inputTool->input8 = outputTool;
  changesMade = 1;						    /* Set flag saying that changes were made to the diagram */
  DrawToolConnection(inputTool);				    /* Draw a line connecting the two tools */
}								    /* end function CheckToolConnection */




ConnectSineTool(outputTool,inputTool,whichSide)
     Tool	*outputTool, *inputTool;
     int	whichSide;
{
  Tool	*tPtr;
  
  if (outputTool == inputTool)					    /* Did user try to connect a tool to itself? */
    {
      printf("Sorry, a tool cannot be connected to itself, except through feedback.\n");
      return;
    }
  if (outputTool->output !=NULL)				    /* Is the output pointer of this tool being used? */
    {
      printf("Sorry, Output is already being used.\n");		    /* Yes, outputs can only be used once, so report this... */
      return;							    /* ...to the user and exit this function */
    }
  if (whichSide == AmpSide)					    /* Decide which input we're trying to connect with */
    tPtr = inputTool->input1;					    /* Amplitude input */
  else if (whichSide == FreqSide)				    /* Frequency input */
    tPtr = inputTool->input2;
  else if (inputTool->input3 == NULL)				    /* Keep checking until the correct input is found */
    tPtr = inputTool->input3;
  else if (inputTool->input4 == NULL)
    tPtr = inputTool->input4;
  else if (inputTool->input5 == NULL)
    tPtr = inputTool->input5;
  else if (inputTool->input6 == NULL)
    tPtr = inputTool->input6;
  else if (inputTool->input7 == NULL)
    tPtr = inputTool->input7;
  else if (inputTool->input8 == NULL)
    tPtr = inputTool->input8;
  if (tPtr != NULL)						    /* Is the input already being used? */
    {
      printf("Sorry, that input is already being used.\n");	    /* Yes, report the error and exit this function */
      return;
    }								    /* end if tPtr... */
  outputTool->output = inputTool;				    /* Connect the output tool */
  if (whichSide == AmpSide)					    /* Determine which input to use */
    inputTool->input1 = outputTool;				    /* Connect the Amp input to the output tool */
  else if (whichSide == FreqSide)				    /* Connect the Freq input to the output tool */
    inputTool->input2 = outputTool;
  else if (tPtr == inputTool->input3)				    /* Find the correct input to connect with */
    inputTool->input3 = outputTool;
  else if (tPtr == inputTool->input4)
    inputTool->input4 = outputTool;
  else if (tPtr == inputTool->input5)
    inputTool->input5 = outputTool;
  else if (tPtr == inputTool->input6)
    inputTool->input7 = outputTool;
  else if (tPtr == inputTool->input7)
    inputTool->input7 = outputTool;
  else if (tPtr == inputTool->input8)
    inputTool->input8 = outputTool;
  changesMade = 1;						    /* Set flag saying that changes were made to the diagram */
  DrawToolConnection(inputTool);				    /* Draw a line connecting the two tools */
}								    /* end function ConnectSineTool */
