/*===========================================================================
  Copyright (C) 2001 European Southern Observatory (ESO)

  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.

  Corresponding concerning ESO-MIDAS should be addressed as follows:
    Internet e-mail: midas@eso.org
    Postal address: European Southern Observatory
            Data Management Division 
            Karl-Schwarzschild-Strasse 2
            D 85748 Garching bei Muenchen 
            GERMANY
===========================================================================*/
/* Program  : trimback.c                                                   */
/* Author   : G. Mulas  -  ITAL_FLAMES Consortium                          */
/* Date     :                                                              */
/*                                                                         */
/* Purpose  : Missing                                                      */
/*                                                                         */
/*                                                                         */
/* Input:  see interface                                                   */ 
/*                                                                      */
/* Output:                                                              */
/*                                                                         */
/* DRS Functions called:                                                   */
/* none                                                                    */ 
/*                                                                         */ 
/* Pseudocode:                                                             */
/* Missing                                                                 */ 
/*                                                                         */ 
/* Version  :                                                              */
/* Last modification date: 2002/08/05                                      */
/* Who     When        Why                Where                            */
/* AMo     02-08-05   Add header         header                            */
/*-------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif


/* C functions include files */ 
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/* MIDAS include files */
#include <flames_midas_def.h>
/* FLAMES-UVES include files */ 
#include <flames_uves.h>
#include <flames.h>
#include <flames_freeback.h>
#include <flames_getordpos.h>
#include <flames_dfs.h>
#include <flames_newmatrix.h>
#include <flames_allocback.h>
#include <flames_trimback.h>
#include <uves_msg.h>

