;+
; NAME:
;     LAUNCHER
; PURPOSE:
;     Main routine for displaying APC data directories and launching
;     analysis tasks.  A list widget shows the contents of data directories
;     and optionally the scan and segment headings of the files.  A
;     context-sensitive list widget is used to launch tasks depending on the
;     type of file/scan/segment selected.
; CATEGORY:
;     OVRO APC ANALYSIS WIDGET
; CALLING SEQUENCE:
;     launcher
; INPUTS:
; OPTIONAL (KEYWORD) INPUT PARAMETERS:
; ROUTINES CALLED:
;     break_file, get_segments, gettask, openarc, wpreferences,
;     findsegentries (internal routine), filename2date
; OUTPUTS:
; COMMENTS:
; SIDE EFFECTS:
; RESTRICTIONS:
; MODIFICATION HISTORY:
;     Written 25-Sep-1997 by Dale Gary
;     11-Jan-1998  DG
;       Changed to use openarc and new version of get_segments
;     12-Jan-1998  DG
;       Changed to menubar rather than menu buttons
;     26-Jul-1998  DG
;       Convert file list from directory into an alpha-numerically sorted list
;     08-Jan-1999  DG
;       Added date widget, on selection of a filename. (Fixed case where selected
;       file is DAILY.ARC, 09-Jan-1999)
;     15-Apr-1999  DG
;       Added buttons for launching the Schedule and Diagnostics
;     20-Apr-1999  DG
;       Considerable changes to enable opening and closing of SCANs (in addition
;       to files), to show or hide segments within the SCAN.
;     17-May-1999  DG
;       Added findsegentries() function and associated code to deal with segments
;       that are not in a scan.  Also fixed problem with opening scans after
;       data had changed (as file grows).
;     29-Dec-1999  DG
;       Added check for POINT scan
;     11-Jan-2000  DG
;       Eliminated !UNIX variable by using !DEFAULTS.FONT
;     21-Jul-2000  DG
;       Now sorts filenames by uppercase.
;     15-Aug-2000  DG
;       Change "change file directory" to accept a directory only, not
;       a file.
;     22-Jun-2002  DG
;       Slight change to use FILENAME2DATE() routine.
;     02-Feb-2014  DG
;       Change file search extension from .arc to .ARC for Linux
;     20-May-2014  DG
;       Changed named {list} structure to anonymous structure to avoid name conflict.
;-


;--------------------------------------------------------------------------

