
#include "mview_display.h"

#include "mview_main.h"
#include "mview_help.h"
#include "mview_menu.h"
#include "mview_clips.h"
#include "mview_stuff.h"
#include "mview_cursor.h"
#include "mview_slice.h"
#include "mview_spectrum.h"
#include "mview_misc.h"
#include "mview_macros.h"
#include "mview_widgets.h"
#include "gmotif/hsvcontrol.h"
#include "gx11/visual_context.h"
#include "gsys/sic_util.h"

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

#include <Xm/Xm.h>
#include <Xm/MwmUtil.h>
#include <Xm/RowColumn.h>
#include <Xm/TextF.h>
#include <Xm/Text.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Xm/Scale.h>
#include <Xm/DrawingA.h>
#include <Xm/ScrollBar.h>
#include <Xm/ScrolledW.h>
#include <Xm/CascadeB.h>
#include <Xm/MainW.h>
#include <Xm/XmStrDefs.h>

#define MAXCOL 127

unsigned long blackpix, whitepix, redpix;

/*
#define max( a,b) ((int)(a)>(int)(b)?(int)(a):(int)(b))
#define min( a,b) ((int)(a)<(int)(b)?(int)(a):(int)(b))
*/
static char dumstr[80];

static int ERROR;
extern int veloleft;

static char *TheWedge = NULL;

static XtActionsRec actions[] = {
    {"cursor_input", (XtActionProc) cursor_input},
    {"slice_input", (XtActionProc) slice_input},
    {"spectrum_slice_input", (XtActionProc) spectrum_slice_input},
    {"coupe_input", (XtActionProc) coupe_input},
    {"set_sticks", (XtActionProc) set_sticks},
    {"spectrum_input", (XtActionProc) spectrum_input},
    {"quit", quit},
    {"mom_input", (XtActionProc) mom_input},
};

static int gesterreurs( Display * canal_aff, XErrorEvent * errev)
{
    XGetErrorText( canal_aff, errev->error_code, dumstr, 80);
    fprintf( stderr, "%s\n", dumstr);
    ERROR = 1;
    return 0;
}

int cursor_mode;

XtAppContext app;
Display *display;
unsigned int depth;
unsigned long blackpix, whitepix, graypix, redpix;
int pixmapdim[2], cpixmapdim[2];

Pixmap testpixmap;
Pixmap pixmap;                  /* Pixmap for mosaic */
Pixmap cpixmap;                 /* Pixmap for wedge */
Pixmap spixmap;                 /* Pixmap for slice */
Pixmap ipixmap;                 /* Pixmap for integ spec along slice */
Pixmap mpixmap = 0;             /* Pixmap for mean */
Pixmap vpixmap = 0;             /* Pixmap for velocity */
Pixmap wpixmap = 0;             /* Pixmap for width */

GC gc, gcx;
XGCValues xgcvl;

int slicewidth;                 /* Maximum width for slice */
int slice_zoomx, slice_zoomy;
int maxspectrumwidth;           /* Maximum width for spectrum pixmap */
int maxspectrumheight;
int specwidth;                  /* width for spectrum draw */
int specheight;                 /* height for spectrum draw */

Dimension disp_w, disp_h;



extern int show_posy;


static char mom_translations[] = "<EnterNotify>: mom_input( )\n\
                 <LeaveNotify>: mom_input( )\n\
                 <MotionNotify>: mom_input( )\n";

void dismiss_zoom( Widget w, XtPointer w_code, XmAnyCallbackStruct * cbs)
{
    XtUnmapWidget( XtParent( XtParent( w)));
}

void redraw( Window window)
{
    XCopyArea( display, pixmap, window, gc, 0, voffset, pixmapdim[0], pixmapdim[1], 0, 0);


    if (cursor_mode == SUBAREA) {
        redraws_box( );

    }
    if (cursor_mode == SLICE) {
        redraws_slice( );
    }

    redraw_cross( );
}

void scrolled( Widget w, XtPointer data, XmScrollBarCallbackStruct * cbs)
{
    int newoffset;

    newoffset = cbs->value * sizey;
    show_posy = show_posy + (voffset - newoffset);
    voffset = newoffset;
    redraw( XtWindow( radec));
}

static XPoint sticks[2];
int stick1, stick2, prev_stick1, prev_stick2;

extern int firstsub;

void draw_sticks( Widget w)
{
    char dum[80];

    XSetForeground( display, gc, blackpix);
    XFillRectangle( display, XtWindow( w), gc, 0, 0, 50, Nsubs * slice_zoomy);
    XSetForeground( display, gc, whitepix);
    XFillRectangle( display, XtWindow( w), gc, 0, sticks[0].y, 50, slice_zoomy);
    XFillRectangle( display, XtWindow( w), gc, 0, sticks[1].y, 50, slice_zoomy);

    sprintf( dum, "%d%c%d", Nsubs - 1 - sticks[0].y / slice_zoomy + firstsub, '-', Nsubs - 1 - sticks[1].y / slice_zoomy + firstsub);
    XmTextSetString( slicelab, dum);
}


void new_sticks( Widget w, int x, int y)
{
    int d, D, n, N;
    int s1, s2;

    D = 1E+05;
    for (n = 0; n < 2; n++) {
        if (y > slice_zoomy * Nsubs / 2)
            d = sqrt( (float)((sticks[n].y + slice_zoomy - y) * (sticks[n].y + slice_zoomy - y)));
        else
            d = sqrt( (float)((sticks[n].y - y) * (sticks[n].y - y)));
        if (d < D) {
            D = d;
            N = n;
        }
    }

    switch (N) {
    case 0:
        sticks[0].y = (min( max( 0, y), slice_zoomy * (Nsubs - 1)) / slice_zoomy) * slice_zoomy;
        break;
    case 1:
        sticks[1].y = (min( max( 0, y), slice_zoomy * (Nsubs - 1)) / slice_zoomy) * slice_zoomy;
        break;
    }

    s1 = sticks[0].y;
    s2 = sticks[1].y;
    sticks[0].y = max( s1, s2);
    sticks[1].y = min( s1, s2);

    draw_sticks( w);
    return;
}

void set_sticks( Widget w, XEvent * event, String * params, Cardinal num_params)
{
    int x, y;

    switch (event->type) {
    case ButtonPress:
        switch (event->xbutton.button) {
        case Button1:
            x = event->xbutton.y;
            y = event->xbutton.y;
            kill_movie( );
            new_sticks( w, x, y);
            break;
        }
        break;


    case MotionNotify:
        x = event->xmotion.x;
        y = event->xmotion.y;

        new_sticks( w, x, y);
        break;

    case ButtonRelease:
        stick1 = Nsubs - 1 - sticks[0].y / slice_zoomy;
        stick2 = Nsubs - 1 - sticks[1].y / slice_zoomy;

        if ((prev_stick1 != stick1) || (prev_stick2 != stick2)) {
            prev_stick1 = stick1;
            prev_stick2 = stick2;
            new_profile( );
        }

        break;
    }
}

static char set_sticks_translations[] = "Button1<Motion>: set_sticks( )\n\
                      <Btn1Down>: set_sticks( )\n\
                      <Btn1Up>: set_sticks( )\n";
