C--------------------------------------------------------------------------
        subroutine ftbdef(ounit,nfield,tform,pcount,nrows,status)

C       Binary table data DEFinition
C       define the structure of the binary table data unit
C
C       ounit   i  Fortran I/O unit number
C       nfield  i  number of fields in the table
C       tform   C  the data format of the column
C       nrows   i  number of rows in the table
C       pcount  i  size in bytes of the special data block following the table
C       status  i  output error status (0 = ok)
C
C       written by Wm Pence, HEASARC/GSFC, June 1991

        integer ounit,nfield,nrows,pcount,status
        character*(*) tform(*)

C-------COMMON BLOCK DEFINITIONS:--------------------------------------------
        integer nb,ne,nf
        parameter (nb = 12)
        parameter (ne = 128)
        parameter (nf = 512)
        integer bufnum,bufpnt,reclen,recnum,bytnum
        integer chdu,maxhdu,hdstrt,hdend,nxthdr,dtstrt
        logical wrmode,modify
        real compid
        common/ft0001/bufnum(199),bufpnt(nb),reclen(199),recnum(nb),
     &  bytnum(nb),wrmode(nb),modify(nb),chdu(nb),maxhdu(nb),
     &  hdstrt(nb,ne),hdend(nb),nxthdr(nb),dtstrt(nb),compid
        integer tfield,tbcol,rowlen,tdtype,trept,tnull,scount
        integer theap,nxheap
        double precision tscale,tzero
        common/ft0002/tfield(nb),tbcol(nf,nb),rowlen(nb),tdtype(nf,nb),
     &  trept(nf,nb),tscale(nf,nb),tzero(nf,nb),tnull(nf,nb),scount(nb)
     &  ,theap(nb),nxheap(nb)
C-------END OF COMMON BLOCK DEFINITIONS-----------------------------------
        
        integer ibuff,i,j,width

        if (status .gt. 0)return

        ibuff=bufnum(ounit)

        if (dtstrt(ibuff) .lt. 0)then
C               freeze the header at its current size
                call fthdef(ounit,0,status)
                if (status .gt. 0)return
        end if

        tfield(ibuff)=nfield
        if (nfield .eq. 0)then
C           no data; the next HDU begins in the next logical block 
            hdstrt(ibuff,chdu(ibuff)+1)=dtstrt(ibuff)
        else
C           initialize the table column parameters
            do 5 i=1,nfield
                tscale(i,ibuff)=1.
                tzero(i,ibuff)=0.
C               choose special value to indicate that null value is not defined
                tnull(i,ibuff)=123454321
C               parse the tform strings to get the data type and repeat count
                call ftbnfm(tform(i),tdtype(i,ibuff),
     &                      trept(i,ibuff),width,status)
                if (tdtype(i,ibuff) .eq. 16)then
C                       store ASCII unit string length in TNULL parameter
                        tnull(i,ibuff)=width
                end if
                if (status .ne. 0)return
5           continue

C           store the size of the special data area, if any
            scount(ibuff)=pcount

C           determine byte offset of the beginning of each field and row length
            call ftgtbc(nfield,tdtype(1,ibuff),trept(1,ibuff),
     &           tbcol(1,ibuff),rowlen(ibuff),status)

C           FITSIO deals with ASCII columns as arrays of strings, not
C           arrays of characters, so need to change the repeat count
C           to indicate the number of strings in the field, not the 
C           total number of characters in the field.
            do 10 i=1,nfield
                if (tdtype(i,ibuff) .eq. 16)then
                    j=trept(i,ibuff)/tnull(i,ibuff)
                    trept(i,ibuff)=max(j,1)
                end if
10          continue

C           initialize the heap offset (=nrows x ncolumns)
            theap(ibuff)=nrows*rowlen(ibuff)
            nxheap(ibuff)=0

C           calculate the start of the next header unit, based on the
C           size of the data unit (table + special data)
            hdstrt(ibuff,chdu(ibuff)+1)=
     &       dtstrt(ibuff)+(rowlen(ibuff)*nrows+pcount+2879)/2880*2880
        end if
        end
