/*
 *	$Source: /u1/Xr/usr/contrib/RB/RCS/image.c,v $
 *	$Header: image.c,v 1.1 86/12/17 08:53:37 swick Exp $
 */

#ifndef lint
static char *rcsid_image_c = "$Header: image.c,v 1.1 86/12/17 08:53:37 swick Exp $";
#endif	lint

static char rcsid[] = "$Header: image.c,v 1.1 86/12/17 08:53:37 swick Exp $";
/*************************************<+>*************************************
 *****************************************************************************
 **
 **   File:        image.c
 **
 **   Project:     X-ray Toolbox
 **
 **   Description: This file contains the routines necessary to create
 **                a window and display and redisplay a raster image
 *                 within it.
 **
 **   *******************************************************************
 **   * (c)  Copyright Hewlett-Packard Company, 1986.  All rights are   *
 **   * reserved.  Copying or other reproduction of this program except *
 **   * for archival purposes is prohibited without the prior written   *
 **   * consent of Hewlett-Packard Company.                             *
 **   *******************************************************************
 **
 **
 **   ------------------------ MODIFICATION RECORD   ------------------------
 *
 * $Log:	image.c,v $
 * Revision 1.1  86/12/17  08:53:37  swick
 * Initial revision
 * 
 *
 *****************************************************************************
 *************************************<+>*************************************/


#include <X/Xlib.h>
#include <Xr/defs.h>
#include <Xr/types.h>
#include "image.h"



Image (windowId, message, data)
Window windowId;
INT32  message;
INT8 * data;