void draw_axes( )
{
    XSetForeground( display, gc, blackpix);
    XFillRectangle( display, XtWindow( drawaxes), gc, 0, 0, slicewidth * slice_zoomx, 30);
    XFillRectangle( display, XtWindow( rdrawaxes), gc, 0, 0, 30, Nsubs * slice_zoomy + 30);
    XFillRectangle( display, XtWindow( ldrawaxes), gc, 0, 0, 30, Nsubs * slice_zoomy + 30);

    XSetForeground( display, gc, whitepix);
    XDrawLine( display, XtWindow( drawaxes), gc, 0, 5, slicewidth * slice_zoomx, 5);
    if (veloleft) {
        XDrawLine( display, XtWindow( drawaxes), gc, slicewidth * slice_zoomx - 5, 0, slicewidth * slice_zoomx, 5);
        XDrawLine( display, XtWindow( drawaxes), gc, slicewidth * slice_zoomx - 5, 10, slicewidth * slice_zoomx, 5);

        XDrawString( display, XtWindow( drawaxes), gc, slicewidth * slice_zoomx - 20, 20, "Pos", 3);

        XDrawLine( display, XtWindow( ldrawaxes), gc, 25, 0, 25, Nsubs * slice_zoomy + 5);
        XDrawLine( display, XtWindow( ldrawaxes), gc, 20, 10, 25, 0);
        XDrawLine( display, XtWindow( ldrawaxes), gc, 25, 0, 30, 10);
        XDrawLine( display, XtWindow( ldrawaxes), gc, 25, Nsubs * slice_zoomy + 5, 30, Nsubs * slice_zoomy + 5);
        XDrawString( display, XtWindow( ldrawaxes), gc, 0, 20, "Vel", 3);
    } else {
        XDrawLine( display, XtWindow( drawaxes), gc, 0, 5, 10, 0);
        XDrawLine( display, XtWindow( drawaxes), gc, 0, 5, 10, 10);

        XDrawString( display, XtWindow( drawaxes), gc, 0, 20, "Pos", 3);

        XDrawLine( display, XtWindow( rdrawaxes), gc, 5, 0, 5, Nsubs * slice_zoomy + 5);
        XDrawLine( display, XtWindow( rdrawaxes), gc, 0, 10, 5, 0);
        XDrawLine( display, XtWindow( rdrawaxes), gc, 5, 0, 10, 10);
        XDrawLine( display, XtWindow( rdrawaxes), gc, 0, Nsubs * slice_zoomy + 5, 5, Nsubs * slice_zoomy + 5);
        XDrawString( display, XtWindow( rdrawaxes), gc, 10, 20, "Vel", 3);
    }
    draw_angle( );

    XFlush( display);
}

void create( Widget w, int w_code, XmAnyCallbackStruct * cbs)
{
    XmString label;
    int j, k, kk;

    switch (w_code) {

    case k_vsb:
        XtVaSetValues( w, XmNorientation, XmVERTICAL, XmNmaximum, rows, XmNsliderSize, min( pixmapdim[1] / sizey, rows), NULL);
        break;

    case k_small_w:
        break;

    case k_scrolled_w:
        break;

    case k_radec:
        XtVaSetValues( w, XmNwidth, pixmapdim[0], XmNheight, pixmapdim[1], NULL);
        break;

    case k_cliparea:
        cpixmap = XCreatePixmap( display, g_vc.root_window, cpixmapdim[0], cpixmapdim[1], depth);
        TheWedge = malloc( 30 * cpixmapdim[1]);
        for (k = 0; k < cpixmapdim[1]; k++) {
            kk = k * MAXCOL / (cpixmapdim[1] - 1);
            for (j = 0; j < 30; j++) {
                TheWedge[(cpixmapdim[1] - k - 1) * 30 + j] = g_vc.colmap[kk];
            }
        }

        XSetForeground( display, gc, blackpix);
        XFillRectangle( display, cpixmap, gc, 0, 0, cpixmapdim[0], cpixmapdim[1]);
        XtVaSetValues( w, XmNwidth, cpixmapdim[0], XmNheight, cpixmapdim[1], XmNbackground, blackpix, NULL);

        break;

    case k_sliceticks:
        XtVaSetValues( sliceticks,
                      XmNwidth, 50,
                      XmNheight, Nsubs * slice_zoomy, XmNtranslations, XtParseTranslationTable( set_sticks_translations), NULL);

        sticks[0].x = 0;
        sticks[0].y = Nsubs * slice_zoomy - slice_zoomy;
        sticks[1].x = 0;
        sticks[1].y = 0;
        stick1 = 0;
        stick2 = Nsubs - 1;
        prev_stick1 = 0;
        prev_stick2 = Nsubs - 1;
        break;

    case k_slicelab:
        XtVaSetValues( w, XmNwidth, 50, XmNheight, 30, NULL);
        break;

    case k_drawaxes:
        XtVaSetValues( w, XmNwidth, slicewidth * slice_zoomx, NULL);
        break;

    case k_ldrawaxes:
        XtVaSetValues( w, XmNheight, Nsubs * slice_zoomy + 30, NULL);
        break;

    case k_rdrawaxes:
        XtVaSetValues( w, XmNheight, Nsubs * slice_zoomy + 30, NULL);
        break;

    case k_coupe:
        XtVaSetValues( coupe, XmNwidth, slicewidth * slice_zoomx, XmNheight, Nsubs * slice_zoomy, NULL);

        spixmap = XCreatePixmap( display, g_vc.root_window, slicewidth * slice_zoomx, Nsubs * slice_zoomy, depth);

        XSetForeground( display, gc, blackpix);
        XFillRectangle( display, spixmap, gc, 0, 0, slicewidth * slice_zoomx, Nsubs * slice_zoomy);
        break;

    case k_coupe_integ:

        XtVaSetValues( coupe_integ, XmNwidth, slicewidth * slice_zoomx, XmNheight, Nsubs * slice_zoomy, NULL);


        ipixmap = XCreatePixmap( display, g_vc.root_window, slicewidth * slice_zoomx, Nsubs * slice_zoomy, depth);

        XSetForeground( display, gc, blackpix);
        XFillRectangle( display, ipixmap, gc, 0, 0, slicewidth * slice_zoomx, Nsubs * slice_zoomy);
        break;

    case k_pixelvalue:
        XtVaSetValues( w, XmNwidth, (pixmapdim[0] + cpixmapdim[0]) / 2, NULL);
        break;
    case k_gridcoord:
        XtVaSetValues( w, XmNwidth, (pixmapdim[0] + cpixmapdim[0]) / 2 - 64, NULL);
        break;

    case k_axis1:
        XtVaSetValues( w, XmNwidth, (pixmapdim[0] + cpixmapdim[0]) / 3, NULL);

        break;
    case k_axis2:
        XtVaSetValues( w, XmNwidth, (pixmapdim[0] + cpixmapdim[0]) / 3, NULL);

        break;

    case k_axis3:
        XtVaSetValues( w, XmNwidth, (pixmapdim[0] + cpixmapdim[0]) / 3 - 64, NULL);

        break;

    case k_spixelvalue:
        XtVaSetValues( w, XmNwidth, (zsizex + specwidth) / 2, NULL);
        break;

    case k_sgridcoord:
        XtVaSetValues( w, XmNwidth, (zsizex + specwidth) / 2, NULL);
        break;

    case k_saxis1:
        XtVaSetValues( w, XmNwidth, (zsizex + specwidth) / 3, NULL);
        break;

    case k_saxis2:
        XtVaSetValues( w, XmNwidth, (zsizex + specwidth) / 3, NULL);
        break;
    case k_saxis3:
        XtVaSetValues( w, XmNwidth, (zsizex + specwidth) / 3, NULL);
        break;

    case k_clip:
        break;
    case k_slice:
        break;
    case k_cursor:
        if (Nsubs < 2) {
            label = XmStringCreateLocalized( "2D box");
            XtVaSetValues( w, XmNlabelString, label, NULL);
            XmStringFree( label);
        }
        break;

    case k_moments:
        if (Nsubs < 2) {
            fprintf( stderr, "Nsubs < 2: Destroying %s\n", XtName( w));
            XtDestroyWidget( w);
        }

        break;
    case k_zoom:
        break;
    case k_highscale:
        break;
    case k_highcut:
        change_clips( w, (XtPointer)( long)w_code, NULL);
        break;
    case k_lowscale:
        break;
    case k_lowcut:
        change_clips( w, (XtPointer)( long)w_code, NULL);
        break;
    case k_ok:
        XmTextSetString( w, "Press OK to validate");
        break;
    }

}

