 ;===============================================================================
subr cop_out
 ;;savepositions
 ;don't save on exit, we now do an explicit one from a menu item
 exit
 endsubr
 ;========================================================
func strmatchesone(s, stest)
 ;returns index of first match if s matches one of the strings in stest
 ;and -1 otherwise, works best if no strings are subsets of others 
 if isstring(s) ne 1 then return, -1
 if isstrarr(stest) then {
   n = num_elem(stest)
   for i=0,n-1 do {
     if s eq stest(i) eq 1 then return, i
   }
   ;no match (or we wouldn't get here) so return -1
   return, -1
 } else if isstring(stest) then {
   if strpos(s, test) ge 0 then return, 0 else return, -1
 } else return, -1
 endfunc
 ;===============================================================================
subr scanpositions, w, label, ix, iy
 ;ix and iy will be unchanged if the label is not found in the list
 if defined($widgetlabels) eq 0 then {
   ;not defined yet? start it up
   ;;ty,'not defined case'
   $widgetlabels = strarr(1)  $widgetprops = zero(lonarr(3, 1))
   $widgetlabels(0) = label    $widgetprops(2,0) = w  ;set label and ID
   return 
 }
 ;check if in the current list
 i =  strmatchesone(label, $widgetlabels)
 ty,'scanpositions i = ', i, '  label = ', label
 if i ge 0 then {
   ty,'found case'
   ix = $widgetprops(0, i)  iy = $widgetprops(1, i)
   ;set the widget ID for this session
   $widgetprops(2,i) = w
   ;;ty,'stored ix, iy = ', ix, iy
 } else {
   ty,'not found case'
   ;we have to extend the list
   if isscalar(ix) eq 0 or isscalar(iy) eq 0 then { ix = 0  iy = 0 }
   ;;ty,'extending widget properties list'
   $widgetlabels = [$widgetlabels, label]
   $widgetprops = [$widgetprops, [ix,iy,w]]
 }
 endsubr
 ;===============================================================================
subr savepositions
 ;scan the list and check location of anything that got registered, these
 ;will have the positions updated
 s = getenv('ANA_PREFERRED_POSITIONS')
 if num_elem(s) le 0 then s = 'anapositions.txt'
 lun = get_lun()
 stat = openw(lun, s)
 if stat ne 1 then { ty, 'error saving widget positions!'  return }
 n = num_elem($widgetlabels)
 for i=0,n-1 do {
   w = $widgetprops(2,i)
   ;find the current whereabouts if widget was used
   if (w gt 0) then xmgetwidgetposition, w, ix, iy else {
     ix = $widgetprops(0,i)  iy = $widgetprops(1,i)
   }
   ;;ty,sprintf('position for widget %d (%s) is: (%d, %d)', w, $widgetlabels(i), ix,iy)
   printf, lun, sprintf('%s %d %d', $widgetlabels(i), ix, iy)
 }
 close, lun
 endsubr
 ;===============================================================================
subr popup
 win = $radio_button
 if $radio_state then {
 $current_window = win
 if defined(eval('$viewer'+string(win))) eq 1 then {
 	xtpopup, eval('$viewer'+string(win)) }
 }
 endsubr
 ;==============================================================
subr view_recompute, win
 ;used when zooming or changing orientation, don't use the re_size callback
 ;for these functions because of recursion and other problems
 ;here the window size has not been changed but we may need to adjust it
 ;the xmsize will call the resize callback
 xwin, win
 ;;ty,'current size =', (!ixhigh+1), (!iyhigh+1)
 nx = $view_nx(win)
 ny = $view_ny(win)
 zm = $view_zoom_fac(win)
 ;ty,'zoom, win =', zm, win
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 ;3/28/2000 - for the connected windows, we need to use another measure for
 ;the max size, think this was causing some of the instabilities
 ;are we part of a connected set of views ?
 if $view_connect(win) then {
   nxs = $view_super_nx
   nys = $view_super_ny
   if $view_order(win) ge 4 then { switch, nxs, nys }
 } else {  nxs = nx  nys = ny }
 draw_x = fix((!ixhigh+1)/zm)<nxs
 draw_y = fix((!iyhigh+1)/zm)<nys
 $view_width(win) = draw_x
 $view_height(win) = draw_y
 ;also need to check ix and iy, try to keep center the same on resize
 ;figure out how the corner will change from center and window size
 ix = ($view_ixc(win) - (draw_x-1)/2) < (nxs - draw_x) > 0
 iy = ($view_iyc(win) - (draw_y-1)/2) < (nys - draw_y) > 0
 ;;ty,'new ix, iy in view_recompute = ', ix, iy
 $view_ix(win) = ix
 $view_iy(win) = iy
 xmscrollbarsetvalues, $view_sch(win), ix, nxs, draw_x, .5*draw_x
 xmscrollbarsetvalues, $view_scv(win), iy, nys, draw_y, .5*draw_y
 ;we might have to shrink the window now
 if ((!ixhigh+1) ne fix(draw_x * zm)) or ((!iyhigh+1) ne fix(draw_y * zm)) then
 	{
 	;;ty,'re-sizing to', fix(draw_x * zm), fix(draw_y * zm)
	xmsize, $view_draw(win), fix(draw_x * zm), fix(draw_y * zm)
	}
 view_redraw, win
 endsubr
 ;=========================================================
subr view_resize_cb, win
 ;new size is !ixhigh+1 and !iyhigh+1, have to check if it got too big
 ;as we resize the scroll bars, don't resize the window here but
 ;defer to view_expose_cb
 ;important - do not do a "xwin, win" in this routine because it will
 ;not return the latest values when this is called as an actual callback
 nx = $view_nx(win)
 ny = $view_ny(win)
 zm = $view_zoom_fac(win)
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 ;are we part of a connected set of views ?
 if $view_connect(win) then {
 	nxs = $view_super_nx
 	nys = $view_super_ny
 	if $view_order(win) ge 4 then { switch, nxs, nys }
 	} else {  nxs = nx  nys = ny }
 draw_x = fix((!ixhigh+1)/zm)<nxs
 draw_y = fix((!iyhigh+1)/zm)<nys
 $view_width(win) = draw_x
 $view_height(win) = draw_y
 ;also need to check ix and iy, try to keep center the same on resize
 ;figure out how the corner will change from center and window size
 ix = ($view_ixc(win) - (draw_x-1)/2) < (nxs - draw_x) > 0
 iy = ($view_iyc(win) - (draw_y-1)/2) < (nys - draw_y) > 0
 $view_ix(win) = ix
 $view_iy(win) = iy
 xmscrollbarsetvalues, $view_sch(win), ix, nxs, draw_x, .5*draw_x
 xmscrollbarsetvalues, $view_scv(win), iy, nys, draw_y, .5*draw_y
 ;and do a view_expose_cb if we got smaller in both directions, in
 ;this case there will be no expose callback
 ;and strange results when shrinking windows
 smaller = 1
 if $view_xsize(win) le (!ixhigh+1) then smaller = 0
 if $view_ysize(win) le (!iyhigh+1) then smaller = 0
 $view_xsize(win) = (!ixhigh+1)
 $view_ysize(win) = (!iyhigh+1)
 ;if a movie window, put the size in the title
 if win ge #play_window and win lt 20 then {
  sq = sprintf('movie window (%s)   %dx%d', string(win),$view_xsize(win),$view_ysize(win)
  xmsettitle,eval('$viewer'+string(win)), sq
 }
 if smaller then view_expose_cb, win
 endsubr
 ;==============================================================
subr view_fullsize, win
 ;used to maximize a window to full size, a little complicated because of connections
 ;and zooms
 zm = $view_zoom_fac(win)
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 ;3/28/2000 - bug fixed for connected views, in this case the max view size is
 ;given by $view_super_nx, etc
 nx = $view_nx(win)
 ny = $view_ny(win)
 ;are we part of a connected set of views ?
 if $view_connect(win) then {
 	nxs = $view_super_nx
 	nys = $view_super_ny
 	if $view_order(win) ge 4 then { switch, nxs, nys }
 	} else {  nxs = nx  nys = ny }
 iq = fix(nxs*zm)
 !ixhigh = iq -1
 iq = fix(nys*zm)
 !iyhigh = iq -1

 if zm gt 1 then {
   iq = (!ixhigh+1)%zm
   !ixhigh = (!ixhigh-iq)>0
   iq = (!iyhigh+1)%zm
   !iyhigh = (!iyhigh-iq)>0
 }
 ;but make smaller than full screen size minus 100
 !ixhigh = !ixhigh < (!screen_width - 100)
 !iyhigh = !iyhigh < (!screen_height - 100)
 xmsize, $view_draw(win), !ixhigh+1, !iyhigh+1
 view_redraw, win
 
 endsubr
 ;==============================================================
subr view_expose_cb, win
 ;if we get called here before the view is finished setting up, just return
 if $view_exists(win) eq 0 then { ty,'not ready for expose' return }
 ;if too big, do a resize on the drawing area to punch it back down
 ;also make the size a multiple of the zoom factor
 rflag = 0
 zm = $view_zoom_fac(win)
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 ;3/28/2000 - bug fixed for connected views, in this case the max view size is
 ;given by $view_super_nx, etc
 nx = $view_nx(win)
 ny = $view_ny(win)
 ;are we part of a connected set of views ?
 if $view_connect(win) then {
 	nxs = $view_super_nx
 	nys = $view_super_ny
 	if $view_order(win) ge 4 then { switch, nxs, nys }
 	} else {  nxs = nx  nys = ny }
 iq = fix(nxs*zm)
 if !ixhigh ge iq then { !ixhigh = iq -1  rflag = 1 }
 iq = fix(nys*zm)
 if !iyhigh ge iq then { !iyhigh = iq -1  rflag = 1 }

 if zm gt 1 then {
   iq = (!ixhigh+1)%zm
   if iq ne 0 then { !ixhigh = (!ixhigh-iq)>0  rflag =1 }
   iq = (!iyhigh+1)%zm
   if iq ne 0 then { !iyhigh = (!iyhigh-iq)>0  rflag =1 }
 }
 
 if rflag then xmsize, $view_draw(win), !ixhigh+1, !iyhigh+1
 view_redraw, win
 endsubr
 ;==============================================================
subr view_input_cb, win
 ;;ty,'win =', win
 ;;ty,'!ix,!iy,!root_x, !root_y=', !ix,!iy,!root_x, !root_y
 ;;ty,'!button,!keycode,!keystate,!keysym =', !button,!keycode,!keystate,!keysym
 if $link_pending eq 1 then {
   ty,smap(byte(7))
   $link_pending = 0
   $link_window = win
   execute, $link_action
   return
 }
 ;check for defined key actions, use keycode to get keypress and not keyrelease
 if !keycode then {
    if !keysym eq 88 or !keysym eq 120 then {
     ;a "x", blow up the window to max size
     view_fullsize, win
     return
    }
    if !keysym eq 66 or !keysym eq 98 then {
     ;a "b", pop the main browser tool
     xtpopup, $browsermain
     return
    }
     if !keysym eq 70 or !keysym eq 102 then {
     ;a "f", pop the file viewer 0 if defined
     if defined($fs0) then xtpopup,$fs0 
     return
    }
   if !keysym eq 84 or !keysym eq 116 then {
     ;a "t", pop the mouse tracker
      w = mouse_widget()
      xmtextfieldsetstring, $mousetext1, string(win)
     return
    }
    if !keysym eq 77 or !keysym eq 109 then {
    ;a "m", pop the colormap for this window
     w = screen_widget()
     xmposition, w, !root_x, !root_y
     xtpopup, w
     xmposition, w, !root_x, !root_y
     if defined($screenwidgetwtext) then
   	  xmtextfieldsetstring, $screenwidgetwtext, string(win)
    }
    
   ;some are just for movies, this assumes 15 - 19 are movie windows
   if win ge #play_window and win le 19 then {
     if !keycode eq 132 then singlestep, 1
     if !keycode eq 131 then singlestep, -1
   } else {
     if !keysym eq 82 or !keysym eq 114 then {
      ;a "r", do an redraw for this window
       erase, win
       view, win
      }
     if !keysym eq 99 or !keysym eq 67 then {
      ;a "c", do a connect for this window
       viewsetconnect_on, win
      }
     if !keysym eq 100 or !keysym eq 68 then {
      ;a "d", do a disconnect for this window
       viewsetconnect_off, win
      }
     if !keysym eq 101 or !keysym eq 69 then {
      ;a "e", do an erase for this window
       erase, win
      }
     if !keysym eq 83 or !keysym eq 115 then {
      ;a "s", do a despike for this window
       viewdespike_cb, win
      }
     if !keysym eq 78 or !keysym eq 110 then {
      ;a "n", do a noise (EMI) removal for this window
       viewemi_cb, win
      }
     if !keysym eq 104 or !keysym eq 72 then {
      ;a "h", hide!
      xtpopdown,  eval('$viewer'+string(win))
      }
     if !keysym eq 76 or !keysym eq 108 then {
      ;a "l", toggle the info text box (manage or unmanage)
      info_box_hide_toggle, win
      }
    }
 } else  {
 ncase !button
   return
   {
     ;these are left button (button 1) actions
     ;for a movie, do a stop/start toggle (unless we are slicing)
     if $view_cb_case(win) eq -1 then return
     
     ncase $view_cb_case(win)
       if win ge #play_window and win le 19 then {
	 if $mv_click_flag eq 0 then return
	 if (#playing_flag ne 0) then {#pause_flag=1 #playing_flag=0} else  play,$data15,0
	 return }
       track_select_pt, win
       track_modify_pt, win
       track_mark_pt, win
       track_group_pt, win
       { !motif = 0	$view_cb_case(win) = 0 }	;used for a wait
       sdisk_mark, win				;6
       sppath_mark_pt, win				;7 for SP path
       tpath_mark_pt, win				;8 for t slice path
     endcase
   }
   {
     ;these are button 2 actions
     ncase $view_cb2_case(win)
       return
     endcase
   }
   {
     ;these are button 3 actions
     ncase $view_cb3_case(win)
       return
       sp_point_profile, win, !ix, !iy		;1 sp point profile
       sppath_end				;2 ends a SP path
       tpath_end				;3 ends a t slice path
     endcase
   }
   {
     ;these are button 4 actions
     ;go forward a frame for a movie window
     if win ge #play_window and win le 19 then { singlestep, 1  return }
     if win eq $blink_win then { blink_callback, 0  return }
     ncase $view_cb4_case(win)
       return
     endcase
   }
   {
     ;these are button 5 actions
     ;go backward a frame for a movie window
     if win ge #play_window and win le 19 then { singlestep, -1  return }
     if win eq $blink_win then { blink_callback, 1  return }
     ncase $view_cb5_case(win)
       return
     endcase
   }
 endcase
 }
 endsubr
 ;==============================================================
