Index: src/hg/lib/hui.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/lib/hui.c,v
retrieving revision 1.272
retrieving revision 1.273
diff -b -B -U 4 -r1.272 -r1.273
--- src/hg/lib/hui.c	5 Apr 2010 23:39:57 -0000	1.272
+++ src/hg/lib/hui.c	12 Apr 2010 16:12:26 -0000	1.273
@@ -87,69 +87,28 @@
     }
 return FALSE;
 }
 
-static boolean metadataInTdbToggle(struct trackDb *tdb,char *title,boolean embeddedInText,boolean showLongLabel)
-/* If metadata exists, create a link that will allow toggling it's display */
-{
-metadata_t *metadata = metadataSettingGet(tdb);
-if(metadata != NULL)
-    {
-    printf("%s<A HREF='#a_meta_%s' onclick='return metadataShowHide(\"%s\");' title='Show metadata details...'>%s</A>",
-           (embeddedInText?"&nbsp;":"<P>"),tdb->tableName,tdb->tableName, title);
-    printf("<DIV id='div_%s_meta' style='display:none;'><!--<table>",tdb->tableName);
-    if(showLongLabel)
-        printf("<tr onmouseover=\"this.style.cursor='text';\"><td colspan=2>%s</td></tr>",tdb->longLabel);
-    printf("<tr onmouseover=\"this.style.cursor='text';\"><td align=right><i>shortLabel:</i></td><td nowrap>%s</td></tr>",tdb->shortLabel);
-    int ix = (sameString(metadata->values[0],"wgEncode")?1:0); // first should be project.
-    for(;ix<metadata->count;ix++)
-        {
-        if(sameString(metadata->tags[ix],"fileName"))
-            {
-            printf("<tr onmouseover=\"this.style.cursor='text';\"><td align=right><i>%s:</i></td><td nowrap>",metadata->tags[ix]);
-            makeNamedDownloadsLink(trackDbTopLevelSelfOrParent(tdb), metadata->values[ix]);
-            printf("</td></tr>");
-            }
-        else
-            if(!sameString(metadata->tags[ix],"composite"))
-                {
-                if(sameString(metadata->tags[ix],"antibody"))
-                    {
-                    int ix2 = stringArrayIx("input",metadata->tags,metadata->count);
-                    if(ix2 != -1 && sameString(metadata->values[ix],metadata->values[ix2]))
-                        continue;
-                    }
-		printf("<tr onmouseover=\"this.style.cursor='text';\"><td align=right><i>%s:</i></td><td nowrap>%s</td></tr>",metadata->tags[ix],metadata->values[ix]);
-                }
-        }
-    printf("</table>--></div>");
-    metadataFree(&metadata);
-    return TRUE;
-    }
-return FALSE;
-}
-
 static boolean metadataToggle(char *db,struct trackDb *tdb,char *title,boolean embeddedInText,boolean showLongLabel)
 /* If metadata from metaTbl if it exists, create a link that will allow toggling it's display */
 {
-struct sqlConnection *conn = sqlConnect(db);
-struct metaObj *metaObj = metaObjQueryByObj(conn,NULL,tdb->tableName,NULL);
-sqlDisconnect(&conn);
-if(metaObj != NULL && metaObj->vars != NULL)
-    {
-    printf("%s<A HREF='#a_meta_%s' onclick='return metadataShowHide(\"%s\");' title='Show metadata details...'>%s</A>",
+const struct metaObj *safeObj = metadataForTable(db,tdb,NULL);
+if(safeObj == NULL || safeObj->vars == NULL)
+return FALSE;
+
+printf("%s<A HREF='#a_meta_%s' onclick='return metadataShowHide(\"%s\");' title='Show metadata details...'>%s</A>",
            (embeddedInText?"&nbsp;":"<P>"),tdb->tableName,tdb->tableName, title);
-    printf("<DIV id='div_%s_meta' style='display:none;'><!--<table>",tdb->tableName);
-    if(showLongLabel)
+printf("<DIV id='div_%s_meta' style='display:none;'><!--<table>",tdb->tableName);
+if(showLongLabel)
         printf("<tr onmouseover=\"this.style.cursor='text';\"><td colspan=2>%s</td></tr>",tdb->longLabel);
-    printf("<tr onmouseover=\"this.style.cursor='text';\"><td align=right><i>shortLabel:</i></td><td nowrap>%s</td></tr>",tdb->shortLabel);
+printf("<tr onmouseover=\"this.style.cursor='text';\"><td align=right><i>shortLabel:</i></td><td nowrap>%s</td></tr>",tdb->shortLabel);
 
-    metaObjRemoveVars(metaObj,"composite project tableName"); // Don't bother showing these (suggest: "composite project dataType view tableName")
-    // FIXME: Leaving tableName out as s clear difference between netaTbl and trackDb setting.  Could add back in if desired.
-    metaObjReorderVars(metaObj,"grant lab dataType cell treatment antibody protocol input view",FALSE); // Bring to front
-    metaObjReorderVars(metaObj,"subId submittedDataVersion dateSubmitted dateResubmitted dateUnrestricted dataVersion tableName fileName",TRUE); // Send to back
-    struct metaVar *metaVar;
-    for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
+struct metaObj *metaObj = metaObjClone(safeObj); // Important if we are going to remove vars!
+metaObjRemoveVars(metaObj,"composite project"); // Don't bother showing these (suggest: "composite project dataType view tableName")
+metaObjReorderVars(metaObj,"grant lab dataType cell treatment antibody protocol input view",FALSE); // Bring to front
+metaObjReorderVars(metaObj,"subId submittedDataVersion dateSubmitted dateResubmitted dateUnrestricted dataVersion tableName fileName",TRUE); // Send to back
+struct metaVar *metaVar;
+for(metaVar=metaObj->vars;metaVar!=NULL;metaVar=metaVar->next)
         {
         if(sameString(metaVar->var,"fileName"))
             {
             printf("<tr onmouseover=\"this.style.cursor='text';\"><td align=right><i>%s:</i></td><td nowrap>",metaVar->var);
@@ -164,25 +123,19 @@
 
             printf("<tr onmouseover=\"this.style.cursor='text';\"><td align=right><i>%s:</i></td><td nowrap>%s</td></tr>",metaVar->var,metaVar->val);
             }
         }
-    printf("</table>--></div>");
-    metaObjsFree(&metaObj);
-    return TRUE;
-    }
-else
-    return metadataInTdbToggle(tdb,title,embeddedInText,showLongLabel); // FIXME: This should be removed when all metadata is in metaTbl!!!
-
-return FALSE;
+printf("</table>--></div>");
+return TRUE;
 }
 
 void extraUiLinks(char *db,struct trackDb *tdb)
 /* Show downlaods, schema and metadata links where appropriate */
 {
 boolean schemaLink = (isCustomTrack(tdb->tableName) == FALSE)
                   && (hTableOrSplitExists(db, tdb->tableName));
-boolean metadataLink = (!tdbIsComposite(tdb))
-                  && trackDbSetting(tdb, "metadata");
+boolean metadataLink = (!tdbIsComposite(tdb)
+                  && metadataForTable(db, tdb, NULL) != NULL);
 boolean downloadLink = (trackDbSetting(tdb, "wgEncode") != NULL);
 boolean moreThanOne = (schemaLink && metadataLink)
                    || (schemaLink && downloadLink)
                    || (downloadLink && metadataLink);
@@ -3191,9 +3144,9 @@
                         break;
     }
 }
 