static void update_clipboard( )
{
    AffPixmap( TheWedge, cpixmap, 30, cpixmapdim[1], 0, 0, cpixmapdim[0] - 30, 0, 30, cpixmapdim[1]);
}

static void redraw_clipboard( )
{
    XCopyArea( display, cpixmap, XtWindow( cliparea), gc, 0, 0, cpixmapdim[0], cpixmapdim[1], 0, 0);
}

void on_dismiss( )
{
    Atom atom;

    if (g_vc.static_display) {
        atom = XInternAtom( display, "COLORTABLE", 0);

        XChangeProperty( display, XtWindow( radec), atom, XA_STRING, 8, PropModeReplace, (unsigned char *)"NEW", strlen( "NEW"));
    }
    XFlush( display);
}

void on_transfert_function( )
{
    extern void Update_IntegMean( );
    extern Pixmap integpixmap;

    if (pixmap != 0) {
        UpdateColorChanged( );
    }
    if (integpixmap != 0) {
        Update_IntegMean( );
    }
    if (TheWedge != NULL && cpixmap != (Pixmap) NULL) {
        update_clipboard( );
        redraw_clipboard( );
    }
}

void expose( Widget w, XtPointer area, XmDrawingAreaCallbackStruct * cbs)
{
    switch ((int)(long)area) {
    case k_radec:
        if (cbs->event->xexpose.count == 0)
            redraw( cbs->window);

        break;
    case k_cliparea:
        if (cbs->event->xexpose.count == 0)
            update_clipboard( );
        redraw_clipboard( );
        break;

    case k_sliceticks:
        draw_sticks( w);
        break;


    case k_coupe:
        if (cbs->event->xexpose.count == 0)
            XCopyArea( cbs->event->xexpose.display,
                      spixmap, cbs->window, gc, 0, 0, slicewidth * slice_zoomx, Nsubs * slice_zoomy, 0, 0);

        break;
    case k_coupe_integ:
        if (cbs->event->xexpose.count == 0)
            XCopyArea( cbs->event->xexpose.display,
                      ipixmap, cbs->window, gc, 0, 0, slicewidth * slice_zoomx, Nsubs * slice_zoomy, 0, 0);
        break;
    case k_drawaxes:
        XSetForeground( display, gc, whitepix);
        XDrawLine( display, XtWindow( w), gc, 0, 5, slicewidth * slice_zoomx, 5);
        if (veloleft) {
            XDrawLine( display, XtWindow( w), gc, slicewidth * slice_zoomx - 5, 0, slicewidth * slice_zoomx, 5);
            XDrawLine( display, XtWindow( w), gc, slicewidth * slice_zoomx - 5, 10, slicewidth * slice_zoomx, 5);

            XDrawString( display, XtWindow( w), gc, slicewidth * slice_zoomx - 20, 20, "Pos", 3);
        } else {
            XDrawLine( display, XtWindow( w), gc, 0, 5, 10, 0);
            XDrawLine( display, XtWindow( w), gc, 0, 5, 10, 10);

            XDrawString( display, XtWindow( w), gc, 0, 20, "Pos", 3);
        }
        draw_angle( );
        break;
    case k_ldrawaxes:
        if (veloleft) {
            XSetForeground( display, gc, whitepix);
            XDrawLine( display, XtWindow( w), gc, 25, 0, 25, Nsubs * slice_zoomy + 5);
            XDrawLine( display, XtWindow( w), gc, 20, 10, 25, 0);
            XDrawLine( display, XtWindow( w), gc, 25, 0, 30, 10);
            XDrawLine( display, XtWindow( w), gc, 25, Nsubs * slice_zoomy + 5, 30, Nsubs * slice_zoomy + 5);
            XDrawString( display, XtWindow( w), gc, 0, 20, "Vel", 3);
        }
        break;
    case k_rdrawaxes:
        if (!veloleft) {
            XSetForeground( display, gc, whitepix);
            XDrawLine( display, XtWindow( w), gc, 5, 0, 5, Nsubs * slice_zoomy + 5);
            XDrawLine( display, XtWindow( w), gc, 0, 10, 5, 0);
            XDrawLine( display, XtWindow( w), gc, 5, 0, 10, 10);
            XDrawLine( display, XtWindow( w), gc, 0, Nsubs * slice_zoomy + 5, 5, Nsubs * slice_zoomy + 5);
            XDrawString( display, XtWindow( w), gc, 10, 20, "Vel", 3);
        }
        break;
    }
}

