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

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

static char rcsid[] = "$Header: main.c,v 1.1 86/12/17 08:53:51 swick Exp $";
/*************************************<+>*************************************
 *****************************************************************************
 **
 **   File:        main.c
 **
 **   Project:     X-ray Toolbox
 **
 **   Description: The file contains the main processing loop for the
 **                icon builder.
 **
 **   *******************************************************************
 **   * (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:	main.c,v $
 * Revision 1.1  86/12/17  08:53:51  swick
 * Initial revision
 * 
 *
 *****************************************************************************
 *************************************<+>*************************************/


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


main (argc, argv)
int argc;
char * argv[];

{
   Display  * displayPtr;
   XEvent     xInput;
   XEvent   * xInputPtr;
   xrEvent  * xrInputPtr;

   INT32 colorTable [8];
   INT32 currentColor;

   RECTANGLE sizeRect;
   POINT     movePt;


   /*
    *  Initialize some variables.
    */

   xInputPtr = &xInput;
   xrInputPtr = (xrEvent *) xInputPtr;


   /*
    *  Get the server and X-ray set up.
    */

   if ((displayPtr = XOpenDisplay (argv[1])) == 0)
      exit();

   if (XrInit (NULL) == FALSE)
      exit();


   /*
    *  Initialize the color tables.
    */

   currentColor = BlackPixel;
   colorTable [0] = BlackPixel;
   colorTable [1] = WhitePixel;

   if (DisplayPlanes() != 1)
   {
      colorTable[2] = GetColor ("red");
      colorTable[3] = GetColor ("green");
      colorTable[4] = GetColor ("blue");
      colorTable[5] = GetColor ("cyan");
      colorTable[6] = GetColor ("magenta");
      colorTable[7] = GetColor ("yellow");
   }


   /*
    *  Set up the default raster information and set 
    *  up the raster display window.
    */

   RasterInit (64, 64, XrBIT1);
   Image (0, MSG_NEW, NULL);


   /*
    *  Get the main window and panel windows going.
    */

   MainWindowInit();
   XDefineCursor (mainWindowId, xrDefaultCursor);
   PanelInit ();
   FilePanel (NULL, MSG_NEW, 0);


   /*
    *  Add all of the menus into the window and activate the top level menu.
    */

   mainMenu = XrMenu (NULL, MSG_NEW, &mainMenuInfo);

   subMenu = XrMenu (NULL, MSG_NEW, &subMenuInfo);
   subMenuIndex.menuInstance = subMenu;
   XrMenu (mainMenu, MSG_ADDSUBMENU, &subMenuIndex);

   subMenu1 = XrMenu (NULL, MSG_NEW, &subMenuInfo1);
   subMenuIndex1.menuInstance = subMenu1;
   XrMenu (mainMenu, MSG_ADDSUBMENU, &subMenuIndex1);

   XrMenu (mainMenu, MSG_ACTIVATEMENU, mainWindowId);


   /*
    *  Select for the types of input needed by this window.
    */

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


   /*
    *  Set up the read loop and wait for input.
    */

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

      if (xInputPtr -> type == XrXRAY)
      {
         switch (xrInputPtr -> inputType)
         {

            case XrEDITOR:
               if (xrInputPtr -> inputCode == XrRASTEREDIT &&
                   xrInputPtr -> value1 == XrSELECT)
                  Image (0, MSG_REDRAW, NULL);
            break;


            case XrMENU:
               if (xrInputPtr -> value2 == 0)
               {
                  switch (xrInputPtr -> value3)
                  {

                     case 0:	/*  Erase Raster  */
                        RasterInit (rasterEditInfo.rasterData.width,
                                    rasterEditInfo.rasterData.height,
                                    rasterEditInfo.rasterData.depth);
                        XrRasterEdit (mainRasterEdit,MSG_REDRAW,XrREDRAW_ALL);
                        Image (0, MSG_REDRAW, NULL);
                     break;


                     case 1:	/*  Select Raster  */
                        SelectRaster();
                     break;


                     case 2:	/*  Single line seperator  */
                     case 3:	/*  Pen color selection    */
                     case 4:	/*  File access selection  */
                     break;


                     case 5:	/*  Builder settings panel  */
                        XSelectInput (mainWindowId, NULL);
                        ProcessPanel();
                        XrEditor (mainWindowId, MSG_REDRAWALL, NULL);
                        XSelectInput (mainWindowId, 
                                      ButtonPressed | ButtonReleased |
                                      KeyPressed    | ExposeWindow);
                     break;


                     case 6:	/*  Double line seperator  */
                     break;


                     case 7:	/*  Exit  */
                        exit();
                     break;
                  }
               }


               /*
                *  Read and Write File panel function handling.
                *  Input is from a menu, value3 indicates which of
                *  the items in the menu were selected.   
                */

               else if (xrInputPtr -> value2 == 1)
               {
                  if (xrInputPtr -> value3 == 0)
                  {
                     XSelectInput (mainWindowId, NULL);
                     if (FilePanel (&rasterEditInfo.rasterData, 
                                   MSG_EDIT, XrREAD) == FALSE) 
                        XrEditor (mainWindowId, MSG_REDRAWALL, NULL);
                     XSelectInput (mainWindowId, 
                                   ButtonPressed | ButtonReleased |
                                   KeyPressed    | ExposeWindow);
                  }
                  else
                  {
                     XSelectInput (mainWindowId, NULL);
                     FilePanel(&rasterEditInfo.rasterData, MSG_EDIT, XrWRITE);
                     XrEditor (mainWindowId, MSG_REDRAWALL, NULL);
                     XSelectInput (mainWindowId, 
                                   ButtonPressed | ButtonReleased |
                                   KeyPressed    | ExposeWindow);
                  }
               }


               /*
                *  Menu color selection -- set current color and the 
                *  raster editor color.
                */

               else if (xrInputPtr -> value2 == 2)
               {
                  currentColor = colorTable[xrInputPtr -> value3];
                  XrRasterEdit (mainRasterEdit, MSG_SETCOLOR, currentColor);
               }
            break;


            default:
            break;
         }
      }


      /*
       *  X ExposeWindow input -- redraw the window.
       */

      else if (xInputPtr -> type == ExposeWindow && 
               xInputPtr -> window == mainWindowId)
         XrEditor (mainWindowId, MSG_REDRAWALL, NULL);

   }
}