PRO LAUNCHERMain_Event, Event

  base = Event.handler
  stash = WIDGET_INFO(base, /CHILD)
  WIDGET_CONTROL, stash, GET_UVALUE=state, /NO_COPY

  if (Event.Id eq state.mbar) then Ev=Event.Value $
                              else WIDGET_CONTROL,Event.Id,GET_UVALUE=Ev

  CASE Ev OF

  ; Event for FileMenu
  'File.Change Directory': BEGIN             ;Event for File.Change Directory
       maxlist = 1000
       datadir = !defaults.datadir
       direc = dialog_pickfile(/dir,path = datadir, /NOCONFIRM)
       files = findfile(direc+'*.ARC',count=n)
       ; Sort files into alphabetical order
       files = files(sort(strupcase(files)))
       state.filedir = direc
       if (n eq 0) then begin
          WIDGET_CONTROL,state.textid,SET_VALUE='< No data files in this directory >'
          state.num = 0
          goto,WRITE_STATE
       endif
       if (n gt maxlist) then print,'Warning: Can only handle ',maxlist,' files'
       outfiles = files(0:(n<maxlist)-1)
       for i = 0, (n<maxlist)-1 do begin
          break_file,files(i),disk,direc,filnam,ext
          outfiles(i) = filnam+ext
       endfor
       WIDGET_CONTROL,state.textid,SET_VALUE='+ '+outfiles(0:(n<maxlist)-1)
       num = n_elements(outfiles)
       state.num = num
       state.inlist(0:num-1).name = outfiles
       state.inlist(0:num-1).type = !T_CFILE
       state.inlist(num:maxlist-1).type = 0           ; Zero out types of rest of list
    END
  'File.Quit': BEGIN                         ;Event for File.Quit
       WIDGET_CONTROL, /DESTROY, Event.Top
       return
    END
  ; Event for OptionsMenu
  'Options.Preferences': BEGIN
         wpreferences
      END
  'Sched': schedule            ; Launch the schedule, but do not declare group leader
  'Diag': diagnose ;,group = Event.Top  ; Launch the diagnose routine with group leader
  'LIST25': BEGIN                               ;Event for DirText
         maxlist = 1000
         if (Event.clicks eq 1) then begin

            ; User selected an item in the file list (one click, or first
            ; of a double-click).  Save the index number of the selected item.

            state.index = Event.index

            ; Handle case where only an information string is contained
            ; in the list widget (no file list exists)
            if (state.num eq 0) then goto,WRITE_STATE

            ; Search backward in list until a file type is found, and
            ; save the file name.  This is necessary if the user clicked
            ; on a scan or segment.

            i = state.index
            while((state.inlist(i).type and !T_FILE) ne !T_FILE) do i=i-1
            state.filename = state.inlist(i).name

            ; Use filename to determine the date, for display in widget label
            datestr = filename2date(state.filename)

            widget_control,state.dateID,set_value=datestr

            ; Update Task List for tasks relevant to the TYPE of the
            ; selected item.

            tlist = gettask(state.inlist(state.index).type)
            if (tlist(0).type ne 0) then begin
               state.tasks(0:n_elements(tlist)-1) = tlist
               WIDGET_CONTROL,state.taskid,SET_VALUE=tlist.name
            endif

         endif else if (Event.clicks eq 2) then begin

            ; Open scan list if what was clicked is a "closed file" (!T_CFILE)
            ; Close scan list if what was clicked is an "open file" (!T_OFILE)
            ; Open segment list if what was clicked is a "closed scan" (!T_CSCAN)
            ; Close seqment list if what was clicked is an "open scan" (!T_OSCAN)
            ; Ignore double-click otherwise
            ocmask = "37   ; Mask to limit consideration to Open/Close bits only
            intype = state.inlist(state.index).type and ocmask

            CASE intype OF
            !T_CFILE: BEGIN

               inlist = state.inlist         ;Work on copy of inlist

               ; Get the list of all of the segments in the selected file

               ; Open the file
               filenam = state.filedir+state.filename
               lun = openarc(filenam,a,nrec)
               IF (lun EQ 0) THEN goto,WRITE_STATE

               ; Get list of segments, then close the file
               seglist = get_segments(a,nrec)
               free_lun,lun

               if (size(seglist,/type) ne 7) then begin  ; If seglist is not a string
                  goto,WRITE_STATE
               endif

               ; Get indexes of header lines (IHED)
               ; Get indexes of segment lines not in a scan (ISEG)
               nadded = findsegentries(seglist,ihed,iseg)

               if (nadded gt 0) then begin
                  ; Combine the indexes into one, sorted array
                  iall = [ihed,iseg]
                  iall = iall(where(iall ne -1,nall))  ; Eliminate -1
                  if (nall ne 0) then iall = iall(sort(iall))
               endif

               ; Append all of the segment list to the file list
               outlist = inlist(0:state.index)
               for i = 0, nadded-1 do begin
                  j = iall[i]
                  ; See if this is a segment, or a scan
                  isg = where(iseg eq j,nsg)
                  if(nsg ne 0) then begin
                     ; It was a segment.  Determine and set any special segment types
                     typ = !T_SEGM
                  endif else begin
                     ; It was a scan.  Determine and set any special scan types
                     typ = !T_CSCAN
                     if (strpos(seglist(j),'GAIN')  NE -1) then typ = typ or !T_GSCAN
                     if (strpos(seglist(j),'FREQ')  NE -1) then typ = typ or !T_FSCAN
                     if (strpos(seglist(j),'SOLAR') NE -1) then typ = typ or !T_SSCAN
                     if (strpos(seglist(j),'POINT ') NE -1) then typ = typ or !T_PTSCN
                     if (strpos(seglist(j),'POINTING') NE -1) then typ = typ or !T_ASCAN
                     if (strpos(seglist(j),'PHASE') NE -1) then typ = typ or !T_PSCAN
                     if (strpos(seglist(j),'REF TP') NE -1) then typ = typ or !T_TPSCN
                     if (strpos(seglist(j),'CENTER') NE -1) then typ = typ or !T_CRSCN
                     if (strpos(seglist(j),'DELAY SCAN') NE -1) then typ = typ or !T_DSCAN
                     if (strpos(seglist(j),'DELAY CAL') NE -1) then typ = typ or !T_DSCAN
                  endelse
                  outlist = [outlist,{list,name:seglist(j),type:typ}]
               endfor

               ; If not the last file in the list, append rest of old
               ; list to new list

               num = where(inlist.type eq 0)
               if(num(0) eq -1) then num = n_elements(inlist) $
                                else num = num(0)
               if (state.index lt num-1) then $
                  outlist = [outlist,inlist(state.index+1:num-1)]
               num = num + nadded

               ; Set the type of the clicked-on file to !T_OFILE

               outlist(state.index).type = !T_OFILE

               ; Save new list to state variable and display it

               state.inlist(0:num-1) = outlist

               ; Reuse variable name outlist -- now just a string array
               outlist = strarr(num)
               outpref = strarr(num)
               closedfiles = where((state.inlist(0:num-1).type and ocmask) eq !T_CFILE,ncf)
               openfiles   = where((state.inlist(0:num-1).type and ocmask) eq !T_OFILE,nof)
               closedscans = where((state.inlist(0:num-1).type and ocmask) eq !T_CSCAN,ncs)
               openscans   = where((state.inlist(0:num-1).type and ocmask) eq !T_OSCAN,nos)
               segments    = where((state.inlist(0:num-1).type and !T_SEGM) ne 0,nseg)
               if (ncf ne 0) then outpref(closedfiles) = '+ '
               if (nof ne 0) then outpref(openfiles)   = '- '
               if (ncs ne 0) then outpref(closedscans) = '  + '
               if (nos ne 0) then outpref(openscans)   = '  - '
               if (nseg ne 0) then outpref(segments)   = '    '

               ; Fill outlist with names from inlist and set the widget
               outlist = outpref+state.inlist(0:num-1).name
               top = WIDGET_INFO(state.textid,/LIST_TOP)
               WIDGET_CONTROL,state.textid,SET_VALUE=outlist,$
                  XSIZE=60,SET_LIST_TOP=top,SET_LIST_SELECT=state.index
            END
            !T_CSCAN: BEGIN

               inlist = state.inlist         ;Work on copy of inlist

               ; Get the list of all of the segments in the selected file

               ; Open the file
               filenam = state.filedir+state.filename
               lun = openarc(filenam,a,nrec)
               IF (lun EQ 0) THEN goto,WRITE_STATE

               ; Get list of segments, then close the file
               seglist = get_segments(a,nrec)
               free_lun,lun

               if (size(seglist,/type) ne 7) then begin  ; If seglist is not a string
                  goto,WRITE_STATE
               endif

               ; Get indexes of header lines (lines containing string 'Header:')
               ihed = where(strpos(seglist,'Header:') ne -1,nhed)

               ; Make sure there are some headers.
               if (nhed eq 0) then begin  ; No headers in seglist???
                  goto,WRITE_STATE
               endif

               ; CURHED is the index in seqlist of the current header (the one selected)
               curhed = (where(strmid(seglist,0,19) eq strmid(state.inlist(state.index).name,0,19),exist))(0)
               if (exist eq 0) then begin  ; The line clicked on doesn't exist in seglist???
                  goto,WRITE_STATE
               endif

               if (curhed eq ihed(nhed-1)) then begin
                  ; Header clicked on is last header in list, so end segment is last one wanted
                  iend = n_elements(seglist)-1
               endif else begin
                  ; Header clicked on is not the last header in the list, so we want segments
                  ; only up to the next header.
                  thishead = where(ihed eq curhed(0))
                  iend = (ihed[thishead+1])(0)-1
               endelse

               ; Determine total number of segments to add to the list
               nadded = iend - curhed
               if (nadded le 0) then begin   ; No segments to add???
                  goto, WRITE_STATE
               endif

               ; Append all of the segment list belonging to this header to the file list
               outlist = inlist(0:state.index)
               for i = 0, nadded-1 do begin
                  j = curhed+i+1
                  ; Set generic segment type
                  typ = !T_SEGM
                  outlist = [outlist,{list,name:seglist(j),type:typ}]
               endfor

               ; If not the last file in the list, append rest of old
               ; list to new list

               num = where(inlist.type eq 0)
               if(num(0) eq -1) then num = n_elements(inlist) $
                                else num = num(0)
               if (state.index lt num-1) then $
                  outlist = [outlist,inlist(state.index+1:num-1)]
               num = num + nadded

               ; Set the type of the clicked-on scan to !T_OSCAN

               outlist(state.index).type = outlist(state.index).type or "20 and not "10

               ; Save new list to state variable and display it

               state.inlist(0:num-1) = outlist

               ; Reuse variable name outlist -- now just a string array
               outlist = strarr(num)
               outpref = strarr(num)
               closedfiles = where((state.inlist(0:num-1).type and ocmask) eq !T_CFILE,ncf)
               openfiles   = where((state.inlist(0:num-1).type and ocmask) eq !T_OFILE,nof)
               closedscans = where((state.inlist(0:num-1).type and ocmask) eq !T_CSCAN,ncs)
               openscans   = where((state.inlist(0:num-1).type and ocmask) eq !T_OSCAN,nos)
               segments    = where((state.inlist(0:num-1).type and !T_SEGM) ne 0,nseg)
               if (ncf ne 0) then outpref(closedfiles) = '+ '
               if (nof ne 0) then outpref(openfiles)   = '- '
               if (ncs ne 0) then outpref(closedscans) = '  + '
               if (nos ne 0) then outpref(openscans)   = '  - '
               if (nseg ne 0) then outpref(segments)   = '    '

               ; Fill outlist with names from inlist and set the widget
               outlist = outpref+state.inlist(0:num-1).name
               top = WIDGET_INFO(state.textid,/LIST_TOP)
               WIDGET_CONTROL,state.textid,SET_VALUE=outlist,$
                  XSIZE=60,SET_LIST_TOP=top,SET_LIST_SELECT=state.index
            END
            !T_OFILE: BEGIN

               ; Determine the end of the real data in the list

               findexes = where(state.inlist.type eq 0)
               oldend = findexes(0)-1
               if (oldend eq -1) then oldend = maxlist-1

               inlist = state.inlist(0:oldend)

               ; Search forward through the list until the next file
               ; name or the end of the list is found

               findexes = where(inlist.type and !T_FILE)
               files_below = where(findexes gt state.index)

               ; Collapse "open file" by omitting non-file entries up to
               ; the next file.  For entries beyond the new end of the
               ; list, set the type to zero to indicate no real data.

               if (files_below(0) eq -1) then begin         ; end of list
                  newend = state.index
                  if (newend lt oldend) then inlist(newend+1:oldend).type = 0
               endif else begin                          ; a file was found
                  findexes = findexes(files_below)
                  newend = oldend-findexes(0)+state.index+1
                  inlist(state.index+1:newend) = $
                     inlist(findexes(0):oldend)
                  if (newend lt oldend) then inlist(newend+1:oldend).type = 0
               endelse

               ; Set the type of the clicked-on file to !T_CFILE

               inlist(state.index).type = !T_CFILE

               ; Save new list to state variable and display it

               state.inlist = inlist
               num = newend+1
               outlist = strarr(num)
               outpref = strarr(num)

               closedfiles = where((state.inlist(0:num-1).type and ocmask) eq !T_CFILE,ncf)
               openfiles   = where((state.inlist(0:num-1).type and ocmask) eq !T_OFILE,nof)
               closedscans = where((state.inlist(0:num-1).type and ocmask) eq !T_CSCAN,ncs)
               openscans   = where((state.inlist(0:num-1).type and ocmask) eq !T_OSCAN,nos)
               segments    = where((state.inlist(0:num-1).type and !T_SEGM) ne 0,nseg)
               if (ncf ne 0) then outpref(closedfiles) = '+ '
               if (nof ne 0) then outpref(openfiles)   = '- '
               if (ncs ne 0) then outpref(closedscans) = '  + '
               if (nos ne 0) then outpref(openscans)   = '  - '
               if (nseg ne 0) then outpref(segments)   = '    '

               outlist = outpref+state.inlist(0:newend).name
               top = WIDGET_INFO(state.textid,/LIST_TOP)
               WIDGET_CONTROL,state.textid,SET_VALUE=outlist,$
                  XSIZE=60,SET_LIST_TOP=top,SET_LIST_SELECT=state.index
            END
            !T_OSCAN: BEGIN

               ; Determine the end of the real data in the list

               findexes = where(state.inlist.type eq 0)
               oldend = findexes(0)-1
               if (oldend eq -1) then oldend = maxlist-1

               inlist = state.inlist(0:oldend)

               ; Search forward through the list until the next scan, or next file
               ; name or the end of the list is found

               sindexes = where(inlist.type and !T_SCAN)
               scans_below = where(sindexes gt state.index,nscan)
               findexes = where(inlist.type and !T_FILE)
               files_below = where(findexes gt state.index,nfile)

               ; Collapse "open scan" by omitting non-scan entries up to
               ; the next scan or file.  For entries beyond the new end of the
               ; list, set the type to zero to indicate no real data.

               if (nscan eq 0 and nfile eq 0) then begin         ; end of list
                  newend = state.index
                  if (newend lt oldend) then inlist(newend+1:oldend).type = 0
               endif else if (nscan ne 0) then begin       ; a scan was found
                  sindexes = sindexes(scans_below)
                  newend = oldend-sindexes(0)+state.index+1
                  inlist(state.index+1:newend) = inlist(sindexes(0):oldend)
                  inlist(newend+1:oldend).type = 0
               endif else begin                 ; no scan, but a file was found
                  findexes = findexes(files_below)
                  newend = oldend-findexes(0)+state.index+1
                  inlist(state.index+1:newend) = $
                     inlist(findexes(0):oldend)
                  inlist(newend+1:oldend).type = 0
               endelse

               ; Set the type of the clicked-on scan to !T_CSCAN

               inlist(state.index).type = inlist(state.index).type or "10 and not "20

               ; Save new list to state variable and display it

               state.inlist = inlist
               num = newend+1
               outlist = strarr(num)
               outpref = strarr(num)

               closedfiles = where((state.inlist(0:num-1).type and ocmask) eq !T_CFILE,ncf)
               openfiles   = where((state.inlist(0:num-1).type and ocmask) eq !T_OFILE,nof)
               closedscans = where((state.inlist(0:num-1).type and ocmask) eq !T_CSCAN,ncs)
               openscans   = where((state.inlist(0:num-1).type and ocmask) eq !T_OSCAN,nos)
               segments    = where((state.inlist(0:num-1).type and !T_SEGM) ne 0,nseg)
               if (ncf ne 0) then outpref(closedfiles) = '+ '
               if (nof ne 0) then outpref(openfiles)   = '- '
               if (ncs ne 0) then outpref(closedscans) = '  + '
               if (nos ne 0) then outpref(openscans)   = '  - '
               if (nseg ne 0) then outpref(segments)   = '    '

               outlist = outpref+state.inlist(0:newend).name
               top = WIDGET_INFO(state.textid,/LIST_TOP)
               WIDGET_CONTROL,state.textid,SET_VALUE=outlist,$
                  XSIZE=60,SET_LIST_TOP=top,SET_LIST_SELECT=state.index
            END
            ELSE:
            ENDCASE
         endif
      END
  'LIST15': BEGIN                               ;Event for TaskList

         ; The user selected an item in the task list.

         k = Event.index

         ; Gather information into variables available to task calls

         indx = state.index
         filename = state.filedir+state.filename
         routine = state.tasks(k).routine

         if (routine eq 'none') then goto, WRITE_STATE  ; No tasks set yet

         recn=1 ; default value if file selected

         if ((state.inlist(indx).type and !T_FILE) eq 0) then begin

            ; Read information from scan or segment entry

            reads,state.inlist(indx).name,format='(13x,i5,1x,i5)',recn,erec
         endif else begin

             ; The user clicked on a filename, so get the full range
             ; of records for the file

             recn = 1
             lun = openarc(filename,a,nrec)
             IF (lun NE 0) THEN BEGIN
                erec = getlrecn(a,nrec)
                free_lun,lun
             ENDIF
         endelse

         i = execute(routine)
      END
  ENDCASE