void create_standard_menu( Widget menubar)
{
    int n = 0;
    Arg args[32];

    filemenu = XmCreatePulldownMenu( menubar, "filemenu", NULL, 0);
    n = 0;
    XtSetArg( args[n], XmNsubMenuId, filemenu);
    n++;
    fileb = XmCreateCascadeButton( menubar, "File", args, n);
    XtManageChild( filemenu);
    XtManageChild( fileb);

    exitbutton = XtVaCreateManagedWidget( "Quit", xmPushButtonWidgetClass, filemenu, NULL);
    XtAddCallback( exitbutton, XmNactivateCallback, (XtCallbackProc) quit, NULL);

    colormenu = XmCreatePulldownMenu( menubar, "colormenu", NULL, 0);
    n = 0;
    XtSetArg( args[n], XmNsubMenuId, colormenu);
    n++;

    colorb = XmCreateCascadeButton( menubar, "Color", args, n);
    XtManageChild( colormenu);
    XtManageChild( colorb);

    hsvbutton = XtVaCreateManagedWidget( "HSV", xmPushButtonWidgetClass, colormenu, NULL);
    XtAddCallback( hsvbutton, XmNactivateCallback, (XtCallbackProc) menu, (XtPointer) k_color);
    clipbutton = XtVaCreateManagedWidget( "clips", xmPushButtonWidgetClass, colormenu, NULL);
    create( clipbutton, k_clip, NULL);
    XtAddCallback( clipbutton, XmNactivateCallback, (XtCallbackProc) menu, (XtPointer) k_clip);

    smoothmenu = XmCreatePulldownMenu( menubar, "smooth", NULL, 0);
    n = 0;
    XtSetArg( args[n], XmNsubMenuId, smoothmenu);
    n++;

    smoothb = XmCreateCascadeButton( menubar, "Smooth", args, n);
    XtManageChild( smoothmenu);
    XtManageChild( smoothb);

    average_2 = XtVaCreateManagedWidget( "v_ave box2", xmPushButtonWidgetClass, smoothmenu, NULL);
    XtAddCallback( average_2, XmNactivateCallback, (XtCallbackProc) average, (XtPointer) k_average_2);
    average_3 = XtVaCreateManagedWidget( "v_ave box3", xmPushButtonWidgetClass, smoothmenu, NULL);
    XtAddCallback( average_3, XmNactivateCallback, (XtCallbackProc) average, (XtPointer) k_average_3);
    none = XtVaCreateManagedWidget( "none", xmPushButtonWidgetClass, smoothmenu, NULL);
    XtAddCallback( none, XmNactivateCallback, (XtCallbackProc) average, (XtPointer) k_none);
    hanning = XtVaCreateManagedWidget( "lm_ave han", xmPushButtonWidgetClass, smoothmenu, NULL);
    XtAddCallback( hanning, XmNactivateCallback, (XtCallbackProc) smooth, (XtPointer) k_hanning);
    gauss = XtVaCreateManagedWidget( "lm_ave gau", xmPushButtonWidgetClass, smoothmenu, NULL);
    XtAddCallback( gauss, XmNactivateCallback, (XtCallbackProc) smooth, (XtPointer) k_gauss);
    box = XtVaCreateManagedWidget( "lm_ave box", xmPushButtonWidgetClass, smoothmenu, NULL);
    XtAddCallback( box, XmNactivateCallback, (XtCallbackProc) smooth, (XtPointer) k_box);


    cursormenu = XmCreatePulldownMenu( menubar, "cursormenu", NULL, 0);
    n = 0;
    XtSetArg( args[n], XmNsubMenuId, cursormenu);
    n++;

    cursorb = XmCreateCascadeButton( menubar, "Mode", args, n);
    XtManageChild( cursormenu);
    XtManageChild( cursorb);

    spectrumbutton = XtVaCreateManagedWidget( "Normal", xmPushButtonWidgetClass, cursormenu, NULL);
    create( spectrumbutton, k_spectrum, NULL);
    XtAddCallback( spectrumbutton, XmNactivateCallback, (XtCallbackProc) menu, (XtPointer) k_spectrum);

    slicebutton = XtVaCreateManagedWidget( "Slice", xmPushButtonWidgetClass, cursormenu, NULL);
    create( slicebutton, k_slice, NULL);
    XtAddCallback( slicebutton, XmNactivateCallback, (XtCallbackProc) menu, (XtPointer) k_slice);
    boxbutton = XtVaCreateManagedWidget( "3D box", xmPushButtonWidgetClass, cursormenu, NULL);
    create( boxbutton, k_cursor, NULL);
    XtAddCallback( boxbutton, XmNactivateCallback, (XtCallbackProc) menu, (XtPointer) k_cursor);

    if (Nsubs >= 2) {
        momentsbutton = XtVaCreateManagedWidget( "Moments", xmPushButtonWidgetClass, cursormenu, NULL);
        create( momentsbutton, k_moments, NULL);
        XtAddCallback( momentsbutton, XmNactivateCallback, (XtCallbackProc) make_moments, NULL);
    }

    if (!standalone) {
        tasksmenu = XmCreatePulldownMenu( menubar, "tasksmenu", NULL, 0);
        n = 0;
        XtSetArg( args[n], XmNsubMenuId, tasksmenu);
        n++;

        tasksb = XmCreateCascadeButton( menubar, "Tasks", args, n);
        XtManageChild( tasksmenu);
        XtManageChild( tasksb);

        extract_task = XtVaCreateManagedWidget( "EXTRACT", xmPushButtonWidgetClass, tasksmenu, NULL);

        XtAddCallback( extract_task, XmNactivateCallback, (XtCallbackProc) extract_image, (XtPointer) k_extract);
        slice_task = XtVaCreateManagedWidget( "SLICE", xmPushButtonWidgetClass, tasksmenu, NULL);

        XtAddCallback( slice_task, XmNactivateCallback, (XtCallbackProc) extract_image, (XtPointer) k_slice);
        spectrum_task = XtVaCreateManagedWidget( "SPECTRUM", xmPushButtonWidgetClass, tasksmenu, NULL);
        create( spectrum_task, k_spectrum, NULL);
        XtAddCallback( spectrum_task, XmNactivateCallback, (XtCallbackProc) extract_image, (XtPointer) k_spectrum);

        map_aver_task = XtVaCreateManagedWidget( "MAP_AVER", xmPushButtonWidgetClass, tasksmenu, NULL);
        create( map_aver_task, k_map_aver, NULL);
        XtAddCallback( map_aver_task, XmNactivateCallback, (XtCallbackProc) extract_image, (XtPointer) k_map_aver);

        map_sum_task = XtVaCreateManagedWidget( "MAP_SUM", xmPushButtonWidgetClass, tasksmenu, NULL);
        create( map_sum_task, k_map_sum, NULL);
        XtAddCallback( map_sum_task, XmNactivateCallback, (XtCallbackProc) extract_image, (XtPointer) k_map_sum);

        spectrum_sum_task = XtVaCreateManagedWidget( "SPECTRUM_SUM", xmPushButtonWidgetClass, tasksmenu, NULL);
        create( spectrum_sum_task, k_spectrum_sum, NULL);
        XtAddCallback( spectrum_sum_task, XmNactivateCallback, (XtCallbackProc) extract_image, (XtPointer) k_spectrum_sum);

        if (Nsubs >= 2) {
            moments_task = XtVaCreateManagedWidget( "MOMENTS", xmPushButtonWidgetClass, tasksmenu, NULL);
            create( moments_task, k_moments, NULL);
            XtAddCallback( moments_task, XmNactivateCallback, (XtCallbackProc) extract_image, (XtPointer) k_moments);
        }

    }

    /*   toolsmenu =  XmCreatePulldownMenu( menubar,"toolsmenu", NULL, 0); */
    /*   n = 0; */
    /*   XtSetArg( args[n], XmNsubMenuId, toolsmenu); n++; */
    /*   toolsb = XmCreateCascadeButton (menubar,"Tools", args, n); */
    /*   XtManageChild( toolsmenu);  */
    /*   XtManageChild( toolsb);       */
    /*   zoombutton = XtVaCreateManagedWidget( "Zoom", */
    /*                                xmPushButtonWidgetClass, */
    /*                                toolsmenu, */
    /*                                NULL); */
    /*   create( zoombutton, k_zoom, NULL); */
    /*   XtAddCallback( zoombutton, XmNactivateCallback, (XtCallbackProc) menu, (XtPointer)k_zoom); */

    helpbutton = XtVaCreateManagedWidget( "Help", xmPushButtonWidgetClass, menubar, NULL);
    XtAddCallback( helpbutton, XmNactivateCallback, (XtCallbackProc) popup_help_file, NULL);
}