/************************************************************************
 *
 *  MainWindowInit sets up the main window the first time it is
 *  called.  It relays out the window using the raster edit rectangle
 *  on subsequent calls.
 *
 ************************************************************************/

MainWindowInit()
{
   INT8 state;
   xrWindowData oldData;


   /*
    *  If either of the editor instance ptr's are NULL, this is the
    *  first time into the routine.  Create and register the window.
    */

   if (mainTitleBar == NULL)
   {
      mainWindowId = XCreateWindow (RootWindow, 10, 10, 1, 1,
                                    xrBorderWidth,
                                    xrWindowForeground,
                                    xrWindowBackground);

      mainWindowData.foreTile = xrWindowForeground;
      mainWindowData.backTile = xrWindowBackground;
      XrSetRect (&mainWindowData.windowRect, 0, 0, 1, 1);

      XrCopyRect (&mainWindowData.windowRect, &oldData.windowRect);
      XrInput (mainWindowId, MSG_ADDWINDOW, &mainWindowData);       

      titleBarInfo.editorWindowId = mainWindowId;
      rasterEditInfo.editorWindowId = mainWindowId;
      XrTitleBar (NULL, MSG_SIZE, &titleBarInfo);
      mainTitleBar = XrTitleBar (NULL, MSG_NEW, &titleBarInfo);

      XMapWindow (mainWindowId);
   }
   else
      XrRasterEdit (mainRasterEdit, MSG_FREE, NULL);


   /*
    * Get the editor sizes and offset them to their proper locations.
    */

   XrRasterEdit (NULL, MSG_SIZE, &rasterEditInfo);

   XrOffsetRect (&rasterEditInfo.editorRect, 5, 
                 titleBarInfo.editorRect.height + 5);

   XrTitleBar (NULL, MSG_SIZE, &titleBarInfo);
   if (titleBarInfo.editorRect.width < rasterEditInfo.editorRect.width + 10)
      titleBarInfo.editorRect.width = rasterEditInfo.editorRect.width + 10;
   else
      rasterEditInfo.editorRect.x = 
       (titleBarInfo.editorRect.width - rasterEditInfo.editorRect.width) / 2;


   /*
    *  Adjust the window size and XrInput's window rectangle information
    *  and if the rectangle has changed, change the window and titlebar.
    */

   mainWindowData.windowRect.width = titleBarInfo.editorRect.width;
   mainWindowData.windowRect.height = rasterEditInfo.editorRect.y +
                                      rasterEditInfo.editorRect.height + 10;

   XrInput (mainWindowId, MSG_GETWINDOWDATA, &oldData);
   if (!(XrEqualRect (&mainWindowData.windowRect, &oldData.windowRect)))
   {
      XrCopyRect (&mainWindowData.windowRect, &oldData.windowRect);
      XChangeWindow (mainWindowId, mainWindowData.windowRect.width,
                                   mainWindowData.windowRect.height);
      XrInput (mainWindowId, MSG_SETWINDOWDATA, &mainWindowData);
      XrTitleBar (mainTitleBar, MSG_RESIZE, &titleBarInfo.editorRect);
   }
   else
      XrTitleBar (mainTitleBar, MSG_REDRAW, XrREDRAW_ALL);


   /*
    *  Get the windows editors set up properly.
    */

   XrTitleBar (mainTitleBar, MSG_GETSTATE, &state);
   if (state == 0)
      XrTitleBar (mainTitleBar, MSG_SETSTATE, XrVISIBLE | XrSENSITIVE);

   mainRasterEdit = XrRasterEdit (NULL, MSG_NEW, &rasterEditInfo);


   /*
    *  Update the image routine to display the new raster.
    */

   Image (mainWindowId, MSG_UPDATE, &rasterEditInfo.rasterData);
}




