;******************************************************************************
;
    PRO TVZOOM_EVENT, EVENT
;
    COMMON TVZOOM_COMMON,XX0,YY0,XX1,YY1,ZOOM_WINDOW,ZOOMED_IMAGE
;
    WIDGET_CONTROL, GET_UVALUE=VALUE, EVENT.ID
    IF VALUE EQ 'Zoom' THEN BEGIN
        XX0 = EVENT.X0
        YY0 = EVENT.Y0
        XX1 = EVENT.X1
        YY1 = EVENT.Y1
        WIDGET_CONTROL, GET_VALUE=ZOOMED_IMAGE, EVENT.ID
        WIDGET_CONTROL, /DESTROY, EVENT.TOP
    ENDIF
;
    END
;
;******************************************************************************
;               Main TVZOOM procedure.
;******************************************************************************
;
    PRO TVZOOM, IMAGE, X0, X1, Y0, Y1, XSIZE=XS, YSIZE=YS, FACT=FACT, $
        INTERP=INTERP, CONTINUOUS=CONT, NOSCALE=NOSCALE,    $
        MISSING=MISSING, MAX=MAX, MIN=MIN, TOP=TOP, BOTTOM=BOTTOM, $
        VELOCITY=VELOCITY, COMBINED=COMBINED, LOWER=LOWER, KEEP=KEEP, $
        ZOOM_WINDOW=ZOOM_WIN,NEW_WINDOW=NEW_WIN,DISABLE=DISABLE, $
        RECURSIVE=RECURSIVE
;
    ON_ERROR,2              ;Return to caller if an error occurs
    COMMON TVZOOM_COMMON,XX0,YY0,XX1,YY1,ZOOM_WINDOW,ZOOMED_IMAGE
;
;  If not passed, then set XSIZE and YSIZE to their default values.
;
    IF N_ELEMENTS(XS) NE 1 THEN XS = 250L
    IF N_ELEMENTS(YS) NE 1 THEN YS = 250L
;
;  Make sure that the ZOOM_WINDOW parameter is defined.  The value -1 stands
;  for no current zoom window.  The NEW_WINDOW keyword forces a new window to
;  be used.
;
    IF KEYWORD_SET(NEW_WIN) THEN ZOOM_WINDOW = -1
    IF N_ELEMENTS(ZOOM_WINDOW) EQ 0 THEN ZOOM_WINDOW = -1
;
;  Make sure that the zoom window does in fact exist.
;
    IF ZOOM_WINDOW GE 0 THEN BEGIN
        DEVICE, WINDOW_STATE=WIN_STATE
        IF NOT WIN_STATE(ZOOM_WINDOW) THEN ZOOM_WINDOW = -1
    ENDIF
;
;  If a zoom window already exists, then get the size of the window.
;
    IF ZOOM_WINDOW GE 0 THEN BEGIN
        OLD_WINDOW = !D.WINDOW
        WSET, ZOOM_WINDOW
        XS = !D.X_SIZE
        YS = !D.Y_SIZE
        WSET, OLD_WINDOW
    ENDIF
;
;  If IMAGE was not passed, then simply call ZOOM.  However, if the graphics
;  device is Microsoft windows, then read the image from the window and use
;  the widget version of TVZOOM on that image.
;
    IF N_PARAMS() EQ 0 THEN BEGIN
        IF !D.NAME EQ 'WIN' THEN BEGIN
            A = TVREAD(DISABLE=DISABLE)
            TVZOOM, A, XSIZE=XS, YSIZE=YS, FACT=FACT,   $
                INTERP=INTERP, CONTINUOUS=CONT, KEEP=KEEP, $
                ZOOM_WINDOW=ZOOM_WIN, NEW_WINDOW=NEW_WIN, $
                /RECURSIVE,/NOSCALE
        END ELSE BEGIN
            TVSELECT, DISABLE=DISABLE
            ZOOM, XSIZE=XS, YSIZE=YS, FACT=FACT, INTERP=INTERP, $
                CONTINUOUS=CONT, KEEP=KEEP, $
                ZOOM_WINDOW=ZOOM_WIN, NEW_WINDOW=NEW_WIN
            TVUNSELECT, DISABLE=DISABLE
        ENDELSE