-char *encodeRestrictionDateDisplay(struct trackDb *trackDb)
+char *encodeRestrictionDateDisplay(char *db,struct trackDb *trackDb)
 /* Create a string for ENCODE restriction date of this track
    if return is not null, then free it after use */
 {
 if (!trackDb)
@@ -3197,21 +3150,21 @@
    if return is not null, then free it after use */
 {
 if (!trackDb)
     return NULL;
+
 boolean addMonths = FALSE;
-char *date = metadataSettingFind(trackDb,"dateUnrestricted");
-if(date == NULL)
+char *date = NULL;
+
+if(metadataForTable(db,trackDb,NULL) != NULL)
     {
-    date = metadataSettingFind(trackDb,"dateSubmitted");
+    addMonths = FALSE;
+    date = cloneString((char *)metadataFindValue(trackDb,"dateUnrestricted"));
+    if(date == NULL)
+        {
+        date = cloneString((char *)metadataFindValue(trackDb,"dateSubmitted"));
     addMonths = TRUE;
     }
-if(date == NULL)
-    {
-    addMonths = FALSE;
-    date = trackDbSetting(trackDb, "dateUnrestricted");
-    if(date)
-        date = cloneString(date); // all returns should be freeable memory
     }
 if(date == NULL)
     {
     date = trackDbSetting(trackDb, "dateSubmitted");
@@ -3237,8 +3190,32 @@
     printf("<script type='text/javascript'>compositeCfgRegisterOnchangeAction(\"%s\")</script>\n",prefix);
 }
 
 #define TV_HIDE "hide"
+static boolean subtracksViewIsHidden(struct cart *cart,struct trackDb *subtrack)
+// Returns TRUE if the subtrack belongs to a view that is hidden
+{
+if(subgroupFind(subtrack,"view",NULL) == FALSE)
+    return FALSE; // No view
+
+if(subtrack->parent == NULL || subtrack->parent->parent != NULL)
+    return FALSE; // Not the subtrack
+
+char * view = trackDbLocalSetting(subtrack->parent, "view");
+if(view == NULL) // assertably not null!
+    return FALSE; // This had better be found
+
+char objName[SMALLBUF];
+char *setting =trackDbLocalSetting(subtrack->parent, "visibility");
+if(setting == NULL)
+    setting = TV_HIDE;
+
+safef(objName, sizeof(objName), "%s.%s.vis", subtrack->parent->parent->tableName,view);
+
+setting = cartUsualString(cart, objName, setting); // Not ClosestToHome
+return sameString(setting,TV_HIDE);
+}
+
 char *tdbResolveVis(struct cart *cart,struct trackDb *tdb, boolean applyMax)
 // Determines the correct vis for a tdb as modified by parent
 {
 // Vis can be in trackDb and/or in cart
@@ -3279,31 +3256,45 @@
 
 return setting; // nothing found
 }
 
+// Four State checkboxes bcan be checked/unchecked by enable/disabled
+#define FOURSTATE_KEY               "fourState"
+#define FOURSTATE_EMPTY             666
+#define FOURSTATE_UNCHECKED         0
+#define FOURSTATE_CHECKED           1
+#define FOURSTATE_DISABLE(val)      {while((val) >= 0) (val) -= 2;}
+#define FOURSTATE_ENABLE(val)       {while((val) < 0) (val) += 2;}
+#define fourStateChecked(fourState) ((fourState) == 1 || (fourState) == -1)
+#define fourStateEnabled(fourState) ((fourState) >= 0)
+
 static int subtrackFourStateChecked(struct trackDb *subtrack, struct cart *cart)
 /* Returns the four state checked state of the subtrack */
 {
 char * setting = NULL;
 char objName[SMALLBUF];
-int fourState = 0;
+int fourState = (int)(long)tdbExtrasGetOrDefault(subtrack,FOURSTATE_KEY,(void *)FOURSTATE_EMPTY);
+if(fourState != FOURSTATE_EMPTY)
+    return fourState;
+
+fourState = FOURSTATE_UNCHECKED;  // default to unchecked, enabled
 if ((setting = trackDbLocalSetting(subtrack, "parent")) != NULL)
     {
     if(findWordByDelimiter("off",' ',setting) == NULL)
-        fourState = 1;
+        fourState = FOURSTATE_CHECKED;
     }
 // Now check visibility
 setting = tdbResolveVis(cart,subtrack,FALSE);
 
-// commenting these out until Tim returns because it breaks tracks without views
-//if(sameWord(setting,TV_HIDE))
-    //fourState -= 2; // visibility: hide means -1 or -2
+// If subtrack's view is hide then fourstate includes disabled
+if(sameWord(setting,TV_HIDE) && subtracksViewIsHidden(cart,subtrack))
+    FOURSTATE_DISABLE(fourState);
 
 safef(objName, sizeof(objName), "%s_sel", subtrack->tableName);
-return cartUsualInt(cart, objName, fourState);
+fourState = cartUsualInt(cart, objName, fourState);
+tdbExtrasAddOrUpdate(subtrack,FOURSTATE_KEY,(void *)(long)fourState);
+return fourState;
 }
-#define fourStateChecked(fourState) ((fourState) == 1 || (fourState) == -1)
-#define fourStateEnabled(fourState) ((fourState) >= 0)
 
 static void compositeUiSubtracks(char *db, struct cart *cart, struct trackDb *parentTdb,
                  boolean selectedOnly, char *primarySubtrack)
 /* Display list of subtracks and descriptions with checkboxes to control visibility and possibly other
@@ -3364,12 +3355,12 @@
     boolean restrictions = FALSE;
     for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next)
         {
 	subtrack = subtrackRef->val;
-        char *date = metadataSettingFind(subtrack,"dateUnrestricted");
-        if(date != NULL)
+        (void)metadataForTable(db,subtrack,NULL);
+        const char *date = metadataFindValue(subtrack,"dateUnrestricted");
+        if(date != NULL) // Note this is stale memory (just freed), but non-NULL means found.
             {
-            freeMem(date);
             restrictions = TRUE;
             break;
             }
         }
@@ -3552,9 +3543,9 @@
             printf("<TD nowrap>&nbsp;");
             makeSchemaLink(db,subtrack,"schema");
             puts("&nbsp;");
 
-            char *dateDisplay = encodeRestrictionDateDisplay(subtrack);
+            char *dateDisplay = encodeRestrictionDateDisplay(db,subtrack);
             if (dateDisplay)
                 printf("</TD><TD align=\"CENTER\">&nbsp;%s&nbsp;", dateDisplay);
 
             puts("</TD></TR>");
@@ -5235,13 +5226,14 @@
 freeMem(matchedSubtracks);
 return TRUE;
 }
 
-static char *labelWithVocabLink(struct trackDb *parentTdb, struct trackDb *childTdb, char *vocabType, char *label)
+static char *labelWithVocabLink(char *db,struct trackDb *parentTdb, struct trackDb *childTdb, char *vocabType, char *label)
 /* If the parentTdb has a controlledVocabulary setting and the vocabType is found,
    then label will be wrapped with the link to display it.  Return string is cloned. */
 {
 char *vocab = trackDbSetting(parentTdb, "controlledVocabulary");
+(void)metadataForTable(db,childTdb,NULL);
 if(vocab == NULL)
     return cloneString(label); // No wrapping!
 
 char *words[15];
@@ -5271,19 +5263,18 @@
         strSwapChar(words[ix],'=',0);
         if(sameString(vocabType,words[ix]))  // tags match, but search for term
             {
             char * cvSetting = words[ix] + strlen(words[ix]) + 1;
-            char * cvTerm = metadataSettingFind(childTdb, cvSetting);
+            const char * cvTerm = metadataFindValue(childTdb,cvSetting);
             if(cvTerm != NULL)
                 {
-                char *encodedTerm = cgiEncode(cvTerm);
+                char *encodedTerm = cgiEncode((char *)cvTerm);
                 int sz=strlen(VOCAB_LINK)+strlen(words[0])+strlen(encodedTerm)+2*strlen(label) + 2;
                 char *link=needMem(sz);
                 safef(link,sz,VOCAB_LINK,words[0],encodedTerm,cvTerm,rootLabel);
                 if(suffix)
                     safecat(link,sz,suffix);
                 freeMem(words[0]);
-                freeMem(cvTerm);
                 freeMem(encodedTerm);
                 return link;
                 }
             }
@@ -5307,9 +5298,9 @@
 }
 
 #define MATRIX_RIGHT_BUTTONS_AFTER 8
 #define MATRIX_BOTTOM_BUTTONS_AFTER 20
-static void matrixXheadingsRow1(struct trackDb *parentTdb, members_t *dimensionX,members_t *dimensionY,struct trackDb **tdbsX,boolean top)
+static void matrixXheadingsRow1(char *db,struct trackDb *parentTdb, members_t *dimensionX,members_t *dimensionY,struct trackDb **tdbsX,boolean top)
 /* prints the top row of a matrix: 'All' buttons; X titles; buttons 'All' */
 {
 printf("<TR ALIGN=CENTER BGCOLOR='%s' valign=%s>\n",COLOR_BG_ALTDEFAULT,top?"BOTTOM":"TOP");
 if(dimensionX && dimensionY)
@@ -5331,9 +5322,9 @@
         {
         if(tdbsX[ixX] != NULL)
             {
             char *label = replaceChars(dimensionX->values[ixX]," (","<BR>(");//
-            printf("<TH WIDTH='60'>&nbsp;%s&nbsp;</TH>",labelWithVocabLink(parentTdb,tdbsX[ixX],dimensionX->tag,label));
+            printf("<TH WIDTH='60'>&nbsp;%s&nbsp;</TH>",labelWithVocabLink(db,parentTdb,tdbsX[ixX],dimensionX->tag,label));
             freeMem(label);
             cntX++;
             }
         }
@@ -5388,33 +5379,33 @@
     puts("</TR>\n");
     }
 }
 
-static void matrixXheadings(struct trackDb *parentTdb, members_t *dimensionX,members_t *dimensionY,struct trackDb **tdbsX,boolean top)
+static void matrixXheadings(char *db,struct trackDb *parentTdb, members_t *dimensionX,members_t *dimensionY,struct trackDb **tdbsX,boolean top)
 /* UI for X headings in matrix */
 {
 if(top)
-    matrixXheadingsRow1(parentTdb,dimensionX,dimensionY,tdbsX,top);
+    matrixXheadingsRow1(db,parentTdb,dimensionX,dimensionY,tdbsX,top);
 
     matrixXheadingsRow2(parentTdb,dimensionX,dimensionY,tdbsX);
 
 if(!top)
-    matrixXheadingsRow1(parentTdb,dimensionX,dimensionY,tdbsX,top);
+    matrixXheadingsRow1(db,parentTdb,dimensionX,dimensionY,tdbsX,top);
 }
 
-static void matrixYheadings(struct trackDb *parentTdb, members_t *dimensionX,members_t *dimensionY,int ixY,struct trackDb *childTdb,boolean left)
+static void matrixYheadings(char *db,struct trackDb *parentTdb, members_t *dimensionX,members_t *dimensionY,int ixY,struct trackDb *childTdb,boolean left)
 /* prints the top row of a matrix: 'All' buttons; X titles; buttons 'All' */
 {
 if(dimensionX && dimensionY && childTdb != NULL) // Both X and Y, then column of buttons
     {
     char objName[SMALLBUF];
     printf("<TH ALIGN=%s nowrap colspan=2>",left?"RIGHT":"LEFT");
     if(left)
-        printf("%s&nbsp;",labelWithVocabLink(parentTdb,childTdb,dimensionY->tag,dimensionY->values[ixY]));
+        printf("%s&nbsp;",labelWithVocabLink(db,parentTdb,childTdb,dimensionY->tag,dimensionY->values[ixY]));
     safef(objName, sizeof(objName), "plus_all_%s", dimensionY->names[ixY]);
     buttonsForOne( objName, dimensionY->names[ixY] );
     if(!left)
-        printf("&nbsp;%s",labelWithVocabLink(parentTdb,childTdb,dimensionY->tag,dimensionY->values[ixY]));
+        printf("&nbsp;%s",labelWithVocabLink(db,parentTdb,childTdb,dimensionY->tag,dimensionY->values[ixY]));
     puts("</TH>");
     }
 else if (dimensionX)
     {
@@ -5422,12 +5413,12 @@
     buttonsForAll();
     puts("</TH>");
     }
 else if (left && dimensionY && childTdb != NULL)
-    printf("<TH ALIGN=RIGHT nowrap>%s</TH>\n",labelWithVocabLink(parentTdb,childTdb,dimensionY->tag,dimensionY->values[ixY]));
+    printf("<TH ALIGN=RIGHT nowrap>%s</TH>\n",labelWithVocabLink(db,parentTdb,childTdb,dimensionY->tag,dimensionY->values[ixY]));
 }
 
-static int displayABCdimensions(struct cart *cart, struct trackDb *parentTdb, struct slRef *subtrackRefList, membersForAll_t* membersForAll)
+static int displayABCdimensions(char *db,struct cart *cart, struct trackDb *parentTdb, struct slRef *subtrackRefList, membersForAll_t* membersForAll)
 /* This will walk through all declared nonX&Y dimensions (X and Y is the 2D matrix of CBs.
    NOTE: ABC dims are only supported if there are X & Y both.  Also expected number should be passed in */
 {
 int count=0,ix;
@@ -5475,9 +5466,9 @@
             safef(objName, sizeof(objName), "%s.mat_%s_dim%c_cb",parentTdb->tableName,membersForAll->members[ix]->names[aIx], 'A' + (ix - dimA));
             safef(javascript,sizeof(javascript),"onclick='matCbClick(this);' class=\"matCB abc %s\"",membersForAll->members[ix]->names[aIx]);
             // TODO Set classes properly (if needed!!!)  The class abc works but what about a b or c?
             cgiMakeCheckBoxJS(objName,alreadySet,javascript);
-            printf("%s",labelWithVocabLink(parentTdb,tdbs[aIx],membersForAll->members[ix]->tag,membersForAll->members[ix]->values[aIx]));
+            printf("%s",labelWithVocabLink(db,parentTdb,tdbs[aIx],membersForAll->members[ix]->tag,membersForAll->members[ix]->values[aIx]));
             puts("</TH>");
             }
         }
     puts("</TR>");
@@ -5556,9 +5547,8 @@
         }
     if(ixX > -1 && ixY > -1)
         {
         cells[ixX][ixY]++;
-        // FIXME This mess should be done once per subtrack, stored in the struct, then reused when subCBs are written out.
         int fourState = subtrackFourStateChecked(subtrack,cart);
         if(fourStateEnabled(fourState) >= 0)  // hidden views are handled by 4-way CBs: only count enabled
             {
             if(subtrackInAllCurrentABCs(subtrack,membersForAll))  // Only bother if the subtrack is found in all ABC dims checked
@@ -5589,14 +5579,14 @@
 puts("<BR>\n");
 
 if(membersForAll->dimensions->count > 2)
     {
-    displayABCdimensions(cart,parentTdb,subtrackRefList,membersForAll);  // No dimABCs without X & Y both
+    displayABCdimensions(db,cart,parentTdb,subtrackRefList,membersForAll);  // No dimABCs without X & Y both
     }
 
 printf("<TABLE class='greenBox' bgcolor='%s' borderColor='%s'>\n",COLOR_BG_DEFAULT,COLOR_BG_DEFAULT);
 
-matrixXheadings(parentTdb,membersForAll->members[dimX],membersForAll->members[dimY],tdbsX,TRUE);
+matrixXheadings(db,parentTdb,membersForAll->members[dimX],membersForAll->members[dimY],tdbsX,TRUE);
 
 // Now the Y by X matrix
 int cntX=0,cntY=0;
 for (ixY = 0; ixY < sizeOfY; ixY++)
@@ -5606,9 +5596,9 @@
         cntY++;
         assert(!membersForAll->members[dimY] || ixY < membersForAll->members[dimY]->count);
         printf("<TR ALIGN=CENTER BGCOLOR=\"#FFF9D2\">");
 
-        matrixYheadings(parentTdb, membersForAll->members[dimX],membersForAll->members[dimY],ixY,tdbsY[ixY],TRUE);
+        matrixYheadings(db,parentTdb, membersForAll->members[dimX],membersForAll->members[dimY],ixY,tdbsY[ixY],TRUE);
 
 #define MAT_CB_SETUP "<INPUT TYPE=CHECKBOX NAME='%s' VALUE=on %s>"
 #define MAT_CB(name,js) printf(MAT_CB_SETUP,(name),(js));
         for (ixX = 0; ixX < sizeOfX; ixX++)
@@ -5654,14 +5644,14 @@
                     puts("<TD>&nbsp;</TD>");
                 }
             }
         if(membersForAll->members[dimX] && cntX>MATRIX_RIGHT_BUTTONS_AFTER)
-            matrixYheadings(parentTdb, membersForAll->members[dimX],membersForAll->members[dimY],ixY,tdbsY[ixY],FALSE);
+            matrixYheadings(db,parentTdb, membersForAll->members[dimX],membersForAll->members[dimY],ixY,tdbsY[ixY],FALSE);
         puts("</TR>\n");
         }
     }
 if(membersForAll->members[dimY] && cntY>MATRIX_BOTTOM_BUTTONS_AFTER)
-    matrixXheadings(parentTdb,membersForAll->members[dimX],membersForAll->members[dimY],tdbsX,FALSE);
+    matrixXheadings(db,parentTdb,membersForAll->members[dimX],membersForAll->members[dimY],tdbsX,FALSE);
 
 puts("</TD></TR></TABLE>");
 
 puts("<BR>\n");