/************************************************************************
 *
 *  RasterInit
 *	RasterInit deallocates the current raster edit raster and 
 *	allocates a new raster described by width, height, and depth.
 *
 ************************************************************************/

RasterInit (width, height, depth)
INT32 width;
INT32 height;
INT8 depth;

{
   int i, j;
   int size;


   /*
    *  Free the raster then get the size needed for the next raster,
    *  allocate and initialize the raster.
    *
    *  Activate or deactivate the color menu items as appropriate to
    *  to the raster depth.
    */

   if (rasterEditInfo.rasterData.raster != NULL)
      (*xrFree) (rasterEditInfo.rasterData.raster);

   if (depth == XrBIT1)
   {
      size = XYPixmapSize (width, height, 1);
      rasterEditInfo.rasterData.raster = (UINT16 *) (*xrMalloc) (size);

      for (i = size/2 - 1; i >= 0; i--)
         *(rasterEditInfo.rasterData.raster + i) = ~0;
      rasterEditInfo.rasterData.depth = XrBIT1;

      panelRValue = 0;

      for (j = 2; j < 8; j++)
         XrMenu (subMenu1, MSG_DEACTIVATEITEM, j);
   }
   else    
   {
      if (DisplayPlanes() <= 8)
         size = BZPixmapSize (width, height);
      else
         size = WZPixmapSize (width, height);

      rasterEditInfo.rasterData.raster = (UINT16 *) (*xrMalloc) (size);

      if (DisplayPlanes() <= 8)
      {
         for (i = size/2 - 1; i >= 0; i--)
            *(rasterEditInfo.rasterData.raster + i) = 0x0101;
         rasterEditInfo.rasterData.depth = XrBYTE1;
      }
      else
      {
         for (i = 0; i < size; i += 2)
            *(rasterEditInfo.rasterData.raster + i) = ~0x0001;
         rasterEditInfo.rasterData.depth = XrBYTE2;
      }

      panelRValue = 1;

      for (j = 2; j < 8; j++)
         XrMenu (subMenu1, MSG_ACTIVATEITEM, j);
   }


   /*
    *  Adjust the raster view width and height if needed, set the
    *  raster width and height, call PanelStrings to get the builder
    *  panel text edit strings to the proper information.
    */

   if (width < rasterEditInfo.viewRegion.width)
      rasterEditInfo.viewRegion.width = width;
   if (height < rasterEditInfo.viewRegion.height)
      rasterEditInfo.viewRegion.height = height;

   rasterEditInfo.rasterData.width = width;
   rasterEditInfo.rasterData.height = height;

   PanelStrings (rasterEditInfo.viewRegion.width,
                 rasterEditInfo.viewRegion.height,
                 -1, width, height);
}




/************************************************************************
 *
 *  GetColor
 *	GetColor takes as input a string which contains the name of
 *      a color and returns the pixel value for the color.
 *
 ************************************************************************/

GetColor (str)
INT8 * str;

{
   Color color;

   if (XParseColor (str, &color) == 0)
      return (BlackPixel);
   if (XGetHardwareColor (&color) == 0)
      return (BlackPixel);

   return (color.pixel);
}




/************************************************************************
 *
 *  CenterWindow
 *	CenterWindow takes a windowRect looks at the current cursor
 *      position and calculated the point where the origin of the
 *      window should be placed in order to center the window under
 *      the cursor.  The point is adjusted to make sure the window
 *      stays within the bounds of the display.
 *
 ************************************************************************/

CenterWindow (windowRect, movePt)
RECTANGLE * windowRect;
POINT     * movePt;

{
   INT32  cursorX, cursorY;
   Window subWin;

   XQueryMouse (RootWindow, &cursorX, &cursorY, &subWin);

   movePt -> x = cursorX - (windowRect -> width / 2);
   movePt -> y = cursorY - (windowRect -> height / 2);

   if (movePt -> x < 0) movePt -> x = 0;
   if (movePt -> y < 0) movePt -> y = 0;
   if (movePt -> x + windowRect -> width > DisplayWidth())
      movePt -> x = DisplayWidth() - windowRect -> width;
   if (movePt -> y + windowRect -> height > DisplayHeight())
      movePt -> y = DisplayHeight() - windowRect -> height;
}

