1 /******************************************************************************
2 *
3 *  NSSDC/CDF                            CDFedit, part 1 (attributes/entries).
4 *
5 *  Version 1.3c, 16-Nov-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  24-Jan-94, J Love     Original version.
10 *   V1.0a  4-Feb-94, J Love     DEC Alpha/OpenVMS port.
11 *   V1.0b 22-Feb-94, J Love     Spelling lesson.
12 *   V1.1  15-Dec-94, J Love     CDF V2.5.
13 *   V1.1a 23-Jan-95, J Love	IRIX 6.x (64-bit).
14 *   V1.1b 28-Feb-95, J Love	Solaris 2.3.  Pass `char' as `int'.
15 *   V1.2  11-Apr-95, J Love	POSIX.
16 *   V1.2a 11-May-95, J Love	EPOCH styles.
17 *   V1.2b  9-Jun-95, J Love	catchrX.
18 *   V1.2c  6-Sep-95, J Love	CDFexport-related changes.  FSI key
19 *				definitions.
20 *   V1.3  30-Sep-96, J Love	CDF V2.6.
21 *   V1.3a 19-Dec-96, J Love	Display error if attempt to browse/edit a
22 *				vAttribute's entries in "text mode" is made.
23 *   V1.3b  2-Sep-97, J Love	Fixed attribute name declaration.
24 *   V1.3c 16-Nov-97, J Love	Windows NT/Visual C++.
25 *
26 ******************************************************************************/
27 
28 #include "cdfedit.h"
29 
30 /******************************************************************************
31 * EditAttrs.
32 ******************************************************************************/
33 
EditAttrs(G,CDFname)34 Logical EditAttrs (G, CDFname)
35 Logical G;                      /* If TRUE, global scoped attributes. */
36 char *CDFname;                  /* Name of the CDF being edited. */
37 {
38    CDFstatus status; int attrX, entryX, entryType;
39    long attrN, entryN, fieldN, *nEntries, *attrNs, **entryNs;
40    long nAttrs;                 /* Number of attributes of the proper scope. */
41    AOSs2 (header, BLANKs78, BLANKs78)
42    AOSs1 (trailerBrowse,
43 	  "Select: ________   Exit: ________   Help: ________")
44    AOSs3 (trailerEdit,
45 "Select: ________ Create attribute: ________ Delete attribute/entry: ________",
46 "Help:   ________ Create entry:     ________",
47 "Exit:   ________ Toggle scope:     ________")
48    static int exitCharsBrowse[] = {
49      ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL
50    };
51    static int exitCharsEdit[] = {
52      ENTERkey_FSI, CREATEATTRkey_EDIT, EXITkey_FSI, HELPkey_FSI,
53      CREATEENTRYkey_EDIT, TOGGLESCOPEkey_EDIT, DELETEATTRorENTRYkey_EDIT, NUL
54    };
55    static char label[6+DU_MAX_NAME_LEN+14+1];
56    static struct ItemWindowStruct IW = {
57       0, 0, 80, label, 2, header, 0, NULL, 0, NULL, NULL, NULL, 0, 0, NULL,
58       NULL, REFRESHkey_FSI, TRUE, NSkey_FSI, PSkey_FSI
59    };
60    static Logical first = TRUE;
61    /***************************************************************************
62    * First time...
63    ***************************************************************************/
64    if (first) {
65      EncodeKeyDefinitions (1, trailerBrowse, ENTERkey_FSI, EXITkey_FSI,
66 			     HELPkey_FSI);
67      EncodeKeyDefinitions (3, trailerEdit, ENTERkey_FSI,
68 			     CREATEATTRkey_EDIT, DELETEATTRorENTRYkey_EDIT,
69 			     HELPkey_FSI, CREATEENTRYkey_EDIT, EXITkey_FSI,
70 			     TOGGLESCOPEkey_EDIT);
71      first = FALSE;
72    }
73 	 if (browseOnly) {
74        IW.NiRows = 14;
75        IW.NtLines = 1;
76        IW.tLines = trailerBrowse;
77        IW.exitChars = exitCharsBrowse;
78      }
79      else {
80        IW.NiRows = 12;
81        IW.NtLines = 3;
82        IW.tLines = trailerEdit;
83        IW.exitChars = exitCharsEdit;
84      }
85    /***************************************************************************
86    * Build attribute/entry lines and display menu.
87    ***************************************************************************/
88    if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
89 		      &nEntries,&entryNs,&IW)) return FALSE;
90    ItemWindow (NEWiw, &IW, 0);
91    /***************************************************************************
92    * Read/process keystrokes until request to exit menu.
93    ***************************************************************************/
94    for (;;) {
95      ItemWindow (READiw, &IW);
96      switch (IW.key) {
97        /***********************************************************************
98        * Item selected.
99        ***********************************************************************/
100        case ENTERkey_FSI: {
101 	 int nameItemN;
102 	 /*********************************************************************
103 	 * Check if any attributes/entries exist.
104 	 *********************************************************************/
105 	 if (IW.nItems == 0) {
106 	   ProblemWindow (BOO(G,"Nothing selected (no gAttributes exist).",
107 			        "Nothing selected (no vAttributes exist)."),
108 			  FALSE);
109 	   break;
110 	 }
111 	 /*********************************************************************
112 	 * Calculate attribute, entry, and field numbers.
113 	 *********************************************************************/
114 	 for (attrX = 0, nameItemN = 0; attrX < nAttrs; attrX++) {
115 	    int nItems = (int) (1 + (4 * nEntries[attrX]));
116 	    if (IW.itemN < nameItemN + nItems) {
117 	      int itemNt = IW.itemN - nameItemN;
118 	      attrN = attrNs[attrX];
119 	      if (itemNt == 0)
120 		fieldN = 0;
121 	      else {
122 		fieldN = ((itemNt - 1) % 4) + 1;
123 		entryX = (itemNt - 1) / 4;
124 		entryN = entryNs[attrX][entryX];
125 		if (G)
126 		  entryType = gENTRYt;
127 		else {
128 		  long NrEntries;
129 		  status = CDFlib (SELECT_, ATTR_, attrN,
130 				   GET_, ATTR_NUMrENTRIES_, &NrEntries,
131 				   NULL_);
132 		  if (!ReportStatus(status,FALSE)) {
133 		    ItemWindow (DELETEiw, &IW);
134 		    return FALSE;
135 		  }
136 		  entryType = (entryX < NrEntries ? rENTRYt : zENTRYt);
137 		}
138 	      }
139 	      break;
140 	    }
141 	    nameItemN += nItems;
142 	 }
143 	 /*********************************************************************
144 	 * Perform desired function (based on field number).
145 	 *********************************************************************/
146 	 switch (fieldN) {
147 	   /*******************************************************************
148 	   * Modify attribute name.
149 	   *******************************************************************/
150 	   case 0: {
151 	     char attrName[CDF_ATTR_NAME_LEN256+1];
152 	     status = CDFlib (SELECT_, ATTR_, attrN,
153 			      GET_, ATTR_NAME_, attrName,
154 			      NULL_);
155 	     if (!ReportStatus(status,FALSE)) {
156 	       ItemWindow (DELETEiw, &IW);
157 	       return FALSE;
158 	     }
159 	     if (browseOnly)
160 	       ShowFullName (attrName, TRUE);
161 	     else {
162 	       static char *header[] = {
163 	         "Enter new name (with delimiters)...",
164 	         "Syntax: <delim><char1><char2>...<charN><delim>",
165 	         "Example: \"FILTERs\""
166 	       };
167 	       AOSs1 (trailer,
168 		      "Enter: ________   Exit: ________  Help: ________")
169 	       static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI,
170 					  HELPkey_FSI, NUL };
171 	       static char value[1+CDF_ATTR_NAME_LEN256+1+1];
172 	       static char label[15+CDF_ATTR_NAME_LEN256+1];
173 	       static struct PromptWindowStruct PWt = {
174 		  label, 4, 1, 78, 3, header, CDF_ATTR_NAME_LEN256+2, value,
175 		  1, trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI,
176 		  EOLkey_FSI, INSERTorOVERkey_FSI
177 	       };
178 	       char delim;
179 	       EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
180 				     HELPkey_FSI);
181 	       delim = PickDelimiter (attrName, strlen(attrName));
182 	       sprintf (value, "%c%s%c", delim, attrName, delim);
183 	       sprintf (label, " %cAttribute %c%s%c ", BOO(G,'g','v'),
184 		        delim, attrName, delim);
185 	       PromptWindow (NEWpw, &PWt, (int) (strlen(PWt.value) - 1),
186 			     LogicalTRUE);
187 	       for (;;) {
188 		  if (EnterPW(&PWt,ATTRRENAMEhelpID)) {
189 		    char attrName[CDF_ATTR_NAME_LEN256+1];
190 		    if (DecodeDelimitedString(PWt.value,attrName)) {
191 		      status = CDFlib (PUT_, ATTR_NAME_, attrName,
192 				       NULL_);
193 		      if (ReportStatus(status,FALSE)) {
194 		        FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
195 		        if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
196 					   &nEntries,&entryNs,&IW)) {
197 			  ItemWindow (DELETEiw, &IW);
198 			  return FALSE;
199 			}
200 		        ItemWindow (UPDATEiw, &IW, IW.itemN);
201 		        break;
202 		      }
203 		      if (NoMoreAccess(NULL)) {
204 			PromptWindow (DELETEpw, &PWt);
205 			ItemWindow (DELETEiw, &IW);
206 			return FALSE;
207 		      }
208 		    }
209 		    else
210 		      ProblemWindow ("Illegal name (check delimiters).",
211 				     FALSE);
212 		  }
213 		  else
214 		    break;
215 	       }
216 	       PromptWindow (DELETEpw, &PWt);
217 	     }
218 	     break;
219 	   }
220 	   /*******************************************************************
221 	   * Modify variable name/global entry number.
222 	   *******************************************************************/
223 	   case 1: {
224 	     if (G)
225 	       ItemWindow (BEEPiw, &IW);
226 	     else {
227 	       char varName[CDF_VAR_NAME_LEN256+1];
228 	       Logical Z = (entryType == zENTRYt); long nVars;
229 	       status = CDFlib (GET_, BOO(Z,CDF_NUMzVARS_,
230 					    CDF_NUMrVARS_), &nVars,
231 				NULL_);
232 	       if (!ReportStatus(status,FALSE)) {
233 		 ItemWindow (DELETEiw, &IW);
234 		 return FALSE;
235 	       }
236 	       if (nVars <= entryN) {
237 		 ProblemWindow (BOO(Z,"No corresponding zVariable.",
238 				      "No corresponding rVariable."), FALSE);
239 		 break;
240 	       }
241 	       status = CDFlib (SELECT_, VAR(Z), entryN,
242 				GET_, VAR_NAME(Z), varName,
243 				NULL_);
244 	       if (!ReportStatus(status,FALSE)) {
245 		 ItemWindow (DELETEiw, &IW);
246 		 return FALSE;
247 	       }
248 	       if (browseOnly)
249 		 ShowFullName (varName, FALSE);
250 	       else {
251 	         static char *header[] = {
252 		   "Enter new name (with delimiters)...",
253 		   "Syntax: <delim><char1><char2>...<charN><delim>",
254 		   "Example: \"Humidity\""
255 	         };
256 	         AOSs1 (trailer,
257 		        "Enter: ________   Exit: ________  Help: ________")
258 	         static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI,
259 					    HELPkey_FSI, NUL };
260 	         static char value[1+CDF_VAR_NAME_LEN256+1+1];
261 	         static char label[14+CDF_VAR_NAME_LEN256+1];
262 	         static struct PromptWindowStruct PWt = {
263 		    label, 4, 1, 78, 3, header, CDF_VAR_NAME_LEN256+2, value,
264 		    1, trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI,
265 		    EOLkey_FSI, INSERTorOVERkey_FSI
266 	         };
267 		 char delim;
268 	         EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
269 				       HELPkey_FSI);
270 	         delim = PickDelimiter (varName, strlen(varName));
271 	         sprintf (value, "%c%s%c", delim, varName, delim);
272 	         sprintf (label, " %cVariable %c%s%c ", BOO(Z,'z','r'),
273 			  delim, varName, delim);
274 	         PromptWindow (NEWpw, &PWt, (int) (strlen(PWt.value) - 1),
275 			       LogicalTRUE);
276 	         for (;;) {
277 		    if (EnterPW(&PWt,VARRENAMEhelpID)) {
278 		      char varName[CDF_VAR_NAME_LEN256+1];
279 		      if (DecodeDelimitedString(PWt.value,varName)) {
280 		        status = CDFlib (PUT_, VAR_NAME(Z), varName,
281 				         NULL_);
282 		        if (ReportStatus(status,FALSE)) {
283 			  FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs,
284 					&IW);
285 			  if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
286 					     &nEntries,&entryNs,&IW)) {
287 			    ItemWindow (DELETEiw, &IW);
288 			    return FALSE;
289 			  }
290 			  ItemWindow (UPDATEiw, &IW, IW.itemN);
291 			  break;
292 		        }
293 			if (NoMoreAccess(NULL)) {
294 			  PromptWindow (DELETEpw, &PWt);
295 			  ItemWindow (DELETEiw, &IW);
296 			  return FALSE;
297 			}
298 		      }
299 		      else
300 		        ProblemWindow ("Illegal name (check delimiters).",
301 				       FALSE);
302 		    }
303 		    else
304 		      break;
305 	         }
306 	         PromptWindow (DELETEpw, &PWt);
307 	       }
308 	     }
309 	     break;
310 	   }
311 	   /*******************************************************************
312 	   * Modify data specification.
313 	   *******************************************************************/
314 	   case 2: {
315 	     if (browseOnly)
316 	       ItemWindow (BEEPiw, &IW);
317 	     else {
318 	       long dataType, numElems;
319 	       if (G)
320 	         sprintf (label, " gEntry %ld ", entryN + 1);
321 	       else {
322 	         Logical Z = (entryType == zENTRYt);
323 	         char varName[CDF_VAR_NAME_LEN256+1], delim;
324 	         status = CDFlib (SELECT_, VAR(Z), entryN,
325 				  GET_, VAR_NAME(Z), varName,
326 				  NULL_);
327 	         switch (status) {
328 		   case NO_SUCH_VAR:
329 		     sprintf (label," %cEntry %ld ",BOO(Z,'z','r'),entryN+1);
330 		     break;
331 		   default:
332 		     if (!ReportStatus(status,FALSE)) {
333 		       ItemWindow (DELETEiw, &IW);
334 		       return FALSE;
335 		     }
336 		     delim = PickDelimiter (varName, strlen(varName));
337 		     sprintf (label, " %cEntry for %c%s%c ", BOO(Z,'z','r'),
338 			      delim, varName, delim);
339 		     break;
340 	         }
341 	       }
342 	       status = CDFlib (SELECT_, ATTR_, attrN,
343 				         ENTRY(entryType), entryN,
344 			        GET_, ENTRY_DATATYPE(entryType), &dataType,
345 			        NULL_);
346 	       if (!ReportStatus(status,FALSE)) {
347 		 ItemWindow (DELETEiw, &IW);
348 		 return FALSE;
349 	       }
350 	       if (SelectDataSpec(&dataType,NULL,label)) {
351 		 status = CDFlib (GET_, ENTRY_NUMELEMS(entryType), &numElems,
352 				  NULL_);
353 		 if (!ReportStatus(status,FALSE)) {
354 		   ItemWindow (DELETEiw, &IW);
355 		   return FALSE;
356 		 }
357 		 status = CDFlib (PUT_, ENTRY_DATASPEC(entryType), dataType,
358 								   numElems,
359 				  NULL_);
360 		 if (ReportStatus(status,FALSE)) {
361 		   FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
362 		   if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
363 				      &nEntries,&entryNs,&IW)) {
364 		     ItemWindow (DELETEiw, &IW);
365 		     return FALSE;
366 		   }
367 		   ItemWindow (UPDATEiw, &IW, IW.itemN);
368 		   break;
369 		 }
370 		 if (NoMoreAccess(NULL)) {
371 		   ItemWindow (DELETEiw, &IW);
372 		   return FALSE;
373 		 }
374 	       }
375 	     }
376 	     break;
377 	   }
378 	   /*******************************************************************
379 	   * Modify data specification/value(s).
380 	   *******************************************************************/
381 	   case 3: {
382 	     if (browseOnly)
383 	       ItemWindow (BEEPiw, &IW);
384 	     else {
385 	       Logical changed = FALSE;
386 	       if (!EditEntry(attrN,entryN,entryType,TRUE,&changed)) {
387 		 ItemWindow (DELETEiw, &IW);
388 		 return FALSE;
389 	       }
390 	       if (changed) {
391 	         FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
392 	         if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
393 				    &nEntries,&entryNs,&IW)) {
394 		   ItemWindow (DELETEiw, &IW);
395 		   return FALSE;
396 		 }
397 	         ItemWindow (UPDATEiw, &IW, IW.itemN);
398 	       }
399 	     }
400 	     break;
401 	   }
402 	   /*******************************************************************
403 	   * Modify value(s).
404 	   *******************************************************************/
405 	   case 4: {
406 	     Logical changed = FALSE;
407 	     if (!EditEntry(attrN,entryN,entryType,FALSE,&changed)) {
408 	       ItemWindow (DELETEiw, &IW);
409 	       return FALSE;
410 	     }
411 	     if (changed) {
412 	       FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
413 	       if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
414 				  &nEntries,&entryNs,&IW)) {
415 		 ItemWindow (DELETEiw, &IW);
416 		 return FALSE;
417 	       }
418 	       ItemWindow (UPDATEiw, &IW, IW.itemN);
419 	     }
420 	     break;
421 	   }
422 	 }
423 
424 	 break;
425        }
426        /***********************************************************************
427        * Create new attribute.
428        ***********************************************************************/
429        case CREATEATTRkey_EDIT: {
430 	 static char *header[] = {
431 	   "Enter name (with delimiters)...",
432 	   "Syntax: <delim><char1><char2>...<charN><delim>",
433 	   "Example: \"Resolution\""
434 	 };
435 	 AOSs1 (trailer, "Enter: ________   Exit: ________  Help: ________")
436 	 static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI,
437 				    NUL };
438 	 static char value[DELIMed_ATTR_NAME_LEN+1];
439 	 static char label[16+1];
440 	 static struct PromptWindowStruct PWt = {
441 	    label, 4, 1, 78, 3, header, CDF_ATTR_NAME_LEN256+2, value, 1,
442 	    trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
443 	    INSERTorOVERkey_FSI
444 	 };
445 	 EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
446 			       HELPkey_FSI);
447 	 strcpyX (value, "\"\"", DELIMed_ATTR_NAME_LEN);
448 	 sprintf (label, " New %cAttribute ", BOO(G,'g','v'));
449 	 PromptWindow (NEWpw, &PWt, 1, LogicalTRUE);
450 	 for (;;) {
451 	    if (EnterPW(&PWt,ATTRNAMEhelpID)) {
452 	      char attrName[CDF_ATTR_NAME_LEN256+1];
453 	      long attrNum;
454 	      if (DecodeDelimitedString(PWt.value,attrName)) {
455 		status = CDFlib (CREATE_, ATTR_, attrName,
456 						 BOO(G,GLOBAL_SCOPE,
457 						       VARIABLE_SCOPE),
458 						 &attrNum,
459 				 NULL_);
460 		if (ReportStatus(status,FALSE)) {
461 		  FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
462 		  if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
463 				     &nEntries,&entryNs,&IW)) {
464 		    ItemWindow (DELETEiw, &IW);
465 		    return FALSE;
466 		  }
467 		  ItemWindow (UPDATEiw, &IW, IW.nItems - 1);
468 		  break;
469 		}
470 		if (NoMoreAccess(NULL)) {
471 		  ItemWindow (DELETEiw, &IW);
472 		  return FALSE;
473 		}
474 	      }
475 	      else
476 		ProblemWindow ("Illegal name (check delimiters).", FALSE);
477 	    }
478 	    else
479 	      break;
480 	 }
481 	 PromptWindow (DELETEpw, &PWt);
482 	 break;
483        }
484        /***********************************************************************
485        * Create new entry.
486        ***********************************************************************/
487        case CREATEENTRYkey_EDIT: {
488 	 int nameItemN; Logical changed = FALSE;
489 	 if (IW.nItems == 0) {
490 	   ProblemWindow(BOO(G,"A gAttribute isn't selected (none exist).",
491 			       "A vAttribute isn't selected (none exist)."),
492 			 FALSE);
493 	   break;
494 	 }
495 	 for (attrX = 0, nameItemN = 0; attrX < nAttrs; attrX++) {
496 	    int nItems = (int) (1 + (4 * nEntries[attrX]));
497 	    if (IW.itemN < nameItemN + nItems) {
498 	      attrN = attrNs[attrX];
499 	      break;
500 	    }
501 	    nameItemN += nItems;
502 	 }
503 	 if (!CreateEntry(G,attrN,&changed)) {
504 	   ItemWindow (DELETEiw, &IW);
505 	   return FALSE;
506 	 }
507 	 if (changed) {
508 	   FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
509 	   if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
510 			      &nEntries,&entryNs,&IW)) {
511 	     ItemWindow (DELETEiw, &IW);
512 	     return FALSE;
513 	   }
514 	   ItemWindow (UPDATEiw, &IW, nameItemN);
515 	 }
516 	 break;
517        }
518        /***********************************************************************
519        * Delete attribute/entry.
520        ***********************************************************************/
521        case DELETEATTRorENTRYkey_EDIT: {
522 	 int nameItemN;
523 	 Logical deleteAttr;
524 	 if (IW.nItems == 0) {
525 	   static char noG[] = {
526 	     "A gAttribute/gEntry isn't selected (none exist)."
527 	   };
528 	   static char noV[] = {
529 	     "A vAttribute/entry isn't selected (none exist)."
530 	   };
531 	   ProblemWindow (BOO(G,noG,noV), FALSE);
532 	   break;
533 	 }
534 	 for (attrX = 0, nameItemN = 0; attrX < nAttrs; attrX++) {
535 	    int nItems = (int) (1 + (4 * nEntries[attrX]));
536 	    if (IW.itemN < nameItemN + nItems) {
537 	      int itemNt = IW.itemN - nameItemN;
538 	      attrN = attrNs[attrX];
539 	      if (itemNt == 0)
540 		deleteAttr = TRUE;
541 	      else {
542 		deleteAttr = FALSE;
543 		entryX = (itemNt - 1) / 4;
544 		entryN = entryNs[attrX][entryX];
545 		if (G)
546 		  entryType = gENTRYt;
547 		else {
548 		  long NrEntries;
549 		  status = CDFlib (SELECT_, ATTR_, attrN,
550 				   GET_, ATTR_NUMrENTRIES_, &NrEntries,
551 				   NULL_);
552 		  if (!ReportStatus(status,FALSE)) {
553 		    ItemWindow (DELETEiw, &IW);
554 		    return FALSE;
555 		  }
556 		  entryType = (entryX < NrEntries ? rENTRYt : zENTRYt);
557 		}
558 	      }
559 	      break;
560 	    }
561 	    nameItemN += nItems;
562 	 }
563 	 if (deleteAttr) {
564 	   char attrName[CDF_ATTR_NAME_LEN256+1],
565 		question[22+CDF_ATTR_NAME_LEN256+1], delim;
566 	   status = CDFlib (SELECT_, ATTR_, attrN,
567 			    GET_, ATTR_NAME_, attrName,
568 			    NULL_);
569 	   if (!ReportStatus(status,FALSE)) {
570 	     ItemWindow (DELETEiw, &IW);
571 	     return FALSE;
572 	   }
573 	   delim = PickDelimiter (attrName, strlen(attrName));
574 	   sprintf (question, "Delete %sAttribute %c%s%c ?",
575 		    BOO(G,"g","v"), delim, attrName, delim);
576 	   if (ConfirmWindow(4,78,question,NULL,FALSE,DELETEATTRhelpID)) {
577 	     status = CDFlib (DELETE_, ATTR_,
578 			      NULL_);
579 	     if (ReportStatus(status,FALSE)) {
580 	       FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
581 	       if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
582 				  &nEntries,&entryNs,&IW)) {
583 		 ItemWindow (DELETEiw, &IW);
584 		 return FALSE;
585 	       }
586 	       ItemWindow (UPDATEiw, &IW, 0);
587 	     }
588 	     else {
589 	       if (NoMoreAccess(NULL)) {
590 		 ItemWindow (DELETEiw, &IW);
591 		 return FALSE;
592 	       }
593 	     }
594 	   }
595 	 }
596 	 else {
597 	   char attrName[CDF_ATTR_NAME_LEN256+1], delim = ' ',
598 		question1[40+ENTRYNUM_FIELD_LEN+CDF_ATTR_NAME_LEN256+1],
599 		question2[31+CDF_VAR_NAME_LEN256+1];
600 	   status = CDFlib (SELECT_, ATTR_, attrN,
601 			    GET_, ATTR_NAME_, attrName,
602 			    NULL_);
603 	   if (!ReportStatus(status,FALSE)) {
604 	     ItemWindow (DELETEiw, &IW);
605 	     return FALSE;
606 	   }
607 	   if (entryType == gENTRYt) {
608 	     delim = PickDelimiter (attrName, strlen(attrName));
609 	     sprintf (question1,
610 		      "Delete gEntry number %ld of gAttribute %c%s%c ?",
611 		      entryN + 1, delim, attrName, delim);
612 	     question2[0] = NUL;
613 	   }
614 	   else {
615 	     char varName[CDF_VAR_NAME_LEN256+1];
616 	     status = CDFlib (SELECT_, BOO(entryType==zENTRYt,zVAR_,
617 							      rVAR_), entryN,
618 			      GET_, BOO(entryType==zENTRYt,
619 					zVAR_NAME_,rVAR_NAME_), varName,
620 			      NULL_);
621 	     switch (status) {
622 	       case NO_SUCH_VAR:
623 		 sprintf (question1,
624 			  "Delete %sEntry number %ld of vAttribute %c%s%c ?",
625 			  BOO(entryType==zENTRYt,"z","r"), entryN + 1, delim,
626 			  attrName, delim);
627 		 question2[0] = NUL;
628 		 break;
629 	       default:
630 		 if (!ReportStatus(status,FALSE)) {
631 		   ItemWindow (DELETEiw, &IW);
632 		   return FALSE;
633 		 }
634 		 delim = PickDelimiter (attrName, strlen(attrName));
635 		 sprintf (question1, "Delete %sEntry of vAttribute %c%s%c",
636 			  BOO(entryType==zENTRYt,"z","r"), delim, attrName,
637 			  delim);
638 		 delim = PickDelimiter (varName, strlen(varName));
639 		 sprintf (question2, "corresponding to %sVariable %c%s%c ?",
640 			  BOO(entryType==zENTRYt,"z","r"), delim, varName,
641 			  delim);
642 		 break;
643 	     }
644 	   }
645 	   if (ConfirmWindow(4,78,question1,
646 			     BOO(NULstring(question2),NULL,question2),
647 			     FALSE,DELETEENTRYhelpID)) {
648 	     status = CDFlib (SELECT_, ENTRY(entryType), entryN,
649 			      DELETE_, ENTRY(entryType),
650 			      NULL_);
651 	     if (ReportStatus(status,FALSE)) {
652 	       FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
653 	       if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
654 				  &nEntries,&entryNs,&IW)) {
655 		 ItemWindow (DELETEiw, &IW);
656 		 return FALSE;
657 	       }
658 	       ItemWindow (UPDATEiw, &IW, 0);
659 	     }
660 	     else {
661 	       if (NoMoreAccess(NULL)) {
662 		 ItemWindow (DELETEiw, &IW);
663 		 return FALSE;
664 	       }
665 	     }
666 	   }
667 	 }
668 	 break;
669        }
670        /***********************************************************************
671        * Toggle scope.
672        ***********************************************************************/
673        case TOGGLESCOPEkey_EDIT: {
674 	 int nameItemN;
675 	 if (IW.nItems == 0) {
676 	   ProblemWindow(BOO(G,"A gAttribute isn't selected (none exist).",
677 			       "A vAttribute isn't selected (none exist)."),
678 			 FALSE);
679 	   break;
680 	 }
681 	 for (attrX = 0, nameItemN = 0; attrX < nAttrs; attrX++) {
682 	    int nItems = (int) (1 + (4 * nEntries[attrX]));
683 	    if (IW.itemN < nameItemN + nItems) {
684 	      attrN = attrNs[attrX];
685 	      break;
686 	    }
687 	    nameItemN += nItems;
688 	 }
689 	 status = CDFlib (SELECT_,ATTR_,attrN,
690 			  PUT_,ATTR_SCOPE_,BOO(G,VARIABLE_SCOPE,GLOBAL_SCOPE),
691 			  NULL_);
692 	 if (ReportStatus(status,FALSE)) {
693 	   FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
694 	   if (!BuildAttrMenu(G,CDFname,&nAttrs,&attrNs,
695 			      &nEntries,&entryNs,&IW)) {
696 	     ItemWindow (DELETEiw, &IW);
697 	     return FALSE;
698 	   }
699 	   ItemWindow (UPDATEiw, &IW, 0);
700 	 }
701 	 else {
702 	   if (NoMoreAccess(NULL)) {
703 	     ItemWindow (DELETEiw, &IW);
704 	     return FALSE;
705 	   }
706 	 }
707 	 break;
708        }
709        /***********************************************************************
710        * Display online help.
711        ***********************************************************************/
712        case HELPkey_FSI:
713 	 OnlineHelpWindow (ilhFile, BOO(G,GATTRShelpID,VATTRShelpID));
714 	 break;
715        /***********************************************************************
716        * Exit menu.
717        ***********************************************************************/
718        case EXITkey_FSI:
719 	 ItemWindow (DELETEiw, &IW);
720 	 FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, &IW);
721 	 return TRUE;
722      }
723    }
724 }
725 
726 /******************************************************************************
727 * BuildAttrMenu.
728 ******************************************************************************/
729 
BuildAttrMenu(G,CDFname,nAttrs,attrNs,nEntries,entryNs,IW)730 Logical BuildAttrMenu (G, CDFname, nAttrs, attrNs, nEntries, entryNs, IW)
731 Logical G;
732 char *CDFname;
733 long *nAttrs;
734 long **attrNs;
735 long **nEntries;
736 long ***entryNs;
737 struct ItemWindowStruct *IW;
738 {
739    CDFstatus status;
740    int attrX, entryX;
741    long dataType, numElems;
742    long NgEntries, NrEntries, NzEntries;
743    char attrName[CDF_ATTR_NAME_LEN256+1];
744    int curItem;
745    int curCol;
746    int lineN;
747    int n;
748    int dataSpecCol;
749    void *binary;
750    char field[80+1];
751    long TnAttrs;                /* Total number of attributes (global and
752 				   variable scoped). */
753    int entryType;
754    int entryXt;
755    int nLines, nItems;
756    long attrN;
757    long estLines;               /* Estimated number of lines for the menu. */
758    AOSs2 (loadingLines, "Loading menu...", "")
759    /***************************************************************************
760    * Determine number of attributes (total and of proper scope).
761    ***************************************************************************/
762    status = CDFlib (GET_, CDF_NUMATTRS_, &TnAttrs,
763 			  BOO(G,CDF_NUMgATTRS_,CDF_NUMvATTRS_), nAttrs,
764 		    NULL_);
765    if (!ReportStatus(status,FALSE)) return FALSE;
766    if (!G) {
767      long NrVars, NzVars;
768      status = CDFlib (GET_, CDF_NUMrVARS_, &NrVars,
769 			    CDF_NUMzVARS_, &NzVars,
770 		      NULL_);
771      if (!ReportStatus(status,FALSE)) return FALSE;
772      estLines = (*nAttrs) * (NrVars + NzVars);
773      if (estLines > MANY_ATTRs_AND_ENTRYs) {
774        MessageWindow (loadingLines, NULL, LogicalFALSE);
775      }
776    }
777    /***************************************************************************
778    * Count/save attribute and entry numbers.  Determine attribute name item
779    * numbers.
780    ***************************************************************************/
781    *nEntries = (long *) cdf_AllocateMemory ((size_t) (*nAttrs * sizeof(long)),
782 					FatalError);
783    *attrNs = (long *) cdf_AllocateMemory ((size_t) (*nAttrs * sizeof(long)),
784 				      FatalError);
785    *entryNs = (long **) cdf_AllocateMemory ((size_t) (*nAttrs * sizeof(long *)),
786 					FatalError);
787    for (attrN=0, attrX=0, nItems=0, nLines=0; attrN < TnAttrs; attrN++) {
788       long scope;
789       /************************************************************************
790       * Determine scope.
791       ************************************************************************/
792       status = CDFlib (SELECT_, ATTR_, attrN,
793 		       GET_, ATTR_SCOPE_, &scope,
794 		       NULL_);
795       if (!ReportStatus(status,FALSE)) return FALSE;
796       /************************************************************************
797       * If proper scope, save attribute number and determine which entries
798       * exist.
799       ************************************************************************/
800       if ((G && (scope == GLOBAL_SCOPE)) ||
801 	  (!G && (scope == VARIABLE_SCOPE))) {
802 	int i;
803 	long entryN;
804 	/**********************************************************************
805 	* Tally an attribute of the proper scope.
806 	**********************************************************************/
807 	(*attrNs)[attrX] = attrN;
808 	nItems++;
809 	nLines++;
810 	/**********************************************************************
811 	* Determine number of entries.
812 	**********************************************************************/
813 	if (G) {
814 	  status = CDFlib (GET_, ATTR_NUMgENTRIES_, &NgEntries,
815 			   NULL_);
816 	  if (!ReportStatus(status,FALSE)) return FALSE;
817 	  (*nEntries)[attrX] = NgEntries;
818 	}
819 	else {
820 	  status = CDFlib (GET_, ATTR_NUMrENTRIES_, &NrEntries,
821 				 ATTR_NUMzENTRIES_, &NzEntries,
822 			   NULL_);
823 	  if (!ReportStatus(status,FALSE)) return FALSE;
824 	  (*nEntries)[attrX] = NrEntries + NzEntries;
825 	}
826 	(*entryNs)[attrX] = (long *)
827 			    cdf_AllocateMemory ((size_t) ((*nEntries)[attrX] *
828 						       sizeof(long)),
829 					    FatalError);
830 	for (i = 0, entryX = 0, entryType = BOO(G,gENTRYt,rENTRYt);
831 	     i < BOO(G,1,2); i++, entryType = zENTRYt) {
832 	  long nEntries = E3(entryType,NgEntries,NrEntries,NzEntries);
833 	  for (entryN = 0, entryXt = 0; entryXt < nEntries; entryN++) {
834 	     status = CDFlib (SELECT_, ENTRY(entryType), entryN,
835 			      CONFIRM_, CURENTRY_EXISTENCE(entryType),
836 			      NULL_);
837 	     switch (status) {
838 	       case NO_SUCH_ENTRY:
839 		 break;
840 	       default:
841 		 if (!ReportStatus(status,FALSE)) return FALSE;
842 		 nItems += 4;
843 		 if (entryX > 0) nLines++;
844 		 (*entryNs)[attrX][entryX] = entryN;
845 		 entryX++;
846 		 entryXt++;
847 		 break;
848 	     }
849 	  }
850 	}
851 	attrX++;
852       }
853    }
854    /***************************************************************************
855    * Allocate item section control/lines.
856    ***************************************************************************/
857    AllocIW (IW, nItems, nLines, 80, FatalError);
858    /***************************************************************************
859    * Encode label/header.
860    ***************************************************************************/
861    sprintf (IW->label, " CDF \"%s\" %cAttributes ", CDFname, BOO(G,'g','v'));
862    if (G) {
863      sprintf (IW->hLines[0], "%ld gAttribute%s", *nAttrs,
864 	      (*nAttrs == 1 ? "" : "s"));
865      strcpyX (IW->hLines[1],
866 	      "AttrName         Entry  DataSpec  Value(s)", 0);
867    }
868    else {
869      sprintf (IW->hLines[0], "%ld vAttribute%s", *nAttrs,
870 	      (*nAttrs == 1 ? "" : "s"));
871      strcpyX (IW->hLines[1],
872 	      "AttrName         VarName          DataSpec  Value(s)", 0);
873    }
874    /***************************************************************************
875    * Build each attribute/entry line.
876    ***************************************************************************/
877    lineN = 0;
878    curItem = 0;
879    for (attrX = 0; attrX < *nAttrs; attrX++) {
880       /************************************************************************
881       * Inquire attribute.
882       ************************************************************************/
883       status = CDFlib (SELECT_, ATTR_, (*attrNs)[attrX],
884 		       GET_, ATTR_NAME_, attrName,
885 		       NULL_);
886       if (!ReportStatus(status,FALSE)) return FALSE;
887       /************************************************************************
888       * Setup attribute name.
889       ************************************************************************/
890       curCol = 0;
891       EncodeString (strlen(attrName), attrName, field, 0, ATTRNAME_FIELD_LEN);
892       strcpyX (IW->iLines[lineN], field, 0);
893       if (strlen(field) < (size_t) ATTRNAME_FIELD_LEN) {
894 	CatNcharacters (IW->iLines[lineN], ATTRNAME_FIELD_LEN - strlen(field),
895 			(int) ' ');
896       }
897       CatNcharacters (IW->iLines[lineN], ATTRNAME_FIELD_BLANKS, (int) ' ');
898       IW->iLineNs[curItem] = lineN;
899       IW->iCols[curItem] = curCol;
900       IW->iLens[curItem] = strlen(field);
901       curCol += ATTRNAME_FIELD_LEN + ATTRNAME_FIELD_BLANKS;
902       curItem++;
903       /************************************************************************
904       * Setup each entry.
905       ************************************************************************/
906       if (!G) {
907 	status = CDFlib (GET_, ATTR_NUMrENTRIES_, &NrEntries,
908 			 NULL_);
909 	if (!ReportStatus(status,FALSE)) return FALSE;
910       }
911       if ((*nEntries)[attrX] > 0) {
912 	for (entryX = 0; entryX < (*nEntries)[attrX]; entryX++) {
913 	   int entryType = BOO(G,gENTRYt,
914 			       BOO(entryX < NrEntries,rENTRYt,zENTRYt));
915 	   /*******************************************************************
916 	   * Inquire entry.
917 	   *******************************************************************/
918 	   status = CDFlib (SELECT_,ENTRY(entryType),(*entryNs)[attrX][entryX],
919 			    GET_, ENTRY_DATATYPE(entryType), &dataType,
920 				  ENTRY_NUMELEMS(entryType), &numElems,
921 			    NULL_);
922 	   if (!ReportStatus(status,FALSE)) return FALSE;
923 	   /*******************************************************************
924 	   * Pad with blanks the attribute name field if this isn't the first
925 	   * entry.
926 	   *******************************************************************/
927 	   if (entryX > 0) {
928 	     strcpyX (IW->iLines[lineN], "", 0);
929 	     CatNcharacters (IW->iLines[lineN], ATTRNAME_FIELD_LEN, (int) ' ');
930 	     CatNcharacters (IW->iLines[lineN], ATTRNAME_FIELD_BLANKS,
931 			     (int) ' ');
932 	     curCol = ATTRNAME_FIELD_LEN + ATTRNAME_FIELD_BLANKS;
933 	   }
934 	   /*******************************************************************
935 	   * Setup entry number field if global scope, variable name if
936 	   * variable scope.
937 	   *******************************************************************/
938 	   if (G) {
939 	     sprintf (field, "%ld", (*entryNs)[attrX][entryX] + 1);
940 	     if (strlen(field) > (size_t) ENTRYNUM_FIELD_LEN)
941 	       strcpyX (field + ENTRYNUM_FIELD_LEN - 3, "...", 0);
942 	   }
943 	   else {
944 	     char varName[CDF_VAR_NAME_LEN256+1];
945 	     status = CDFlib (SELECT_, E3(entryType,0,rVAR_,
946 					  zVAR_), (*entryNs)[attrX][entryX],
947 			      GET_, E3(entryType,0,
948 				       rVAR_NAME_,zVAR_NAME_), varName,
949 			      NULL_);
950 	     switch (status) {
951 	       case NO_SUCH_VAR: {
952 		 Logical Z = E3(entryType,FALSE,FALSE,TRUE);
953 		 sprintf (field, "<%sEntry.%ld>", BOO(Z,"z","r"),
954 			  (*entryNs)[attrX][entryX] + 1);
955 		 break;
956 	       }
957 	       default:
958 		 if (!ReportStatus(status,FALSE)) return FALSE;
959 		 EncodeString (strlen(varName), varName, field, 0,
960 			       VARNAME_FIELD_LEN);
961 		 break;
962 	     }
963 	   }
964 	   strcatX (IW->iLines[lineN], field, 0);
965 	   if (strlen(field) < (size_t) BOO(G,ENTRYNUM_FIELD_LEN,
966 					      VARNAME_FIELD_LEN)) {
967 	     CatNcharacters (IW->iLines[lineN],
968 			     BOO(G,ENTRYNUM_FIELD_LEN,
969 				   VARNAME_FIELD_LEN) - strlen(field),
970 			     (int) ' ');
971 	   }
972 	   CatNcharacters (IW->iLines[lineN],
973 			   BOO(G,ENTRYNUM_FIELD_BLANKS,VARNAME_FIELD_BLANKS),
974 			   (int) ' ');
975 	   IW->iLineNs[curItem] = lineN;
976 	   IW->iCols[curItem] = curCol;
977 	   IW->iLens[curItem] = strlen(field);
978 	   curCol += BOO(G,ENTRYNUM_FIELD_LEN,VARNAME_FIELD_LEN) +
979 		     BOO(G,ENTRYNUM_FIELD_BLANKS,VARNAME_FIELD_BLANKS);
980 	   curItem++;
981 	   /*******************************************************************
982 	   * Setup data type & number of elements.
983 	   *******************************************************************/
984 	   strcpyX (field, DataTypeToken(dataType), 0);
985 	   catchrX (field, (int) '/', 0);
986 	   sprintf (&field[strlen(field)], "%ld", numElems);
987 	   if (strlen(field) > (size_t) DATASPEC_FIELD_LEN) {
988 	     strcpyX (field + DATASPEC_FIELD_LEN - 3, "...", 0);
989 	   }
990 	   strcatX (IW->iLines[lineN], field, 0);
991 	   if (strlen(field) < (size_t) DATASPEC_FIELD_LEN) {
992 	     CatNcharacters (IW->iLines[lineN],
993 			     DATASPEC_FIELD_LEN - strlen(field), (int) ' ');
994 	   }
995 	   CatNcharacters (IW->iLines[lineN], DATASPEC_FIELD_BLANKS, (int)' ');
996 	   IW->iLineNs[curItem] = lineN;
997 	   IW->iCols[curItem] = curCol;
998 	   IW->iLens[curItem] = strlen(field);
999 	   dataSpecCol = curCol;
1000 	   curCol += DATASPEC_FIELD_LEN + DATASPEC_FIELD_BLANKS;
1001 	   curItem++;
1002 	   /*******************************************************************
1003 	   * Setup value(s) field.
1004 	   *******************************************************************/
1005 	   binary = cdf_AllocateMemory ((size_t) (numElems *
1006 					      CDFelemSize(dataType)),
1007 				    FatalError);
1008 	   status = CDFlib (GET_, ENTRY_DATA(entryType), binary,
1009 			    NULL_);
1010 	   if (!ReportStatus(status,FALSE)) return FALSE;
1011 	   n = EncodeValuesFormat (dataType, numElems, binary,
1012 				   &(IW->iLines[lineN][curCol]), NULL, 0,
1013 				   BOO(G,gAttrENTRYVALUE_FIELD_LEN,
1014 					 vAttrENTRYVALUE_FIELD_LEN),
1015 				   EPOCH0_STYLE);
1016 	   cdf_FreeMemory (binary, FatalError);
1017 	   /*******************************************************************
1018 	   * Set 'dataSpec/value' item control information.
1019 	   *******************************************************************/
1020 	   IW->iLineNs[curItem] = lineN;
1021 	   IW->iCols[curItem] = dataSpecCol;
1022 	   IW->iLens[curItem] = strlen(&(IW->iLines[lineN][dataSpecCol]));
1023 	   curItem++;
1024 	   /*******************************************************************
1025 	   * Set `value' item control information.
1026 	   *******************************************************************/
1027 	   IW->iLineNs[curItem] = lineN;
1028 	   IW->iCols[curItem] = curCol;
1029 	   IW->iLens[curItem] = n;
1030 	   curItem++;
1031 	   lineN++;
1032 	}
1033       }
1034       else {
1035 	lineN++;        /* No entries, just increment to next line. */
1036       }
1037    }
1038    if (!G) {
1039      if (estLines > MANY_ATTRs_AND_ENTRYs) MessageWindow (NULL);
1040    }
1041    return TRUE;
1042 }
1043 
1044 /******************************************************************************
1045 * FreeAttrMenu.
1046 ******************************************************************************/
1047 
FreeAttrMenu(nAttrs,attrNs,nEntries,entryNs,IW)1048 void FreeAttrMenu (nAttrs, attrNs, nEntries, entryNs, IW)
1049 long nAttrs;
1050 long *attrNs;
1051 long *nEntries;
1052 long **entryNs;
1053 struct ItemWindowStruct *IW;
1054 {
1055   int attrX;
1056   FreeIW (IW, FatalError);
1057   for (attrX = (int) (nAttrs - 1); attrX >= 0; attrX--) {
1058      if (entryNs[attrX] != NULL) cdf_FreeMemory (entryNs[attrX],
1059 					     FatalError);
1060   }
1061   if (entryNs != NULL) cdf_FreeMemory (entryNs, FatalError);
1062   if (attrNs != NULL) cdf_FreeMemory (attrNs, FatalError);
1063   if (nEntries != NULL) cdf_FreeMemory (nEntries, FatalError);
1064   return;
1065 }
1066 
1067 /******************************************************************************
1068 * EditEntry.
1069 * Returns FALSE if a fatal CDF error occurred.
1070 ******************************************************************************/
1071 
EditEntry(attrN,entryN,entryType,newDataSpec,changed)1072 Logical EditEntry (attrN, entryN, entryType, newDataSpec, changed)
1073 long attrN;
1074 long entryN;
1075 int entryType;
1076 Logical newDataSpec;
1077 Logical *changed;	/* Assumed to be initialized to FALSE by the caller. */
1078 {
1079   long dataType, numElems; int cursorAtThisChar; CDFstatus status;
1080   static char value[MAX_ENTRYSTRING_LEN+1];
1081   static char label[15+CDF_VAR_NAME_LEN256+1];
1082   static char *headerBrowse[] = {
1083     "Full entry value..."
1084   };
1085   static char *headerChar[] = {
1086     "Enter character string (with delimiters)...",
1087     "Syntax: <delim><char1><char2>...<charN><delim>"
1088   };
1089   static char *headerNoChar[] = {
1090     "Enter value(s)...",
1091     "Syntax: <value1>,<value2>,...,<valueN>"
1092   };
1093   AOSs1A (trailerBrowse, "Exit: ________   Help: ________")
1094   AOSs1B (trailerEdit, "Enter: ________   Exit: ________   Help: ________")
1095   static int exitCharsBrowse[] = { EXITkey_FSI, HELPkey_FSI, NUL };
1096   static int exitCharsEdit[] = {
1097     ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL
1098   };
1099   static struct PromptWindowStruct PW = {
1100     label, 4, 1, 78, 0, NULL, MAX_ENTRYSTRING_LEN, value, 1, NULL,
1101     NULL, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI, INSERTorOVERkey_FSI
1102   };
1103   /****************************************************************************
1104   * Encode label.
1105   ****************************************************************************/
1106   switch (entryType) {
1107     case gENTRYt:
1108       sprintf (label, " gEntry %ld ", entryN + 1);
1109       break;
1110     case rENTRYt:
1111     case zENTRYt: {
1112       Logical Z = (entryType == zENTRYt);
1113       char varName[CDF_VAR_NAME_LEN256+1], delim;
1114       status = CDFlib (SELECT_, VAR(Z), entryN,
1115 		       GET_, VAR_NAME(Z), varName,
1116 		       NULL_);
1117       switch (status) {
1118 	case NO_SUCH_VAR:
1119 	  sprintf (label, " %cEntry %ld ", BOO(Z,'z','r'), entryN + 1);
1120 	  break;
1121 	default:
1122 	  if (!ReportStatus(status,FALSE)) return FALSE;
1123 	  delim = PickDelimiter (varName, strlen(varName));
1124 	  sprintf (label, " %cEntry for %c%s%c ", BOO(Z,'z','r'),
1125 		   delim, varName, delim);
1126 	  break;
1127       }
1128       break;
1129     }
1130   }
1131   /****************************************************************************
1132   * Either prompt for a new data type (the number of elements will be implied
1133   * by the value entered) or read the current data specification and value.
1134   * Note that it should never be necessary to prompt for a new data type when
1135   * browsing.
1136   ****************************************************************************/
1137   if (!browseOnly && newDataSpec) {
1138     dataType = NO_DATATYPE;
1139     if (!SelectDataSpec(&dataType,NULL,label)) return TRUE;
1140     strcpyX (value, BOO(STRINGdataType(dataType),"\"\"",""),
1141 	     MAX_ENTRYSTRING_LEN);
1142   }
1143   else {
1144     void *binary;
1145     status = CDFlib (SELECT_, ATTR_, attrN,
1146 			      ENTRY(entryType), entryN,
1147 		     GET_, ENTRY_DATATYPE(entryType), &dataType,
1148 			   ENTRY_NUMELEMS(entryType), &numElems,
1149 		     NULL_);
1150     if (!ReportStatus(status,FALSE)) return FALSE;
1151     binary = cdf_AllocateMemory ((size_t) (numElems * CDFelemSize(dataType)),
1152 			     FatalError);
1153     status = CDFlib (GET_, ENTRY_DATA(entryType), binary,
1154 		     NULL_);
1155     if (!ReportStatus(status,FALSE)) return FALSE;
1156     EncodeValuesFormat (dataType, numElems, binary, value, NULL, 0,
1157 			MAX_ENTRYSTRING_LEN, EPOCH0_STYLE);
1158     cdf_FreeMemory (binary, FatalError);
1159   }
1160   /****************************************************************************
1161   * Prompt for the new value.
1162   ****************************************************************************/
1163   if (browseOnly) {
1164     EncodeKeyDefinitions (1, trailerBrowse, EXITkey_FSI, HELPkey_FSI);
1165     PW.NhLines = 1;
1166     PW.hLines = headerBrowse;
1167     PW.tLines = trailerBrowse;
1168     PW.exitChars = exitCharsBrowse;
1169   }
1170   else {
1171     EncodeKeyDefinitions (1, trailerEdit, ENTERkey_FSI, EXITkey_FSI,
1172 			  HELPkey_FSI);
1173     PW.NhLines = 2;
1174     PW.hLines = BOO(STRINGdataType(dataType),headerChar,headerNoChar);
1175     PW.tLines = trailerEdit;
1176     PW.exitChars = exitCharsEdit;
1177   }
1178   cursorAtThisChar = BOO(browseOnly,0,strlen(PW.value) -
1179 				      BOO(STRINGdataType(dataType),1,0));
1180   PromptWindow (NEWpw, &PW, cursorAtThisChar, LogicalTRUE);
1181   for (;;) {
1182      if (EnterPW(&PW,ENTRYVALUEhelpID)) {
1183        void *newBinary;
1184        long newNumElems;
1185        if (DecodeValues(PW.value,dataType,&newNumElems,
1186 			&newBinary,EPOCH0_STYLE)) {
1187 	 status = CDFlib (SELECT_, ATTR_, attrN,
1188 				   ENTRY(entryType), entryN,
1189 			  PUT_, ENTRY_DATA(entryType), dataType,
1190 						       newNumElems,
1191 						       newBinary,
1192 			  NULL_);
1193 	 cdf_FreeMemory (newBinary, FatalError);
1194 	 if (ReportStatus(status,FALSE)) {
1195 	   *changed = TRUE;
1196 	   break;
1197 	 }
1198 	 if (NoMoreAccess(NULL)) {
1199 	   PromptWindow (DELETEpw, &PW);
1200 	   return FALSE;
1201 	 }
1202        }
1203        else
1204 	 ProblemWindow ("Error decoding values.", FALSE);
1205      }
1206      else
1207        break;
1208   }
1209   PromptWindow (DELETEpw, &PW);
1210   return TRUE;
1211 }
1212 
1213 /******************************************************************************
1214 * EditVarEntries.
1215 ******************************************************************************/
1216 
EditVarEntries(Z,varN,nVars)1217 Logical EditVarEntries (Z, varN, nVars)
1218 Logical Z;
1219 long varN;
1220 long nVars;
1221 {
1222    CDFstatus status;
1223    long nAttrs;                 /* Number of variable scoped attributes. */
1224    long attrN;
1225    AOSs2 (header, BLANKs78, BLANKs78)
1226    AOSs1 (trailerBrowse,
1227      "Select: ________   Exit: ________   Help: ________   Next variable: ________")
1228    AOSs3 (trailerEdit,
1229      "Select: ________   Create attribute: ________   Next variable: ________",
1230      "Exit:   ________   Create entry:     ________   Delete entry:  ________",
1231      "Help:   ________")
1232    static int exitCharsBrowse[] = {
1233      ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NEXTVARkey_EDIT, NUL
1234    };
1235    static int exitCharsEdit[] = {
1236      ENTERkey_FSI, EXITkey_FSI, CREATEATTRkey_EDIT, HELPkey_FSI,
1237      CREATEENTRYkey_EDIT, DELETEATTRorENTRYkey_EDIT, NEXTVARkey_EDIT, NUL
1238    };
1239    static char label[12+CDF_VAR_NAME_LEN256+11+1];
1240    static struct ItemWindowStruct IW = {
1241       0, 0, 80, label, 2, header, 0, NULL, 0, NULL, NULL, NULL, 0, 0, NULL,
1242       NULL, REFRESHkey_FSI, TRUE, NSkey_FSI, PSkey_FSI
1243    };
1244    long *attrNs;                /* Attribute numbers. */
1245    Logical *entryIs;            /* TRUE if there is an entry. */
1246    int attrX;                   /* Attribute index (which variable scoped
1247 				   attribute). */
1248    static Logical first = TRUE;
1249    /***************************************************************************
1250    * First time...
1251    ***************************************************************************/
1252    if (first) {
1253        EncodeKeyDefinitions (1, trailerBrowse, ENTERkey_FSI, EXITkey_FSI,
1254 			     HELPkey_FSI, NEXTVARkey_EDIT);
1255        EncodeKeyDefinitions (3, trailerEdit, ENTERkey_FSI,
1256 			     CREATEATTRkey_EDIT, NEXTVARkey_EDIT, EXITkey_FSI,
1257 			     CREATEENTRYkey_EDIT, DELETEATTRorENTRYkey_EDIT,
1258 			     HELPkey_FSI);
1259      first = FALSE;
1260    }
1261      if (browseOnly) {
1262        IW.NiRows = 14;
1263        IW.NtLines = 1;
1264        IW.tLines = trailerBrowse;
1265        IW.exitChars = exitCharsBrowse;
1266      }
1267      else {
1268        IW.NiRows = 12;
1269        IW.NtLines = 3;
1270        IW.tLines = trailerEdit;
1271        IW.exitChars = exitCharsEdit;
1272      }
1273    /***************************************************************************
1274    * Build attribute/entry lines and display window.
1275    ***************************************************************************/
1276    if (!BuildVarEntryMenu(Z,varN,&nAttrs,&attrNs,&entryIs,&IW)) return FALSE;
1277    ItemWindow (NEWiw, &IW, 0);
1278    /***************************************************************************
1279    * Read/process keystrokes until request to exit menu.
1280    ***************************************************************************/
1281    for (;;) {
1282      ItemWindow (READiw, &IW);
1283      switch (IW.key) {
1284        /***********************************************************************
1285        * Item selected.
1286        ***********************************************************************/
1287        case ENTERkey_FSI: {
1288 	 int fieldN, nameItemN;
1289 	 /*********************************************************************
1290 	 * Do any items exist?
1291 	 *********************************************************************/
1292 	 if (IW.nItems == 0) {
1293 	   ProblemWindow ("Nothing selected (no vAttributes exist).", FALSE);
1294 	   break;
1295 	 }
1296 	 /*********************************************************************
1297 	 * Calculate attribute and field numbers.
1298 	 *********************************************************************/
1299 	 for (attrX = 0, nameItemN = 0; attrX < nAttrs; attrX++) {
1300 	    int nItems = (int) (entryIs[attrX] ? 4 : 1);
1301 	    if (IW.itemN < nameItemN + nItems) {
1302 	      attrN = attrNs[attrX];
1303 	      fieldN = IW.itemN - nameItemN;
1304 	      break;
1305 	    }
1306 	    nameItemN += nItems;
1307 	 }
1308 	 /*********************************************************************
1309 	 * Perform desired function (based on field number).
1310 	 *********************************************************************/
1311 	 switch (fieldN) {
1312 	   /*******************************************************************
1313 	   * Modify attribute name.
1314 	   *******************************************************************/
1315 	   case 0: {
1316 	     char attrName[CDF_ATTR_NAME_LEN256+1];
1317 	     status = CDFlib (SELECT_, ATTR_, attrN,
1318 			      GET_, ATTR_NAME_, attrName,
1319 			      NULL_);
1320 	     if (!ReportStatus(status,FALSE)) {
1321 	       ItemWindow (DELETEiw, &IW);
1322 	       return FALSE;
1323 	     }
1324 	     if (browseOnly)
1325 	       ShowFullName (attrName, TRUE);
1326 	     else {
1327 	       static char *header[] = {
1328 		  "Enter new name (with delimiters)...",
1329 		  "Syntax: <delim><char1><char2>...<charN><delim>",
1330 		  "Example: \"RANGE\""
1331 	       };
1332 	       AOSs1 (trailer,
1333 		      "Enter: ________   Exit: ________  Help: ________")
1334 	       static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI,
1335 					  HELPkey_FSI, NUL };
1336 	       static char value[1+CDF_ATTR_NAME_LEN256+1+1];
1337 	       static char label[15+CDF_ATTR_NAME_LEN256+1];
1338 	       static struct PromptWindowStruct PW = {
1339 		  label, 4, 1, 78, 3, header, CDF_ATTR_NAME_LEN256+2, value, 1,
1340 		  trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
1341 		  INSERTorOVERkey_FSI
1342 	       };
1343 	       char delim;
1344 	       EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
1345 				     HELPkey_FSI);
1346 	       delim = PickDelimiter (attrName, strlen(attrName));
1347 	       sprintf (value, "%c%s%c", delim, attrName, delim);
1348 	       sprintf (label, " vAttribute %c%s%c ", delim, attrName, delim);
1349 	       PromptWindow (NEWpw, &PW, (int) (strlen(PW.value) - 1),
1350 			     LogicalTRUE);
1351 	       for (;;) {
1352 		  if (EnterPW(&PW,ATTRRENAMEhelpID)) {
1353 		    char attrName[CDF_ATTR_NAME_LEN256+1];
1354 		    if (DecodeDelimitedString(PW.value,attrName)) {
1355 		      status = CDFlib (PUT_, ATTR_NAME_, attrName,
1356 				       NULL_);
1357 		      if (ReportStatus(status,FALSE)) {
1358 		        FreeVarEntryMenu (attrNs, entryIs, &IW);
1359 		        if (!BuildVarEntryMenu(Z,varN,&nAttrs,
1360 					       &attrNs,&entryIs,&IW)) {
1361 			  PromptWindow (DELETEpw, &PW);
1362 			  ItemWindow (DELETEiw, &IW);
1363 			  return FALSE;
1364 			}
1365 		        ItemWindow (UPDATEiw, &IW, IW.itemN);
1366 		        break;
1367 		      }
1368 		      if (NoMoreAccess(NULL)) {
1369 			PromptWindow (DELETEpw, &PW);
1370 			ItemWindow (DELETEiw, &IW);
1371 			return FALSE;
1372 		      }
1373 		    }
1374 		    else
1375 		      ProblemWindow ("Illegal name (check delimiters).",
1376 				     FALSE);
1377 		  }
1378 		  else
1379 		    break;
1380 	       }
1381 	       PromptWindow (DELETEpw, &PW);
1382 	     }
1383 	     break;
1384 	   }
1385 	   /*******************************************************************
1386 	   * Modify data specification.
1387 	   *******************************************************************/
1388 	   case 1: {
1389 	     if (browseOnly)
1390 	       ItemWindow (BEEPiw, &IW);
1391 	     else {
1392 	       long dataType, numElems;
1393 	       char varName[CDF_VAR_NAME_LEN256+1], delim;
1394 	       status = CDFlib (SELECT_, VAR(Z), varN,
1395 				         ATTR_, attrN,
1396 				         BOO(Z,zENTRY_,rENTRY_), varN,
1397 			        GET_, VAR_NAME(Z), varName,
1398 				      BOO(Z,zENTRY_DATATYPE_,
1399 					    rENTRY_DATATYPE_), &dataType,
1400 				      BOO(Z,zENTRY_NUMELEMS_,
1401 					    rENTRY_NUMELEMS_), &numElems,
1402 			        NULL_);
1403 	       if (!ReportStatus(status,FALSE)) {
1404 		 ItemWindow (DELETEiw, &IW);
1405 		 return FALSE;
1406 	       }
1407 	       delim = PickDelimiter (varName, strlen(varName));
1408 	       sprintf (label, " %cEntry for %c%s%c ", BOO(Z,'z','r'),
1409 		        delim, varName, delim);
1410 	       if (SelectDataSpec(&dataType,NULL,label)) {
1411 		 status = CDFlib (PUT_, BOO(Z,zENTRY_DATASPEC_,
1412 					      rENTRY_DATASPEC_), dataType,
1413 								 numElems,
1414 				  NULL_);
1415 		 if (ReportStatus(status,FALSE)) {
1416 		   FreeVarEntryMenu (attrNs, entryIs, &IW);
1417 		   if (!BuildVarEntryMenu(Z,varN,&nAttrs,
1418 					  &attrNs,&entryIs,&IW)) {
1419 		     ItemWindow (DELETEiw, &IW);
1420 		     return FALSE;
1421 		   }
1422 		   ItemWindow (UPDATEiw, &IW, IW.itemN);
1423 		 }
1424 		 else {
1425 		   if (NoMoreAccess(NULL)) {
1426 		     ItemWindow (DELETEiw, &IW);
1427 		     return FALSE;
1428 		   }
1429 		 }
1430 	       }
1431 	     }
1432 	     break;
1433 	   }
1434 	   /*******************************************************************
1435 	   * Modify data specification/value(s).
1436 	   *******************************************************************/
1437 	   case 2: {
1438 	     if (browseOnly)
1439 	       ItemWindow (BEEPiw, &IW);
1440 	     else {
1441 	       Logical changed = FALSE;
1442 	       if (!EditEntry(attrN,varN,
1443 			      BOO(Z,zENTRYt,rENTRYt),
1444 			      TRUE,&changed)) {
1445 		 ItemWindow (DELETEiw, &IW);
1446 		 return FALSE;
1447 	       }
1448 	       if (changed) {
1449 	         FreeVarEntryMenu (attrNs, entryIs, &IW);
1450 	         if (!BuildVarEntryMenu(Z,varN,&nAttrs,&attrNs,&entryIs,&IW)) {
1451 		   ItemWindow (DELETEiw, &IW);
1452 		   return FALSE;
1453 		 }
1454 	         ItemWindow (UPDATEiw, &IW, IW.itemN);
1455 	       }
1456 	     }
1457 	     break;
1458 	   }
1459 	   /*******************************************************************
1460 	   * Modify value(s).
1461 	   *******************************************************************/
1462 	   case 3: {
1463 	     Logical changed = FALSE;
1464 	     if (!EditEntry(attrN,varN,
1465 			    BOO(Z,zENTRYt,rENTRYt),
1466 			    FALSE,&changed)) {
1467 	       ItemWindow (DELETEiw, &IW);
1468 	       return FALSE;
1469 	     }
1470 	     if (changed) {
1471 	       FreeVarEntryMenu (attrNs, entryIs, &IW);
1472 	       if (!BuildVarEntryMenu(Z,varN,&nAttrs,
1473 				      &attrNs,&entryIs,&IW)) {
1474 		 ItemWindow (DELETEiw, &IW);
1475 		 return FALSE;
1476 	       }
1477 	       ItemWindow (UPDATEiw, &IW, IW.itemN);
1478 	     }
1479 	     break;
1480 	   }
1481 	 }
1482 	 break;
1483        }
1484        /***********************************************************************
1485        * Create attribute.
1486        ***********************************************************************/
1487        case CREATEATTRkey_EDIT: {
1488 	 static char *header[] = {
1489 	   "Enter name (with delimiters)...",
1490 	   "Syntax: <delim><char1><char2>...<charN><delim>",
1491 	   "Example: \"MetricUnits\""
1492 	 };
1493 	 AOSs1 (trailer, "Enter: ________   Exit: ________  Help: _______")
1494 	 static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI,
1495 				    NUL };
1496 	 static char value[DELIMed_ATTR_NAME_LEN+1];
1497 	 static struct PromptWindowStruct PWt = {
1498 	    " New vAttribute ", 4, 1, 78, 3, header, CDF_ATTR_NAME_LEN256+2,
1499 	    value, 1, trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI,
1500 	    EOLkey_FSI, INSERTorOVERkey_FSI
1501 	 };
1502 	 EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
1503 			       HELPkey_FSI);
1504 	 strcpyX (PWt.value, "\"\"", DELIMed_ATTR_NAME_LEN);
1505 	 PromptWindow (NEWpw, &PWt, 1, LogicalTRUE);
1506 	 for (;;) {
1507 	    if (EnterPW(&PWt,ATTRNAMEhelpID)) {
1508 	      char attrName[CDF_ATTR_NAME_LEN256+1]; long attrNum;
1509 	      if (DecodeDelimitedString(PWt.value,attrName)) {
1510 		status = CDFlib (CREATE_, ATTR_, attrName, VARIABLE_SCOPE,
1511 						 &attrNum,
1512 				 NULL_);
1513 		if (ReportStatus(status,FALSE)) {
1514 		  FreeVarEntryMenu (attrNs, entryIs, &IW);
1515 		  if (!BuildVarEntryMenu(Z,varN,&nAttrs,
1516 					 &attrNs,&entryIs,&IW)) {
1517 		    PromptWindow (DELETEpw, &PWt);
1518 		    ItemWindow (DELETEiw, &IW);
1519 		    return FALSE;
1520 		  }
1521 		  ItemWindow (UPDATEiw, &IW, IW.nItems - 1);
1522 		  break;
1523 		}
1524 		if (NoMoreAccess(NULL)) {
1525 		  PromptWindow (DELETEpw, &PWt);
1526 		  ItemWindow (DELETEiw, &IW);
1527 		  return FALSE;
1528 		}
1529 	      }
1530 	      else
1531 		ProblemWindow ("Illegal name (check delimiters).", FALSE);
1532 	    }
1533 	    else
1534 	      break;
1535 	 }
1536 	 PromptWindow (DELETEpw, &PWt);
1537 	 break;
1538        }
1539        /***********************************************************************
1540        * Create entry.
1541        ***********************************************************************/
1542        case CREATEENTRYkey_EDIT: {
1543 	 int nameItemN;
1544 	 /*********************************************************************
1545 	 * Do any items exist?
1546 	 *********************************************************************/
1547 	 if (IW.nItems == 0) {
1548 	   ProblemWindow ("A vAttribute isn't selected (none exist).",
1549 			  FALSE);
1550 	   break;
1551 	 }
1552 	 /*********************************************************************
1553 	 * Calculate attribute number.
1554 	 *********************************************************************/
1555 	 for (attrX = 0, nameItemN = 0; attrX < nAttrs; attrX++) {
1556 	    int nItems = (int) (entryIs[attrX] ? 4 : 1);
1557 	    if (IW.itemN < nameItemN + nItems) {
1558 	      attrN = attrNs[attrX];
1559 	      break;
1560 	    }
1561 	    nameItemN += nItems;
1562 	 }
1563 	 /*********************************************************************
1564 	 * Create entry (unless it already exists).
1565 	 *********************************************************************/
1566          if (entryIs[attrX])
1567            ProblemWindow ("An entry already exists.", FALSE);
1568          else {
1569 	   Logical changed = FALSE;
1570            if (!EditEntry(attrN,varN,BOO(Z,zENTRYt,rENTRYt),TRUE,&changed)) {
1571 	     ItemWindow (DELETEiw, &IW);
1572 	     return FALSE;
1573 	   }
1574 	   if (changed) {
1575              FreeVarEntryMenu (attrNs, entryIs, &IW);
1576              if (!BuildVarEntryMenu(Z,varN,&nAttrs,&attrNs,&entryIs,&IW)) {
1577 	       ItemWindow (DELETEiw, &IW);
1578 	       return FALSE;
1579 	     }
1580              ItemWindow (UPDATEiw, &IW, nameItemN);
1581            }
1582 	 }
1583 	 break;
1584        }
1585        /***********************************************************************
1586        * Delete entry.
1587        ***********************************************************************/
1588        case DELETEATTRorENTRYkey_EDIT: {
1589 	 int nameItemN;
1590 	 /*********************************************************************
1591 	 * Do any items exist?
1592 	 *********************************************************************/
1593 	 if (IW.nItems == 0) {
1594 	   ProblemWindow ("A vAttribute isn't selected (none exist).", FALSE);
1595 	   break;
1596 	 }
1597 	 /*********************************************************************
1598 	 * Calculate attribute number.
1599 	 *********************************************************************/
1600 	 for (attrX = 0, nameItemN = 0; attrX < nAttrs; attrX++) {
1601 	    int nItems = (int) (entryIs[attrX] ? 4 : 1);
1602 	    if (IW.itemN < nameItemN + nItems) {
1603 	      attrN = attrNs[attrX];
1604 	      break;
1605 	    }
1606 	    nameItemN += nItems;
1607 	 }
1608 	 /*********************************************************************
1609 	 * Delete entry (unless it doesn't exist).
1610 	 *********************************************************************/
1611 	 if (entryIs[attrX]) {
1612 	   char attrName[CDF_ATTR_NAME_LEN256+1], varName[CDF_VAR_NAME_LEN256+1],
1613 		question1[28+1+CDF_ATTR_NAME_LEN256+1+1],
1614 		question2[29+1+CDF_VAR_NAME_LEN256+1+1], delim;
1615 	   status = CDFlib (SELECT_, ATTR_, attrN,
1616 			    GET_, ATTR_NAME_, attrName,
1617 			    SELECT_, BOO(Z,zVAR_,rVAR_), varN,
1618 			    GET_, BOO(Z,zVAR_NAME_,rVAR_NAME_), varName,
1619 			    NULL_);
1620 	   if (!ReportStatus(status,FALSE)) {
1621 	     ItemWindow (DELETEiw, &IW);
1622 	     return FALSE;
1623 	   }
1624 	   delim = PickDelimiter (attrName, strlen(attrName));
1625 	   sprintf (question1, "Delete %sEntry of vAttribute %c%s%c",
1626 		    BOO(Z,"z","r"), delim, attrName, delim);
1627 	   delim = PickDelimiter (varName, strlen(varName));
1628 	   sprintf (question2, "corresponding to %sVariable %c%s%c ?",
1629 		    BOO(Z,"z","r"), delim, varName, delim);
1630 	   if (ConfirmWindow(4,78,question1,question2,
1631 			     FALSE,DELETEENTRYhelpID)) {
1632 	     status = CDFlib (SELECT_, BOO(Z,zENTRY_,rENTRY_), varN,
1633 			      DELETE_, BOO(Z,zENTRY_,rENTRY_),
1634 			      NULL_);
1635 	     if (ReportStatus(status,FALSE)) {
1636 	       FreeVarEntryMenu (attrNs, entryIs, &IW);
1637 	       if (!BuildVarEntryMenu(Z,varN,&nAttrs,
1638 				      &attrNs,&entryIs,&IW)) {
1639 		 ItemWindow (DELETEiw, &IW);
1640 		 return FALSE;
1641 	       }
1642 	       ItemWindow (UPDATEiw, &IW, nameItemN);
1643 	     }
1644 	     else {
1645 	       if (NoMoreAccess(NULL)) {
1646 		 ItemWindow (DELETEiw, &IW);
1647 		 return FALSE;
1648 	       }
1649 	     }
1650 	   }
1651 	 }
1652 	 else
1653 	   ProblemWindow ("An entry does not exist.", FALSE);
1654 	 break;
1655        }
1656        /***********************************************************************
1657        * Next variable.
1658        ***********************************************************************/
1659        case NEXTVARkey_EDIT:
1660 	 varN = (varN + 1) % nVars;
1661 	 FreeVarEntryMenu (attrNs, entryIs, &IW);
1662 	 if (!BuildVarEntryMenu(Z,varN,&nAttrs,&attrNs,&entryIs,&IW)) {
1663 	   ItemWindow (DELETEiw, &IW);
1664 	   return FALSE;
1665 	 }
1666 	 ItemWindow (UPDATEiw, &IW, 0);
1667 	 break;
1668        /***********************************************************************
1669        * Display online help.
1670        ***********************************************************************/
1671        case HELPkey_FSI:
1672 	 OnlineHelpWindow (ilhFile, ENTRIEShelpID);
1673 	 break;
1674        /***********************************************************************
1675        * Exit menu.
1676        ***********************************************************************/
1677        case EXITkey_FSI:
1678 	 ItemWindow (DELETEiw, &IW);
1679 	 FreeVarEntryMenu (attrNs, entryIs, &IW);
1680 	 return TRUE;
1681      }
1682    }
1683 }
1684 
1685 /******************************************************************************
1686 * BuildVarEntryMenu.
1687 ******************************************************************************/
1688 
BuildVarEntryMenu(Z,varN,nAttrs,attrNs,entryIs,IW)1689 Logical BuildVarEntryMenu (Z, varN, nAttrs, attrNs, entryIs, IW)
1690 Logical Z;
1691 long varN;
1692 long *nAttrs;
1693 long **attrNs;
1694 Logical **entryIs;
1695 struct ItemWindowStruct *IW;
1696 {
1697    CDFstatus status;
1698    int attrX, curItem, curCol, lineN, n, nItems, dataSpecCol;
1699    long dataType, numElems, attrN;
1700    char attrName[CDF_ATTR_NAME_LEN256+1], varName[CDF_VAR_NAME_LEN256+1], delim,
1701 	field[80+1];
1702    void *binary;
1703    /***************************************************************************
1704    * Determine number of attributes (of variable scope).
1705    ***************************************************************************/
1706    status = CDFlib (GET_, CDF_NUMvATTRS_, nAttrs,
1707 		    NULL_);
1708    if (!ReportStatus(status,FALSE)) return FALSE;
1709    /***************************************************************************
1710    * Count/save attribute numbers.
1711    ***************************************************************************/
1712    *attrNs = (long *) cdf_AllocateMemory ((size_t) (*nAttrs * sizeof(long)),
1713 				      FatalError);
1714    *entryIs = (Logical *) cdf_AllocateMemory ((size_t) (*nAttrs * sizeof(Logical)),
1715 					  FatalError);
1716    for (attrN = 0, attrX = 0, nItems = 0; attrX < *nAttrs; attrN++) {
1717       long scope;
1718       /************************************************************************
1719       * Determine scope.
1720       ************************************************************************/
1721       status = CDFlib (SELECT_, ATTR_, attrN,
1722 		       GET_, ATTR_SCOPE_, &scope,
1723 		       NULL_);
1724       if (!ReportStatus(status,FALSE)) return FALSE;
1725       /************************************************************************
1726       * If proper scope, save attribute number and determine if entry exists.
1727       ************************************************************************/
1728       if (scope == VARIABLE_SCOPE) {
1729 	(*attrNs)[attrX] = attrN;
1730 	status = CDFlib (SELECT_, BOO(Z,zENTRY_,rENTRY_), varN,
1731 			 GET_, BOO(Z,zENTRY_DATATYPE_,
1732 				     rENTRY_DATATYPE_), &dataType,
1733 			 NULL_);
1734 	switch (status) {
1735 	  case NO_SUCH_ENTRY:
1736 	    (*entryIs)[attrX] = FALSE;
1737 	    nItems += 1;
1738 	    break;
1739 	  default:
1740 	    if (!ReportStatus(status,FALSE)) return FALSE;
1741 	    (*entryIs)[attrX] = TRUE;
1742 	    nItems += 4;
1743 	    break;
1744 	}
1745 	attrX++;
1746       }
1747    }
1748    /***************************************************************************
1749    * Allocate item section control/lines.
1750    ***************************************************************************/
1751    AllocIW (IW, nItems, (int) *nAttrs, 80, FatalError);
1752    /***************************************************************************
1753    * Encode label/header.
1754    ***************************************************************************/
1755    status = CDFlib (SELECT_, VAR(Z), varN,
1756 		    GET_, VAR_NAME(Z), varName,
1757 		    NULL_);
1758    if (!ReportStatus(status,FALSE)) return FALSE;
1759    delim = PickDelimiter (varName, strlen(varName));
1760    sprintf (IW->label, " %cVariable %c%s%c %cEntries ", BOO(Z,'z','r'), delim,
1761 	    varName, delim, BOO(Z,'z','r'));
1762 
1763    sprintf (IW->hLines[0],"%ld vAttributes", *nAttrs);
1764    strcpyX (IW->hLines[1], "AttrName         DataSpec  Value(s)", 0);
1765    /***************************************************************************
1766    * Build each attribute/entry line.
1767    ***************************************************************************/
1768    lineN = 0;
1769    curItem = 0;
1770    for (attrX = 0; attrX < *nAttrs; attrX++) {
1771       /************************************************************************
1772       * Inquire attribute/entry.
1773       ************************************************************************/
1774       status = CDFlib (SELECT_, ATTR_, (*attrNs)[attrX],
1775 		       GET_, ATTR_NAME_, attrName,
1776 		       NULL_);
1777       if (!ReportStatus(status,FALSE)) return FALSE;
1778       /************************************************************************
1779       * Setup attribute name.
1780       ************************************************************************/
1781       curCol = 0;
1782       EncodeString (strlen(attrName), attrName, field, 0, ATTRNAME_FIELD_LEN);
1783       strcpyX (IW->iLines[lineN], field, 0);
1784       if (strlen(field) < (size_t) ATTRNAME_FIELD_LEN) {
1785 	CatNcharacters (IW->iLines[lineN], ATTRNAME_FIELD_LEN - strlen(field),
1786 			(int) ' ');
1787       }
1788       CatNcharacters (IW->iLines[lineN], ATTRNAME_FIELD_BLANKS, (int) ' ');
1789       IW->iLineNs[curItem] = lineN;
1790       IW->iCols[curItem] = curCol;
1791       IW->iLens[curItem] = strlen(field);
1792       curCol += ATTRNAME_FIELD_LEN + ATTRNAME_FIELD_BLANKS;
1793       curItem++;
1794       /************************************************************************
1795       * Setup entry data specification/value(s).
1796       ************************************************************************/
1797       if ((*entryIs)[attrX]) {
1798 	status = CDFlib (SELECT_, BOO(Z,zENTRY_,rENTRY_), varN,
1799 			 GET_, BOO(Z,zENTRY_DATATYPE_,
1800 				     rENTRY_DATATYPE_), &dataType,
1801 			       BOO(Z,zENTRY_NUMELEMS_,
1802 				     rENTRY_NUMELEMS_), &numElems,
1803 			 NULL_);
1804 	if (!ReportStatus(status,FALSE)) return FALSE;
1805 	strcpyX (field, DataTypeToken(dataType), 0);
1806 	catchrX (field, (int) '/', 0);
1807 	sprintf (&field[strlen(field)], "%ld", numElems);
1808 	if (strlen(field) > (size_t) DATASPEC_FIELD_LEN) {
1809 	  strcpyX (field + DATASPEC_FIELD_LEN - 3, "...", 0);
1810 	}
1811 	strcatX (IW->iLines[lineN], field, 0);
1812 	if (strlen(field) < (size_t) DATASPEC_FIELD_LEN) {
1813 	  CatNcharacters (IW->iLines[lineN],
1814 			  DATASPEC_FIELD_LEN - strlen(field), (int) ' ');
1815 	}
1816 	CatNcharacters (IW->iLines[lineN], DATASPEC_FIELD_BLANKS, (int) ' ');
1817 	IW->iLineNs[curItem] = lineN;
1818 	IW->iCols[curItem] = curCol;
1819 	IW->iLens[curItem] = strlen(field);
1820 	dataSpecCol = curCol;
1821 	curCol += DATASPEC_FIELD_LEN + DATASPEC_FIELD_BLANKS;
1822 	curItem++;
1823 	binary = cdf_AllocateMemory ((size_t) (numElems * CDFelemSize(dataType)),
1824 				 FatalError);
1825 	status = CDFlib (GET_, BOO(Z,zENTRY_DATA_,rENTRY_DATA_), binary,
1826 			 NULL_);
1827 	if (!ReportStatus(status,FALSE)) return FALSE;
1828 	n = EncodeValuesFormat (dataType, numElems, binary,
1829 				&(IW->iLines[lineN][curCol]), NULL, 0,
1830 				varENTRYVALUE_FIELD_LEN, EPOCH0_STYLE);
1831 	cdf_FreeMemory (binary, FatalError);
1832 	IW->iLineNs[curItem] = lineN;
1833 	IW->iCols[curItem] = dataSpecCol;
1834 	IW->iLens[curItem] = strlen(&(IW->iLines[lineN][dataSpecCol]));
1835 	curItem++;
1836 	IW->iLineNs[curItem] = lineN;
1837 	IW->iCols[curItem] = curCol;
1838 	IW->iLens[curItem] = n;
1839 	curItem++;
1840       }
1841       lineN++;
1842    }
1843    return TRUE;
1844 }
1845 
1846 /******************************************************************************
1847 * FreeVarEntryMenu.
1848 ******************************************************************************/
1849 
FreeVarEntryMenu(attrNs,entryIs,IW)1850 void FreeVarEntryMenu (attrNs, entryIs, IW)
1851 long *attrNs;
1852 Logical *entryIs;
1853 struct ItemWindowStruct *IW;
1854 {
1855   FreeIW (IW, FatalError);
1856   if (attrNs != NULL) cdf_FreeMemory (attrNs, FatalError);
1857   if (entryIs != NULL) cdf_FreeMemory (entryIs, FatalError);
1858   return;
1859 }
1860 
1861 /******************************************************************************
1862 * CreateEntry.
1863 ******************************************************************************/
1864 
CreateEntry(G,attrN,changed)1865 Logical CreateEntry (G, attrN, changed)
1866 Logical G;
1867 long attrN;
1868 Logical *changed;	/* Assumed to be initialized to FALSE by caller. */
1869 {
1870   long entryN;
1871   int entryType;
1872   char attrName[CDF_ATTR_NAME_LEN256+1], delim;
1873   CDFstatus status;
1874   /****************************************************************************
1875   * Inquire attribute name and delimiter to be used.
1876   ****************************************************************************/
1877   status = CDFlib (SELECT_, ATTR_, attrN,
1878 		   GET_, ATTR_NAME_, attrName,
1879 		   NULL_);
1880   if (!ReportStatus(status,FALSE)) return FALSE;
1881   delim = PickDelimiter (attrName, strlen(attrName));
1882   if (G) {
1883     /**************************************************************************
1884     * Global scope attribute, prompt for entry number.
1885     **************************************************************************/
1886     static char *header[] = { "Enter gEntry number..." };
1887     AOSs2 (trailer, "Enter: ________   Exit: ________", "Help:  ________")
1888     static char value[MAX_ENTRYNUM_LEN+1];
1889     static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI,
1890 			       NUL };
1891     static char label[15+CDF_ATTR_NAME_LEN256+1];
1892     static struct PromptWindowStruct PW = {
1893       label, 4, 23, 34, 1, header, MAX_ENTRYNUM_LEN, value, 2, trailer,
1894       exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
1895       INSERTorOVERkey_FSI
1896     };
1897     entryType = gENTRYt;
1898     EncodeKeyDefinitions (2, trailer, ENTERkey_FSI, EXITkey_FSI,
1899 			  HELPkey_FSI);
1900     strcpyX (PW.value, "", MAX_ENTRYNUM_LEN);
1901     sprintf (label, " gAttribute %c%s%c ", delim, attrName, delim);
1902     PromptWindow (NEWpw, &PW, 0, LogicalTRUE);
1903     for (;;) {
1904        if (EnterPW(&PW,ENTRYNUMBERhelpID)) {
1905 	 long entryNt; Logical exists;
1906 	 if (sscanf(PW.value,"%ld",&entryNt) == 1) {
1907 	   if (entryNt > 0) {
1908 	     if (!EntryExists(attrN,entryNt-1,entryType,&exists)) {
1909 	       PromptWindow (DELETEpw, &PW);
1910 	       return FALSE;
1911 	     }
1912 	     if (!exists) {
1913 	       entryN = entryNt - 1;
1914 	       break;
1915 	     }
1916 	     else
1917 	       ProblemWindow (E3(entryType,"That gEntry already exists.",
1918 					   "That rEntry already exists.",
1919 					   "That zEntry already exists."),
1920 			      FALSE);
1921 	   }
1922 	   else
1923 	     ProblemWindow ("Illegal gEntry number.", FALSE);
1924 	 }
1925 	 else
1926 	   ProblemWindow ("Error decoding gEntry number.", FALSE);
1927        }
1928        else {
1929 	 entryN = -1;
1930 	 break;
1931        }
1932     }
1933     PromptWindow (DELETEpw, &PW);
1934   }
1935   else {
1936     /**************************************************************************
1937     * Variable scope attribute, select corresponding variable (or enter entry
1938     * number).
1939     **************************************************************************/
1940     static char *header[] =  { "Select the corresponding variable..." };
1941     AOSs3 (trailer, "Select: ________   Numbered rEntry: ________",
1942 		    "Exit:   ________   Numbered zEntry: ________",
1943 		    "Help:   ________")
1944     static int exitChars[] = { ENTERkey_FSI, rENTRYbyNUMBERkey_EDIT,
1945 			       EXITkey_FSI, zENTRYbyNUMBERkey_EDIT,
1946 			       HELPkey_FSI, NUL };
1947     static char label[15+CDF_ATTR_NAME_LEN256+1];
1948     static struct ItemWindowStruct IW = {
1949 	4, 16, 48, label, 1, header, 0, NULL, 0, NULL, NULL, NULL, 7,
1950 	3, trailer, exitChars, REFRESHkey_FSI, TRUE, NSkey_FSI, PSkey_FSI
1951     };
1952     CDFstatus status; long NrVars, NzVars; int nVars, varX;
1953     EncodeKeyDefinitions (3, trailer, ENTERkey_FSI, rENTRYbyNUMBERkey_EDIT,
1954 			  EXITkey_FSI, zENTRYbyNUMBERkey_EDIT, HELPkey_FSI);
1955     sprintf (label, " vAttribute %c%s%c ", delim, attrName, delim);
1956     status = CDFlib (GET_, CDF_NUMrVARS_, &NrVars,
1957 			   CDF_NUMzVARS_, &NzVars,
1958 		     NULL_);
1959     if (!ReportStatus(status,FALSE)) return FALSE;
1960     nVars = (int) (NrVars + NzVars);
1961     AllocIW (&IW, nVars, nVars, 1+CDF_VAR_NAME_LEN256+1+1, FatalError);
1962     for (varX = 0; varX < nVars; varX++) {
1963        char varName[CDF_VAR_NAME_LEN256+1], delim; size_t lengthX;
1964        Logical Z = (varX < NrVars ? FALSE : TRUE);
1965        long varN = BOO(Z,varX-NrVars,varX);
1966        status = CDFlib (SELECT_, VAR(Z), varN,
1967 			GET_, VAR_NAME(Z), varName,
1968 			NULL_);
1969        if (!ReportStatus(status,FALSE)) return FALSE;
1970        delim = PickDelimiter (varName, strlen(varName));
1971        sprintf (IW.iLines[varX], "%c%s%c", delim, varName, delim);
1972        IW.iLineNs[varX] = varX;
1973        IW.iCols[varX] = 0;
1974        lengthX = strlen(IW.iLines[varX]);
1975        IW.iLens[varX] = (int) MINIMUM(40,lengthX);
1976     }
1977     ItemWindow (NEWiw, &IW, 0);
1978     for (entryN = -2; entryN == -2; ) {
1979        ItemWindow (READiw, &IW);
1980        switch (IW.key) {
1981 	 case ENTERkey_FSI:
1982 	   if (IW.nItems == 0)
1983 	     ProblemWindow ("No variables exist.", FALSE);
1984 	   else {
1985 	     Logical Z = BOO(IW.itemN < NrVars,FALSE,TRUE), exists;
1986 	     long entryNt = BOO(Z,IW.itemN-NrVars,IW.itemN);
1987 	     entryType = BOO(Z,zENTRYt,rENTRYt);
1988 	     if (!EntryExists(attrN,entryNt,entryType,&exists)) {
1989 	       ItemWindow (DELETEiw, &IW);
1990 	       return FALSE;
1991 	     }
1992 	     if (!exists)
1993 	       entryN = entryNt;
1994 	     else
1995 	       ProblemWindow (E3(entryType,"That gEntry already exists.",
1996 					   "That rEntry already exists.",
1997 					   "That zEntry already exists."),
1998 			      FALSE);
1999 	   }
2000 	   break;
2001 	 case zENTRYbyNUMBERkey_EDIT:
2002 	 case rENTRYbyNUMBERkey_EDIT: {
2003 	   static char *rHeader[] = { "Enter rEntry number..." };
2004 	   static char *zHeader[] = { "Enter zEntry number..." };
2005 	   AOSs2 (trailer, "Enter: ________   Exit: ________",
2006 			   "Help:  ________")
2007 	   static char value[MAX_ENTRYNUM_LEN+1];
2008 	   static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI,
2009 				      HELPkey_FSI, NUL };
2010 	   static char label[15+CDF_ATTR_NAME_LEN256+1];
2011 	   static struct PromptWindowStruct PW = {
2012 	     label, 7, 23, 34, 1, NULL, MAX_ENTRYNUM_LEN, value, 2, trailer,
2013 	     exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
2014 	     INSERTorOVERkey_FSI
2015 	   };
2016 	   Logical Z = (IW.key == zENTRYbyNUMBERkey_EDIT);
2017 	   entryType = BOO(Z,zENTRYt,rENTRYt);
2018 	   EncodeKeyDefinitions (2, trailer, ENTERkey_FSI, EXITkey_FSI,
2019 				 HELPkey_FSI);
2020 	   PW.hLines = BOO(Z,zHeader,rHeader);
2021 	   strcpyX (PW.value, "", MAX_ENTRYNUM_LEN);
2022 	   sprintf (label, " vAttribute %c%s%c ", delim, attrName, delim);
2023 	   PromptWindow (NEWpw, &PW, 0, LogicalTRUE);
2024 	   for (;;) {
2025 	      if (EnterPW(&PW,ENTRYNUMBERhelpID)) {
2026 		long entryNt; Logical exists;
2027 		if (sscanf(PW.value,"%ld",&entryNt) == 1) {
2028 		  if (entryNt > 0) {
2029 		    if (!EntryExists(attrN,entryNt-1,entryType,&exists)) {
2030 		      PromptWindow (DELETEpw, &PW);
2031 		      return FALSE;
2032 		    }
2033 		    if (!exists) {
2034 		      entryN = entryNt - 1;
2035 		      break;
2036 		    }
2037 		    else
2038 		      ProblemWindow (E3(entryType,
2039 					"That gEntry already exists.",
2040 					"That rEntry already exists.",
2041 					"That zEntry already exists."), FALSE);
2042 		  }
2043 		  else
2044 		    ProblemWindow (BOO(Z,"Illegal zEntry number.",
2045 					 "Illegal rEntry number."), FALSE);
2046 		}
2047 		else
2048 		  ProblemWindow (BOO(Z,"Error decoding zEntry number.",
2049 				       "Error decoding rEntry number."),FALSE);
2050 	      }
2051 	      else {
2052 		entryN = -1;
2053 		break;
2054 	      }
2055 	   }
2056 	   PromptWindow (DELETEpw, &PW);
2057 	   break;
2058 	 }
2059 	 case HELPkey_FSI:
2060 	   OnlineHelpWindow (ilhFile, VARSELECThelpID);
2061 	   break;
2062 	 case EXITkey_FSI:
2063 	   entryN = -1;
2064 	   break;
2065        }
2066     }
2067     ItemWindow (DELETEiw, &IW);
2068     FreeIW (&IW, FatalError);
2069   }
2070   /****************************************************************************
2071   * Return if an entry number wasn't selected/entered.
2072   ****************************************************************************/
2073   if (entryN == -1) return TRUE;
2074   /****************************************************************************
2075   * Create the entry.
2076   ****************************************************************************/
2077   return EditEntry(attrN,entryN,entryType,TRUE,changed);
2078 }
2079 
2080 /******************************************************************************
2081 * EntryExists.
2082 ******************************************************************************/
2083 
EntryExists(attrN,entryN,entryType,exists)2084 Logical EntryExists (attrN, entryN, entryType, exists)
2085 long attrN;
2086 long entryN;
2087 int entryType;
2088 Logical *exists;
2089 {
2090   CDFstatus status = CDFlib (SELECT_, ATTR_, attrN,
2091 			     CONFIRM_, ENTRY_EXISTENCE(entryType), entryN,
2092 			     NULL_);
2093   switch (status) {
2094     case NO_SUCH_ENTRY:
2095       *exists = FALSE;
2096       break;
2097     default:
2098       ReportStatus (status, FALSE);
2099       if (StatusBAD(status)) return FALSE;
2100       *exists = StatusOK(status);
2101       break;
2102   }
2103   return TRUE;
2104 }
2105 
2106 /******************************************************************************
2107 * EditAttrsX.
2108 ******************************************************************************/
2109 
EditAttrsX(G,CDFname)2110 Logical EditAttrsX (G, CDFname)
2111 Logical G;                      /* If TRUE, global scoped attributes. */
2112 char *CDFname;                  /* Name of the CDF being edited. */
2113 {
2114    CDFstatus status;
2115    long nAttrs;			/* Total number of attributes. */
2116    long nAttrsOfScope;		/* Number of attributes of the proper scope. */
2117    long attrN;
2118    long fieldN;
2119    long *attrNs;
2120    AOSs2 (header, BLANKs78, BLANKs78)
2121    AOSs1 (trailerBrowse,
2122     "Select: ________   Exit: ________   Help: ________")
2123    AOSs2A (trailerEdit,
2124     "Select: ________  Create attribute: ________  Toggle scope:     ________",
2125     "Exit:   ________  Help:             ________  Delete attribute: ________")
2126    static int exitCharsBrowse[] = {
2127      ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL
2128    };
2129    static int exitCharsEdit[] = {
2130      ENTERkey_FSI, EXITkey_FSI, CREATEATTRkey_EDIT, HELPkey_FSI,
2131      TOGGLESCOPEkey_EDIT, DELETEATTRorENTRYkey_EDIT, NUL
2132    };
2133    static char label[6+DU_MAX_NAME_LEN+14+1];
2134    static struct ItemWindowStruct IW = {
2135       0, 0, 80, label, 2, header, 0, NULL, 0, NULL, NULL, NULL, 0, 0, NULL,
2136       NULL, REFRESHkey_FSI, TRUE, NSkey_FSI, PSkey_FSI
2137    };
2138    static Logical first = TRUE;
2139    /***************************************************************************
2140    * First time...
2141    ***************************************************************************/
2142    if (first) {
2143        EncodeKeyDefinitions (1, trailerBrowse, ENTERkey_FSI, EXITkey_FSI,
2144 			     HELPkey_FSI);
2145        EncodeKeyDefinitions (2, trailerEdit, ENTERkey_FSI,
2146 			     CREATEATTRkey_EDIT, TOGGLESCOPEkey_EDIT,
2147 			     EXITkey_FSI, HELPkey_FSI,
2148 			     DELETEATTRorENTRYkey_EDIT);
2149      first = FALSE;
2150    }
2151      if (browseOnly) {
2152        IW.NiRows = 14;
2153        IW.NtLines = 1;
2154        IW.tLines = trailerBrowse;
2155        IW.exitChars = exitCharsBrowse;
2156      }
2157      else {
2158        IW.NiRows = 13;
2159        IW.NtLines = 2;
2160        IW.tLines = trailerEdit;
2161        IW.exitChars = exitCharsEdit;
2162      }
2163    /***************************************************************************
2164    * Build attribute lines and display menu.
2165    ***************************************************************************/
2166    if (!BuildAttrMenuX(G,CDFname,&nAttrs,
2167 		       &nAttrsOfScope,&attrNs,&IW)) return FALSE;
2168    ItemWindow (NEWiw, &IW, 0);
2169    /***************************************************************************
2170    * Read/process keystrokes until request to exit menu.
2171    ***************************************************************************/
2172    for (;;) {
2173      ItemWindow (READiw, &IW);
2174      if (IW.nItems != 0) {
2175        fieldN = IW.itemN % 3;
2176        attrN = attrNs[IW.itemN/3];
2177      }
2178      switch (IW.key) {
2179        /***********************************************************************
2180        * Item selected.
2181        ***********************************************************************/
2182        case ENTERkey_FSI: {
2183 	 /*********************************************************************
2184 	 * Check if any attributes/entries exist.
2185 	 *********************************************************************/
2186 	 if (IW.nItems == 0) {
2187 	   ProblemWindow (BOO(G,"Nothing selected (no gAttributes exist).",
2188 			        "Nothing selected (no vAttributes exist)."),
2189 			  FALSE);
2190 	   break;
2191 	 }
2192 	 /*********************************************************************
2193 	 * Perform desired function (based on field number).
2194 	 *********************************************************************/
2195 	 switch (fieldN) {
2196 	   /*******************************************************************
2197 	   * Modify attribute name.
2198 	   *******************************************************************/
2199 	   case 0: {
2200 	     char attrName[CDF_ATTR_NAME_LEN256+1];
2201 	     status = CDFlib (SELECT_, ATTR_, attrN,
2202 			      GET_, ATTR_NAME_, attrName,
2203 			      NULL_);
2204 	     if (!ReportStatus(status,FALSE)) {
2205 	       ItemWindow (DELETEiw, &IW);
2206 	       return FALSE;
2207 	     }
2208 	     if (browseOnly) {
2209 	       ShowFullName (attrName, TRUE);
2210 	     }
2211 	     else {
2212 	       static char *header[] = {
2213 	         "Enter new name (with delimiters)...",
2214 	         "Syntax: <delim><char1><char2>...<charN><delim>",
2215 	         "Example: \"FILTERs\""
2216 	       };
2217 	       AOSs1 (trailer,
2218 		      "Enter: ________   Exit: ________  Help: ________")
2219 	       static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI,
2220 					  HELPkey_FSI, NUL };
2221 	       static char value[1+CDF_ATTR_NAME_LEN256+1+1];
2222 	       static char label[15+CDF_ATTR_NAME_LEN256+1];
2223 	       static struct PromptWindowStruct PWt = {
2224 		  label, 4, 1, 78, 3, header, CDF_ATTR_NAME_LEN256+2, value,
2225 		  1, trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI,
2226 		  EOLkey_FSI, INSERTorOVERkey_FSI
2227 	       };
2228 	       char delim;
2229 	       EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
2230 				     HELPkey_FSI);
2231 	       delim = PickDelimiter (attrName, strlen(attrName));
2232 	       sprintf (value, "%c%s%c", delim, attrName, delim);
2233 	       sprintf (label, " %cAttribute %c%s%c ", BOO(G,'g','v'),
2234 		        delim, attrName, delim);
2235 	       PromptWindow (NEWpw, &PWt, (int)(strlen(PWt.value) - 1),
2236 			     LogicalTRUE);
2237 	       for (;;) {
2238 		  if (EnterPW(&PWt,ATTRRENAMEhelpID)) {
2239 		    char attrName[CDF_ATTR_NAME_LEN256+1];
2240 		    if (DecodeDelimitedString(PWt.value,attrName)) {
2241 		      status = CDFlib (PUT_, ATTR_NAME_, attrName,
2242 				       NULL_);
2243 		      if (ReportStatus(status,FALSE)) {
2244 		        FreeAttrMenuX (attrNs, &IW);
2245 		        if (!BuildAttrMenuX(G,CDFname,&nAttrs,
2246 					    &nAttrsOfScope,&attrNs,&IW)) {
2247 			  PromptWindow (DELETEpw, &PWt);
2248 			  ItemWindow (DELETEiw, &IW);
2249 			  return FALSE;
2250 			}
2251 		        ItemWindow (UPDATEiw, &IW, IW.itemN);
2252 		        break;
2253 		      }
2254 		      if (NoMoreAccess(NULL)) {
2255 			PromptWindow (DELETEpw, &PWt);
2256 			ItemWindow (DELETEiw, &IW);
2257 			return FALSE;
2258 		      }
2259 		    }
2260 		    else
2261 		      ProblemWindow ("Illegal name (check delimiters).",
2262 				     FALSE);
2263 		  }
2264 		  else
2265 		    break;
2266 	       }
2267 	       PromptWindow (DELETEpw, &PWt);
2268 	     }
2269 	     break;
2270 	   }
2271 	   /*******************************************************************
2272 	   * Edit entries.
2273 	   *******************************************************************/
2274 	   case 1: {
2275 	     ItemWindow (UNDISPLAYiw, &IW);
2276 	     if (!EditAttrEntriesX(G,attrN,nAttrs)) {
2277 	       ItemWindow (DELETEiw, &IW);
2278 	       return FALSE;
2279 	     }
2280 	     ItemWindow (REDISPLAYiw, &IW);
2281 	     break;
2282 	   }
2283 	   /*******************************************************************
2284 	   * TextEdit entries.
2285 	   *******************************************************************/
2286 	   case 2: {
2287 	     if (G) {
2288 	       if (!TextEditEntries(attrN)) {
2289 		 ItemWindow (DELETEiw, &IW);
2290 		 return FALSE;
2291 	       }
2292 	     }
2293 	     else
2294 	       ProblemWindow ("Not supported for vAttributes.", FALSE);
2295 	     break;
2296 	   }
2297 	 }
2298 	 break;
2299        }
2300        /***********************************************************************
2301        * Create new attribute.
2302        ***********************************************************************/
2303        case CREATEATTRkey_EDIT: {
2304 	 static char *header[] = {
2305 	   "Enter name (with delimiters)...",
2306 	   "Syntax: <delim><char1><char2>...<charN><delim>",
2307 	   "Example: \"Resolution\""
2308 	 };
2309 	 AOSs1 (trailer, "Enter: ________   Exit: ________  Help: ________")
2310 	 static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI,
2311 				    NUL };
2312 	 static char value[DELIMed_ATTR_NAME_LEN+1];
2313 	 static char label[16+1];
2314 	 static struct PromptWindowStruct PWt = {
2315 	   label, 4, 1, 78, 3, header, CDF_ATTR_NAME_LEN256+2, value, 1, trailer,
2316 	   exitChars, REFRESHkey_FSI, SOLkey_FSI, EOLkey_FSI,
2317 	   INSERTorOVERkey_FSI
2318 	 };
2319 	 EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
2320 			       HELPkey_FSI);
2321 	 strcpyX (value, "\"\"", DELIMed_ATTR_NAME_LEN);
2322 	 sprintf (label, " New %cAttribute ", BOO(G,'g','v'));
2323 	 PromptWindow (NEWpw, &PWt, 1, LogicalTRUE);
2324 	 for (;;) {
2325 	    if (EnterPW(&PWt,ATTRNAMEhelpID)) {
2326 	      char attrName[CDF_ATTR_NAME_LEN256+1];
2327 	      long attrNum;
2328 	      if (DecodeDelimitedString(PWt.value,attrName)) {
2329 		status = CDFlib (CREATE_, ATTR_, attrName,
2330 						 BOO(G,GLOBAL_SCOPE,
2331 						       VARIABLE_SCOPE),
2332 						 &attrNum,
2333 				 NULL_);
2334 		if (ReportStatus(status,FALSE)) {
2335 		  FreeAttrMenuX (attrNs, &IW);
2336 		  if (!BuildAttrMenuX(G,CDFname,&nAttrs,
2337 				      &nAttrsOfScope,&attrNs,&IW)) {
2338 		    PromptWindow (DELETEpw, &PWt);
2339 		    ItemWindow (DELETEiw, &IW);
2340 		    return FALSE;
2341 		  }
2342 		  ItemWindow (UPDATEiw, &IW, IW.nItems - 3);
2343 		  break;
2344 		}
2345 		if (NoMoreAccess(NULL)) {
2346 		  PromptWindow (DELETEpw, &PWt);
2347 		  ItemWindow (DELETEiw, &IW);
2348 		  return FALSE;
2349 		}
2350 	      }
2351 	      else
2352 		ProblemWindow ("Illegal name (check delimiters).", FALSE);
2353 	    }
2354 	    else
2355 	      break;
2356 	 }
2357 	 PromptWindow (DELETEpw, &PWt);
2358 	 break;
2359        }
2360        /***********************************************************************
2361        * Delete attribute.
2362        ***********************************************************************/
2363        case DELETEATTRorENTRYkey_EDIT: {
2364 	 char attrName[CDF_ATTR_NAME_LEN256+1],
2365 	      question[22+CDF_ATTR_NAME_LEN256+1], delim;
2366 	 if (IW.nItems == 0) {
2367 	   ProblemWindow
2368 	       (BOO(G,"A gAttribute isn't selected (none exist).",
2369 		      "A vAttribute isn't selected (none exist)."), FALSE);
2370 	   break;
2371 	 }
2372 	 status = CDFlib (SELECT_, ATTR_, attrN,
2373 			  GET_, ATTR_NAME_, attrName,
2374 			  NULL_);
2375 	 if (!ReportStatus(status,FALSE)) {
2376 	   ItemWindow (DELETEiw, &IW);
2377 	   return FALSE;
2378 	 }
2379 	 delim = PickDelimiter (attrName, strlen(attrName));
2380 	 sprintf (question, "Delete %sAttribute %c%s%c ?",
2381 		  BOO(G,"g","v"), delim, attrName, delim);
2382 	 if (ConfirmWindow(4,78,question,NULL,FALSE,DELETEATTRhelpID)) {
2383 	   status = CDFlib (DELETE_, ATTR_,
2384 			    NULL_);
2385 	   if (ReportStatus(status,FALSE)) {
2386 	     int itemNt = IW.itemN - (IW.itemN % 3);
2387 	     FreeAttrMenuX (attrNs, &IW);
2388 	     if (!BuildAttrMenuX(G,CDFname,&nAttrs,
2389 				 &nAttrsOfScope,&attrNs,&IW)) {
2390 	       ItemWindow (DELETEiw, &IW);
2391 	       return FALSE;
2392 	     }
2393 	     if (itemNt == IW.nItems) itemNt = MaxInt (0, itemNt - 3);
2394 	     ItemWindow (UPDATEiw, &IW, itemNt);
2395 	   }
2396 	   else {
2397 	     if (NoMoreAccess(NULL)) {
2398 	       ItemWindow (DELETEiw, &IW);
2399 	       return FALSE;
2400 	     }
2401 	   }
2402 	 }
2403 	 break;
2404        }
2405        /***********************************************************************
2406        * Toggle scope.
2407        ***********************************************************************/
2408        case TOGGLESCOPEkey_EDIT: {
2409 	 if (IW.nItems == 0) {
2410 	   ProblemWindow(BOO(G,"A gAttribute isn't selected (none exist).",
2411 			       "A vAttribute isn't selected (none exist)."),
2412 			 FALSE);
2413 	   break;
2414 	 }
2415 	 status = CDFlib (SELECT_,ATTR_,attrN,
2416 			  PUT_,ATTR_SCOPE_,BOO(G,VARIABLE_SCOPE,GLOBAL_SCOPE),
2417 			  NULL_);
2418 	 if (ReportStatus(status,FALSE)) {
2419 	   int itemNt = IW.itemN - (IW.itemN % 3);
2420 	   FreeAttrMenuX (attrNs, &IW);
2421 	   if (!BuildAttrMenuX(G,CDFname,&nAttrs,
2422 			       &nAttrsOfScope,&attrNs,&IW)) {
2423 	     ItemWindow (DELETEiw, &IW);
2424 	     return FALSE;
2425 	   }
2426 	   if (itemNt == IW.nItems) itemNt = MaxInt (0, itemNt - 3);
2427 	   ItemWindow (UPDATEiw, &IW, itemNt);
2428 	 }
2429 	 else {
2430 	   if (NoMoreAccess(NULL)) {
2431 	     ItemWindow (DELETEiw, &IW);
2432 	     return FALSE;
2433 	   }
2434 	 }
2435 	 break;
2436        }
2437        /***********************************************************************
2438        * Display online help.
2439        ***********************************************************************/
2440        case HELPkey_FSI:
2441 	 OnlineHelpWindow (ilhFile, BOO(G,GATTRShelpIDx,VATTRShelpIDx));
2442 	 break;
2443        /***********************************************************************
2444        * Exit menu.
2445        ***********************************************************************/
2446        case EXITkey_FSI:
2447 	 ItemWindow (DELETEiw, &IW);
2448 	 FreeAttrMenuX (attrNs, &IW);
2449 	 return TRUE;
2450      }
2451    }
2452 }
2453 
2454 /******************************************************************************
2455 * BuildAttrMenuX.
2456 ******************************************************************************/
2457 
BuildAttrMenuX(G,CDFname,nAttrs,nAttrsOfScope,attrNs,IW)2458 Logical BuildAttrMenuX (G, CDFname, nAttrs, nAttrsOfScope, attrNs, IW)
2459 Logical G;
2460 char *CDFname;
2461 long *nAttrs;
2462 long *nAttrsOfScope;
2463 long **attrNs;
2464 struct ItemWindowStruct *IW;
2465 {
2466    CDFstatus status; long attrN; int lineN; size_t nBytes;
2467    int attrNameFieldLen = BOO(browseOnly,ATTRNAME_bFIELD_LEN,
2468 					 ATTRNAME_eFIELD_LEN);
2469    /***************************************************************************
2470    * Determine number of attributes (total and of proper scope).
2471    ***************************************************************************/
2472    status = CDFlib (GET_, CDF_NUMATTRS_, nAttrs,
2473 			  BOO(G,CDF_NUMgATTRS_,CDF_NUMvATTRS_), nAttrsOfScope,
2474 		    NULL_);
2475    if (!ReportStatus(status,FALSE)) return FALSE;
2476    /***************************************************************************
2477    * Allocate item section control/lines.
2478    ***************************************************************************/
2479    nBytes = (size_t) (*nAttrsOfScope * sizeof(long));
2480    *attrNs = (long *) cdf_AllocateMemory (nBytes, FatalError);
2481    AllocIW (IW, (int) (3 * (*nAttrsOfScope)), (int) *nAttrsOfScope,
2482 	    80, FatalError);
2483    /***************************************************************************
2484    * Encode label/header.
2485    ***************************************************************************/
2486    sprintf (IW->label, " CDF \"%s\" %cAttributes ", CDFname, BOO(G,'g','v'));
2487    if (G)
2488      sprintf (IW->hLines[0], "%ld gAttribute%s", *nAttrsOfScope,
2489 	      (*nAttrs == 1 ? "" : "s"));
2490    else
2491      sprintf (IW->hLines[0], "%ld vAttribute%s", *nAttrsOfScope,
2492 	      (*nAttrs == 1 ? "" : "s"));
2493    strcpyX (IW->hLines[1], "AttrName", 0);
2494    /***************************************************************************
2495    * Build each attribute/entry line.
2496    ***************************************************************************/
2497    for (attrN = 0, lineN = 0; attrN < *nAttrs; attrN++) {
2498       long scope; int itemN, nameLen;
2499       char attrName[CDF_ATTR_NAME_LEN256+1];
2500       /************************************************************************
2501       * Inquire attribute.
2502       ************************************************************************/
2503       status = CDFlib (SELECT_, ATTR_, attrN,
2504 		       GET_, ATTR_NAME_, attrName,
2505 			     ATTR_SCOPE_, &scope,
2506 		       NULL_);
2507       if (!ReportStatus(status,FALSE)) return FALSE;
2508       /************************************************************************
2509       * If of the proper scope...
2510       ************************************************************************/
2511       if ((G && scope == GLOBAL_SCOPE) ||
2512 	  (!G && scope == VARIABLE_SCOPE)) {
2513 	/**********************************************************************
2514 	* Save attribute number.
2515 	**********************************************************************/
2516 	(*attrNs)[lineN] = attrN;
2517 	/**********************************************************************
2518 	* Setup attribute name.
2519 	**********************************************************************/
2520         nameLen = (int) strlen(attrName);
2521 	EncodeString ((long) nameLen, attrName, IW->iLines[lineN],
2522 		      -attrNameFieldLen, attrNameFieldLen);
2523 	strcatX (IW->iLines[lineN], " ", 0);
2524 	itemN = 3 * lineN;
2525 	IW->iLineNs[itemN] = lineN;
2526 	IW->iCols[itemN] = 0;
2527 	IW->iLens[itemN] = MinInt(1 + nameLen + 1,attrNameFieldLen);
2528 	/**********************************************************************
2529 	* Setup <Edit/Browse entries> field.
2530 	**********************************************************************/
2531 	IW->iCols[itemN+1] = (int) strlen(IW->iLines[lineN]);
2532 	strcatX (IW->iLines[lineN],
2533 		 BOO(browseOnly,"<Browse entries> ","<Edit entries> "), 0);
2534 	IW->iLineNs[itemN+1] = lineN;
2535 	IW->iLens[itemN+1] = BOO(browseOnly,16,14);
2536 	/**********************************************************************
2537 	* Setup <TextEdit/TextBrowse entries> field.
2538 	**********************************************************************/
2539 	IW->iCols[itemN+2] = (int) strlen(IW->iLines[lineN]);
2540 	strcatX (IW->iLines[lineN],
2541 		 BOO(browseOnly,"<TextBrowse entries>","<TextEdit entries>"),
2542 		 0);
2543 	IW->iLineNs[itemN+2] = lineN;
2544 	IW->iLens[itemN+2] = BOO(browseOnly,20,18);
2545 	/**********************************************************************
2546 	* Increment to next line.
2547 	**********************************************************************/
2548 	lineN++;
2549      }
2550    }
2551    return TRUE;
2552 }
2553 
2554 /******************************************************************************
2555 * FreeAttrMenuX.
2556 ******************************************************************************/
2557 
FreeAttrMenuX(attrNs,IW)2558 void FreeAttrMenuX (attrNs, IW)
2559 long *attrNs;
2560 struct ItemWindowStruct *IW;
2561 {
2562   if (attrNs != NULL) cdf_FreeMemory (attrNs, FatalError);
2563   FreeIW (IW, FatalError);
2564   return;
2565 }
2566 
2567 /******************************************************************************
2568 * TextEditEntries.
2569 ******************************************************************************/
2570 
TextEditEntries(attrN)2571 Logical TextEditEntries (attrN)
2572 long attrN;		/* Attribute number being edited. */
2573 {
2574    AOSs1A (header,
2575 	   "Is your favorite editing key missing?  If so, contact CDFsupport.")
2576    AOSs1B (trailerBrowse, "Exit: ________   Help: ________")
2577    AOSs1C (trailerEdit, "Update: ________   Exit: ________   Help: ________")
2578    static int exitCharsBrowse[] = { EXITkey_FSI, HELPkey_FSI, NUL };
2579    static int exitCharsEdit[] = { UPDATEkey_EDIT, EXITkey_FSI, HELPkey_FSI };
2580    static char label[12+1+CDF_ATTR_NAME_LEN256+1+13+1];
2581    static struct EditWindowStruct EW = {
2582       label, 0, 0, 80, 1, header, NULL, 15, 1, NULL, TRUE, TRUE,
2583       NULL, REFRESHkey_FSI, NUL, NUL, NUL, NUL, NSkey_FSI, PSkey_FSI,
2584       NUL, NUL, INSERTorOVERkey_FSI
2585    };
2586    static Logical first = TRUE; Logical allCharacter;
2587    /***************************************************************************
2588    * First time...
2589    ***************************************************************************/
2590    if (first) {
2591        EncodeKeyDefinitions (1, trailerBrowse, EXITkey_FSI, HELPkey_FSI);
2592        EncodeKeyDefinitions (1, trailerEdit, UPDATEkey_EDIT, EXITkey_FSI,
2593 			     HELPkey_FSI);
2594      first = FALSE;
2595    }
2596      if (browseOnly) {
2597        EW.tLines = trailerBrowse;
2598        EW.exitChars = exitCharsBrowse;
2599        EW.readOnly = TRUE;
2600      }
2601      else {
2602        EW.tLines = trailerEdit;
2603        EW.exitChars = exitCharsEdit;
2604        EW.readOnly = FALSE;
2605      }
2606    /***************************************************************************
2607    * Build attribute/entry lines and display menu.
2608    ***************************************************************************/
2609    if (!BuildTextEditEntriesMenu(attrN,&EW,&allCharacter)) return FALSE;
2610    if (!allCharacter) {
2611      ProblemWindow ("Not all entries have a character data type.", FALSE);
2612      return TRUE;
2613    }
2614    EditWindow (NEWiw, &EW, TRUE);
2615    /***************************************************************************
2616    * Read/process keystrokes until request to exit menu.
2617    ***************************************************************************/
2618    for (;;) {
2619      EditWindow (READew, &EW);
2620      switch (EW.key) {
2621        case UPDATEkey_EDIT: {
2622 	 UpdateTextEditEntries (attrN, &EW);
2623 	 EditWindow (DELETEew, &EW);
2624 	 cdf_FreeMemory (EW.eText, FatalError);
2625 	 return (!NoMoreAccess(NULL));
2626        }
2627        /***********************************************************************
2628        * Display online help.
2629        ***********************************************************************/
2630        case HELPkey_FSI:
2631 	 OnlineHelpWindow (ilhFile, TEXTENTRIEShelpID);
2632 	 break;
2633        /***********************************************************************
2634        * Exit menu.
2635        ***********************************************************************/
2636        case EXITkey_FSI:
2637 	 EditWindow (DELETEew, &EW);
2638 	 cdf_FreeMemory (EW.eText, FatalError);
2639 	 return TRUE;
2640      }
2641    }
2642 }
2643 
2644 /******************************************************************************
2645 * BuildTextEditEntriesMenu.
2646 * Returns FALSE if a fatal error detected.
2647 ******************************************************************************/
2648 
BuildTextEditEntriesMenu(attrN,EW,allCharacter)2649 Logical BuildTextEditEntriesMenu (attrN, EW, allCharacter)
2650 long attrN;			/* gAttribute number. */
2651 struct EditWindowStruct *EW;	/* EditWindow structure pointer. */
2652 Logical *allCharacter;		/* All character data type entries? */
2653 {
2654   CDFstatus status; char *line, attrName[CDF_ATTR_NAME_LEN256+1]; int i;
2655   long totalChars = 0, maxEntry, entryN, dataType, numElems, totalBytes;
2656   /****************************************************************************
2657   * Encode label.
2658   ****************************************************************************/
2659   status = CDFlib (SELECT_, ATTR_, attrN,
2660 		   GET_, ATTR_NAME_, attrName,
2661 		   NULL_);
2662   if (!ReportStatus(status,FALSE)) return FALSE;
2663   sprintf (EW->label, " gAttribute \"%s\" TextEntries ", attrName);
2664   /****************************************************************************
2665   * Verify that all entries have a character data type and count the total
2666   * number of characters.
2667   ****************************************************************************/
2668   status = CDFlib (GET_, ATTR_MAXgENTRY_, &maxEntry,
2669 		   NULL_);
2670   if (!ReportStatus(status,FALSE)) return FALSE;
2671   for (entryN = 0; entryN <= maxEntry; entryN++) {
2672      status = CDFlib (SELECT_, gENTRY_, entryN,
2673 		      GET_, gENTRY_DATATYPE_, &dataType,
2674 			    gENTRY_NUMELEMS_, &numElems,
2675 		      NULL_);
2676      switch (status) {
2677        case NO_SUCH_ENTRY:
2678 	 break;
2679        default:
2680 	 if (!ReportStatus(status,FALSE)) return FALSE;
2681 	 if (!STRINGdataType(dataType)) {
2682 	   *allCharacter = FALSE;
2683 	   return TRUE;
2684 	 }
2685 	 totalChars += numElems;
2686 	 break;
2687      }
2688   }
2689   /****************************************************************************
2690   * Build text.
2691   ****************************************************************************/
2692   totalBytes = (maxEntry + 1) + totalChars + 1;
2693   EW->eText = (char *) cdf_AllocateMemory ((size_t) totalBytes, FatalError);
2694   MakeNUL (EW->eText);
2695   for (entryN = 0; entryN <= maxEntry; entryN++) {
2696      status = CDFlib (SELECT_, gENTRY_, entryN,
2697 		      GET_, gENTRY_NUMELEMS_, &numElems,
2698 		      NULL_);
2699      switch (status) {
2700        case NO_SUCH_ENTRY:
2701 	 strcatX (EW->eText, "\n", (size_t) totalBytes);
2702 	 break;
2703        default:
2704 	 if (!ReportStatus(status,FALSE)) return FALSE;
2705 	 line = (char *) cdf_AllocateMemory ((size_t) (numElems + 1),
2706 					 FatalError);
2707 	 status = CDFlib (GET_, gENTRY_DATA_, line,
2708 			  NULL_);
2709 	 if (!ReportStatus(status,FALSE)) return FALSE;
2710 	 for (i = 0; i < numElems; i++) {
2711 	    if (!Printable(line[i])) line[i] = '.';
2712 	 }
2713 	 line[(int)numElems] = NUL;
2714 	 strcatX (EW->eText, line, (size_t) totalBytes);
2715 	 strcatX (EW->eText, "\n", (size_t) totalBytes);
2716 	 cdf_FreeMemory (line, FatalError);
2717 	 break;
2718      }
2719   }
2720   *allCharacter = TRUE;
2721   return TRUE;
2722 }
2723 
2724 /******************************************************************************
2725 * UpdateTextEditEntries.
2726 ******************************************************************************/
2727 
UpdateTextEditEntries(attrN,EW)2728 Logical UpdateTextEditEntries (attrN, EW)
2729 long attrN;			/* gAttribute number. */
2730 struct EditWindowStruct *EW;	/* EditWindow structure pointer. */
2731 {
2732   CDFstatus status; long entryN, maxEntryN; char *ptr1, *ptr2; size_t length;
2733   /****************************************************************************
2734   * Select attribute.
2735   ****************************************************************************/
2736   status = CDFlib (SELECT_, ATTR_, attrN,
2737 		   NULL_);
2738   if (!ReportStatus(status,FALSE)) return FALSE;
2739   /****************************************************************************
2740   * Scan text...
2741   ****************************************************************************/
2742   entryN = NO_ENTRY;
2743   ptr1 = EW->eText;
2744   for (;;) {
2745      /*************************************************************************
2746      * Look for next newline character.
2747      *************************************************************************/
2748      ptr2 = strchr (ptr1, Nl);
2749      /*************************************************************************
2750      * If a newline character wasn't found, check if one or more characters
2751      * exist before the terminating NUL.  If not, we're done scanning the
2752      * text.
2753      *************************************************************************/
2754      if (ptr2 == NULL) {
2755        length = strlen (ptr1);
2756        if (length == 0) break;
2757        ptr2 = ptr1 + length;
2758      }
2759      else
2760        length = (size_t) (ptr2 - ptr1);
2761      /*************************************************************************
2762      * Rewrite or delete the entry depending on the length of this line of
2763      * text.
2764      *************************************************************************/
2765      entryN++;
2766      if (length > 0) {
2767        status = CDFlib (SELECT_, gENTRY_, entryN,
2768 			PUT_, gENTRY_DATA_, CDF_CHAR, (long) length, ptr1,
2769 			NULL_);
2770        if (!ReportStatus(status,FALSE)) return FALSE;
2771      }
2772      else {
2773        status = CDFlib (SELECT_, gENTRY_, entryN,
2774 			DELETE_, gENTRY_,
2775 			NULL_);
2776        switch (status) {
2777 	 case NO_SUCH_ENTRY:
2778 	   break;
2779 	 default:
2780 	   if (!ReportStatus(status,FALSE)) return FALSE;
2781 	   break;
2782        }
2783      }
2784      /*************************************************************************
2785      * If this line of text ended on the NUL, then we're done scanning the
2786      * text.  Otherwise, continue at the next character.
2787      *************************************************************************/
2788      if (*ptr2 == NUL) break;
2789      ptr1 = ptr2 + 1;
2790   }
2791   /****************************************************************************
2792   * Determine maximum gEntry number.
2793   ****************************************************************************/
2794   status = CDFlib (GET_, ATTR_MAXgENTRY_, &maxEntryN,
2795 		   NULL_);
2796   if (!ReportStatus(status,FALSE)) return FALSE;
2797   /****************************************************************************
2798   * Delete remaining entries.
2799   ****************************************************************************/
2800   entryN++;
2801   while (entryN <= maxEntryN) {
2802     status = CDFlib (SELECT_, gENTRY_, entryN,
2803 		     DELETE_, gENTRY_,
2804 		     NULL_);
2805     switch (status) {
2806       case NO_SUCH_ENTRY:
2807 	break;
2808       default:
2809 	if (!ReportStatus(status,FALSE)) return FALSE;
2810 	break;
2811     }
2812     entryN++;
2813   }
2814   return TRUE;
2815 }
2816 
2817 /******************************************************************************
2818 * EditAttrEntriesX.
2819 ******************************************************************************/
2820 
EditAttrEntriesX(G,attrN,nAttrs)2821 Logical EditAttrEntriesX (G, attrN, nAttrs)
2822 Logical G;	/* If TRUE, global scoped attribute. */
2823 long attrN;     /* Attribute number being edited. */
2824 long nAttrs;	/* Number of attributes with this scope. */
2825 {
2826    CDFstatus status;
2827    long entryN, fieldN, scope;
2828    AOSs2 (header, BLANKs78, BLANKs78)
2829    AOSs1 (trailerBrowse,
2830 	  "Select: ________   Exit: ________   Help: ________   Next attribute: ________")
2831    AOSs2A (trailerEdit,
2832 	  "Modify: ________   Create entry: ________   Delete entry:   ________",
2833 	  "Exit:   ________   Help:         ________   Next attribute: ________")
2834    static int exitCharsBrowse[] = {
2835      ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NEXTATTRkey_EDIT, NUL
2836    };
2837    static int exitCharsEdit[] = {
2838      ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, CREATEENTRYkey_EDIT,
2839      DELETEATTRorENTRYkey_EDIT, NEXTATTRkey_EDIT, NUL
2840    };
2841    static char label[12+1+CDF_ATTR_NAME_LEN256+1+9+1];
2842    static struct ItemWindowStruct IW = {
2843       0, 0, 80, label, 2, header, 0, NULL, 0, NULL, NULL, NULL, 0, 0, NULL,
2844       NULL, REFRESHkey_FSI, TRUE, NSkey_FSI, PSkey_FSI
2845    };
2846    long nEntries; long *entryNs; int *entryTypes, entryType;
2847    static Logical first = TRUE;
2848    /***************************************************************************
2849    * First time...
2850    ***************************************************************************/
2851    if (first) {
2852        EncodeKeyDefinitions (1, trailerBrowse, ENTERkey_FSI, EXITkey_FSI,
2853 			     HELPkey_FSI, NEXTATTRkey_EDIT);
2854        EncodeKeyDefinitions (2, trailerEdit, ENTERkey_FSI,
2855 			     CREATEENTRYkey_EDIT, DELETEATTRorENTRYkey_EDIT,
2856 			     EXITkey_FSI, HELPkey_FSI, NEXTATTRkey_EDIT);
2857      first = FALSE;
2858    }
2859      if (browseOnly) {
2860        IW.NiRows = 14;
2861        IW.NtLines = 1;
2862        IW.tLines = trailerBrowse;
2863        IW.exitChars = exitCharsBrowse;
2864      }
2865      else {
2866        IW.NiRows = 13;
2867        IW.NtLines = 2;
2868        IW.tLines = trailerEdit;
2869        IW.exitChars = exitCharsEdit;
2870      }
2871    /***************************************************************************
2872    * Build attribute/entry lines and display menu.
2873    ***************************************************************************/
2874    if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,
2875 			      &entryNs,&entryTypes,&IW)) return FALSE;
2876    ItemWindow (NEWiw, &IW, 0);
2877    /***************************************************************************
2878    * Read/process keystrokes until request to exit menu.
2879    ***************************************************************************/
2880    for (;;) {
2881      ItemWindow (READiw, &IW);
2882      /*********************************************************************
2883      * Calculate entry and field numbers and entry type.
2884      *********************************************************************/
2885      if (IW.nItems != 0) {
2886        fieldN = IW.itemN % 4;
2887        entryN = entryNs[IW.itemN/4];
2888        entryType = entryTypes[IW.itemN/4];
2889      }
2890      switch (IW.key) {
2891        /***********************************************************************
2892        * Item selected.
2893        ***********************************************************************/
2894        case ENTERkey_FSI: {
2895 	 /*********************************************************************
2896 	 * Check if any attributes/entries exist.
2897 	 *********************************************************************/
2898 	 if (IW.nItems == 0) {
2899 	   ProblemWindow (BOO(G,"Nothing selected (no gEntries exist).",
2900 			        "Nothing selected (no entries exist)."),FALSE);
2901 	   break;
2902 	 }
2903 	 /*********************************************************************
2904 	 * Perform desired function (based on field number).
2905 	 *********************************************************************/
2906 	 switch (fieldN) {
2907 	   /*******************************************************************
2908 	   * Modify variable name/global entry number.
2909 	   *******************************************************************/
2910 	   case 0: {
2911 	     if (G)
2912 	       ItemWindow (BEEPiw, &IW);
2913 	     else {
2914 	       char varName[CDF_VAR_NAME_LEN256+1]; long nVars;
2915 	       Logical Z = (entryType == zENTRYt);
2916 	       status = CDFlib (GET_, BOO(Z,CDF_NUMzVARS_,
2917 					    CDF_NUMrVARS_), &nVars,
2918 				NULL_);
2919 	       if (!ReportStatus(status,FALSE)) {
2920 		 ItemWindow (DELETEiw, &IW);
2921 		 return FALSE;
2922 	       }
2923 	       if (entryN >= nVars) {
2924 		 ProblemWindow (BOO(Z,"No corresponding zVariable.",
2925 				      "No corresponding rVariable."), FALSE);
2926 		 break;
2927 	       }
2928 	       status = CDFlib (SELECT_, VAR(Z), entryN,
2929 				GET_, VAR_NAME(Z), varName,
2930 				NULL_);
2931 	       if (!ReportStatus(status,FALSE)) {
2932 		 ItemWindow (DELETEiw, &IW);
2933 		 return FALSE;
2934 	       }
2935 	       if (browseOnly)
2936 		 ShowFullName (varName, FALSE);
2937 	       else {
2938 	         static char *header[] = {
2939 		   "Enter new name (with delimiters)...",
2940 		   "Syntax: <delim><char1><char2>...<charN><delim>",
2941 		   "Example: \"Humidity\""
2942 	         };
2943 	         AOSs1 (trailer,
2944 		        "Enter: ________   Exit: ________  Help: ________")
2945 	         static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI,
2946 					    HELPkey_FSI, NUL };
2947 	         static char value[1+CDF_VAR_NAME_LEN256+1+1];
2948 	         static char label[14+CDF_VAR_NAME_LEN256+1];
2949 	         static struct PromptWindowStruct PWt = {
2950 		    label, 4, 1, 78, 3, header, CDF_VAR_NAME_LEN256+2, value,
2951 		    1, trailer, exitChars, REFRESHkey_FSI, SOLkey_FSI,
2952 		    EOLkey_FSI, INSERTorOVERkey_FSI
2953 	         };
2954 	         char delim;
2955 	         EncodeKeyDefinitions (1, trailer, ENTERkey_FSI, EXITkey_FSI,
2956 				       HELPkey_FSI);
2957 	         delim = PickDelimiter (varName, strlen(varName));
2958 	         sprintf (value, "%c%s%c", delim, varName, delim);
2959 	         sprintf (label, " %cVariable %c%s%c ", BOO(Z,'z','r'),
2960 			  delim, varName, delim);
2961 	         PromptWindow (NEWpw, &PWt, (int) (strlen(PWt.value) - 1),
2962 			       LogicalTRUE);
2963 	         for (;;) {
2964 		    if (EnterPW(&PWt,VARRENAMEhelpID)) {
2965 		      char varName[CDF_VAR_NAME_LEN256+1];
2966 		      if (DecodeDelimitedString(PWt.value,varName)) {
2967 		        status = CDFlib (PUT_, VAR_NAME(Z), varName,
2968 				         NULL_);
2969 		        if (ReportStatus(status,FALSE)) {
2970 			  FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
2971 			  if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,
2972 						     &entryNs,&entryTypes,
2973 						     &IW)) {
2974 			    PromptWindow (DELETEpw, &PWt);
2975 			    ItemWindow (DELETEiw, &IW);
2976 			    return FALSE;
2977 			  }
2978 			  ItemWindow (UPDATEiw, &IW, IW.itemN);
2979 			  break;
2980 		        }
2981 			if (NoMoreAccess(NULL)) {
2982 			  PromptWindow (DELETEpw, &PWt);
2983 			  ItemWindow (DELETEiw, &IW);
2984 			  return FALSE;
2985 			}
2986 		      }
2987 		      else
2988 		        ProblemWindow ("Illegal name (check delimiters).",
2989 				       FALSE);
2990 		    }
2991 		    else
2992 		      break;
2993 	         }
2994 	         PromptWindow (DELETEpw, &PWt);
2995 	       }
2996 	     }
2997 	     break;
2998 	   }
2999 	   /*******************************************************************
3000 	   * Modify data specification.
3001 	   *******************************************************************/
3002 	   case 1: {
3003 	     if (browseOnly)
3004 	       ItemWindow (BEEPiw, &IW);
3005 	     else {
3006 	       long dataType, numElems;
3007 	       static char label[15+CDF_VAR_NAME_LEN256+1];
3008 	       if (G)
3009 	         sprintf (label, " gEntry %ld ", entryN + 1);
3010 	       else {
3011 	         Logical Z = (entryType == zENTRYt);
3012 	         char varName[CDF_VAR_NAME_LEN256+1], delim;
3013 	         status = CDFlib (SELECT_, VAR(Z), entryN,
3014 				  GET_, VAR_NAME(Z), varName,
3015 				  NULL_);
3016 	         switch (status) {
3017 		   case NO_SUCH_VAR:
3018 		     sprintf (label," %cEntry %ld ",BOO(Z,'z','r'),entryN + 1);
3019 		     break;
3020 		   default:
3021 		     if (!ReportStatus(status,FALSE)) {
3022 		       ItemWindow (DELETEiw, &IW);
3023 		       return FALSE;
3024 		     }
3025 		     delim = PickDelimiter (varName, strlen(varName));
3026 		     sprintf (label, " %cEntry for %c%s%c ", BOO(Z,'z','r'),
3027 			      delim, varName, delim);
3028 		     break;
3029 	         }
3030 	       }
3031 	       status = CDFlib (SELECT_, ATTR_, attrN,
3032 				         ENTRY(entryType), entryN,
3033 			        GET_, ENTRY_DATATYPE(entryType), &dataType,
3034 				      ENTRY_NUMELEMS(entryType), &numElems,
3035 			        NULL_);
3036 	       if (!ReportStatus(status,FALSE)) {
3037 		 ItemWindow (DELETEiw, &IW);
3038 		 return FALSE;
3039 	       }
3040 	       if (SelectDataSpec(&dataType,NULL,label)) {
3041 		 status = CDFlib (PUT_, ENTRY_DATASPEC(entryType), dataType,
3042 								   numElems,
3043 				  NULL_);
3044 		 if (ReportStatus(status,FALSE)) {
3045 		   FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
3046 		   if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,&entryNs,
3047 					      &entryTypes,&IW)) {
3048 		     ItemWindow (DELETEiw, &IW);
3049 		     return FALSE;
3050 		   }
3051 		   ItemWindow (UPDATEiw, &IW, IW.itemN);
3052 		 }
3053 		 else {
3054 		   if (NoMoreAccess(NULL)) {
3055 		     ItemWindow (DELETEiw, &IW);
3056 		     return FALSE;
3057 		   }
3058 		 }
3059 	       }
3060 	     }
3061 	     break;
3062 	   }
3063 	   /*******************************************************************
3064 	   * Modify data specification/value(s).
3065 	   *******************************************************************/
3066 	   case 2: {
3067 	     if (browseOnly)
3068 	       ItemWindow (BEEPiw, &IW);
3069 	     else {
3070 	       Logical changed = FALSE;
3071 	       if (!EditEntry(attrN,entryN,entryType,TRUE,&changed)) {
3072 		 ItemWindow (DELETEiw, &IW);
3073 		 return FALSE;
3074 	       }
3075 	       if (changed) {
3076 	         FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
3077 	         if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,
3078 					    &entryNs,&entryTypes,&IW)) {
3079 		   ItemWindow (DELETEiw, &IW);
3080 		   return FALSE;
3081 		 }
3082 	         ItemWindow (UPDATEiw, &IW, IW.itemN);
3083 	       }
3084 	     }
3085 	     break;
3086 	   }
3087 	   /*******************************************************************
3088 	   * Modify value(s).
3089 	   *******************************************************************/
3090 	   case 3: {
3091 	     Logical changed = FALSE;
3092 	     if (!EditEntry(attrN,entryN,entryType,FALSE,&changed)) {
3093 	       ItemWindow (DELETEiw, &IW);
3094 	       return FALSE;
3095 	     }
3096 	     if (changed) {
3097 	       FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
3098 	       if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,
3099 					  &entryNs,&entryTypes,&IW)) {
3100 		 ItemWindow (DELETEiw, &IW);
3101 		 return FALSE;
3102 	       }
3103 	       ItemWindow (UPDATEiw, &IW, IW.itemN);
3104 	     }
3105 	     break;
3106 	   }
3107 	 }
3108 	 break;
3109        }
3110        /***********************************************************************
3111        * Create new entry.
3112        ***********************************************************************/
3113        case CREATEENTRYkey_EDIT: {
3114 	 Logical changed = FALSE;
3115 	 if (!CreateEntry(G,attrN,&changed)) {
3116 	   ItemWindow (DELETEiw, &IW);
3117 	   return FALSE;
3118 	 }
3119 	 if (changed) {
3120 	   FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
3121 	   if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,
3122 				      &entryNs,&entryTypes,&IW)) {
3123 	     ItemWindow (DELETEiw, &IW);
3124 	     return FALSE;
3125 	   }
3126 	   ItemWindow (UPDATEiw, &IW, 0);
3127 	 }
3128 	 break;
3129        }
3130        /***********************************************************************
3131        * Delete attribute/entry.
3132        ***********************************************************************/
3133        case DELETEATTRorENTRYkey_EDIT: {
3134 	 char attrName[CDF_ATTR_NAME_LEN256+1], delim,
3135 	      question1[40+ENTRYNUM_FIELD_LEN+CDF_ATTR_NAME_LEN256+1],
3136 	      question2[31+CDF_VAR_NAME_LEN256+1];
3137 	 if (IW.nItems == 0) {
3138 	   ProblemWindow (BOO(G,"A gEntry isn't selected (none exist).",
3139 			        "An entry isn't selected (none exist)."),
3140 			  FALSE);
3141 	   break;
3142 	 }
3143 	 status = CDFlib (SELECT_, ATTR_, attrN,
3144 			  GET_, ATTR_NAME_, attrName,
3145 			  NULL_);
3146 	 if (!ReportStatus(status,FALSE)) {
3147 	   ItemWindow (DELETEiw, &IW);
3148 	   return FALSE;
3149 	 }
3150 	 delim = PickDelimiter (attrName, strlen(attrName));
3151 	 if (entryType == gENTRYt) {
3152 	   sprintf (question1,
3153 		    "Delete gEntry number %ld of gAttribute %c%s%c ?",
3154 		    entryN + 1, delim, attrName, delim);
3155 	   question2[0] = NUL;
3156 	 }
3157 	 else {
3158 	   char varName[CDF_VAR_NAME_LEN256+1], attrName[CDF_ATTR_NAME_LEN256+1];
3159 	   status = CDFlib (SELECT_, ATTR_, attrN,
3160 			    GET_, ATTR_NAME_, attrName,
3161 			    SELECT_, BOO(entryType == zENTRYt,zVAR_,
3162 							      rVAR_), entryN,
3163 			    GET_, BOO(entryType == zENTRYt,
3164 				      zVAR_NAME_,rVAR_NAME_), varName,
3165 			    NULL_);
3166 	   switch (status) {
3167 	     case NO_SUCH_VAR:
3168 	       sprintf (question1,
3169 			"Delete %sEntry number %ld of vAttribute %c%s%c ?",
3170 			BOO(entryType==zENTRYt,"z","r"), entryN + 1, delim,
3171 			attrName, delim);
3172 	       question2[0] = NUL;
3173 	       break;
3174 	     default:
3175 	       if (!ReportStatus(status,FALSE)) {
3176 		 ItemWindow (DELETEiw, &IW);
3177 		 return FALSE;
3178 	       }
3179 	       delim = PickDelimiter (attrName, strlen(attrName));
3180 	       sprintf (question1, "Delete %sEntry of vAttribute %c%s%c",
3181 			BOO(entryType==zENTRYt,"z","r"), delim, attrName,
3182 			delim);
3183 	       delim = PickDelimiter (varName, strlen(varName));
3184 	       sprintf (question2, "corresponding to %sVariable %c%s%c ?",
3185 			BOO(entryType==zENTRYt,"z","r"), delim, varName,delim);
3186 	       break;
3187 	   }
3188 	 }
3189 	 if (ConfirmWindow(4,78,question1,
3190 			   BOO(NULstring(question2),NULL,question2),
3191 			   FALSE,DELETEENTRYhelpID)) {
3192 	   status = CDFlib (SELECT_, ENTRY(entryType), entryN,
3193 			    DELETE_, ENTRY(entryType),
3194 			    NULL_);
3195 	   if (ReportStatus(status,FALSE)) {
3196 	     int itemNt = IW.itemN - (IW.itemN % 4);
3197 	     FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
3198 	     if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,
3199 					&entryNs,&entryTypes,&IW)) {
3200 	       ItemWindow (DELETEiw, &IW);
3201 	       return FALSE;
3202 	     }
3203 	     if (itemNt == IW.nItems) itemNt = MaxInt (0, itemNt - 4);
3204 	     ItemWindow (UPDATEiw, &IW, itemNt);
3205 	   }
3206 	   else {
3207 	     if (NoMoreAccess(NULL)) {
3208 	       ItemWindow (DELETEiw, &IW);
3209 	       return FALSE;
3210 	     }
3211 	   }
3212 	 }
3213 	 break;
3214        }
3215        /***********************************************************************
3216        * Next attribute (of the same scope).
3217        ***********************************************************************/
3218        case NEXTATTRkey_EDIT:
3219 	 for (;;) {
3220 	    attrN = (attrN + 1) % nAttrs;
3221 	    status = CDFlib (SELECT_, ATTR_, attrN,
3222 			     GET_, ATTR_SCOPE_, &scope,
3223 			     NULL_);
3224 	    if (!ReportStatus(status,FALSE)) {
3225 	      ItemWindow (DELETEiw, &IW);
3226 	      return FALSE;
3227 	    }
3228 	    if ((G && scope == GLOBAL_SCOPE) ||
3229 		(!G && scope == VARIABLE_SCOPE)) break;
3230 	 }
3231 	 FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
3232 	 if (!BuildAttrEntriesMenuX(G,attrN,&nEntries,
3233 				    &entryNs,&entryTypes,&IW)) {
3234 	   ItemWindow (DELETEiw, &IW);
3235 	   return FALSE;
3236 	 }
3237 	 ItemWindow (UPDATEiw, &IW, 0);
3238 	 break;
3239        /***********************************************************************
3240        * Display online help.
3241        ***********************************************************************/
3242        case HELPkey_FSI:
3243 	 OnlineHelpWindow (ilhFile, BOO(G,GATTRENTRIEShelpIDx,
3244 					  VATTRENTRIEShelpIDx));
3245 	 break;
3246        /***********************************************************************
3247        * Exit menu.
3248        ***********************************************************************/
3249        case EXITkey_FSI:
3250 	 ItemWindow (DELETEiw, &IW);
3251 	 FreeAttrEntriesMenuX (entryNs, entryTypes, &IW);
3252 	 return TRUE;
3253      }
3254    }
3255 }
3256 
3257 /******************************************************************************
3258 * BuildAttrEntriesMenuX.
3259 ******************************************************************************/
3260 
BuildAttrEntriesMenuX(G,attrN,nEntries,entryNs,entryTypes,IW)3261 Logical BuildAttrEntriesMenuX (G, attrN, nEntries, entryNs, entryTypes, IW)
3262 Logical G;
3263 long attrN;
3264 long *nEntries;
3265 long **entryNs;
3266 int **entryTypes;
3267 struct ItemWindowStruct *IW;
3268 {
3269    CDFstatus status; void *binary;
3270    long dataType, numElems, entryN, NgEntries, NrEntries, NzEntries;
3271    char field[80+1], attrName[CDF_ATTR_NAME_LEN256+1];
3272    int entryX, curCol, n, dataSpecCol, entryType, itemN;
3273    AOSs2 (loadingLines, "Loading menu...", "")
3274    /***************************************************************************
3275    * Make attribute current and get name.
3276    ***************************************************************************/
3277    status = CDFlib (SELECT_, ATTR_, attrN,
3278 		    GET_, ATTR_NAME_, attrName,
3279 		    NULL_);
3280    if (!ReportStatus(status,FALSE)) return FALSE;
3281    /***************************************************************************
3282    * Determine number of entries.
3283    ***************************************************************************/
3284    if (G) {
3285      status = CDFlib (GET_, ATTR_NUMgENTRIES_, &NgEntries,
3286 		      NULL_);
3287      if (!ReportStatus(status,FALSE)) return FALSE;
3288      *nEntries = NgEntries;
3289    }
3290    else {
3291      status = CDFlib (GET_, ATTR_NUMrENTRIES_, &NrEntries,
3292 		      ATTR_NUMzENTRIES_, &NzEntries,
3293 		      NULL_);
3294      if (!ReportStatus(status,FALSE)) return FALSE;
3295      *nEntries = NrEntries + NzEntries;
3296    }
3297    if (*nEntries > MANY_ENTRYs) MessageWindow (loadingLines,NULL,LogicalFALSE);
3298    *entryNs = (long *) cdf_AllocateMemory ((size_t) ((*nEntries) * sizeof(long)),
3299 				       FatalError);
3300    *entryTypes = (int *) cdf_AllocateMemory ((size_t) ((*nEntries) * sizeof(int)),
3301 					 FatalError);
3302    if (G) {
3303      for (entryN = 0, entryX = 0; entryX < NgEntries; entryN++) {
3304 	status = CDFlib (SELECT_, gENTRY_, entryN,
3305 			 CONFIRM_, CURgENTRY_EXISTENCE_,
3306 			 NULL_);
3307 	switch (status) {
3308 	  case NO_SUCH_ENTRY:
3309 	    break;
3310 	  default:
3311 	    if (!ReportStatus(status,FALSE)) return FALSE;
3312 	    (*entryNs)[entryX] = entryN;
3313 	    (*entryTypes)[entryX] = gENTRYt;
3314 	    entryX++;
3315 	    break;
3316 	}
3317      }
3318    }
3319    else {
3320      for (entryN = 0, entryX = 0; entryX < NrEntries; entryN++) {
3321 	status = CDFlib (SELECT_, rENTRY_, entryN,
3322 			 CONFIRM_, CURrENTRY_EXISTENCE_,
3323 			 NULL_);
3324 	switch (status) {
3325 	  case NO_SUCH_ENTRY:
3326 	    break;
3327 	  default:
3328 	    if (!ReportStatus(status,FALSE)) return FALSE;
3329 	    (*entryNs)[entryX] = entryN;
3330 	    (*entryTypes)[entryX] = rENTRYt;
3331 	    entryX++;
3332 	    break;
3333 	}
3334      }
3335      for (entryN = 0; entryX < *nEntries; entryN++) {
3336 	status = CDFlib (SELECT_, zENTRY_, entryN,
3337 			 CONFIRM_, CURzENTRY_EXISTENCE_,
3338 			 NULL_);
3339 	switch (status) {
3340 	  case NO_SUCH_ENTRY:
3341 	    break;
3342 	  default:
3343 	    if (!ReportStatus(status,FALSE)) return FALSE;
3344 	    (*entryNs)[entryX] = entryN;
3345 	    (*entryTypes)[entryX] = zENTRYt;
3346 	    entryX++;
3347 	    break;
3348 	}
3349      }
3350    }
3351    /***************************************************************************
3352    * Allocate item section control/lines.
3353    ***************************************************************************/
3354    AllocIW (IW, (int) (4 * (*nEntries)), (int) *nEntries, 80, FatalError);
3355    /***************************************************************************
3356    * Encode label/header.
3357    ***************************************************************************/
3358    sprintf (IW->label," %cAttribute \"%s\" Entries ",BOO(G,'g','v'),attrName);
3359    if (G) {
3360      sprintf (IW->hLines[0], "%ld gEntr%s",
3361 	      NgEntries, BOO(NgEntries == 1,"y","ies"));
3362      strcpyX (IW->hLines[1],
3363 	      "Entry  DataSpec  Value(s)", 0);
3364    }
3365    else {
3366      sprintf (IW->hLines[0], "%ld rEntr%s, %ld zEntr%s",
3367 	      NrEntries, BOO(NrEntries == 1,"y","ies"),
3368 	      NzEntries, BOO(NzEntries == 1,"y","ies"));
3369      strcpyX (IW->hLines[1],
3370 	      "VarName          DataSpec  Value(s)", 0);
3371    }
3372    /***************************************************************************
3373    * Build each attribute/entry line.
3374    ***************************************************************************/
3375    for (entryX = 0, curCol = 0; entryX < *nEntries; entryX++, curCol = 0) {
3376       entryType = (*entryTypes)[entryX];
3377       status = CDFlib (SELECT_, ENTRY(entryType), (*entryNs)[entryX],
3378 		       GET_, ENTRY_DATATYPE(entryType), &dataType,
3379 			     ENTRY_NUMELEMS(entryType), &numElems,
3380 		       NULL_);
3381       if (!ReportStatus(status,FALSE)) return FALSE;
3382       /*******************************************************************
3383       * Setup entry number field if global scope, variable name if
3384       * variable scope.
3385       *******************************************************************/
3386       if (G) {
3387 	sprintf (field, "%ld", (*entryNs)[entryX] + 1);
3388 	if (strlen(field) > (size_t) ENTRYNUM_FIELD_LENx) {
3389 	  strcpyX (field + ENTRYNUM_FIELD_LENx - 3, "...", 0);
3390 	}
3391       }
3392       else {
3393 	char varName[CDF_VAR_NAME_LEN256+1];
3394 	status = CDFlib (SELECT_, E3(entryType,
3395 				     0,rVAR_,zVAR_), (*entryNs)[entryX],
3396 			 GET_, E3(entryType,0,rVAR_NAME_,zVAR_NAME_), varName,
3397 			 NULL_);
3398 	switch (status) {
3399 	  case NO_SUCH_VAR: {
3400 	     Logical Z = E3(entryType,FALSE,FALSE,TRUE);
3401 	     sprintf (field, "<%sEntry.%ld>",
3402 		      BOO(Z,"z","r"), (*entryNs)[entryX] + 1);
3403 	     break;
3404 	  }
3405 	  default:
3406 	    if (!ReportStatus(status,FALSE)) return FALSE;
3407 	    EncodeString (strlen(varName), varName, field, 0,
3408 			  VARNAME_FIELD_LENx);
3409 	    break;
3410 	}
3411       }
3412       strcpyX (IW->iLines[entryX], field, 0);
3413       if (strlen(field) < (size_t) BOO(G,ENTRYNUM_FIELD_LENx,
3414 					 VARNAME_FIELD_LENx)) {
3415 	CatNcharacters (IW->iLines[entryX],
3416 			BOO(G,ENTRYNUM_FIELD_LENx,
3417 			      VARNAME_FIELD_LENx) - strlen(field), (int) ' ');
3418       }
3419       CatNcharacters (IW->iLines[entryX],
3420 		      BOO(G,ENTRYNUM_FIELD_BLANKSx,VARNAME_FIELD_BLANKSx),
3421 		      (int) ' ');
3422       itemN = 4 * entryX;
3423       IW->iLineNs[itemN] = entryX;
3424       IW->iCols[itemN] = curCol;
3425       IW->iLens[itemN] = strlen(field);
3426       curCol += BOO(G,ENTRYNUM_FIELD_LENx,VARNAME_FIELD_LENx) +
3427 		BOO(G,ENTRYNUM_FIELD_BLANKSx,VARNAME_FIELD_BLANKSx);
3428       /*******************************************************************
3429       * Setup data type & number of elements.
3430       *******************************************************************/
3431       strcpyX (field, DataTypeToken(dataType), 0);
3432       catchrX (field, (int) '/', 0);
3433       sprintf (&field[strlen(field)], "%ld", numElems);
3434       if (strlen(field) > (size_t) DATASPEC_FIELD_LENx) {
3435 	strcpyX (field + DATASPEC_FIELD_LENx - 3, "...", 0);
3436       }
3437       strcatX (IW->iLines[entryX], field, 0);
3438       if (strlen(field) < (size_t) DATASPEC_FIELD_LENx) {
3439 	CatNcharacters (IW->iLines[entryX],
3440 			DATASPEC_FIELD_LENx - strlen(field), (int) ' ');
3441       }
3442       CatNcharacters (IW->iLines[entryX], DATASPEC_FIELD_BLANKSx, (int) ' ');
3443       itemN = (4 * entryX) + 1;
3444       IW->iLineNs[itemN] = entryX;
3445       IW->iCols[itemN] = curCol;
3446       IW->iLens[itemN] = strlen(field);
3447       dataSpecCol = curCol;
3448       curCol += DATASPEC_FIELD_LENx + DATASPEC_FIELD_BLANKSx;
3449       /*******************************************************************
3450       * Setup value(s) field.
3451       *******************************************************************/
3452       binary = cdf_AllocateMemory ((size_t) (numElems * CDFelemSize(dataType)),
3453 			       FatalError);
3454       status = CDFlib (GET_, ENTRY_DATA(entryType), binary,
3455 		       NULL_);
3456       if (!ReportStatus(status,FALSE)) return FALSE;
3457       n = EncodeValuesFormat (dataType, numElems, binary,
3458 			      &(IW->iLines[entryX][curCol]), NULL, 0,
3459 			      BOO(G,gAttrENTRYVALUE_FIELD_LENx,
3460 				    vAttrENTRYVALUE_FIELD_LENx),
3461 			      EPOCH0_STYLE);
3462       cdf_FreeMemory (binary, FatalError);
3463       /*******************************************************************
3464       * Set 'dataSpec/value' item control information.
3465       *******************************************************************/
3466       itemN = (4 * entryX) + 2;
3467       IW->iLineNs[itemN] = entryX;
3468       IW->iCols[itemN] = dataSpecCol;
3469       IW->iLens[itemN] = strlen(&(IW->iLines[entryX][dataSpecCol]));
3470       /*******************************************************************
3471       * Set `value' item control information.
3472       *******************************************************************/
3473       itemN = (4 * entryX) + 3;
3474       IW->iLineNs[itemN] = entryX;
3475       IW->iCols[itemN] = curCol;
3476       IW->iLens[itemN] = n;
3477    }
3478    if (*nEntries > MANY_ENTRYs) MessageWindow (NULL);
3479    return TRUE;
3480 }
3481 
3482 /******************************************************************************
3483 * FreeAttrEntriesMenuX.
3484 ******************************************************************************/
3485 
FreeAttrEntriesMenuX(entryNs,entryTypes,IW)3486 void FreeAttrEntriesMenuX (entryNs, entryTypes, IW)
3487 long *entryNs;
3488 int *entryTypes;
3489 struct ItemWindowStruct *IW;
3490 {
3491   FreeIW (IW, FatalError);
3492   if (entryTypes != NULL) cdf_FreeMemory (entryTypes, FatalError);
3493   if (entryNs != NULL) cdf_FreeMemory (entryNs, FatalError);
3494   return;
3495 }
3496