void inidisplay( )
{
    XColor cdef;
    static char zzz[] = "<Key>Delete: popup_help_file( )\n\
     <Key>Q: quit( )\n";
    Widget main_w;
    Widget mwmenubar, menubar;
    Font fonte;
    int n = 0;
    String name[1] = { "mview" };
    Arg args[32];
    char lutpath[SIC_MAX_TRANSLATION_LENGTH];
    char tmppath[SIC_MAX_TRANSLATION_LENGTH];

    cursor_mode = 0;

    if (!(toplevel = XtVaAppInitialize( &app, "Mview", NULL, 0, &n, name, NULL, NULL))) {
        printf( "Failed to start X Window\n");
        exit( 0);
    }

    vc_build( XtDisplay( toplevel), XtScreen( toplevel));

    /* set global variables */
    display = g_vc.display;
    depth = g_vc.depth;
    blackpix = g_vc.black_pixel;
    whitepix = g_vc.white_pixel;
    gc = g_vc.gc;

    printf( "I-X,  Default Screen characteristics %d planes. \n", depth);

    strcpy( lutpath, sic_s_get_translation( "GAG_LUT:"));
    strcpy( tmppath, sic_s_get_translation( "GAG_TMP:"));

    hsv_init_colors( lutpath, tmppath);

    if (!XParseColor( display, g_vc.colormap, "Gray", &cdef) || !XAllocColor( display, g_vc.colormap, &cdef))
        graypix = blackpix;
    else
        graypix = cdef.pixel;

    if (!XParseColor( display, g_vc.colormap, "Red", &cdef) || !XAllocColor( display, g_vc.colormap, &cdef))
        redpix = blackpix;
    else
        redpix = cdef.pixel;

    xgcvl.function = GXinvert;
    xgcvl.foreground = whitepix;
    xgcvl.background = blackpix;
    xgcvl.line_width = 0;
    if (!(gcx = XCreateGC(display, g_vc.root_window, GCForeground | GCBackground | GCFunction, &xgcvl))) {
        printf( "creates_itt : could not get a graphic context. Aborting !\n");
        exit( 0);
    }
    fonte = XLoadFont( display, "6x10");
    XSetFont( display, gc, fonte);


    disp_w = 0.9 * WidthOfScreen( g_vc.screen_pt);
    disp_h = 0.9 * HeightOfScreen( g_vc.screen_pt);

    cols = 1;
    rows = 1;
    zoom = 1;

    while (1) {
        if (cols * rows >= Nsubs)
            break;
        cols++;
        if (cols * rows >= Nsubs)
            break;
        rows++;
    }

    cpixmapdim[0] = 102;

    while (1) {
        if ((cols * npix[0] * (zoom + 1) + cpixmapdim[0] > disp_w) || (rows * npix[1] * (zoom + 1) + 200 > disp_h))
            break;
        zoom++;
    }

    zoom = 1;
    while (1) {
        incr++;

        sizex = (zoom * npix[0]) / incr;
        sizey = (zoom * npix[1]) / incr;

        pixmapdim[0] = sizex * cols;
        pixmapdim[1] = sizey * rows;
        /*
           fprintf( stderr,  "Nsubs %d cols %d rows %d", Nsubs, cols, rows);

           fprintf( stderr, "sizex %d sizey %d", sizex, sizey);

           fprintf( stderr, "view_width %d view_height %d",
           pixmapdim[0], pixmapdim[1]);

         */

        if ((rows > 1) && ((pixmapdim[0] + cpixmapdim[0] > disp_w) || (pixmapdim[1] + 200 > disp_h))) {
            cols = max( 1, (disp_w - cpixmapdim[0]) / sizex - 1);
            cols = min( cols, Nsubs);
            rows = (Nsubs + cols - 1) / cols;

            pixmapdim[0] = sizex * cols;

            pixmapdim[1] = min( sizey * rows, max( sizey * ((disp_h - 200) / sizey), sizey));
            /*
               pixmapdim[1] = sizey*rows;
             */
        }
        /*
           fprintf( stderr, "Nsubs %d cols %d rows %d", Nsubs, cols, rows);
           fprintf( stderr, "subset_width %d subset_height%d", sizex, sizey);

           fprintf( stderr, "view_width %d view_height %d",
           pixmapdim[0], pixmapdim[1]);

           fprintf( stderr, "Create Pixmap %d %d", cols*sizex,
           rows*sizey);
         */


        XSetErrorHandler( gesterreurs);

        ERROR = 0;
        pixmap = XCreatePixmap( display, g_vc.root_window, cols * sizex, rows * sizey, depth);

        XSync( display, False);


        if (!ERROR) {
            /*
               fprintf( stderr, "%s\n", "Pixmap OK");
             */
            break;
        }
        /*
           fprintf( stderr, "decimation %d", incr);
           fprintf( stderr, "Zoom %d\n", zoom);
         */
    }

    XSetErrorHandler( NULL);

    XSetForeground( display, gc, whitepix);
    XFillRectangle( display, pixmap, gc, 0, 0, cols * sizex, rows * sizey);

    /*
       if (Nsubs < 16)
       specwidth = Nsubs*16 + 40;
       else if (Nsubs < 32)
       specwidth = Nsubs*8 + 40;
       else if (Nsubs < 64)
       specwidth = Nsubs*4 + 40;
       else
       specwidth = Nsubs*2 + 40;
     */

    if (disp_h > 1000) {
        maxspectrumwidth = 512;
        maxspectrumheight = 384;
    } else {
        maxspectrumwidth = 256;
        maxspectrumheight = 256;
    }

    specwidth = Nsubs * (max( 1, 256 / Nsubs)) + 40;

    localzoom = 1;
    while ((npix[0] * (localzoom + 1) <= maxspectrumwidth)
           && (npix[1] * (localzoom + 1) <= maxspectrumheight))
        localzoom++;

    /*
       fprintf( stderr, "%s %d\n", "spectrum zoom =", localzoom);
     */
    zsizex = localzoom * npix[0];
    zsizey = localzoom * npix[1];


    if (disp_h > 1000)
        slice_zoomy = max( 1, zsizey / Nsubs);
    else
        slice_zoomy = max( 1, zsizey / (2 * Nsubs));

    slicewidth = sqrt( (float)(npix[0] * npix[0]) / (incr * incr) + (float)(npix[1] * npix[1]) / (incr * incr));


    if (slicewidth <= 64)
        slice_zoomx = 8;
    else if (slicewidth <= 128)
        slice_zoomx = 4;
    else if (slicewidth <= 256)
        slice_zoomx = 2;
    else
        slice_zoomx = 1;

    if (npix[0] > maxspectrumwidth) {
        slice_zoomx = 1;
        maxspectrumwidth = npix[0];
    }
    if (npix[1] > maxspectrumwidth) {
        slice_zoomx = 1;
        maxspectrumwidth = npix[1];
    }

    cpixmapdim[1] = pixmapdim[1];

    main_w = XtVaCreateManagedWidget( "main_w", xmFormWidgetClass, toplevel, NULL);
    XtAppAddActions( app, actions, XtNumber( actions));
    small_w = XtVaCreateManagedWidget( "small_w",
                                      xmDrawingAreaWidgetClass,
                                      main_w,
                                      XmNrightAttachment, XmATTACH_FORM,
                                      XmNtopAttachment, XmATTACH_FORM,
                                      XmNforeground, whitepix, XmNbackground, blackpix, XmNwidth, 64, XmNheight, 64, NULL);
    XtAugmentTranslations( small_w, XtParseTranslationTable( zzz));
    create( small_w, k_small_w, NULL);

    form1 = XtVaCreateManagedWidget( "form1",
                                    xmFormWidgetClass,
                                    main_w,
                                    XmNforeground, whitepix,
                                    XmNbackground, blackpix,
                                    XmNtopAttachment, XmATTACH_FORM,
                                    XmNleftAttachment, XmATTACH_FORM,
                                    XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, small_w, XmNheight, 32, NULL);
    pixelvalue = XtVaCreateManagedWidget( "pixelvalue",
                                         xmTextWidgetClass,
                                         form1,
                                         XmNleftAttachment, XmATTACH_FORM,
                                         XmNtraversalOn, FALSE,
                                         XmNbackground, blackpix,
                                         XmNforeground, whitepix, XmNcursorPositionVisible, FALSE, XmNeditable, FALSE, NULL);
    create( pixelvalue, k_pixelvalue, NULL);

    gridcoord = XtVaCreateManagedWidget( "gridcoord",
                                        xmTextWidgetClass,
                                        form1,
                                        XmNleftAttachment, XmATTACH_WIDGET,
                                        XmNleftWidget, pixelvalue,
                                        XmNrightAttachment, XmATTACH_FORM,
                                        XmNbackground, blackpix,
                                        XmNforeground, whitepix,
                                        XmNtraversalOn, FALSE, XmNcursorPositionVisible, FALSE, XmNeditable, FALSE, NULL);
    create( gridcoord, k_gridcoord, NULL);

    form2 = XtVaCreateManagedWidget( "form2",
                                    xmFormWidgetClass,
                                    main_w,
                                    XmNforeground, whitepix,
                                    XmNbackground, blackpix,
                                    XmNtopAttachment, XmATTACH_WIDGET,
                                    XmNtopWidget, form1,
                                    XmNleftAttachment, XmATTACH_FORM,
                                    XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, small_w, XmNheight, 32, NULL);

    axis1 = XtVaCreateManagedWidget( "axis1",
                                    xmTextWidgetClass,
                                    form2,
                                    XmNleftAttachment, XmATTACH_FORM,
                                    XmNtraversalOn, FALSE,
                                    XmNbackground, blackpix,
                                    XmNforeground, whitepix, XmNcursorPositionVisible, FALSE, XmNeditable, FALSE, NULL);
    create( axis1, k_axis1, NULL);
    axis2 = XtVaCreateManagedWidget( "axis2",
                                    xmTextWidgetClass,
                                    form2,
                                    XmNleftAttachment, XmATTACH_WIDGET,
                                    XmNleftWidget, axis1,
                                    XmNbackground, blackpix,
                                    XmNforeground, whitepix,
                                    XmNtraversalOn, FALSE, XmNcursorPositionVisible, FALSE, XmNeditable, FALSE, NULL);
    create( axis2, k_axis2, NULL);

    axis3 = XtVaCreateManagedWidget( "axis3",
                                    xmTextWidgetClass,
                                    form2,
                                    XmNleftAttachment, XmATTACH_WIDGET,
                                    XmNleftWidget, axis2,
                                    XmNrightAttachment, XmATTACH_FORM,
                                    XmNbackground, blackpix,
                                    XmNforeground, whitepix,
                                    XmNtraversalOn, FALSE, XmNcursorPositionVisible, FALSE, XmNeditable, FALSE, NULL);
    create( axis3, k_axis3, NULL);

    n = 0;
    XtSetArg( args[n], XmNmarginWidth, 0);
    n++;
    XtSetArg( args[n], XmNmarginHeight, 0);
    n++;
    XtSetArg( args[n], XmNshadowThickness, 0);
    n++;
    XtSetArg( args[n], XmNshadowType, XmSHADOW_OUT);
    n++;
    XtSetArg( args[n], XmNtopAttachment, XmATTACH_WIDGET);
    n++;
    XtSetArg( args[n], XmNtopWidget, form2);
    n++;
    XtSetArg( args[n], XmNleftAttachment, XmATTACH_FORM);
    n++;
    XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM);
    n++;

    menubar = mwmenubar = XmCreateMenuBar( main_w, "mwmenubar", args, n);
    create_standard_menu( menubar);
    XtManageChild( menubar);

    cliparea = XtVaCreateManagedWidget( "cliparea",
                                       xmDrawingAreaWidgetClass,
                                       main_w,
                                       XmNleftAttachment, XmATTACH_FORM,
                                       XmNtopAttachment, XmATTACH_WIDGET,
                                       XmNtopWidget, mwmenubar, XmNbottomAttachment, XmATTACH_FORM, NULL);

    create( cliparea, k_cliparea, NULL);
    XtAddCallback( cliparea, XmNexposeCallback, (XtCallbackProc) expose, (XtPointer) k_cliparea);

    n = 0;
    XtSetArg( args[n], XmNtopAttachment, XmATTACH_WIDGET);
    n++;
    XtSetArg( args[n], XmNtopWidget, mwmenubar);
    n++;
    XtSetArg( args[n], XmNleftAttachment, XmATTACH_WIDGET);
    n++;
    XtSetArg( args[n], XmNleftWidget, cliparea);
    n++;
    XtSetArg( args[n], XmNrightAttachment, XmATTACH_FORM);
    n++;
    XtSetArg( args[n], XmNbottomAttachment, XmATTACH_FORM);
    n++;

    XtSetArg( args[n], XmNscrollingPolicy, XmAPPLICATION_DEFINED);
    n++;
    XtSetArg( args[n], XmNvisualPolicy, XmVARIABLE);
    n++;
    scrolled_w = XmCreateScrolledWindow( main_w, "scrolled_w", args, n);
    create( scrolled_w, k_scrolled_w, NULL);

    radec = XtVaCreateManagedWidget( "radec", xmDrawingAreaWidgetClass, scrolled_w, NULL);
    create( radec, k_radec, NULL);
    XtAddCallback( radec, XmNexposeCallback, (XtCallbackProc) expose, (XtPointer) k_radec);

    XtAddEventHandler( radec, PropertyChangeMask, False, (XtEventHandler) average, (XtPointer) k_none);
    vsb = XtVaCreateManagedWidget( "vsb", xmScrollBarWidgetClass, scrolled_w, NULL);
    create( vsb, k_vsb, NULL);
    XtAddCallback( vsb, XmNvalueChangedCallback, (XtCallbackProc) scrolled, NULL);
    XtAddCallback( vsb, XmNdragCallback, (XtCallbackProc) scrolled, NULL);

    XmScrolledWindowSetAreas( scrolled_w, NULL, vsb, radec);

    if ((cols * sizex == pixmapdim[0]) && (rows * sizey == pixmapdim[1]))
        XtUnmanageChild( vsb);

    /* Actually map the window */

    XtManageChild( scrolled_w);

    XtManageChild( main_w);

    XtRealizeWidget( toplevel);


}

