/*------------------------------------------------------------\
|                                                             |
| Tool    :                   GRAAL                           |
|                                                             |
| File    :                  Cursor.c                         |
|                                                             |
| Authors :      Venot Frederic and Jacomme Ludovic           |
|                                                             |
| Date    :                  01.08.93                         |
|                                                             |
\------------------------------------------------------------*/

/*------------------------------------------------------------\
|                                                             |
|                         Include Files                       |
|                                                             |
\------------------------------------------------------------*/

# include <stdio.h>
# include <X11/Intrinsic.h>
# include <X11/StringDefs.h>
# include <Xm/Xm.h>

# include MUT_H
# include MPH_H
# include RDS_H
# include RPR_H
# include GSB_H
# include GMX_H
# include "GMX_view.h"
# include "GMX_grid.h"
# include "GMX_cursor.h"

/*------------------------------------------------------------\
|                                                             |
|                           Constants                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                            Types                            |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Variables                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                            Buffer                           |
|                                                             |
\------------------------------------------------------------*/

  static char  GraalCursorBuffer[ GRAAL_MAX_CURSOR_BUFFER ];

/*------------------------------------------------------------\
|                                                             |
|                         Coordinates                         |
|                                                             |
\------------------------------------------------------------*/

  Position GraalCursorX       = 0;
  Position GraalCursorY       = 0;
  Position GraalCursorSaveX   = 0;
  Position GraalCursorSaveY   = 0;
  char     GraalCursorSaved   = GRAAL_FALSE;
  char     GraalCursorInside  = GRAAL_FALSE;
  char     GraalCursorType    = GRAAL_INPUT_HALF_BOX;

  long     GraalLambdaCursorX = 0;
  long     GraalLambdaCursorY = 0;
  long     GraalPixelCursorX  = 0;
  long     GraalPixelCursorY  = 0;

  long     GraalLambdaCursorSaveX[ 2 ] = { 0, 0 };
  long     GraalLambdaCursorSaveY[ 2 ] = { 0, 0 };
  char     GraalCursorIndex            = 0;