flames_err 
trimback(flames_frame *Frame, 
         orderpos *Order, 
         int32_t **wxlow, 
         int32_t **wxup,
         int32_t **wylow, 
         int32_t **wyup,
         scatterswitch2 bkgswitch2,
         int badwinxsize, 
         int badwinysize,
         double badfracthres, 
         int badtotthres)
{
    flames_background *backbuffer=0;
    int32_t i=0, j=0, qq=0;
    int32_t goodwindows=0;

    double yshift=0;
    double belowlimit=0, abovelimit=0;
    double highshift=0, lowshift=0, ordbelow=0, ordabove=0;
    double wcx=0, dtot=0;
    int32_t *Window_x_low=0, *Window_x_up=0, *Window_y_low=0, *Window_y_up=0;
    int32_t *gwindow_x_low=0, *gwindow_x_up=0, *gwindow_y_low=0;
    int32_t *gwindow_y_up=0;
    int32_t scanlowxlim=0, scanupxlim=0, scanlowylim=0, scanupylim=0;
    int32_t badpixels=0;
    int rejectthres=0;
    double pixelsinwindow=0;

    frame_mask *fmvecbuf1=0;
    int32_t ijoffset=0;
    int32_t ijindex=0;

    fmvecbuf1 = Frame->badpixel[0];

    fprintf(stderr, "%d %d "
            "%f %f %f %f %d %d %d %d\n",
            Frame->nflats,
            Frame->maxfibres,
            //          Frame->yshift[0],
            //          Frame->fibremask[0],
            //          Frame->fibremask[1],
            //          Frame->fibremask[2],
            //          Frame->fibremask[3],
            //          Frame->fibremask[4],
            //          Frame->fibremask[5],
            //          Frame->fibremask[6],
            //          Frame->fibremask[7],
            //          Frame->fibremask[8],
            Frame->substepx,
            Frame->substepy,
            Frame->substartx,
            Frame->substarty,
            Frame->subcols,
            Frame->subrows,
            Frame->back.xdegree,
            Frame->back.ydegree);

#if FLAMES_DEBUG
    //  fprintf(stderr, "%d %d %f %d %d %d %d %d %d %d %d %d"
    //          "%f %f %f %f %d %d %d %d\n",
#endif

    /* compute the average yshift of this Science frame, if we can */
    if (Frame->nflats > 0) {
        for (i=0; i<=(Frame->nflats-1); i++) {
            yshift += Frame->yshift[i];
            uves_msg_debug("yshift[%d] = %f\n", i, Frame->yshift[i]);
        }
        yshift /= (double)Frame->nflats;
        uves_msg_debug("yshift = %f\n", yshift);
    }

    /* find the lowest and highest lit fibres in this frame */
    highshift = lowshift = 0;
    j=0;
    for (i=0; i<=(Frame->maxfibres-1); i++) {
        if (Frame->fibremask[i] == TRUE) {
            j++;
            highshift = lowshift = Order->fibrepos[i];

            uves_msg_debug("order->fibrepos[%d] = %f\n", i, Order->fibrepos[i]);
        }
    }
    if (j>0) {
        for (i=0; i<=(Frame->maxfibres-1); i++) {
            uves_msg_debug("fibremask[%d] = %d\n", i, Frame->fibremask[i]);
            if (Frame->fibremask[i] == TRUE) {
                if (Order->fibrepos[i] > highshift) highshift=Order->fibrepos[i];
                if (Order->fibrepos[i] < lowshift) lowshift=Order->fibrepos[i];
            }
        }
        uves_msg_debug("Order->halfibrewidth = %f\n", Order->halfibrewidth);
        highshift += Order->halfibrewidth;
        lowshift -= Order->halfibrewidth;
    }
    else {
        SCTPUT("Warning: no lit fibres in this frame");
    }


    /* correct the highest and lowest fibre limits for the yshift of the frame,
     if already measured */
    highshift += yshift;
    lowshift += yshift;
    /* the order centres were all computed as an average between the lowest
     and highest fibres present in the order/fibre positioning frames; since 
     some of the fibres may be absent in this frame, this results in an 
     effective shift of the orders, and thus of the interorder positions.
     Compute that offset here and put it in yshift */
    yshift = (highshift+lowshift)/2;


    uves_msg_debug(
                    "lowshift, highshift = %f, %f\n",
                    lowshift, highshift);


    /* allocate some local temporary vectors */
    Window_x_low = lvector(1, Frame->back.Window_Number);
    Window_x_up = lvector(1, Frame->back.Window_Number);
    Window_y_low = lvector(1, Frame->back.Window_Number);
    Window_y_up = lvector(1, Frame->back.Window_Number);

    for (qq=1; qq<=Frame->back.Window_Number; qq++) {
        if (((Frame->back.window[qq][3]-Frame->back.window[qq][2]) /
                        fabs(Frame->substepx) < 1) ||
                        ((Frame->back.window[qq][5]-Frame->back.window[qq][4]) /
                                        fabs(Frame->substepy) < 1)) {
            /* la finestra � pi� stretta di un pixel, quindi inutilizzabile */
            //fprintf(stderr, "la finestra � pi� stretta di un pixel, quindi inutilizzabile\n");
            Window_x_low[qq] = 1;
            Window_x_up[qq] = 0;
            Window_y_low[qq] = 1;
            Window_y_up[qq] = 0;
            /* these settings ensure that this window will be skipped */
        }
        else {
            if (Frame->substepx > 0) {
                //              fprintf(stderr, "frame->substepx > 0\n");

                Window_x_low[qq] =
                                (int32_t) ceil((Frame->back.window[qq][2]-Frame->substartx)/
                                                Frame->substepx);
                Window_x_up[qq] =
                                (int32_t) floor((Frame->back.window[qq][3]-Frame->substartx)/
                                                Frame->substepx);
            }
            else {
                Window_x_up[qq] =
                                (int32_t) ceil((Frame->back.window[qq][2]-Frame->substartx)/
                                                Frame->substepx);
                Window_x_low[qq] =
                                (int32_t) floor((Frame->back.window[qq][3]-Frame->substartx)/
                                                Frame->substepx);
            }
            if (Window_x_low[qq]<0) Window_x_low[qq] = 0;
            if (Window_x_up[qq]>(Frame->subcols-1)) Window_x_up[qq]=Frame->subcols-1;
            if ((Window_x_low[qq] > (Frame->subcols-1)) || (Window_x_up[qq] < 0)) {
                /* completely outside frame */
                //fprintf(stderr, "completely outside frame\n");

                Window_x_low[qq] = 1;
                Window_x_up[qq] = 0;
                Window_y_low[qq] = 1;
                Window_y_up[qq] = 0;
                /* these settings ensure that this window will be skipped */
            }
            else {
                if (Frame->substepy > 0) {
                    //                  fprintf(stderr, "Frame->substepy > 0\n");

                    Window_y_low[qq] =
                                    (int32_t)ceil((Frame->back.window[qq][4]-Frame->substarty+yshift)/
                                                    Frame->substepy);
                    Window_y_up[qq] =
                                    (int32_t)floor((Frame->back.window[qq][5]-Frame->substarty+yshift)
                                                    /Frame->substepy);
                }
                else {
                    Window_y_up[qq] =
                                    (int32_t)ceil((Frame->back.window[qq][4]-Frame->substarty+yshift)/
                                                    Frame->substepy);
                    Window_y_low[qq] =
                                    (int32_t)floor((Frame->back.window[qq][5]-Frame->substarty+yshift)
                                                    /Frame->substepy);
                }
                if (Window_y_low[qq]<0) Window_y_low[qq] = 0;
                if (Window_y_up[qq]>(Frame->subrows-1))
                    Window_y_up[qq]=Frame->subrows-1;
                if ((Window_y_low[qq] > (Frame->subrows-1)) || (Window_y_up[qq] < 0)) {
                    /* completely outside frame */
                    //                  fprintf(stderr, "completely outside frame 2\n");
                    Window_x_low[qq] = 1;
                    Window_x_up[qq] = 0;
                    Window_y_low[qq] = 1;
                    Window_y_up[qq] = 0;
                    /* these settings ensure that this window will be skipped */
                }
            }
            if ((Window_y_low[qq]<=Window_y_up[qq]) &&
                            (Window_x_low[qq]<=Window_x_up[qq])) {

                //              fprintf(stderr, "Window_y_low[qq]<=Window_y_up[qq]) && "
                //                      "(Window_x_low[qq]<=Window_x_up[qq])\n");

                ordbelow = floor(Frame->back.window[qq][1]);
                ordabove = ceil(Frame->back.window[qq][1]);

                //              fprintf(stderr, "before  %d %d %d %d  %f %f\n",
                //                      Window_x_low[qq],
                //                      Window_x_up[qq],
                //                      Window_y_low[qq],
                //                      Window_y_up[qq], ordbelow, ordabove);

                for (j=Window_x_low[qq]; j<=Window_x_up[qq]; j++) {
                    /* find the limits of the orders above and below the current
                     window */
                    wcx = (double)j*Frame->substepx+Frame->substartx;
                    flames_err status;
                    if ((status = get_ordpos(Order, ordbelow, wcx, &belowlimit))
                                    !=NOERR) {
                        SCTPUT("Error computing order position");
                        //        SCSEPI();
                        return flames_midas_error(MAREMMA);
                    }
                    if ((status = get_ordpos(Order, ordabove, wcx, &abovelimit))
                                    !=NOERR) {
                        SCTPUT("Error computing order position");
                        //        SCSEPI();
                        return flames_midas_error(MAREMMA);
                    }
                    if (abovelimit < belowlimit) {
                        dtot = belowlimit;
                        belowlimit = abovelimit;
                        abovelimit = dtot;
                    }
                    abovelimit += lowshift; /* find the limit of the lowest lit fibre in
                                             the order above the current window */
                    belowlimit += highshift; /* find the limit of the highest lit fibre
                                              in the order below the current window */
                    /* convert to pixel coordinates */
                    belowlimit = ceil((belowlimit-Frame->substarty)/Frame->substepy);
                    abovelimit = floor((abovelimit-Frame->substarty)/Frame->substepy);
                    /* if necessary, swap them again */
                    if (Frame->substepy < 0) {
                        dtot = belowlimit;
                        belowlimit = abovelimit;
                        abovelimit = dtot;
                    }
                    /* limit the background fitting window to the parts which are not
                     covered by any lit fibres */
                    if (belowlimit > (double) Window_y_low[qq]) {

                        //                      fprintf(stderr, "ylow: %d --> %f\n",
                        //                              Window_y_low[qq], belowlimit);

                        Window_y_low[qq] = (int32_t) belowlimit;

                    }
                    if (abovelimit < (double) Window_y_up[qq]) {

                        //                      fprintf(stderr, "yup: %d --> %f\n",
                        //                              Window_y_up[qq], abovelimit);


                        Window_y_up[qq] = (int32_t) abovelimit;
                    }
                } /* for j */
                /* if this is a good window, in the end, count it as such */
                if (Window_y_low[qq]<=Window_y_up[qq]) goodwindows++;
            } /* if ylow < yup  && xlow < xup */
        } /* else */

        //      fprintf(stderr, "%d %d %d %d\n",
        //              Window_x_low[qq],
        //              Window_x_up[qq],
        //              Window_y_low[qq],
        //              Window_y_up[qq]);

    } /* for qq */

    /* since it is quite possible that a few windows must be skipped according
     to the code above, do check we have some left */
    if (goodwindows==0) {
        SCTPUT("Background estimation1 impossible: no usable windows!\n");
        //    SCSEPI();
        return flames_midas_error(MAREMMA);
    }


    /* put here the background neighborhood bad pixel scanning code */
    /* was neighborhood bad pixel scanning required? */
    switch (bkgswitch2) {
    case FRACBADSCAN:
        /* scan the frame neighborhood for bad pixels */
        goodwindows = 0;
        for (qq=1; qq<=Frame->back.Window_Number; qq++) {
            if ((Window_x_up[qq]>=Window_x_low[qq]) &&
                            (Window_y_up[qq]>=Window_y_low[qq])) {
                if ((scanlowxlim = Window_x_low[qq]-badwinxsize)<0)
                    scanlowxlim = 0;
                if ((scanupxlim = Window_x_up[qq]+badwinxsize)>(Frame->subcols-1))
                    scanupxlim = Frame->subcols-1;
                if ((scanlowylim = Window_y_low[qq]-badwinysize)<0)
                    scanlowylim = 0;
                if ((scanupylim = Window_y_up[qq]+badwinysize)>(Frame->subrows-1))
                    scanupylim = Frame->subrows-1;
                badpixels = 0;
                for (i=scanlowylim; i<=scanupylim; i++) {
                    ijoffset = i*Frame->subcols;
                    for (j=scanlowxlim; j<=scanupxlim; j++) {
                        ijindex = ijoffset+j;
                        if (fmvecbuf1[ijindex] != 0) {
                            /* bad pixel, count it */
                            badpixels++;
                        }
                    }
                }
                /* how many bad pixels did I find, do I exceed the threshold? */
                pixelsinwindow = (double)((scanupylim-scanlowylim+1)*
                                (scanupxlim-scanlowxlim+1));
                rejectthres = (int)ceil(pixelsinwindow*badfracthres);
                if (badpixels<rejectthres) {
                    /* no, good window, keep it */
                    goodwindows++;
                }
                else {
                    /* yes, make sure that this window gets rejected later */
                    Window_x_low[qq] = 1;
                    Window_x_up[qq] = 0;
                    Window_y_low[qq] = 1;
                    Window_y_up[qq] = 0;
                }
            }
        }
        break;
    case ABSBADSCAN:
        /* scan the frame neighborhood for bad pixels */
        goodwindows = 0;
        for (qq=1; qq<=Frame->back.Window_Number; qq++) {
            if ((Window_x_up[qq]>=Window_x_low[qq]) &&
                            (Window_y_up[qq]>=Window_y_low[qq])) {
                if ((scanlowxlim = Window_x_low[qq]-badwinxsize)<0)
                    scanlowxlim = 0;
                if ((scanupxlim = Window_x_up[qq]+badwinxsize)>(Frame->subcols-1))
                    scanupxlim = Frame->subcols-1;
                if ((scanlowylim = Window_y_low[qq]-badwinysize)<0)
                    scanlowylim = 0;
                if ((scanupylim = Window_y_up[qq]+badwinysize)>(Frame->subrows-1))
                    scanupylim = Frame->subrows-1;
                badpixels = 0;
                for (i=scanlowylim; i<=scanupylim; i++) {
                    ijoffset = i*Frame->subcols;
                    for (j=scanlowxlim; j<=scanupxlim; j++) {
                        ijindex = ijoffset+j;
                        if (fmvecbuf1[ijindex] != 0) {
                            /* bad pixel, count it */
                            badpixels++;
                        }
                    }
                }
                /* how many bad pixels did I find, do I exceed the threshold? */
                if (badpixels<badtotthres) {
                    /* no, good window, keep it */
                    goodwindows++;
                }
                else {
                    /* yes, make sure that this window gets rejected later */
                    Window_x_low[qq] = 1;
                    Window_x_up[qq] = 0;
                    Window_y_low[qq] = 1;
                    Window_y_up[qq] = 0;
                }
            }
        }
        break;
    default:
        /* we should never arrive here, unless an unsupported bad pixel
       scanning method was selected */
        SCTPUT("Error: unsupported naighborhood bad pixel scanning method");
        SCTPUT("Falling back to no scanning before background fitting");
    case NOBADSCAN:
        /* nothing to do here */
        break;
    }

    /* since it is quite possible that a few windows must be skipped according
     to the code above, do check we have some left */
    if (goodwindows==0) {
        SCTPUT("Background estimation2 impossible: no usable windows after \
neighborhood bad pixel scanning!\n");
        return flames_midas_error(MAREMMA);
    }

    /* build an updated background structure, with only the windows we kept
     so far and the trimmed limits */
    if (!(backbuffer = calloc(1, sizeof(flames_background)))) {
        SCTPUT("Allocation error during the allocation of new backbuffer structure");
        //    SCSEPI();
        return flames_midas_error(MAREMMA);
    }
    backbuffer->Window_Number = goodwindows;
    backbuffer->xdegree = Frame->back.xdegree;
    backbuffer->ydegree = Frame->back.ydegree;
    if (allocback(backbuffer) != NOERR) {
        /* problems allocating the background buffer */
        SCTPUT("Error allocating the background buffer");
        //    SCSEPI();
        return flames_midas_error(MAREMMA);
    }

    gwindow_x_low = lvector(1, goodwindows);
    gwindow_x_up = lvector(1, goodwindows);
    gwindow_y_low = lvector(1, goodwindows);
    gwindow_y_up = lvector(1, goodwindows);

    /* Ok, now rebuild backbuffer, remembering it is in world coordinates;
     duplicate some code to avoid checks inside the loops */
    goodwindows = 0;
    if (Frame->substepx>0) {
        if (Frame->substepy>0) {
            for (qq=1; qq<=Frame->back.Window_Number; qq++) {
                if ((Window_x_up[qq]>=Window_x_low[qq]) &&
                                (Window_y_up[qq]>=Window_y_low[qq])) {
                    goodwindows++;
                    gwindow_x_up[goodwindows]=Window_x_up[qq];
                    gwindow_x_low[goodwindows]=Window_x_low[qq];
                    gwindow_y_up[goodwindows]=Window_y_up[qq];
                    gwindow_y_low[goodwindows]=Window_y_low[qq];
                    backbuffer->x[goodwindows] = Frame->back.x[qq];
                    backbuffer->y[goodwindows] = Frame->back.y[qq];
                    backbuffer->window[goodwindows][1] = Frame->back.window[qq][1];
                    backbuffer->window[goodwindows][2] =
                                    ((double)Window_x_low[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][3] =
                                    ((double)Window_x_up[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][4] =
                                    ((double)Window_y_low[qq]+Frame->substarty)/Frame->substepy;
                    backbuffer->window[goodwindows][5] =
                                    ((double)Window_y_up[qq]+Frame->substarty)/Frame->substepy;
                }
            }
        }
        else {
            for (qq=1; qq<=Frame->back.Window_Number; qq++) {
                if ((Window_x_up[qq]>=Window_x_low[qq]) &&
                                (Window_y_up[qq]>=Window_y_low[qq])) {
                    goodwindows++;
                    gwindow_x_up[goodwindows]=Window_x_up[qq];
                    gwindow_x_low[goodwindows]=Window_x_low[qq];
                    gwindow_y_up[goodwindows]=Window_y_up[qq];
                    gwindow_y_low[goodwindows]=Window_y_low[qq];
                    backbuffer->x[goodwindows] = Frame->back.x[qq];
                    backbuffer->y[goodwindows] = Frame->back.y[qq];
                    backbuffer->window[goodwindows][1] = Frame->back.window[qq][1];
                    backbuffer->window[goodwindows][2] =
                                    ((double)Window_x_low[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][3] =
                                    ((double)Window_x_up[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][5] =
                                    ((double)Window_y_low[qq]+Frame->substarty)/Frame->substepy;
                    backbuffer->window[goodwindows][4] =
                                    ((double)Window_y_up[qq]+Frame->substarty)/Frame->substepy;
                }
            }
        }
    }
    else {
        if (Frame->substepy>0) {
            for (qq=1; qq<=Frame->back.Window_Number; qq++) {
                if ((Window_x_up[qq]>=Window_x_low[qq]) &&
                                (Window_y_up[qq]>=Window_y_low[qq])) {
                    goodwindows++;
                    gwindow_x_up[goodwindows]=Window_x_up[qq];
                    gwindow_x_low[goodwindows]=Window_x_low[qq];
                    gwindow_y_up[goodwindows]=Window_y_up[qq];
                    gwindow_y_low[goodwindows]=Window_y_low[qq];
                    backbuffer->x[goodwindows] = Frame->back.x[qq];
                    backbuffer->y[goodwindows] = Frame->back.y[qq];
                    backbuffer->window[goodwindows][1] = Frame->back.window[qq][1];
                    backbuffer->window[goodwindows][3] =
                                    ((double)Window_x_low[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][2] =
                                    ((double)Window_x_up[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][4] =
                                    ((double)Window_y_low[qq]+Frame->substarty)/Frame->substepy;
                    backbuffer->window[goodwindows][5] =
                                    ((double)Window_y_up[qq]+Frame->substarty)/Frame->substepy;
                }
            }
        }
        else {
            for (qq=1; qq<=Frame->back.Window_Number; qq++) {
                if ((Window_x_up[qq]>=Window_x_low[qq]) &&
                                (Window_y_up[qq]>=Window_y_low[qq])) {
                    goodwindows++;
                    gwindow_x_up[goodwindows]=Window_x_up[qq];
                    gwindow_x_low[goodwindows]=Window_x_low[qq];
                    gwindow_y_up[goodwindows]=Window_y_up[qq];
                    gwindow_y_low[goodwindows]=Window_y_low[qq];
                    backbuffer->x[goodwindows] = Frame->back.x[qq];
                    backbuffer->y[goodwindows] = Frame->back.y[qq];
                    backbuffer->window[goodwindows][1] = Frame->back.window[qq][1];
                    backbuffer->window[goodwindows][3] =
                                    ((double)Window_x_low[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][2] =
                                    ((double)Window_x_up[qq]+Frame->substartx)/Frame->substepx;
                    backbuffer->window[goodwindows][5] =
                                    ((double)Window_y_low[qq]+Frame->substarty)/Frame->substepy;
                    backbuffer->window[goodwindows][4] =
                                    ((double)Window_y_up[qq]+Frame->substarty)/Frame->substepy;
                }
            }
        }
    }

    /* free the old back structure */
    if (freeback(&(Frame->back)) != NOERR) {
        /* problems freeing old background internals */
        SCTPUT("Error freeing old background internals");
        //    SCSEPI();
        return flames_midas_error(MAREMMA);
    }


    /* free the local arrays */
    free_lvector(Window_x_low, 1, Frame->back.Window_Number);
    free_lvector(Window_x_up, 1, Frame->back.Window_Number);
    free_lvector(Window_y_low, 1, Frame->back.Window_Number);
    free_lvector(Window_y_up, 1, Frame->back.Window_Number);

    /* put the new back structure in place */
    Frame->back.Window_Number = goodwindows;
    Frame->back.x = backbuffer->x;
    Frame->back.y = backbuffer->y;
    Frame->back.window = backbuffer->window;
    Frame->back.coeff = backbuffer->coeff;
    Frame->back.expon = backbuffer->expon;

    /* free the unneeded buffer */
    free(backbuffer);

    /* fill in return values */
    *wxlow=gwindow_x_low;
    *wxup=gwindow_x_up;
    *wylow=gwindow_y_low;
    *wyup=gwindow_y_up;

    return NOERR;

}