void set_colormap( Widget w)
{
    vc_set_colormap( XtWindow( w));
}

void realize_top( )
{

    /* Allow the ScrolledWindow to initialize itself accordingly... */

    set_colormap( toplevel);

    spectrum( );

    slice( );

    /* loop on X-Window events */

    XtAppMainLoop( app);
}

static Widget momshell = NULL, meanshell = NULL, veloshell = NULL, widthshell = NULL;
static Widget mean_w, velo_w, width_w;

static Widget seuil_w;
static float seuil;

void change_seuil( Widget w, int *tag, XmScaleCallbackStruct * cbs)
{

    char dum[80];

    seuil = clip[0] + ((float)(cbs->value) / 100.) * (clip[1] - clip[0]);

    sprintf( dum, "%10.2g", seuil);

    XmTextFieldSetString( seuil_w, dum);
}

void get_seuil( float *s)
{
    *s = seuil;
}

static float vel[512];
static float *fmean = NULL, *fvelo = NULL, *fwidth = NULL;

void compute_moments( Widget w, XtPointer w_code, XmAnyCallbackStruct * cbs)
{
    int i, x, y, z, k;
    float t, f;
    double uc[3];
    char chainx[80], chainy[80], chainz[80], chainv[80];
    int sub[2];

    if (fmean == NULL) {
        x = 1;
        y = 1;
        for (i = 0; i < Nsubs; i++) {
            z = i + 1;
            phys_coord( &x, &y, &z, uc,
                       chainx, chainy, chainz, chainv, strlen( chainx), strlen( chainy), strlen( chainz), strlen( chainv));
            vel[i] = (float)atof( chainz);
        }

        fmean = (float *)malloc( npix[0] * npix[1] * sizeof( float));

        fvelo = (float *)malloc( npix[0] * npix[1] * sizeof( float));

        fwidth = (float *)malloc( npix[0] * npix[1] * sizeof( float));
    }

    /* Calcul des moments */
    for (k = 0; k < npix[0] * npix[1]; k++) {
        fmean[k] = 0.0;
        fvelo[k] = 0.0;
        fwidth[k] = 0.0;
    }
    /*
       k = 0;
       for (y = 0; y<npix[1]; y++) {
       for (x = 0; x<npix[0]; x++) {

       for (z = 0; z <Nsubs; z++) {
       t = vel[z];

       f = *(F_ADDR(x, y, z));
       if (((float)fabs( (double)(f - Blank)) <= Tolerance) ||
       (f < seuil))
       f = 0.;

       fmean[k] = fmean[k] + f;
       fvelo[k] = fvelo[k] + t*f;
       fwidth[k] = fwidth[k] + t*t*f;
       }
       k++;
       }
       }
     */

    get_relative_sub( sub);

    if (sub[0] > sub[1]) {
        z = sub[1];
        sub[1] = sub[0];
        sub[0] = z;
    }

    for (z = sub[0]; z <= sub[1]; z++) {
        k = 0;
        t = vel[z];
        for (y = 0; y < npix[1]; y++) {
            for (x = 0; x < npix[0]; x++) {
                f = *(F_ADDR(x, y, z));
                if (((float)fabs( (double)(f - Blank)) <= Tolerance) || (f < seuil))
                    f = 0.;

                fmean[k] = fmean[k] + f;
                fvelo[k] = fvelo[k] + t * f;
                fwidth[k] = fwidth[k] + t * t * f;
                k++;
            }
        }
    }

    for (k = 0; k < npix[0] * npix[1]; k++) {
        if (fmean[k] != 0.) {
            fvelo[k] = fvelo[k] / fmean[k];
            fwidth[k] = fwidth[k] / fmean[k];
            if (fwidth[k] - fvelo[k] * fvelo[k] < 0.) {
                fwidth[k] = 0.;
            } else
                fwidth[k] = (float)sqrt( (double)(fwidth[k] - fvelo[k] * fvelo[k]));
        } else {
            fvelo[k] = 0.;
            fwidth[k] = 0.;
        }
    }
    view_mean( );
    view_velo( );
    view_width( );

    create_momwidgets( );
}