/*------------------------------------------------------------\
|                                                             |
|                           Functions                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                      GraalComputeCursor                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalComputeCursor( X, Y )

       Position X;
       Position Y;
  {
    Y = GraalGraphicDy - Y;

    GraalLambdaCursorX = X + GraalPixelGridX;
    GraalLambdaCursorY = Y + GraalPixelGridY;

    if ( GraalLambdaCursorX < 0 )
    {
      GraalLambdaCursorX = ((float)(GraalLambdaCursorX) / GraalLambdaGridStep) - 0.5 ;
    }
    else
    {
      GraalLambdaCursorX = ((float)(GraalLambdaCursorX) / GraalLambdaGridStep) + 0.5 ;
    }

    if ( GraalLambdaCursorY < 0 )
    {
      GraalLambdaCursorY = ((float)(GraalLambdaCursorY) / GraalLambdaGridStep) - 0.5 ;
    }
    else
    {
      GraalLambdaCursorY = ((float)(GraalLambdaCursorY) / GraalLambdaGridStep) + 0.5 ;
    }

    GraalPixelCursorX  = ((float)(GraalLambdaCursorX) * GraalLambdaGridStep);
    GraalPixelCursorY  = ((float)(GraalLambdaCursorY) * GraalLambdaGridStep);

    GraalCursorX = GraalPixelCursorX - GraalPixelGridX;
    GraalCursorY = GraalPixelCursorY - GraalPixelGridY;
    GraalCursorY = GraalGraphicDy - GraalCursorY;
  }

/*------------------------------------------------------------\
|                                                             |
|                    GraalDisplayCoordinates                  |
|                                                             |
\------------------------------------------------------------*/

  void GraalDisplayCoordinates()

  {
    sprintf( GraalCursorBuffer, "%d", GraalLambdaCursorX );
    GraalDisplayMessage( GRAAL_MESSAGE_X, GraalCursorBuffer );

    sprintf( GraalCursorBuffer, "%d", GraalLambdaCursorY );
    GraalDisplayMessage( GRAAL_MESSAGE_Y, GraalCursorBuffer );

    sprintf( GraalCursorBuffer, "%d", GraalLambdaCursorX - GraalLambdaCursorSaveX[0] );
    GraalDisplayMessage( GRAAL_MESSAGE_DX, GraalCursorBuffer );

    sprintf( GraalCursorBuffer, "%d", GraalLambdaCursorY - GraalLambdaCursorSaveY[0] );
    GraalDisplayMessage( GRAAL_MESSAGE_DY, GraalCursorBuffer );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalPointCursor                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalPointCursor()

  {
    GraalUndisplayCursor();

    GraalLambdaCursorSaveX[ GraalCursorIndex ] = GraalLambdaCursorX;
    GraalLambdaCursorSaveY[ GraalCursorIndex ] = GraalLambdaCursorY;

    GraalCursorIndex = GraalCursorIndex + 1;

    GraalDisplayCursor();
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalResetCursor                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalResetCursor()

  {
    GraalUndisplayCursor();

    GraalCursorIndex = GraalCursorIndex - 1;

    GraalDisplayCursor();
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalChangeCursor                    |
|                                                             |
\------------------------------------------------------------*/

  void GraalChangeCursorType( ArrayX, ArrayY, Index, Type )

     long *ArrayX;
     long *ArrayY;
     char  Index;
     char  Type;
  {
    GraalUndisplayCursor();

    GraalCursorType  = Type;
    GraalCursorIndex = Index;

    if ( Index != 0 )
    {
      GraalLambdaCursorSaveX[ 0 ] = ArrayX[0];
      GraalLambdaCursorSaveY[ 0 ] = ArrayY[0];
      GraalLambdaCursorSaveX[ 1 ] = ArrayX[1];
      GraalLambdaCursorSaveY[ 1 ] = ArrayY[1];
    }
    
    GraalDisplayCursor();
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalDrawCursor                      |
|                                                             |
\------------------------------------------------------------*/

  void GraalDrawCursor()

  {
    long X1;
    long Y1;
    long X2;
    long Y2;
    long DeltaX;
    long DeltaY;
    long Swap;
    char DrawLine;

    XDrawLine( XtDisplay( GraalGraphicWindow ),
               XtWindow( GraalGraphicWindow ),
               GraalXorGC,
               GraalCursorSaveX - 5, GraalCursorSaveY - 5,
               GraalCursorSaveX + 5, GraalCursorSaveY + 5 );

    XDrawLine( XtDisplay( GraalGraphicWindow ),
               XtWindow( GraalGraphicWindow ),
               GraalXorGC,
               GraalCursorSaveX - 5, GraalCursorSaveY + 5,
               GraalCursorSaveX + 5, GraalCursorSaveY - 5 );

    if ( GraalCursorIndex > 0 )
    {
      X1 = (float)(GraalLambdaCursorSaveX[0]) * GraalLambdaGridStep;
      Y1 = (float)(GraalLambdaCursorSaveY[0]) * GraalLambdaGridStep;
      X1 = X1 - GraalPixelGridX;
      Y1 = Y1 - GraalPixelGridY;
      Y1 = GraalGraphicDy - Y1;

      if ( GraalCursorIndex == 1 )
      {
        X2 = GraalCursorSaveX;
        Y2 = GraalCursorSaveY;
      }
      else
      {
        X2 = (float)(GraalLambdaCursorSaveX[1]) * GraalLambdaGridStep;
        Y2 = (float)(GraalLambdaCursorSaveY[1]) * GraalLambdaGridStep;
        X2 = X2 - GraalPixelGridX;
        Y2 = Y2 - GraalPixelGridY;
        Y2 = GraalGraphicDy - Y2;
      }

      switch( GraalCursorType )
      {
        case GRAAL_INPUT_POINT :
  
          break;

        case GRAAL_INPUT_LINE  :

          XDrawLine( XtDisplay( GraalGraphicWindow ),
                     XtWindow( GraalGraphicWindow ),
                     GraalXorGC,
                     X1, Y1, X2, Y2 );
          break;

        case GRAAL_INPUT_HALF_BOX :

          XDrawLine( XtDisplay( GraalGraphicWindow ),
                     XtWindow( GraalGraphicWindow ),
                     GraalXorGC,
                     X1, Y1, X2, Y1 );

          XDrawLine( XtDisplay( GraalGraphicWindow ),
                     XtWindow( GraalGraphicWindow ),
                     GraalXorGC,
                     X2, Y1, X2, Y2 );
          break; 

        case GRAAL_INPUT_ORTHO   :
        case GRAAL_INPUT_SORTHO  :
        case GRAAL_INPUT_LSTRING :

          DeltaX = X2 - X1; if ( DeltaX < 0 ) DeltaX = - DeltaX;
          DeltaY = Y2 - Y1; if ( DeltaY < 0 ) DeltaY = - DeltaY;

          if ( DeltaX > DeltaY )
          {
            Y2 = Y1;

            if ( X1 > X2 ) { Swap = X1; X1 = X2; X2 = Swap; }

            if ( X1 < 0              ) X1 = 0;
            if ( X2 > GraalGraphicDx ) X2 = GraalGraphicDx;

            if ( ( X1 <  X2             ) &&
                 ( Y1 >= 0              ) &&
                 ( Y1 <= GraalGraphicDy ) )
            {
              XDrawLine( XtDisplay( GraalGraphicWindow ),
                         XtWindow( GraalGraphicWindow ),
                         GraalXorGC,
                         X1, Y1, X2, Y2 );
            }
          }
          else
          {
            X2 = X1;

            if ( Y1 > Y2 ) { Swap = Y1; Y1 = Y2; Y2 = Swap; }

            if ( Y1 < 0              ) Y1 = 0;
            if ( Y2 > GraalGraphicDy ) Y2 = GraalGraphicDy;

            if ( ( Y1 <  Y2             ) &&
                 ( X1 >= 0              ) &&
                 ( X1 <= GraalGraphicDx ) )
            {
              XDrawLine( XtDisplay( GraalGraphicWindow ), 
                         XtWindow( GraalGraphicWindow ), 
                         GraalXorGC,   
                         X1, Y1, X2, Y2 ); 
            }
          }

          break;

        case GRAAL_INPUT_BOX :
 
          if ( X1 > X2 ) { Swap = X1; X1 = X2; X2 = Swap; }
          if ( Y1 > Y2 ) { Swap = Y1; Y1 = Y2; Y2 = Swap; }

          DrawLine = 0;

          if ( X1 < 0              ) { X1 = 0;              DrawLine |= GRAAL_WEST;  }
          if ( X2 > GraalGraphicDx ) { X2 = GraalGraphicDx; DrawLine |= GRAAL_EAST;  }
          if ( Y1 < 0              ) { Y1 = 0;              DrawLine |= GRAAL_SOUTH; }
          if ( Y2 > GraalGraphicDy ) { Y2 = GraalGraphicDy; DrawLine |= GRAAL_NORTH; }

          if ( DrawLine == 0 )
          {
            XDrawRectangle( XtDisplay( GraalGraphicWindow ),
                            XtWindow( GraalGraphicWindow ),
                            GraalXorGC,
                            X1, Y1,
                            X2 - X1, Y2 - Y1 );
          }
          else 
          {
            if ( ( DrawLine & GRAAL_WEST ) == 0 )
            {
              XDrawLine( XtDisplay( GraalGraphicWindow ),
                         XtWindow( GraalGraphicWindow ),
                         GraalXorGC,
                         X1, Y2,
                         X1, Y1 );
            }

            if ( ( DrawLine & GRAAL_EAST ) == 0 )
            {
              XDrawLine( XtDisplay( GraalGraphicWindow ),
                         XtWindow( GraalGraphicWindow ),
                         GraalXorGC,
                         X2, Y2,
                         X2, Y1 );
            }

            if ( ( DrawLine & GRAAL_SOUTH ) == 0 )
            {
              XDrawLine( XtDisplay( GraalGraphicWindow ),
                         XtWindow( GraalGraphicWindow ),
                         GraalXorGC,
                         X1, Y1,
                         X2, Y1 );
            }

            if ( ( DrawLine & GRAAL_NORTH ) == 0 )
            {
              XDrawLine( XtDisplay( GraalGraphicWindow ),
                         XtWindow( GraalGraphicWindow ),
                         GraalXorGC,
                         X1, Y2,
                         X2, Y2 );
            }
          }

        break;

      }
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                    GraalUndisplayCursor                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalUndisplayCursor()

  {
    if ( GraalCursorInside == GRAAL_TRUE )
    {
      if ( GraalCursorSaved == GRAAL_TRUE )
      {
        GraalDrawCursor();
      }

      GraalCursorSaved = GRAAL_FALSE;
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                      GraalDisplayCursor                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalDisplayCursor()

  {
    if ( GraalCursorInside == GRAAL_TRUE )
    {
      if ( GraalCursorSaved == GRAAL_TRUE )
      {
        GraalDrawCursor();

        GraalCursorSaved = GRAAL_FALSE;
      }

      if ( ( GraalCursorY >= 0              ) &&
           ( GraalCursorX <= GraalGraphicDx ) )
      {
        GraalCursorSaveX = GraalCursorX;
        GraalCursorSaveY = GraalCursorY;

        GraalDrawCursor();

        GraalCursorSaved = GRAAL_TRUE;
      }
    }
  }