;
;  Otherwise, if IMAGE was passed, then check the IMAGE array.
;
    END ELSE BEGIN
        S = SIZE(IMAGE)
        IF S(0) NE 2 THEN MESSAGE, 'IMAGE must be two-dimensional.
;
;  Get the scale of the displayed image.  Calculate the reduction value.
;
        IF NOT KEYWORD_SET(RECURSIVE) THEN BEGIN
            GET_TV_SCALE,SX,SY,MX,MY,IX,IY,DISABLE=DISABLE
            IF (SX NE S(1)) OR (SY NE S(2)) THEN MESSAGE,   $
                'IMAGE size does not agree with displayed image'
            REDUCTION = (FLOAT(SX)/MX) > (FLOAT(SY)/MY) > 1
        END ELSE BEGIN
            SX = S(1)
            SY = S(2)
            REDUCTION = 1
        ENDELSE
;
;  Call CW_TVZOOM to display the zoomed image.
;
        IM = IMAGE
        BSCALE,IM,NOSCALE=NOSCALE,MISSING=MISSING,MAX=MAX,MIN=MIN, $
            TOP=TOP,BOTTOM=BOTTOM,VELOCITY=VELOCITY,$
                        COMBINED=COMBINED,LOWER=LOWER
        BASE = WIDGET_BASE(TITLE='TVZOOM',/COLUMN)
        TEXT = 'Exit with "Report Zoom to Parent" button'
        TEMP = WIDGET_TEXT(BASE,VALUE=TEXT,XSIZE=STRLEN(TEXT))
        ZOOMW = CW_TVZOOM(BASE,UVALUE='Zoom',XSIZE=SX,YSIZE=SY, $
            REDUCTION=REDUCTION,SAMPLE=(1-KEYWORD_SET(INTERP)), $
            TRACK=CONT,X_ZSIZE=XS,Y_ZSIZE=YS)
        OLD_WINDOW = !D.WINDOW
        WIDGET_CONTROL,BASE,/REALIZE
        WIDGET_CONTROL,ZOOMW,SET_VALUE=IM
        XMANAGER,'TVZOOM',BASE
        WSET, OLD_WINDOW
;
;  Retrieve the coordinates of the zoomed image.
;
        X0 = XX0
        Y0 = YY0
        X1 = XX1
        Y1 = YY1
;
;  If the KEEP keyword was set, then display the zoomed image in the zoom
;  window.
;
        IF KEYWORD_SET(KEEP) THEN BEGIN
;
;  Store the value of the current window.  If a zoom window hasn't been created
;  yet, then create it.  Otherwise, switch to the zoom window.
;
            OLD_WINDOW = !D.WINDOW
            IF ZOOM_WINDOW LT 0 THEN BEGIN  ;Make new window?
                WINDOW,/FREE,XSIZE=XS,YSIZE=YS, $
                    TITLE='Zoomed Image'
                ZOOM_WINDOW = !D.WINDOW
            ENDIF ELSE BEGIN
                WSET, ZOOM_WINDOW
            ENDELSE
;
;  Display the zoomed image in the window, and reset to the undisplayed window.
;
            TV, ZOOMED_IMAGE
            WSET, OLD_WINDOW
;
;  If KEEP was not set, and a zoom window already exists, then destroy it.
;  This maintains compatibility with the behavior of the standard ZOOM routine.
;
        END ELSE BEGIN
            IF ZOOM_WINDOW GE 0 THEN WDELETE, ZOOM_WINDOW
            ZOOM_WINDOW = -1
        ENDELSE
;
;  Return the index of the zoom window to the user.
;
        ZOOM_WIN = ZOOM_WINDOW
    ENDELSE
;
    RETURN
    END