void destroy_momshell( Widget w, Pixmap * area, XmAnyCallbackStruct * cbs)
{
    momshell = NULL;
}

void make_moments( Widget w, int *code, XmAnyCallbackStruct * cbs)
{

    Widget rowcol, scale_w, button;
    XmString string;
    char dum[80];

    if (Nsubs < 2)
        return;

    if (momshell == NULL) {

        momshell = XtVaAppCreateShell( "Moments",
                                      "momshell",
                                      topLevelShellWidgetClass,
                                      display,
                                      XmNmwmDecorations, MWM_DECOR_MENU |
                                      MWM_DECOR_TITLE | MWM_DECOR_BORDER | MWM_DECOR_MINIMIZE, NULL);

        XtAddCallback( momshell, XtNdestroyCallback, (XtCallbackProc) destroy_momshell, NULL);


        rowcol = XtVaCreateManagedWidget( "rowcol",
                                         xmRowColumnWidgetClass,
                                         momshell,
                                         XmNforeground, whitepix, XmNbackground, blackpix, XmNorientation, XmHORIZONTAL, NULL);

        seuil_w = XtVaCreateManagedWidget( "seuil_w",
                                          xmTextFieldWidgetClass, rowcol, XmNbackground, blackpix, XmNforeground, whitepix, NULL);
        seuil = clip[0];
        sprintf( dum, "%10.2g", seuil);
        XmTextFieldSetString( seuil_w, dum);


        string = XmStringCreateLocalized( "Seuil");

        scale_w =
         XtVaCreateManagedWidget( "scale_w",
                                 xmScaleWidgetClass,
                                 rowcol,
                                 XmNforeground, whitepix,
                                 XmNbackground, blackpix,
                                 XmNorientation, XmHORIZONTAL, XmNwidth, 512, XmNtitleString, string, NULL);
        XmStringFree( string);
        XtAddCallback( scale_w, XmNdragCallback, (XtCallbackProc) change_seuil, NULL);

        XtAddCallback( scale_w, XmNvalueChangedCallback, (XtCallbackProc) change_seuil, NULL);

        button = XtVaCreateManagedWidget( "OK",
                                         xmPushButtonWidgetClass, rowcol, XmNforeground, whitepix, XmNbackground, blackpix, NULL);

        XtAddCallback( button, XmNactivateCallback, (XtCallbackProc) compute_moments, NULL);

        XtRealizeWidget( momshell);
        set_colormap( momshell);
    }


}

static int mom_gesterreurs( Display * canal_aff, XErrorEvent * errev)
{
    XGetErrorText( canal_aff, errev->error_code, dumstr, 80);

    fprintf( stderr, "%s\n", dumstr);
    return 0;
}

void view_mean( )
{
    int i;
    float mclip[2];
    Window fen_rac;
    int x, y;
    unsigned int larg, haut, ep_bord, prof;
    Status ret;

    XSetErrorHandler( mom_gesterreurs);

    if (mpixmap == 0) {

        mpixmap = XCreatePixmap( display, g_vc.root_window, zsizex, zsizey, depth);

        ret = XGetGeometry( display, mpixmap, &fen_rac, &x, &y, &larg, &haut, &ep_bord, &prof);
        if (ret == 0) {
            fprintf( stderr, "%s\n", "not enough mem");
            mpixmap = 0;
            return;
        }
    }


    mclip[1] = 0.;
    for (i = 0; i < npix[0] * npix[1]; i++)
        if (fmean[i] > mclip[1])
            mclip[1] = fmean[i];
    mclip[0] = mclip[1];
    for (i = 0; i < npix[0] * npix[1]; i++)
        if ((fmean[i] < mclip[0]) && (fmean[i] != 0))
            mclip[0] = fmean[i];
    /*
       fprintf( stderr, "mean clips %f %f\n", mclip[0], mclip[1]);
     */
    AffImage( fmean, mpixmap, zsizex, zsizey,
             1, npix[0], 1, npix[1], localzoom, localzoom, mclip[0], mclip[1], 1, 0, 0, 0, 0, zsizex, zsizey);
}

void view_velo( )
{

    int i;
    float vclip[2];
    Window fen_rac;
    int x, y;
    unsigned int larg, haut, ep_bord, prof;
    Status ret;

    if (vpixmap == 0) {
        vpixmap = XCreatePixmap( display, g_vc.root_window, zsizex, zsizey, depth);

        ret = XGetGeometry( display, vpixmap, &fen_rac, &x, &y, &larg, &haut, &ep_bord, &prof);
        if (ret == 0) {
            fprintf( stderr, "%s\n", "not enough mem");
            vpixmap = 0;
            return;
        }
    }

    vclip[1] = 0.;
    for (i = 0; i < npix[0] * npix[1]; i++)
        if (fvelo[i] > vclip[1])
            vclip[1] = fvelo[i];
    vclip[0] = vclip[1];
    for (i = 0; i < npix[0] * npix[1]; i++)
        if ((fvelo[i] < vclip[0]) && (fvelo[i] != 0))
            vclip[0] = fvelo[i];
    /*
       fprintf( stderr, "velo clips %f %f\n", vclip[0], vclip[1]);
     */
    AffImage( fvelo, vpixmap, zsizex, zsizey,
             1, npix[0], 1, npix[1], localzoom, localzoom, vclip[0], vclip[1], 1, 0, 0, 0, 0, zsizex, zsizey);
}


void view_width( )
{
    int i;
    float wclip[2];
    Window fen_rac;
    int x, y;
    unsigned int larg, haut, ep_bord, prof;
    Status ret;

    if (wpixmap == 0) {
        wpixmap = XCreatePixmap( display, g_vc.root_window, zsizex, zsizey, depth);

        ret = XGetGeometry( display, wpixmap, &fen_rac, &x, &y, &larg, &haut, &ep_bord, &prof);
        if (ret == 0) {
            fprintf( stderr, "%s\n", "not enough mem");
            wpixmap = 0;
            return;
        }

    }

    wclip[1] = 0.;
    for (i = 0; i < npix[0] * npix[1]; i++)
        if (fwidth[i] > wclip[1])
            wclip[1] = fwidth[i];
    wclip[0] = wclip[1];
    for (i = 0; i < npix[0] * npix[1]; i++)
        if ((fwidth[i] < wclip[0]) && (fwidth[i] != 0))
            wclip[0] = fwidth[i];
    /*
       fprintf( stderr, "width clips %f %f\n", wclip[0], wclip[1]);
     */
    AffImage( fwidth, wpixmap, zsizex, zsizey,
             1, npix[0], 1, npix[1], localzoom, localzoom, wclip[0], wclip[1], 1, 0, 0, 0, 0, zsizex, zsizey);
    XSetErrorHandler( NULL);
}

void expose_moment( Widget w, Pixmap * area, XmDrawingAreaCallbackStruct * cbs)
{

    XCopyArea( cbs->event->xexpose.display, *area, cbs->window, gc, 0, 0, zsizex, zsizey, 0, 0);
}

void destroy_moment( Widget w, Pixmap * area, XmAnyCallbackStruct * cbs)
{

    if (*area == mpixmap)
        meanshell = NULL;
    if (*area == vpixmap)
        veloshell = NULL;
    if (*area == wpixmap)
        widthshell = NULL;

}

