home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / xfitsvew.zip / XFITSview / imagedisp.c < prev    next >
C/C++ Source or Header  |  1998-04-02  |  38KB  |  1,120 lines

  1. /* Display widget for images for XFITSview */
  2. /* allows zoom and scroll            */
  3. /*-----------------------------------------------------------------------
  4. *  Copyright (C) 1996,1997
  5. *  Associated Universities, Inc. Washington DC, USA.
  6. *  This program is free software; you can redistribute it and/or
  7. *  modify it under the terms of the GNU General Public License as
  8. *  published by the Free Software Foundation; either version 2 of
  9. *  the License, or (at your option) any later version.
  10. *
  11. *  This program is distributed in the hope that it will be useful,
  12. *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. *  GNU General Public License for more details.
  15. *-----------------------------------------------------------------------*/
  16. #include <Xm/Xm.h> 
  17. #include <Xm/DrawingA.h> 
  18. #include <Xm/MainW.h>
  19. #include <Xm/ScrollBar.h>
  20. #include <Xm/Form.h>
  21. #include <X11/IntrinsicP.h>
  22. #include <X11/cursorfont.h> 
  23. #include "imagedisp.h"
  24. #include "wpos.h"
  25. #include "logger.h"
  26. #include "menu.h"
  27. #include "messagebox.h"
  28. #include "position.h"
  29. #define min(a,b) (((a) < (b)) ? (a) : (b))
  30. #define max(a,b) (((a) > (b)) ? (a) : (b))
  31. #define SBAR_WIDTH 16; /* width of scroll bars */
  32.  
  33. /* prototypes */
  34. /* internal */
  35. int  FitPos(ImageDisplay *IDdata);
  36. void UpdateInfo (ImageDisplay *IDdata);
  37.  
  38. /* progress/cancel box in FITS2Pix.c*/
  39. void WorkingCursor(int on, int verbose, char* filename);
  40.  
  41.  
  42.  
  43. void ZoomDisplay (ImageDisplay *IDdata, int iXsize, int iYsize, int iXpos, 
  44.           int iYpos, int Width, int Height)
  45. /* Display zoomed image with pixel (iXpos, iYpos) in bottom */
  46. /* left corner. */
  47. /*  iXsize, iYsize = size of display area in pixels */
  48. /*  Width, Height are the width and height of the region in the image */
  49. {
  50.   int xinc, yinc, xrep, yrep, ix, iy, iix, iiy, i, j, icol;
  51.   long yaddr, addr, yaddr2, addr2, nxin, nxout;
  52.   XImage *work, *pixarray;
  53.   unsigned int nx, ny;
  54.   char *pixarray_data, *work_data;
  55.  
  56. /*  debug */
  57. /*  Dimension cwid,chei;
  58.      XtVaGetValues (IDdata->canvas,
  59.             XmNwidth, &cwid,
  60.             XmNheight, &chei,
  61.             NULL);
  62. fprintf (stderr," ZoomDisplay: canvas size: Width %d, Height %d\n",cwid,chei);
  63. */
  64.  
  65. /* don't bother if there's no image yet */
  66.   if (!IDdata) return;
  67.   
  68. /* is there a display yet? */
  69.   if (!IDdata->canvas) return;
  70.   if (!XtIsRealized (IDdata->canvas)) return;
  71.  
  72. /* a few more validity checks */
  73.   if (!image[CurImag].valid) return;
  74.   if (!image[CurImag].pixarray) return;
  75.  
  76. /* with no zoom it's simple */
  77. if (IDdata->zoom==1)  /* no zoom */ 
  78.   {
  79. /* blank it out first */
  80. /*    XSetForeground (XtDisplay(IDdata->canvas), IDdata->gc, 
  81.             BlackPixelOfScreen(XtScreen(IDdata->canvas)));
  82.     XFillRectangle (XtDisplay(IDdata->canvas), XtWindow(IDdata->canvas), 
  83.             IDdata->gc, 0, 0, IDdata->disp_wid, 
  84.             IDdata->disp_hei);*/
  85.  
  86.     XPutImage (XtDisplay (IDdata->canvas), XtWindow(IDdata->canvas), 
  87.            IDdata->gc, image[CurImag].pixarray, iXpos, iYpos, 0, 0,
  88.            (unsigned int) Width, (unsigned int)Height);
  89.     return;
  90.   }
  91.  
  92.   pixarray = image[CurImag].pixarray;
  93.   nxin = pixarray->width;
  94.   pixarray_data = pixarray->data;
  95.   work = IDdata->work;
  96.   nxout = work->width;
  97.   work_data = work->data;
  98. /* set increment, multiples in pixel array */
  99.   if (IDdata->zoom>=1) /* no zoom or zoom in */
  100.     { xinc = 1;
  101.       xrep = IDdata->zoom;
  102.       yinc = 1;
  103.       yrep = IDdata->zoom;}
  104.   else  /* zoom out */
  105.     { xinc = -IDdata->zoom;
  106.       xrep = 1;
  107.       yinc = -IDdata->zoom;
  108.       yrep = 1;}
  109.  
  110.  
  111. /* ix, iy are image pixel numbers, iix, iiy are display pixels */
  112.  
  113.   if (IDdata->depth==8) /* 8 bit display goes faster */
  114.     {
  115. /* copy selected portion of image to display */
  116.       if (IDdata->zoom<=1) /* no zooming or zoom out */
  117.     {iiy = -1;
  118.      for (iy=iYpos; iy<iYpos+Height; iy += yinc)  /* loop over columns */
  119.        {iiy++; iix = -1;
  120.         yaddr = iy * nxin; yaddr2 = iiy * nxout;
  121.         for (ix=iXpos; ix<iXpos+Width; ix += xinc)  /* loop down rows */
  122.           {iix++;
  123.            addr = yaddr + ix; addr2 = yaddr2 + iix;
  124.            *(work_data + addr2) = *(pixarray_data + addr);
  125.          }
  126.       }
  127.        }
  128.       else  /* zooming */
  129.     {iiy = -1;
  130.      for (iy=iYpos; iy<iYpos+Height; iy++)  /* loop over columns */
  131.        {for (j=0; j<yrep; j++)
  132.           {iiy++; iix = -1;
  133.            yaddr = iy * nxin; yaddr2 = iiy * nxout;
  134.            for (ix=iXpos; ix<iXpos+Width; ix++)  /* loop down rows */
  135.          {addr = yaddr + ix; 
  136.           for (i=0; i<xrep; i++)
  137.             {iix++;
  138.              addr2 = yaddr2 + iix;
  139.              *(work_data + addr2) = *(pixarray_data + addr);
  140.            }
  141.         }
  142.          }
  143.       }
  144.        }
  145.     }
  146.   else  /* slowly for non 8-bit displays */
  147.     {iiy = -1;
  148.      for (iy=iYpos; iy<iYpos+Height; iy+=yinc)  /* loop over columns */
  149.        {for (j=0; j<yrep; j++)
  150.       {iiy++; iix = -1;
  151.        for (ix=iXpos; ix<iXpos+Width; ix+=xinc)  /* loop down rows */
  152.          { for (i=0; i<xrep; i++)
  153.          {iix++;
  154.           XPutPixel (work, iix, iiy, XGetPixel(pixarray, ix, iy));
  155.         }
  156.          }
  157.      }
  158.       }
  159.    }
  160. /* blank it out first*/
  161. /*    XSetForeground (XtDisplay(IDdata->canvas), IDdata->gc, 
  162.             BlackPixelOfScreen(XtScreen(IDdata->canvas)));
  163.     XFillRectangle (XtDisplay(IDdata->canvas), XtWindow(IDdata->canvas), 
  164.             IDdata->gc, 0, 0, IDdata->disp_wid, 
  165.             IDdata->disp_hei);*/
  166.  
  167. /* write it out */
  168.   XPutImage (XtDisplay (IDdata->canvas), XtWindow(IDdata->canvas), 
  169.          IDdata->gc, IDdata->work, 0, 0, 0, 0,
  170.          (unsigned int)iix, (unsigned int)iiy);
  171. } /* end ZoomDisplay */
  172.  
  173. void ResetDisplay (ImageDisplay *IDdata)
  174. /* set display parameters and ensures a single expose event to repaint the
  175.    image on the display */
  176. {
  177.   int old_wid, old_hei;
  178.  
  179. /* save old display size */
  180.   old_wid = IDdata->disp_wid;
  181.   old_hei = IDdata->disp_hei;
  182.  
  183. /* reset display parameters*/
  184.   SetDisplay(IDdata);
  185.  
  186. /* terrible hack - if SetDisplay made the display area larger then this
  187.    will provoke an expose event.  If not then create one here. */
  188.     if ((XtIsRealized (IDdata->canvas)) && (old_wid>=IDdata->disp_wid) && 
  189.     (old_hei>=IDdata->disp_hei)) {
  190.       PaintImage(IDdata); /* redraw */
  191.     }
  192. } /* end ResetDisplay */
  193.  
  194. void SetDisplay (ImageDisplay* IDdata) 
  195. /*  sets size and position of the Image display window */
  196. {
  197.      int iXHalf, iYHalf, inXZoom, inYZoom, iScrWid, iScrHei;
  198.      int iZoom, ch1;
  199.      Dimension cwid, chei;
  200.      char *ZP;
  201.      Display     *dpy = XtDisplay (IDdata->display);
  202.      unsigned int unx, uny;
  203.      unsigned long pasize, ilong;
  204.      int value, slider_size, increment, page_increment;
  205.      int sbar_width = SBAR_WIDTH; 
  206.  
  207. /* update info in control pixel info area*/
  208.      UpdateInfo(IDdata);  
  209.  
  210. /* don't bother if there's no valid image yet */
  211.      if (!IDdata) return; /* shouldn't happen */
  212.      if (!image[CurImag].valid) { /* set display for no image */
  213.       /* no scroll bars */
  214.       if (XtIsRealized (IDdata->hscroll)) XtUnmapWidget (IDdata->hscroll);
  215.       IDdata->hscr_vis = 0;
  216.       if (XtIsRealized (IDdata->vscroll)) XtUnmapWidget (IDdata->vscroll);
  217.       IDdata->vscr_vis = 0;
  218.       /* no image - give default label */
  219.       XtVaSetValues(IDdata->shell, XmNtitle, "XFITSview", NULL);
  220. /* hide display */
  221.       if (XtIsRealized (IDdata->canvas)) XtUnmapWidget (IDdata->canvas);
  222.       return;}
  223.  
  224. /*                    maximum display size */
  225.      XtVaGetValues (IDdata->display,
  226.             XmNwidth, &cwid,
  227.             XmNheight, &chei,
  228.             NULL);
  229. /*     cwid = cwid - CONTROLWIDTH;  leave room for control panel */
  230.      IDdata->disp_wid = cwid;
  231.      IDdata->disp_hei = chei;
  232.  
  233.      iZoom = IDdata->zoom; /* for convinence */
  234.  
  235. /*         display should be an integral multiple of image pixels */
  236.      if (iZoom>1)
  237.         {IDdata->disp_wid =
  238.             ((IDdata->disp_wid/iZoom)*iZoom);
  239.          IDdata->disp_hei =
  240.             ((IDdata->disp_hei/iZoom)*iZoom);}
  241. /*                    zoomed image size */
  242.      inXZoom = image[CurImag].iImageNx;
  243.      if (iZoom>1) inXZoom =  inXZoom * iZoom;
  244.      if (iZoom<0) inXZoom = -inXZoom / iZoom;
  245.      inYZoom = image[CurImag].iImageNy;
  246.      if (iZoom>1) inYZoom =  inYZoom * iZoom;
  247.      if (iZoom<0) inYZoom = -inYZoom / iZoom;
  248. /*                     scroll bar size */
  249.      iScrWid = sbar_width;
  250.      iScrHei = sbar_width;
  251. /*                      scroll bars needed? (iterate to get it right) */
  252.      if ((IDdata->disp_wid-iScrWid)>=inXZoom) iScrHei = 0;
  253.      if ((IDdata->disp_hei-iScrHei)>=inYZoom) iScrWid = 0;
  254.      if ((IDdata->disp_wid-iScrWid)>=inXZoom) iScrHei = 0;
  255.      if ((IDdata->disp_hei-iScrHei)>=inYZoom) iScrWid = 0;
  256.      if (image[CurImag].valid) /* something in display? */
  257.               /* Display needn't be larger than display+scrollbars */
  258.               /* This sets the image size for no & negative zooms */
  259.        {IDdata->disp_wid=min(IDdata->disp_wid, inXZoom+iScrWid);
  260.         IDdata->disp_hei=min(IDdata->disp_hei,inYZoom+iScrHei);}
  261. /*                      correct for size of scroll bars */
  262.      IDdata->disp_wid -= iScrWid; 
  263.      if (IDdata->disp_wid<0) IDdata->disp_wid = iScrWid;
  264.      IDdata->disp_hei -= iScrHei; 
  265.      if (IDdata->disp_hei<0) IDdata->disp_hei = iScrHei;
  266. /*   Display may still be too big */
  267.      if (image[CurImag].valid) /* something in display? */
  268.        {IDdata->disp_wid = min (IDdata->disp_wid, inXZoom);
  269.         IDdata->disp_hei = min (IDdata->disp_hei, inYZoom);}
  270.      else
  271.        {IDdata->disp_wid += iScrWid;  /* no scroll bars if no image */
  272.         IDdata->disp_hei += iScrHei;} 
  273. /* leave at least the width of the scroll bars (SBAR_WIDTH) around the edge */
  274.      IDdata->disp_wid = min (IDdata->disp_wid, (int)cwid-sbar_width);
  275.      IDdata->disp_hei = min (IDdata->disp_hei, (int)chei-sbar_width);
  276. /*                    display should have an even number  of rows */
  277. /*     IDdata->disp_hei = 2 * ((IDdata->disp_hei+1)/2); */
  278.  
  279. /* resize window */
  280.      if (XtIsRealized (IDdata->canvas)) XtMapWidget (IDdata->canvas);
  281.      XtResizeWidget(IDdata->canvas, 
  282.             (Dimension)IDdata->disp_wid,
  283.             (Dimension)IDdata->disp_hei, 
  284.             (Dimension)0);
  285.  
  286. /*                      Half Size of display in image pixels */
  287.      iXHalf = IDdata->disp_wid/2;
  288.      if (iZoom>1) iXHalf =  iXHalf / iZoom;
  289.      if (iZoom<0) iXHalf = -iXHalf * iZoom;
  290.      iYHalf = IDdata->disp_hei/2;
  291.      if (iZoom>1) iYHalf =  iYHalf / iZoom;
  292.      if (iZoom<0) iYHalf = -iYHalf * iZoom;
  293.      iXHalf = min (iXHalf, image[CurImag].iImageNx/2);
  294.      iYHalf = min (iYHalf, image[CurImag].iImageNy/2);
  295.  
  296. /* setup and center scroll */
  297. /*     IDdata->scrollx = image[CurImag].iImageNx / 2; */
  298. /*     IDdata->scrolly = image[CurImag].iImageNy / 2; */
  299.      IDdata->hscr_max = image[CurImag].iImageNx-2*iXHalf;
  300.      IDdata->hscr_min = 1;
  301.      if (IDdata->hscr_max<=IDdata->hscr_min) 
  302.        IDdata->hscr_max = IDdata->hscr_min + 1;
  303.      IDdata->hscr_half = iXHalf;
  304.      value = IDdata->scrollx - iXHalf;
  305.      slider_size = 2 * iXHalf;
  306.      increment = iXHalf / 5; if (increment<1) increment = 1;
  307.      page_increment = 3 * iXHalf / 2; if (page_increment<1) page_increment = 1;
  308.      if (value>IDdata->hscr_max) value = IDdata->hscr_max;
  309.      if (value<IDdata->hscr_min) value = IDdata->hscr_min;
  310.      if (iScrHei)
  311.        {
  312.          /* keep X-Windows from blowing it's tiny mind */
  313.          XmScrollBarSetValues (IDdata->hscroll, 1, 1, 1, 1, False);
  314.      XtVaSetValues(IDdata->hscroll, 
  315.              XmNheight,    iScrHei,
  316.              XmNvalue,     value,
  317.              XmNmaximum,   (Dimension)(IDdata->hscr_max+2*iXHalf),
  318.              XmNminimum,   (Dimension)(IDdata->hscr_min),
  319.              NULL);
  320.     XmScrollBarSetValues (IDdata->hscroll, value, slider_size, increment, 
  321.                   page_increment, False);}
  322.      IDdata->vscr_max = image[CurImag].iImageNy-2*iYHalf;
  323.      IDdata->vscr_min = 1;
  324.      if (IDdata->vscr_max<=IDdata->vscr_min) 
  325.        IDdata->vscr_max = IDdata->vscr_min + 1;
  326.      IDdata->vscr_half = iYHalf;
  327.      value = IDdata->scrolly - iYHalf;
  328.      slider_size = 2 * iYHalf;
  329.      increment = iYHalf / 5; if (increment<1) increment = 1;
  330.      page_increment = 3 * iYHalf / 2; if (page_increment<1) page_increment = 1;
  331.      if (value>IDdata->vscr_max) value = IDdata->vscr_max;
  332.      if (value<IDdata->vscr_min) value = IDdata->vscr_min;
  333.      if (iScrWid)
  334.        {
  335.          /* keep X-Windows from blowing it's tiny mind */
  336.          XmScrollBarSetValues (IDdata->vscroll, 1, 1, 1, 1, False);
  337.      XtVaSetValues(IDdata->vscroll, 
  338.              XmNwidth,     iScrWid,
  339.              XmNvalue,     value,
  340.              XmNmaximum,   (Dimension)(IDdata->vscr_max+2*iYHalf),
  341.              XmNminimum,   (Dimension)(IDdata->vscr_min),
  342.              NULL);
  343.     XmScrollBarSetValues (IDdata->vscroll, value, slider_size, increment, 
  344.                   page_increment, False);}
  345.  
  346. /*     make horizonal scroll bar visible or invisible as necessary */
  347. /*  iScrHei = 0 => no horizontal scroll */
  348.      if (iScrHei) /* visible */
  349.        {XtMapWidget (IDdata->hscroll);
  350.     IDdata->hscr_vis = 1;}
  351.      else /* invisible */
  352.        {XtUnmapWidget (IDdata->hscroll);
  353.     IDdata->hscr_vis = 0;}
  354.  
  355. /*     make vertical scroll bar visible or invisible as necessary */
  356. /*  iScrWid = 0 => no vertical scroll */
  357.      if (iScrWid) /* visible */
  358.        {XtMapWidget (IDdata->vscroll);
  359.     IDdata->vscr_vis = 1;}
  360.      else /* invisible */
  361.        {XtUnmapWidget (IDdata->vscroll);
  362.     IDdata->vscr_vis = 0;}
  363.  
  364. /* make work ZPixmap for zooming display */
  365.      if (iZoom!=1) 
  366.        {
  367. /* delete old if necessary*/
  368.      unx = IDdata->disp_wid;
  369.      uny = IDdata->disp_hei;
  370.      if ( !IDdata->work || 
  371.          (unx>IDdata->work->width) || (uny>IDdata->work->height)) 
  372.        {
  373.          if (IDdata->work) 
  374.            {if (IDdata->work->data) XtFree(IDdata->work->data);
  375.         XtFree((XtPointer)IDdata->work);}
  376.  
  377. /* create new pix map */
  378.          pasize = unx * uny * ((IDdata->depth+1)/8);
  379.          ZP = (char*) XtMalloc (pasize);
  380.          IDdata->work = 
  381.            XCreateImage (dpy, 
  382.                  DefaultVisual(dpy, DefaultScreen(dpy)), 
  383.                  IDdata->depth, ZPixmap, 0, 
  384.                  ZP, unx, uny, 8, 0); 
  385. /* blank it out */
  386.          for (ilong=0; ilong<pasize; ilong++) 
  387.            IDdata->work->data[ilong] = 0;
  388.   
  389.        }} /* end of create new ZPixmap */
  390.  
  391. } /* end SetDisplay */
  392.  
  393. void PaintImage (ImageDisplay* IDdata)
  394. /* redraw the image on the canvas computing zoom and scroll */
  395. {
  396.   int nXDIB, nYDIB, iZoom, iSrcWid, iSrcHei, iXHalf, iYHalf, K;
  397.   int iXSize, iYSize, iXPos, iYPos, iXPage, iYPage;
  398.   Dimension cWidth, cHeight;
  399.   int i, ch1;
  400.   char TitleString[500], *cptr;
  401.  
  402. /* blank if there's no image yet */
  403.      if (!IDdata) return; /* this shouldn't happen */
  404.      if (!image[CurImag].valid) {
  405.        if (XtIsRealized (IDdata->canvas)) 
  406.      XClearArea (XtDisplay (IDdata->canvas), XtWindow (IDdata->canvas), 
  407.              0, 0, 0, 0, TRUE);
  408.      }
  409.      if (!image[CurImag].pixarray) return;
  410.  
  411. /* reset window title to file name */
  412.   if (image[CurImag].valid) { /* title for image only */
  413.     cptr = image[CurImag].FileName->sp;
  414.     ch1 = 0;
  415.     for (i=0; i<image[CurImag].FileName->length;i++)
  416.       if (cptr[i]=='/') ch1 = i+1;
  417.     if (image[CurImag].iNumPlanes>1)
  418.       {sprintf (TitleString,"%s, plane %d",
  419.         &cptr[ch1],
  420.         image[CurImag].PlaneNo+1);}
  421.     else /* one plane */
  422.       {sprintf (TitleString,"%s", &cptr[ch1]);}
  423.     XtVaSetValues(IDdata->shell, 
  424.           XmNtitle,   TitleString,
  425.           NULL);
  426.   } /* end of label */
  427.  
  428.   cWidth = IDdata->disp_wid;   /* current display size */
  429.   cHeight = IDdata->disp_hei;
  430.  
  431.   nXDIB = image[CurImag].iImageNx;
  432.   nYDIB = image[CurImag].iImageNy;
  433.   iZoom = IDdata->zoom;
  434.   if (iZoom == 0) iZoom = 1;
  435.   /* size of display in image pixels */
  436.   iXHalf = IDdata->disp_wid;  /* divide by two later */
  437.   if (iZoom>1) iXHalf =  iXHalf / iZoom;
  438.   if (iZoom<0) iXHalf = -iXHalf * iZoom;
  439.   iYHalf = IDdata->disp_hei; /* divide by two later */
  440.   if (iZoom>1) iYHalf =  iYHalf / iZoom;
  441.   if (iZoom<0) iYHalf = -iYHalf * iZoom;
  442.   iXHalf = min (iXHalf, nXDIB);
  443.   iYHalf = min (iYHalf, nYDIB);
  444.   iSrcWid = iXHalf;
  445.   iSrcHei = iYHalf;
  446.   iXHalf = iXHalf / 2;
  447.   iYHalf = iYHalf / 2;
  448.   /* Size of display area */
  449.   iXSize = IDdata->disp_wid;
  450.   iYSize = IDdata->disp_hei;
  451.   iXSize = min (iXSize, nXDIB);
  452.   iYSize = min (iYSize, nYDIB);
  453.   if (iZoom>1) {iYSize=iYSize*iZoom; iXSize=iXSize*iZoom;}
  454.  
  455. /*  for negative zooms, iDisp* is set in SetDisplay */
  456.   iXSize = min (iXSize, (int)cWidth);
  457.   iYSize = min (iYSize, (int)cHeight);
  458.   iXSize = max (iXSize, 1);
  459.   iYSize = max (iYSize, 1);
  460.   /* "page" size for scrolling */
  461.   iXPage = iSrcWid;
  462.   iYPage = iSrcHei;
  463.   iXPos = IDdata->scrollx - iXHalf;
  464.   iYPos = IDdata->scrolly - iYHalf;
  465.   iXPos = max (iXPos, 0);
  466.   iYPos = max (iYPos, 0);
  467.   iXPos = min (iXPos, image[CurImag].iImageNx-iXHalf*2);
  468.   iYPos = min (iYPos, image[CurImag].iImageNy-iYHalf*2);
  469.   IDdata->iXCorn = iXPos;
  470.   IDdata->iYCorn = iYPos;
  471.  
  472. /* copy Pixarray to display */
  473.   ZoomDisplay (IDdata, iXSize, iYSize, iXPos, iYPos, iSrcWid, iSrcHei);
  474.  
  475. } /* end PaintImage */
  476.  
  477. void hscrollCB (Widget w, XtPointer clientData, XtPointer callData)
  478. /* call back for motion in horizonal scroll */
  479. {
  480.     ImageDisplay *IDdata = (ImageDisplay *)clientData;
  481.     XmScrollBarCallbackStruct *call_data = 
  482.       (XmScrollBarCallbackStruct *) callData;
  483.  
  484. /* read value of scrollbar */
  485.     IDdata->scrollx = call_data->value+IDdata->hscr_half;
  486.     PaintImage((ImageDisplay*)clientData); /* redraw */
  487. } /* end hscrollCB */
  488.  
  489. void vscrollCB (Widget w, XtPointer clientData, XtPointer callData)
  490. /* call back for motion in vertical scroll */
  491. {
  492.     ImageDisplay *IDdata = (ImageDisplay *)clientData;
  493.     XmScrollBarCallbackStruct *call_data = 
  494.       (XmScrollBarCallbackStruct *) callData;
  495. /* read value of scrollbar */
  496.     IDdata->scrolly = call_data->value+IDdata->vscr_half;
  497. /* reset scroll position and redraw */
  498.   PaintImage((ImageDisplay*)clientData);
  499. } /* end vscrollCB */
  500.  
  501. void   ImageRedispCB (Widget w, XtPointer clientData, XtPointer callData)
  502. /* redisplay image canvas */
  503. {
  504.   ImageDisplay *IDdata = (ImageDisplay *)clientData;
  505.   XmDrawingAreaCallbackStruct *cb = (XmDrawingAreaCallbackStruct *)callData;
  506.   XExposeEvent  *event = (XExposeEvent *) cb->event;
  507.  
  508. /* NOP unless widget is canvas */
  509.     if (!IDdata) return;
  510.     if (!IDdata->canvas) return;
  511.     if (w!=IDdata->canvas) return;
  512.  
  513.   /*fprintf (stderr,"RedispCB: x %d, y %d, nx %d, ny %d, count %d\n",
  514.      event->x, event->y, event->width, event->height, event->count);*/
  515.  
  516. /* return if there are more expose events in the queue */
  517.     if (event->count) return;
  518.  
  519. /* reset display */
  520.     SetDisplay(IDdata);
  521. /* redraw exposed area from ImageData */
  522.     PaintImage (IDdata);
  523.   } /* end of ImageRedispCB */
  524.  
  525. void   ImageResizeCB (Widget w, XtPointer clientData, XtPointer callData)
  526. /* resize image canvas */
  527. {
  528.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  529.  
  530.     if (!IDdata) return;
  531.     if (!IDdata->canvas) return;
  532.  
  533. /*fprintf(stderr,"ImageResizeCB: window resized\n "); debug */
  534.  
  535. /* reset display */
  536.      ResetDisplay(IDdata);
  537. /* redraw exposed area from ImageData */
  538. /*    PaintImage (IDdata); */
  539.   } /* end of ImageResizeCB */
  540.  
  541. /* event handlers */
  542. void ButtonEH (Widget w, XtPointer data, XEvent *event)
  543. /* event handler for button press in image display window */
  544. {
  545.   int          ix, iy, isOK;
  546.   float        fx, fy, z;
  547.   ImageDisplay *IDdata = (ImageDisplay*)data;
  548.  
  549. if (!IDdata) return;
  550. if (!image[CurImag].valid) return;
  551.  
  552. /* determine image pixel */
  553.   fx = (float)event->xbutton.x;
  554.   fy = (float)event->xbutton.y;
  555.   z = IDdata->zoom;
  556.   if (z>1)  /* zoomed? Take care of sub pixel precision*/
  557.     {fx = (fx - (z*0.5) + 0.5) / z;
  558.      fy = (fy - (z*0.5) + 0.5) / z;}
  559.   if (z<0) 
  560.     {fx = -fx * z; fy = -fy * z; }
  561.   fx = fx + IDdata->iXCorn;
  562.   fy = image[CurImag].iImageNy - (fy + IDdata->iYCorn) - 1.0;
  563.   ix = (int)(fx+0.5); iy = (int)(fy+0.5);
  564.   IDdata->showInfo = 1; /* have something to show */
  565.   if (event->xbutton.button==1) /* left button - display pixel value*/
  566.     { image[CurImag].fXpixel = fx;
  567.       image[CurImag].fYpixel = fy;
  568.       image[CurImag].iXPixel = ix;
  569.       image[CurImag].iYPixel = iy;
  570.       image[CurImag].iFitted = 0; 
  571.       UpdateInfo(IDdata);  /* write info in control info area*/
  572.       isOK = 1;
  573.     } /* end Left button */
  574.  
  575.   if (event->xbutton.button==3) /* right button - fit position */
  576.     { image[CurImag].iXPixel = ix;
  577.       image[CurImag].iYPixel = iy;
  578.       image[CurImag].iFitted = FitPos(IDdata);
  579.       UpdateInfo(IDdata);  /* write info in control info area*/
  580.       isOK = image[CurImag].iFitted==1;
  581.     } /* end Right button */
  582.   if (doLog &&  isOK) DoLogger(); /* log if necessary */
  583. } /* end ButtonEH */
  584.  
  585. ImageDisplay* MakeDisplay (Widget parent, Widget shell)
  586. /* Make image display widget */
  587. {
  588.   Widget        display;   /* return display widget */
  589.   ImageDisplay *IDdata;     /* display data structure */
  590.   int           i;
  591.   Dimension     cwid, chei;
  592.   int           sbar_width = SBAR_WIDTH;
  593.   
  594.   IDdata = (ImageDisplay*) XtMalloc (sizeof (ImageDisplay));
  595.  
  596. /* set size */
  597. /*                    maximum display size */
  598.   XtVaGetValues (parent,
  599.          XmNwidth, &cwid,
  600.          XmNheight, &chei,
  601.          NULL);
  602.   cwid = cwid - CONTROLWIDTH; /* leave room for control panel */
  603. /*  chei = chei - 40; */
  604.  
  605.   IDdata->disp_wid = cwid;
  606.   IDdata->disp_hei = chei;
  607.  
  608. /* save main window */
  609.   IDdata->parent = parent;
  610.  
  611. /* set top level form */
  612.   IDdata->shell = shell;
  613.  
  614. /* make Form widget for display */
  615.   IDdata->display = XtVaCreateManagedWidget ("display", xmFormWidgetClass,
  616.                      parent,
  617. /* add extra pixels for scroll bars */
  618.                      XmNwidth,     IDdata->disp_wid+sbar_width,
  619.                      XmNheight,    IDdata->disp_hei+sbar_width,
  620.                       XmNtopAttachment,  XmATTACH_FORM,
  621.                      XmNrightAttachment,  XmATTACH_FORM,
  622.                      NULL);
  623.  
  624. /* drawing canvas */
  625.   IDdata->canvas = 
  626.     XtVaCreateManagedWidget ("canvas", xmDrawingAreaWidgetClass, 
  627.                  IDdata->display, 
  628. /*                 XmNwidth,     IDdata->disp_wid-sbar_width,
  629.                  XmNheight,    IDdata->disp_hei-sbar_width,*/
  630.                  XmNwidth,     1,
  631.                  XmNheight,    1,
  632.                  XmNtopAttachment,  XmATTACH_FORM,
  633.                  XmNleftAttachment,  XmATTACH_FORM,
  634.                  NULL);
  635. /*   Add callbacks to handle resize and exposures.  */
  636.   XtAddCallback (IDdata->canvas, XmNexposeCallback, ImageRedispCB, 
  637.          (XtPointer)IDdata);
  638.  
  639. /* trap button press */
  640.   XtAddEventHandler (IDdata->canvas, ButtonPressMask, FALSE, 
  641.              (XtEventHandler)ButtonEH, 
  642.              (XtPointer)IDdata);
  643.  
  644. /* add horizonal scroll bar ("scale" in X-Windows) */
  645.  
  646.   IDdata->hscroll = 
  647.     XtVaCreateManagedWidget ("hscroll", xmScrollBarWidgetClass, 
  648.                        IDdata->display,
  649.                        XmNwidth,     IDdata->disp_wid,
  650.                        XmNheight,     sbar_width,
  651.                             XmNmaximum,   IDdata->disp_wid,
  652.                        XmNminimum,            1,
  653.                             XmNvalue,              1,
  654.                        XmNshowValue,       False,
  655.                        XmNorientation, XmHORIZONTAL,
  656.                        XmNprocessingDirection, XmMAX_ON_RIGHT,
  657. /*                       XmNtopAttachment, XmATTACH_WIDGET,
  658.                        XmNtopWidget,     IDdata->canvas,*/
  659.                        XmNbottomAttachment, XmATTACH_FORM,
  660.                        XmNleftAttachment,  XmATTACH_FORM,
  661.                        XmNrightAttachment,  XmATTACH_FORM,
  662.                           XmNrightOffset,     sbar_width,
  663.                        NULL);
  664.   IDdata->hscr_vis = 1;  /* it's visible */
  665. /* add call backs */
  666.   XtAddCallback(IDdata->hscroll, XmNvalueChangedCallback, hscrollCB, 
  667.         (XtPointer) IDdata);
  668. /*  XtAddCallback(IDdata->hscroll, XmNdragCallback, hscrollCB, 
  669.         (XtPointer) IDdata); */
  670.  
  671. /* add vertical scroll bar */
  672.  
  673.   IDdata->vscroll = 
  674.     XtVaCreateManagedWidget ("vscroll", xmScrollBarWidgetClass, 
  675.                        IDdata->display,
  676.                        XmNheight,     IDdata->disp_hei,
  677.                        XmNwidth,          sbar_width,
  678.                             XmNmaximum,   IDdata->disp_hei,
  679.                        XmNminimum,            1,
  680.                             XmNvalue,              1,
  681.                        XmNshowValue,       False,
  682.                        XmNorientation, XmVERTICAL,
  683.                        XmNprocessingDirection, XmMAX_ON_BOTTOM,
  684.                           XmNtopAttachment,  XmATTACH_FORM,
  685.                           XmNbottomAttachment,  XmATTACH_FORM,
  686.                           XmNbottomOffset,     sbar_width,
  687.                           XmNrightAttachment,  XmATTACH_FORM,
  688. /*                       XmNleftAttachment, XmATTACH_WIDGET,
  689.                        XmNleftWidget,   IDdata->canvas,*/
  690.                        NULL);
  691.   IDdata->vscr_vis = 1;  /* it's visible */
  692. /* add call back */
  693.   XtAddCallback(IDdata->vscroll, XmNvalueChangedCallback, vscrollCB, 
  694.         (XtPointer) IDdata);
  695. /*  XtAddCallback(IDdata->vscroll, XmNdragCallback, vscrollCB, 
  696.         (XtPointer) */
  697.  
  698. /* make dummy widget the size of the display which can detect when 
  699.    it's size has changed */
  700.   IDdata->goober = 
  701.     XtVaCreateManagedWidget ("goober", xmDrawingAreaWidgetClass, 
  702.                  IDdata->display, 
  703.                  XmNtopAttachment,  XmATTACH_FORM,
  704.                  XmNleftAttachment,  XmATTACH_FORM,
  705.                  XmNbottomAttachment,  XmATTACH_FORM,
  706.                  XmNrightAttachment,  XmATTACH_FORM,
  707.                  NULL);
  708. /* go boom  XtUnmapWidget (IDdata->goober);  make invisible */
  709.   XtAddCallback (IDdata->goober, XmNresizeCallback, ImageResizeCB,
  710.          (XtPointer)IDdata);
  711. /* number of colors */
  712.   IDdata->ncolors = XDisplayCells (XtDisplay (IDdata->display), 
  713.                  XDefaultScreen (XtDisplay (IDdata->display)));
  714.   if (IDdata->ncolors>MAXCOLOR) IDdata->ncolors = MAXCOLOR;
  715.   for (i=0; i<MAXCOLOR; i++) 
  716.     {IDdata->colut[i]=0;
  717.      IDdata->red[i]=0;
  718.      IDdata->green[i]=0;
  719.      IDdata->blue[i]=0;}
  720.  
  721. /* bit planes in display */
  722.   IDdata->depth = XDisplayPlanes (XtDisplay (IDdata->display), 
  723.                  XDefaultScreen (XtDisplay (IDdata->display)));
  724. /* context */
  725.   IDdata->gc = XCreateGC (XtDisplay (IDdata->display), 
  726.               DefaultRootWindow (XtDisplay(IDdata->display)),
  727.               0, NULL );
  728. /* init image */
  729.   IDdata->work = NULL;
  730.   IDdata->zoom = 1;
  731.   IDdata->scrollx = 0;
  732.   IDdata->scrolly = 0;
  733.   IDdata->iXCorn = 0;
  734.   IDdata->iYCorn = 0;
  735. /* no color map yet */
  736.   IDdata->cmap = 0;
  737.  
  738. /* no slider controls yet */
  739.   IDdata->BriScroll = NULL;
  740.   IDdata->ConScroll = NULL;
  741.   IDdata->value[0] = 0;
  742.   IDdata->value[1] = 0;
  743.   IDdata->Info1 = NULL;
  744.   IDdata->Info2 = NULL;
  745.   IDdata->Info3 = NULL;
  746.   IDdata->Info4 = NULL;
  747.   IDdata->Info5 = NULL;
  748.   IDdata->Info6 = NULL;
  749.   IDdata->Info7 = NULL;
  750.   IDdata->showInfo = 0;
  751.  
  752. /* return Image display structure */
  753.   return IDdata;
  754.  
  755. } /* end MakeDisplay */
  756.  
  757. void FitPosCB (Widget w, XtPointer clientData, XtPointer callData)
  758. /* menu callback routine to fit position */
  759. {
  760.   int          isOK;
  761.   ImageDisplay *IDdata = (ImageDisplay *)clientData;
  762.  
  763. /* use last position selected */
  764.   image[CurImag].iFitted = FitPos(IDdata);
  765.   UpdateInfo(IDdata);  /* write info in control info area*/
  766.   isOK = image[CurImag].iFitted==1;
  767.   if (doLog &&  isOK) DoLogger(); /* log if necessary */
  768.   FitPos(IDdata);
  769. } /* End FitPosCB */
  770.  
  771. int FitPos(ImageDisplay *IDdata)
  772. /* routine to fit a point near the position of the cursor: */
  773. /* IDdata->iXPixel, iYPixel */
  774. /* Sets Dis[iDs] values fXpixel, fYpixel, fBpixel */
  775. /* returns 1 if worked otherwise 0, -1 => fit failed. */
  776. { int iXcen, iYcen, iX, iY, iXp, iYp;
  777.   float data[9][9], fblank;
  778.   Logical valid;
  779.   Integer error, pos[7] = {0, 0, 0, 0, 0, 0, 0}, ndim;
  780.   MatrixPos *impos;
  781.   float s, dx[2];
  782.   Display *dpy = XtDisplay(IDdata->canvas);
  783.  
  784.   ndim=image[CurImag].ndim;
  785.   iXcen = image[CurImag].iXPixel;
  786.   iYcen = image[CurImag].iYPixel;
  787.   fblank = MagicBlank();
  788. /* default return values */
  789.   image[CurImag].fBpixel = 0.;
  790.   image[CurImag].fXpixel = 0.;
  791.   image[CurImag].fYpixel = 0.;
  792.  
  793. /* make matrix pos */
  794.   impos = MakeMatrixPos(ndim, pos);
  795.  
  796.   if (!image[CurImag].valid) return 0;
  797.  
  798. /* use 9x9 values around center */
  799.   impos->pos[2] = image[CurImag].PlaneNo;
  800.   WorkingCursor(True, False, NULL); /* indicate working */
  801.   for (iY=0; iY<9; iY++) {
  802.     iYp = iYcen + iY - 4;
  803.     impos->pos[1] = iYp;
  804.     for (iX=0; iX<9; iX++) {
  805.       iXp = iXcen + iX - 4;
  806.       impos->pos[0] = iXp;
  807. /* check validity */
  808.       valid = IsValid(image[CurImag].Image->matx, impos);
  809.       if (valid)
  810. /* read pixel values */
  811.     {data[iY][iX] = MatrixGetPixel(image[CurImag].Image->matx, impos);
  812.      error = image[CurImag].Image->matx->fw->error;
  813.      if (error)   /* I/O error */
  814.        {MessageShow("FitPos: error reading pixel value");
  815.         KillMatrixPos(impos);
  816.         IDdata->showInfo= 0; /* file no longer available? */
  817.         image[CurImag].valid = 0; /* mark as invalid */
  818.         return 0;}/* failed */
  819.        }
  820.       else  /* blank */
  821.     data [iY][iX] = fblank;
  822.     }
  823.   }  /*  end of loop loading image data in array */
  824.   WorkingCursor(False, False, NULL); /* reset cursor */
  825.   KillMatrixPos(impos);
  826.   if (pfit (data, &s, dx, fblank))
  827.     {/*fprintf (stderr, "fit failed\n");*/
  828.      XBell(dpy, 50); 
  829.      return -1;}  /* fit failed*/
  830.   image[CurImag].fBpixel = s;
  831.   image[CurImag].fXpixel = (float)iXcen + dx[0];
  832.   image[CurImag].fYpixel = (float)iYcen + dx[1];
  833.   return 1;
  834. } /* end fit pos */
  835.  
  836. void UpdateInfo (ImageDisplay *IDdata)
  837. /* update information about selected pixel in control window */
  838. {
  839.   Integer      ndim;
  840.   int          i, posOK;
  841.   XmString     wierdstring = NULL;
  842.   char         jerkstring[100];
  843.   Arg          wargs[5]; 
  844.   float        fblank, val, pix[7];
  845.   char         axtype[3][9], label[3][20];
  846.   double       pos[3];
  847.   Logical      valid;
  848.   Integer error, ipos[7] = {0, 0, 0, 0, 0, 0, 0};
  849.   MatrixPos    *impos=NULL;
  850.   Display *dpy = XtDisplay(IDdata->display);
  851.   static Cursor cursor=(Cursor)NULL;
  852.   extern Widget shell;
  853.   XSetWindowAttributes attrs;
  854.  
  855.   /* check that info defined for current image */
  856.   if ((!image[CurImag].Image) || (!image[CurImag].Image->descript)) 
  857.     IDdata->showInfo = 0;
  858.  
  859. /* need to blank display? */
  860.   if (!IDdata->showInfo)
  861.     {
  862.       wierdstring = XmStringCreateSimple ("    ");
  863.       XtSetArg (wargs[0], XmNlabelString, wierdstring);
  864.       XtSetValues (IDdata->Info1, wargs, 1);
  865.       XtSetValues (IDdata->Info2, wargs, 1);
  866.       XtSetValues (IDdata->Info3, wargs, 1);
  867.       XtSetValues (IDdata->Info4, wargs, 1);
  868.       XtSetValues (IDdata->Info5, wargs, 1);
  869.       XtSetValues (IDdata->Info6, wargs, 1);
  870.       XtSetValues (IDdata->Info7, wargs, 1);
  871.       if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  872.       return;
  873.     } /* end blank info area */
  874. /* return OK if no valid image */
  875.   if (!image[CurImag].valid) return;
  876.   ndim = image[CurImag].ndim;  /* Number of dimensions */
  877. /* make sure hourglass cursor initialized */
  878.   if (!cursor) cursor = XCreateFontCursor(dpy, XC_watch);
  879. /*  fitted or current */
  880.   if (ndim>2)
  881.     sprintf (jerkstring, "(%7.2f,%7.2f, %d)",
  882.          image[CurImag].fXpixel+1.0, image[CurImag].fYpixel+1.0,
  883.          image[CurImag].PlaneNo+1);
  884.   else
  885.     sprintf (jerkstring, "(%7.2f,%7.2f)",
  886.          image[CurImag].fXpixel+1.0, image[CurImag].fYpixel+1.0);
  887.   wierdstring = XmStringCreateSimple (jerkstring);
  888.   XtSetArg (wargs[0], XmNlabelString, wierdstring);
  889.   XtSetValues (IDdata->Info1, wargs, 1);
  890.   if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  891.  
  892. /*  get flux */
  893.   fblank = MagicBlank();
  894. /*  fitted or current? */
  895.   if (image[CurImag].iFitted>0) /* fitted values */
  896.     {valid = 1;
  897.      if (image[CurImag].fBpixel==fblank)
  898.        /* blanked */
  899.        sprintf (jerkstring, "pixel blanked");
  900.      else
  901.        sprintf (jerkstring, "value=%f", image[CurImag].fBpixel);}
  902.   else  /* current position */
  903.     {val = 0;
  904.      for (i=3; i<7; i++) ipos[i] = 0;
  905. /* Note: Image class pixel numbers are 0 rel; geometry is 1 rel. */
  906.      ipos[0] = image[CurImag].iXPixel; ipos[1] = image[CurImag].iYPixel;
  907.      ipos[2] = image[CurImag].PlaneNo;
  908. /* make Matrix */
  909.      impos = MakeMatrixPos(ndim, ipos);
  910.      valid = (ndim>1) && IsValid(image[CurImag].Image->matx, impos);
  911.      if (valid)
  912. /* get pixel value */
  913.        {
  914.     WorkingCursor(True, False, NULL); /* indicate working */
  915.     val = MatrixGetPixel(image[CurImag].Image->matx, impos);
  916.     WorkingCursor(False, False, NULL); /* reset cursor */
  917.     error = image[CurImag].Image->matx->fw->error;
  918.     if (error)   /* I/O error */
  919.       {MessageShow("UpdateInfo: Error reading pixel value");
  920.        IDdata->showInfo= 0; /* file no longer available? */
  921.        image[CurImag].valid = 0; /* mark as invalid */
  922.        val = fblank;}
  923.     if (val==fblank)
  924.       /* blanked */
  925.       sprintf (jerkstring, "pixel blanked");
  926.     else
  927.       sprintf (jerkstring, "value=%f", val);
  928.       }
  929.    }
  930.   KillMatrixPos(impos);
  931.   if (!valid) sprintf (jerkstring, "invalid pixel");
  932. /* write second line (flux density) */
  933.   jerkstring[16] = 0; /* limit size of string */
  934.   wierdstring = XmStringCreateSimple (jerkstring);
  935.   XtSetArg (wargs[0], XmNlabelString, wierdstring);
  936.   XtSetValues (IDdata->Info2, wargs, 1);
  937.   if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  938.  
  939. /* celestial position */
  940. /* equinox is line 3 */
  941.   if ((usr_equinox>0.0) && (image[CurImag].Image->descript->equinox>0.0))
  942.     sprintf(jerkstring,"Equinox %6.1f", usr_equinox);
  943.   else if (image[CurImag].Image->descript->equinox>0.0)
  944.     sprintf(jerkstring,"Equinox %6.1f", image[CurImag].Image->descript->equinox);
  945.   else
  946.     sprintf(jerkstring,"Equinox unknown");
  947.   wierdstring = XmStringCreateSimple (jerkstring);
  948.   XtSetArg (wargs[0], XmNlabelString, wierdstring);
  949.   XtSetValues (IDdata->Info3, wargs, 1);
  950.   if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  951.  
  952.  
  953. /*  Get position */
  954.   pix[0] = image[CurImag].fXpixel+1.0; 
  955.   pix[1] = image[CurImag].fYpixel+1.0;
  956.   pix[2] = (float)image[CurImag].PlaneNo+1.0;
  957.   if (valid)
  958.     {strncpy(axtype[0], image[CurImag].cname[0]->sp, 8);
  959.      strncpy(axtype[1], image[CurImag].cname[1]->sp, 8);
  960.      strncpy(axtype[2], image[CurImag].cname[2]->sp, 8);
  961.      axtype[0][8] = 0; axtype[1][8] = 0; axtype[2][8] = 0;
  962.      posOK = !get_wpos(image[CurImag].Image->descript, pix, pos);
  963.      AxisLabel(pos[0], axtype[0], label[0]);  /* human readable */
  964.      if (ndim>=2) AxisLabel(pos[1], axtype[1], label[1]);
  965.      if (ndim>=3) AxisLabel(pos[2], axtype[2], label[2]);
  966.      if (posOK) {  /* valid position */
  967. /* write fourth line (first axis) */
  968.        wierdstring = 
  969.      XmStringCreateSimple (label[0]);
  970.        XtSetArg (wargs[0], XmNlabelString, wierdstring);
  971.        XtSetValues (IDdata->Info4, wargs, 1);
  972.        if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  973.        
  974. /* write fifth line (second axis) */
  975.        if (ndim>=2) 
  976.      {wierdstring = 
  977.         XmStringCreateSimple (label[1]);
  978.       XtSetArg (wargs[0], XmNlabelString, wierdstring);
  979.       XtSetValues (IDdata->Info5, wargs, 1);
  980.       if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;}
  981.  
  982. /* write sixth line (third axis) */
  983.        if (ndim>=3) 
  984.      {wierdstring = 
  985.         XmStringCreateSimple (label[2]);
  986.       XtSetArg (wargs[0], XmNlabelString, wierdstring);
  987.       XtSetValues (IDdata->Info6, wargs, 1);
  988.       if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;}
  989.      }}
  990.   else {  /* invalid position */
  991.     sprintf (jerkstring, "invalid pixel");
  992. /* write third line (invalid pixel message) */
  993.     wierdstring = 
  994.       XmStringCreateSimple (jerkstring);
  995.     XtSetArg (wargs[0], XmNlabelString, wierdstring);
  996.     XtSetValues (IDdata->Info3, wargs, 1);
  997.     if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  998.   }  /* end of give position on invalid */
  999. /*  fitted or current? */
  1000.   if (image[CurImag].iFitted>0) /* fitted values */
  1001.     sprintf (jerkstring, "fitted");
  1002.   else if (image[CurImag].iFitted<0) /* fit failed */
  1003.     sprintf (jerkstring, "fit failed!");
  1004.   else /* no fit */
  1005.     sprintf (jerkstring, "");
  1006.  
  1007. /* write seventh line  */
  1008.   wierdstring = 
  1009.     XmStringCreateSimple (jerkstring);
  1010.   XtSetArg (wargs[0], XmNlabelString, wierdstring);
  1011.   XtSetValues (IDdata->Info7, wargs, 1);
  1012.   if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  1013. } /* end UpdateInfo */
  1014.  
  1015. /* call backs for zoom */
  1016. void Zoom25CB (Widget w, XtPointer clientData, XtPointer callData)
  1017. {
  1018.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  1019.  
  1020. /* NOP if same zoom */
  1021.     if (IDdata->zoom==-4) return;
  1022.  
  1023.     IDdata->zoom = -4; /* set new zoom factor */
  1024.  
  1025. /* reset display */
  1026.     ResetDisplay(IDdata);
  1027. /* mark in menu */
  1028.     MenuMarkZoom (0);
  1029.   } /* end of Zoom25CB */
  1030.  
  1031. void Zoom50CB (Widget w, XtPointer clientData, XtPointer callData)
  1032. {
  1033.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  1034.  
  1035. /* NOP if same zoom */
  1036.     if (IDdata->zoom==-2) return;
  1037.  
  1038.     IDdata->zoom = -2; /* set new zoom factor */
  1039.  
  1040. /* reset display */
  1041.     ResetDisplay(IDdata);
  1042. /* mark in menu */
  1043.     MenuMarkZoom (1);
  1044.   } /* end of Zoom50CB */
  1045.  
  1046. void Zoom100CB (Widget w, XtPointer clientData, XtPointer callData)
  1047. {
  1048.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  1049.  
  1050. /* NOP if same zoom */
  1051.     if (IDdata->zoom==1) return;
  1052.  
  1053.     IDdata->zoom = 1; /* set new zoom factor */
  1054.  
  1055. /* reset display */
  1056.     ResetDisplay(IDdata);
  1057. /* mark in menu */
  1058.     MenuMarkZoom (2);
  1059.   } /* end of Zoom100CB */
  1060.  
  1061. void Zoom200CB (Widget w, XtPointer clientData, XtPointer callData)
  1062. {
  1063.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  1064.  
  1065. /* NOP if same zoom */
  1066.     if (IDdata->zoom==2) return;
  1067.  
  1068.     IDdata->zoom = 2; /* set new zoom factor */
  1069.  
  1070. /* reset display */
  1071.     ResetDisplay(IDdata);
  1072. /* mark in menu */
  1073.     MenuMarkZoom (3);
  1074.   } /* end of Zoom200CB */
  1075.  
  1076. void Zoom400CB (Widget w, XtPointer clientData, XtPointer callData)
  1077. {
  1078.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  1079.  
  1080. /* NOP if same zoom */
  1081.     if (IDdata->zoom==4) return;
  1082.  
  1083.     IDdata->zoom = 4; /* set new zoom factor */
  1084.  
  1085. /* reset display */
  1086.     ResetDisplay(IDdata);
  1087. /* mark in menu */
  1088.     MenuMarkZoom (4);
  1089.   } /* end of Zoom400CB */
  1090.  
  1091. void Zoom800CB (Widget w, XtPointer clientData, XtPointer callData)
  1092. {
  1093.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  1094.  
  1095. /* NOP if same zoom */
  1096.     if (IDdata->zoom==8) return;
  1097.  
  1098.     IDdata->zoom = 8; /* set new zoom factor */
  1099.  
  1100. /* reset display */
  1101.     ResetDisplay(IDdata);
  1102. /* mark in menu */
  1103.     MenuMarkZoom (5);
  1104.   } /* end of Zoom800CB */
  1105.  
  1106. void Zoom1600CB (Widget w, XtPointer clientData, XtPointer callData)
  1107. {
  1108.     ImageDisplay  *IDdata = (ImageDisplay *)clientData;
  1109.  
  1110. /* NOP if same zoom */
  1111.     if (IDdata->zoom==16) return;
  1112.  
  1113.     IDdata->zoom = 16; /* set new zoom factor */
  1114.  
  1115. /* reset display */
  1116.     ResetDisplay(IDdata);
  1117. /* mark in menu */
  1118.     MenuMarkZoom (6);
  1119.   } /* end of Zoom1600CB */
  1120.