subr viewsp_input_cb, win
 ;2/27/2008 - an alternate version for SP slice views with some specialized
 ;feedbacks
 ;;ty,'win =', win
 ;;ty,'!ix,!iy,!root_x, !root_y=', !ix,!iy,!root_x, !root_y
 ;;ty,'!kb,!keycode,!keystate,!keysym =', !button,!keycode,!keystate,!keysym
 if $link_pending eq 1 then {
 ty,smap(byte(7))
 $link_pending = 0
 $link_window = win
 execute, $link_action
 return
 }
 ;check for defined key actions, use keycode to get keypress and not keyrelease
 if !keycode then {
   if !keysym eq 82 or !keysym eq 114 then {
    ;a "r", do an redraw for this window
     erase, win
     view, win
    }
    if !keysym eq 84 or !keysym eq 116 then {
     ;a "t", pop the main tool
     xtpopup, $browsermain
     return
    }
   if !keysym eq 77 or !keysym eq 109 then {
    ;a "m", pop the colormap for this window
     w = screen_widget()
     xmposition, w, !root_x, !root_y
     xtpopup, w
     xmposition, w, !root_x, !root_y
     if defined($screenwidgetwtext) then
   	  xmtextfieldsetstring, $screenwidgetwtext, string(win)
    }
    ;don't support connect/disconnect
   if !keysym eq 101 or !keysym eq 69 then {
    ;a "e", do an erase for this window
     erase, win
    }
    ;don't support despike, noise removal
   if !keysym eq 104 or !keysym eq 72 then {
    ;a "h", hide!
    xtpopdown,  eval('$viewer'+string(win))
    }
   if !keysym eq 76 or !keysym eq 108 then {
    ;a "l", toggle the info text box (manage or unmanage)
    info_box_hide_toggle, win
    }
 } else {

 ncase !button
   return
   {
     iw = !ix % 112
     $spxywaveindex = iw
     xmtextsetstring, $viewts_text_widgets(0, win), string($spxywaveindex)
     ;we need to check for wsum and mirror
     spgetwsum, win
     sbxyw_cubeload_cb
     ;;$spxylineindex = !iy
     spdrawindex, win, iw, !iy
     spdrawslices, win, !iy
     spdrawprofile, win, !iy
   }
   {
     ;these are button 2 actions
     ncase $view_cb2_case(win)
       return
     endcase
   }
   {   
     ;these are button 3 actions
     ncase $view_cb3_case(win)
       return
       sp_point_profile, win, !ix, !iy
       sppath_end				;2 ends a SP path
     endcase
   }
   {
     ;these are button 4 actions
     ncase $view_cb4_case(win)
       return
       spwindexup_cb, win
       spsindexup_cb, win
     endcase
   }
   {
     ;these are button 5 actions
     ncase $view_cb5_case(win)
       return
       spwindexdn_cb, win
       spsindexdn_cb, win
     endcase
   }
 endcase
 }
 endsubr
 ;==============================================================
subr link_setup
 ;just set the flag and action for now, may want to do more later
 $link_pending = 1
 ty,'$link_action =', $link_action
 endsubr
 ;==============================================================
subr view_redraw, win
 ;use tvplane because it handles the offsets and zoom for us
 !tvplanezoom = $view_zoom_fac(win)

 ;need to check if we are coupled with other windows
 ;alignment of multiple movies is done differently and further below

 if $view_connect(win) then { slave_align, win 		return }

 sw = string(win)
 ;need to check if this is a movie window
 if win lt #play_window or win ge 20 then {
   if defined(eval('$viewrangewidget'+sw)) eq 1 then view_range_update, win
   tvplane, eval('$view_data'+sw), 0 , $view_ix(win), $view_iy(win), win
   return
 }

 ;some sort of movie, gets complicated
 j = $now+$j1
 ix = $view_ix(win)
 iy = $view_iy(win)
 ;and there are now 2 types of movies, the old single one and the multi's
 if win eq #play_window then {
   sw = '$data'+sw
   it = $play_index(j)
   ;don't do both the track and the drift
   zeroifnotdefined, $mv_track_flag, $movie_drift_flag
   ;8/18/2000 - modified to handle set of differently sized images, this means
   ;we always use $mv_track_dx and $mv_track_dy but they are loaded with
   ;different values depending on $mv_track_flag
   ix = ix + $mv_track_dx(it)
   iy = iy + $mv_track_dy(it)
   ;don't do both the track and the drift; i.e., the drift can be used only
   ;when solar tracking is off
   if $movie_drift_flag eq 1 and $mv_track_flag eq 0 then {
	  ix = ix + rfix(it * $movie_drift_x)
	  }
   if $mv_align_flag then {  ix = ix + $mv_align_dx(it)  iy = iy + $mv_align_dy(it) }
   tvplane, eval(sw), it, ix, iy, win
   if $decorate_flag then decorateimage, win, it
 } else {
   ;this is for the multi's, we have to find what we need in the set, assumes
   ;that the windows are contiguous
   ;slave alignment is done here for movies sets
   if $multi_link_flags(win - $play_window(1)) then {
     for i=0, $num_movies-1 do {
       if $multi_link_flags(i) then {
	  iq = i + 1 + $play_window(0)
	  if iq ne win then {
	    ;adjust this window (iq) to match win
	    $view_zoom_fac(iq) = !tvplanezoom
	    $view_xsize(iq) = $view_xsize(win)
	    $view_ysize(iq) = $view_ysize(win)
	    $view_ix(iq) = ix
	    $view_iy(iq) = iy
	    draw_x = $view_width(win)
	    $view_width(iq) = draw_x
	    draw_y = $view_height(win)
	    $view_height(iq) = draw_y
	    ;because the xmsize will generally call view_resize_cb, we must get
	    ;the centers done here
	    $view_ixc(iq) = $view_ixc(win)
	    $view_iyc(iq) = $view_iyc(win)
	    xmscrollbarsetvalues, $view_sch(iq), ix, $view_nx(iq), draw_x, .5*draw_x
	    xmscrollbarsetvalues, $view_scv(iq), iy, $view_ny(iq), draw_y, .5*draw_y
	    xmsize, $view_draw(iq), $view_xsize(iq), $view_ysize(iq)
	  }
	 sw = '$movie'+string(i+1)
	 it = $play_multi(j, i)
	 tvplane, eval(sw), it, ix + $multi_track_dx(j, i), iy + $multi_track_dy(j, i), iq
	 if $decorate_flag then decorateimage, iq, it
       }
     }

   } else {
     ;this covers case of an unlinked movie
     iq = win - $play_window(1)
     it = $play_multi(j, iq)
     sw = '$movie'+string(iq+1)
     ix = ix + $multi_track_dx(j, iq)
     iy = iy + $multi_track_dy(j, iq)
     tvplane, eval(sw), it, ix, iy, win
     if $decorate_flag then decorateimage, win, it
   }
 }
 endsubr
 ;==============================================================