void mom_input( Widget w, XEvent * event)
{
    static int prev_x, prev_y;
    static int prev_xm = -1, prev_ym, prev_sub, prev_sub1, prev_sub2;
    int x, y, z, xm, ym, rang, sub, sub1, sub2, do_it;
    float ecart;
    char dum[80];
    static char *preval;

    if (event->type == EnterNotify) {
        preval = XmTextGetString( axis3);
        prev_xm = -1;
        return;
    }

    if (event->type == LeaveNotify) {
        XmTextSetString( axis3, preval);
        XtFree( preval);
    }

    if ((event->type == LeaveNotify) && (prev_xm != -1)) {
        if (w == velo_w) {
            DRAWCIRC(radec, POSX(prev_xm, prev_sub), POSY(prev_ym, prev_sub));
        }
        if (w == width_w) {
            for (z = min( prev_sub1, prev_sub2); z <= max( prev_sub1, prev_sub2); z++) {
                DRAWCIRC(radec, POSX(prev_xm, z), POSY(prev_ym, z));
            }
        }

        DRAWCIRC(w, prev_x, prev_y);
        return;
    }

    x = event->xmotion.x;
    y = event->xmotion.y;

    do_it = 1;

    if ((x < 0) || (x >= zsizex) || (y < 0) || (y >= zsizey))
        do_it = 0;

    if (do_it) {
        rang = ((zsizey - 1 - y) / localzoom) * npix[0] + x / localzoom;
        if (fvelo[rang] == 0)
            do_it = 0;
    }

    if (do_it == 0) {
        if (prev_xm != -1) {
            if (w == velo_w) {
                DRAWCIRC(radec, POSX(prev_xm, prev_sub), POSY(prev_ym, prev_sub));
            }
            if (w == width_w) {
                for (z = min( prev_sub1, prev_sub2); z <= max( prev_sub1, prev_sub2); z++) {
                    DRAWCIRC(radec, POSX(prev_xm, z), POSY(prev_ym, z));
                }
            }
            DRAWCIRC(w, prev_x, prev_y);
            XmTextSetString( axis3, NULL);
        }
        prev_xm = -1;
        return;
    }

    sprintf( dum, "%g", fvelo[rang]);

    XmTextSetString( axis3, dum);

    if (prev_xm != -1) {
        DRAWCIRC(w, prev_x, prev_y);
    }
    DRAWCIRC(w, x, y);
    prev_x = x;
    prev_y = y;


    ecart = ((float)(Nsubs - 1)) / (vel[Nsubs - 1] - vel[0]);

    xm = zoom * ((float)x / localzoom) / incr;
    ym = zoom * ((float)y / localzoom) / incr;

    if (w == velo_w) {
        sub = (fvelo[rang] - vel[0]) * ecart;

        if (prev_xm != -1) {
            DRAWCIRC(radec, POSX(prev_xm, prev_sub), POSY(prev_ym, prev_sub));
        }
        DRAWCIRC(radec, POSX(xm, sub), POSY(ym, sub));
        prev_xm = xm;
        prev_ym = ym;
        prev_sub = sub;
    }

    if (w == width_w) {
        sub1 = (fvelo[rang] - fwidth[rang] - vel[0]) * ecart;
        sub2 = (fvelo[rang] + fwidth[rang] - vel[0]) * ecart;

        if (prev_xm != -1) {
            for (z = min( prev_sub1, prev_sub2); z <= max( prev_sub1, prev_sub2); z++) {
                DRAWCIRC(radec, POSX(prev_xm, z), POSY(prev_ym, z));
            }
        }
        for (z = min( sub1, sub2); z <= max( sub1, sub2); z++) {
            DRAWCIRC(radec, POSX(xm, z), POSY(ym, z));
        }

        prev_xm = xm;
        prev_ym = ym;
        prev_sub1 = sub1;
        prev_sub2 = sub2;
    }

}

void create_momwidgets( )
{
    if (meanshell == NULL) {

        meanshell = XtVaAppCreateShell( "Mean", "meanshell", topLevelShellWidgetClass, display, NULL);
        XtAddCallback( meanshell, XtNdestroyCallback, (XtCallbackProc) destroy_moment, &mpixmap);

        mean_w =
         XtVaCreateManagedWidget( "mean_w",
                                 xmDrawingAreaWidgetClass,
                                 meanshell,
                                 XmNforeground, whitepix, XmNbackground, blackpix, XmNwidth, zsizex, XmNheight, zsizey, NULL);

        XtAddCallback( mean_w, XmNexposeCallback, (XtCallbackProc) expose_moment, &mpixmap);
        XtRealizeWidget( meanshell);
        set_colormap( meanshell);
    }
    XCopyArea( display, mpixmap, XtWindow( mean_w), gc, 0, 0, zsizex, zsizey, 0, 0);
    XFlush( display);

    if (veloshell == NULL) {

        veloshell = XtVaAppCreateShell( "Velocity", "veloshell", topLevelShellWidgetClass, display, NULL);
        XtAddCallback( veloshell, XtNdestroyCallback, (XtCallbackProc) destroy_moment, &vpixmap);

        velo_w =
         XtVaCreateManagedWidget( "velo_w",
                                 xmDrawingAreaWidgetClass,
                                 veloshell, XmNforeground, whitepix, XmNbackground, blackpix, XmNwidth, zsizex, XmNheight, zsizey,
                                 /*
                                    XmNtranslations,
                                    XtParseTranslationTable( mom_translations),
                                  */
                                 NULL);
        XtVaSetValues( velo_w, XmNtranslations, XtParseTranslationTable( mom_translations), NULL);

        XtAddCallback( velo_w, XmNexposeCallback, (XtCallbackProc) expose_moment, &vpixmap);
        XtRealizeWidget( veloshell);
        set_colormap( veloshell);
    }
    XCopyArea( display, vpixmap, XtWindow( velo_w), gc, 0, 0, zsizex, zsizey, 0, 0);
    XFlush( display);

    if (widthshell == NULL) {

        widthshell = XtVaAppCreateShell( "Width", "widthshell", topLevelShellWidgetClass, display, NULL);
        XtAddCallback( widthshell, XtNdestroyCallback, (XtCallbackProc) destroy_moment, &wpixmap);

        width_w =
         XtVaCreateManagedWidget( "width_w",
                                 xmDrawingAreaWidgetClass,
                                 widthshell, XmNforeground, whitepix, XmNbackground, blackpix, XmNwidth, zsizex, XmNheight, zsizey,
                                 /*
                                    XmNtranslations,
                                    XtParseTranslationTable( mom_translations),
                                  */
                                 NULL);

        XtVaSetValues( width_w, XmNtranslations, XtParseTranslationTable( mom_translations), NULL);

        XtAddCallback( width_w, XmNexposeCallback, (XtCallbackProc) expose_moment, &wpixmap);

        XtRealizeWidget( widthshell);
        set_colormap( widthshell);
    }
    XCopyArea( display, wpixmap, XtWindow( width_w), gc, 0, 0, zsizex, zsizey, 0, 0);
    XFlush( display);

}

void AffImage( float *fimage, Drawable drawable, int sx, int sy, int xmin, int xmax, int ymin, int ymax, int scalex, int scaley,
              float clipdeb, float clipfin, int incr, int src_x, int src_y, int dest_x, int dest_y, int width, int height)
{
    char *sdata;

    sdata = (char *)malloc( sx * sy * sizeof( char));

    _2DfloatTo2Dbyte( fimage, xmin, xmax, ymin, ymax, sdata, scalex, scaley, clipdeb, clipfin, incr);
    AffPixmap( sdata, drawable, sx, sy, src_x, src_y, dest_x, dest_y, width, height);

    free( sdata);
}