WRITE_STATE:
  WIDGET_CONTROL, stash, SET_UVALUE=state, /NO_COPY

END


;--------------------------------------------------------------------------


PRO launcher, GROUP=Group

  IF N_ELEMENTS(Group) EQ 0 THEN GROUP=0

  junk   = { CW_PDMENU_S, flags:0, name:'' }


  LAUNCHERMain = WIDGET_BASE(GROUP_LEADER=Group, $
      ROW=1, $
      MAP=1, $
      MBAR=mbar, $
      TITLE='OVRO Analysis Launcher', $
      UVALUE='LAUNCHERMain', $
      RESOURCE_NAME='Launcher')

  BASE2 = WIDGET_BASE(LAUNCHERMain, $
      COLUMN=1, $
      MAP=1, $
      TITLE='ExtraBase', $
      UVALUE='BASE2')

  BASE3 = WIDGET_BASE(BASE2, $
      ROW=1, $
      MAP=1, $
      TITLE='MenuBase', $
      UVALUE='BASE3')

  FileMenuDesc = [ $
      { CW_PDMENU_S,       3, 'File' }, $             ;        0
      { CW_PDMENU_S,       0, 'Change Directory' }, $ ;        1
      { CW_PDMENU_S,       2, 'Quit' } $              ;        2
  ]


  FileMenu = CW_PDMENU( mBar, FileMenuDesc, /RETURN_FULL_NAME, $
      UVALUE='FileMenu',/MBAR)

  OptionsMenuDesc = [ $
      { CW_PDMENU_S,       3, 'Options' }, $             ;       0
      { CW_PDMENU_S,       2, 'Preferences' } $          ;       1
  ]


  FileMenu = CW_PDMENU( mBar, OptionsMenuDesc, /RETURN_FULL_NAME, $
      UVALUE='OptionsMenu',/MBAR)


  BASE6 = WIDGET_BASE(BASE2, $
      ROW=1, $
      MAP=1, $
      TITLE='WindowBase', $
      UVALUE='BASE6')

  BASE7 = WIDGET_BASE(BASE6, $
      COLUMN=1, $
      FRAME=1, $
      MAP=1, $
      TITLE='DirBase', $
      UVALUE='BASE7')

  LABEL8 = WIDGET_LABEL( BASE7, $
      UVALUE='LABEL8', $
      VALUE='List of Available Data')

  defsysv,'!DEFAULTS',EXISTS=exists
  if not exists then defparms

  font = !DEFAULTS.FONT