subr view_button_save, win
 ;save the current ranges
 wtext = eval('$viewtext'+string(win))
 x1 = fix(xmtextfieldgetstring( wtext(1)))
 y1 = fix(xmtextfieldgetstring( wtext(2)))
 dx = fix(xmtextfieldgetstring( wtext(3)))
 dy = fix(xmtextfieldgetstring( wtext(4)))
 equate, eval('$viewsaverange'+string(win)), [x1,y1,dx,dy]
 endsubr
 ;==============================================================
subr view_button_restore, win
 ;restore the current ranges
 wtext = eval('$viewtext'+string(win))
 if defined(eval('$viewsaverange'+string(win))) eq 0 then {
   equate, eval('$viewsaverange'+string(win)), [0,0,512,512] }
 r = eval('$viewsaverange'+string(win))
 for i=0,3 do xmtextfieldsetstring, wtext(i+1), string(r(i))
 view_button_resize_cb, win
 endsubr
 ;==============================================================
subr view_button_resize_cb, win
 ;resize according to values in text widgets
 ;for connected views, we want this to represent the indices of the array
 ;in win, this can be complicated
 wtext = eval('$viewtext'+string(win))
 x1 = fix(xmtextfieldgetstring( wtext(1)))
 y1 = fix(xmtextfieldgetstring( wtext(2)))
 dx = fix(xmtextfieldgetstring( wtext(3)))
 dy = fix(xmtextfieldgetstring( wtext(4)))
 ;;ty,'view_button_resize_cb, begin with: x1,y1,dx,dy =', x1,y1,dx,dy 
 ;below similar to convertforview but without offset and zoom
 ;3/28/2000 - bug fixed for connected views, in this case the max view size is
 ;given by $view_super_nx, etc
 nx = $view_nx(win)
 ny = $view_ny(win)
 iq = $view_order(win)
 ;check if a transpose
 if iq ge 4 then { switch, x1,y1	switch, dx, dy}
 ;are we part of a connected set of views ?
 if $view_connect(win) then {
 	nxs = $view_super_nx
 	nys = $view_super_ny
 	if iq ge 4 then {  switch, nxs, nys  }
 	} else {  nxs = nx  nys = ny }
 dx = (dx < nxs) > 1	;the cutout could exceed the array size, up to superview
 dy = (dy < nys) > 1
 jq = iq%4
 ;reverse direction of x and y as needed, still in array coordinates so nx,ny
 if jq lt 2 then { y1 = ny-y1-dy }
 if jq%2 eq 1 then { x1 = nx-x1-dx }

 zm = $view_zoom_fac(win)
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 ;now convert to view coordinates, means adjusting by connect offsets
 if $view_connect(win) then {
 	x1 = x1 - $view_connectx(win)
 	y1 = y1 - $view_connecty(win)
  }
 $view_ixc(win) = x1 + (dx-1)/2
 $view_iyc(win) = y1 + (dy-1)/2
 ;ty, '$view_ixc(win), $view_iyc(win) =', $view_ixc(win), $view_iyc(win)
 xmsize, $view_draw(win), fix(dx * zm), fix(dy * zm)
 xtloop, 2
 view_recompute, win
 endsubr
 ;==============================================================
subr maxsize, win
 ;expand to size of view_data but restrict via globals
 nx = $view_nx(win)
 ny = $view_ny(win)
 zm = $view_zoom_fac(win)
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 xmsize, $view_draw(win), fix(nx * zm)<$maxhsize, fix(ny * zm)<$maxvsize
 xtloop, 2
 endsubr
 ;==============================================================
subr view_scrollh_cb, win
 $view_ix(win) = $scroll_value
 xwin, win	;gets window size because we need !ixhigh
 zm = $view_zoom_fac(win)
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 $view_ixc(win) = $scroll_value + (fix((!ixhigh+1)/zm)-1)/2
 view_redraw, win
 endsubr
 ;==============================================================
subr view_scrollv_cb, win
 $view_iy(win) = $scroll_value
 xwin, win	;gets window size because we need !iyhigh
 zm = $view_zoom_fac(win)
 if zm lt 0 then { zm = 1.0/abs(zm) }	;make zm fp, so have to "fix" a lot
 $view_iyc(win) = $scroll_value + (fix((!iyhigh+1)/zm)-1)/2
 view_redraw, win
 endsubr
 ;==============================================================
subr viewzoom_cb, win
 ;the $radio button varies from 0 to 7 corresponding to factors of
 ;0.25, 0.5, 1, 2, 3, 4, 8, 16
 ;only react if state is set on
 if $radio_state then {
   zm = $radio_button - 1
   if zm gt 4 then { if zm eq 5 then zm=8 else if zm eq 6 then zm=16 }
   if zm le 0 then { if zm eq 0 then zm= -2  if zm eq -1 then zm= -4 }
   ;try erasing whenever zooming down to avoid leftover junk when window
   ;doesn't resize to fit (no shrinkwrap)
   if zm lt $view_zoom_fac(win) then erase, win
   $view_zoom_fac(win) = zm
   view_recompute, win
 }
 endsubr
 ;========================================================
subr equate,a,b
 ;just used when the lhs is an evaluated string
 a = b
 endsubr
 ;==============================================================
subr imagemod, a, inx, xq, save
 ;useful when some of the args are evals
 ;this puts some sort of pattern in a using indices inx and value xq
 ;the original contents are put in save for possible restore
 save = a(inx)
 a(inx) = xq
 endsubr
 ;==============================================================
subr re_orient(or1_in, or2_in, win)
 ;;ty,'in re_orient', or1_in, or2_in, win
 ;modified to handle connected sets
 ;this routine should be (carefully) updated to use the newer reorder function
 $view_order(win) = or2_in	;new value
 or1 = or1_in xor 2
 or2 = or2_in xor 2
  ;we assume that these are in the legal 0 to 7 range
 transpose_flag = or1/4 xor or2/4
 ;get reverse parts
 r1 = or1%4	r2 = or2%4
 if transpose_flag then { if r1 eq 1 then r1 = 2 else if r1 eq 2 then r1 = 1 }
 switch, x, eval('$view_data'+string(win))
 reverse_flag = r1 xor r2
 ;;ty, 'reverse_flag, transpose_flag =', reverse_flag, transpose_flag
 if transpose_flag then {
 ;transposes are messier for rectangles,
 x = x(>1,>0)		;transpose
 $view_nx(win) = dimen(x,0)
 $view_ny(win) = dimen(x,1)	;new because of transpose
 xq = $view_ixc(win)		;interchange the centers
 $view_ixc(win) = $view_iyc(win)
 $view_iyc(win) = xq
 }
 ;;ty,'new reverse_flag =',reverse_flag
 if reverse_flag gt 0 then {
 ncase reverse_flag-1
 { x = reverse(x,0)	$view_ixc(win) = dimen(x,0) - $view_ixc(win) }
 { x = reverse(x,1)	$view_iyc(win) = dimen(x,1) - $view_iyc(win) }
 { x = reverse(x,0,1)
 			$view_ixc(win) = dimen(x,0) - $view_ixc(win)
			$view_iyc(win) = dimen(x,1) - $view_iyc(win)
 }
 endcase
 }
 ;are we part of a connected set of views ?
 if $view_connect(win) then {
  if transpose_flag then {
  	xq = $view_connectx(win)
  	$view_connectx(win) = $view_connecty(win)
  	$view_connecty(win) = xq
  	nxs = $view_super_ny
  	nys = $view_super_nx
   } else {
  	nxs = $view_super_nx
  	nys = $view_super_ny
   }
  nx = $view_nx(win)
  ny = $view_ny(win)
  if reverse_flag gt 0 then {
    ncase reverse_flag-1
     {	$view_connectx(win) = nx - nxs - $view_connectx(win)  }
     {	$view_connecty(win) = ny - nys - $view_connecty(win)  }
     {	$view_connectx(win) = nx - nxs - $view_connectx(win)
	$view_connecty(win) = ny - nys - $view_connecty(win)  }
    endcase    
    }

  }

 switch, x, eval('$view_data'+string(win))
 
 ;might be that we always want to re-draw after this but leave out for now
 endsubr
 ;==============================================================
subr set_orient(or1_in, or2_in, win)
 ;this routine should be (carefully) updated to use the newer reorder function
 ;this differs from re_orient in the treatment of ixc, iyc
 ;it is intended for the initial orientation of a newly read image
 ;while maintaining the old ixc, iyc (if possible)
 $view_order(win) = or2_in	;new value
 or1 = or1_in xor 2
 or2 = or2_in xor 2
  ;we assume that these are in the legal 0 to 7 range
 transpose_flag = or1/4 xor or2/4
 ;get reverse parts
 r1 = or1%4	r2 = or2%4
 if transpose_flag then { if r1 eq 1 then r1 = 2 else if r1 eq 2 then r1 = 1 }
 switch, x, eval('$view_data'+ist(win,1))
 reverse_flag = r1 xor r2
 if transpose_flag then {
 ;transposes are messier for rectangles,
 x = x(>1,>0)		;transpose
 $view_nx(win) = dimen(x,0)
 $view_ny(win) = dimen(x,1)	;new because of transpose
 }
 ;ty,'new reverse_flag =',reverse_flag
 if reverse_flag gt 0 then {
 ncase reverse_flag-1
 { x = reverse(x,0) }
 { x = reverse(x,1) }
 { x = reverse(x,0,1) }
 endcase
 }
 switch, x, eval('$view_data'+ist(win,1))
 
 ;note that the effect on connections is not done here since a call to
 ;connect_adjust comes after the set_orient in subr view; it gets done there
 
 endsubr
 ;==============================================================
subr orient_cb, win
 or1 = $view_order(win)		;previous value
 or2 = $option_value
 re_orient, or1, or2, win
 view_recompute, win
 endsubr
 ;==============================================================
subr get_scaling, p, win
 ;3/5/2001 - modified to get all possible scaling parameters, returned in p
 ;9/5/2010 - works for limb using win = $limbwinflag, currently this just gets
 ;p from the current limb enhance widget values, might want to save
 ;for each view, that would be more complicated
 sw = string(win)
 ss = '$imaptext'+sw
 if defined(eval(ss)) eq 0 then {
   p = $default_view_params
 } else {
   xq = eval(ss)
   n = num_elem(xq)
   p = fltarr(n)
   for i = 0,n-1 do p(i) = float(xmtextfieldgetstring(xq(i)))
 }
 endsubr
 ;==============================================================
