1 /*  This file, modkey.c, contains routines that modify, insert, or update  */
2 /*  keywords in a FITS header.                                             */
3 
4 /*  The FITSIO software was written by William Pence at the High Energy    */
5 /*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
6 /*  Goddard Space Flight Center.                                           */
7 
8 #include <string.h>
9 /* stddef.h is apparently needed to define size_t */
10 #include <ctype.h>
11 #include <stddef.h>
12 #include <stdlib.h>
13 #include "fitsio2.h"
14 /*--------------------------------------------------------------------------*/
ffuky(fitsfile * fptr,int datatype,const char * keyname,void * value,const char * comm,int * status)15 int ffuky( fitsfile *fptr,     /* I - FITS file pointer        */
16            int  datatype,      /* I - datatype of the value    */
17            const char *keyname,/* I - name of keyword to write */
18            void *value,        /* I - keyword value            */
19            const char *comm,   /* I - keyword comment          */
20            int  *status)       /* IO - error status            */
21 /*
22   Update the keyword, value and comment in the FITS header.
23   The datatype is specified by the 2nd argument.
24 */
25 {
26     if (*status > 0)           /* inherit input status value if > 0 */
27         return(*status);
28 
29     if (datatype == TSTRING)
30     {
31         ffukys(fptr, keyname, (char *) value, comm, status);
32     }
33     else if (datatype == TBYTE)
34     {
35         ffukyj(fptr, keyname, (LONGLONG) *(unsigned char *) value, comm, status);
36     }
37     else if (datatype == TSBYTE)
38     {
39         ffukyj(fptr, keyname, (LONGLONG) *(signed char *) value, comm, status);
40     }
41     else if (datatype == TUSHORT)
42     {
43         ffukyj(fptr, keyname, (LONGLONG) *(unsigned short *) value, comm, status);
44     }
45     else if (datatype == TSHORT)
46     {
47         ffukyj(fptr, keyname, (LONGLONG) *(short *) value, comm, status);
48     }
49     else if (datatype == TINT)
50     {
51         ffukyj(fptr, keyname, (LONGLONG) *(int *) value, comm, status);
52     }
53     else if (datatype == TUINT)
54     {
55         ffukyg(fptr, keyname, (double) *(unsigned int *) value, 0,
56                comm, status);
57     }
58     else if (datatype == TLOGICAL)
59     {
60         ffukyl(fptr, keyname, *(int *) value, comm, status);
61     }
62     else if (datatype == TULONG)
63     {
64         ffukyg(fptr, keyname, (double) *(unsigned long *) value, 0,
65                comm, status);
66     }
67     else if (datatype == TLONG)
68     {
69         ffukyj(fptr, keyname, (LONGLONG) *(long *) value, comm, status);
70     }
71     else if (datatype == TLONGLONG)
72     {
73         ffukyj(fptr, keyname, *(LONGLONG *) value, comm, status);
74     }
75     else if (datatype == TFLOAT)
76     {
77         ffukye(fptr, keyname, *(float *) value, -7, comm, status);
78     }
79     else if (datatype == TDOUBLE)
80     {
81         ffukyd(fptr, keyname, *(double *) value, -15, comm, status);
82     }
83     else if (datatype == TCOMPLEX)
84     {
85         ffukyc(fptr, keyname, (float *) value, -7, comm, status);
86     }
87     else if (datatype == TDBLCOMPLEX)
88     {
89         ffukym(fptr, keyname, (double *) value, -15, comm, status);
90     }
91     else
92         *status = BAD_DATATYPE;
93 
94     return(*status);
95 }
96 /*--------------------------------------------------------------------------*/
ffukyu(fitsfile * fptr,const char * keyname,const char * comm,int * status)97 int ffukyu(fitsfile *fptr,      /* I - FITS file pointer  */
98            const char *keyname, /* I - keyword name       */
99            const char *comm,    /* I - keyword comment    */
100            int *status)         /* IO - error status      */
101 {
102     int tstatus;
103 
104     if (*status > 0)           /* inherit input status value if > 0 */
105         return(*status);
106 
107     tstatus = *status;
108 
109     if (ffmkyu(fptr, keyname, comm, status) == KEY_NO_EXIST)
110     {
111         *status = tstatus;
112         ffpkyu(fptr, keyname, comm, status);
113     }
114     return(*status);
115 }
116 /*--------------------------------------------------------------------------*/
ffukys(fitsfile * fptr,const char * keyname,const char * value,const char * comm,int * status)117 int ffukys(fitsfile *fptr,       /* I - FITS file pointer  */
118            const char *keyname,  /* I - keyword name       */
119            const char *value,    /* I - keyword value      */
120            const char *comm,     /* I - keyword comment    */
121            int *status)          /* IO - error status      */
122 {
123     int tstatus;
124 
125     if (*status > 0)           /* inherit input status value if > 0 */
126         return(*status);
127 
128     tstatus = *status;
129 
130     if (ffmkys(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
131     {
132         *status = tstatus;
133         ffpkys(fptr, keyname, value, comm, status);
134     }
135     return(*status);
136 }
137 /*--------------------------------------------------------------------------*/
ffukls(fitsfile * fptr,const char * keyname,const char * value,const char * comm,int * status)138 int ffukls(fitsfile *fptr,      /* I - FITS file pointer  */
139            const char *keyname, /* I - keyword name       */
140            const char *value,   /* I - keyword value      */
141            const char *comm,    /* I - keyword comment    */
142            int *status)         /* IO - error status      */
143 {
144     /* update a long string keyword */
145 
146     int tstatus;
147     char junk[FLEN_ERRMSG];
148 
149     if (*status > 0)           /* inherit input status value if > 0 */
150         return(*status);
151 
152     tstatus = *status;
153 
154     if (ffmkls(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
155     {
156         /* since the ffmkls call failed, it wrote a bogus error message */
157         fits_read_errmsg(junk);  /* clear the error message */
158 
159         *status = tstatus;
160         ffpkls(fptr, keyname, value, comm, status);
161     }
162     return(*status);
163 }/*--------------------------------------------------------------------------*/
ffukyl(fitsfile * fptr,const char * keyname,int value,const char * comm,int * status)164 int ffukyl(fitsfile *fptr,     /* I - FITS file pointer  */
165            const char *keyname,/* I - keyword name       */
166            int value,          /* I - keyword value      */
167            const char *comm,   /* I - keyword comment    */
168            int *status)        /* IO - error status      */
169 {
170     int tstatus;
171 
172     if (*status > 0)           /* inherit input status value if > 0 */
173         return(*status);
174 
175     tstatus = *status;
176 
177     if (ffmkyl(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
178     {
179         *status = tstatus;
180         ffpkyl(fptr, keyname, value, comm, status);
181     }
182     return(*status);
183 }
184 /*--------------------------------------------------------------------------*/
ffukyj(fitsfile * fptr,const char * keyname,LONGLONG value,const char * comm,int * status)185 int ffukyj(fitsfile *fptr,     /* I - FITS file pointer  */
186            const char *keyname,/* I - keyword name       */
187            LONGLONG value,     /* I - keyword value      */
188            const char *comm,   /* I - keyword comment    */
189            int *status)        /* IO - error status      */
190 {
191     int tstatus;
192 
193     if (*status > 0)           /* inherit input status value if > 0 */
194         return(*status);
195 
196     tstatus = *status;
197 
198     if (ffmkyj(fptr, keyname, value, comm, status) == KEY_NO_EXIST)
199     {
200         *status = tstatus;
201         ffpkyj(fptr, keyname, value, comm, status);
202     }
203     return(*status);
204 }
205 /*--------------------------------------------------------------------------*/
ffukyf(fitsfile * fptr,const char * keyname,float value,int decim,const char * comm,int * status)206 int ffukyf(fitsfile *fptr,     /* I - FITS file pointer  */
207            const char *keyname,/* I - keyword name       */
208            float value,        /* I - keyword value      */
209            int decim,          /* I - no of decimals     */
210            const char *comm,   /* I - keyword comment    */
211            int *status)        /* IO - error status      */
212 {
213     int tstatus;
214 
215     if (*status > 0)           /* inherit input status value if > 0 */
216         return(*status);
217 
218     tstatus = *status;
219 
220     if (ffmkyf(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
221     {
222         *status = tstatus;
223         ffpkyf(fptr, keyname, value, decim, comm, status);
224     }
225     return(*status);
226 }
227 /*--------------------------------------------------------------------------*/
ffukye(fitsfile * fptr,const char * keyname,float value,int decim,const char * comm,int * status)228 int ffukye(fitsfile *fptr,     /* I - FITS file pointer  */
229            const char *keyname,/* I - keyword name       */
230            float value,        /* I - keyword value      */
231            int decim,          /* I - no of decimals     */
232            const char *comm,   /* I - keyword comment    */
233            int *status)        /* IO - error status      */
234 {
235     int tstatus;
236 
237     if (*status > 0)           /* inherit input status value if > 0 */
238         return(*status);
239 
240     tstatus = *status;
241 
242     if (ffmkye(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
243     {
244         *status = tstatus;
245         ffpkye(fptr, keyname, value, decim, comm, status);
246     }
247     return(*status);
248 }
249 /*--------------------------------------------------------------------------*/
ffukyg(fitsfile * fptr,const char * keyname,double value,int decim,const char * comm,int * status)250 int ffukyg(fitsfile *fptr,     /* I - FITS file pointer  */
251            const char *keyname,/* I - keyword name       */
252            double value,       /* I - keyword value      */
253            int decim,          /* I - no of decimals     */
254            const char *comm,   /* I - keyword comment    */
255            int *status)        /* IO - error status      */
256 {
257     int tstatus;
258 
259     if (*status > 0)           /* inherit input status value if > 0 */
260         return(*status);
261 
262     tstatus = *status;
263 
264     if (ffmkyg(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
265     {
266         *status = tstatus;
267         ffpkyg(fptr, keyname, value, decim, comm, status);
268     }
269     return(*status);
270 }
271 /*--------------------------------------------------------------------------*/
ffukyd(fitsfile * fptr,const char * keyname,double value,int decim,const char * comm,int * status)272 int ffukyd(fitsfile *fptr,     /* I - FITS file pointer  */
273            const char *keyname,/* I - keyword name       */
274            double value,       /* I - keyword value      */
275            int decim,          /* I - no of decimals     */
276            const char *comm,   /* I - keyword comment    */
277            int *status)        /* IO - error status      */
278 {
279     int tstatus;
280 
281     if (*status > 0)           /* inherit input status value if > 0 */
282         return(*status);
283 
284     tstatus = *status;
285 
286     if (ffmkyd(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
287     {
288         *status = tstatus;
289         ffpkyd(fptr, keyname, value, decim, comm, status);
290     }
291     return(*status);
292 }
293 /*--------------------------------------------------------------------------*/
ffukfc(fitsfile * fptr,const char * keyname,float * value,int decim,const char * comm,int * status)294 int ffukfc(fitsfile *fptr,     /* I - FITS file pointer  */
295            const char *keyname,/* I - keyword name       */
296            float *value,       /* I - keyword value      */
297            int decim,          /* I - no of decimals     */
298            const char *comm,   /* I - keyword comment    */
299            int *status)        /* IO - error status      */
300 {
301     int tstatus;
302 
303     if (*status > 0)           /* inherit input status value if > 0 */
304         return(*status);
305 
306     tstatus = *status;
307 
308     if (ffmkfc(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
309     {
310         *status = tstatus;
311         ffpkfc(fptr, keyname, value, decim, comm, status);
312     }
313     return(*status);
314 }
315 /*--------------------------------------------------------------------------*/
ffukyc(fitsfile * fptr,const char * keyname,float * value,int decim,const char * comm,int * status)316 int ffukyc(fitsfile *fptr,     /* I - FITS file pointer  */
317            const char *keyname,/* I - keyword name       */
318            float *value,       /* I - keyword value      */
319            int decim,          /* I - no of decimals     */
320            const char *comm,   /* I - keyword comment    */
321            int *status)        /* IO - error status      */
322 {
323     int tstatus;
324 
325     if (*status > 0)           /* inherit input status value if > 0 */
326         return(*status);
327 
328     tstatus = *status;
329 
330     if (ffmkyc(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
331     {
332         *status = tstatus;
333         ffpkyc(fptr, keyname, value, decim, comm, status);
334     }
335     return(*status);
336 }
337 /*--------------------------------------------------------------------------*/
ffukfm(fitsfile * fptr,const char * keyname,double * value,int decim,const char * comm,int * status)338 int ffukfm(fitsfile *fptr,     /* I - FITS file pointer  */
339            const char *keyname,/* I - keyword name       */
340            double *value,      /* I - keyword value      */
341            int decim,          /* I - no of decimals     */
342            const char *comm,   /* I - keyword comment    */
343            int *status)        /* IO - error status      */
344 {
345     int tstatus;
346 
347     if (*status > 0)           /* inherit input status value if > 0 */
348         return(*status);
349 
350     tstatus = *status;
351 
352     if (ffmkfm(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
353     {
354         *status = tstatus;
355         ffpkfm(fptr, keyname, value, decim, comm, status);
356     }
357     return(*status);
358 }
359 /*--------------------------------------------------------------------------*/
ffukym(fitsfile * fptr,const char * keyname,double * value,int decim,const char * comm,int * status)360 int ffukym(fitsfile *fptr,     /* I - FITS file pointer  */
361            const char *keyname,/* I - keyword name       */
362            double *value,      /* I - keyword value      */
363            int decim,          /* I - no of decimals     */
364            const char *comm,   /* I - keyword comment    */
365            int *status)        /* IO - error status      */
366 {
367     int tstatus;
368 
369     if (*status > 0)           /* inherit input status value if > 0 */
370         return(*status);
371 
372     tstatus = *status;
373 
374     if (ffmkym(fptr, keyname, value, decim, comm, status) == KEY_NO_EXIST)
375     {
376         *status = tstatus;
377         ffpkym(fptr, keyname, value, decim, comm, status);
378     }
379     return(*status);
380 }
381 /*--------------------------------------------------------------------------*/
ffucrd(fitsfile * fptr,const char * keyname,const char * card,int * status)382 int ffucrd(fitsfile *fptr,     /* I - FITS file pointer  */
383            const char *keyname,/* I - keyword name       */
384            const char *card,   /* I - card string value  */
385            int *status)        /* IO - error status      */
386 {
387     int tstatus;
388 
389     if (*status > 0)           /* inherit input status value if > 0 */
390         return(*status);
391 
392     tstatus = *status;
393 
394     if (ffmcrd(fptr, keyname, card, status) == KEY_NO_EXIST)
395     {
396         *status = tstatus;
397         ffprec(fptr, card, status);
398     }
399     return(*status);
400 }
401 /*--------------------------------------------------------------------------*/
ffmrec(fitsfile * fptr,int nkey,const char * card,int * status)402 int ffmrec(fitsfile *fptr,    /* I - FITS file pointer               */
403            int nkey,          /* I - number of the keyword to modify */
404            const char *card,  /* I - card string value               */
405            int *status)       /* IO - error status                   */
406 {
407     if (*status > 0)           /* inherit input status value if > 0 */
408         return(*status);
409 
410     ffmaky(fptr, nkey+1, status);
411     ffmkey(fptr, card, status);
412     return(*status);
413 }
414 /*--------------------------------------------------------------------------*/
ffmcrd(fitsfile * fptr,const char * keyname,const char * card,int * status)415 int ffmcrd(fitsfile *fptr,      /* I - FITS file pointer  */
416            const char *keyname, /* I - keyword name       */
417            const char *card,    /* I - card string value  */
418            int *status)         /* IO - error status      */
419 {
420     char tcard[FLEN_CARD], valstring[FLEN_CARD], comm[FLEN_CARD], value[FLEN_CARD];
421     char nextcomm[FLEN_COMMENT];
422     int keypos, len;
423 
424     if (*status > 0)           /* inherit input status value if > 0 */
425         return(*status);
426 
427     if (ffgcrd(fptr, keyname, tcard, status) > 0)
428         return(*status);
429 
430     ffmkey(fptr, card, status);
431 
432     /* calc position of keyword in header */
433     keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80) + 1;
434 
435     ffpsvc(tcard, valstring, comm, status);
436 
437     if (*status > 0)           /* inherit input status value if > 0 */
438         return(*status);
439 
440     /* check for string value which may be continued over multiple keywords */
441     ffpmrk(); /* put mark on message stack; erase any messages after this */
442     ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
443 
444     if (*status == VALUE_UNDEFINED) {
445        ffcmrk();  /* clear any spurious error messages, back to the mark */
446        *status = 0;
447     } else {
448 
449       len = strlen(value);
450 
451       while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
452       {
453         ffgcnt(fptr, value, nextcomm, status);
454         if (*value)
455         {
456             ffdrec(fptr, keypos, status);  /* delete the keyword */
457             len = strlen(value);
458         }
459         else   /* a null valstring indicates no continuation */
460             len = 0;
461       }
462     }
463 
464     return(*status);
465 }
466 /*--------------------------------------------------------------------------*/
ffmnam(fitsfile * fptr,const char * oldname,const char * newname,int * status)467 int ffmnam(fitsfile *fptr,     /* I - FITS file pointer     */
468            const char *oldname,/* I - existing keyword name */
469            const char *newname,/* I - new name for keyword  */
470            int *status)        /* IO - error status         */
471 {
472     char comm[FLEN_COMMENT];
473     char value[FLEN_VALUE];
474     char card[FLEN_CARD];
475 
476     if (*status > 0)           /* inherit input status value if > 0 */
477         return(*status);
478 
479     if (ffgkey(fptr, oldname, value, comm, status) > 0)
480         return(*status);
481 
482     ffmkky(newname, value, comm, card, status);  /* construct the card */
483     ffmkey(fptr, card, status);  /* rewrite with new name */
484 
485     return(*status);
486 }
487 /*--------------------------------------------------------------------------*/
ffmcom(fitsfile * fptr,const char * keyname,const char * comm,int * status)488 int ffmcom(fitsfile *fptr,     /* I - FITS file pointer  */
489            const char *keyname,/* I - keyword name       */
490            const char *comm,   /* I - keyword comment    */
491            int *status)        /* IO - error status      */
492 {
493     char oldcomm[FLEN_COMMENT];
494     char value[FLEN_VALUE];
495     char card[FLEN_CARD];
496 
497     if (*status > 0)           /* inherit input status value if > 0 */
498         return(*status);
499 
500     if (ffgkey(fptr, keyname, value, oldcomm, status) > 0)
501         return(*status);
502 
503     ffmkky(keyname, value, comm, card, status);  /* construct the card */
504     ffmkey(fptr, card, status);  /* rewrite with new comment */
505 
506     return(*status);
507 }
508 /*--------------------------------------------------------------------------*/
ffpunt(fitsfile * fptr,const char * keyname,const char * unit,int * status)509 int ffpunt(fitsfile *fptr,     /* I - FITS file pointer   */
510            const char *keyname,/* I - keyword name        */
511            const char *unit,   /* I - keyword unit string */
512            int *status)        /* IO - error status       */
513 /*
514     Write (put) the units string into the comment field of the existing keyword.
515     This routine uses a  FITS convention  in which the units are enclosed in
516     square brackets following the '/' comment field delimiter, e.g.:
517 
518     KEYWORD =                   12 / [kpc] comment string goes here
519 */
520 {
521     char oldcomm[FLEN_COMMENT];
522     char newcomm[FLEN_COMMENT];
523     char value[FLEN_VALUE];
524     char card[FLEN_CARD];
525     char *loc;
526     size_t len;
527 
528     if (*status > 0)           /* inherit input status value if > 0 */
529         return(*status);
530 
531     if (ffgkey(fptr, keyname, value, oldcomm, status) > 0)
532         return(*status);
533 
534     /* copy the units string to the new comment string if not null */
535     if (*unit)
536     {
537         strcpy(newcomm, "[");
538         strncat(newcomm, unit, 45);  /* max allowed length is about 45 chars */
539         strcat(newcomm, "] ");
540         len = strlen(newcomm);
541         len = FLEN_COMMENT - len - 1;  /* amount of space left in the field */
542     }
543     else
544     {
545         newcomm[0] = '\0';
546         len = FLEN_COMMENT - 1;
547     }
548 
549     if (oldcomm[0] == '[')  /* check for existing units field */
550     {
551         loc = strchr(oldcomm, ']');  /* look for the closing bracket */
552         if (loc)
553         {
554             loc++;
555             while (*loc == ' ')   /* skip any blank spaces */
556                loc++;
557 
558             strncat(newcomm, loc, len);  /* concat remainder of comment */
559         }
560         else
561         {
562             strncat(newcomm, oldcomm, len);  /* append old comment onto new */
563         }
564     }
565     else
566     {
567         strncat(newcomm, oldcomm, len);
568     }
569 
570     ffmkky(keyname, value, newcomm, card, status);  /* construct the card */
571     ffmkey(fptr, card, status);  /* rewrite with new units string */
572 
573     return(*status);
574 }
575 /*--------------------------------------------------------------------------*/
ffmkyu(fitsfile * fptr,const char * keyname,const char * comm,int * status)576 int ffmkyu(fitsfile *fptr,     /* I - FITS file pointer  */
577            const char *keyname,/* I - keyword name       */
578            const char *comm,   /* I - keyword comment    */
579            int *status)        /* IO - error status      */
580 {
581     char valstring[FLEN_VALUE];
582     char oldcomm[FLEN_COMMENT];
583     char card[FLEN_CARD];
584 
585     if (*status > 0)           /* inherit input status value if > 0 */
586         return(*status);
587 
588     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
589         return(*status);                               /* get old comment */
590 
591     strcpy(valstring," ");  /* create a dummy value string */
592 
593     if (!comm || comm[0] == '&')  /* preserve the current comment string */
594         ffmkky(keyname, valstring, oldcomm, card, status);
595     else
596         ffmkky(keyname, valstring, comm, card, status);
597 
598     ffmkey(fptr, card, status);
599 
600     return(*status);
601 }
602 /*--------------------------------------------------------------------------*/
ffmkys(fitsfile * fptr,const char * keyname,const char * value,const char * comm,int * status)603 int ffmkys(fitsfile *fptr,          /* I - FITS file pointer  */
604            const char *keyname,     /* I - keyword name       */
605            const char *value,       /* I - keyword value      */
606            const char *comm,        /* I - keyword comment    */
607            int *status)             /* IO - error status      */
608 {
609   /* NOTE: This routine does not support long continued strings */
610   /*  It will correctly overwrite an existing long continued string, */
611   /*  but it will not write a new long string.  */
612 
613     char oldval[FLEN_VALUE], valstring[FLEN_VALUE];
614     char oldcomm[FLEN_COMMENT];
615     char card[FLEN_CARD], nextcomm[FLEN_COMMENT];
616     int len, keypos;
617 
618     if (*status > 0)           /* inherit input status value if > 0 */
619         return(*status);
620 
621     if (ffgkey(fptr, keyname, oldval, oldcomm, status) > 0)
622         return(*status);                               /* get old comment */
623 
624     ffs2c(value, valstring, status);   /* convert value to a string */
625 
626     if (!comm || comm[0] == '&')  /* preserve the current comment string */
627         ffmkky(keyname, valstring, oldcomm, card, status);
628     else
629         ffmkky(keyname, valstring, comm, card, status);
630 
631     ffmkey(fptr, card, status); /* overwrite the previous keyword */
632 
633     keypos = (int) (((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80) + 1);
634 
635     if (*status > 0)
636         return(*status);
637 
638     /* check if old string value was continued over multiple keywords */
639     ffpmrk(); /* put mark on message stack; erase any messages after this */
640     ffc2s(oldval, valstring, status); /* remove quotes and trailing spaces */
641 
642     if (*status == VALUE_UNDEFINED) {
643        ffcmrk();  /* clear any spurious error messages, back to the mark */
644        *status = 0;
645     } else {
646 
647       len = strlen(valstring);
648 
649       while (len && valstring[len - 1] == '&')  /* ampersand is continuation char */
650       {
651         ffgcnt(fptr, valstring, nextcomm, status);
652         if (*valstring)
653         {
654             ffdrec(fptr, keypos, status);  /* delete the continuation */
655             len = strlen(valstring);
656         }
657         else   /* a null valstring indicates no continuation */
658             len = 0;
659       }
660     }
661 
662     return(*status);
663 }
664 /*--------------------------------------------------------------------------*/
ffmkls(fitsfile * fptr,const char * keyname,const char * value,const char * incomm,int * status)665 int ffmkls( fitsfile *fptr,           /* I - FITS file pointer        */
666             const char *keyname,      /* I - name of keyword to write */
667             const char *value,        /* I - keyword value            */
668             const char *incomm,       /* I - keyword comment          */
669             int  *status)             /* IO - error status            */
670 /*
671   Modify the value and optionally the comment of a long string keyword.
672   This routine supports the
673   HEASARC long string convention and can modify arbitrarily long string
674   keyword values.  The value is continued over multiple keywords that
675   have the name COMTINUE without an equal sign in column 9 of the card.
676   This routine also supports simple string keywords which are less than
677   69 characters in length.
678 
679   This routine is not very efficient, so it should be used sparingly.
680 */
681 {
682     char valstring[FLEN_VALUE];
683     char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
684     char comm[FLEN_COMMENT];
685     char tstring[FLEN_VALUE], *cptr;
686     char *longval;
687     int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;
688     int nkeys, keypos;
689 
690     if (*status > 0)           /* inherit input status value if > 0 */
691         return(*status);
692 
693     if (!incomm || incomm[0] == '&')  /* preserve the old comment string */
694     {
695         ffghps(fptr, &nkeys, &keypos, status); /* save current position */
696 
697         if (ffgkls(fptr, keyname, &longval, comm, status) > 0)
698             return(*status);            /* keyword doesn't exist */
699 
700         free(longval);  /* don't need the old value */
701 
702         /* move back to previous position to ensure that we delete */
703         /* the right keyword in case there are more than one keyword */
704         /* with this same name. */
705         ffgrec(fptr, keypos - 1, card, status);
706     } else {
707         /* copy the input comment string */
708         strncpy(comm, incomm, FLEN_COMMENT-1);
709         comm[FLEN_COMMENT-1] = '\0';
710     }
711 
712     /* delete the old keyword */
713     if (ffdkey(fptr, keyname, status) > 0)
714         return(*status);            /* keyword doesn't exist */
715 
716     ffghps(fptr, &nkeys, &keypos, status); /* save current position */
717 
718     /* now construct the new keyword, and insert into header */
719     remain = strlen(value);    /* number of characters to write out */
720     next = 0;                  /* pointer to next character to write */
721 
722     /* count the number of single quote characters in the string */
723     nquote = 0;
724     cptr = strchr(value, '\'');   /* search for quote character */
725 
726     while (cptr)  /* search for quote character */
727     {
728         nquote++;            /*  increment no. of quote characters  */
729         cptr++;              /*  increment pointer to next character */
730         cptr = strchr(cptr, '\'');  /* search for another quote char */
731     }
732 
733     strncpy(tmpkeyname, keyname, 80);
734     tmpkeyname[80] = '\0';
735 
736     cptr = tmpkeyname;
737     while(*cptr == ' ')   /* skip over leading spaces in name */
738         cptr++;
739 
740     /* determine the number of characters that will fit on the line */
741     /* Note: each quote character is expanded to 2 quotes */
742 
743     namelen = strlen(cptr);
744     if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
745     {
746         /* This a normal 8-character FITS keyword */
747         nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
748     }
749     else
750     {
751 	nchar = 80 - nquote - namelen - 5;
752     }
753 
754     contin = 0;
755     while (remain > 0)
756     {
757         if (nchar > FLEN_VALUE-1)
758         {
759            ffpmsg("longstr keyword value is too long (ffmkls)");
760            return (*status=BAD_KEYCHAR);
761         }
762         strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
763         tstring[nchar] = '\0';
764         ffs2c(tstring, valstring, status);  /* put quotes around the string */
765 
766         if (remain > nchar)   /* if string is continued, put & as last char */
767         {
768             vlen = strlen(valstring);
769             nchar -= 1;        /* outputting one less character now */
770 
771             if (valstring[vlen-2] != '\'')
772                 valstring[vlen-2] = '&';  /*  over write last char with &  */
773             else
774             { /* last char was a pair of single quotes, so over write both */
775                 valstring[vlen-3] = '&';
776                 valstring[vlen-1] = '\0';
777             }
778         }
779 
780         if (contin)           /* This is a CONTINUEd keyword */
781         {
782            ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
783            strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
784         }
785         else
786         {
787            ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
788         }
789 
790         ffirec(fptr, keypos, card, status);  /* insert the keyword */
791 
792         keypos++;        /* next insert position */
793         contin = 1;
794         remain -= nchar;
795         next  += nchar;
796         nchar = 68 - nquote;
797     }
798     return(*status);
799 }
800 /*--------------------------------------------------------------------------*/
ffmkyl(fitsfile * fptr,const char * keyname,int value,const char * comm,int * status)801 int ffmkyl(fitsfile *fptr,          /* I - FITS file pointer  */
802            const char *keyname,     /* I - keyword name       */
803            int value,               /* I - keyword value      */
804            const char *comm,        /* I - keyword comment    */
805            int *status)             /* IO - error status      */
806 {
807     char valstring[FLEN_VALUE];
808     char oldcomm[FLEN_COMMENT];
809     char card[FLEN_CARD];
810 
811     if (*status > 0)           /* inherit input status value if > 0 */
812         return(*status);
813 
814     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
815         return(*status);                               /* get old comment */
816 
817     ffl2c(value, valstring, status);   /* convert value to a string */
818 
819     if (!comm || comm[0] == '&')  /* preserve the current comment string */
820         ffmkky(keyname, valstring, oldcomm, card, status);
821     else
822         ffmkky(keyname, valstring, comm, card, status);
823 
824     ffmkey(fptr, card, status);
825 
826     return(*status);
827 }
828 /*--------------------------------------------------------------------------*/
ffmkyj(fitsfile * fptr,const char * keyname,LONGLONG value,const char * comm,int * status)829 int ffmkyj(fitsfile *fptr,          /* I - FITS file pointer  */
830            const char *keyname,     /* I - keyword name       */
831            LONGLONG value,          /* I - keyword value      */
832            const char *comm,        /* I - keyword comment    */
833            int *status)             /* IO - error status      */
834 {
835     char valstring[FLEN_VALUE];
836     char oldcomm[FLEN_COMMENT];
837     char card[FLEN_CARD];
838 
839     if (*status > 0)           /* inherit input status value if > 0 */
840         return(*status);
841 
842     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
843         return(*status);                               /* get old comment */
844 
845     ffi2c(value, valstring, status);   /* convert value to a string */
846 
847     if (!comm || comm[0] == '&')  /* preserve the current comment string */
848         ffmkky(keyname, valstring, oldcomm, card, status);
849     else
850         ffmkky(keyname, valstring, comm, card, status);
851 
852     ffmkey(fptr, card, status);
853 
854     return(*status);
855 }
856 /*--------------------------------------------------------------------------*/
ffmkyf(fitsfile * fptr,const char * keyname,float value,int decim,const char * comm,int * status)857 int ffmkyf(fitsfile *fptr,          /* I - FITS file pointer  */
858            const char *keyname,     /* I - keyword name       */
859            float value,             /* I - keyword value      */
860            int decim,               /* I - no of decimals     */
861            const char *comm,        /* I - keyword comment    */
862            int *status)             /* IO - error status      */
863 {
864     char valstring[FLEN_VALUE];
865     char oldcomm[FLEN_COMMENT];
866     char card[FLEN_CARD];
867 
868     if (*status > 0)           /* inherit input status value if > 0 */
869         return(*status);
870 
871     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
872         return(*status);                               /* get old comment */
873 
874     ffr2f(value, decim, valstring, status);   /* convert value to a string */
875 
876     if (!comm || comm[0] == '&')  /* preserve the current comment string */
877         ffmkky(keyname, valstring, oldcomm, card, status);
878     else
879         ffmkky(keyname, valstring, comm, card, status);
880 
881     ffmkey(fptr, card, status);
882 
883     return(*status);
884 }
885 /*--------------------------------------------------------------------------*/
ffmkye(fitsfile * fptr,const char * keyname,float value,int decim,const char * comm,int * status)886 int ffmkye(fitsfile *fptr,          /* I - FITS file pointer  */
887            const char *keyname,     /* I - keyword name       */
888            float value,             /* I - keyword value      */
889            int decim,               /* I - no of decimals     */
890            const char *comm,        /* I - keyword comment    */
891            int *status)             /* IO - error status      */
892 {
893     char valstring[FLEN_VALUE];
894     char oldcomm[FLEN_COMMENT];
895     char card[FLEN_CARD];
896 
897     if (*status > 0)           /* inherit input status value if > 0 */
898         return(*status);
899 
900     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
901         return(*status);                               /* get old comment */
902 
903     ffr2e(value, decim, valstring, status);   /* convert value to a string */
904 
905     if (!comm || comm[0] == '&')  /* preserve the current comment string */
906         ffmkky(keyname, valstring, oldcomm, card, status);
907     else
908         ffmkky(keyname, valstring, comm, card, status);
909 
910     ffmkey(fptr, card, status);
911 
912     return(*status);
913 }
914 /*--------------------------------------------------------------------------*/
ffmkyg(fitsfile * fptr,const char * keyname,double value,int decim,const char * comm,int * status)915 int ffmkyg(fitsfile *fptr,          /* I - FITS file pointer  */
916            const char *keyname,     /* I - keyword name       */
917            double value,            /* I - keyword value      */
918            int decim,               /* I - no of decimals     */
919            const char *comm,        /* I - keyword comment    */
920            int *status)             /* IO - error status      */
921 {
922     char valstring[FLEN_VALUE];
923     char oldcomm[FLEN_COMMENT];
924     char card[FLEN_CARD];
925 
926     if (*status > 0)           /* inherit input status value if > 0 */
927         return(*status);
928 
929     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
930         return(*status);                               /* get old comment */
931 
932     ffd2f(value, decim, valstring, status);   /* convert value to a string */
933 
934     if (!comm || comm[0] == '&')  /* preserve the current comment string */
935         ffmkky(keyname, valstring, oldcomm, card, status);
936     else
937         ffmkky(keyname, valstring, comm, card, status);
938 
939     ffmkey(fptr, card, status);
940 
941     return(*status);
942 }
943 /*--------------------------------------------------------------------------*/
ffmkyd(fitsfile * fptr,const char * keyname,double value,int decim,const char * comm,int * status)944 int ffmkyd(fitsfile *fptr,          /* I - FITS file pointer  */
945            const char *keyname,     /* I - keyword name       */
946            double value,            /* I - keyword value      */
947            int decim,               /* I - no of decimals     */
948            const char *comm,        /* I - keyword comment    */
949            int *status)             /* IO - error status      */
950 {
951     char valstring[FLEN_VALUE];
952     char oldcomm[FLEN_COMMENT];
953     char card[FLEN_CARD];
954 
955     if (*status > 0)           /* inherit input status value if > 0 */
956         return(*status);
957 
958     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
959         return(*status);                               /* get old comment */
960 
961     ffd2e(value, decim, valstring, status);   /* convert value to a string */
962 
963     if (!comm || comm[0] == '&')  /* preserve the current comment string */
964         ffmkky(keyname, valstring, oldcomm, card, status);
965     else
966         ffmkky(keyname, valstring, comm, card, status);
967 
968     ffmkey(fptr, card, status);
969 
970     return(*status);
971 }
972 /*--------------------------------------------------------------------------*/
ffmkfc(fitsfile * fptr,const char * keyname,float * value,int decim,const char * comm,int * status)973 int ffmkfc(fitsfile *fptr,          /* I - FITS file pointer  */
974            const char *keyname,     /* I - keyword name       */
975            float *value,            /* I - keyword value      */
976            int decim,               /* I - no of decimals     */
977            const char *comm,        /* I - keyword comment    */
978            int *status)             /* IO - error status      */
979 {
980     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
981     char oldcomm[FLEN_COMMENT];
982     char card[FLEN_CARD];
983 
984     if (*status > 0)           /* inherit input status value if > 0 */
985         return(*status);
986 
987     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
988         return(*status);                               /* get old comment */
989 
990     strcpy(valstring, "(" );
991     ffr2f(value[0], decim, tmpstring, status); /* convert to string */
992     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
993     {
994        ffpmsg("complex key value too long (ffmkfc)");
995        return(*status=BAD_F2C);
996     }
997     strcat(valstring, tmpstring);
998     strcat(valstring, ", ");
999     ffr2f(value[1], decim, tmpstring, status); /* convert to string */
1000     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1001     {
1002        ffpmsg("complex key value too long (ffmkfc)");
1003        return(*status=BAD_F2C);
1004     }
1005     strcat(valstring, tmpstring);
1006     strcat(valstring, ")");
1007 
1008     if (!comm || comm[0] == '&')  /* preserve the current comment string */
1009         ffmkky(keyname, valstring, oldcomm, card, status);
1010     else
1011         ffmkky(keyname, valstring, comm, card, status);
1012 
1013     ffmkey(fptr, card, status);
1014 
1015     return(*status);
1016 }
1017 /*--------------------------------------------------------------------------*/
ffmkyc(fitsfile * fptr,const char * keyname,float * value,int decim,const char * comm,int * status)1018 int ffmkyc(fitsfile *fptr,          /* I - FITS file pointer  */
1019            const char *keyname,     /* I - keyword name       */
1020            float *value,            /* I - keyword value      */
1021            int decim,               /* I - no of decimals     */
1022            const char *comm,        /* I - keyword comment    */
1023            int *status)             /* IO - error status      */
1024 {
1025     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
1026     char oldcomm[FLEN_COMMENT];
1027     char card[FLEN_CARD];
1028 
1029     if (*status > 0)           /* inherit input status value if > 0 */
1030         return(*status);
1031 
1032     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
1033         return(*status);                               /* get old comment */
1034 
1035     strcpy(valstring, "(" );
1036     ffr2e(value[0], decim, tmpstring, status); /* convert to string */
1037     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
1038     {
1039        ffpmsg("complex key value too long (ffmkyc)");
1040        return(*status=BAD_F2C);
1041     }
1042     strcat(valstring, tmpstring);
1043     strcat(valstring, ", ");
1044     ffr2e(value[1], decim, tmpstring, status); /* convert to string */
1045     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1046     {
1047        ffpmsg("complex key value too long (ffmkyc)");
1048        return(*status=BAD_F2C);
1049     }
1050     strcat(valstring, tmpstring);
1051     strcat(valstring, ")");
1052 
1053     if (!comm || comm[0] == '&')  /* preserve the current comment string */
1054         ffmkky(keyname, valstring, oldcomm, card, status);
1055     else
1056         ffmkky(keyname, valstring, comm, card, status);
1057 
1058     ffmkey(fptr, card, status);
1059 
1060     return(*status);
1061 }
1062 /*--------------------------------------------------------------------------*/
ffmkfm(fitsfile * fptr,const char * keyname,double * value,int decim,const char * comm,int * status)1063 int ffmkfm(fitsfile *fptr,          /* I - FITS file pointer  */
1064            const char *keyname,     /* I - keyword name       */
1065            double *value,           /* I - keyword value      */
1066            int decim,               /* I - no of decimals     */
1067            const char *comm,        /* I - keyword comment    */
1068            int *status)             /* IO - error status      */
1069 {
1070     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
1071     char oldcomm[FLEN_COMMENT];
1072     char card[FLEN_CARD];
1073 
1074     if (*status > 0)           /* inherit input status value if > 0 */
1075         return(*status);
1076 
1077     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
1078         return(*status);                               /* get old comment */
1079 
1080     strcpy(valstring, "(" );
1081     ffd2f(value[0], decim, tmpstring, status); /* convert to string */
1082     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
1083     {
1084        ffpmsg("complex key value too long (ffmkfm)");
1085        return(*status=BAD_F2C);
1086     }
1087     strcat(valstring, tmpstring);
1088     strcat(valstring, ", ");
1089     ffd2f(value[1], decim, tmpstring, status); /* convert to string */
1090     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1091     {
1092        ffpmsg("complex key value too long (ffmkfm)");
1093        return(*status=BAD_F2C);
1094     }
1095     strcat(valstring, tmpstring);
1096     strcat(valstring, ")");
1097 
1098     if (!comm || comm[0] == '&')  /* preserve the current comment string */
1099         ffmkky(keyname, valstring, oldcomm, card, status);
1100     else
1101         ffmkky(keyname, valstring, comm, card, status);
1102 
1103     ffmkey(fptr, card, status);
1104 
1105     return(*status);
1106 }
1107 /*--------------------------------------------------------------------------*/
ffmkym(fitsfile * fptr,const char * keyname,double * value,int decim,const char * comm,int * status)1108 int ffmkym(fitsfile *fptr,    /* I - FITS file pointer  */
1109            const char *keyname,     /* I - keyword name       */
1110            double *value,     /* I - keyword value      */
1111            int decim,         /* I - no of decimals     */
1112            const char *comm,        /* I - keyword comment    */
1113            int *status)       /* IO - error status      */
1114 {
1115     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
1116     char oldcomm[FLEN_COMMENT];
1117     char card[FLEN_CARD];
1118 
1119     if (*status > 0)           /* inherit input status value if > 0 */
1120         return(*status);
1121 
1122     if (ffgkey(fptr, keyname, valstring, oldcomm, status) > 0)
1123         return(*status);                               /* get old comment */
1124 
1125     strcpy(valstring, "(" );
1126     ffd2e(value[0], decim, tmpstring, status); /* convert to string */
1127     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
1128     {
1129        ffpmsg("complex key value too long (ffmkym)");
1130        return(*status=BAD_F2C);
1131     }
1132     strcat(valstring, tmpstring);
1133     strcat(valstring, ", ");
1134     ffd2e(value[1], decim, tmpstring, status); /* convert to string */
1135     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1136     {
1137        ffpmsg("complex key value too long (ffmkym)");
1138        return(*status=BAD_F2C);
1139     }
1140     strcat(valstring, tmpstring);
1141     strcat(valstring, ")");
1142 
1143     if (!comm || comm[0] == '&')  /* preserve the current comment string */
1144         ffmkky(keyname, valstring, oldcomm, card, status);
1145     else
1146         ffmkky(keyname, valstring, comm, card, status);
1147 
1148     ffmkey(fptr, card, status);
1149 
1150     return(*status);
1151 }
1152 /*--------------------------------------------------------------------------*/
ffikyu(fitsfile * fptr,const char * keyname,const char * comm,int * status)1153 int ffikyu(fitsfile *fptr,          /* I - FITS file pointer  */
1154            const char *keyname,     /* I - keyword name       */
1155            const char *comm,        /* I - keyword comment    */
1156            int *status)             /* IO - error status      */
1157 /*
1158   Insert a null-valued keyword and comment into the FITS header.
1159 */
1160 {
1161     char valstring[FLEN_VALUE];
1162     char card[FLEN_CARD];
1163 
1164     if (*status > 0)           /* inherit input status value if > 0 */
1165         return(*status);
1166 
1167     strcpy(valstring," ");  /* create a dummy value string */
1168     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1169     ffikey(fptr, card, status);
1170 
1171     return(*status);
1172 }
1173 /*--------------------------------------------------------------------------*/
ffikys(fitsfile * fptr,const char * keyname,const char * value,const char * comm,int * status)1174 int ffikys(fitsfile *fptr,          /* I - FITS file pointer  */
1175            const char *keyname,     /* I - keyword name       */
1176            const char *value,       /* I - keyword value      */
1177            const char *comm,        /* I - keyword comment    */
1178            int *status)             /* IO - error status      */
1179 {
1180     char valstring[FLEN_VALUE];
1181     char card[FLEN_CARD];
1182 
1183     if (*status > 0)           /* inherit input status value if > 0 */
1184         return(*status);
1185 
1186     ffs2c(value, valstring, status);   /* put quotes around the string */
1187 
1188     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1189     ffikey(fptr, card, status);
1190 
1191     return(*status);
1192 }
1193 /*--------------------------------------------------------------------------*/
ffikls(fitsfile * fptr,const char * keyname,const char * value,const char * comm,int * status)1194 int ffikls( fitsfile *fptr,           /* I - FITS file pointer        */
1195             const char *keyname,      /* I - name of keyword to write */
1196             const char *value,        /* I - keyword value            */
1197             const char *comm,         /* I - keyword comment          */
1198             int  *status)             /* IO - error status            */
1199 /*
1200   Insert a long string keyword.  This routine supports the
1201   HEASARC long string convention and can insert arbitrarily long string
1202   keyword values.  The value is continued over multiple keywords that
1203   have the name COMTINUE without an equal sign in column 9 of the card.
1204   This routine also supports simple string keywords which are less than
1205   69 characters in length.
1206 */
1207 {
1208     char valstring[FLEN_VALUE];
1209     char card[FLEN_CARD], tmpkeyname[FLEN_CARD];
1210     char tstring[FLEN_VALUE], *cptr;
1211     int next, remain, vlen, nquote, nchar, namelen, contin, tstatus = -1;
1212 
1213     if (*status > 0)           /* inherit input status value if > 0 */
1214         return(*status);
1215 
1216     /*  construct the new keyword, and insert into header */
1217     remain = strlen(value);    /* number of characters to write out */
1218     next = 0;                  /* pointer to next character to write */
1219 
1220     /* count the number of single quote characters in the string */
1221     nquote = 0;
1222     cptr = strchr(value, '\'');   /* search for quote character */
1223 
1224     while (cptr)  /* search for quote character */
1225     {
1226         nquote++;            /*  increment no. of quote characters  */
1227         cptr++;              /*  increment pointer to next character */
1228         cptr = strchr(cptr, '\'');  /* search for another quote char */
1229     }
1230 
1231 
1232     strncpy(tmpkeyname, keyname, 80);
1233     tmpkeyname[80] = '\0';
1234 
1235     cptr = tmpkeyname;
1236     while(*cptr == ' ')   /* skip over leading spaces in name */
1237         cptr++;
1238 
1239     /* determine the number of characters that will fit on the line */
1240     /* Note: each quote character is expanded to 2 quotes */
1241 
1242     namelen = strlen(cptr);
1243     if (namelen <= 8 && (fftkey(cptr, &tstatus) <= 0) )
1244     {
1245         /* This a normal 8-character FITS keyword */
1246         nchar = 68 - nquote; /*  max of 68 chars fit in a FITS string value */
1247     }
1248     else
1249     {
1250 	nchar = 80 - nquote - namelen - 5;
1251     }
1252 
1253     contin = 0;
1254     while (remain > 0)
1255     {
1256         if (nchar > FLEN_VALUE-1)
1257         {
1258            ffpmsg("longstr keyword value is too long (ffikls)");
1259            return (*status=BAD_KEYCHAR);
1260         }
1261         strncpy(tstring, &value[next], nchar); /* copy string to temp buff */
1262         tstring[nchar] = '\0';
1263         ffs2c(tstring, valstring, status);  /* put quotes around the string */
1264 
1265         if (remain > nchar)   /* if string is continued, put & as last char */
1266         {
1267             vlen = strlen(valstring);
1268             nchar -= 1;        /* outputting one less character now */
1269 
1270             if (valstring[vlen-2] != '\'')
1271                 valstring[vlen-2] = '&';  /*  over write last char with &  */
1272             else
1273             { /* last char was a pair of single quotes, so over write both */
1274                 valstring[vlen-3] = '&';
1275                 valstring[vlen-1] = '\0';
1276             }
1277         }
1278 
1279         if (contin)           /* This is a CONTINUEd keyword */
1280         {
1281            ffmkky("CONTINUE", valstring, comm, card, status); /* make keyword */
1282            strncpy(&card[8], "   ",  2);  /* overwrite the '=' */
1283         }
1284         else
1285         {
1286            ffmkky(keyname, valstring, comm, card, status);  /* make keyword */
1287         }
1288 
1289         ffikey(fptr, card, status);  /* insert the keyword */
1290 
1291         contin = 1;
1292         remain -= nchar;
1293         next  += nchar;
1294         nchar = 68 - nquote;
1295     }
1296     return(*status);
1297 }
1298 /*--------------------------------------------------------------------------*/
ffikyl(fitsfile * fptr,const char * keyname,int value,const char * comm,int * status)1299 int ffikyl(fitsfile *fptr,          /* I - FITS file pointer  */
1300            const char *keyname,     /* I - keyword name       */
1301            int value,               /* I - keyword value      */
1302            const char *comm,        /* I - keyword comment    */
1303            int *status)             /* IO - error status      */
1304 {
1305     char valstring[FLEN_VALUE];
1306     char card[FLEN_CARD];
1307 
1308     if (*status > 0)           /* inherit input status value if > 0 */
1309         return(*status);
1310 
1311     ffl2c(value, valstring, status);   /* convert logical to 'T' or 'F' */
1312     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1313     ffikey(fptr, card, status);  /* write the keyword*/
1314 
1315     return(*status);
1316 }
1317 /*--------------------------------------------------------------------------*/
ffikyj(fitsfile * fptr,const char * keyname,LONGLONG value,const char * comm,int * status)1318 int ffikyj(fitsfile *fptr,          /* I - FITS file pointer  */
1319            const char *keyname,     /* I - keyword name       */
1320            LONGLONG value,          /* I - keyword value      */
1321            const char *comm,        /* I - keyword comment    */
1322            int *status)             /* IO - error status      */
1323 {
1324     char valstring[FLEN_VALUE];
1325     char card[FLEN_CARD];
1326 
1327     if (*status > 0)           /* inherit input status value if > 0 */
1328         return(*status);
1329 
1330     ffi2c(value, valstring, status);   /* convert to formatted string */
1331     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1332     ffikey(fptr, card, status);  /* write the keyword*/
1333 
1334     return(*status);
1335 }
1336 /*--------------------------------------------------------------------------*/
ffikyf(fitsfile * fptr,const char * keyname,float value,int decim,const char * comm,int * status)1337 int ffikyf(fitsfile *fptr,          /* I - FITS file pointer  */
1338            const char *keyname,     /* I - keyword name       */
1339            float value,             /* I - keyword value      */
1340            int decim,               /* I - no of decimals     */
1341            const char *comm,        /* I - keyword comment    */
1342            int *status)             /* IO - error status      */
1343 {
1344     char valstring[FLEN_VALUE];
1345     char card[FLEN_CARD];
1346 
1347     if (*status > 0)           /* inherit input status value if > 0 */
1348         return(*status);
1349 
1350     ffr2f(value, decim, valstring, status);   /* convert to formatted string */
1351     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1352     ffikey(fptr, card, status);  /* write the keyword*/
1353 
1354     return(*status);
1355 }
1356 /*--------------------------------------------------------------------------*/
ffikye(fitsfile * fptr,const char * keyname,float value,int decim,const char * comm,int * status)1357 int ffikye(fitsfile *fptr,          /* I - FITS file pointer  */
1358            const char *keyname,     /* I - keyword name       */
1359            float value,             /* I - keyword value      */
1360            int decim,               /* I - no of decimals     */
1361            const char *comm,        /* I - keyword comment    */
1362            int *status)             /* IO - error status      */
1363 {
1364     char valstring[FLEN_VALUE];
1365     char card[FLEN_CARD];
1366 
1367     if (*status > 0)           /* inherit input status value if > 0 */
1368         return(*status);
1369 
1370     ffr2e(value, decim, valstring, status);   /* convert to formatted string */
1371     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1372     ffikey(fptr, card, status);  /* write the keyword*/
1373 
1374     return(*status);
1375 }
1376 /*--------------------------------------------------------------------------*/
ffikyg(fitsfile * fptr,const char * keyname,double value,int decim,const char * comm,int * status)1377 int ffikyg(fitsfile *fptr,          /* I - FITS file pointer  */
1378            const char *keyname,     /* I - keyword name       */
1379            double value,            /* I - keyword value      */
1380            int decim,               /* I - no of decimals     */
1381            const char *comm,        /* I - keyword comment    */
1382            int *status)             /* IO - error status      */
1383 {
1384     char valstring[FLEN_VALUE];
1385     char card[FLEN_CARD];
1386 
1387     if (*status > 0)           /* inherit input status value if > 0 */
1388         return(*status);
1389 
1390     ffd2f(value, decim, valstring, status);   /* convert to formatted string */
1391     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1392     ffikey(fptr, card, status);  /* write the keyword*/
1393 
1394     return(*status);
1395 }
1396 /*--------------------------------------------------------------------------*/
ffikyd(fitsfile * fptr,const char * keyname,double value,int decim,const char * comm,int * status)1397 int ffikyd(fitsfile *fptr,          /* I - FITS file pointer  */
1398            const char *keyname,     /* I - keyword name       */
1399            double value,            /* I - keyword value      */
1400            int decim,               /* I - no of decimals     */
1401            const char *comm,        /* I - keyword comment    */
1402            int *status)             /* IO - error status      */
1403 {
1404     char valstring[FLEN_VALUE];
1405     char card[FLEN_CARD];
1406 
1407     if (*status > 0)           /* inherit input status value if > 0 */
1408         return(*status);
1409 
1410     ffd2e(value, decim, valstring, status);   /* convert to formatted string */
1411     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1412     ffikey(fptr, card, status);  /* write the keyword*/
1413 
1414     return(*status);
1415 }
1416 /*--------------------------------------------------------------------------*/
ffikfc(fitsfile * fptr,const char * keyname,float * value,int decim,const char * comm,int * status)1417 int ffikfc(fitsfile *fptr,          /* I - FITS file pointer  */
1418            const char *keyname,     /* I - keyword name       */
1419            float *value,            /* I - keyword value      */
1420            int decim,               /* I - no of decimals     */
1421            const char *comm,        /* I - keyword comment    */
1422            int *status)             /* IO - error status      */
1423 {
1424     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
1425     char card[FLEN_CARD];
1426 
1427     if (*status > 0)           /* inherit input status value if > 0 */
1428         return(*status);
1429 
1430     strcpy(valstring, "(" );
1431     ffr2f(value[0], decim, tmpstring, status); /* convert to string */
1432     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
1433     {
1434        ffpmsg("complex key value too long (ffikfc)");
1435        return(*status=BAD_F2C);
1436     }
1437     strcat(valstring, tmpstring);
1438     strcat(valstring, ", ");
1439     ffr2f(value[1], decim, tmpstring, status); /* convert to string */
1440     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1441     {
1442        ffpmsg("complex key value too long (ffikfc)");
1443        return(*status=BAD_F2C);
1444     }
1445     strcat(valstring, tmpstring);
1446     strcat(valstring, ")");
1447 
1448     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1449     ffikey(fptr, card, status);  /* write the keyword*/
1450 
1451     return(*status);
1452 }
1453 /*--------------------------------------------------------------------------*/
ffikyc(fitsfile * fptr,const char * keyname,float * value,int decim,const char * comm,int * status)1454 int ffikyc(fitsfile *fptr,          /* I - FITS file pointer  */
1455            const char *keyname,     /* I - keyword name       */
1456            float *value,            /* I - keyword value      */
1457            int decim,               /* I - no of decimals     */
1458            const char *comm,        /* I - keyword comment    */
1459            int *status)             /* IO - error status      */
1460 {
1461     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
1462     char card[FLEN_CARD];
1463 
1464     if (*status > 0)           /* inherit input status value if > 0 */
1465         return(*status);
1466 
1467     strcpy(valstring, "(" );
1468     ffr2e(value[0], decim, tmpstring, status); /* convert to string */
1469     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
1470     {
1471        ffpmsg("complex key value too long (ffikyc)");
1472        return(*status=BAD_F2C);
1473     }
1474     strcat(valstring, tmpstring);
1475     strcat(valstring, ", ");
1476     ffr2e(value[1], decim, tmpstring, status); /* convert to string */
1477     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1478     {
1479        ffpmsg("complex key value too long (ffikyc)");
1480        return(*status=BAD_F2C);
1481     }
1482     strcat(valstring, tmpstring);
1483     strcat(valstring, ")");
1484 
1485     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1486     ffikey(fptr, card, status);  /* write the keyword*/
1487 
1488     return(*status);
1489 }
1490 /*--------------------------------------------------------------------------*/
ffikfm(fitsfile * fptr,const char * keyname,double * value,int decim,const char * comm,int * status)1491 int ffikfm(fitsfile *fptr,          /* I - FITS file pointer  */
1492            const char *keyname,     /* I - keyword name       */
1493            double *value,           /* I - keyword value      */
1494            int decim,               /* I - no of decimals     */
1495            const char *comm,        /* I - keyword comment    */
1496            int *status)             /* IO - error status      */
1497 {
1498     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
1499     char card[FLEN_CARD];
1500 
1501     if (*status > 0)           /* inherit input status value if > 0 */
1502         return(*status);
1503 
1504 
1505     strcpy(valstring, "(" );
1506     ffd2f(value[0], decim, tmpstring, status); /* convert to string */
1507     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
1508     {
1509        ffpmsg("complex key value too long (ffikfm)");
1510        return(*status=BAD_F2C);
1511     }
1512     strcat(valstring, tmpstring);
1513     strcat(valstring, ", ");
1514     ffd2f(value[1], decim, tmpstring, status); /* convert to string */
1515     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1516     {
1517        ffpmsg("complex key value too long (ffikfm)");
1518        return(*status=BAD_F2C);
1519     }
1520     strcat(valstring, tmpstring);
1521     strcat(valstring, ")");
1522 
1523     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1524     ffikey(fptr, card, status);  /* write the keyword*/
1525 
1526     return(*status);
1527 }
1528 /*--------------------------------------------------------------------------*/
ffikym(fitsfile * fptr,const char * keyname,double * value,int decim,const char * comm,int * status)1529 int ffikym(fitsfile *fptr,          /* I - FITS file pointer  */
1530            const char *keyname,     /* I - keyword name       */
1531            double *value,           /* I - keyword value      */
1532            int decim,               /* I - no of decimals     */
1533            const char *comm,        /* I - keyword comment    */
1534            int *status)             /* IO - error status      */
1535 {
1536     char valstring[FLEN_VALUE], tmpstring[FLEN_VALUE];
1537     char card[FLEN_CARD];
1538 
1539     if (*status > 0)           /* inherit input status value if > 0 */
1540         return(*status);
1541 
1542     strcpy(valstring, "(" );
1543     ffd2e(value[0], decim, tmpstring, status); /* convert to string */
1544     if (strlen(tmpstring)+3 > FLEN_VALUE-1)
1545     {
1546        ffpmsg("complex key value too long (ffikym)");
1547        return(*status=BAD_F2C);
1548     }
1549     strcat(valstring, tmpstring);
1550     strcat(valstring, ", ");
1551     ffd2e(value[1], decim, tmpstring, status); /* convert to string */
1552     if (strlen(valstring) + strlen(tmpstring)+1 > FLEN_VALUE-1)
1553     {
1554        ffpmsg("complex key value too long (ffikym)");
1555        return(*status=BAD_F2C);
1556     }
1557     strcat(valstring, tmpstring);
1558     strcat(valstring, ")");
1559 
1560     ffmkky(keyname, valstring, comm, card, status);  /* construct the keyword*/
1561     ffikey(fptr, card, status);  /* write the keyword*/
1562 
1563     return(*status);
1564 }
1565 /*--------------------------------------------------------------------------*/
ffirec(fitsfile * fptr,int nkey,const char * card,int * status)1566 int ffirec(fitsfile *fptr,    /* I - FITS file pointer              */
1567            int nkey,          /* I - position to insert new keyword */
1568            const char *card,  /* I - card string value              */
1569            int *status)       /* IO - error status                  */
1570 {
1571     if (*status > 0)           /* inherit input status value if > 0 */
1572         return(*status);
1573 
1574     ffmaky(fptr, nkey, status);  /* move to insert position */
1575     ffikey(fptr, card, status);  /* insert the keyword card */
1576 
1577     return(*status);
1578 }
1579 /*--------------------------------------------------------------------------*/
ffikey(fitsfile * fptr,const char * card,int * status)1580 int ffikey(fitsfile *fptr,    /* I - FITS file pointer  */
1581            const char *card,  /* I - card string value  */
1582            int *status)       /* IO - error status      */
1583 /*
1584   insert a keyword at the position of (fptr->Fptr)->nextkey
1585 */
1586 {
1587     int ii, len, nshift, keylength;
1588     long nblocks;
1589     LONGLONG bytepos;
1590     char *inbuff, *outbuff, *tmpbuff, buff1[FLEN_CARD], buff2[FLEN_CARD];
1591 
1592     if (*status > 0)           /* inherit input status value if > 0 */
1593         return(*status);
1594 
1595     /* reset position to the correct HDU if necessary */
1596     if (fptr->HDUposition != (fptr->Fptr)->curhdu)
1597         ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
1598 
1599     if ( ((fptr->Fptr)->datastart - (fptr->Fptr)->headend) == 80) /* only room for END card */
1600     {
1601         nblocks = 1;
1602         if (ffiblk(fptr, nblocks, 0, status) > 0) /* add new 2880-byte block*/
1603             return(*status);
1604     }
1605 
1606     /* no. keywords to shift */
1607     nshift= (int) (( (fptr->Fptr)->headend - (fptr->Fptr)->nextkey ) / 80);
1608 
1609     strncpy(buff2, card, 80);     /* copy card to output buffer */
1610     buff2[80] = '\0';
1611 
1612     len = strlen(buff2);
1613 
1614     /* silently replace any illegal characters with a space */
1615     for (ii=0; ii < len; ii++)
1616         if (buff2[ii] < ' ' || buff2[ii] > 126) buff2[ii] = ' ';
1617 
1618     for (ii=len; ii < 80; ii++)   /* fill buffer with spaces if necessary */
1619         buff2[ii] = ' ';
1620 
1621     keylength = strcspn(buff2, "=");
1622     if (keylength == 80) keylength = 8;
1623 
1624     /* test for the common commentary keywords which by definition have 8-char names */
1625     if ( !fits_strncasecmp( "COMMENT ", buff2, 8) || !fits_strncasecmp( "HISTORY ", buff2, 8) ||
1626          !fits_strncasecmp( "        ", buff2, 8) || !fits_strncasecmp( "CONTINUE", buff2, 8) )
1627 	 keylength = 8;
1628 
1629     for (ii=0; ii < keylength; ii++)       /* make sure keyword name is uppercase */
1630         buff2[ii] = toupper(buff2[ii]);
1631 
1632     fftkey(buff2, status);        /* test keyword name contains legal chars */
1633 
1634 /*  no need to do this any more, since any illegal characters have been removed
1635     fftrec(buff2, status);  */      /* test rest of keyword for legal chars   */
1636 
1637     inbuff = buff1;
1638     outbuff = buff2;
1639 
1640     bytepos = (fptr->Fptr)->nextkey;           /* pointer to next keyword in header */
1641     ffmbyt(fptr, bytepos, REPORT_EOF, status);
1642 
1643     for (ii = 0; ii < nshift; ii++) /* shift each keyword down one position */
1644     {
1645         ffgbyt(fptr, 80, inbuff, status);   /* read the current keyword */
1646 
1647         ffmbyt(fptr, bytepos, REPORT_EOF, status); /* move back */
1648         ffpbyt(fptr, 80, outbuff, status);  /* overwrite with other buffer */
1649 
1650         tmpbuff = inbuff;   /* swap input and output buffers */
1651         inbuff = outbuff;
1652         outbuff = tmpbuff;
1653 
1654         bytepos += 80;
1655     }
1656 
1657     ffpbyt(fptr, 80, outbuff, status);  /* write the final keyword */
1658 
1659     (fptr->Fptr)->headend += 80; /* increment the position of the END keyword */
1660     (fptr->Fptr)->nextkey += 80; /* increment the pointer to next keyword */
1661 
1662     return(*status);
1663 }
1664 /*--------------------------------------------------------------------------*/
ffdkey(fitsfile * fptr,const char * keyname,int * status)1665 int ffdkey(fitsfile *fptr,    /* I - FITS file pointer  */
1666            const char *keyname,     /* I - keyword name       */
1667            int *status)       /* IO - error status      */
1668 /*
1669   delete a specified header keyword
1670 */
1671 {
1672     int keypos, len;
1673     char valstring[FLEN_VALUE], comm[FLEN_COMMENT], value[FLEN_VALUE];
1674     char message[FLEN_ERRMSG], nextcomm[FLEN_COMMENT];
1675 
1676     if (*status > 0)           /* inherit input status value if > 0 */
1677         return(*status);
1678 
1679     if (ffgkey(fptr, keyname, valstring, comm, status) > 0) /* read keyword */
1680     {
1681         snprintf(message, FLEN_ERRMSG,"Could not find the %s keyword to delete (ffdkey)",
1682                 keyname);
1683         ffpmsg(message);
1684         return(*status);
1685     }
1686 
1687     /* calc position of keyword in header */
1688     keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80);
1689 
1690     ffdrec(fptr, keypos, status);  /* delete the keyword */
1691 
1692     if (*status > 0)           /* inherit input status value if > 0 */
1693         return(*status);
1694 
1695     /* check for string value which may be continued over multiple keywords */
1696     ffpmrk(); /* put mark on message stack; erase any messages after this */
1697     ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
1698 
1699     if (*status == VALUE_UNDEFINED) {
1700        ffcmrk();  /* clear any spurious error messages, back to the mark */
1701        *status = 0;
1702     } else {
1703 
1704       len = strlen(value);
1705 
1706       while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
1707       {
1708         ffgcnt(fptr, value, nextcomm, status);
1709         if (*value)
1710         {
1711             ffdrec(fptr, keypos, status);  /* delete the keyword */
1712             len = strlen(value);
1713         }
1714         else   /* a null valstring indicates no continuation */
1715             len = 0;
1716       }
1717     }
1718 
1719     return(*status);
1720 }
1721 /*--------------------------------------------------------------------------*/
ffdstr(fitsfile * fptr,const char * string,int * status)1722 int ffdstr(fitsfile *fptr,    /* I - FITS file pointer  */
1723            const char *string,     /* I - keyword name       */
1724            int *status)       /* IO - error status      */
1725 /*
1726   delete a specified header keyword containing the input string
1727 */
1728 {
1729     int keypos, len;
1730     char valstring[FLEN_VALUE], comm[FLEN_COMMENT], value[FLEN_VALUE];
1731     char card[FLEN_CARD], message[FLEN_ERRMSG], nextcomm[FLEN_COMMENT];
1732 
1733     if (*status > 0)           /* inherit input status value if > 0 */
1734         return(*status);
1735 
1736     if (ffgstr(fptr, string, card, status) > 0) /* read keyword */
1737     {
1738         snprintf(message, FLEN_ERRMSG,"Could not find the %s keyword to delete (ffdkey)",
1739                 string);
1740         ffpmsg(message);
1741         return(*status);
1742     }
1743 
1744     /* calc position of keyword in header */
1745     keypos = (int) ((((fptr->Fptr)->nextkey) - ((fptr->Fptr)->headstart[(fptr->Fptr)->curhdu])) / 80);
1746 
1747     ffdrec(fptr, keypos, status);  /* delete the keyword */
1748 
1749     /* check for string value which may be continued over multiple keywords */
1750     ffpsvc(card, valstring, comm, status);
1751 
1752     if (*status > 0)           /* inherit input status value if > 0 */
1753         return(*status);
1754 
1755     /* check for string value which may be continued over multiple keywords */
1756     ffpmrk(); /* put mark on message stack; erase any messages after this */
1757     ffc2s(valstring, value, status);   /* remove quotes and trailing spaces */
1758 
1759     if (*status == VALUE_UNDEFINED) {
1760        ffcmrk();  /* clear any spurious error messages, back to the mark */
1761        *status = 0;
1762     } else {
1763 
1764       len = strlen(value);
1765 
1766       while (len && value[len - 1] == '&')  /* ampersand used as continuation char */
1767       {
1768         ffgcnt(fptr, value, nextcomm, status);
1769         if (*value)
1770         {
1771             ffdrec(fptr, keypos, status);  /* delete the keyword */
1772             len = strlen(value);
1773         }
1774         else   /* a null valstring indicates no continuation */
1775             len = 0;
1776       }
1777     }
1778 
1779     return(*status);
1780 }/*--------------------------------------------------------------------------*/
ffdrec(fitsfile * fptr,int keypos,int * status)1781 int ffdrec(fitsfile *fptr,   /* I - FITS file pointer  */
1782            int keypos,       /* I - position in header of keyword to delete */
1783            int *status)      /* IO - error status      */
1784 /*
1785   Delete a header keyword at position keypos. The 1st keyword is at keypos=1.
1786 */
1787 {
1788     int ii, nshift;
1789     LONGLONG bytepos;
1790     char *inbuff, *outbuff, *tmpbuff, buff1[81], buff2[81];
1791     char message[FLEN_ERRMSG];
1792 
1793     if (*status > 0)           /* inherit input status value if > 0 */
1794         return(*status);
1795 
1796     /* reset position to the correct HDU if necessary */
1797     if (fptr->HDUposition != (fptr->Fptr)->curhdu)
1798         ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
1799 
1800     if (keypos < 1 ||
1801         keypos > (fptr->Fptr)->headend - (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] / 80 )
1802         return(*status = KEY_OUT_BOUNDS);
1803 
1804     (fptr->Fptr)->nextkey = (fptr->Fptr)->headstart[(fptr->Fptr)->curhdu] + (keypos - 1) * 80;
1805 
1806     nshift=(int) (( (fptr->Fptr)->headend - (fptr->Fptr)->nextkey ) / 80); /* no. keywords to shift */
1807 
1808     if (nshift <= 0)
1809     {
1810         snprintf(message, FLEN_ERRMSG,"Cannot delete keyword number %d.  It does not exist.",
1811                 keypos);
1812         ffpmsg(message);
1813         return(*status = KEY_OUT_BOUNDS);
1814     }
1815 
1816     bytepos = (fptr->Fptr)->headend - 80;  /* last keyword in header */
1817 
1818     /* construct a blank keyword */
1819     strcpy(buff2, "                                        ");
1820     strcat(buff2, "                                        ");
1821     inbuff  = buff1;
1822     outbuff = buff2;
1823     for (ii = 0; ii < nshift; ii++) /* shift each keyword up one position */
1824     {
1825 
1826         ffmbyt(fptr, bytepos, REPORT_EOF, status);
1827         ffgbyt(fptr, 80, inbuff, status);   /* read the current keyword */
1828 
1829         ffmbyt(fptr, bytepos, REPORT_EOF, status);
1830         ffpbyt(fptr, 80, outbuff, status);  /* overwrite with next keyword */
1831 
1832         tmpbuff = inbuff;   /* swap input and output buffers */
1833         inbuff = outbuff;
1834         outbuff = tmpbuff;
1835 
1836         bytepos -= 80;
1837     }
1838 
1839     (fptr->Fptr)->headend -= 80; /* decrement the position of the END keyword */
1840     return(*status);
1841 }
1842 
1843