aboutsummaryrefslogtreecommitdiff
path: root/pkg/tbtables/fitsio/ftiblk.f
blob: 9c61fd129ceec9db7c7969c9fb5c3fb9785aaf1b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
C--------------------------------------------------------------------------
        subroutine ftiblk(ounit,nblock,hdrdat,status)

C       insert a 2880-byte block at the end of the current header or data.

C       ounit   i  fortran output unit number
C       nblock  i  number of blocks to insert
C       hdrdat  i  insert space in header (0) or data (1)
C       status  i  returned error status (0=ok)

        integer ounit,nblock,hdrdat,status

C       COMMON BLOCK DEFINITIONS:--------------------------------------------
        integer nb,ne
        parameter (nb = 20)
        parameter (ne = 200)
        integer bufnum,chdu,hdutyp,maxhdu,hdstrt,hdend,nxthdr,dtstrt
        integer nxtfld
        logical wrmode
        common/ft0001/bufnum(199),chdu(nb),hdutyp(nb),maxhdu(nb),
     &  wrmode(nb),hdstrt(nb,ne),hdend(nb),nxthdr(nb),dtstrt(nb),nxtfld
        character*1 buff(2880,2)
        common/ftheap/buff
C       END OF COMMON BLOCK DEFINITIONS:------------------------------------

        integer ibuff,ipoint,jpoint,i,tstat,thdu,nshift,in,out,tin
        character*1 cfill

        if (status .gt. 0)return
        tstat=status

C       get the number of the data buffer used for this unit
        ibuff=bufnum(ounit)

C       set the appropriate fill value
        if (hdrdat .eq. 0 .or. hdutyp(ibuff) .eq. 1)then
C               fill  header or ASCII table with space
                cfill=char(32)
        else
C               fill with Null (0) in image or bintable data area        
                cfill=char(0)
        end if

C       find position in file to insert new block
        if (hdrdat .eq. 0)then
            ipoint=dtstrt(ibuff)
        else
            ipoint=hdstrt(ibuff,chdu(ibuff)+1)
        end if


        if (nblock .eq. 1 .and. hdrdat .eq. 0)then
C******************************************************************
C  Don't use this algoritm, even though it may be faster (but initial
C  tests showed it didn't make any difference on a SUN) because it is
C  less safe than the other more general algorithm.  If there is
C  not enough disk space available for the added block, this faster
C  algorithm won't fail until it tries to move the last block, thus leaving
C  the FITS file in a corrupted state.   The other more general
C  algorithm tries to add a new empty block to the file as the
C  first step.  If this fails, it still leaves the current FITS
C  file unmodified, which is better for the user.  
C******************************************************************
C  (Note added later:)
C  Will use this algorithm anyway when inserting one block in a FITS
C  header because the more general algorithm results in a status=252 error
C  in cases where the number of rows in a table has not yet been defined
C******************************************************************
C           use this more efficient algorithm if just adding a single block
C           initialize the first buffer
            do 5 i=1,2880
               buff(i,1)=cfill
5           continue

            in=2
            out=1

C           move to the read start position
10          call ftmbyt(ounit,ipoint,.false.,status)

C           read one 2880-byte FITS logical record into the input buffer
            call ftgcbf(ounit,0,2880,buff(1,in),status)

C           check for End-Of-File
            if (status .eq. 107)go to 20

C           move back to the write start postion
            call ftmbyt(ounit,ipoint,.false.,status)

C           write the 2880-byte FITS logical record stored in the output buffer
            call ftpcbf(ounit,0,2880,buff(1,out),status)

C           check for error during write (the file may not have write access)
            if (status .gt. 0)return

C           swap the input and output buffer pointers and move to next block
            tin=in
            in=out
            out=tin
            ipoint=ipoint+2880

C           now repeat the process until we reach the End-Of-File
            go to 10

C           we have reached the end of file; now append the last block
20          status=tstat

C           move back to the write start postion
            call ftmbyt(ounit,ipoint,.true.,status)

C           write the 2880-byte FITS logical record stored in the output buffer
            call ftpcbf(ounit,0,2880,buff(1,out),status)

        else
C           use this general algorithm for adding arbitrary number of blocks

C           first, find the end of file
            thdu=chdu(ibuff)

30          call ftmahd(ounit,maxhdu(ibuff)+1,i,status)

            if (status .eq. 107)then
                status=tstat
C               move back to the current extension
                call ftmahd(ounit,thdu,i,status)
                go to 100
            else if (status .le. 0)then
                go to 30
            else
                call ftpmsg('Error while seeking End of File (FTIBLK)')
                return
            end if

C           calculate number of 2880-byte blocks that have to be shifted down
100         continue
            nshift=(hdstrt(ibuff,maxhdu(ibuff)+1)-ipoint)/2880
            jpoint=hdstrt(ibuff,maxhdu(ibuff)+1)-2880

C           move all the blocks, one at a time, starting at end of file and
C           working back to the insert position
            do 110 i=1,nshift

C               move to the read start position
                call ftmbyt(ounit,jpoint,.false.,status)

C               read one 2880-byte FITS logical record
                call ftgcbf(ounit,0,2880,buff,status)

C               move forward to the write start postion
                call ftmbyt(ounit,jpoint+nblock*2880,.true.,status)

C               write the 2880-byte FITS logical record
                call ftpcbf(ounit,0,2880,buff,status)

C               check for error 
                if (status .gt. 0)then
                    call ftpmsg('Error inserting empty FITS block(s) '//
     &              '(FTIBLK)')
                    return
                end if
                jpoint=jpoint-2880
110         continue

            do 120 i=1,2880
                buff(i,1)=cfill
120         continue
             
C           move back to the write start postion
            call ftmbyt(ounit,ipoint,.true.,status)

            do 130 i=1,nblock
C               write the 2880-byte FITS logical record 
                call ftpcbf(ounit,0,2880,buff,status)
130         continue
        end if

        if (hdrdat .eq. 0)then
C               recalculate the starting location of the current data unit
                dtstrt(ibuff)=dtstrt(ibuff)+2880*nblock
        end if

C       recalculate the starting location of all subsequent HDUs
        do 140 i=chdu(ibuff)+1,maxhdu(ibuff)+1
                    hdstrt(ibuff,i)=hdstrt(ibuff,i)+2880*nblock
140     continue
        if (status .gt. 0)then
            call ftpmsg('Error inserting FITS block(s) (FTIBLK)')
        end if
        end