subr map_limit_adjust, p, et, xsum
 ;exposure compensation with some frills, et is the actual exposure time,
 ;the ref time is included in p, this is very specialized and depends
 ;on various p indices being stable
 etref = p(15)
 sumref = p(19)
 ;don't change anything if etref is nonsense
 if etref gt 0.0 then {
  ;5/17/2002, if the sums are different, so are the pedestals
  if xsum le 1 then ped = p(16) else ped = p(17) ;normally 87 and 110
  if sumref le 1 then pedref = p(16) else pedref = p(17)
  fac = et*xsum*xsum/(etref*sumref*sumref)
  inq = [0,1, 7,8, 10,11,12]
  for i=0,6 do {  j = inq(i)  p(j) = (p(j) - pedref) * fac + ped }
  ;try a noise margin - for cases with low exposures we don't want to emphasize
  ;the noise just above the lower limit, this means increasing the lower limit
  ;(and the upper if necessary) by an amount that increases with fac
  nmargin = p(18)
  if nmargin gt 0 then {
   if fac lt 1.0 then {
    xq = nmargin * (1-fac)
    p(0) += xq   p(1) = p(1) > ( p(0) + 2)    
    p(7) += xq   p(8) = p(8) > ( p(7) + 2)
    p(10) += xq   p(11) = p(11) > ( p(10) + 2)  p(12) = p(12) > ( p(11) + 1)
    }
   }
  }
 endsubr
 ;==============================================================
func ftscsubimage(x, p, type)
 ;used by ftsc for the set of subimages or zones, usually just one, limb enhance
 ;is the first use
 ncase type
   { hbot = p(0)   htop = p(1)   gam = p(2)
     if hbot eq 0 and htop eq 0 then { hbot = min(x)  htop = !lastmax }
     y = pscale(x, hbot, htop, gam)   $trim_range = [hbot, htop]
     }
   { hbot = min(x)  htop = !lastmax gam = p(3)
     y = pscale(x, hbot, htop, gam)   $trim_range = [hbot, htop]
     }
   { hbot = p(4)   htop = p(5)   gam = p(6)
     y = ft(x, hbot, htop, gam)
     }
   { hbot = p(7)   htop = p(8)   gam = p(9)
     y = logimage(x, hbot, htop, gam)
     }
   { bot = p(10)   kink = p(11)  top = p(12)  gam = p(13)
     frac = .01*p(14)
     y = logkink(x,bot,kink,top,gam,frac,$show_gmap)
     ;if a problem in logkink, return all zeroes
     if isscalar(y) then y = zero(x)
     }
   { bot = p(20)  kink = p(21)
      ;this is the atan case
      y = atanscale(x, bot, kink)
     }
 endcase
 $trim_gamma = gam
 return, y
 endfunc
 ;==============================================================
func ftsc(x, win)
 ;returns a scaled byte array version of x, could be either an ft type scaling
 ;or just a specified scale range depending on $view_scaletype parameter
 ;check for mapping info
 zeroifnotdefined, $show_gmap  ;this is used for a plot for logkink
 ;9/5/2010 - upgrade to do limb enhancement as a second zone
 inz0 = 0
 if $viewlimbenhanceflag(win) then {
   xl = limbenhanceapply(x, win, inz0, inz1, y, 0, 0, 1)
   d, xl
   if isarray(xl) then {
     ;now get the p for the limb part
     get_scaling, p, $limbwinflag
     ;need TRACE stuff here for possible p adjustments


     y(inz1) = ftscsubimage(xl, p, $limb_scaletype(win))
     ;check if no disk portion (then we are done)
     if isscalar(inz0) then if inz0 eq -1 then { return, y }
   }
 }
 
 ;get main zone
 get_scaling, p, win
 ;3/5/2001 - p now contains all parameters, which we use depends on scaletype
 sw = string(win)
 ;3/6/2001 - if TRACE data, p may be modified for this image
 if $view_data_type(win) eq 1 and $view_mapaec(win) eq 1 then {
   ;get the reference exposure and this exposure
   et = subsc(eval('$view_trace_info_flt_'+sw),0)
   xsum = subsc(eval('$view_trace_info_int_'+sw),7)
   map_limit_adjust, p, et, xsum
 }
 ;for the main zone, need to check if all or part
 if isscalar(inz0) then {
   y = ftscsubimage(x, p, $view_scaletype(win))
 } else {
   y(inz0) = ftscsubimage(x(inz0), p, $view_scaletype(win))
 }
 return, y
 endfunc
 ;========================================================
func logimage(x, bot, top, gam)
 ;5/20/98 - slow to start with
 if symdtype(x) le 2 then {
 ;integer cases, weed out <= 0
 if bot le 0 then bot = min(x) > 1
 if top le 0 then top = max(x) > 1
 y = alog(float(x) > 1.0)
 } else {
 ;the floats, use min if not 0, otherwise try 1.e-20 for clamp
 if bot le 0 then bot = min(x)
 if top le 0 then top = max(x)
 ;but min(y) could be <= 0
 if bot le 0 then bot = 1.E-20
 ;so could max
 if top le 0 then top = 1.E-20
 y = alog(x > bot)
 }
 $trim_range = [bot, top]
 y = pscale(y, alog(bot), alog(top), gam)
 return, y
 endfunc
 ;========================================================