{
   switch (message)
   {

      /*
       *  Set up the editors needed to handle the display of the 
       *  image and create a panel to display the image.
       */

      case MSG_NEW:
      {

         mainWindowId = 
            XCreateWindow (RootWindow, 0, 0, 1, 1,
                           xrBorderWidth, 
                           xrWindowForeground, xrWindowBackground);
         subWindowId = 
            XCreateWindow (mainWindowId, 0, 0, 1, 1,
                           1, BlackPixmap, WhitePixmap);

         XDefineCursor (mainWindowId, xrDefaultCursor);
         XDefineCursor (subWindowId, xrDefaultCursor);

         XSelectInput (mainWindowId, ButtonPressed | ButtonReleased |
                                     EnterWindow   | ExposeWindow);
                                     

         XrSetRect (&windowData.windowRect, 0, 0, 0, 0);
         windowData.foreTile = BlackPixmap;
         windowData.backTile = WhitePixmap;
         XrInput (mainWindowId, MSG_ADDWINDOW, &windowData);
         windowFunct.processFlag = TRUE;
         windowFunct.funct = (xrPFI) ImageEdit;
         windowFunct.instance = (INT32) mainWindowId;
         windowFunct.message = (INT32) MSG_EDIT;
         windowFunct.eventCount = 1;
         windowFunct.eventList = &eventSet[0];
         XrInput (mainWindowId, MSG_ADDWINDOWFUNCT, &windowFunct);

         XrTitleBar (NULL, MSG_SIZE, &titleBarInfo);
         XrScrollBar (NULL, MSG_SIZE, &scrollHorInfo);
         XrScrollBar (NULL, MSG_SIZE, &scrollVertInfo);

         titleBarInfo.editorWindowId = mainWindowId;
         scrollHorInfo.editorWindowId = mainWindowId;
         scrollVertInfo.editorWindowId = mainWindowId;

         titleBar = XrTitleBar (NULL, MSG_NEW, &titleBarInfo);
      }
      break;


      /*
       *  Add a pixmap or bitmap into the window by setting the window
       *  sizes, setting the editors, mapping the windows, and writing
       *  the bits.
       */

      case MSG_UPDATE:
      {
         WindowInfo info;
         INT32      moreWidth;

         XSelectInput (mainWindowId, NULL);

         XQueryWindow (windowId, &info);

         mainWindowX = info.x + info.width + 20;
         mainWindowY = info.y;

         pixmap = (xrPixmap *)  data;


         /*
          *  Calculate the necessary width of the window.
          */

         if (horScrollable == TRUE)
            XrScrollBar (scrollHor, MSG_FREE, NULL);

         horScrollable = FALSE;

         XrTitleBar (NULL, MSG_SIZE, &titleBarInfo);
         mainWindowWidth = titleBarInfo.editorRect.width;

         if (pixmap -> height > maxWindowHeight - 
                                titleBarInfo.editorRect.height - 10)
         {
            moreWidth = scrollVertInfo.editorRect.width;
            mainWindowWidth += moreWidth;
         }
         else
            moreWidth = 0;

         if (mainWindowWidth - 10 < pixmap -> width)
            mainWindowWidth = pixmap -> width + 10 + moreWidth;

         if (mainWindowWidth > maxWindowWidth)
         {
            mainWindowWidth = maxWindowWidth;
            horScrollable = TRUE;
         }

         titleBarInfo.editorRect.width = mainWindowWidth;


         /*
          *  Calculate the height of the window.
          */

         if (vertScrollable == TRUE)
            XrScrollBar (scrollVert, MSG_FREE, NULL);

         vertScrollable = FALSE;
         mainWindowHeight = 
            titleBarInfo.editorRect.height + pixmap -> height + 10;

         if (horScrollable)
            mainWindowHeight += scrollHorInfo.editorRect.height;

         if (mainWindowHeight > maxWindowHeight)
         {
            mainWindowHeight = maxWindowHeight;
            vertScrollable = TRUE;
         }

            
         /*
          *  Position the scroll bars.
          */

         if (horScrollable)
         {
            scrollHorInfo.editorRect.x = 5;

            scrollHorInfo.editorRect.width = mainWindowWidth - 10 + 1;
            if (vertScrollable)
               scrollHorInfo.editorRect.width -= 
                        scrollVertInfo.editorRect.width;
            scrollHor = XrScrollBar (NULL, MSG_NEW, &scrollHorInfo);
         }
         if (vertScrollable)
         {
            scrollVertInfo.editorRect.y = 
                      titleBarInfo.editorRect.height + 5;
            scrollVertInfo.editorRect.height = mainWindowHeight - 
                      titleBarInfo.editorRect.height - 10 + 1;
            if (horScrollable)
               scrollVertInfo.editorRect.height -= 
                        scrollHorInfo.editorRect.height;
            scrollVert = XrScrollBar (NULL, MSG_NEW, &scrollVertInfo);
         }


         /*
          *  Calculate the sub window size, position and mapping point.
          */

         if (horScrollable)
         {
            subWindowX = 5;
            subWindowWidth = scrollHorInfo.editorRect.width - 2;
         }
         else
         {
            subWindowWidth = pixmap -> width;
            if (!vertScrollable)
               subWindowX = (mainWindowWidth - subWindowWidth) / 2;
            else
               subWindowX = (mainWindowWidth - subWindowWidth - 
                             scrollVertInfo.editorRect.width) / 2;
            XrScrollBar (scrollHor, MSG_SETSTATE, 0);
         }

         subWindowY = titleBarInfo.editorRect.height + 5;

         if (vertScrollable)
            subWindowHeight = scrollVertInfo.editorRect.height - 2;
         else
         {
            subWindowHeight = pixmap -> height;
            XrScrollBar (scrollVert, MSG_SETSTATE, 0);
         }

         scrollHorInfo.editorRect.y = subWindowY + subWindowHeight + 1;
         scrollVertInfo.editorRect.x = subWindowX + subWindowWidth + 1;

         pixmapMapX = 0;
         pixmapMapY = 0;


         /*
          *  Get both windows set to the correct size.
          */

         XConfigureWindow (mainWindowId, mainWindowX, mainWindowY,
                           mainWindowWidth, mainWindowHeight);
         XConfigureWindow (subWindowId, subWindowX, subWindowY,
                           subWindowWidth, subWindowHeight);
         XMapWindow (mainWindowId);
         XMapWindow (subWindowId);


         XrSetRect(&windowData.windowRect, mainWindowX, mainWindowY,
                                           mainWindowWidth, mainWindowHeight);
         windowData.foreTile = BlackPixmap;
         windowData.backTile = WhitePixmap;
         XrInput (mainWindowId, MSG_SETWINDOWDATA, &windowData);


         /*
          *  Resize the editors and reposition the editors.
          */

         XrTitleBar (titleBar, MSG_RESIZE, &titleBarInfo.editorRect);
         XrTitleBar (titleBar, MSG_SETSTATE, XrVISIBLE | XrSENSITIVE);

         if (horScrollable)
         {
            XrScrollBar(scrollHor, MSG_RESIZE,
                        &scrollHorInfo.editorRect);
            XrScrollBar(scrollHor, MSG_SETSTATE, XrVISIBLE | XrSENSITIVE);
         }

         if (vertScrollable)
         {
            XrScrollBar(scrollVert, MSG_RESIZE,
                        &scrollVertInfo.editorRect);
            XrScrollBar(scrollVert, MSG_SETSTATE, XrVISIBLE | XrSENSITIVE);
         }


         /*
          *  Display the image.
          */

         if (pixmap -> depth == XrBIT1)
            XBitmapBitsPut (subWindowId, -pixmapMapX, -pixmapMapY,
                                         pixmap -> width, pixmap -> height,
                                         pixmap -> raster,
                                         1, 0, 0, GXcopy, AllPlanes);
         else
            XPixmapBitsPutZ (subWindowId, -pixmapMapX, -pixmapMapY,
                                          pixmap -> width, pixmap -> height,
                                          pixmap -> raster,
                                          0, GXcopy, AllPlanes);

         XSelectInput (mainWindowId, ButtonPressed | ButtonReleased |
                                     EnterWindow   | ExposeWindow);
         XFlush();

      }
      break;


      case MSG_REDRAW:
      {
         POINT * mapPt;

         mapPt = (POINT *) data;
         if (mapPt != NULL)
         {
            pixmapMapX = mapPt -> x;
            pixmapMapY = mapPt -> y;
         }

         if (pixmap -> depth == XrBIT1)
            XBitmapBitsPut (subWindowId, -pixmapMapX, -pixmapMapY,
                                         pixmap -> width, pixmap -> height,
                                         pixmap -> raster,
                                         1, 0, 0, GXcopy, AllPlanes);
         else
            XPixmapBitsPutZ (subWindowId, -pixmapMapX, -pixmapMapY,
                                          pixmap -> width, pixmap -> height,
                                          pixmap -> raster,
                                          0, GXcopy, AllPlanes);

      }
      break;


      default:
      break;
   }
}



