Index: trunk/psModules/src/camera/pmFPAfileDefine.c
===================================================================
--- trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 7679)
+++ trunk/psModules/src/camera/pmFPAfileDefine.c	(revision 7728)
@@ -33,6 +33,4 @@
     PS_ASSERT_INT_POSITIVE(strlen(name), NULL);
 
-
-
     bool status;
     char *type;
@@ -118,8 +116,13 @@
     }
 
-    psMetadataAddPtr (config->files, PS_LIST_TAIL, name, PS_DATA_UNKNOWN, "", file);
-    psFree (file); // we free this copy of file, but 'files' still has a copy
-
-    return (file); // the returned value is a view into the version on 'files'
+    // XXX ppImage and similar require the added file to be unique
+    // XXX ppFocus wants to override the selection with the new selection
+    // XXX require programs like ppFocus to remove existing files by hand
+    if (!psMetadataAddPtr (config->files, PS_LIST_TAIL, name, PS_DATA_UNKNOWN, "", file)) {
+        psError (PS_ERR_IO, false, "could not add %s to config files", name);
+        return NULL;
+    }
+    psFree (file);
+    return (file);
 }
 
@@ -345,6 +348,6 @@
         psError(PS_ERR_IO, false, "file %s not defined\n", filename);
         psFree(phu);
-        psFree (fpa);
-        psFree (format);
+        psFree(fpa);
+        psFree(format);
         return NULL;
     }
@@ -411,4 +414,124 @@
 }
 
+// search for argname on the config->argument list
+// construct an FPA based on the files in this list (each represents the same FPA)
+// built the association between the FPA elements (CHIP/CELL) and the files
+// define the pmFPAfile filenames and bind them to the FPAs
+// save the pmFPAfiles on config->files
+// return the pmFPAfiles (a view to the one saved on config->files)
+pmFPAfile *pmFPAfileDefineSingleFromArgs (bool *found, pmConfig *config, char *filename, char *argname, int entry)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+    PS_ASSERT_PTR_NON_NULL(filename, NULL);
+    PS_ASSERT_INT_POSITIVE(strlen(filename), NULL);
+    PS_ASSERT_PTR_NON_NULL(argname, NULL);
+    PS_ASSERT_INT_POSITIVE(strlen(argname), NULL);
+
+    bool status;
+    pmFPA *fpa = NULL;
+    psFits *fits = NULL;
+    pmFPAfile *file = NULL;
+    psMetadata *phu = NULL;
+    psMetadata *format = NULL;
+
+    if (*found)
+        return NULL;
+
+    // we search the argument data for the named fileset (argname)
+    psArray *infiles = psMetadataLookupPtr(&status, config->arguments, argname);
+    if (!status) {
+        psTrace("pmFPAfile", 5, "Failed to find %s in argument list", argname);
+        return NULL;
+    }
+    if (infiles->n <= entry) {
+        psError(PS_ERR_IO, false, "only %d files in %s in argument, entry %d requested\n", infiles->n, argname, entry);
+        return NULL;
+    }
+
+    // examine the list of input files and validate their cameras
+    // associated each filename with an element of the FPA
+    // save the association on file->names
+    fits = psFitsOpen (infiles->data[entry], "r");
+    phu = psFitsReadHeader (NULL, fits);
+    psFitsClose (fits);
+
+    // on first call to this function, config->camera is not set.
+    // later calls will give an error if the cameras do not match
+    format = pmConfigCameraFormatFromHeader (config, phu);
+    if (!format) {
+        psError(PS_ERR_IO, false, "Failed to read CCD format from %s\n", infiles->data[0]);
+        psFree(phu);
+        return NULL;
+    }
+
+    // build the template fpa, set up the basic view
+    fpa = pmFPAConstruct (config->camera);
+    if (!fpa) {
+        psError(PS_ERR_IO, false, "Failed to construct FPA from %s", infiles->data[0]);
+        return NULL;
+    }
+
+    // load the given filerule (from config->camera) and bind it to the fpa
+    // the returned file is just a view to the entry on config->files
+    // we need a variable name here... (but in filerule)
+    file = pmFPAfileDefineInput (config, fpa, filename);
+    if (!file) {
+        psError(PS_ERR_IO, false, "file %s not defined\n", filename);
+        psFree(phu);
+        psFree(fpa);
+        psFree(format);
+        return NULL;
+    }
+    file->format = format;
+
+    // adjust the rules to identify these files in the file->names data
+    psFree (file->filerule);
+    psFree (file->filextra);
+    file->filerule = psStringCopy ("@FILES");
+    file->filextra = psStringCopy ("{CHIP.NAME}.{CELL.NAME}");
+
+    // find the matching fileLevel
+    psMetadata *filemenu = psMetadataLookupPtr (&status, format, "FILE");
+    if (!filemenu) {
+        psError (PS_ERR_IO, true, "missing FILE in FORMAT");
+        return NULL;
+    }
+    char *levelName = psMetadataLookupStr (&status, filemenu, "PHU");
+    if (!levelName) {
+        psError (PS_ERR_IO, true, "missing PHU in FILE in FORMAT");
+        return NULL;
+    }
+    file->fileLevel = pmFPALevelFromName (levelName);
+    if (file->fileLevel == PM_FPA_LEVEL_NONE) {
+        psError (PS_ERR_IO, true, "unknown level");
+        return NULL;
+    }
+
+    // set the view to the corresponding entry for this phu
+    pmFPAview *view = pmFPAAddSourceFromHeader (fpa, phu, format);
+    if (!view) {
+        psError(PS_ERR_IO, false, "Unable to determine source for %s", file->name);
+        psFree(phu);
+        psFree (fpa);
+        psFree (format);
+        return NULL;
+    }
+
+    // associate the filename with the FPA element
+    char *name = pmFPAfileNameFromRule (file->filextra, file, view);
+
+    // save the name association in the pmFPAfile structure
+    psMetadataAddStr (file->names, PS_LIST_TAIL, name, 0, "", infiles->data[entry]);
+
+    psFree (view);
+    psFree (name);
+    psFree (phu);
+    psFree (fpa);
+
+    file->format = format;
+    *found = true;
+    return file;
+}
+
 // define the named pmFPAfile from the camera->config
 // only valid for pmFPAfile->mode = READ
@@ -661,13 +784,4 @@
     file->fpa = pmFPAConstruct(file->camera);
 
-    for (int i = 0; i < file->fpa->chips->n; i++) {
-        pmChip *chip = file->fpa->chips->data[i];
-        for (int j = 0; j < chip->cells->n; j++) {
-            pmCell *cell = chip->cells->data[j];
-            char *name = psMetadataLookupStr (NULL, cell->concepts, "CELL.NAME");
-            fprintf (stderr, "cell %d,%d : %s\n", i, j, name);
-        }
-    }
-
     return file;
 }