func logkink(x,bot,kink,top,gam,frac,mode)
 ;a 2 part mapping
 kink = kink < top
 kink = kink > bot
 frac = frac < 1.0
 frac = frac > 0.0
 kq = kink - bot
 type = symdtype(x)
 ;;ty,'bot,kink,top,gam,frac =', bot,kink,top,gam,frac
 ;;if type lt 3 then { 
 ;accept FP cases if n is reasonable
   ;for integer types, just a finite set of cases
   n=abs(top-bot)+1
   if n lt 2 or n gt 50000 then {
     ty,'bad range for kink/log = ', n
     y = zero(x)
     return, y
   }
   g=indgen(fltarr(n))
   g1 = g(0:kq) ^ gam
   ;normalize to the allowed range
   g1 = g1 * (1.0 - frac) /max(g1)
   g2 = g(kq:*)
   g2 = frac * ( alog(g2) - alog(kq) )/(alog(top-bot) - alog(kq))
   g2 = g2 + (1.0 - frac)
   if num_elem(g2) gt 1 then g = [g1, g2(1:*)]
 g=scale(g)
 offset = bot<top
 if top lt bot then g = reverse(g)
 if type eq 1 or type eq 0 then offset=word(rfix(offset))

 if (mode) {
   xport,60,400,400
   plot,indgen(fltarr(num_elem(g)))+offset, g
   xraise,60
 }

 y = g( (x-offset) )
 $gmap = g
 $trim_range = [bot, top]
 
 return, y
 endfunc
 ;========================================================
func atanscale(x, bot, ref)
 ;we don't need a max because defined to infinity but we need to compute
 ;max for the data because we make a lut
 top = max(x)
 if bot le 0 then bot = !lastmin
 $trim_range = [bot, top]
 n=abs(top-bot)+1
 ty,'bot, top, ref, n =', bot, top, ref, n
 ;for integer types, just a finite set of cases
 if n gt 65536 then {
   ty, 'bad range, clipping range to 65536'
   n = 65536
 }
 g=indgen(fltarr(n))
 lut = scale(atan( (g+bot)/ref) )
 y = lut(x - bot)
 return, y
 endfunc
 ;========================================================
func ftsc256(x, win)
 ;used by save and perhaps others, uses ftsc to make a scaled version
 ;of the view from the data like ftsc but uses the 0-255 range for
 ;output
 
 s1 = !scalemin		s2 = !scalemax	!scalemin = 0	!scalemax = 255
 xc = ftsc(x, win)
 !scalemin = s1		!scalemax = s2
 return, xc
 endfunc
 ;========================================================
subr ftsc_mode_cb, win
 ;this doesn't change the views, just changes the option widgets and states
 ;9/4/2010 - add check for $limbwinflag
 ;12/9/2000 - support for 15 user views (didn't notice until now!) from 10
 ;3/22/99 - support for movie mapping via win ge 15
 ;5/20/98 - added log function
 ty,'$option_value =', $option_value
 if win eq $limbwinflag then {
   ;this is an exception that works the limb enhance tool options, here win
   ;is a flag and we have to get the real target win dynamically for $limb_scaletype
   sw = string(win)
   ;just use the $limbwinflag for the widgets
   equate, xq, eval('$imagemaptypeswidget'+sw)
   ;but for the type, we need the target window
   wq = getlimbenhancetarget()
   $limb_scaletype(wq) = $option_value
 } else {
   if win lt $play_window(0) then {
    $view_scaletype(win) = $option_value
    ;change the labels for the type of scaling
    sw = string(win)
   } 
   if win ge $play_window(0) and win le $play_window(4) then {
    sw = string(#play_window)   ;for all of them
    $mv_scaletype = $option_value
    $view_scaletype(#play_window) = $option_value
   }
   equate, xq, eval('$imagemaptypeswidget'+sw)
 }
 n = num_elem(xq)
 ;unmanage them all
 for i=0,n-1 do xtunmanage, xq(i)
 ;manage our guy
 xtmanage, xq($option_value)
 
 endsubr
 ;=============================================================================== 
subr fitCheckKey_cb
 if $radio_state then $inspectsetkey = 1  else $inspectsetkey = 0
 endsubr
 ;=============================================================================== 
subr filekeyword_cb
 ;called from fileinspecwidgettool.ana
 ;used to search a list of FITS keywords in a text box and position to it
 skey = upcase(xmtextfieldgetstring($findKeyText))
 ;;ty, 'skey = ', skey
 nkm = num_elem(skey) - 1
 ;is it really a fits file?
 if $inspectFileType ne 1 then { errormess,'key find is\nonly for FITS files' return}
 ;get the tesxt contents, we assume a lot here about how it was
 ;constructed
 s = xmtextgetstring($fileinspec_t2)
 ;want to allow multiple searches to find the next occurence, so keep a pointer
 zeroifundefined, $keyps
 ;;ty, '$keyps = ', $keyps
 ;restrict to keys by taking only 8 characters after each line feed
 ns = num_elem(s)
 ;;ty,'ns = ', ns
 i1 = $keyps
 if ns gt $keyps then sq = s($keyps:*) else  {  sq = s  i1 = 0 }
 i2 = 0
 while 1 {
   while 1 {
    ;now find the line feed in sq
     j = strpos(sq, '\n')
     ;;ty,'j =', j, ' strlen(sq)-1 =', strlen(sq)-1
     if j lt 0 or j ge (strlen(sq)-1) then break	;this means end of text
     j = j + 1
     i1 = i1 + j
     sq = sq(j:*)
     s3 = sq(0:7)
     ;;ty,'i1,j,s3 =', i1,j,' ',s3
     j = strpos(s3, skey)
     ;;ty,'j =', j
     if j ge 0 then { i1 = i1 + j   i2 = i1 + nkm  break }
     ;not found yet so go on
   }
   ;if we found it then i2 ne 0
   if i2 eq 0 then {
     if $keyps eq 0 then { errormess,'key not found' break }
     ;setup to search again  if we hadn't started from beginning
     $keyps = 0
   } else break
 }
 ;;ty,'i2 =', i2
 $keyps = i2
 ;;ty,'string =', s(i1:i2)
 xmtextsetselection, $fileinspec_t2, i1, i2+1
 return
 endsubr
 ;=============================================================================== 
subr load_file
 ;this is called by the movie list widget, it just determines which window
 ;is selected in the main widget and then calls read_file to read and view it
 ;note that the file name will be in $selected_file
 ;also checks if the $inspect_flag is on
 ;9/27/2003 - this is moved to read_file_current so it works for other file reads
 ;if $inspect_flag eq 1 then {
 ;iq = file_inspect(fns(get_ft($movfrwidget_t1), $fnum))
 ;}
 read_file_current
 endsubr
 ;=============================================================================
subr read_file_current
 if $inspect_flag eq 1 then iq = file_inspect($selected_file)
 read_file, $current_window
 endsubr
 ;=============================================================================
subr update_globals, win, x
 ;update globals                     LS 22nov99
 ;used for file reads via read_file and fdmgtools
 ;4/15/2000 - how we set the times and positions
 ;6/15/2003 - add some options for Solar B if it is a Solar B file
 ; if the data time is 0, it is invalid, just pass to view in either case
 $view_tai(win) = $data_time_tai
 ;if the scale is 0, we have no useful positions or scales, just set to 0
 if $view_data_type(win) eq 5 or $view_data_type(win) eq 6 then {
   ;some fakes for SDO early data
   $data_xcen = 0.0
   $data_ycen = 0.0
   if $data_xscale eq 0 then { $data_xscale = 0.6 $data_yscale = 0.6 }
 }
 $view_sun_pixel_scale(win) = $data_xscale
 if $data_xscale then {
   $view_sun_xc(win) = $data_xcen
   $view_sun_yc(win) = $data_ycen
 } else {
   $view_sun_xc(win) = 0
   $view_sun_yc(win) = 0
 }
 ;save the data in an array named after the window number
 if $view_scaletype(win) eq 6 then $view_scaletype(win) = 2
 switch,x,eval('$data'+string(win))
 ;do we want a despike ?
 if $viewdespikeflag(win) then viewdespike, win
 ;label, put in time and position
 sq = sprintf('%s\n@(%3.1f, %3.1f)" pix %5.3f"', date_from_tai($data_time_tai), -
 	$data_xcen, $data_ycen, $data_xscale)
 ;allow for some special types, Solar B
 if $view_data_type(win) eq 3 then {
   ;for Solar B data
   sq = sq + $solarbstrs
 }
 if $view_data_type(win) eq 5 or $view_data_type(win) eq 6 then {
   ;for HMI data
   sq = sq + $sdostrs
 }
 view, win
 xmtextsetstring, $view_text_widget(win), sq
 endsubr
 ;=============================================================================
subr winplot, win, x
 ;;xwin, -1, 512, 400
 xwin, 47, 512, 400
 if num_dim(x) eq 1 then {
   plot, x, 'index'
 } else {
   ;we expect one of the dimensions to be 2 here and we expect just 2 dimensions
   nx = dimen(x,0)  ny = dimen(x,1)
   if nx eq 2 then plot, x(0,*), x(1,*)
   if ny eq 2 then plot, x(*,0), x(*,1)
 }
 ;save the data in an array named after the window number
 switch,x,eval('$data'+istring(win, 1))
 endsubr
 ;=============================================================================
subr read_file, win
 ;2/12/2008 - use solarbdisplay routine for displaying Solar B SOT images
 ;1/7/2008 - add Solar B info for text box, assumes solarboptions called
 ;12/26/96 don't query about cubes, just load them
 ;11/11/96 remove nan's in fp arrays, may want to make this optional later
 ;usually called by a file selector, name must be in $selected_file
 ;displays an image file
 ;fty=file type = 0 for fz, = 1 for fits
 if xexist(win) eq 1 then xcursor, win, 150
 xflush
 ;open and display the file
 if defined(h) eq 0 then h=''	; or a problem with undefined argument
 if dataread(x, $selected_file, h) eq 1 then {
   ;check for Solar B (just SOT for now)
   if $instrument_type eq 3 then {
     $view_data_type(win) = 3 
     exchange, x, $sbdata
     exchange, h, $sbhead
     $current_window = win
     solarbdisplay, $selected_file, 0
   } else {
     $view_data_type(win) = 0	;or it may act like a previous type
     ;remove any nan's here for F*4 or F*8 data
     if symdtype(x) eq 3 or symdtype(x) eq 4 then zeronans, x
     if symdtype(x) eq 2 then zeronondata, x
     ;;ty,'array dim =', num_dim(x)
     ;symarr's will be 1-D and are caught below with any 3-D data
     nd = num_dim(x)
     if nd ne 2 then {
      ;some exception processing here, so far for cubes and 1-D plots
      ;also have to recognize some Solar B types
      if (nd eq 3 and symdtype(x) eq 0) or issymarr(x) then {
	switch, x, $data15
	;call a professional in toolset4 to finish the movie setup
	mvload_read, $selected_file
      } else if nd eq 1 then {
	;a 1-D array, just plot it in a pixmap and copy to view
	winplot, win, x
      } else {
	;check if it may have a mif type file
	if $multi_image_flag then {
	 iq = mif_open_file($selected_file)
	 } else if nd eq 3 then {
	 ;general 3-D arrays can sometimes be just presented
	 ;via the old "movie" viewer
	 framesetup_3d_fits, $selected_file
	 } else errormess, $mess5
      }
     } else {
      ;nd is 2 but if one of the dimensions is just 2, assume an x/y plot
      nx = dimen(x,0)  ny = dimen(x,1)
      if nx le 2 or ny le 2 then {
	winplot, win, x
      } else {
	;global updates only needed in 2-D image for the current window, don't
	;want to do this for movie files for example
	update_globals, win, x
      }
     }
   }
 } else {
  sq = '\nfile type unknown'
  if filesize($selected_file) lt 0 then sq = '\nfile doesn''t exist'
  errormess, $selected_file+sq
 }
 xcursor, win, 132
 endsubr
 ;=============================================================================
subr load_image, x
 ;displays an image, adapted and simplified from load_file
 ty,'load_image'
 win = $current_window
 if xexist(win) eq 1 then xcursor, win, 150
 xflush
 ;remove any nan's here
 if symdtype(x) ge 3 then zeronans, x
 ;save the data in an array named after the window number
 if $view_scaletype(win) eq 6 then $view_scaletype(win) = 2
 switch,x,eval('$data'+istring(win, 1))
 ;do we want a despike ?
 if $viewdespikeflag(win) then viewdespike, win
 $view_data_type(win) = 0	;or it may act like a previous type
 view, win
 ;clear label, may want to add something about the image eventually
 xmtextsetstring, $view_text_widget(win), ''
 xcursor, win, 132
 endsubr
 ;=============================================================================
subr centerfront, w
 xtmanage, w
 xmgetwidgetsize, w, dx, dy
 ;;ty,'widget size =', dx, dy
 ;;xtpopdown, w
 xmposition, w, (!screen_width-dx)/3, (!screen_height - dy)/3
 ;;xmraise, xtparent(w)
 xtpopup, w
 endsubr
 ;=============================================================================== 
subr finspect
 ;currently just a front end for:
 iq = file_inspect($selected_file)
 endsubr
 ;=============================================================================== 
subr draw_grid, win, nspace
 ;draws a grid by loading lines of the grid color in the $view array and then
 ;doing a view_redraw, this makes a "permanent grid" which can still be erased
 ;by recomputing the $view array
 ;the grid lines are spaced wrt the current origin of the $view array, not the
 ;original data coords., this allows the reference to be from any corner
 ;depending on the view orientation
 nx = $view_nx(win)
 ny = $view_ny(win)
 switch, x, eval('$view_data'+string(win))
 ;first insert the horizontal lines
 xq = zero(bytarr(nx)) + byte(#grid_pixel)
 redim, xq, nx, 1
 iy = nspace
 while (iy lt ny) { insert, x, xq, 0, iy	iy += nspace }
 ;now the vertical, re-use variables
 xq = zero(bytarr(ny)) + byte(#grid_pixel)
 redim, xq, 1, ny
 iy = nspace
 while (iy lt nx) { insert, x, xq, iy, 0	iy += nspace }
 switch, x, eval('$view_data'+string(win))
 view_redraw, win
 endsubr
 ;=============================================================================== 
subr view_destroy, win
 ;destroy the arrays but not the widget, the primary motivation is to recover
 ;the array memory
 $view_exists(win) = 0		;to let other tools know not to use this view
 $view_scaletype(win)= 2	;in case it was a special
 xtpopdown,  eval('$viewer'+string(win))
 equate, eval('$view_data'+string(win)), 0
 equate, eval('$data'+string(win)), 0
 endsubr
 ;=============================================================================== 
subr view_print_old, win
 ;spawns several things to read and print this view
 viq = eval('$viewer'+string(win))
 xmsettitle, viq, 'printing'
 wait, .1
 xtloop, 2
 wait, .1
 spawn, 'xwd -out junk.print -name printing'
 spawn, 'fromxwd junk.print junk.print'
 spawn, 'tops junk.print -rgb  > window.ps'
 spawn, 'glp -s -F window.ps'
 spawn, 'rm -f junk.print'
 xmsettitle, viq, $window_title(win)
 endsubr
 ;=============================================================================== 
subr view_print, win
 ;uses xwd_id to read view and makes a postscript image to print
 viq = eval('$viewer'+string(win))
 xtpopup, viq
 xtloop, 2
 wait, .1
 xtloop, 2
 wait, .1
 xq = xwd_id(xtwindow(viq))
 nx = dimen(xq,1)
 ny = dimen(xq,2)
 !landscape = 0
 pdev, 1, 'window.ps'
 fac = (.7/nx) < (.9/ny)
 x0 = 0.5 * (.75 - nx*fac)
 x1 = x0 + nx*fac
 y0 = 0.5 * (1.0 - ny*fac)
 y1 = y0 + ny*fac
 postcolorimage, xq, x0,x1,y0,y1
 ;also a stamp on the bottom, high enough for 9" printers
 portraitlabel,'TRACE browser '+!time
 ;also put some scaling info at the top (Jake's request)
 y1 = (y1 + 0.01) < 1.0
 postclabel, $window_title(win), .375, y1
 postrel
 pdev, 0
 spawn, 'glp -s -F window.ps'
 if !spawn then {
  errormess,'Problem with glp\nyou may be able to manually\nprint the window.ps file'
 }
 endsubr
 ;=============================================================================== 
subr window_print, win, fname_in
 ;reads a ANA window and generates a postscript file, win is the ANA window
 ;# here, not the X window ID
 if !narg ge 2 then fname = fname_in else fname ='window.ps'
 ;uses xwd to read window and makes a postscript image to print
 xraise, win
 wait, .1
 xq = xwd(win)
 nx = dimen(xq,1)
 ny = dimen(xq,2)
 !landscape = 0
 pdev, 1, fname
 fac = (.7/nx) < (.9/ny)
 x0 = 0.5 * (.75 - nx*fac)
 x1 = x0 + nx*fac
 y0 = 0.5 * (1.0 - ny*fac)
 y1 = y0 + ny*fac
 postcolorimage, xq, x0,x1,y0,y1
 ;also a stamp on the bottom
 portraitlabel,'Window # '+string(win)+' '+!time
 postrel
 pdev, 0
 spawn, 'glp -s -F '+fname
 if !spawn then {
  errormess,'Problem with glp\nyou may be able to manually\nprint the window.ps file'
 }
 endsubr
 ;=============================================================================== 
subr window_to_rgb, win, fname_in
 ;reads a ANA window and generates an SGI rgb file, win is the ANA window
 ;# here, not the X window ID
 if !narg ge 2 then fname = fname_in else fname ='window.rgb'
 ;uses xwd to read window
 xraise, win
 wait, .1
 xq = xwd(win)
 iq = wrt_sgi_rgb(xq(0,*,*), xq(1,*,*), xq(2,*,*), fname)
 if iq ne 1 then errormess,'Problem writing\nSGI rgb file'
 endsubr
 ;=============================================================================== 
subr w2eps
 ;reads a ANA window and generates an eps file, prompt for info
 win = 0
 fname = ''
 read, 'enter window #', win
 read,'enter output file name', fname
 ;uses xwd to read window
 xraise, win
 wait, .1
 xq = xwd(win)
 nx = dimen(xq,1)
 ny = dimen(xq,2)
 !landscape = 0
 pdev, 1, fname
 fac = (.7/nx) < (.9/ny)
 x0 = 0.5 * (.75 - nx*fac)
 x1 = x0 + nx*fac
 y0 = 0.5 * (1.0 - ny*fac)
 y1 = y0 + ny*fac
 postcolorimage, xq, x0,x1,y0,y1
 postrel
 pdev, 0
 endsubr
 ;=============================================================================== 
subr w2eps6
 ;reads a ANA window and generates an eps file, prompt for info
 ;this is a special one for 6 inch prints, eliminate when not needed/understood
 win = 0
 fname = ''
 read, 'enter window #', win
 read,'enter output file name', fname
 ;uses xwd to read window
 xraise, win
 wait, .1
 xq = xwd(win)
 nx = dimen(xq,1)
 ny = dimen(xq,2)
 !landscape = 0
 pdev, 1, fname
 fac = (.6/nx) < (.9/ny)
 x0 = 0.5 * (.75 - nx*fac)
 x1 = x0 + nx*fac
 y0 = 0.5 * (1.0 - ny*fac)
 y1 = y0 + ny*fac
 postcolorimage, xq, x0,x1,y0,y1
 postrel
 pdev, 0
 endsubr
 ;=============================================================================== 
subr printanymode_cb
 if $radio_state then {
 $printanymode = $radio_button
 }
 endsubr
 ;========================================================
subr printany_cb
 change_button_label, $printany_b1, 'click on\ndesired window','red'
 id =xgetwinid()
 change_button_label, $printany_b1, 'working\nplease wait','red'
 ;two ways to try, the straight xwd seems to muck up some types of windows,
 ;the root will show overlays but maybe messes up 16 bit windows on SGI's ?
 xroot_coord_id, id, ix,iy,nx,ny
 ;;xq = xwd_id(id)
 if $browser_win then {
   ix = ix - 7
   nx = nx + 14
   iy = iy -30
   ny = ny + 37
   xq = tvread(ix, iy, nx, ny) 
 } else xq = xwd_root(ix, iy, nx, ny)
 nx = dimen(xq,1)
 ny = dimen(xq,2)
 if $browser_win then {
   $gif_color = xtvrct(#play_window)
   color = $gif_color(0,*)
   red = color(xq)
   green = bytarr(dimen(xq,0), dimen(xq,1))
   color = $gif_color(1,*)
   green = color(xq)
   blue = bytarr(dimen(xq,0), dimen(xq,1))
   color = $gif_color(2,*)
   blue = color(xq)
   rgb =[ [red], [green], [blue]]
   rgb = rgb(>1,>2,>0)
   exchange, xq, rgb
 }
  ncase $printanymode
  fname = 'window.ps'
  fname = xmtextfieldgetstring($printany_text1) + '.eps'
  fname = xmtextfieldgetstring($printany_text2) + '.rgb'
  fname = xmtextfieldgetstring($printany_text3) + '.jpeg'
 endcase
 ;if we are printing or making an eps, the first step is to make an eps
 if $printanymode lt 2 then {
   !landscape = 0
   pdev, 1, fname
   fac = (.7/nx) < (.9/ny)
   x0 = 0.5 * (.75 - nx*fac)
   x1 = x0 + nx*fac
   y0 = 0.5 * (1.0 - ny*fac)
   y1 = y0 + ny*fac
   postcolorimage, xq, x0,x1,y0,y1
   postrel
   pdev, 0
   ;now if printing, we call glp and then delete the file
   if $printanymode eq 0 then {
     spawn, 'glp -s -F '+fname
     if !spawn then {
       errormess,'Problem with glp, but\nyou may be able to manually\nprint the window.ps file'
     }
   }
 } else {
  if $printanymode eq 2 then {
    ;better if we flip it, but maybe not?
    ;;ty,'reversing'
    xq = reverse(xq,2)
    iq = wrt_sgi_rgb(xq(0,*,*), xq(1,*,*), xq(2,*,*), fname)
    if iq ne 1 then errormess,'Problem writing\nSGI rgb file'
    }
  if $printanymode eq 3 then {
    jpeg_options
    if defined($jpeg_quality) eq 0 then $jpeg_quality=75
    iq = write_jpeg(xq, fname, $jpeg_quality)
  
   }
 }
 change_button_label, $printany_b1, 'select and\nprint/save','gray'
 endsubr
 ;========================================================
func printany_widget(dummy)
 if defined($printanywidget) ne 1 then {
 $printanywidget = xmtoplevel_board(0,0, 'Print/Save any Window',10,10)
 wq = topbuttonsetupsanslink_tl('$printany')
 rb = xmradiobox(wq,'printanymode_cb',$f4,'','print', 'save to eps file', -
 	'save to rgb file', 'save to JPEG file')
 n=num_elem(rb)-1
 for i=1,n do xmselectcolor, rb(i),'red'
 xmposition, rb(0), 10, 40
 xmtogglesetstate, rb(1), 1
 $printanymode = 0
 $printany_text1 = xmtextfield(wq,'',200,'',$f3,'white')
 xmposition, $printany_text1, 150, 70,200,32
 xmposition, xmlabel(wq, '.eps', $f4), 355, 74
 $printany_text2 = xmtextfield(wq,'',200,'',$f3,'white')
 xmposition, $printany_text2, 150, 100,200,32
 xmposition, xmlabel(wq, '.rgb', $f4), 355, 104
 $printany_text3 = xmtextfield(wq,'',200,'',$f3,'white')
 xmposition, $printany_text3, 150, 130,200,32
 xmposition, xmlabel(wq, '.jpeg', $f4), 355, 134
 bb = xmbutton(wq,'select and\nprint/save','printany_cb',$f4,'gray')
 xmposition, bb, 150, 0, 150, 0
 $printany_b1 = bb
 }
 return, $printanywidget
 endfunc
 ;=============================================================================== 
subr view_file, win
 ;the items are: load file, save, hide, destroy
 ;;4/24/2008 - remove print option until we fix it
  w = -1
 ncase $option_value
   { ;set up a file selection dialog
     sw = string(win)
     ;here the image will be loaded by the callback in the file selection widget
     sq = '$fs'+sw
     if defined(eval(sq)) eq 1 then xtmanage, eval(sq) else {
       s1 = 'File Reader for View '+sw
       iq = xmfileselect(0,s1,'read_file,'+sw,'Load','finspect','fscancel,'+sw,$f3,$f5,-
         '', '', 'Inspect', 'Dismiss')
       equate, eval(sq), iq
       scanpositions, iq, 'fs'+sw, $bw_ix, $bw_iy
       xmposition, iq, $bw_ix, $bw_iy + $magic_mac_yoffset
       xtloop, 2
       return
     }
   }
   {
     w = save_widget()
     ;also prime with this window number
     xmtextfieldsetstring, $savetext1, string(win)
   }
   ;;{ view_print, win }
   xtpopdown,  eval('$viewer'+ist(win,1))
   view_destroy, win
 endcase
 endsubr
 ;=============================================================================== 
subr view_swfile, win
 ;the items are: redraw, hide, destroy, save
 ;;4/24/2008 - remove print option until we fix it
 w = -1
 ncase $option_value
   {
     w = save_widget()
     ;also prime with this window number
     xmtextfieldsetstring, $savetext1, string(win)
   }
   ;;{ view_print, win }
   xtpopdown,  eval('$viewer'+ist(win,1))
   view_destroy, win
 endcase
 endsubr
 ;=============================================================================== 
subr info_box_hide_toggle, win
 if $view_text_hide(win) then {
   $view_text_hide(win) = 0
   xtmanage, $view_text_widget(win)
  } else {
   $view_text_hide(win) = 1
   xtunmanage, $view_text_widget(win)
  }
 endsubr
 ;=============================================================================== 
subr info_box_hide, win
 if xtismanaged($view_text_widget(win)) then {
   xtunmanage, $view_text_widget(win)
  }
 $view_text_hide(win) = 1
 endsubr
 ;=============================================================================== 
subr view_display, win
 w = -1
 ncase $option_value
   w = view_despike_widget(win)
   w = view_map_widget(win)
   w = view_connect_widget(win)
   w = view_range_widget(win)
   w = view_solar_widget(win)
   w = view_clock_widget(win)
   w = view_emi_widget(win)
   view, win	;the redraw option
   { ty,'grid menu call, shouldn''t happen' }
   { erase, win }
   { info_box_hide_toggle, win }
 endcase
 ;;if w ge 0 then centerfront, w
 if w ge 0 then { xtmanage, w     xtpopup, w }
 ;and some extra work if we need to push some radio buttons
 if $option_value eq 1 then {
  jq = $view_scaletype(win)
  if jq ge 6 or jq lt 0 then jq = 0
  iq = eval('$imapoption'+string(win))
  xmsetoptionselection, iq(0), iq(jq+1)
 }
 endsubr
 ;=============================================================================== 
subr viewts_display, win
 w = -1
 ncase $option_value
   w = view_map_widget(win)
   w = view_range_widget(win)
   view, win	;the redraw option
   { erase, win }
   { info_box_hide_toggle, win }
 endcase
 ;;if w ge 0 then centerfront, w
 if w ge 0 then { xtmanage, w     xtpopup, w }
 ;and some extra work if we need to push some radio buttons
 if $option_value eq 1 then {
  jq = $view_scaletype(win)
  if jq ge 6 or jq lt 0 then jq = 0
  iq = eval('$imapoption'+string(win))
  xmsetoptionselection, iq(0), iq(jq+1)
 }
 endsubr
 ;=============================================================================== 
subr grid_color_cb
 ;currently the same color for all windows but doesn't re-draw so old grids
 ;don't have colors changed
 ncase $option_value
 #grid_pixel = !black_pixel
 #grid_pixel = !white_pixel
 #grid_pixel = !red_pixel
 #grid_pixel = !yellow_pixel
 #grid_pixel = !green_pixel
 endcase
 endsubr
 ;=============================================================================== 
subr grid_cb, win
 ncase $option_value
 nx = 5
 nx = 10
 nx = 20
 nx = 50
 nx = 100
 endcase
 draw_grid, win, nx
 endsubr
 ;=============================================================================== 
subr view_option, win
 ;magnify, bin, rotate, undo
 w = -1
 ;presently we just prompt for an appropiate value and then do the operation
 ;a fancier interface someday
 ;also a fast (and dirty) rotator and maybe magnifier for use with scroll bars
 ;or dials
 ;statistics is another special case, puts up a separate widget somewhat like
 ;the image mapping under display
 ;2/12/2001 - adjust the pixel scale for magnify/compress operations
 ty,'view option =', $option_value
 if $option_value eq 0 then {
  w = view_stats_widget(win)
  if w ge 0 then centerfront, w
 return
 }

 save_str = '$save_last'+string(win)
 data_str = '$data'+string(win)
 sc = $view_sun_pixel_scale(win)
 equate, eval('$save_sc'+string(win)), sc
 ;undo is a special case and we test for it first
 if $option_value eq 4 then {
 if defined(eval(save_str)) eq 0 or isscalar(eval(save_str)) eq 1 then {
  errormess, 'nothing to "undo"'
  } else {
  switch, eval(save_str), eval(data_str)
  equate, eval(save_str), 0
  equate, $view_sun_pixel_scale(win), eval('$save_sc'+string(win))
  view, win
  }
 return
 }
 ncase $option_value-1
 sq = 'enter magification\nfactor below'
 sq = 'enter integer\nbin factor below'
 sq = 'enter ccw angle\nin degrees\n(apparent direction\nvaries with orientation)'
 endcase
 xmprompt,sq,'','prompt_cb',1,$f7,'',200,200
 xtloop, 1
 ;we get here after the prompt_cb lets us (it sets !motif = 0)
 !motif = 1
 ;get the value for the operation and do it
 ncase $option_value-1
 { xq = float($textfield_value)
  zq = mag3( eval(data_str), xq)
  sc = sc/xq	}
 { xq = rfix($textfield_value)
  zq = compress( eval(data_str), xq)
  sc = sc*xq	}
 { xq = float($textfield_value)
  zq = rotate3( eval(data_str), xq)	}
 endcase

 $view_sun_pixel_scale(win) = sc
 ;5/10/2002 any of these invalidate a specialized data type
 $view_data_type(win) = 0
 switch, eval(save_str), eval(data_str)
 switch, zq, eval(data_str)
 zq = 0
 view, win
 endsubr
 ;=============================================================================== 
subr view_part1, win
 ;this is called by view and view_adjust_scales (in toolset0)
 ;2/18/2008 - generalize for other types of views
 wtype = 0
 if win ge 20 wtype = 1
 if win ge 24 wtype = 2
 ;check now for views that ignore the data, or we could make some mistakes
 if $view_scaletype(win) eq 6 or wtype ne 0 then {
   dst = '$view_data'+string(win)
 } else dst = '$data'+string(win)	;name of the data array
 if wtype ne 0 then {
   ;note that $view_zoom_fac should be 1 for these since the zooms are not done by tvplane
   $view_zoom_fac(win) = 1
 }
 ;whoever we got must be 2-D
 if num_dim(eval(dst)) ne 2 then { ty,'VIEW - array must be 2-D' return, 0 }
 nx = dimen(eval(dst),0)	ny = dimen(eval(dst),1)
 $view_nx(win) = nx
 $view_ny(win) = ny
 $viewdespikestatus(win) = 0	;start out raw of course

 $view_exists(win) = 1
 sw = string(win)
 if defined(eval('$viewer'+sw)) eq 0 then {
   $win = win
   ;create the widget in a separate compile file
   compile_file, getenv('ANA_WLIB') + '/view_widgettool'
   win = $win	;needed in case we called view from top level
   ;start without a text box if wtype ne 0 
   if wtype ne 0 info_box_hide, win
   ty,'$view_scaletype(win) = ', $view_scaletype(win)
 }
 sq = 'viewer '+string(win)+', '+show_array(eval(dst))
 ;allow for data that is already display ready, use $view_scaletype of 6
 if $view_scaletype(win) ne 6 then {
   ;note that limb enhance is done in ftsc
   xq = ftsc(eval(dst), win)
   switch, xq, eval('$view_data'+string(win))
   xq = 0 ;in case $view_data was already defined, recover memory
   $view_scale_range(0,win) = $trim_range
   sq2 = ''
   if $view_scaletype(win) eq 3 then sq2 = ' log '
   if $view_scaletype(win) eq 5 then {
     sq2 = sprintf(' atan %g to %g, g = %3.1f',$view_scale_range(0,win),$view_scale_range(1,win),$trim_gamma)
   } else {
     sq2+=sprintf(' scaled %g to %g, g = %3.1f',$view_scale_range(0,win),$view_scale_range(1,win),$trim_gamma)
   }
   ;for this case, where there is data that is scaled, the data always has
   ;orientation 2, so convert the view_data now
   set_orient, 2, $view_order(win), win
 } else {
   sq2 = ' custom scaling'
   ;for this case, where the $data array is non-existent or being ignored for the
   ;view, we have to insist that the code providing the view_data ensure that it
   ;is already oriented correctly; otherwise we have problems with redraws
   ;flipping the view; so here we do not do another set_orient, it should
   ;already be right for either the initial view or a redraw
 }
 sq3 = sq+sq2
 $window_title(win) = sq3
 if $view_label(0,win) ne 0 then xmsetlabel, $view_label(0,win), sq2
 if wtype ne 0 then {
   ;the time slice or wavelength array are always prepared for iorder = 0 display, if the
   ;current display is not 0, we have to flip it here
   maxsize, win
   or2 = $view_order(win)
   if or2 then re_orient, 0, or2, win
   if wtype eq 1 then $window_title(win) = 'time slice viewer '+sw
   if wtype eq 2 then $window_title(win) = 'space/wavelength slice viewer '+sw
 }
 endsubr
 ;=============================================================================== 
subr view, win
 ;divide into 2 parts to allow for possible adjustments associated with
 ;a connection that could involve a rescale
 view_part1, win
 viq = eval('$viewer'+str(win))
 stips = ' (T:pop main, X:expand, H:hide)'
 xmsettitle, viq, $window_title(win) + stips
 ;try to get by without changing all the properties, if the image is a different
 ;size, some will have to be changed
 xtpopup, viq
 
 ;some of these are not applicable to wtype ne 0 but flags should be 0 also
 ;check if we are drawing latitude/longitude
 if $viewlatlongflag(win) then stony_trace, win
 view_recompute, win
 ;do we want stats updated?
 if $viewstatsflag(win) then viewstats, win
 ;do we want a time box updated?
 if $viewclockflag(win) then view_clock_box, win
 ;are we part of a connected set of views ?
 if $view_connect(win) then connect_adjust
 endsubr
 ;==============================================================
func window_data(win, z1, s1, nx, ny)
 ;11/1/2000 - a rewrite, make a function that returns non-zero if error
 ;and handle movie windows (just return the current image)
 ;this does a switch (or exchange) of the window symbol unless it is
 ;a movie window, this is to avoid copying the array
 ;check if the variable exists
 s1 = '$data'+string(win)
 if isarray(eval(s1)) eq 0 and issymarr(eval(s1)) eq 0 then {
  errormess,sprintf('no valid data\nassociated with\nwindow %d',win)
  return, 1 }
 if win lt #play_window then {
   switch, z1, eval(s1)
 } else {
   ;some sort of movie, gets complicated
   j = $now+$j1
     if win eq #play_window then {
     nt = dimen($play_index,0)
     if j ge nt or j lt 0 then {
       errormess,sprintf('error getting movie\nframe %d', it)
       return, 1
     }
     it = $play_index(j)
   } else {
     ;this is for the multi's, we have to find what we need in the set, assumes
     ;that the windows are contiguous
     nt = dimen($play_multi,0)
     if j ge nt or j lt 0 then {
       errormess,sprintf('error getting movie\nframe %d', it)
       return, 1
     }
     i = win - $play_window(1)
     it = $play_multi(j, i)
   }
   z1 = getxy(eval(s1), it)
   s1 = ''	;to prevent the reverse switch
 }
 nx = dimen(z1, 0)		ny = dimen(z1, 1)
 return, 0
 endfunc
 ;===============================================================================
subr setpath_widget, win
 ;read a special file and load name field with choice
 if defined($setpathwidget) eq 0 then {
 $setpathwidget = xmdialog_board(0,0,0, 'some popular paths',0,0,10,10)
 help_file = $help_path + '/instructions.setpath'
 topbuttonsetupsanslink,'$setpathwidget','$setpathhelp',help_file
 fn='/hosts/diapason/usr1/people/shine/movies/popular_paths'
 xmposition, xmlabel($setpathwidget, 'file with path list' ,$f4), 10, 50
 $setpathtext1 = xmtextfield($setpathwidget,'',280,'',$f3,'white')
 xmposition, $setpathtext1, 10, 76, 350, 35
 bq = xmbutton($setpathwidget, 're-load', 'reload_setpath_cb', $f4, 'darkgreen')
 xmposition, bq, 250, 46, 70, 30
 sq = 'select a path for file viewer'
 xmposition,xmlabel($setpathwidget, sq ,$f4), 50, 140
 $setpathfield=xmlistfromfile($setpathwidget,'setpath_cb',fn,10,$f3,'white')
 if $setpathfield eq -1 then {	;couldn't read the file
 errormess, 'popular_paths file\nnot readable'
 fw = xmframe($setpathwidget)
 $setpathfield = xmtextbox(fw, 15, 80, $f3, 'white')
 xmtextappend, $setpathfield, -
 	'The path list file could not be found or was not readable.', 1
 xmtextappend, $setpathfield, -
 	'Check the name and path, make corrections and try re-load', 1
 }
 xmposition, xtparent($setpathfield), 10, 160
 }
 xmtextfieldsetstring, $setpathtext1, fn
 xtmanage, $setpathwidget
 return
 endsubr
 ;==========================================================
subr reload_setpath_cb
 name = xmtextfieldgetstring ($setpathtext1)
 lun = get_lun()
 iq = openr( lun, name)
 close, lun
 if iq ne 1 then {
 errormess,'popular_paths file\nnot readable'
 return
 }
 ;xtunmanage, $setpathwidget
 xmdestroy, xtparent($setpathfield)
 $setpathfield = xmlistfromfile($setpathwidget, 'setpath_cb', -
 	name, 10, $f3, 'white')
 xmposition, xtparent($setpathfield), 10, 160
 ;xtmanage, $setpathwidget
 endsubr
 ;========================================================
subr setpath_cb
 $datapath = $list_item
 ;check if a file viewer is up
 if defined($fs1) then xmsetdirectory, $fs1, $datapath
 endsubr
 ;========================================================
func get_ft, widget
 ;get the file template and check it
 file_template = xmtextfieldgetstring(widget)
 ic=strcount(file_template,'#')
 if ic le 0 {	;a problem, maybe we just have a 0001 that we can replace
	 if strpos(file_template, '0001') ge 0 then {
		 file_template = strreplace(file_template,'0001','####')
		 xmtextfieldsetstring, widget, file_template
	 } else {
	 ;or even a 001
	 if strpos(file_template, '001') ge 0 then {
		 file_template = strreplace(file_template,'001','###')
		 xmtextfieldsetstring, widget, file_template
	 }
	 }
 }
 return, file_template	;always return with original or modified, if still bad
			 ;it gets noted latter
 endfunc
 ;===============================================================================
subr set_movie_stuff
 ;called by movie_list, first call the frame selector widget and then set
 ;the various fields
 movie_frame_widget
 xmtextfieldsetstring, $movfrwidget_t1, $movie_name, 1
 xmtextfieldsetstring, $first_file_widget, istring($first_file,1)
 xmtextfieldsetstring, $last_file_widget, istring($last_file,1)
 xmscaleresetlimits, $movfrwidget_sc, $first_file, $last_file
 $SCALE_VALUE = $first_file
 xmscalesetvalue,$movfrwidget_sc, $SCALE_VALUE
 $fnum = $SCALE_VALUE
 xmtextfieldsetstring,$movfrwidget_t3,string($fnum)
 ;if the movie cube tool is set up, pass along some info
 ;if defined($mvgetwidget) eq 1 then mvget_loadname_cb
 ;ditto for the time slicer tools
 ;if defined($xyslicewidget) eq 1 then {
 ;xmtextfieldsetstring,$xyslicet3, istring($first_file,1)
 ;xmtextfieldsetstring,$xyslicet4, istring($last_file,1)
 ;xmtextfieldsetstring,$xyslicet5, '1'
 ;}
 endsubr
 ;===============================================================================
subr window_cb, action
 ;used to do something to a window
 ;which window ?
 win = $current_window
 if defined('$data'+string(win)) eq 0 then return
 ncase action
   view,win
   xtpopdown, eval('$viewer'+string(win))
   { w2 =  fix(xmtextfieldgetstring ($brow_copy_win))
     ;copy from win to w2
     if w2 gt 14 or w2 lt 0 then {
     errormess,'illegal destination\nfor window copy'
     } else {
     inherit_params, w2, win
     xmsetcolors, $brow_copy_but, 'black'
     equate, eval('$data'+string(w2)), eval('$data'+string(win))
     $view_scaletype(w2) = $view_scaletype(win)
     if $view_scaletype(w2) eq 6 then
     	equate, eval('$view_data'+string(w2)), eval('$view_data'+string(win))
     $view_zoom_fac(w2) = $view_zoom_fac(win)
     view, w2
     ;if the original window had a image display widget, duplicate it
     if defined(eval('$imagemapwidget'+string(win))) eq 1 then {
      $option_value = 1
      view_display, w2
      vw = eval('$imaptext'+string(win))
      n = num_elem(vw)
      vw2 = eval('$imaptext'+string(w2))
      for i=0,n-1 do xmtextfieldsetstring,vw2(i),xmtextfieldgetstring(vw(i))
      ;also means another view to use it
      view, w2
     }
     xmsetcolors, $brow_copy_but, 'red'
     }
   }
 endcase
 endsubr
 ;=============================================================================
subr win_hide_cb
 ;hide any windows that exist
 ;assuming 15 views and 24 windows total
 for win = 0, 24 do {
 if defined(eval('$viewer'+ist(win,1))) eq 1 then {
 	xtpopdown, eval('$viewer'+ist(win,1)) }
 }
 ;kill the blink window since it is not a widget we can unmanage (this
 ;should probably be changed)
 if xexist($blink_win) then xdelete, $blink_win
 endsubr
 ;=============================================================================
subr tool_hide_cb
 ;hide any tools that have been registered as hideable
 if isarray($hideable) then {
  n = num_elem($hideable)
  for i =0, n-1 do xtpopdown, $hideable(i)
 }
 endsubr
 ;=============================================================================
subr menu_display
 ;11/24/96 only the screen display left here now since others now done
 ;in view widget
 w = -1
 ncase $option_value
  w = screen_widget()
  win_hide_cb
  tool_hide_cb
  limbenhance, 0
 endcase
 if w ge 0 then {
 xtpopup, w
 }
 endsubr
 ;===============================================================================
subr add_to_hideables, w
 if defined($hideable) then {
  ;check if already in the list
  if min(abs(w - $hideable)) ne 0 then $hideable = [$hideable, w] 
  } else {
  $hideable = [w]
 }
 endsubr
 ;===============================================================================
subr tog1
 
 ncase $option_value
   w = save_widget()
   { w = magnify_widget()	 xtmanage, w   w = -1 }
   w = hist_widget()
   w = islice_widget()
   w = filter_widget()
   w = thresh_widget()
   w = noise_widget()
   w = basin_widget()
   w = object_widget()
   w = flux_widget()
   w = area_widget()
   w = mouse_widget()
   w = power_widget()
   w = bittoy_widget()
   w = seek_widget()
   w = sdisk_widget()
 endcase
 ;;if w ge 0 then {
   ;;xtpopup, w
   ;;xmgetwidgetsize, w, dx, dy
   ;;xmposition, w, $bw_ix - dx, !screen_height - dy - 5
   ;;add_to_hideables, w
 ;;}
 endsubr
 ;===============================================================================
subr tog2
 ;all converted to top level 12/9/98
 ncase $option_value
   w = blink_widget()
   w = superpose_widget()
   w = crossplot_widget()
   w = bops_widget()
   w = align_widget()
   w = alignauto_widget()
   w = fade_widget()
   w = blend_widget()
   w = dark_widget()
   w = limbalign_widget()
   w = imagematch_widget()
 endcase
 ;;if w ge 0 then {
  ;;xtpopup, w
  ;;xmgetwidgetsize, w, dx, dy
  ;;xmposition, w, $bw_ix - dx, !screen_height - dy - 5
  ;;add_to_hideables, w
 ;;}
 endsubr
 ;===============================================================================
subr tog3
 w = 0
 ncase $option_value
  tswidget_widget
  track_widget
  sp_xyw_widget
  dicer_widget
 endcase
 endsubr
 ;===============================================================================
subr tog4
 ncase $option_value
   w = mvget_widget()
   w = mvplay_widget()
   w = readcube_widget()
   w = editcube_widget()
   w = movie_despike_widget()
   w = mvstats_widget()
   w = lightcurve_widget()
   w = magcurve_widget()
 endcase
 endsubr
 ;===============================================================================
subr tog_slice
 if defined($data15) eq 0 then {
 	errormess,'no movie\ncube defined'  return }
 color = 'red'
 ncase $option_value
 xyslicer, $data15, 15, 38, 39, color
 line_slicer, $data15, 15, 37, color
 c_slicer, $data15, 15, 36, color
 four_slicer, $data15, 15, 37, color, 192
 endcase
 endsubr
 ;===============================================================================
subr tog5
 ;just one case now
 w = flowdtool()
 if w ge 0 then {
 xtmanage, w
 xmgetwidgetsize, w, dx, dy
 xmposition, w, $bw_ix - dx, !screen_height - dy - 5
 }
 endsubr
 ;===============================================================================
;;subr menu_command
 ;only one call now
;; w = ana_command_widget()
;; if w ge 0 then {
;; xtmanage, w
;; xmgetwidgetsize, w, dx, dy
;; xmposition, w, $bw_ix - dx, !screen_height - dy - 5
;; }
;; endsubr
 ;===============================================================================
subr menu_file
 ncase $option_value
   { ;set up a file selection dialog for the selected window
     ;2/15/2001 - change to allow multiple file viewers but they always
     ;display in $current_window, should be less confusing than previous
     ;system
     sw = '0'
     if $num_file_viewers gt 0 then {
       if defined($file_view_querywidget) eq 0 then
    	   compile_file, getenv('ANA_WLIB') + '/fileviewquerywidgettool.ana'
       xtpopup, $file_view_querywidget
       return
     } else $num_file_viewers = 1
     sw = string($num_file_viewers-1)
     sq = '$fs'+sw
     if defined(eval(sq)) eq 1 then xtpopup, eval(sq) else {
      s1 = 'File Reader for Selected View'
      iq = xmfileselect(0, s1,'read_file_current','Load','finspect','fscancel,'+sw, -
   	  $f3,$f5, '', '', 'Inspect', 'Dismiss')
      equate, eval(sq), iq
      scanpositions, iq, 'fs'+sw, $bw_ix, $bw_iy
      xmposition, iq, $bw_ix, $bw_iy + $magic_mac_yoffset
      xtloop, 2
     }
     return
   }
   { ;launch a file set widget
     movie_frame_widget	;also make sure this is active in case list doesn't exist
   }
   { ;save window positions
     ;;movie_list, 'set_movie_stuff'
     ;;movie_frame_widget	;also make sure this is active in case list doesn't exist
     savepositions
   }
   { sdo_widget }
   { sb_widget }
   { xrt_widget }
   { t3d_widget }
   { ;a list of lists widget
     image_list_wq
   }
   { w = fdmg_widget() }
   { lpthumb_widget }
   { w = yohkoh_widget()
     xtpopup, w }
   {
     w = save_widget()
   }
   { w = printany_widget()
     centerfront, w
   }
   cop_out
 endcase
 endsubr
 ;===============================================================================
subr menu_help
 ;presently 2 cases
 ncase $option_value
 { widget_help, $browser_help, $help_path+'instructions.browser2' }
 { widget_help, $browser_news, $help_path + 'instructions.browser_news' }
 endcase
 endsubr
 ;=============================================================================== 
subr nosupport
 errormess,$mess3
 return
 endsubr
 ;=============================================================================== 