;  'Lucida Console*bold*14'
;  if (!UNIX) then font = ''

  listval = ['< Select a directory from the File Menu >']
  LIST25 = WIDGET_LIST( BASE7,VALUE=ListVal, $
      UVALUE='LIST25', $
      YSIZE=25, $
      FONT=font, /MULTIPLE,$
      RESOURCE_NAME='FileList')

  BASE14 = WIDGET_BASE(BASE6, $
      COLUMN=1, $
      FRAME=1, $
      MAP=1, $
      TITLE='ButtonBase', $
      UVALUE='BASE14')

  LABEL22 = WIDGET_LABEL( BASE14, $
      UVALUE='LABEL22', $
      VALUE='Task List')

  ListVal196 = [ $
    '<empty>' ]
  LIST15 = WIDGET_DROPLIST( BASE14,VALUE=ListVal196, $
      UVALUE='LIST15',FONT=font)

  DateID = WIDGET_LABEL( BASE14, UVALUE='DateID', VALUE = 'YYYY/MM/DD')

  SchedID = WIDGET_BUTTON( BASE14, UVALUE='Sched', VALUE = 'Schedule')
  DiagID = WIDGET_BUTTON( BASE14, UVALUE='Diag', VALUE = 'Diagnostics')

  WIDGET_CONTROL, LAUNCHERMain, /REALIZE

  junk = {name:'',type:0}   ; This is merely to define the {list} structure
  junk1 = gettask(!T_FILE)        ; This is to obtain the definition of the
                                 ;   {task} structure.

  state = {textid:0L, taskid:0L, dateID:dateID, $
            index:0, files:replicate('',100), filedir:'',$
            filename:'', scan_n:1,tasks:replicate({task},gettask(/numtasks)), $
            num:0,inlist:replicate(junk,1000), MBAR:mBar}

  state.textid = LIST25
  state.taskid = LIST15

  ; If we can read some files from the data directory, set up the file list

  maxlist = 1000
  datadir = !defaults.datadir
  files = findfile(datadir+'*.ARC',count=n)
  ; Sort files into alphabetical order
  files = files(sort(strupcase(files)))

  if (n gt 0) then begin
     if (n gt maxlist) then print,'Warning: Can only handle ',maxlist,' files'
     outfiles = files(0:(n<maxlist)-1)
     for i = 0, (n<maxlist)-1 do begin
        break_file,files(i),disk,direc,filnam,ext
        outfiles(i) = filnam+ext
     endfor
     listval = outfiles
     state.filedir = disk+direc
     num = n_elements(outfiles)
     state.num = num
     if (num eq 1) then begin
        state.inlist(0).name = outfiles(0)
        state.inlist(0).type = !T_CFILE
     endif else begin
        state.inlist(0:num-1).name = outfiles
        state.inlist(0:num-1).type = !T_CFILE
     endelse
     WIDGET_CONTROL,LIST25,SET_VALUE='+ '+listval

     ; Set up initial task list for tasks that operate on files

     tlist = gettask(state.inlist(0).type)
     state.tasks(0:n_elements(tlist)-1) = tlist
     WIDGET_CONTROL,state.taskid,SET_VALUE=tlist.name
  endif else begin

    ; No files yet, so set up an empty task list

     state.tasks(0) = {task,name:'<empty>',routine:'none',type:0}
     WIDGET_CONTROL,state.taskid,SET_VALUE=state.tasks(0).name
  endelse

  ; Connect the STATE structure to the first child of the base widget

  WIDGET_CONTROL, WIDGET_INFO(LAUNCHERMain, /CHILD), SET_UVALUE=state, /NO_COPY

  XMANAGER, 'LAUNCHERMain', LAUNCHERMain, /NO_BLOCK
END