/************************************************************************
 *
 *  ImageEdit is the editing routine for the image window.  It is
 *  called by XrInput upon an enter window event.  It handles the
 *  scrolling and redisplay of the image.
 *
 ************************************************************************/

ImageEdit (windowId, message, input)
Window   windowId;
INT32    message;
XEvent * input;

{
   XExposeEvent * regionInput;
   XMouseOrCrossingEvent * crossInput;
   RECTANGLE      redrawRect;
   xrEvent      * xrInput;
   xrSBParameters parms;


   if (input -> type & ExposeWindow)
   {
         if (input -> subwindow == 0)
         {
            Image (0, MSG_REDRAW, NULL);

            XrTitleBar (titleBar, MSG_REDRAW, XrREDRAW_ALL);

            if (horScrollable)
               XrScrollBar (scrollHor, MSG_REDRAW, XrREDRAW_ALL);

            if (vertScrollable)
               XrScrollBar (scrollVert, MSG_REDRAW, XrREDRAW_ALL);
         }

         input -> type = XrXRAY;
         input -> window = 0;
         XrInput (0, MSG_PUSHEVENT, input);
         return(TRUE);
   }

      
   /*
    *  Turn off the event processing for this function so that recursive
    *  calls do not get generated.
    */

   XSync (1);
   XSelectInput (mainWindowId, ButtonPressed | ButtonReleased);

   while (1)
   {
      XrInput (mainWindowId, MSG_BLKHOTREAD, input);

      if (input -> window != mainWindowId && input -> window != subWindowId)
      {
         XrInput (mainWindowId, MSG_PUSHEVENT, input);
         XSelectInput (mainWindowId, ButtonPressed | ButtonReleased |
                                     EnterWindow   | ExposeWindow);
         return (TRUE);
      }

      else if (input -> type == XrXRAY)
      {
         xrInput = (xrEvent *) input;

         switch (xrInput -> inputType)
         {
            case XrEDITOR:
               if (xrInput -> inputCode == XrTITLEBAR)
                  ;
               else if (xrInput -> inputCode == XrSCROLLBAR)
               {
                  XrScrollBar ((xrEditor *) xrInput -> valuePtr,
                               MSG_GETPARAMETERS, &parms);

                  if (xrInput -> value1 == XrSCROLL_LEFT ||
                      xrInput -> value1 == XrSCROLL_UP)
                  {
                     parms.slidePosition -= 5;
                     DrawImage (xrInput -> valuePtr, &parms);

                     while (XrInput (0, MSG_NONBLKREAD, input) == FALSE)
                     {
                        parms.slidePosition -= 5;
                        DrawImage (xrInput -> valuePtr, &parms);
                     }
                  }
                  else if (xrInput -> value1 == XrSCROLL_RIGHT ||
                           xrInput -> value1 == XrSCROLL_DOWN)
                  {
                     parms.slidePosition += 5;
                     DrawImage (xrInput -> valuePtr, &parms);

                     while (XrInput (0, MSG_NONBLKREAD, input) == FALSE)
                     {
                        parms.slidePosition += 5;
                        DrawImage (xrInput -> valuePtr, &parms);
                     }
                  }
                  else if (xrInput -> value1 == XrSCROLL_LESS ||
                           xrInput -> value1 == XrSCROLL_MORE)
                  {
                     parms.slidePosition = xrInput -> value3;
                     DrawImage (xrInput -> valuePtr, &parms);
                  }
                  else
                  {
                     parms.slidePosition = xrInput -> value2;
                     DrawImage (xrInput -> valuePtr, &parms);
                  }
               }
            break;
         
            default:
            break;
         }
      }
   }
}


/************************************************************************
 *
 *  DrawImage uses the horizontal or vertical scroll parameters to
 *  calculate what part of the image is to be displayed.  It them
 *  call Image to display the image.
 *
 ************************************************************************/

DrawImage (editorInstance, parms)
xrEditor * editorInstance;
xrSBParameters * parms;

{
   if (parms -> slidePosition < 0)
      parms -> slidePosition = 0;
   if (parms -> slidePosition > 100)
      parms -> slidePosition = 100;

   XrScrollBar (editorInstance, MSG_SETPARAMETERS, parms);

   if (editorInstance == scrollHor)
      pixmapMapX = parms -> slidePosition * 
                   (pixmap -> width - subWindowWidth) / 100;
   else
      pixmapMapY = parms -> slidePosition * 
                   (pixmap -> height - subWindowHeight) / 100;
   Image (0, MSG_REDRAW, NULL);
}

